jaja ich habs noch nicht ganz aufgegeben. Trotz rudimentärem Verständnis für Trigonometrie und ähnliche Schweinereien versuche ich mich immer noch mal in 3D durch den Weltraum zu bewegen, der ja bekanntlich keinen Boden hat. Somit sollte ich meine Kamera ja auch in alle Richtungen frei bewegen können.
Habe mir die Formeln, die hier im Forum dazu geschrieben wurden, immer wieder inhaliert und scheinbar doch nicht wirklich verstanden.
Im folgenden Beispiel ist die Kamera erst einmal auf 0,0,0 gesetzt. Um die Kamera hab ich willkürlich 50 Kuben verstreut (3Dprimitives.gbas aus Common-Ordner einbinden). Nun will ich mit den Cursortasten die Kamera frei bewegen können.
Links - rechts für Bewegung auf X-Z
Oben- unten für Bewegung auf Y-Z
bewege ich nach dem Programmstart die Kamera links-rechts, klappt das wunderbar. Bei oben-unten nur bis Winkel 90 (bzw. 270). dann wird dort die Bewegungsrichtung umgekehrt.
Weiterhin, wenn ich die Kamera z.B. ein wenig nach oben oder unten bewege und dann wieder links-rechts drehe, scheint die Bewegung einer Kurve zu folgen und nicht mehr einer Geraden.
Ich bin ehrlich verwirrt.
Helft einem armen Nicht-Mathematiker.
TYPE t_vertex
x; y; z
ENDTYPE
TYPE t_camera
pos AS t_vertex
delta AS t_vertex
phi // angle x-z
psi // angle y-z
ENDTYPE
GLOBAL cam AS t_camera
TYPE t_3dobj
pos AS t_vertex
object
texture
rotate AS t_vertex
angle AS t_vertex
ENDTYPE
GLOBAL new3dobj AS t_3dobj
GLOBAL d3dobj[] AS t_3dobj
TYPE t_ship
speed
max_speed = 5
ENDTYPE
GLOBAL ship AS t_ship
LOADSPRITE "lava01.bmp", 0
FOR i = 0 TO 50
CreateCube(i, RAND(20, 50), RGB(128, 128, 128))
new3dobj.pos.x = RAND(-500, 500)
new3dobj.pos.y = RAND(-400, 400)
new3dobj.pos.z = RAND(-400, 500)
new3dobj.object = i
new3dobj.texture = 0
new3dobj.rotate.x = RAND(-10, 10) / 10
new3dobj.rotate.y = RAND(-10, 10) / 10
new3dobj.rotate.z = RAND(-10, 10) / 10
DIMPUSH d3dobj[], new3dobj
NEXT
GLOBAL KEY_LEFT = 203
GLOBAL KEY_RIGHT = 205
GLOBAL KEY_UP = 200
GLOBAL KEY_DOWN = 208
GLOBAL KEY_W = 17 //accellarate
GLOBAL KEY_S = 31 //break
needcalc = TRUE
WHILE TRUE
WHILE cam.phi > 360; DEC cam.phi, 360; WEND
WHILE cam.phi < 0; INC cam.phi, 360; WEND
WHILE cam.psi > 360; DEC cam.psi, 360; WEND
WHILE cam.psi < 0; INC cam.psi, 360; WEND
IF KEY(KEY_LEFT)
DEC cam.phi, 1
needcalc = TRUE
ENDIF
IF KEY(KEY_RIGHT)
INC cam.phi, 1
needcalc = TRUE
ENDIF
IF KEY(KEY_UP)
DEC cam.psi, 1
needcalc = TRUE
ENDIF
IF KEY(KEY_DOWN)
INC cam.psi, 1
needcalc = TRUE
ENDIF
IF needcalc = TRUE
// IF cam.psi >= 90 AND cam.psi < 270
// cam.delta.x = COS(cam.phi) * -COS(cam.psi)
// cam.delta.y = -SIN(cam.psi)
// cam.delta.z = -SIN(cam.phi) * -COS(cam.psi)
// ELSE
cam.delta.x = COS(cam.phi) * COS(cam.psi)
cam.delta.y = SIN(cam.psi)
cam.delta.z = -SIN(cam.phi) * COS(cam.psi)
// ENDIF
needcalc = FALSE
ENDIF
IF KEY(KEY_W)
INC ship.speed, 0.01
IF ship.speed > ship.max_speed THEN ship.speed = ship.max_speed
ENDIF
IF KEY(KEY_S)
DEC ship.speed, 0.01
IF ship.speed < 0 THEN ship.speed = 0
ENDIF
INC cam.pos.x, cam.delta.x * ship.speed
INC cam.pos.y, cam.delta.y * ship.speed
INC cam.pos.z, cam.delta.z * ship.speed
X_MAKE3D 1, 1000, 45
X_CAMERA cam.pos.x, cam.pos.y, cam.pos.z, cam.pos.x+cam.delta.x, cam.pos.y+cam.delta.y, cam.pos.z+cam.delta.z
FOREACH obj IN d3dobj[]
X_MOVEMENT obj.pos.x, obj.pos.y, obj.pos.z
X_ROTATION obj.angle.x, 1, 0, 0
INC obj.angle.x, obj.rotate.x
X_ROTATION obj.angle.y, 0, 1, 0
INC obj.angle.y, obj.rotate.y
X_ROTATION obj.angle.z, 0, 0, 1
INC obj.angle.z, obj.rotate.z
X_SETTEXTURE obj.texture, -1
X_DRAWOBJ obj.object, 0
NEXT
//X_DRAWAXES 0, 0, 0
X_MAKE2D
PRINT "Speed: " + (INTEGER(ship.speed * 100)), 0, 0
PRINT "PHI: " + cam.phi, 0, 20
PRINT "PSI: " + cam.psi, 0, 40
SHOWSCREEN
WEND
// ------------------------------------------------------------- //
// --- RAND ---
// ------------------------------------------------------------- //
FUNCTION RAND: minimum, maximum
RETURN minimum + RND(-minimum + maximum)
ENDFUNCTION // RAND
Nimm das EntitySystem von Gernot !
Ich weis es zwar nicht mehr wo, aber schranzor hat mal (ich glaub bei codeschnipsel) den code nur für die Bewegung und drehung einer camera reingestellt (inklusive Trigonometrie). Such mal, findest man bestimmt schnell.
ja ich weiß, damit funktionierts ja auch. Problem ist ja auch eher daß ich das ganze verstehen will, daher ist auch das Entity-System erst einmal keine Alternative. naja ich probiers halt weiter ;)
Was willste den machen, das Rad neu erfinden?
Also wenn du´s nicht anhant eines beispiels erlernen willst, wie denn dann?
nein Schranzor, nichts neu erfinden, lediglich das Prinzip verstehen.
Also, habe mir Tenorms Rat zu Herzen genommen und Schranzors Beispiel nochmals inhaliert. Korrigier mich bitte, Schranzor, wenn ich was falsches sage, aber mit deinem Beispiel kann man sich zwar in x-z-Richtung im Kreis drehen, nicht jedoch in y-z-Richtung, da hier die Bewegung in deinem Beispiel auf 90° limitiert ist. Und genau das will ich ja nicht, auch in dieser Richtung soll man sich frei im Kreis bewegen können.
Wenn ich die Abfrage nach updownlimit herausnehme habe ich genau den Effekt, den ich oben beschrieben habe, nämlich daß sich die Bewegungsrichtung ab einem bestimmten Winkel umkehrt. Ist ja auch logisch, da dann sin(winkel) negativ wird.
Konkrete Frage also: Wie kann ich das umgehen?
Hier noch mal Schranzors Codeschnipsel:
http://www.glbasic.com/forum/viewtopic.php?id=1147
Ist garnet mal so einfach da sich ja alles umdreht wenn man über einen gewissen Punkt dreht :)
ebend ;)
ahh ich glaube des Rätsels Lösung liegt bei X_CAMERAUP
Bigsofty hatte das gleiche Problem ;)
http://www.glbasic.com/forum/viewtopic.php?id=804
[edit]
tja, das Problem ist schon mehrfach beschrieben, immer mit Hinweis auf X_CAMERAUP, aber leider nie mit einem Beispiel. Hat jemand das vielleicht schon mal genutzt.
[edit]
ahhh jetzt hab ich einen ersten Teilerfolg.
bei der Berechnung der y-Koordinate einfach mit X_CAMERAUP die y-Richtung umkehren
also
IF cam.psi > 90 AND cam.psi <= 270
X_CAMERAUP 0, -1, 0
ENDIF
X_CAMERA cam.pos.x, cam.pos.y, cam.pos.z, cam.delta.x, cam.delta.y, cam.delta.z
nach jedem X_MAKE3D wird X_CAMERAUP wieder auf 0, 1, 0 gesetzt. Jetzt kann ich mich zumindest in y-Richtung im Kreis drehen, solange ich mit der Kamera an Position 0,0,0 stehen bleibe. Bewege ich mich davon weg, springt die Ansicht wüst umher, also weiter probieren.
ahhh ich habs. Schranzor, sorry für den Doppelpost, aber das passt jetzt inhaltlich wirklich nicht mehr in den alten ;)
So jetzt kann ich mich endlich frei in alle Richtungen drehen und dabei mit den Tasten W (beschleunigen) und S (bremsen) auch noch die Kamera bewegen. Mit Textur sehen die Würfel natürlich chicer aus. Als Beispiel kann man das hier mal nehmen:
http://www.gallerie1.de/iron02.jpg
// --------------------------------- //
// Project: 3D-Rookie
// Start: Saturday, January 05, 2008
// IDE Version: 5.110
TYPE t_vertex
x; y; z
ENDTYPE
TYPE t_camera
pos AS t_vertex
delta AS t_vertex
phi // angle x-z
psi // angle y-z
ENDTYPE
GLOBAL cam AS t_camera
TYPE t_3dobj
pos AS t_vertex
object
texture
rotate AS t_vertex
angle AS t_vertex
ENDTYPE
GLOBAL new3dobj AS t_3dobj
GLOBAL d3dobj[] AS t_3dobj
TYPE t_ship
speed
max_speed = 5
ENDTYPE
GLOBAL ship AS t_ship
LOADSPRITE "iron02.png", 0
FOR i = 0 TO 360 STEP 10
CreateCube(i, RAND(20, 50), RGB(128, 128, 128))
new3dobj.pos.x = RAND(-500, 500)
new3dobj.pos.y = RAND(-400, 400)
new3dobj.pos.z = RAND(-400, 500)
new3dobj.object = i
new3dobj.texture = 0
new3dobj.rotate.x = RAND(-10, 10) / 10
new3dobj.rotate.y = RAND(-10, 10) / 10
new3dobj.rotate.z = RAND(-10, 10) / 10
DIMPUSH d3dobj[], new3dobj
NEXT
GLOBAL KEY_LEFT = 203
GLOBAL KEY_RIGHT = 205
GLOBAL KEY_UP = 200
GLOBAL KEY_DOWN = 208
GLOBAL KEY_W = 17 //accellarate
GLOBAL KEY_S = 31 //break
needcalc = TRUE
//cam.phi = 90
WHILE TRUE
WHILE cam.phi > 360; DEC cam.phi, 360; WEND
WHILE cam.phi < 0; INC cam.phi, 360; WEND
WHILE cam.psi > 360; DEC cam.psi, 360; WEND
WHILE cam.psi < 0; INC cam.psi, 360; WEND
IF KEY(KEY_LEFT)
DEC cam.phi, 1
needcalc = TRUE
ENDIF
IF KEY(KEY_RIGHT)
INC cam.phi, 1
needcalc = TRUE
ENDIF
IF KEY(KEY_UP)
DEC cam.psi, 1
needcalc = TRUE
ENDIF
IF KEY(KEY_DOWN)
INC cam.psi, 1
needcalc = TRUE
ENDIF
IF needcalc = TRUE
cam.delta.x = COS(cam.phi) * COS(cam.psi)
cam.delta.z = -SIN(cam.phi) * COS(cam.psi)
cam.delta.y = SIN(cam.psi)
needcalc = FALSE
ENDIF
IF KEY(KEY_W)
INC ship.speed, 0.01
IF ship.speed > ship.max_speed THEN ship.speed = ship.max_speed
ENDIF
IF KEY(KEY_S)
DEC ship.speed, 0.01
IF ship.speed < 0 THEN ship.speed = 0
ENDIF
INC cam.pos.x, cam.delta.x * ship.speed
INC cam.pos.y, cam.delta.y * ship.speed
INC cam.pos.z, cam.delta.z * ship.speed
X_MAKE3D 1, 1000, 45
IF cam.psi > 90 AND cam.psi <= 270
X_CAMERAUP 0, -1, 0
ENDIF
X_CAMERA cam.pos.x, cam.pos.y, cam.pos.z, cam.pos.x + cam.delta.x, cam.pos.y + cam.delta.y, cam.pos.z + cam.delta.z
FOREACH obj IN d3dobj[]
X_MOVEMENT obj.pos.x, obj.pos.y, obj.pos.z
X_ROTATION obj.angle.x, 1, 0, 0
INC obj.angle.x, obj.rotate.x
X_ROTATION obj.angle.y, 0, 1, 0
INC obj.angle.y, obj.rotate.y
X_ROTATION obj.angle.z, 0, 0, 1
INC obj.angle.z, obj.rotate.z
X_SETTEXTURE obj.texture, -1
X_DRAWOBJ obj.object, 0
NEXT
X_DRAWAXES 0, 0, 100
X_MAKE2D
PRINT "Speed: " + (INTEGER(ship.speed * 100)), 0, 0
PRINT "PHI: " + cam.phi, 0, 20
PRINT "PSI: " + cam.psi, 0, 40
PRINT "cam.delta.x: " + cam.delta.x, 0, 60
PRINT "cam.delta.y: " + cam.delta.y, 0, 80
PRINT "cam.delta.z: " + cam.delta.z, 0, 100
PRINT "cam.pos.x: " + cam.pos.x, 0, 120
PRINT "cam.pos.y: " + cam.pos.y, 0, 140
PRINT "cam.pos.x: " + cam.pos.x, 0, 160
SHOWSCREEN
WEND
// ------------------------------------------------------------- //
// --- RAND ---
// ------------------------------------------------------------- //
FUNCTION RAND: minimum, maximum
RETURN minimum + RND(-minimum + maximum)
ENDFUNCTION // RAND
Du kannst das ganze ja auch einfach doppelt machen, etwa so:
IF rotation>0 AND rotation<=180 THEN ...
IF rotation>180 AND rotation<=360 THEN ...
IF rotation>360 THEN rotation=rotation-360
IF rotation<0 THEN rotation=rotation+360
Nicht schön, aber eigendlich sollts das tun...
Ich stehe hier gewaltig auf dem Schlauch.
folgendes kleine Beispiel soll das verdeutlichen. Der Richtungsvektor der Kamera wird hier durch eine rote Linie dargestellt. Cursortaste rechts - links und oben - unten zur Bewegung der Kamera. (bzw. des Vektors). Solange ich mich nur in der Ebene x-z bewege, ist das auch in Ordnung. Auch in y-z-Richtung is ok
AAAAAAAAABBBER.
je mehr der Vektor in Richtung y-Achse zeigt, umso kleiner werden die Kreisbewegungen, bis schließlich bei (0, 1, 0) als wenn der Richtungsvektor gleich der y-Achse ist, die Bewegung ganz aufhört, wenn ich die Cursortasten rechts-links betätige. Ok, ist anhand der Formeln auch klar.
Wie bekomme ich es hin, daß der beschriebene Kreis immer gleich groß ist (bei rechts-links), auch wenn sich der Winkel zur y-Achse ändert. Bei (0, 1, 0) müsste das dann z.B. eine Rotation um die Z-Achse sein.
Tip? Denkanstoss?
// --------------------------------- //
// Project: 3D-Rookie2
// Start: Friday, April 18, 2008
// IDE Version: 5.204
TYPE t_vertex
x; y; z
ENDTYPE
TYPE t_camera
pos AS t_vertex // camera position
delta AS t_vertex // lookat vector
up AS t_vertex // vector for X_CAMERAUP
phi // angle x-z
psi // angle y-z
ENDTYPE
GLOBAL cam AS t_camera
GLOBAL KEY_LEFT = 203
GLOBAL KEY_RIGHT = 205
GLOBAL KEY_UP = 200
GLOBAL KEY_DOWN = 208
needcalc = TRUE
cam.phi = 90
WHILE TRUE
WHILE cam.phi > 360; DEC cam.phi, 360; WEND
WHILE cam.phi < 0; INC cam.phi, 360; WEND
WHILE cam.psi > 360; DEC cam.psi, 360; WEND
WHILE cam.psi < 0; INC cam.psi, 360; WEND
IF KEY(KEY_LEFT)
INC cam.phi, 1
needcalc = TRUE
ENDIF
IF KEY(KEY_RIGHT)
DEC cam.phi, 1
needcalc = TRUE
ENDIF
IF KEY(KEY_UP)
INC cam.psi, 1
needcalc = TRUE
ENDIF
IF KEY(KEY_DOWN)
DEC cam.psi, 1
needcalc = TRUE
ENDIF
IF needcalc = TRUE
cam.delta.x = COS(cam.phi) * COS(cam.psi)
cam.delta.y = SIN(cam.psi)
cam.delta.z = -SIN(cam.phi) * COS(cam.psi)
ENDIF
X_MAKE3D 1, 2000, 45
X_CAMERA 20, 20, -100, 0, 0, 0
X_LINE cam.pos.x, cam.pos.y, cam.pos.z, cam.pos.x+cam.delta.x*10, cam.pos.y+cam.delta.y*10, cam.pos.z+cam.delta.z*10, 3, RGB(255, 0, 0)
X_PRINT "Lookat-vector", cam.delta.x*10, cam.delta.y*10, cam.delta.z*10, 0
X_DRAWAXES 0, 0, 0
X_MAKE2D
PRINT "PHI: " + cam.phi, 0, 20
PRINT "PSI: " + cam.psi, 0, 40
PRINT "cam.pos.x: " + cam.pos.x, 0, 60
PRINT "cam.pos.y: " + cam.pos.y, 0, 80
PRINT "cam.pos.x: " + cam.pos.x, 0, 100
PRINT "lookat x: " + FORMAT$(4, 2, cam.pos.x + cam.delta.x), 0, 120
PRINT "lookat y: " + FORMAT$(4, 2, cam.pos.y + cam.delta.y), 0, 140
PRINT "lookat z: " + FORMAT$(4, 2,cam.pos.z + cam.delta.z), 0, 160
PRINT "Upvector x: " + FORMAT$(4, 2, cam.pos.x + cam.up.x), 0, 180
PRINT "Upvector y: " + FORMAT$(4, 2, cam.pos.y + cam.up.y), 0, 200
PRINT "Upvector z: " + FORMAT$(4, 2, cam.pos.z + cam.up.z), 0, 220
SHOWSCREEN
WEND
Warum nimmst du nich schranzor´s bsp?
Tenorm