3D-Programmierung (Mathematik) Teil 03: Polarkoordinaten

Folgendes Problem gilt es zu lösen – bitte geben sie Lage der Stadt Berlin auf der Erdkugel an. Würde man mit kartesischen Koordinaten arbeiten, würde man den Ursprung des Koordinatensystems ins Zentrum der Erde legen und dann dem Ortsvektor von Berlin die gesuchten x-, y- und z-Koordinaten zuweisen. Nun gut, niemand ginge auf diese Weise vor, stattdessen würde man auf einem Globus oder einer Weltkarte nach dem korrekten Längen- und Breitengrad suchen. Zur Information, die Breitengrade liegen parallel zum Äquator und die Längengrade verlaufen senkrecht dazu von Pol zu Pol. Zweites Problem – man beschreibe die Bewegung der Erde um die Sonne und nehme hierfür zur Vereinfachung eine nahezu kreisförmige Bewegung an.


















Veranschaulicht man sich das Problem graphisch, so fällt auf, dass sich bei der Bewegung eigentlich nur der Winkel (Drehwinkel) zwischen dem Ortsvektor und der x-Achse ändert. Die Länge des Ortsvektors (sein Betrag) dagegen bleibt konstant. Was liegt also näher, als die Umlaufbahn der Erde als Funktion ihres Drehwinkels zu beschreiben. Man spricht in diesem Zusammenhang von einer zweidimensionalen Polarkoordinatendarstellung.

 
Polarkoordinaten können natürlich auch für den dreidimensionalen Raum definiert werden. Ihre Verwendung bietet sich, wie im ersten Beispiel beschrieben, bei der Positionsangabe von Städten auf einer Weltkarte an oder bei der Positionierung von Hintergrundnebeln und Galaxien in einem Weltraumspiel. Die nachfolgende Abbildung veranschaulicht eine mögliche Definition der dreidimensionalen Polarkoordinatendarstellung:
 

Hier nun der Zusammenhang zwischen den Polarwinkeln und den kartesischen Koordinaten:

 
Hinweis:
Setzt man jetzt für den Vertikalwinkel 90° ein, zeigt der Ortsvektor immer in die positive y-Richtung.
Ist der Vertikalwinkel gleich 0° und der Horizontalwinkel gleich 90°, zeigt der Ortsvektor in die positive x-Richtung.
Ist der Vertikalwinkel gleich 0° und der Horizontalwinkel gleich 180°, zeigt der Ortsvektor in die negative z-Richtung.

In der täglichen Programmierpraxis ergibt sich oftmals das Problem, dass für einen gegebenen Richtungsvektor (Einheitsvektor) die zugehörigen Polarwinkel berechnet werden müssen. Ein Beispiel hierfür wäre eine Explosion. Man kennt die Bewegungsrichtung der einzelnen Trümmerteile und benötigt für die effektvolle Darstellung von Rauch- und Brandspuren (Billboards) die zugehörigen Polarwinkel. Im Weltraum-Echtzeitstrategiespiel „Haegemonia“ wurde dies sehr eindrucksvoll umgesetzt.

Die nachfolgende CalculatePolarCoordinates()-Funktion berechnet nun nicht nur die einzelnen Polarwinkel, sondern liefert dem Programmierer darüber hinaus auch die zugehörigen Sinus- und Kosinuswerte.

inline void CalculatePolarCoordinates(D3DXVECTOR3* pDirection,

                                      float &DirectionVerticalAngle,
                                      float &DirectionSinVerticalAngle,
                                      float &DirectionCosVerticalAngle,

                                      float &DirectionHorizontalAngle,
                                      float &DirectionSinHorizontalAngle,
                                      float &DirectionCosHorizontalAngle)
{
    // Berechnung der Polarkoordinatenwinkel:
    DirectionSinVerticalAngle = pDirection->y;

    if(fabs(DirectionSinVerticalAngle) > 0.999f) // 90°
    {
        DirectionCosVerticalAngle   = 0.0f;
        DirectionCosHorizontalAngle = 1.0f;
        DirectionSinHorizontalAngle = 0.0f;
        return;
    }
    else
    {
        // Vertikalwinkel berechnen:
        DirectionVerticalAngle = asinf(DirectionSinVerticalAngle);

        DirectionCosVerticalAngle = cosf(DirectionVerticalAngle);

        // Horizontalwinkel berechnen:
        DirectionCosHorizontalAngle = pDirection->z/
                                      DirectionCosVerticalAngle;

        DirectionHorizontalAngle = acosf(DirectionCosHorizontalAngle);

        if(pDirection->x < 0.0f)
        DirectionHorizontalAngle = 6.283185308f-DirectionHorizontalAngle;

        DirectionSinHorizontalAngle = sinf(DirectionHorizontalAngle);
        return;
    }
}