Mein erstes Raycasting
Übersicht

![]() |
KabelbinderSieger des WM-Contest 2006Betreff: Mein erstes Raycasting |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ist irgendwie komisch, wie sich die Dinge manchmal so ergeben:
Ich hab vor ner Zeit hier mal in einem Thread einen Link zu einer Seite gefunden, die wohl sein Jahren nicht mehr aktualisiert wurde und da stand irgendsowas, wie: "Mit Blitzbasic kann man noch keine 3D Spiele machen, höchstens Raycasting oder Isometrie" Ich hab von diesem Raycasting vorher noch nie was gehört und das deshalb mal bei Wikipedia nachgeschlagen. Hab rausgefunden: "Wunderbar, damit kann man also 3D Korridore erstellen" und weil ich zuvor noch gar keine Ahnung hatte, wie man überhaupt dreidimensionale sachen auf dem Bildschirm darstellen kann und mich das interessiert hat, hab ich mich mal damit beschäftigt und dashier ist rausgekommen: Code: [AUSKLAPPEN] AppTitle "Raycasting"
Graphics 640,680,16,2 SetBuffer BackBuffer() Const w = 7 Const h = 7 Const plane_w = 320 Const plane_h = 240 Const view_arc = 60 Const view_w = 500 Global xcor#,ycor#,rot,divisor,distance#,st,togo,mx,my Dim map(7,7) For y = 0 To 7 For x = 0 To 7 Read map(x,y) Next Next Data 1,1,1,1,1,1,1,1 Data 1,0,1,0,0,0,0,1 Data 1,0,1,0,0,0,0,1 Data 1,0,1,0,1,0,1,1 Data 1,0,1,1,1,0,0,1 Data 1,0,0,0,1,1,0,1 Data 1,0,1,0,0,0,0,1 Data 1,1,1,1,1,1,1,1 xcor = 75 ycor = 125 rot = 90 divisor = view_arc/plane_w ;For i = 0 To 2000 ;If coll((xcor+Cos(rot)*i),(ycor+Sin(rot)*i)) Then ;distance = i ;Exit ;EndIf ;Next distance = (1/Tan(30))*120 ;st = 0 ;For f# = 0.0 To 60.0 Step 0.1875 ;togo = 1 ;For g = 0 To view_w ;If togo = 1 ;If coll(xcor+Cos(rot-30+f)*g,ycor+Sin(rot-30+f)*g) Then ;Color g,g,g ;Rect st+150,150,1,240 ;DebugLog g ;togo = 0 ;EndIf ;EndIf ;Next ;st = st + 1 ;Next Function coll(x,y) If RectsOverlap(x,y,1,1,0,0,(w+1)*50,(h+1)*50) Then If map(x/50,y/50)=1 Then Return 1 EndIf End Function Function move() If KeyDown(208)=1 Then xcor = xcor - Cos(rot) If coll(xcor,ycor) Then xcor = xcor + Cos(rot) ycor = ycor - Sin(rot) If coll(xcor,ycor) Then ycor = ycor + Sin(rot) EndIf If KeyDown(200)=1 Then xcor = xcor + Cos(rot) If coll(xcor,ycor) Then xcor = xcor - Cos(rot) ycor = ycor + Sin(rot) If coll(xcor,ycor) Then ycor = ycor - Sin(rot) EndIf If KeyDown(203) Then rot = rot - 1 EndIf If KeyDown(205) Then rot = rot + 1 EndIf If rot > 360 Then rot = 0 If rot < 0 Then rot = 360 End Function Repeat mx = MouseX() my = MouseY() st = 0 For f# = 0.0 To 60.0 Step 0.1875 togo = 1 For g = 0 To view_w If togo = 1 If coll(xcor+Cos(rot-30+f)*g,ycor+Sin(rot-30+f)*g) Then If g > 20 Then Color 255/(g/20),255/(g/20),255/(g/20) Else Color 255,255,255 EndIf Rect st+150,150+(240-distance/g*120),1,distance/g*240 ;DebugLog g togo = 0 g = view_w EndIf EndIf Next st = st + 1 Next move() For y = 0 To 7 For x = 0 To 7 Color 255,255,255 If map(x,y)=1 Then Rect x*20,y*20,20,20 EndIf ;Color 0,0,0 ;Rect x*2,y*2,2,2,0 Next Next Color 255,0,0 Oval xcor/2.5-2,ycor/2.5-2,5,5 Line xcor/2.5,ycor/2.5,xcor/2.5+Cos(rot)*10,ycor/2.5+Sin(rot)*10 ;Plot xcor/50,ycor/50 Text 200,0,distance Text 200,10,xcor Text 200,20,ycor Text 200,30,st Text 200,40,togo Text 200,50,rot Text 200,60,Str$(mx)+" "+Str$(my) Flip Cls Until KeyHit(1) End Also theoretisch könnte ich jetzt Macrophage in 3D nachprogrammieren ![]() |
||
<Wing Avenger Download> ◊◊◊ <Macrophage Download> |
![]() |
IronstormErstklassiger Contest-Veranstalter |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also, ist nicht schlecht, aber man bewegt sich nsehr lllllaaaaannnnnggggsssaaaammmm *einschlaf*!
Aber für dein erstes Raycasting ist es echt gut. Blitzmaker |
||
..:: blackbird design : blackbird photography : Futuro Verde : X-Commander ::..
MacBook | Intel Core 2 Duo 2,1 GHz | 2048 MB RAM | 80 GB HDD | Mac OS X 10.6.2 (Snow Leopard) | Adobe CS4 Design Premium |
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wow,.. Auch noch wenig Code und nicht so überladen mit sinnlosen Funktionen. Und, du hast die Entfernung radial ausgestreckt, nicht wie es die meisten machen linear. Der Vorteil dieses Verfahrens ist ja, daß eine art Linseneffekt auftritt. Der ja realistisch ist und bei herkömlicher 3D-Darstellung nicht vorkommt. | ||
![]() |
maximilian |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das größte Problem bisj jetzt ist wohl dieser Fish-Bowl-Effekt. Probiere den wegzubekommen und es sieht sehr viel besser aus. ![]() |
||
Variety is the spice of life. One day ignore people, next day annoy them. |
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
@LordChaos, der Fish-Effekt ist doch eigendlich das coole daran. Das kommt daher das der Ray sich radial vom Betrachter entfernt. Dieser Effekt ist soweit auch realistisch! Kommt beispielsweise ganz stark bei Weitwinkelobjektiv oder Panoramaaufnahmen vor. Bei einer normalen Kamera sieht man den Effekt nicht so stark, da diese nur einen kleinen Teil des ganzen einfangen. Diesen Effekt kann man leicht durch eine parallele Ausbreitung des Rays unterbinden, aber dann kann man ja auch gleich mit der 3D-Unterstützung von DirectX/OpenGL usw. weiter machen.
Da ich mal wieder nicht die Finger lassen konnte... Hier mal meine Version eines Raycasters. Mit Cursor Bewegen. Mit Maus hoch/runter/links/rechts schauen. Mit 1 und 2 kann man den Sichtbereich einstellen... Code: [AUSKLAPPEN] Graphics 400,400,0,2
SetBuffer BackBuffer() Origin 200,200 HidePointer Dim xy(9,9) ;Spielfeld xp#=1 ;Spieler-X-Position yp#=1 ;Spieler-Y-Position ws#=90 ;SPieler-Sollwinkel wi#=90 ;Spieler-Istwinkel hs#=0 ;Spieler-Sollhöhe hi#=0 ;Spieler-Isthöhe x#=0 ;Schleifenvariable y#=0 ;Schleifenvariable e#=0 ;Strahlentfernung zur Wand w%=6 ;wsnkeleinfang (tele/weit) f%=0 ;Funktionsvariable For y=0 To 9 For x=0 To 9 Read xy(x,y) Next Next Data 1,1,1,1,1,1,1,1,1,1 Data 1,0,1,0,0,0,0,0,0,1 Data 1,0,1,0,1,0,1,0,0,1 Data 1,0,0,0,1,0,0,0,0,1 Data 1,0,1,1,1,0,1,0,0,1 Data 1,0,1,0,0,0,0,0,0,1 Data 1,0,1,0,0,0,0,0,0,1 Data 1,0,1,1,1,1,1,1,0,1 Data 1,0,0,0,0,0,0,0,0,1 Data 1,1,1,1,1,1,1,1,1,1 ;Hauptschleife While Not KeyHit(1) ;Kopfbewegung ws=(ws+MouseXSpeed())/1.4 hs=(hs+MouseYSpeed())/1.4 wi=wi+ws/20 hi=hi-hs/5 MoveMouse 200,200 If hi<-160 Then hi=-160 If hi>160 Then hi=160 ;Körperbewegung If KeyDown(203) Then wi=wi-16/w If KeyDown(205) Then wi=wi+16/w If KeyDown(200) Then If xy(xp+Cos(wi)/24,yp+Sin(wi)/24)=0 Then xp=xp+Cos(wi)/24:yp=yp+Sin(wi)/24 If KeyDown(208) Then If xy(xp-Cos(wi)/24,yp-Sin(wi)/24)=0 Then xp=xp-Cos(wi)/24:yp=yp-Sin(wi)/24 If MouseDown(2) Then If xy(xp+Cos(wi)/24,yp+Sin(wi)/24)=0 Then xp=xp+Cos(wi)/24:yp=yp+Sin(wi)/24 If KeyHit(2) Then w=w-1:If w<1 Then w=1 If KeyHit(3) Then w=w+1:If w>8 Then w=8 ;Raycaster For x=-200 To 200 Step 2 f=0 For e=0 To 5 Step .02 If f=0 And xy(xp+Cos(wi+x/w)*e,yp+Sin(wi+x/w)*e)=1 Then Color 255-e*50,255-e*50,255-e*50 Rect x,hi-200/e,2,400/e f=1 End If Next Next ;Map zeichnen Color 0,0,0 Rect -200,-200,80,80,1 Color 240,240,240 For y=0 To 9 For x=0 To 9 If xy(x,y)=1 Then Rect x*8-200,y*8-200,8,8,1 Next Next Rect xp*8-197.5,yp*8-197.5,3,3,1 Line xp*8-196.5,yp*8-196.5,xp*8-196.5+Cos(wi)*4,yp*8-196.5+Sin(wi)*4 Flip Cls Wend End /EDIT: Habs leider mit der Kollision nicht so gut hinbekommen. Bei einer Wandkollision bleibt mein Männchen stehen. ![]() |
||
![]() |
maximilian |
![]() Antworten mit Zitat ![]() |
---|---|---|
So, jetzt fehlt nurnoch Texture-Mapping. Sollte auch ziemlich einfach zu implementieren sein. ![]() |
||
Variety is the spice of life. One day ignore people, next day annoy them. |
#ReaperNewsposter |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Also das sieht doch echt mal toll aus ![]() ![]() Würde sowas wohl nicht hinbekommen ![]() Allerdings, finde ich das mit dem Fischauge etwas..unrealistisch.also, vielleicht seh ich ja auch nicht richtig, aber zumindestens sieht das nicht so stark aus ![]() Okok...ich versteh davon eh nicht viel..fas nichts ^^ Nur weiter so ![]() MfG #Reaper |
||
AMD Athlon 64 3500+, ATI AX800 Pro/TD, 2048 MB DRR 400 von Infineon, ♥RIP♥ (2005 - Juli 2015 -> sic!)
Blitz3D, BlitzMax, MaxGUI, Monkey X; Win7 |
![]() |
KabelbinderSieger des WM-Contest 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
hm, bisher konnte ich den Linseneffekt nur minimieren:
Code: [AUSKLAPPEN] AppTitle "Raycasting"
Graphics 850,680,16,2 SetBuffer BackBuffer() Const w = 7 Const h = 7 Const view_arc# = 100 Const view_w = 255 Const quality = 2 Const width_fac# = 0.21 Global xcor#,ycor#,rot,distance#,st,togo,mx,my,speed Dim map(7,7) For y = 0 To 7 For x = 0 To 7 Read map(x,y) Next Next Data 1,1,1,1,1,1,1,1 Data 1,0,1,0,0,0,0,1 Data 1,0,1,0,0,0,0,1 Data 1,0,1,0,1,0,1,1 Data 1,0,1,1,1,0,0,1 Data 1,0,0,0,1,1,0,1 Data 1,0,1,0,0,0,0,1 Data 1,1,1,1,1,1,1,1 xcor = 75 ycor = 125 rot = 90 speed = 2 distance = (1/Tan(view_arc/2))*120 Function coll(x,y) If RectsOverlap(x,y,1,1,0,0,(w+1)*50,(h+1)*50) Then If map(x/50,y/50)=1 Then Return 1 EndIf End Function Function move() If KeyDown(208)=1 Then xcor = xcor - Cos(rot) *speed If coll(xcor,ycor) Then xcor = xcor + Cos(rot)*speed ycor = ycor - Sin(rot) *speed If coll(xcor,ycor) Then ycor = ycor + Sin(rot) *speed EndIf If KeyDown(200)=1 Then xcor = xcor + Cos(rot) *speed If coll(xcor,ycor) Then xcor = xcor - Cos(rot) *speed ycor = ycor + Sin(rot) *speed If coll(xcor,ycor) Then ycor = ycor - Sin(rot) *speed EndIf If KeyDown(203) Then rot = rot - 1 *speed EndIf If KeyDown(205) Then rot = rot + 1 *speed EndIf If rot > 360 Then rot = 0 If rot < 0 Then rot = 360 End Function Repeat mx = MouseX() my = MouseY() st = 0 For f# = 0.0 To view_arc Step width_fac# togo = 1 For g = 0 To view_w Step quality If togo = 1 If coll(xcor+Cos(rot-view_arc/2+f)*g,ycor+Sin(rot-view_arc/2+f)*g) Then If g <= 255 Then Color -g+255,-g+255,-g+255 Else Color 0,0,0 EndIf Rect st+150,150+(240-distance/g*120),1,distance/g*240 togo = 0 g = view_w EndIf EndIf Next st = st + 1 Next Color 0,0,0 Rect 0,0,850,150 Rect 0,480+150,850,680 Rect 0,0,150,680 Rect 150+666,0,150,680 move() For y = 0 To 7 For x = 0 To 7 Color 255,255,255 If map(x,y)=1 Then Rect x*20,y*20,20,20 EndIf Next Next Color 255,0,0 Oval xcor/2.5-2,ycor/2.5-2,5,5 Line xcor/2.5,ycor/2.5,xcor/2.5+Cos(rot)*10,ycor/2.5+Sin(rot)*10 Text 200,0,distance Text 200,10,xcor Text 200,20,ycor Text 200,30,st Text 200,40,togo Text 200,50,rot Text 200,60,Str$(mx)+" "+Str$(my) Flip Cls Until KeyHit(1) End Ich hab die Brennweite verändert und einen Rahmen um die ganze Geschichte gemacht. Ich glaube, das liegt einfach an der Methode, die ich benutze, nach der ist das ganz gut nachvollziehbar mit dem Linseneffekt. Ich weiß auch nicht, wie ich den Effekt ganz wegbekommen kann. Läuft jetzt auch schneller Im Moment versuche ich das zu texturieren, was ich wohl nie hinkriegen werde |
||
<Wing Avenger Download> ◊◊◊ <Macrophage Download> |
FWeinbehemals "ich" |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
seit super aus aber ![]() könte einer bitte bitte bitte den code kommentieren |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo ich ![]() ;Bildschirmauflösung setzen
Graphics 320,240,32,1 ;Bildschirmzwischenpuffer einschalten SetBuffer BackBuffer() ;X/Y-Koordinaten auf Bildschirmmitte verlagern Origin 160,120 ;Mauspointer versteken (nur bei Fenstermodus) HidePointer Dim xy(19,19) ;Spielfeld xp#=1 ;Spieler-X-Position yp#=1 ;Spieler-Y-Position ws#=90 ;SPieler-Sollwinkel wi#=90 ;Spieler-Istwinkel hs#=0 ;Spieler-Sollhöhe hi#=0 ;Spieler-Isthöhe x#=0 ;Schleifenvariable y#=0 ;Schleifenvariable e#=0 ;Strahlentfernung zur Wand w%=3 ;Winkeleinfang (tele/weit) f%=0 ;Funktionsvariable ;Hier wird die Map in die DIM-Felder eingelesen For y=0 To 19 For x=0 To 19 ;Datafelder nacheinander auslesen und positioniert in das Dim eintragen Read xy(x,y) Next Next ;Die Map, 0=frei, 1=Wand Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 Data 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 Data 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 Data 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 Data 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 Data 1,0,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,0,0,1 Data 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1 Data 1,0,1,1,1,1,1,0,1,0,0,0,0,0,0,0,1,0,1,1 Data 1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1 Data 1,0,1,0,1,1,1,0,1,0,0,0,0,0,0,0,0,0,1,1 Data 1,0,1,0,1,0,0,0,0,0,0,1,0,1,0,0,0,1,1,1 Data 1,0,0,0,1,0,1,0,1,0,1,1,0,1,1,0,0,0,0,1 Data 1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1 Data 1,0,0,0,0,0,1,0,1,0,1,1,0,1,1,0,0,0,0,1 Data 1,0,1,1,1,1,1,0,0,0,0,1,0,1,0,0,0,1,1,1 Data 1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1 Data 1,0,1,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1 Data 1,0,1,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,0,1 Data 1,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,0,0,0,1 Data 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 ;HAUPTSCHLEIFE While Not KeyHit(1) ;KOPFBEWEGUNG ;WS ist der Sollwinkel (Laufrichtung) der durch eine Maus-X-Bewegung berechnet wird. ws=(ws+MouseXSpeed())/1.4 ;HS ist die Sollbetrachtungshöhe (Kopf hoch/runter) der durch eine Maus-Y-Bewegung berechnet wird. hs=(hs+MouseYSpeed())/1.4 ;Damit die Bewegungen nicht zu 'hackelig' wird, wird eine Annäherung zum Sollwinkel berechnet. ;WI ist der Istwinkel (Laufrichtung) der sich an den Sollwinkel annährt. wi=wi+ws/3/w ;HI ist die Istbetrachtungshöhe (Kopf hoch/runter) der sich an die Sollhöhe annährt. hi=hi-hs/5 ;Da die Mausabfrage nur relativ genutzt wird (erst damit wird es möglich sich öffters umrum zu ;drehen, da die Maus jetzt keine Begrenzug mehr kennt) muß die Maus zur Bildschirmmitte bewegt werden. MoveMouse 160,120 ;Damit die Kopfhöhe keinen Nackenbruch des Spielers hervorruft wird die Betrachtungshöhe eingegrenzt. If hi<-80 Then hi=-80 If hi>80 Then hi=80 ;KÖRPERBEWEGUNG ;Wenn [Strg] gedrückt (nach links sliden) dann soll überprüft werden ob es überhaupt geht. Dies wird durch ;eine umgerechnete 'Kollisionsprüfung' auf dem Dim-feld direkt geacht. Ist das Feld frei dann wird bewegt. If KeyDown(29) Then If xy(xp-Cos(wi+90)/48,yp-Sin(wi+90)/48)=0 Then xp=xp-Cos(wi+90)/48:yp=yp-Sin(wi+90)/48 ;Wenn [linke Alt] gedrückt (nach rechts sliden) dann wird das gleiche gemacht wie bei [Strg] nur nach rechts. If KeyDown(56) Then If xy(xp-Cos(wi-90)/48,yp-Sin(wi-90)/48)=0 Then xp=xp-Cos(wi-90)/48:yp=yp-Sin(wi-90)/48 ;Wenn [q] gedrückt (nach hinten laufen) dann wird das gleiche gamcht wie bei [Strg], [linke Alt] nur nach hinten. If KeyDown(16) Then If xy(xp-Cos(wi)/24,yp-Sin(wi)/24)=0 Then xp=xp-Cos(wi)/24:yp=yp-Sin(wi)/24 ;Wenn [rechte Maustaste] gedrückt (nach vorne laufen) dann wird das gleiche gamcht wie bei den anderen nur nach vorne. If MouseDown(2) Then If xy(xp+Cos(wi)/24,yp+Sin(wi)/24)=0 Then xp=xp+Cos(wi)/24:yp=yp+Sin(wi)/24 ;Wenn [1] gedrückt wird der Bildeinfangwinkel/Betrachtungswinkel vergrössert (ähnlich einem Weitwinkelobjektiv). If KeyHit(2) Then w=w-1:If w<1 Then w=1 ;Wenn [2] gedrückt wird der Bildeinfangwinkel/Betrachtungswinkel verkleiner (ähnlich einem Teleobjektiv). If KeyHit(3) Then w=w+1:If w>6 Then w=6 ;RAYCASTER ;Die X/Y-Koordinaten sind durch Origin 160,120 zum Bildschirmmitte verlagert worden. ;Jede zweite Bildschirmzeile von links nach rechts durchgehen X-Variable. For x=-160 To 160 Step 2 ;F ist eine Hilfsvariable die die Darstellung erheblich schneller macht. Sie ermöglicht es sinnlose ;überprüfungen (Rechenaufwendig) zu vermeiden. f=0 ;E ist die Entfernung die der Ray hinterlegen muß, bis es auf eine Wand (Dim xy(xx,yy)) trifft. For e=0 To 26 Step .04 ;Nur so lange weiterprüfen wenn der aktuelle Ray noch keine Wand 'getroffen' hat. If f=0 Then ;Überprüfen ob neue berechnete Position des Ray's auf eine wand trifft. If xy(xp+Cos(wi+x/w)*e,yp+Sin(wi+x/w)*e)=1 Then ;Ray hat jetzt eine Wand getroffen. Aufgrund der Entfernung E wird ;jetzt der Farbwerd der Wand an dieser Stelle berechnet. Color 512/(e+2),1024/(e+4),512/(e+2);255-e*9 ;Die neu berechnete Wand wird entsprechend der Entfernung E in einer berechneten 'größe' dargestellt. Rect x,hi-100/e,2,200/e ;Der Ray hat eine Wand getroffen, weitere Berechnungen werden für diesen Ray hiermit unterbunden. f=1 End If End If Next Next ;FADENKREUZ ;Zeichnet das Fadenkreuz ein Color 255,255,255:Rect -1,-1,2,2,1 ;Damit V-Sync immer 'erzwungen' wird. Auch dann wenn der User ;der Meinung ist er müsse das Treiberseitig ausschalten. :-) VWait ;Bildschirm anzeigen. Bitte immer 0, da bereits VWait aktiviert! Flip 0 ;Bildschirm für neue Ausgabe löschen Cls Wend End P.S. Ich verlange eine Antwort, ob ich dir damit helfen konnte... ![]() |
||
![]() |
maximilian |
![]() Antworten mit Zitat ![]() |
---|---|---|
Man kann durch eine weitere Formel den Fishbowl-Effekt komplett vermeiden, da ich aber von Raycasting keine Ahnung habe... ![]() Auf QBasic.de war mal (und ist immernoch) ein enorm gutes Tutorial über die Grafikprogrammierung in QB. Da hat der Raycasting enorm gut beschrieben. Vielleicht schaust du es dir mal an, steht auch genau drin wie du diesen Effekt wegberechnen kannst. ![]() |
||
Variety is the spice of life. One day ignore people, next day annoy them. |
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Also noch einmal... Warum sollte man etwas schlechter und dabei auch noch aufwendiger machen als man es bereits fertig hat? Dieser Effekt kommt übrigens immer vor! Es ist schlicht unmöglch 'richtiges 3D' darzustellen und auf ein solchen Effekt zu verzichten. Dieser Effekt kommt bei Fotografien, Kameraaufnahmen, dem Menschlichem Auge etc. praktisch überall vor wo die 3D-Welt auf eine flache 2D-Darstellung abgelichtet wird (Beim Auge ist der Effekt wiederrum nicht so stark, da die Netzhaut bereits auch gewölbt ist, aber nicht so stark wie der Betrachtungswinkeleinfang des Auges.). Bei normalen Aufnahmen sieht man es nicht so stark, da Fehrnsehshows, Nachrichten etc nur einen sehr kleinen Teil der Vollaufnahme einfangen. Also je mehr Weitwinkel um so mehr Fishauge-Effekt. Bei Panoramaaufnahmen kommt der Effekt noch mehr zu tragen, und da würde keiner sagen "Das hat man mit dem Computer extra so gemacht damit der Betrachter verwirrt ist". Mir ist klar das ein Raycaster (also eine umgerechete 2D-Grafik) nur in der Y-Achse die Verzehrung hat. Bei richigen Renderprogrammen (Raytracer) wird auch die X-Achse verzehrt. Eine solche Darstellung währe aber in Realtime noch nicht möglich und erst recht nicht unter BB.
Um den Effekt komplett bei einem Raycaster zu vermeiden müsste man die 'Strahlen' nicht radial sondern parallel ausbreiten. Die Entfernung zu Objekten währe dann am Rande des Bildschirmes weiter weg als in der Mitte, würden aber fälschlicherweise gleih nah gezeichnet. Übrigens: Das was die Grafikkarten bei HalfLife1+2, Doom3, etc darstellen, ist weniger richtiges 3D als die Versuche hier! Doom1+2, Heretic, Duke Nukem etc wahren alle Raycaster aber mit paralleler Ausbreitung der Strahlen. Warum die das so gemacht haben weiß ich nicht. Vielleicht habe sie gesehen das viele damit nicht klar kommen. Oder vielleicht weil sonst die Texturen nicht mehr so 'einfach' auf die Welt projeziert werden kann. Könnte mich mal in den nächsten Tagen hinsetzen und ein solchen programmieren. |
||
Apocalyptic |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
@Hectic: Der Fischaugen-Effekt mag zwar rein theoretisch realistisch sein - aber wenn du die Welt mit deinen Augen so war nimmst, tust du mir Leid ![]() Es ist schlicht weg Fakt, dass unser Auge unsere Umgebung nicht derart verzerrt wahrnimmt. Das dürfte wohl auch der Grund sein, warum Doom1+2, Heretic, Duke Nukem etc. den Fischaugen-Effekt vermeiden - der Spieler läuft eben nicht mit einem Fischaugenobjektiv vor den Augen rum ![]() @Kabelbinder: Netter Anfang. Wenn du den Fischaugen-Effekt nicht so verehrst wie Hectic, reicht es, wenn du anstatt der realen Entfernung, welche die Hypothenuse c des folgenden Dreiecks darstellt, die Ankathete a für die Berechnung der Höhe einer Wand nimmst: ![]() Diese lässt sich mit einfachsten trigonometrischen Kenntnissen aus der Hypothenuse berechnen ![]() |
||
Suum cuique
[ www.ffs-net.de.vu ] [ Raycaster ] |
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo Apocalyptic, das menschliche Auge nimmt diesen Effekt aus zwei Gründen nicht so stark war wie das eines Weitwinkelobjektives. 1) Das Gehirn 'richtet' die Krümmung um geraden besser ausfindig zu machen. 2) Weil die Netzhaut im inneren des Auges auch eine Krümmung hat (ist ja nicht platt). Beim ersteren kann man dies am besten erkennen wenn man sich in einer nicht gewöhnlichen Situation befindet. Beispiel: Man lege sich in die Mitte eines Zimmers und schaut gerade nach oben, so das man alle vier Wände sehen kann. Die Kanten an der Decke erscheinen dann auch gewölbt.
Wer denoch ein Raycaster mit geraden haben will nimmt sich mein letzten oben geposteten Code und ersetzt die Zeile 102 durch folgende.Code: [AUSKLAPPEN] If xy(xp+(Cos(wi)*e)+Cos(90+wi)*(e*x/100),yp+(Sin(wi)*e)+Sin(90+wi)*(e*x/100))=1 Then
|
||
Apocalyptic |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
hectic hat Folgendes geschrieben: 1) Das Gehirn 'richtet' die Krümmung um geraden besser ausfindig zu machen. 2) Weil die Netzhaut im inneren des Auges auch eine Krümmung hat (ist ja nicht platt).
Richtig. Das führt dazu, dass, wenn du senkrecht auf eine Wand siehst, diese nicht derart gekrümmt wahrnimmst: ![]() Wieso sollte dieses Verhalten der menschlichen Wahrnehmung dann bei einem Raycaster nicht nachempfunden werden, wenn diese "Korrekturen", die der Mensch mehr als nur gewohnt ist, bei der Darstellung eines dreidimensionalen Raumes auf einem flachen Bildschirm nicht funktionieren? |
||
Suum cuique
[ www.ffs-net.de.vu ] [ Raycaster ] |
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Weil das menschliche Auge in der realen Welt diese Korekturen vornimmt, aber die Linse eines Weitwinkelobjektives nicht und somit die Darstellung der realen Welt auf ein flachen Bildschirm genauso verzehrt am 'richtigsten' ist. Wenn ich vor einer Mauer stehe sehe ich die Verzehrung nicht besonders (weil das Gehirn es für mich überarbeitet hat, sonst könnten wir einen geraden Masst nicht von einem gekrümten Baum unterscheiden). Wenn man sich nicht grad dumm anstellt, kann man auch mit sturem Geradeausblick auf eine Mauer beide Fluchtpunkte gleichzeitig sehen. Das nachahmen der beiden Fluchtpunkten wird erst in einem Raycaster möglich. Ich muß mich nicht mit der Maus umschauen um den einen oder anderen Fluchtpunkt zu sehen, sondern es reicht wenn ich mein Auge an den Seiten meines Spiels richte. Letztendlich bleibt es jedem selbst überlassen. Ich zu meinem Teil würde am liebsten HalfLife2 mit einer Raytracer-Engine spielen, was wohl noch an der Performance schrauben dürfte. Alle mir bekannten Egoshoter haben 90° (+-45° in der X-Achse) Blickeinfang. Erst mit einem Raycaster sind 180° und mehr möglich. Perfekt währe das spielen eines solchen Spiels dann erst vor einer Leinwand die bereits fast den ganzen Sichtbereich des Auges abdeckt. Aber für die die es nicht so gern haben, habe ich mein letzten Post geschrieben. Gerade Linien auf einem Raycaster. Dann kann man lieber gleich auf die 3D-Unterstützung der Grafikkarten zurrückgreifen. Ein weiteres Problem bei der Hardware unterstützten Darstellung ist, daß Gegenstände am Rande des Bildschirmes fast doppelt so tief wirken als sie es sind. Das passiert bei einem Raycaster nicht.
werde mal zum Spaß noch einen Raytracer schreiben. Allerdings nicht auf Vektorbasis sondern per 3D-Dim-Felder. Mal sehen wie das dann aussieht. |
||
![]() |
KabelbinderSieger des WM-Contest 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
thx, Apocalyptic. könnte man sich nicht vielleicht auch senkrecht zur blitzrichtung bewegen und jeden Pixel einen Strahl werfen?
dann müsste man doch auch so Gerade Kanten herausbekommen. Ich hab jetzt den Linseneffekt eigentlich raus, dafür tritt jetzt aber eine Art Klopapiereffekt auf ![]() Code: [AUSKLAPPEN] AppTitle "Raycasting"
Graphics 850,680,16,2 SetBuffer BackBuffer() Const w = 7 Const h = 7 Const view_arc# = 100 Const view_w = 255 Const quality = 2 Const width_fac# = 0.21 Global xcor#,ycor#,rot,distance#,st,togo,mx,my,speed,textur ;textur = LoadImage("Bild/Tex2.bmp") ;Dim wall(320) ;For i = 1 To 320 Step 3 ;wall(i)=CopyImage(textur) ;ResizeImage(wall(i),i,i) ;wall(i+1)=wall(i) ;wall(i+2)=wall(i) ;Print i ;Next Dim map(7,7) For y = 0 To 7 For x = 0 To 7 Read map(x,y) Next Next Data 1,1,1,1,1,1,1,1 Data 1,0,1,0,0,0,0,1 Data 1,0,1,0,0,0,0,1 Data 1,0,1,0,1,0,1,1 Data 1,0,1,1,1,0,0,1 Data 1,0,0,0,1,1,0,1 Data 1,0,1,0,0,0,0,1 Data 1,1,1,1,1,1,1,1 xcor = 75 ycor = 125 rot = 90 speed = 2 distance = (1/Tan(view_arc/2))*120 Function coll(x,y) If RectsOverlap(x,y,1,1,0,0,(w+1)*50,(h+1)*50) Then If map(x/50,y/50)=1 Then Return 1 EndIf End Function Function move() If KeyDown(208)=1 Then xcor = xcor - Cos(rot) *speed If coll(xcor,ycor) Then xcor = xcor + Cos(rot)*speed ycor = ycor - Sin(rot) *speed If coll(xcor,ycor) Then ycor = ycor + Sin(rot) *speed EndIf If KeyDown(200)=1 Then xcor = xcor + Cos(rot) *speed If coll(xcor,ycor) Then xcor = xcor - Cos(rot) *speed ycor = ycor + Sin(rot) *speed If coll(xcor,ycor) Then ycor = ycor - Sin(rot) *speed EndIf If KeyDown(203) Then rot = rot - 1 *speed EndIf If KeyDown(205) Then rot = rot + 1 *speed EndIf If rot > 360 Then rot = 0 If rot < 0 Then rot = 360 End Function Repeat mx = MouseX() my = MouseY() st = 0 For f# = 0.0 To view_arc Step width_fac# togo = 1 For g = 0 To view_w Step quality If togo = 1 If coll(xcor+Cos(rot-view_arc/2+f)*g,ycor+Sin(rot-view_arc/2+f)*g) Then If g <= 255 Then Color -g+255,-g+255,-g+255 Else Color 0,0,0 EndIf Rect st+150,150+80000.0/Float(480+Cos(view_arc/2)*g),1,80000.0/Float(480+Cos(view_arc/2)*g) togo = 0 g = view_w EndIf EndIf Next st = st + 1 Next Color 0,0,0 Rect 0,0,850,150 Rect 0,480+150,850,680 Rect 0,0,150,680 Rect 150+666,0,150,680 move() For y = 0 To 7 For x = 0 To 7 Color 255,255,255 If map(x,y)=1 Then Rect x*20,y*20,20,20 EndIf Next Next Color 255,0,0 Oval xcor/2.5-2,ycor/2.5-2,5,5 Line xcor/2.5,ycor/2.5,xcor/2.5+Cos(rot)*10,ycor/2.5+Sin(rot)*10 Text 200,0,distance Text 200,10,xcor Text 200,20,ycor Text 200,30,st Text 200,40,togo Text 200,50,rot Text 200,60,Str$(mx)+" "+Str$(my) Flip Cls Until KeyHit(1) End |
||
<Wing Avenger Download> ◊◊◊ <Macrophage Download> |
Apocalyptic |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Kabelbinder hat Folgendes geschrieben: könnte man sich nicht vielleicht auch senkrecht zur blitzrichtung bewegen und jeden Pixel einen Strahl werfen?
Blitzrichtung? o_O Kabelbinder hat Folgendes geschrieben: Ich hab jetzt den Linseneffekt eigentlich raus, dafür tritt jetzt aber eine Art Klopapiereffekt auf
![]() Das hier ist auch nicht die Ankathete:Code: [AUSKLAPPEN] Cos(view_arc/2)*g ![]() |
||
Suum cuique
[ www.ffs-net.de.vu ] [ Raycaster ] |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group