Formeln: Unterschied zwischen den Versionen

Aus Das Sopra Wiki
Florian (Diskussion | Beiträge)
Keine Bearbeitungszusammenfassung
Wernerj (Diskussion | Beiträge)
K entfernung toter link
 
(10 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
{{Stub}}
{{Stub}}
__FORCETOC__


Dieser Artikel enthält ähnlich einer Formelsammlung nützliche Berechnungen zur Spieleprogrammierung.
Dieser Artikel enthält ähnlich einer Formelsammlung nützliche Berechnungen zur Spieleprogrammierung.
Zeile 5: Zeile 7:
== Drehung zu einem Ziel im 2D Fall ==
== Drehung zu einem Ziel im 2D Fall ==


Im folgenden wird erklärt wie man ein Objekt im zweidimensionalen Fall, also auf einer Ebene, zu einem Ziel drehen kann. Die Vorraussetzungen die man hierzu benötigt sind der Positionsvektor des Objekts (<math>\vec o_p \!\,</math>), der Forwardvektor des Objekts (<math>\vec o_f \!\,</math>) welcher angibt in welche Richtung es gerade gedreht ist und der Positionsvektor des Zielpunkts (<math>\vec t_p \!\,</math>) zu welchem sich das Objekt drehen soll. Gehen wir im weiteren davon aus dass sich das Objekt auf der X-Z-Ebene bewegt, um es zum Zielpunkt zu drehen müssen wir es also um seine eigene Y-Achse drehen. Für andere Ebenen funktioniert das ganze analog, es muss nur entsprechend immer um die zur Ebene orthogonale Achse gedreht werden.
Im folgenden wird erklärt wie man ein Objekt im zweidimensionalen Fall, also auf einer Ebene, zu einem Ziel drehen kann. Die Vorraussetzungen die man hierzu benötigt sind der Positionsvektor des Objekts (<math>\vec o_p \!\,</math>), der Forwardvektor des Objekts (<math>\vec o_f \!\,</math>) welcher angibt in welche Richtung es gerade gedreht ist und der Positionsvektor des Zielpunkts (<math>\vec t_p \!\,</math>) zu welchem sich das Objekt drehen soll. Gehen wir im weiteren davon aus dass sich das Objekt auf der X-Z-Ebene bewegt, um es zum Zielpunkt zu drehen müssen wir es also um seine eigene Y-Achse drehen.
 
Als erstes projiziert man den Forwardvektor des Objekts auf die X-Z-Ebene (indem man den Y-Wert auf 0 setzt) und normalisiert den Vektor um die Berechnung des Winkels später zu vereinfachen:
 
<math>\vec o_f.y = 0 \!\,</math> <br/>
<math>\vec o_f.normalize() \!\,</math>


Als erstes berechnet man nun den X- und Z-Wert des Richtungsvektors vom Objekt zum Zielpunkt (<math>\vec d_{ot}\!\,</math>). Der Y-Wert wird auf 0 gesetzt weil wir den Winkel in der X-Z-Ebene ausrechnen wollen. Zusätzlich wird der Vektor noch normalisiert um die Berechnung des Winkels später zu vereinfachen:
Dann berechnet man den Richtungsvektors vom Objekt zum Zielpunkt (<math>\vec d_{ot}\!\,</math>). Der Y-Wert wird auf 0 gesetzt um auch diesen auf die X-Z-Ebene zu projizieren. Zusätzlich wird der Vektor ebenfalls normalisiert:


<math>\vec d_{ot} = \vec t_p - \vec o_p \!\,</math> <br/>
<math>\vec d_{ot} = \vec t_p - \vec o_p \!\,</math> <br/>
Zeile 13: Zeile 20:
<math>\vec d_{ot}.normalize() \!\,</math>
<math>\vec d_{ot}.normalize() \!\,</math>


Dann projiziert man den Forwardvektor des Objekts ebenfalls auf die X-Z-Ebene (indem man den Y-Wert auf 0 setzt) und normalisiert den Vektor:
Das Skalarprodukt des Forwardvektors und des Richtungsvektors zum Zielpunkt liefert nun den Arkuscosinus des Winkels um den das Objekt zum Zielpunkt auf der Y-Achse gedreht ist:
 
<math>\vec o_f.y = 0 \!\,</math> <br/>
<math>\vec o_f.normalize() \!\,</math>


Das Skalarprodukt des Forwardvektors und des Richtungsvektors zum Zielpunkt liefert nun den Arkuscosinus des Winkels um den das Objekt zum Zielpunkt auf der Y-Achse gedreht ist:
<math>\measuredangle\left(Y-Achse\right) = \measuredangle\left(\vec o_f, \vec d_{ot}\right) = \arccos\left(\vec o_f \cdot \vec d_{ot}\right) \!\,</math>


<math>\measuredangle\left(\vec o_f, \vec d_{ot}\right) = \arccos (\vec o_f \cdot \vec d_{ot}) \!\,</math>
:'''Achtung:''' Durch Rundungsfehler in der Gleitkommaberechnung kann es vorkommen dass das Skalarprodukt der Vektoren etwas kleiner wie -1 bzw größer wie 1 wird. Der Arkuscosinus ist allerdings nur für das Intervall [-1;1] definiert! Man muss also z.B. durch einen Aufruf von MathHelper.Clamp(...) sicherstellen dass das Skalarprodukt innerhalb dieses Intervalls liegt!


Jetzt muss man nur noch bestimmen ob man das Objekt um diesen Winkel nach links oder rechts drehen muss um es zum Ziel hin auszurichten. Dies lässt sich nun leicht anhand des Y-Werts des Kreuzprodukts der beiden Winkel bestimmen. Da beide Vektoren auf der X-Z-Ebene liegen, liegt der Vektor des Kreuzprodukts auf der Y-Achse, da dieser orthogonal zu den anderen Vektoren ist. Das Vorzeichen des Y-Werts des Kreuzprodukts gibt daher an ob man nach links oder rechts drehen muss:
Jetzt muss man nur noch bestimmen ob man das Objekt um diesen Winkel nach links oder rechts drehen muss um es zum Ziel hin auszurichten. Dies lässt sich nun leicht anhand des Y-Werts des Kreuzprodukts der beiden Winkel bestimmen. Da beide Vektoren auf der X-Z-Ebene liegen, liegt der Vektor des Kreuzprodukts auf der Y-Achse, da dieser orthogonal zu den anderen Vektoren ist. Das Vorzeichen des Y-Werts des Kreuzprodukts gibt daher an ob man nach links oder rechts drehen muss:
Zeile 28: Zeile 32:
Wenn crossY > 0 ist dann muss man nach links drehen, ansonsten nach rechts. (Dies kann man mit der Rechte-Hand-Regel bestimmen.)
Wenn crossY > 0 ist dann muss man nach links drehen, ansonsten nach rechts. (Dies kann man mit der Rechte-Hand-Regel bestimmen.)


[[Kategorie:Mathematik]]
== Drehung zu einem beliebigen Punkt im 3D Raum ==
 
Durch eine Drehung von -180° bis +180° um seine Y-Achse und eine Drehung von -90° bis +90° um seine X-Achse kann ein Objekt zu jedem beliebigen Punkt im 3D Raum ausgerichtet werden. Eine Drehung um die Z-Achse bewirkt lediglich ein seitliches rollen. Um ein Objekt also auf einen beliebigen Punkt zu drehen muss man lediglich die Winkel um die X- und Y-Achse relativ zum Zielpunkt berechnen und das Objekt dann um diese drehen. Benötigt werden hierzu wieder der Positionsvektor des Objekts (<math>\vec o_p \!\,</math>), der Forwardvektor des Objekts (<math>\vec o_f \!\,</math>) welcher angibt in welche Richtung es gerade gedreht ist und der Positionsvektor des Zielpunkts (<math>\vec t_p \!\,</math>) zu welchem sich das Objekt drehen soll.
 
Als erstes berechnet man den Richtungsvektor vom Objekt zum Zielpunkt (<math>\vec d_{ot}\!\,</math>) durch einfaches subtrahieren und anschließendes normalisieren:
 
<math>\vec d_{ot} = \vec t_p - \vec o_p \!\,</math> <br/>
<math>\vec d_{ot}.normalize() \!\,</math>
 
Die Berechnung des Winkels um die Y-Achse geht dann analog zum 2D Fall durch das projizieren des Forwardvektors des Objekts und des Richtungsvektors vom Objekt zum Zielpunkt auf die X-Z-Ebene und das anschließende Berechnen des Winkels zwischen diesen beiden Vektoren. Hinzu kommt nun also lediglich die Berechnung des Winkels um den um die X-Achse gedreht werden muss. Diesen Winkel kann man berechnen indem man den Richtungsvektor vom Objekt zum Zielpunkt in die Ebene die vom Forwardvektor des Objekts aufgespannt wird projiziert (<math>\vec d_f \!\,</math>) und dann den Winkel zwischen diesen beiden Vektoren bestimmt. Dazu berechnet man den Y-Wert des Vektors der vom Forwardvektor des Objekts zum Richtungsvektor vom Objekt zum Zielpunkt geht und addiert diesen zum Y-Wert des Forwardvektors:
 
<math>tempY = \vec d_{ot}.y - \vec o_f.y \!\,</math> <br/>
<math>\vec d_f = \vec o_f \!\,</math> <br/>
<math>\vec d_f.y = \vec d_f.y + tempY \!\,</math> <br/>
<math>\vec d_f.normalize() \!\,</math> <br/>
 
Der gesuchte Winkel ist dann der Arkuscosinus des Skalarprodukts des Forwardvektors des Objekts und des in die selbe Ebene projizierten Richtungsvektors vom Objekt zum Zielpunkt:
 
<math>\measuredangle\left(X-Achse\right) = \measuredangle\left(\vec o_f, \vec d_f\right) = \arccos\left(\vec o_f \cdot \vec d_f\right) \!\,</math>
 
:'''Achtung:''' Beim Arkuscosinus des Skalarprodukts muss hier die Bereichsprüfung genauso beachtet werden wie oben!
 
Ob man um diesen Winkel um die X-Achse nach oben oder unten drehen muss ist kann man dann ganz einfach anhand des temporär berechneten Y-Werts bestimmen, wenn tempY > 0 dann dreht man nach oben, andernfalls nach unten.
 
 
[[Kategorie:Mathematik]][[Kategorie:Tutorials]][[Kategorie: Begriffe]]
[[Kategorie:MS01]]
[[Kategorie:MS02]]
[[Kategorie:MS03]]
[[Kategorie:MS04]]
[[Kategorie:MS05]]

Aktuelle Version vom 17. Oktober 2019, 18:56 Uhr




Dieser Artikel enthält ähnlich einer Formelsammlung nützliche Berechnungen zur Spieleprogrammierung.

Drehung zu einem Ziel im 2D Fall

Im folgenden wird erklärt wie man ein Objekt im zweidimensionalen Fall, also auf einer Ebene, zu einem Ziel drehen kann. Die Vorraussetzungen die man hierzu benötigt sind der Positionsvektor des Objekts (<math>\vec o_p \!\,</math>), der Forwardvektor des Objekts (<math>\vec o_f \!\,</math>) welcher angibt in welche Richtung es gerade gedreht ist und der Positionsvektor des Zielpunkts (<math>\vec t_p \!\,</math>) zu welchem sich das Objekt drehen soll. Gehen wir im weiteren davon aus dass sich das Objekt auf der X-Z-Ebene bewegt, um es zum Zielpunkt zu drehen müssen wir es also um seine eigene Y-Achse drehen.

Als erstes projiziert man den Forwardvektor des Objekts auf die X-Z-Ebene (indem man den Y-Wert auf 0 setzt) und normalisiert den Vektor um die Berechnung des Winkels später zu vereinfachen:

<math>\vec o_f.y = 0 \!\,</math>
<math>\vec o_f.normalize() \!\,</math>

Dann berechnet man den Richtungsvektors vom Objekt zum Zielpunkt (<math>\vec d_{ot}\!\,</math>). Der Y-Wert wird auf 0 gesetzt um auch diesen auf die X-Z-Ebene zu projizieren. Zusätzlich wird der Vektor ebenfalls normalisiert:

<math>\vec d_{ot} = \vec t_p - \vec o_p \!\,</math>
<math>\vec d_{ot}.y = 0 \!\,</math>
<math>\vec d_{ot}.normalize() \!\,</math>

Das Skalarprodukt des Forwardvektors und des Richtungsvektors zum Zielpunkt liefert nun den Arkuscosinus des Winkels um den das Objekt zum Zielpunkt auf der Y-Achse gedreht ist:

<math>\measuredangle\left(Y-Achse\right) = \measuredangle\left(\vec o_f, \vec d_{ot}\right) = \arccos\left(\vec o_f \cdot \vec d_{ot}\right) \!\,</math>

Achtung: Durch Rundungsfehler in der Gleitkommaberechnung kann es vorkommen dass das Skalarprodukt der Vektoren etwas kleiner wie -1 bzw größer wie 1 wird. Der Arkuscosinus ist allerdings nur für das Intervall [-1;1] definiert! Man muss also z.B. durch einen Aufruf von MathHelper.Clamp(...) sicherstellen dass das Skalarprodukt innerhalb dieses Intervalls liegt!

Jetzt muss man nur noch bestimmen ob man das Objekt um diesen Winkel nach links oder rechts drehen muss um es zum Ziel hin auszurichten. Dies lässt sich nun leicht anhand des Y-Werts des Kreuzprodukts der beiden Winkel bestimmen. Da beide Vektoren auf der X-Z-Ebene liegen, liegt der Vektor des Kreuzprodukts auf der Y-Achse, da dieser orthogonal zu den anderen Vektoren ist. Das Vorzeichen des Y-Werts des Kreuzprodukts gibt daher an ob man nach links oder rechts drehen muss:

<math>crossY = \vec o_f.z \cdot \vec d_{ot}.x - \vec o_f.x \cdot \vec d_{ot}.z \!\,</math>

Wenn crossY > 0 ist dann muss man nach links drehen, ansonsten nach rechts. (Dies kann man mit der Rechte-Hand-Regel bestimmen.)

Drehung zu einem beliebigen Punkt im 3D Raum

Durch eine Drehung von -180° bis +180° um seine Y-Achse und eine Drehung von -90° bis +90° um seine X-Achse kann ein Objekt zu jedem beliebigen Punkt im 3D Raum ausgerichtet werden. Eine Drehung um die Z-Achse bewirkt lediglich ein seitliches rollen. Um ein Objekt also auf einen beliebigen Punkt zu drehen muss man lediglich die Winkel um die X- und Y-Achse relativ zum Zielpunkt berechnen und das Objekt dann um diese drehen. Benötigt werden hierzu wieder der Positionsvektor des Objekts (<math>\vec o_p \!\,</math>), der Forwardvektor des Objekts (<math>\vec o_f \!\,</math>) welcher angibt in welche Richtung es gerade gedreht ist und der Positionsvektor des Zielpunkts (<math>\vec t_p \!\,</math>) zu welchem sich das Objekt drehen soll.

Als erstes berechnet man den Richtungsvektor vom Objekt zum Zielpunkt (<math>\vec d_{ot}\!\,</math>) durch einfaches subtrahieren und anschließendes normalisieren:

<math>\vec d_{ot} = \vec t_p - \vec o_p \!\,</math>
<math>\vec d_{ot}.normalize() \!\,</math>

Die Berechnung des Winkels um die Y-Achse geht dann analog zum 2D Fall durch das projizieren des Forwardvektors des Objekts und des Richtungsvektors vom Objekt zum Zielpunkt auf die X-Z-Ebene und das anschließende Berechnen des Winkels zwischen diesen beiden Vektoren. Hinzu kommt nun also lediglich die Berechnung des Winkels um den um die X-Achse gedreht werden muss. Diesen Winkel kann man berechnen indem man den Richtungsvektor vom Objekt zum Zielpunkt in die Ebene die vom Forwardvektor des Objekts aufgespannt wird projiziert (<math>\vec d_f \!\,</math>) und dann den Winkel zwischen diesen beiden Vektoren bestimmt. Dazu berechnet man den Y-Wert des Vektors der vom Forwardvektor des Objekts zum Richtungsvektor vom Objekt zum Zielpunkt geht und addiert diesen zum Y-Wert des Forwardvektors:

<math>tempY = \vec d_{ot}.y - \vec o_f.y \!\,</math>
<math>\vec d_f = \vec o_f \!\,</math>
<math>\vec d_f.y = \vec d_f.y + tempY \!\,</math>
<math>\vec d_f.normalize() \!\,</math>

Der gesuchte Winkel ist dann der Arkuscosinus des Skalarprodukts des Forwardvektors des Objekts und des in die selbe Ebene projizierten Richtungsvektors vom Objekt zum Zielpunkt:

<math>\measuredangle\left(X-Achse\right) = \measuredangle\left(\vec o_f, \vec d_f\right) = \arccos\left(\vec o_f \cdot \vec d_f\right) \!\,</math>

Achtung: Beim Arkuscosinus des Skalarprodukts muss hier die Bereichsprüfung genauso beachtet werden wie oben!

Ob man um diesen Winkel um die X-Achse nach oben oder unten drehen muss ist kann man dann ganz einfach anhand des temporär berechneten Y-Werts bestimmen, wenn tempY > 0 dann dreht man nach oben, andernfalls nach unten.