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);
&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;
}
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;
}
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;
}