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:
+28
-16
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
|
||||
Reference in New Issue
Block a user