Raycaster(mit Texturing) objekt orientiert
Übersicht

![]() |
VertexBetreff: Raycaster(mit Texturing) objekt orientiert |
![]() Antworten mit Zitat ![]() |
---|---|---|
Auf den Spuren von Wolfenstein3D und Co, wollte ich mal einen eigenen Raycaster schreiben. Code: [AUSKLAPPEN] Const FACE_FRONT : Byte = 1
Const FACE_BACK : Byte = 2 Const FACE_LEFT : Byte = 3 Const FACE_RIGHT : Byte = 4 Type TRaycaster Field TileSize : Int Field TileCount : Int Field Tiles : TTexture[] Field MapSize : Int[2] Field Map : Int[,] Field Camera : TCamera Method New() Self.TileSize = 64 Self.TileCount = 0 Self.MapSize = [0, 0] Self.Camera = Null End Method Method LoadTile:Int(URL:Object) Local Texture:TTexture Texture = TTexture.Load(URL, Self.TileSize) If Not Texture Then Return -1 Self.TileCount :+ 1 Tiles = Tiles[..Self.TileCount] Tiles[Self.TileCount-1] = Texture Return Self.TileCount End Method Method SetMapSize(Columns:Int, Rows:Int) Self.MapSize[0] = Columns Self.MapSize[1] = Rows Self.Map = New Int[Columns, Rows] End Method Method SetTile(Column:Int, Row:Int, TileNr:Int) If (Column < 0 Or Column => Self.MapSize[0]) Or .. (Row < 0 Or Row => Self.MapSize[1]) Or .. (TileNr < 0 Or TileNr > Self.TileCount) Then Return Self.Map[Column, Row] = TileNr End Method Method SetCamera(Camera:TCamera) Self.Camera = Camera End Method Method Render() If Self.Camera Then Self.Camera.Render(Self) End Method End Type Type TCamera Field FOV : Float Field Viewport : Int[4] Field ClearColor : Byte[3] Field Position : Float[2] Field Yaw : Float Field Screen : TPixmap Method New() Self.SetFOV(60.0) Self.SetViewport(0, 0, GraphicsWidth(), GraphicsHeight()) Self.SetClearColor(0, 0, 0) Self.SetPosition(0.0, 0.0) Self.SetRotation(0.0) End Method Method SetFOV(FOV:Float) Self.FOV = FOV End Method Method SetViewport(X:Int, Y:Int, Width:Int, Height:Int) Self.Viewport[0] = X Self.Viewport[1] = Y Self.Viewport[2] = Width Self.Viewport[3] = Height Self.Screen = CreatePixmap(Width, Height, PF_RGBA8888) End Method Method SetClearColor(Red:Byte, Green:Byte, Blue:Byte, Alpha:Byte=255) Self.ClearColor[0] = Red Self.ClearColor[1] = Green Self.ClearColor[2] = Blue Self.CLearColor[3] = Alpha End Method Method SetRotation(Yaw:Float) Self.Yaw = Yaw End Method Method Turn(DeltaYaw:Float) Self.Yaw :+ DeltaYaw End Method Method SetPosition(X:Float, Z:Float) Self.Position[0] = X Self.Position[1] = Z End Method Method Translate(X:Float, Z:Float) Self.Position[0] :+ X Self.Position[1] :+ Z End Method Method Move(Speed:Float) Self.Position[0] :+ (Cos(Self.Yaw)*Speed) Self.Position[1] :+ (Sin(Self.Yaw)*Speed) End Method Method Clear() Local X:Int, Y:Int, Offset:Byte Ptr Offset = Self.Screen.Pixels For Y = 0 Until Self.Viewport[3] For X = 0 Until Self.Viewport[2] Offset[0] = Self.ClearColor[0] Offset[1] = Self.ClearColor[1] Offset[2] = Self.ClearColor[2] Offset[3] = Self.ClearColor[3] Offset :+ 4 Next Next End Method Method Render(Raycaster:TRaycaster) Local DeltaAngle:Float, Ray:TRay, Column:Int Local Dividend:Float, Height:Int Local Texture:TTexture, TextureColumn:Int ' Clear Background Self.Clear() ' Calculate Angle for one Screen-Column DeltaAngle = Self.FOV/Float(Self.Viewport[2]) ' Emit Rays Ray = New TRay Ray.Angle = Self.Yaw - Self.FOV/2.0 ' Dividend to calculate the projected Height Dividend = Float(Raycaster.TileSize) * .. Sin(90.0-Self.FOV/2.0)*Float(Self.Viewport[2]/2) For Column = 0 Until Self.Viewport[2] Ray.Z = Self.Position[1] Ray.Emit(Raycaster) If Ray.Tile > 0 Then Texture = Raycaster.Tiles[Ray.Tile-1] Select Ray.Face Case FACE_FRONT TextureColumn = Int(Ray.X) Mod Raycaster.TileSize Case FACE_BACK TextureColumn = Raycaster.TileSize - (Int(Ray.X) .. Mod Raycaster.TileSize) - 1 Case FACE_LEFT TextureColumn = Raycaster.TileSize - (Int(Ray.Z) .. Mod Raycaster.TileSize) - 1 Case FACE_RIGHT TextureColumn = Int(Ray.Z) Mod Raycaster.TileSize End Select ' Correct the Fisheye-Effect Height = Dividend/(Ray.Distance*Cos(Self.Yaw - Ray.Angle)) ' Draw scaled Comlumn Texture.DrawColumn(Column, TextureColumn, Height, Self) EndIf Ray.Angle :+ DeltaAngle Next ' Display the Result DrawPixmap(Self.Screen, Self.Viewport[0], Self.Viewport[1]) End Method End Type Type TRay Field Angle : Float Field X : Float Field Z : Float Field Tile : Int Field Distance : Float Field Face : Byte Method Emit(Raycaster:TRaycaster) Local DeltaX:Float, DeltaZ:Float, DX:Float, DZ:Float, TanAngle:Float Local Quit:Int, Face:Byte, MapColumn:Int, MapRow:Int, Tile:Int, Distance:Float Local OldX:Float, OldZ:Float, OldTile:Int, OldDistance:Float, OldFace:Byte ' 0° => Angle <= 360° Self.Angle = Self.Angle Mod 360.0 If Self.Angle < 0.0 Then Self.Angle = 360.0+Self.Angle TanAngle = Tan(Self.Angle) ' Find horizontal intersection Quit = False If Self.Angle > 0.0 And Self.Angle < 180.0 Then DeltaZ = Float(Raycaster.TileSize) DeltaX = DeltaZ/TanAngle Self.Z = Float((Int(Raycaster.Camera.Position[1]) / .. Raycaster.TileSize)*Raycaster.TileSize + Raycaster.TileSize) DZ = Self.Z - Raycaster.Camera.Position[1] DX = DZ/TanAngle Self.X = Raycaster.Camera.Position[0] + DX Face = FACE_BACK ElseIf Self.Angle > 180.0 And Self.Angle < 360.0 Then DeltaZ = -Float(Raycaster.TileSize) DeltaX = DeltaZ/TanAngle Self.Z = Float((Int(Raycaster.Camera.Position[1]) / .. Raycaster.TileSize)*Raycaster.TileSize) DZ = Self.Z - Raycaster.Camera.Position[1] DX = DZ/TanAngle Self.X = Raycaster.Camera.Position[0] + DX FACE = FACE_FRONT ElseIf Self.Angle = 0.0 Or Self.Angle = 180.0 Quit = True ElseIf Self.Angle = 90.0 Then DeltaZ = Float(Raycaster.TileSize) DeltaX = 0.0 Self.Z = Float((Int(Raycaster.Camera.Position[1]) / .. Raycaster.TileSize)*Raycaster.TileSize + Raycaster.TileSize) Self.X = Raycaster.Camera.Position[0] FACE = FACE_BACK ElseIf Self.Angle = 270.0 Then DeltaZ = -Float(Raycaster.TileSize) DeltaX = 0.0 Self.Z = Float((Int(Raycaster.Camera.Position[1]) / .. Raycaster.TileSize)*Raycaster.TileSize) Self.X = Raycaster.Camera.Position[0] FACE = FACE_FRONT EndIf Tile = 0 While Not Quit MapColumn = Int(Self.X)/Raycaster.TileSize If Self.Angle => 0.0 And Self.Angle <= 180.0 Then MapRow = Int(Self.Z)/Raycaster.TileSize ElseIf Self.Angle > 180.0 And Self.Angle < 360.0 Then MapRow = Int(Self.Z)/Raycaster.TileSize - 1 EndIf If MapColumn < 0 Or MapColumn > Raycaster.MapSize[0] - 1 Or .. MapRow < 0 Or MapRow > Raycaster.MapSize[1] - 1 Then Exit Tile = Raycaster.Map[MapColumn, MapRow] If Tile > 0 Then Exit Self.X :+ DeltaX Self.Z :+ DeltaZ Wend If Tile > 0 Then DX = Raycaster.Camera.Position[0] - Self.X DZ = Raycaster.Camera.Position[1] - Self.Z Distance = Sqr(DX*DX + DZ*DZ) EndIf OldX = Self.X OldZ = Self.Z OldDistance = Distance OldTile = Tile OldFace = Face ' Find vertical intersection Quit = False If (Self.Angle > 270.0 And Self.Angle < 360.0) Or .. (Self.Angle > 0.0 And Self.Angle < 90.0) Then DeltaX = Float(Raycaster.TileSize) DeltaZ = TanAngle*DeltaX Self.X = Float(Int(Raycaster.Camera.Position[0])/Raycaster.TileSize * .. Raycaster.TileSize + Raycaster.TileSize) DX = Self.X - Raycaster.Camera.Position[0] DZ = TanAngle*DX Self.Z = Raycaster.Camera.Position[1]+DZ Face = FACE_RIGHT ElseIf Self.Angle > 90.0 And Self.Angle < 270.0 Then DeltaX = -Float(Raycaster.TileSize) DeltaZ = TanAngle*DeltaX Self.X = Float(Int(Raycaster.Camera.Position[0])/Raycaster.TileSize * .. Raycaster.TileSize) DX = Self.X - Raycaster.Camera.Position[0] DZ = TanAngle*DX Self.Z = Raycaster.Camera.Position[1]+DZ Face = FACE_LEFT ElseIf Self.Angle = 90.0 Or Self.Angle = 270.0 Then Quit = True ElseIf Self.Angle = 0.0 Then DeltaX = Float(Raycaster.TileSize) DeltaZ = 0.0 Self.X = Float(Int(Raycaster.Camera.Position[0])/Raycaster.TileSize * .. Raycaster.TileSize + Raycaster.TileSize) Self.Z = Raycaster.Camera.Position[1] Face = FACE_RIGHT ElseIf Self.Angle = 180.0 DeltaX = -Float(Raycaster.TileSize) DeltaZ = 0.0 Self.X = Float(Int(Raycaster.Camera.Position[0])/Raycaster.TileSize * .. Raycaster.TileSize) Self.Z = Raycaster.Camera.Position[1] Face = FACE_LEFT EndIf Tile = 0 While Not Quit MapRow = Int(Self.Z)/Raycaster.TileSize If (Self.Angle > 270.0 And Self.Angle < 360.0) Or .. (Self.Angle => 0.0 And Self.Angle < 90.0) Then MapColumn = Int(Self.X)/Raycaster.TileSize ElseIf Self.Angle => 90.0 And Self.Angle <= 270.0 Then MapColumn = Int(Self.X)/Raycaster.TileSize - 1 EndIf If MapColumn < 0 Or MapColumn > Raycaster.MapSize[0] - 1 Or .. MapRow < 0 Or MapRow > Raycaster.MapSize[1] - 1 Then Exit Tile = Raycaster.Map[MapColumn, MapRow] If Tile > 0 Then Exit Self.X :+ DeltaX Self.Z :+ DeltaZ Wend ' Find the shortest Distance If Tile > 0 Then DX = Raycaster.Camera.Position[0] - Self.X DZ = Raycaster.Camera.Position[1] - Self.Z Distance = Sqr(DX*DX + DZ*DZ) If OldTile > 0 Then If Distance <= OldDistance Then Self.Distance = Distance Self.Tile = Tile Self.Face = Face Else Self.Distance = OldDistance Self.X = OldX Self.Z = OldZ Self.Tile = OldTile Self.Face = OldFace EndIf Else Self.Distance = Distance Self.Tile = Tile Self.Face = Face EndIf Else Self.Distance = OldDistance Self.X = OldX Self.Z = OldZ Self.Tile = OldTile Self.Face = OldFace EndIf End Method End Type Type TTexture Field Height : Int Field Texels : Int[,] Method New() Self.Height = 0 Self.Texels = Null End Method Method Delete() If Self.Texels Then MemFree(Self.Texels) End Method Method DrawColumn(X:Int, Column:Int, Height:Int, Camera:TCamera) Local DeltaY:Float, StartY:Int, Y:Int Local Texel:Int, TempY:Int, Offset:Byte Ptr DeltaY = Float(Self.Height)/Float(Height) If Height > Camera.Viewport[3] Then StartY = (Height - Camera.Viewport[3])/2 Height = Camera.Viewport[3] Else StartY = 0 EndIf TempY = Camera.Viewport[3]/2 - Height/2 - StartY For Y = StartY Until Height+StartY Row = Int(Float(Y)*DeltaY) Offset = Camera.Screen.Pixels + .. (TempY+Y)*Camera.Viewport[2]*4 + X*4 Texel = Self.Texels[Row, Column] Offset[2] = (Texel Shr 16) & $FF Offset[1] = (Texel Shr 8) & $FF Offset[0] = Texel & $FF Next End Method Function Load:TTexture(URL:Object, TileSize:Int) Local Pixmap:TPixmap, Texture:TTexture Pixmap = LoadPixmap(URL) If Not Pixmap Then Return Null Pixmap = ResizePixmap(Pixmap, TileSize, Pixmap.Height) Pixmap = Pixmap.Convert(PF_RGBA8888) Texture = New TTexture Texture.Height = Pixmap.Height Texture.Texels = New Int[Texture.Height, TileSize] MemCopy(Texture.Texels, Pixmap.PixelPtr(0, 0), TileSize*Texture.Height*4) Return Texture End Function End Type Beispiel: Code: [AUSKLAPPEN] SuperStrict
Framework BRL.Max2D Import BRL.GLMax2D Import BRL.StandardIO Import BRL.PolledInput Import BRL.PNGLoader Include "Raycaster.bmx" Global Raycaster : TRaycaster Global Camera : TCamera Global MapWidth : Int Global MapDepth : Int Global Column : Int Global Row : Int Global Tile : Int Global FrameCount : Int Global Start : Int Global FPS : Int Graphics(320, 240, 0, 0) ' Init Raycaster Raycaster = New TRaycaster ' Load Tileset Raycaster.LoadTile("Tile1.png") Raycaster.LoadTile("Tile2.png") Raycaster.LoadTile("Tile3.png") Raycaster.LoadTile("Tile4.png") Raycaster.LoadTile("Tile5.png") Raycaster.LoadTile("Tile6.png") Raycaster.LoadTile("Tile7.png") Raycaster.LoadTile("Tile8.png") ' Read Map RestoreData Level ReadData MapWidth, MapDepth Raycaster.SetMapSize(MapWidth, MapDepth) For Row = 0 Until MapDepth For Column = 0 Until MapWidth ReadData Tile Raycaster.SetTile(Column, Row, Tile) Next Next ' Add Camera Camera = New TCamera Camera.SetClearColor(30, 10, 0) Camera.SetPosition(672.0, 672.0) Raycaster.SetCamera(Camera) While Not KeyDown(KEY_ESCAPE) If KeyDown(KEY_LEFT) Then Camera.Turn(-1.0) If KeyDown(KEY_RIGHT) Then Camera.Turn( 1.0) If KeyDown(KEY_UP) Then Camera.Move( 1.0) If KeyDown(KEY_DOWN) Then Camera.Move(-1.0) Raycaster.Render() SetColor(255, 255, 255) DrawText(FPS+" FPS", 10, 10) Flip() FrameCount :+ 1 If MilliSecs() - Start > 999 Then FPS = FrameCount FrameCount = 0 Start = MilliSecs() EndIf Wend EndGraphics() End #Level DefData 20, 20 DefData 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 DefData 1, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 DefData 1, 0, 0, 0, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1 DefData 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1 DefData 1, 0, 0, 0, 2, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0, 2, 0, 0, 0, 1 DefData 1, 0, 0, 0, 2, 0, 0, 0, 3, 3, 6, 6, 6, 3, 0, 2, 0, 0, 0, 1 DefData 1, 0, 0, 0, 2, 0, 0, 0, 3, 3, 6, 6, 6, 3, 0, 2, 0, 0, 0, 1 DefData 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 6, 6, 6, 3, 0, 2, 0, 0, 0, 1 DefData 1, 0, 0, 0, 2, 2, 0, 3, 3, 6, 6, 6, 6, 3, 0, 2, 0, 0, 0, 1 DefData 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 0, 2, 0, 0, 0, 1 DefData 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1 DefData 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 1 DefData 1, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 DefData 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 DefData 1, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 DefData 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 DefData 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 1 DefData 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 1 DefData 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 DefData 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 1 Ist noch recht langsam, da ich zu faul war, die Pixmaps durch Speicherbänke zu ersetzen. Mal schauen, ob ich noch Boden und Himmel, sowie Texturefiltering hinzufüge. Beispiel mit Texturen und lauffähiger *.exe Datei unter Download mfg olli |
||
vertex.dreamfall.at | GitHub |
- Zuletzt bearbeitet von Vertex am So, März 12, 2006 18:48, insgesamt einmal bearbeitet
![]() |
BtbN |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wow, nicht schlecht!
Bei mir läuft der Spaß zwar nur mit ~20FPS, das liegt aber eher an meinem Rechner. Allerdings fängts arg an zu laggen, wenn ich mich ner Wand nähere. |
||
![]() |
Suco-XBetreff: ...... |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi
Sehr schön. Mfg Suco |
||
Intel Core 2 Quad Q8300, 4× 2500 MHz, 4096 MB DDR2-Ram, GeForce 9600GT 512 MB |
![]() |
Vertex |
![]() Antworten mit Zitat ![]() |
---|---|---|
Danke!
So, habe ihn jetzt rund 4 mal schneller gemacht. Mehr Perfomance reise ich da jetzt sicher nichtmehr heraus. mfg olli |
||
vertex.dreamfall.at | GitHub |
![]() |
Jan_Ehemaliger Admin |
![]() Antworten mit Zitat ![]() |
---|---|---|
Nett, aber ich muss zustimmen, die 200 FPS, sind wahrscheinlich nicht für normal sterbliche zu erreichen.
ich müsste das mal auf meiner GF 6800 testen, aber hier, komme ich cniht über 20 herraus. (3,2GHZ Radeon 9600 & 512 MB DDR 400) |
||
between angels and insects |
![]() |
Phalastos |
![]() Antworten mit Zitat ![]() |
---|---|---|
Zitat: Nett, aber ich muss zustimmen, die 200 FPS, sind wahrscheinlich nicht für normal sterbliche zu erreichen.
Einfach mal die ganze Ad-Ware deinstallieren Jan. ![]() Ich habe durchgehend 76 FPS ( denke mal vSync ist aktiv ) mit einer viel schlechteren Konfiguration. ( Athlon 2200+, 512 MB Radeon 9100 64 MB ) Gruß Alex |
||
Forbiddenmagic - Warfare of Forgotten Power |
![]() |
Vertex |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi!
Der Raycaster ist ein Softwarerenderer, somit sollte es nicht auf die Grafikkarte sondern auf den Prozessor(nichteinmal Arbeitspeicher) ankommen. Habe einen 2,8 GHz Pentium IV. Benutze mal statts "Import BRL.GLMax2D" "Import BRL.D3D7Max2D". Bei mir sinkt da die FPS-Rate schlagartig auf 70, aber ist denke ich Treibersache. Hatte jetzt noch bi-lineares Texturefiltering eingebaut, ist aber noch zu lahm. mfg olli |
||
vertex.dreamfall.at | GitHub |
![]() |
DarkEvil |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also mit meinen Athlon64 3700+, Geforce 5900xt und 1GB Ram komme ich so auf 300-350 FPS im Fenster Modus. | ||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group