Tipp 0348
|
Direct3D - Bewegen im 3D-Raum
|
 |
|
Autor/Einsender: Datum: |
|
Alexander Csadek 25.07.2003 |
|
Entwicklungsumgebung:
DirectX-Version: |
|
VB 6
DirectX 7 |
|
|
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 der Kamera im 3D-Raum und der zweite Vektor das Ziel 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 im 3D-Raum sie sich 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 schau wohin ich
geh, oder andersrum, ich geh wohin ich schau. Um das in einem 3D-Spiel zu realisieren, braucht man einen
Blickwinkel, 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 Zielposition der Kamera berechnet und die Kamera (= ViewPort) neu gesetzt, oder wir verwenden die Matrizen-Funktionen.
|
Der Tipp zeigt wie die Kamera (ViewPort) im 3D-Raum unter Verwendung der Matrizen-Funktionen bewegt werden kann. Hierbei muss der Blickpunkt des 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.
Wird dann die Matrix als neuer ViewPort an Direct3D übergeben, wird der Blickpunkt 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.
|
Es folgen nun die wichtigsten Code-Bereiche...
|
|
Code im Direct3D Erstellungs-Bereich |
|
|
'ViewportMatrix einstellen
With DX7
.IdentityMatrix View3DMatrix
.ViewMatrix View3DMatrix, RVector(0, 0, 0), _
RVector(0, 0, 1000), RVector(0, 1, 0), 0
End With
Device.SetTransform D3DTRANSFORMSTATE_VIEW, View3DMatrix
'neuen Ursprung der ViewportMatrix einstellen
Device.GetTransform D3DTRANSFORMSTATE_VIEW, View3DMatrix
TranslateMatrix View3DMatrix, RVector( _
PLAYER.x * -1, PLAYER.y * -1, PLAYER.z * -1)
Device.SetTransform D3DTRANSFORMSTATE_VIEW, View3DMatrix
|
|
|
|
|
Do
PLAYER.TurnHor = 0#
PLAYER.TurnVer = 0#
PLAYER.Move = MOVE_NONE
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, RVector( _
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
Device.SetTransform D3DTRANSFORMSTATE_VIEW, View3DMatrix
End If
'Szene rendern
Render3D
BackBuffer.BltFast 394, 294, bmpCross, recCross, _
DDBLTFAST_WAIT Or DDBLTFAST_SRCCOLORKEY
PrimarySurface.Flip BackBuffer, DDFLIP_WAIT
DoEvents
Loop While Running
|
|
|
|
|
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))) / 2
pz = Cos((PLAYER.AngleY * (PI / 180))) / 2
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))) / 2
pz = -Cos((PLAYER.AngleY * (PI / 180))) / 2
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))) / 2
pz = -Cos((PLAYER.AngleY * (PI / 180))) / 2
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))) / 2
pz = -Cos((PLAYER.AngleY * (PI / 180))) / 2
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.rc41 = v.x
m.rc42 = v.y
m.rc43 = v.z
End Sub
Public Function RetMatrixMult(a As D3DMATRIX, b As D3DMATRIX) _
As D3DMATRIX
Dim ret As D3DMATRIX
ret.rc11 = b.rc11 * a.rc11 + b.rc21 * a.rc12 + _
b.rc31 * a.rc13 + b.rc41 * a.rc14
ret.rc12 = b.rc12 * a.rc11 + b.rc22 * a.rc12 + _
b.rc32 * a.rc13 + b.rc42 * a.rc14
ret.rc13 = b.rc13 * a.rc11 + b.rc23 * a.rc12 + _
b.rc33 * a.rc13 + b.rc43 * a.rc14
ret.rc14 = b.rc14 * a.rc11 + b.rc24 * a.rc12 + _
b.rc34 * a.rc13 + b.rc44 * a.rc14
ret.rc21 = b.rc11 * a.rc21 + b.rc21 * a.rc22 + _
b.rc31 * a.rc23 + b.rc41 * a.rc24
ret.rc22 = b.rc12 * a.rc21 + b.rc22 * a.rc22 + _
b.rc32 * a.rc23 + b.rc42 * a.rc24
ret.rc23 = b.rc13 * a.rc21 + b.rc23 * a.rc22 + _
b.rc33 * a.rc23 + b.rc43 * a.rc24
ret.rc24 = b.rc14 * a.rc21 + b.rc24 * a.rc22 + _
b.rc34 * a.rc23 + b.rc44 * a.rc24
ret.rc31 = b.rc11 * a.rc31 + b.rc21 * a.rc32 + _
b.rc31 * a.rc33 + b.rc41 * a.rc34
ret.rc32 = b.rc12 * a.rc31 + b.rc22 * a.rc32 + _
b.rc32 * a.rc33 + b.rc42 * a.rc34
ret.rc33 = b.rc13 * a.rc31 + b.rc23 * a.rc32 + _
b.rc33 * a.rc33 + b.rc43 * a.rc34
ret.rc34 = b.rc14 * a.rc31 + b.rc24 * a.rc32 + _
b.rc34 * a.rc33 + b.rc44 * a.rc34
ret.rc41 = b.rc11 * a.rc41 + b.rc21 * a.rc42 + _
b.rc31 * a.rc43 + b.rc41 * a.rc44
ret.rc42 = b.rc12 * a.rc41 + b.rc22 * a.rc42 + _
b.rc32 * a.rc43 + b.rc42 * a.rc44
ret.rc43 = b.rc13 * a.rc41 + b.rc23 * a.rc42 + _
b.rc33 * a.rc43 + b.rc43 * a.rc44
ret.rc44 = b.rc14 * a.rc41 + b.rc24 * a.rc42 + _
b.rc34 * a.rc43 + b.rc44 * a.rc44
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.rc11 = cosine
ret.rc33 = cosine
ret.rc13 = sine
ret.rc31 = -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.rc22 = cosine
ret.rc33 = cosine
ret.rc23 = -sine
ret.rc32 = sine
End Sub
Public Function RVector(ByVal x As Single, ByVal y As Single, _
ByVal z As Single) As D3DVECTOR
Dim v As D3DVECTOR
v.x = x
v.y = y
v.z = z
RVector = v
End Function
|
|
|
|
|
|
Um dieses Beispiel ausführen zu können, wird die DirectX 7
for Visual Basic Type Library
benötigt (siehe dazu die Erläuterungen in der DirectX-Rubrik).
|
|
Windows-Version |
95 |
 |
|
98/SE |
 |
|
ME |
 |
|
NT |
 |
|
2000 |
 |
|
XP |
 |
|
Vista |
 |
|
Win
7 |
 |
|
|
VB-Version |
VBA 5 |
 |
|
VBA 6 |
 |
|
VB 4/16 |
 |
|
VB 4/32 |
 |
|
VB 5 |
 |
|
VB 6 |
 |
|
|
|
Download (257
kB)
|
Downloads bisher: [ 3009
]
|
|
|