Billboard Techniken: Ausrichtung mithilfe der Kamera-Transformationsmatrix

Im letzten Artikel habe ich Ihnen gezeigt, wie sich Billboards bei der Hintergrunddarstellung einsetzen lassen. Heute demonstriere ich ihnen eine Technik die sich insbesondere im Zuge der Darstellung von Rauch, Feuer, Explosionen und Lens Flares einsetzen lässt. Ausgerichtet werden die Billboards hierbei mithilfe der Kamera-Transformationsmatrix.


Hinweis:
Die Kamera-Transformationsmatrix entspricht der inversen beziehungsweise der transponierten Sichtmatrix (View Matrix). Siehe hierzu den Artikel Mathematik der 3D-Programmierung Teil 10.

D3DXMatrixLookAtLH(&g_matView, &g_NullVector, &g_CameraViewDirection,
                   &g_CameraVertical);

D3DXMatrixTranspose(&g_CameraTransformationMatrix, &g_matView);

Zunächst werden eine Skalierung- und eine Translationsmatrix erzeugt. Durch Multiplikation dieser Matrizen mit der Kamera-Transformationsmatrix erhält man die gesuchte Kameraraum-Transformationsmatrix (pCameraSpaceTransformationMatrix) für die spätere Transformation der Billboard-Vertices im Vertex Shader.

inline void Positioning_2DObject(
            D3DXMATRIXA16* pCameraSpaceTransformationMatrix,
            D3DXVECTOR3* pCameraSpacePosition,
            float
&scaleX, float &scaleY)
{
    D3DXMATRIXA16 TranslationMatrix, ScaleMatrix;

    // Skalierungsmatrix erstellen:
    D3DXMatrixScaling(&ScaleMatrix, scaleX, scaleY, 1.0f);

    // Verschiebungsmatrix erstellen:
    D3DXMatrixTranslation(&TranslationMatrix, pCameraSpacePosition->x,
                         pCameraSpacePosition->y, pCameraSpacePosition->z);

    *pCameraSpaceTransformationMatrix = ScaleMatrix*
    g_CameraTransformationMatrix*TranslationMatrix;
}

Die zuvor besprochene Funktion hat einen gravierenden Nachteil – man sieht ein Billboard unabhängig von der Blickrichtung immer unter dem gleichen Blickwinkel. Bei einer Kameradrehung um die Blickrichtungsachse – dies entspricht einer seitlichen Nickbewegung des Kopfes – würde man jedoch instinktiv erwarten, dass sich der Blickwinkel, unter dem man ein Billboard wahrnimmt, währenddessen verändert. Dies ist jedoch nicht der Fall, da die Drehbewegung durch die Kamera-Transformationsmatrix kompensiert wird.

Die nachfolgende Funktion schafft hier Abhilfe, den sie berücksichtigt zum einen die Kameradrehung um die Blickrichtungsachse (gespeichert wird der Drehwinkel in der globalen Variable g_ViewRotationAngle) und ermöglicht darüber hinaus die Darstellung eines Billboards unter einem beliebigen Blickwinkel (rotationAngle). Ermöglicht wird dies durch eine zusätzliche Drehung des Billboards um die Blickrichtungsachse.

inline void Positioning_2DObjectRotated(
            D3DXMATRIXA16* pCameraSpaceTransformationMatrix,
            D3DXVECTOR3* pCameraSpacePosition,
            float
&scaleX, float &scaleY, float &rotationAngle)
{
    D3DXMATRIXA16 RotationTranslationMatrix, ScaleMatrix;

    // Skalierungsmatrix erstellen:
    D3DXMatrixScaling(&ScaleMatrix, scaleX, scaleY, 1.0f);

    // Bei der Drehung des Billboard um die Blickrichtungsachse
    // muss die Kameradrehung um selbige Achse stets mitberücksichtigt
    // werden. Das Billboard dreht sich gewissermaßen mit der Kamera mit!

    float corrected_BillboardAngle = rotationAngle-g_ViewRotationAngle;

    if(corrected_BillboardAngle > D3DX_PI)
        corrected_BillboardAngle -= 6.283185308f;
    else if(corrected_BillboardAngle < -D3DX_PI)
        corrected_BillboardAngle += 6.283185308f;

    D3DXMatrixRotationAxis(&RotationTranslationMatrix,
                           &g_CameraViewDirection,
                           corrected_BillboardAngle);

    RotationTranslationMatrix._41 = pCameraSpacePosition->x;
    RotationTranslationMatrix._42 = pCameraSpacePosition->y;
    RotationTranslationMatrix._43 = pCameraSpacePosition->z;

    *pCameraSpaceTransformationMatrix = ScaleMatrix*
    g_CameraTransformationMatrix*RotationTranslationMatrix;
}