Tipp 0462
|
Bewegen im 3D-Raum
|
|
|
Autor/Einsender: Datum: |
|
Alexander Csadek 22.09.2005 |
|
Entwicklungsumgebung:
DirectX-Version: |
|
VB 6
DirectX 8 |
|
|
Ein Spiel in 3D bringt nicht viel wenn man sich im 3D-Raum nicht bewegen kann. Solch ein Bewegen im 3D-Raum ist nicht schwer zu
realisieren, wenn die Grundlagen beachtet werden mit denen Direct3D arbeitet.
|
Alles hängt von der Kamera (ViewPort) ab. Hierbei ist es wichtig zu wissen, dass die Kamera aus zwei Positionen im 3D Raum
besteht, genauer gesagt, aus zwei Vektoren. Der erste Vektor beschreibt die Position (Eye Point) der Kamera im 3D-Raum und
der zweite Vektor das Ziel (LookAt) der Kamera im 3D-Raum. Den Abstand zwischen den beiden Vektoren könnte man als Sichtweite
bezeichnen.
|
Würde man nur die Position (Start-Vektor) der Kamera verändern aber nicht das Ziel, dann würde die Kamera, egal wo sie sich im 3D-Raum
gerade befindet, immer auf das gleiche Ziel (End-Vektor) blicken. Und das wäre in einem Spiel nicht gerade der erwünschte Effekt.
In den Spielen ist es meist so, ich schaue wohin ich gehe, oder andersrum, ich gehe wohin ich schaue.
Um das in einem 3D-Spiel zu realisieren, braucht man einen Blick-Winkel. Also einen Winkel der festlegt, wohin der Spieler im
3D-Raum schaut.
|
Mit der Position des Spielers (= Kamera), dem Blickwinkel und der Sichtweite, kann die Ausrichtung der Kamera (= die
Zielposition der Kamera) berechnet werden. Hierfür gibt es zwei Möglichkeiten. Es werden Start- und Ziel-Position der Kamera
berechnet und die Kamera (ViewPort) neu gesetzt. Oder wir verwenden die Matrizen-Funktonen.
|
Der Tipp zeigt wie die Kamera (ViewPort) im 3D-Raum unter Verwendung der Matrizen-Funktionen bewegt werden kann. Hierbei
muss der Blick-Punkt der Spielers nicht manuell errechnet werden.
|
In Direct3D wird der ViewPort (Kamera) über eine Matrix definiert. Eine Matrix kann man verschieben (translate) und um die
X-, Y-, Z-Achse rotieren (rotate) lassen. Wenn dann die Matrix als neuer ViewPort (Kamera) an Direct3D übergeben wird,
wird der Blick-punkt automatisch neu berechnet.
|
Wie sieht das nun also aus?
|
|
1. |
Beim Erstellen vom Direct3D wird der ViewPort (Kamera) auf einen Startpunkt und Zielpunkt gesetzt, dabei wird dem Direct3D gleich die gewünschte Sichtweite mitgeteilt. |
2. |
Der ViewPort (Kamera) wird an die gewünschte Position geschoben (translate), da es ja ziemlich unsinnig ist, wenn der Spieler außerhalb vom Level beginnt. |
|
Im Spiel selbst benötigen wir drei Hilfsmatrizen, mit denen die Bewegungen in der ViewPort-Matrix durchgeführt werden:
|
|
1. |
Dreht sich der Spieler, so wird die neue Blickrichtung (Blickwinkel) und Laufrichtung errechnet. |
2. |
Bewegt sich der Spieler nun vor-, rück- oder seitwärts, so wird die Matrix auf Grund der Laufrichtung verschoben. |
3. |
Die Matrix wird mit dem neuen Blickwinkel um die Y-Achse gedreht. |
4. |
Schaut der Spieler rauf oder runter, wird die Matrix um die X-Achse entsprechend gedreht. |
5. |
Damit alle Veränderungen zusammengeführt werden, müssen die Hilfsmatrizen miteinander multipliziert werden. |
6. |
Das Ergebnis wird dem Direct3D als neue ViewPort-Matrix übergeben. |
|
|
|
'--- Im Erstellungs-Bereich vom Direct3D ---
'ViewportMatrix einstellen
'Dieser wird definiert durch einen Ausgangspunkt (auch
'Eye Point genannt), einer Orientierung (auch LookAt genannt)
'und der Angabe wo "oben" ist (Standard ist Y, die Achse, die
'"oben" ist).
D3DXMatrixIdentity View3DMatrix
D3DXMatrixLookAtLH View3DMatrix, vec3(0, 0, 0), _
vec3(0, 0, 1000), vec3(0, 1, 0)
gD3DDevice8.SetTransform D3DTS_VIEW, View3DMatrix
'Neuen Ursprung der Viewport-Matrix einstellen
gD3DDevice8.GetTransform D3DTS_VIEW, View3DMatrix
TranslateMatrix View3DMatrix, _
vec3(PLAYER.X * -1, PLAYER.Y * -1, PLAYER.Z * -1)
gD3DDevice8.SetTransform D3DTS_VIEW, View3DMatrix
'--- Game-Loop ---
Do
PLAYER.TurnHor = 0#
PLAYER.TurnVer = 0#
PLAYER.Move = MOVE_NONE
'Prüfen auf Anwender-Eingabe
DIModule.CheckInput
DIModule.CheckMouse
With PLAYER
'y-Achse rotieren
If .TurnHor <> 0 Then
.AngleY = .AngleY + (.TurnHor / 5)
.Move = .Move Or MOVE_TURN
If .AngleY < 0 Then
.AngleY = 360 + .AngleY
ElseIf .AngleY > 360 Then
.AngleY = .AngleY - 360
End If
End If
'x-Achse rotieren
If .TurnVer <> 0 Then
.AngleX = .AngleX + (.TurnVer / 10)
If .AngleX > 50 Then .AngleX = 50
If .AngleX < -50 Then .AngleX = -50
.Move = .Move Or MOVE_TURN
End If
End With
'Hat sich der Spieler überhaupt bewegt?
If PLAYER.Move <> MOVE_NONE Then
'neue Spielerposition berechnen
CalculateViewStartPos
'Matrix-Ursprung auf Spielerposition setzen
TranslateMatrix myTranslateMatrix, _
vec3(PLAYER.X * -1, PLAYER.Y * -1, PLAYER.Z * -1)
'Matrix Y-Rotation
RotateYMatrix myYMatrix, PLAYER.AngleY * PI / 180
'Matrix X-Rotation
RotateXMatrix myXMatrix, PLAYER.AngleX * PI / 180
'Matrizen zusammenführen
myNewMatrix = RetMatrixMult(myTranslateMatrix, myYMatrix)
View3DMatrix = RetMatrixMult(myNewMatrix, myXMatrix)
'Transformation der ViewPortMatrix durchführen
gD3DDevice8.SetTransform D3DTS_VIEW, View3DMatrix
End If
'3D Szene rendern
Render3D
DoEvents
Loop While running
'--- Berechnungen ---
'Position des Spielers berechnen
Private Sub CalculateViewStartPos()
Dim px As Single
Dim pz As Single
If (PLAYER.Move And MOVE_FORE) = MOVE_FORE Then
px = Sin((PLAYER.AngleY * (PI / 180)))
pz = Cos((PLAYER.AngleY * (PI / 180)))
PLAYER.X = PLAYER.X + px
PLAYER.Z = PLAYER.Z + pz
End If
If (PLAYER.Move And MOVE_BACK) = MOVE_BACK Then
px = -Sin((PLAYER.AngleY * (PI / 180)))
pz = -Cos((PLAYER.AngleY * (PI / 180)))
PLAYER.X = PLAYER.X + px
PLAYER.Z = PLAYER.Z + pz
End If
If (PLAYER.Move And MOVE_LEFT) = MOVE_LEFT Then
px = Sin((PLAYER.AngleY * (PI / 180)))
pz = -Cos((PLAYER.AngleY * (PI / 180)))
PLAYER.X = PLAYER.X - pz * -1
PLAYER.Z = PLAYER.Z - px * -1
End If
If (PLAYER.Move And MOVE_RIGHT) = MOVE_RIGHT Then
px = Sin((PLAYER.AngleY * (PI / 180)))
pz = -Cos((PLAYER.AngleY * (PI / 180)))
PLAYER.X = PLAYER.X + pz * -1
PLAYER.Z = PLAYER.Z + px * -1
End If
End Sub
Public Sub TranslateMatrix(m As D3DMATRIX, v As D3DVECTOR)
m.m41 = v.X
m.m42 = v.Y
m.m43 = v.Z
End Sub
Public Function RetMatrixMult(a As D3DMATRIX, b As D3DMATRIX) _
As D3DMATRIX
Dim ret As D3DMATRIX
ret.m11 = b.m11 * a.m11 + b.m21 * a.m12 + b.m31 * a.m13 + _
b.m41 * a.m14
ret.m12 = b.m12 * a.m11 + b.m22 * a.m12 + b.m32 * a.m13 + _
b.m42 * a.m14
ret.m13 = b.m13 * a.m11 + b.m23 * a.m12 + b.m33 * a.m13 + _
b.m43 * a.m14
ret.m14 = b.m14 * a.m11 + b.m24 * a.m12 + b.m34 * a.m13 + _
b.m44 * a.m14
ret.m21 = b.m11 * a.m21 + b.m21 * a.m22 + b.m31 * a.m23 + _
b.m41 * a.m24
ret.m22 = b.m12 * a.m21 + b.m22 * a.m22 + b.m32 * a.m23 + _
b.m42 * a.m24
ret.m23 = b.m13 * a.m21 + b.m23 * a.m22 + b.m33 * a.m23 + _
b.m43 * a.m24
ret.m24 = b.m14 * a.m21 + b.m24 * a.m22 + b.m34 * a.m23 + _
b.m44 * a.m24
ret.m31 = b.m11 * a.m31 + b.m21 * a.m32 + b.m31 * a.m33 + _
b.m41 * a.m34
ret.m32 = b.m12 * a.m31 + b.m22 * a.m32 + b.m32 * a.m33 + _
b.m42 * a.m34
ret.m33 = b.m13 * a.m31 + b.m23 * a.m32 + b.m33 * a.m33 + _
b.m43 * a.m34
ret.m34 = b.m14 * a.m31 + b.m24 * a.m32 + b.m34 * a.m33 + _
b.m44 * a.m34
ret.m41 = b.m11 * a.m41 + b.m21 * a.m42 + b.m31 * a.m43 + _
b.m41 * a.m44
ret.m42 = b.m12 * a.m41 + b.m22 * a.m42 + b.m32 * a.m43 + _
b.m42 * a.m44
ret.m43 = b.m13 * a.m41 + b.m23 * a.m42 + b.m33 * a.m43 + _
b.m43 * a.m44
ret.m44 = b.m14 * a.m41 + b.m24 * a.m42 + b.m34 * a.m43 + _
b.m44 * a.m44
RetMatrixMult = ret
End Function
Public Sub RotateYMatrix(ByRef ret As D3DMATRIX, _
ByVal rads As Single)
Dim cosine As Single
Dim sine As Single
cosine = Cos(rads)
sine = Sin(rads)
ret.m11 = cosine
ret.m33 = cosine
ret.m13 = sine
ret.m31 = -sine
End Sub
Public Sub RotateXMatrix(ByRef ret As D3DMATRIX, _
ByVal rads As Single)
Dim cosine As Single
Dim sine As Single
cosine = Cos(rads)
sine = Sin(rads)
ret.m22 = cosine
ret.m33 = cosine
ret.m23 = -sine
ret.m32 = sine
End Sub
'Hilfsfunktion - einen D3DVektor erzeugen
Public Function vec3(X As Single, Y As Single, Z As Single) _
As D3DVECTOR
vec3.X = X
vec3.Y = Y
vec3.Z = Z
End Function
|
|
|
|
Um dieses Beispiel ausführen zu können, wird die DirectX 8 for Visual Basic Type Library
benötigt (siehe dazu die Erläuterungen in der DirectX-Rubrik).
|
|
Windows-Version |
95 |
|
|
98 |
|
|
ME |
|
|
NT |
|
|
2000 |
|
|
XP |
|
|
Vista |
|
|
Win
7 |
|
|
|
VB-Version |
VBA 5 |
|
|
VBA 6 |
|
|
VB 4/16 |
|
|
VB 4/32 |
|
|
VB 5 |
|
|
VB 6 |
|
|
|
|
Download (297
kB)
|
Downloads bisher: [ 835 ]
|
|
|