Perspektive ohne Krümmung im Raycaster

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Perspektive ohne Krümmung im Raycaster

Beitrag 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.
Benutzeravatar
AndyX
Beiträge: 1272
Registriert: 17.12.2004 20:10
Wohnort: Niederösterreich
Kontaktdaten:

Beitrag 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!
Benutzeravatar
AndyX
Beiträge: 1272
Registriert: 17.12.2004 20:10
Wohnort: Niederösterreich
Kontaktdaten:

Beitrag von AndyX »

oh mist :| hab das was übersehen :oops:
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag 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
Kekskiller
Beiträge: 752
Registriert: 14.09.2004 21:39
Kontaktdaten:

Beitrag 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 :| ...
Benutzeravatar
SoS
Beiträge: 340
Registriert: 29.08.2004 09:31
Kontaktdaten:

Beitrag 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. ;)
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

richtig...

und wenn du deinen wertebereich vorher abschätzen kannst,
lohnt es sich evtl. ein array als sin/cos-tabelle anzulegen...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag 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!
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag 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?
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
remi_meier
Beiträge: 1078
Registriert: 29.08.2004 20:11
Wohnort: Schweiz

Beitrag 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
Antworten