Translation and scaling (when applied in that order) are trivially combined;

save a matrix multiply for every actor.  (Maybe we can avoid doing any,
for objects which are neither rotated nor scaled--such as those positioned
based on their parent--but I'm not sure it's worth it.)  Rotations can be
combined without doing a full matrix multiply, too; if an actor rotates at all,
only do one matrix multiply.
This commit is contained in:
Glenn Maynard
2005-02-05 03:12:04 +00:00
parent aceff788bf
commit 3e389c103b
3 changed files with 117 additions and 16 deletions
+28 -16
View File
@@ -246,23 +246,35 @@ void Actor::BeginDraw() // set the world matrix and calculate actor properties
}
}
DISPLAY->Translate(
m_pTempState->pos.x,
m_pTempState->pos.y,
m_pTempState->pos.z );
DISPLAY->Scale(
m_pTempState->scale.x * m_baseScale.x,
m_pTempState->scale.y * m_baseScale.y,
m_pTempState->scale.z * m_baseScale.z );
{
RageMatrix m;
RageMatrixTranslateAndScale( &m,
m_pTempState->pos.x,
m_pTempState->pos.y,
m_pTempState->pos.z,
m_pTempState->scale.x * m_baseScale.x,
m_pTempState->scale.y * m_baseScale.y,
m_pTempState->scale.z * m_baseScale.z );
/* The only time rotation and quat should normally be used simultaneously
* is for m_baseRotation. */
if( m_pTempState->rotation.x + m_baseRotation.x != 0 )
DISPLAY->RotateX( m_pTempState->rotation.x + m_baseRotation.x );
if( m_pTempState->rotation.y + m_baseRotation.y != 0 )
DISPLAY->RotateY( m_pTempState->rotation.y + m_baseRotation.y );
if( m_pTempState->rotation.z + m_baseRotation.z != 0 )
DISPLAY->RotateZ( m_pTempState->rotation.z + m_baseRotation.z );
DISPLAY->PreMultMatrix( m );
}
{
/* The only time rotation and quat should normally be used simultaneously
* is for m_baseRotation. Most objects aren't rotated at all, so optimize
* that case. */
const float fRotateX = m_pTempState->rotation.x + m_baseRotation.x;
const float fRotateY = m_pTempState->rotation.y + m_baseRotation.y;
const float fRotateZ = m_pTempState->rotation.z + m_baseRotation.z;
if( fRotateX != 0 || fRotateY != 0 || fRotateZ != 0 )
{
RageMatrix m;
RageMatrixRotationXYZ( &m, fRotateX, fRotateY, fRotateZ );
DISPLAY->PreMultMatrix( m );
}
}
if( m_pTempState->quat.x != 0 || m_pTempState->quat.y != 0 || m_pTempState->quat.z != 0 || m_pTempState->quat.w != 1 )
{
+87
View File
@@ -151,6 +151,40 @@ void RageMatrixScaling( RageMatrix* pOut, float x, float y, float z )
pOut->m[2][2] = z;
}
/*
* Return:
*
* RageMatrix translate;
* RageMatrixTranslation( &translate, fTransX, fTransY, fTransZ );
* RageMatrix scale;
* RageMatrixScaling( &scale, fScaleX, float fScaleY, float fScaleZ );
* RageMatrixMultiply( pOut, &translate, &scale );
*/
void RageMatrixTranslateAndScale( RageMatrix* pOut,
float fTransX, float fTransY, float fTransZ,
float fScaleX, float fScaleY, float fScaleZ )
{
pOut->m00 = fScaleX;
pOut->m01 = 0;
pOut->m02 = 0;
pOut->m03 = 0;
pOut->m10 = 0;
pOut->m11 = fScaleY;
pOut->m12 = 0;
pOut->m13 = 0;
pOut->m20 = 0;
pOut->m21 = 0;
pOut->m22 = fScaleZ;
pOut->m23 = 0;
pOut->m30 = fTransX;
pOut->m31 = fTransY;
pOut->m32 = fTransZ;
pOut->m33 = 1;
}
void RageMatrixRotationX( RageMatrix* pOut, float theta )
{
theta *= PI/180;
@@ -187,6 +221,59 @@ void RageMatrixRotationZ( RageMatrix* pOut, float theta )
pOut->m[1][0] = -pOut->m[0][1];
}
/* Return RageMatrixRotationX(rX) * RageMatrixRotationY(rY) * RageMatrixRotationZ(rZ)
* quickly (without actually doing two complete matrix multiplies), by removing the
* parts of the matrix multiplies that we know will be 0. */
void RageMatrixRotationXYZ( RageMatrix* pOut, float rX, float rY, float rZ )
{
rX *= PI/180;
rY *= PI/180;
rZ *= PI/180;
const float cX = cosf(rX);
const float sX = sinf(rX);
const float cY = cosf(rY);
const float sY = sinf(rY);
const float cZ = cosf(rZ);
const float sZ = sinf(rZ);
/*
* X*Y:
* RageMatrix(
* cY, sY*sX, sY*cX, 0,
* 0, cX, -sX, 0,
* -sY, cY*sX, cY*cX, 0,
* 0, 0, 0, 1
* );
*
* X*Y*Z:
*
* RageMatrix(
* cZ*cY, cZ*sY*sX+sZ*cX, cZ*sY*cX+sZ*(-sX), 0,
* (-sZ)*cY, (-sZ)*sY*sX+cZ*cX, (-sZ)*sY*cX+cZ*(-sX), 0,
* -sY, cY*sX, cY*cX, 0,
* 0, 0, 0, 1
* );
*/
pOut->m00 = cZ*cY;
pOut->m01 = cZ*sY*sX+sZ*cX;
pOut->m02 = cZ*sY*cX+sZ*(-sX);
pOut->m03 = 0;
pOut->m10 = (-sZ)*cY;
pOut->m11 = (-sZ)*sY*sX+cZ*cX;
pOut->m12 = (-sZ)*sY*cX+cZ*(-sX);
pOut->m13 = 0;
pOut->m20 = -sY;
pOut->m21 = cY*sX;
pOut->m22 = cY*cX;
pOut->m23 = 0;
pOut->m30 = 0;
pOut->m31 = 0;
pOut->m32 = 0;
pOut->m33 = 1;
}
/* This is similar in style to Actor::Command. However, Actors don't store
* matrix stacks; they only store offsets and scales, and compound them into
* a single transformations at once. This makes some things easy, but it's not
+2
View File
@@ -31,9 +31,11 @@ void RageMatrixIdentity( RageMatrix* pOut );
void RageMatrixMultiply( RageMatrix* pOut, const RageMatrix* pA, const RageMatrix* pB );
void RageMatrixTranslation( RageMatrix* pOut, float x, float y, float z );
void RageMatrixScaling( RageMatrix* pOut, float x, float y, float z );
void RageMatrixTranslateAndScale( RageMatrix* pOut, float fTransX, float fTransY, float fTransZ, float fScaleX, float fScaleY, float fScaleZ );
void RageMatrixRotationX( RageMatrix* pOut, float fTheta );
void RageMatrixRotationY( RageMatrix* pOut, float fTheta );
void RageMatrixRotationZ( RageMatrix* pOut, float fTheta );
void RageMatrixRotationXYZ( RageMatrix* pOut, float rX, float rY, float rZ );
void RageMatrixCommand( CString sCommandString, RageMatrix &mat );
void RageQuatFromHPR(RageVector4* pOut, RageVector3 hpr );
void RageQuatFromPRH(RageVector4* pOut, RageVector3 prh );