Seite 1 von 3

Perspektive ohne Krümmung im Raycaster

Verfasst: 01.12.2005 00:19
von Kekskiller
Nach ich Monate lang gebraucht habe, um rauszufinden, dass alle meine Raycaster-Ansätze nur an dem Umrechnen von Gradmaß in Bogenmaß gescheitert bin, verzweifle ich nun mal wieder an dem Problem mit der Krümmung der Wand. Das kennt sicher jeder, der sich auf eigene Faust mit Raycasting beschäftigt hat.

Laut einem Tutorial soll ich den falschen Wandabstand mit cos(beta) multiplizieren. beta stellt hiebei den Winkel dar, der zwischen dem aktuellen Winkel des zu zeichnenden Rays und dem Blickwinkel des Spielers besteht (das ist logischerweise die Mitte des Sichtfeldes). Doch nun sagt mir bitte- wie soll ich das hier integrieren :| (?) :

Code: Alles auswählen

Global mapx.l, mapy.l, mapz.l
Global fps.l, time.l

Global playerx.l, playery.l, playerz.f
Global playerfov.l, playermove.l, playerturn.l

#PI = 3.141592
Procedure.f atosin(angle.w)
  s.f = (#PI / 180) * angle
  ProcedureReturn s
EndProcedure

mapz = 32
mapx = 10*mapz
mapy = 10*mapz

playerx = 1*mapz
playery = 1*mapz
playerz = atosin(85)

playerfov = atosin(45)
playermove = mapz / 5
playerturn = 5

Dim map.l(mapx,mapy)


#color_wall = $999999


Debug "playerfov: " + Str(playerfov)
Debug "playerz: " + Str(playerz)
Debug ""
Debug ""


Procedure cast(z,distlen,correction) ;"correction" ist die korrekturvariable der perspektive
  Protected pix.f
  pix.f = mapz / distlen * 277
  pix.f * correction
  Box(z,120-Int(pix)/2, 1,Int(pix), #color_wall)
EndProcedure

Procedure render()
  Protected angle.f, dist.l
  Protected rx.l, ry.l, z.l
  Protected pfovhalf.f, astep.f
  
  pfovhalf.f = playerfov / 2
  astep.f = playerfov / 320
  
  angle = playerz - pfovhalf
  
  For z=0 To 319
    angle + astep
    dist=0
    Repeat
      dist+1
      rx = playerx + Sin(angle) * dist
      ry = playery + Cos(angle) * dist
      If rx>=0 And ry>=0 And rx<mapx And ry<mapy
          If map(rx,ry) = 1
            If z <= 149
              c = Cos(playerz - Int(angle))
            ElseIf z>=150
              c = Cos(Int(angle) - playerz)
            EndIf
            cast(z, dist, c)
            Break
          EndIf
      Else
        Break
      EndIf
    ForEver
  Next
EndProcedure

Procedure load()
  For zy=0 To mapy
    For zx=0 To mapx
      If zy=0 Or zy=mapx-1 Or zx=0 Or zx=mapy-1
          map(zx, zy) = 1
      EndIf
    Next
  Next
EndProcedure

load()
InitSprite()
InitKeyboard()

;OpenWindow(0,0,0,320,240,#PB_Window_SystemMenu, "rm3")
;OpenWindowedScreen(WindowID(), 0,0, 320,240, 0,0,0)
OpenScreen(320,240,16,"rm3")

Repeat
  ;event = WindowEvent()
  ClearScreen(0,0,0)
  ExamineKeyboard()
  
  If KeyboardPushed(#PB_Key_Left)
    playerz - atosin(playerturn)
  ElseIf KeyboardPushed(#PB_Key_Right)
    playerz + atosin(playerturn)
  EndIf
  
  If KeyboardPushed(#PB_Key_Up)
    playerx + (Sin(playerz) * playermove)
    playery + (Cos(playerz) * playermove)
  ElseIf KeyboardPushed(#PB_Key_Down)
    playerx - (Sin(playerz) * playermove)
    playery - (Cos(playerz) * playermove)
  EndIf
  
  If KeyboardReleased(#PB_Key_PageUp)
    playerfov + 5
  ElseIf KeyboardPushed(#PB_Key_PageDown)
    playerfov - 5
  EndIf
  
  StartDrawing(ScreenOutput())
    time=ElapsedMilliseconds()
    render()
    Debug ElapsedMilliseconds()-time
    DrawText(Str(playerz/(#PI/180)))
  StopDrawing()
  
;  Debug CpuUsage()
  
  FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape); Or event=#PB_Event_CloseWindow
Ich verzweifle gerade wirklich daran, weil mir kein Geisteblit kommt, bzw. nicht ansatzweise eine Lösung in meinen Kopf flackert. Könnt ihr mir hier weiterhelfen? Das wäre großartig, dann könnte ich mich dem Texturieren zuwenden und hätte nicht schon wieder so einen Block im Kopf... Die Theorie verstehe ich schließlich, nur haperts gerade an der Umsetzung, ich habe heute einfach einen Blackout.

Verfasst: 01.12.2005 16:07
von AndyX
ey krass... Ich krieg das noch nichtmal hin, dass die Wände überhaupt gezeichnet werden... Respekt :!:

Ne kleine Frage hab ich: was soll das:

Code: Alles auswählen

If z <= 149
....
ElseIf z>=150
??

z wird doch nirgendwo ein Wert zugewiesen!

Verfasst: 01.12.2005 16:07
von AndyX
oh mist :| hab das was übersehen :oops:

Verfasst: 01.12.2005 20:28
von Kekskiller
Ich dachte eigentlich, dass ich so rausbekommen kann, auf welcher Seite nun der Zähler ist, so kriegt man raus, wie man den Winkel beta rausbekommt. Und sonst ist der Raycaster auch unglaublich lahm... Ich weiß nicht warum, Rechnung sollten eigentlich nicht zu viele drinne sein...

Sowieso ist mir gerade aufgefallen, dass es:
If z <= 149
c = Cos(angle - playerz)
ElseIf z>=150
c = Cos(playerz - angle)
EndIf
und nicht:
If z <= 149
c = Cos(Int(angle) - playerz)
ElseIf z>=150
c = Cos(playerz - Int(angle))
EndIf
heißt. Aber helfen tut mir das gerade auch nicht viel... HM

Verfasst: 01.12.2005 21:46
von Kekskiller
Ich habs jetzt rausbekommen. Ich schäme mich so! Natürlich ist c nicht FLOAT, sondern LONG gewesen /:-> . Kein Wunder, dass das nicht funktioniert. Danach hats aber trotzdem nicht funktioniert. Im Gegenteil, die Krümmung wurde nur noch stärker. Ich habe die Multiplikation einfach umgedreht und eine Division drausgemacht, jetzt klappts komischweise /:-> :wink: .

So, jetzt kommt "Lichtbrechung" an den Wänden und dann schlag ich beim Fischauge ein :allright: .

Edit: Jetzt kommts auch mit dem Speed hin, komisch :| ...

Verfasst: 02.12.2005 07:51
von SoS
Moin

Was mir hier gerade so auffällt.
Warum ersetzte Du nicht #PI / 180 z.b. durch eine Konstante #PI2=#PI / 180 ?
Kleinvieh macht bekanntlich auch Mist. ;)

Verfasst: 02.12.2005 15:18
von Kaeru Gaman
richtig...

und wenn du deinen wertebereich vorher abschätzen kannst,
lohnt es sich evtl. ein array als sin/cos-tabelle anzulegen...

Verfasst: 02.12.2005 15:40
von remi_meier
@SoS: falsch
PB hat Constants Folding, welches Konstanten zusammenfasst:
#PI / 180.0 wird direkt zu 0.01745329 noch während der Kompilierzeit!

Verfasst: 02.12.2005 15:57
von Kaeru Gaman
hey, danke, remi. gut zu wissen.

also, alles, was in einem ausdruck so dasteht, daß der compiler es von
den variablen isolieren kann, wird vorberechnet?

also, wenn ich sinnvoll klammer, kann ich ne menge performance sparen?

Verfasst: 02.12.2005 16:11
von remi_meier
Ja, obwohl er hierbei nicht sehr 'gescheit' vorgeht:

Code: Alles auswählen

a = 5 * a * 3
wird nicht zusammengefasst, sondern zu

Code: Alles auswählen

MOV ebx,dword [v_a]
 IMUL ebx,5
 IMUL ebx,3
 MOV dword [v_a],ebx
Wobei man hier sehen kann, dass es intern gut möglich wäre, da anscheinend
intern 5 und 3 direkt 'nebeneinander' stehen.

Tja, ev. macht das Fred ja irgendwann mal /:->

greetz
Remi