- Drehung um die Blickrichtungsachse (der Kamera)
 - Drehung um die horizontale Achse (der Kamera)
 - Drehung um die vertikale Achse (der Kamera)
 
// Blickrichtungsachse der Kamera:
D3DXVECTOR3 g_CameraViewDirection (0.0f, 0.0f, 1.0f);
// vertikale Achse der Kamera:
D3DXVECTOR3 g_CameraVertical (0.0f, 1.0f, 0.0f);
// horizontale Achse der Kamera:
D3DXVECTOR3 g_CameraHorizontal (1.0f, 0.0f, 0.0f);
// Kameradrehwinkel um die Blickrichtungsachse, wird für die
// Billboard-Ausrichtung benötigt
float g_ViewRotationAngle = 0.0f;
// Sichtmatrix (Kameramatrix) "Das Auge der Kamera"
D3DXMATRIXA16 g_matView;
// inverse Sichtmatrix für die Beschreibung der
// Ausrichtung (Orientierung) der Kamera:
D3DXMATRIXA16 g_CameraTransformationMatrix;
 
// Drehachsen der Kamera in ihrer originalen Ausrichtung
// vor etwaigen Kameradrehungen (Ausgangslage):
D3DXVECTOR3 g_CameraViewDirectionOriginal (0.0f, 0.0f, 1.0f);
D3DXVECTOR3 g_CameraVerticalOriginal (0.0f, 1.0f, 0.0f);
D3DXVECTOR3 g_CameraHorizontalOriginal (1.0f, 0.0f, 0.0f);
D3DXVECTOR3 g_CameraViewDirectionOriginalNeg (0.0f, 0.0f, -1.0f);
D3DXVECTOR3 g_CameraVerticalOriginalNeg (0.0f, -1.0f, 0.0f);
D3DXVECTOR3 g_CameraHorizontalOriginalNeg (-1.0f, 0.0f, 0.0f);
D3DXVECTOR3 g_CameraViewDirection (0.0f, 0.0f, 1.0f);
// vertikale Achse der Kamera:
D3DXVECTOR3 g_CameraVertical (0.0f, 1.0f, 0.0f);
// horizontale Achse der Kamera:
D3DXVECTOR3 g_CameraHorizontal (1.0f, 0.0f, 0.0f);
// Kameradrehwinkel um die Blickrichtungsachse, wird für die
// Billboard-Ausrichtung benötigt
float g_ViewRotationAngle = 0.0f;
// Sichtmatrix (Kameramatrix) "Das Auge der Kamera"
D3DXMATRIXA16 g_matView;
// inverse Sichtmatrix für die Beschreibung der
// Ausrichtung (Orientierung) der Kamera:
D3DXMATRIXA16 g_CameraTransformationMatrix;
// Drehachsen der Kamera in ihrer originalen Ausrichtung
// vor etwaigen Kameradrehungen (Ausgangslage):
D3DXVECTOR3 g_CameraViewDirectionOriginal (0.0f, 0.0f, 1.0f);
D3DXVECTOR3 g_CameraVerticalOriginal (0.0f, 1.0f, 0.0f);
D3DXVECTOR3 g_CameraHorizontalOriginal (1.0f, 0.0f, 0.0f);
D3DXVECTOR3 g_CameraViewDirectionOriginalNeg (0.0f, 0.0f, -1.0f);
D3DXVECTOR3 g_CameraVerticalOriginalNeg (0.0f, -1.0f, 0.0f);
D3DXVECTOR3 g_CameraHorizontalOriginalNeg (-1.0f, 0.0f, 0.0f);
Die Arbeitsweise unserer Funktionen für die Durchführung der Kameradrehungen (Camera_HorizontalRotation(), Camera_VerticalRotation() und Camera_ViewRotation())  ist denkbar einfach. Zunächst wird eine Rotationsmatrix berechnet, die  die Drehung für das aktuelle Frame beschreibt. Man spricht daher auch  von einer Frame-Rotationsmatrix. Im zweiten Schritt wird diese Matrix mit der Gesamtrotationsmatrix g_CameraTransformationMatrix multipliziert, die alle bisherigen Drehungen der Kamera aus ihrer  Ausgangslage (Blickrichtung: positive z-Richtung, Horizontale Achse: positive  x-Richtung, Vertikale Achse: positive y-Richtung) beschreibt. Hierbei ist auf  die richtige Multiplikationsreihenfolge zu achten:
Drehung um die Blickrichtungsachse:
Gesamtrotationsmatrix(neues Frame) = Gesamtrotationsmatrix(altes Frame)*
FrameRotationsmatrix
FrameRotationsmatrix
Schritt 1: Kameradrehung aus der Ausgangslage in die vorherige Blickrichtung.
Schritt 2: Kameradrehung um die aktuelle Blickrichtungsachse (Frame-Drehung).
Schritt 1 beschreibt also die vorherige Ausrichtung der Kamera und Schritt 2 die zusätzlich auszuführende Drehung.
Horizontale und vertikale Drehung:
Gesamtrotationsmatrix(neues Frame) = FrameRotationsmatrix*
Gesamtrotationsmatrix(altes Frame)
Gesamtrotationsmatrix(altes Frame)
Bei  der horizontalen bzw. bei der vertikalen Drehung verändern wir die  Multiplikationsreihenfolge. Fassen wir also die zweite Matrixgleichung  in Worte:
Schritt 1:  Kameradrehung aus der Ausgangslage entweder um die anfängliche  horizontale bzw. um die anfängliche vertikale Achse (Frame-Drehung).
Schritt2: Kameradrehung mithilfe der bisherigen Gesamtrotationsmatrix in die endgültige Blickrichtung.
Genial  an dieser Multiplikationsreihenfolge ist die Tatsache, dass wir für die  Durchführung der Frame-Drehungen weder die aktuelle horizontale noch die  aktuelle vertikale Drehachse benötigen – die originalen Drehachsen  reichen völlig aus!
Hinweis:
Die Gesamtrotationsmatrix aller durchgeführten Kameradrehungen  g_CameraTransformationMatrix  kommt in unseren Demoprogrammen u.a. bei der Ausrichtung von  2D-Objekten (Billboards) zum Einsatz. Vom mathematischen Standpunkt aus  betrachtet entspricht diese Matrix der inversen bzw. transponierten  Sichtmatrix (View Matrix).
Berechnung der neuen Kameraachsen nach einer Drehung
Unter  der Voraussetzung, dass wir anfangs die positive z-Richtung als  Blickrichtung, die positive x-Richtung als horizontale und die positive  y-Richtung als vertikale Kameraachse gewählt haben, entspricht die erste  Zeile der Kamera-Gesamtrotationsmatrix der horizontalen Kameraachse,  die zweite Zeile der vertikalen Kameraachse und die dritte Zeile der  Blickrichtung.
Erklärung:
Befinden  sich die Kameraachsen noch in ihrer Ausgangslage, dann entspricht die  Kamera-Gesamtrotationsmatrix der Einheitsmatrix. Die erste Zeile dieser  Matrix (1, 0, 0) entspricht der horizontalen Kameraachse, die zweite  Zeile (0, 1, 0) entspricht der vertikalen Kameraachse und die dritte  Zeile (0, 0, 1) entspricht der Blickrichtung.
Alternative Berechnung der neuen Kameraachsen:
Zusätzlich  zur Blickrichtung ändert sich bei einer horizontalen Drehung die  horizontale Achse bzw. bei einer vertikalen Drehung die vertikale Achse.  Mit der Hilfe des Kreuzprodukts (Vektorprodukts) aus der neuen  Blickrichtung und der unverändert gebliebenen Drehachse könnte man jetzt  auf alternative Weise die neue horizontale Achse bzw. vertikale Achse  bestimmen.
Im Fall einer Drehung um  die Blickrichtungsachse ändern sich sowohl die horizontale als auch die  vertikale Achse. Die neuen Achsen lassen sich alternativ durch  Multiplikation der alten Achsen mit der Frame-Rotationsmatrix berechnen.
Nachdem  die neuen Drehachsen berechnet worden sind, müssen diese gegebenenfalls  noch normiert werden. Bedenken Sie, dass es aufgrund der begrenzten  Genauigkeit der Variablen immer mal zu Rundungsfehlern kommen kann.  Unter Verwendung der aktualisierten Drehachsen wird im letzten Schritt  mithilfe der Funktion D3DXMatrixLookAtLH() die neue Sichtmatrix berechnet.
Hier nun die zugehörigen Funktionen:
horizontale Kameradrehung
inline void Camera_HorizontalRotation(float rotationAngle)
{
rotationAngle = rotationAngle*D3DX_PI/180.0f;
D3DXMATRIXA16 tempMatrix1;
D3DXMatrixRotationY(&tempMatrix1, rotationAngle);
g_CameraTransformationMatrix = tempMatrix1*
g_CameraTransformationMatrix;
g_CameraHorizontal.x = g_CameraTransformationMatrix._11;
g_CameraHorizontal.y = g_CameraTransformationMatrix._12;
g_CameraHorizontal.z = g_CameraTransformationMatrix._13;
g_CameraViewDirection.x = g_CameraTransformationMatrix._31;
g_CameraViewDirection.y = g_CameraTransformationMatrix._32;
g_CameraViewDirection.z = g_CameraTransformationMatrix._33;
D3DXVec3Normalize(&g_CameraHorizontal, &g_CameraHorizontal);
D3DXVec3Normalize(&g_CameraViewDirection, &g_CameraViewDirection);
D3DXMatrixLookAtLH(&g_matView, &g_NullVector, &g_CameraViewDirection,
&g_CameraVertical);
}
{
rotationAngle = rotationAngle*D3DX_PI/180.0f;
D3DXMATRIXA16 tempMatrix1;
D3DXMatrixRotationY(&tempMatrix1, rotationAngle);
g_CameraTransformationMatrix = tempMatrix1*
g_CameraTransformationMatrix;
g_CameraHorizontal.x = g_CameraTransformationMatrix._11;
g_CameraHorizontal.y = g_CameraTransformationMatrix._12;
g_CameraHorizontal.z = g_CameraTransformationMatrix._13;
g_CameraViewDirection.x = g_CameraTransformationMatrix._31;
g_CameraViewDirection.y = g_CameraTransformationMatrix._32;
g_CameraViewDirection.z = g_CameraTransformationMatrix._33;
D3DXVec3Normalize(&g_CameraHorizontal, &g_CameraHorizontal);
D3DXVec3Normalize(&g_CameraViewDirection, &g_CameraViewDirection);
D3DXMatrixLookAtLH(&g_matView, &g_NullVector, &g_CameraViewDirection,
&g_CameraVertical);
}
vertikale Kameradrehung
inline void Camera_VerticalRotation(float rotationAngle)
{
rotationAngle = rotationAngle*D3DX_PI/180.0f;
D3DXMATRIXA16 tempMatrix1;
D3DXMatrixRotationX(&tempMatrix1, rotationAngle);
g_CameraTransformationMatrix = tempMatrix1*
g_CameraTransformationMatrix;
g_CameraVertical.x = g_CameraTransformationMatrix._21;
g_CameraVertical.y = g_CameraTransformationMatrix._22;
g_CameraVertical.z = g_CameraTransformationMatrix._23;
g_CameraViewDirection.x = g_CameraTransformationMatrix._31;
g_CameraViewDirection.y = g_CameraTransformationMatrix._32;
g_CameraViewDirection.z = g_CameraTransformationMatrix._33;
D3DXVec3Normalize(&g_CameraVertical, &g_CameraVertical);
D3DXVec3Normalize(&g_CameraViewDirection, &g_CameraViewDirection);
D3DXMatrixLookAtLH(&g_matView, &g_NullVector, &g_CameraViewDirection,
&g_CameraVertical);
}
{
rotationAngle = rotationAngle*D3DX_PI/180.0f;
D3DXMATRIXA16 tempMatrix1;
D3DXMatrixRotationX(&tempMatrix1, rotationAngle);
g_CameraTransformationMatrix = tempMatrix1*
g_CameraTransformationMatrix;
g_CameraVertical.x = g_CameraTransformationMatrix._21;
g_CameraVertical.y = g_CameraTransformationMatrix._22;
g_CameraVertical.z = g_CameraTransformationMatrix._23;
g_CameraViewDirection.x = g_CameraTransformationMatrix._31;
g_CameraViewDirection.y = g_CameraTransformationMatrix._32;
g_CameraViewDirection.z = g_CameraTransformationMatrix._33;
D3DXVec3Normalize(&g_CameraVertical, &g_CameraVertical);
D3DXVec3Normalize(&g_CameraViewDirection, &g_CameraViewDirection);
D3DXMatrixLookAtLH(&g_matView, &g_NullVector, &g_CameraViewDirection,
&g_CameraVertical);
}
Kameradrehung um die Blickrichtungsachse
inline void Camera_ViewRotation(float rotationAngle)
{
rotationAngle = rotationAngle*D3DX_PI/180.0f;
g_ViewRotationAngle += rotationAngle;
if(g_ViewRotationAngle > D3DX_PI)
g_ViewRotationAngle -= 6.283185308f;
else if(g_ViewRotationAngle < -D3DX_PI)
g_ViewRotationAngle += 6.283185308f;
D3DXMATRIXA16 tempMatrix1;
D3DXMatrixRotationAxis(&tempMatrix1, &g_CameraViewDirection,
rotationAngle);
g_CameraTransformationMatrix = g_CameraTransformationMatrix*
tempMatrix1;
g_CameraHorizontal.x = g_CameraTransformationMatrix._11;
g_CameraHorizontal.y = g_CameraTransformationMatrix._12;
g_CameraHorizontal.z = g_CameraTransformationMatrix._13;
g_CameraVertical.x = g_CameraTransformationMatrix._21;
g_CameraVertical.y = g_CameraTransformationMatrix._22;
g_CameraVertical.z = g_CameraTransformationMatrix._23;
D3DXVec3Normalize(&g_CameraHorizontal, &g_CameraHorizontal);
D3DXVec3Normalize(&g_CameraVertical, &g_CameraVertical);
D3DXMatrixLookAtLH(&g_matView, &g_NullVector, &g_CameraViewDirection,
&g_CameraVertical);
}
{
rotationAngle = rotationAngle*D3DX_PI/180.0f;
g_ViewRotationAngle += rotationAngle;
if(g_ViewRotationAngle > D3DX_PI)
g_ViewRotationAngle -= 6.283185308f;
else if(g_ViewRotationAngle < -D3DX_PI)
g_ViewRotationAngle += 6.283185308f;
D3DXMATRIXA16 tempMatrix1;
D3DXMatrixRotationAxis(&tempMatrix1, &g_CameraViewDirection,
rotationAngle);
g_CameraTransformationMatrix = g_CameraTransformationMatrix*
tempMatrix1;
g_CameraHorizontal.x = g_CameraTransformationMatrix._11;
g_CameraHorizontal.y = g_CameraTransformationMatrix._12;
g_CameraHorizontal.z = g_CameraTransformationMatrix._13;
g_CameraVertical.x = g_CameraTransformationMatrix._21;
g_CameraVertical.y = g_CameraTransformationMatrix._22;
g_CameraVertical.z = g_CameraTransformationMatrix._23;
D3DXVec3Normalize(&g_CameraHorizontal, &g_CameraHorizontal);
D3DXVec3Normalize(&g_CameraVertical, &g_CameraVertical);
D3DXMatrixLookAtLH(&g_matView, &g_NullVector, &g_CameraViewDirection,
&g_CameraVertical);
}
Kameradrehungen zurücksetzen
inline void Reset_CameraRotation(void)
{
g_ViewRotationAngle = 0.0f;
{
g_ViewRotationAngle = 0.0f;
g_CameraViewDirection = g_CameraViewDirectionOriginal;
g_CameraVertical = g_CameraVerticalOriginal;
g_CameraHorizontal = g_CameraHorizontalOriginal;
D3DXMatrixLookAtLH(&g_matView, &g_NullVector, &g_CameraViewDirection,
&g_CameraVertical);
D3DXMatrixInverse(&g_CameraTransformationMatrix, NULL,
&g_matView);
}