123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867 |
- /******************************************************************************
- @File PVRTMatrixX.cpp
- @Title PVRTMatrixX
- @Version
- @Copyright Copyright (C) Imagination Technologies Limited.
- @Platform ANSI compatible
- @Description Set of mathematical functions involving matrices, vectors and
- quaternions.
- ******************************************************************************/
- #include "PVRTContext.h"
- #include <math.h>
- #include <string.h>
- #include "PVRTFixedPoint.h"
- #include "PVRTMatrix.h"
- /****************************************************************************
- ** Constants
- ****************************************************************************/
- static const PVRTMATRIXx c_mIdentity = {
- {
- PVRTF2X(1.0f), PVRTF2X(0.0f), PVRTF2X(0.0f), PVRTF2X(0.0f),
- PVRTF2X(0.0f), PVRTF2X(1.0f), PVRTF2X(0.0f), PVRTF2X(0.0f),
- PVRTF2X(0.0f), PVRTF2X(0.0f), PVRTF2X(1.0f), PVRTF2X(0.0f),
- PVRTF2X(0.0f), PVRTF2X(0.0f), PVRTF2X(0.0f), PVRTF2X(1.0f)
- }
- };
- /****************************************************************************
- ** Functions
- ****************************************************************************/
- /*!***************************************************************************
- @Function PVRTMatrixIdentityX
- @Output mOut Set to identity
- @Description Reset matrix to identity matrix.
- *****************************************************************************/
- void PVRTMatrixIdentityX(PVRTMATRIXx &mOut)
- {
- mOut.f[ 0]=PVRTF2X(1.0f); mOut.f[ 4]=PVRTF2X(0.0f); mOut.f[ 8]=PVRTF2X(0.0f); mOut.f[12]=PVRTF2X(0.0f);
- mOut.f[ 1]=PVRTF2X(0.0f); mOut.f[ 5]=PVRTF2X(1.0f); mOut.f[ 9]=PVRTF2X(0.0f); mOut.f[13]=PVRTF2X(0.0f);
- mOut.f[ 2]=PVRTF2X(0.0f); mOut.f[ 6]=PVRTF2X(0.0f); mOut.f[10]=PVRTF2X(1.0f); mOut.f[14]=PVRTF2X(0.0f);
- mOut.f[ 3]=PVRTF2X(0.0f); mOut.f[ 7]=PVRTF2X(0.0f); mOut.f[11]=PVRTF2X(0.0f); mOut.f[15]=PVRTF2X(1.0f);
- }
- /*!***************************************************************************
- @Function PVRTMatrixMultiplyX
- @Output mOut Result of mA x mB
- @Input mA First operand
- @Input mB Second operand
- @Description Multiply mA by mB and assign the result to mOut
- (mOut = p1 * p2). A copy of the result matrix is done in
- the function because mOut can be a parameter mA or mB.
- The fixed-point shift could be performed after adding
- all four intermediate results together however this might
- cause some overflow issues.
- ****************************************************************************/
- void PVRTMatrixMultiplyX(
- PVRTMATRIXx &mOut,
- const PVRTMATRIXx &mA,
- const PVRTMATRIXx &mB)
- {
- PVRTMATRIXx mRet;
- /* Perform calculation on a dummy matrix (mRet) */
- mRet.f[ 0] = PVRTXMUL(mA.f[ 0], mB.f[ 0]) + PVRTXMUL(mA.f[ 1], mB.f[ 4]) + PVRTXMUL(mA.f[ 2], mB.f[ 8]) + PVRTXMUL(mA.f[ 3], mB.f[12]);
- mRet.f[ 1] = PVRTXMUL(mA.f[ 0], mB.f[ 1]) + PVRTXMUL(mA.f[ 1], mB.f[ 5]) + PVRTXMUL(mA.f[ 2], mB.f[ 9]) + PVRTXMUL(mA.f[ 3], mB.f[13]);
- mRet.f[ 2] = PVRTXMUL(mA.f[ 0], mB.f[ 2]) + PVRTXMUL(mA.f[ 1], mB.f[ 6]) + PVRTXMUL(mA.f[ 2], mB.f[10]) + PVRTXMUL(mA.f[ 3], mB.f[14]);
- mRet.f[ 3] = PVRTXMUL(mA.f[ 0], mB.f[ 3]) + PVRTXMUL(mA.f[ 1], mB.f[ 7]) + PVRTXMUL(mA.f[ 2], mB.f[11]) + PVRTXMUL(mA.f[ 3], mB.f[15]);
- mRet.f[ 4] = PVRTXMUL(mA.f[ 4], mB.f[ 0]) + PVRTXMUL(mA.f[ 5], mB.f[ 4]) + PVRTXMUL(mA.f[ 6], mB.f[ 8]) + PVRTXMUL(mA.f[ 7], mB.f[12]);
- mRet.f[ 5] = PVRTXMUL(mA.f[ 4], mB.f[ 1]) + PVRTXMUL(mA.f[ 5], mB.f[ 5]) + PVRTXMUL(mA.f[ 6], mB.f[ 9]) + PVRTXMUL(mA.f[ 7], mB.f[13]);
- mRet.f[ 6] = PVRTXMUL(mA.f[ 4], mB.f[ 2]) + PVRTXMUL(mA.f[ 5], mB.f[ 6]) + PVRTXMUL(mA.f[ 6], mB.f[10]) + PVRTXMUL(mA.f[ 7], mB.f[14]);
- mRet.f[ 7] = PVRTXMUL(mA.f[ 4], mB.f[ 3]) + PVRTXMUL(mA.f[ 5], mB.f[ 7]) + PVRTXMUL(mA.f[ 6], mB.f[11]) + PVRTXMUL(mA.f[ 7], mB.f[15]);
- mRet.f[ 8] = PVRTXMUL(mA.f[ 8], mB.f[ 0]) + PVRTXMUL(mA.f[ 9], mB.f[ 4]) + PVRTXMUL(mA.f[10], mB.f[ 8]) + PVRTXMUL(mA.f[11], mB.f[12]);
- mRet.f[ 9] = PVRTXMUL(mA.f[ 8], mB.f[ 1]) + PVRTXMUL(mA.f[ 9], mB.f[ 5]) + PVRTXMUL(mA.f[10], mB.f[ 9]) + PVRTXMUL(mA.f[11], mB.f[13]);
- mRet.f[10] = PVRTXMUL(mA.f[ 8], mB.f[ 2]) + PVRTXMUL(mA.f[ 9], mB.f[ 6]) + PVRTXMUL(mA.f[10], mB.f[10]) + PVRTXMUL(mA.f[11], mB.f[14]);
- mRet.f[11] = PVRTXMUL(mA.f[ 8], mB.f[ 3]) + PVRTXMUL(mA.f[ 9], mB.f[ 7]) + PVRTXMUL(mA.f[10], mB.f[11]) + PVRTXMUL(mA.f[11], mB.f[15]);
- mRet.f[12] = PVRTXMUL(mA.f[12], mB.f[ 0]) + PVRTXMUL(mA.f[13], mB.f[ 4]) + PVRTXMUL(mA.f[14], mB.f[ 8]) + PVRTXMUL(mA.f[15], mB.f[12]);
- mRet.f[13] = PVRTXMUL(mA.f[12], mB.f[ 1]) + PVRTXMUL(mA.f[13], mB.f[ 5]) + PVRTXMUL(mA.f[14], mB.f[ 9]) + PVRTXMUL(mA.f[15], mB.f[13]);
- mRet.f[14] = PVRTXMUL(mA.f[12], mB.f[ 2]) + PVRTXMUL(mA.f[13], mB.f[ 6]) + PVRTXMUL(mA.f[14], mB.f[10]) + PVRTXMUL(mA.f[15], mB.f[14]);
- mRet.f[15] = PVRTXMUL(mA.f[12], mB.f[ 3]) + PVRTXMUL(mA.f[13], mB.f[ 7]) + PVRTXMUL(mA.f[14], mB.f[11]) + PVRTXMUL(mA.f[15], mB.f[15]);
- /* Copy result in pResultMatrix */
- mOut = mRet;
- }
- /*!***************************************************************************
- @Function Name PVRTMatrixTranslationX
- @Output mOut Translation matrix
- @Input fX X component of the translation
- @Input fY Y component of the translation
- @Input fZ Z component of the translation
- @Description Build a transaltion matrix mOut using fX, fY and fZ.
- *****************************************************************************/
- void PVRTMatrixTranslationX(
- PVRTMATRIXx &mOut,
- const int fX,
- const int fY,
- const int fZ)
- {
- mOut.f[ 0]=PVRTF2X(1.0f); mOut.f[ 4]=PVRTF2X(0.0f); mOut.f[ 8]=PVRTF2X(0.0f); mOut.f[12]=fX;
- mOut.f[ 1]=PVRTF2X(0.0f); mOut.f[ 5]=PVRTF2X(1.0f); mOut.f[ 9]=PVRTF2X(0.0f); mOut.f[13]=fY;
- mOut.f[ 2]=PVRTF2X(0.0f); mOut.f[ 6]=PVRTF2X(0.0f); mOut.f[10]=PVRTF2X(1.0f); mOut.f[14]=fZ;
- mOut.f[ 3]=PVRTF2X(0.0f); mOut.f[ 7]=PVRTF2X(0.0f); mOut.f[11]=PVRTF2X(0.0f); mOut.f[15]=PVRTF2X(1.0f);
- }
- /*!***************************************************************************
- @Function Name PVRTMatrixScalingX
- @Output mOut Scale matrix
- @Input fX X component of the scaling
- @Input fY Y component of the scaling
- @Input fZ Z component of the scaling
- @Description Build a scale matrix mOut using fX, fY and fZ.
- *****************************************************************************/
- void PVRTMatrixScalingX(
- PVRTMATRIXx &mOut,
- const int fX,
- const int fY,
- const int fZ)
- {
- mOut.f[ 0]=fX; mOut.f[ 4]=PVRTF2X(0.0f); mOut.f[ 8]=PVRTF2X(0.0f); mOut.f[12]=PVRTF2X(0.0f);
- mOut.f[ 1]=PVRTF2X(0.0f); mOut.f[ 5]=fY; mOut.f[ 9]=PVRTF2X(0.0f); mOut.f[13]=PVRTF2X(0.0f);
- mOut.f[ 2]=PVRTF2X(0.0f); mOut.f[ 6]=PVRTF2X(0.0f); mOut.f[10]=fZ; mOut.f[14]=PVRTF2X(0.0f);
- mOut.f[ 3]=PVRTF2X(0.0f); mOut.f[ 7]=PVRTF2X(0.0f); mOut.f[11]=PVRTF2X(0.0f); mOut.f[15]=PVRTF2X(1.0f);
- }
- /*!***************************************************************************
- @Function Name PVRTMatrixRotationXX
- @Output mOut Rotation matrix
- @Input fAngle Angle of the rotation
- @Description Create an X rotation matrix mOut.
- *****************************************************************************/
- void PVRTMatrixRotationXX(
- PVRTMATRIXx &mOut,
- const int fAngle)
- {
- int fCosine, fSine;
- /* Precompute cos and sin */
- #if defined(BUILD_DX9) || defined(BUILD_D3DM) || defined(BUILD_DX10)
- fCosine = PVRTXCOS(-fAngle);
- fSine = PVRTXSIN(-fAngle);
- #else
- fCosine = PVRTXCOS(fAngle);
- fSine = PVRTXSIN(fAngle);
- #endif
- /* Create the trigonometric matrix corresponding to X Rotation */
- mOut.f[ 0]=PVRTF2X(1.0f); mOut.f[ 4]=PVRTF2X(0.0f); mOut.f[ 8]=PVRTF2X(0.0f); mOut.f[12]=PVRTF2X(0.0f);
- mOut.f[ 1]=PVRTF2X(0.0f); mOut.f[ 5]=fCosine; mOut.f[ 9]=fSine; mOut.f[13]=PVRTF2X(0.0f);
- mOut.f[ 2]=PVRTF2X(0.0f); mOut.f[ 6]=-fSine; mOut.f[10]=fCosine; mOut.f[14]=PVRTF2X(0.0f);
- mOut.f[ 3]=PVRTF2X(0.0f); mOut.f[ 7]=PVRTF2X(0.0f); mOut.f[11]=PVRTF2X(0.0f); mOut.f[15]=PVRTF2X(1.0f);
- }
- /*!***************************************************************************
- @Function Name PVRTMatrixRotationYX
- @Output mOut Rotation matrix
- @Input fAngle Angle of the rotation
- @Description Create an Y rotation matrix mOut.
- *****************************************************************************/
- void PVRTMatrixRotationYX(
- PVRTMATRIXx &mOut,
- const int fAngle)
- {
- int fCosine, fSine;
- /* Precompute cos and sin */
- #if defined(BUILD_DX9) || defined(BUILD_D3DM) || defined(BUILD_DX10)
- fCosine = PVRTXCOS(-fAngle);
- fSine = PVRTXSIN(-fAngle);
- #else
- fCosine = PVRTXCOS(fAngle);
- fSine = PVRTXSIN(fAngle);
- #endif
- /* Create the trigonometric matrix corresponding to Y Rotation */
- mOut.f[ 0]=fCosine; mOut.f[ 4]=PVRTF2X(0.0f); mOut.f[ 8]=-fSine; mOut.f[12]=PVRTF2X(0.0f);
- mOut.f[ 1]=PVRTF2X(0.0f); mOut.f[ 5]=PVRTF2X(1.0f); mOut.f[ 9]=PVRTF2X(0.0f); mOut.f[13]=PVRTF2X(0.0f);
- mOut.f[ 2]=fSine; mOut.f[ 6]=PVRTF2X(0.0f); mOut.f[10]=fCosine; mOut.f[14]=PVRTF2X(0.0f);
- mOut.f[ 3]=PVRTF2X(0.0f); mOut.f[ 7]=PVRTF2X(0.0f); mOut.f[11]=PVRTF2X(0.0f); mOut.f[15]=PVRTF2X(1.0f);
- }
- /*!***************************************************************************
- @Function Name PVRTMatrixRotationZX
- @Output mOut Rotation matrix
- @Input fAngle Angle of the rotation
- @Description Create an Z rotation matrix mOut.
- *****************************************************************************/
- void PVRTMatrixRotationZX(
- PVRTMATRIXx &mOut,
- const int fAngle)
- {
- int fCosine, fSine;
- /* Precompute cos and sin */
- #if defined(BUILD_DX9) || defined(BUILD_D3DM) || defined(BUILD_DX10)
- fCosine = PVRTXCOS(-fAngle);
- fSine = PVRTXSIN(-fAngle);
- #else
- fCosine = PVRTXCOS(fAngle);
- fSine = PVRTXSIN(fAngle);
- #endif
- /* Create the trigonometric matrix corresponding to Z Rotation */
- mOut.f[ 0]=fCosine; mOut.f[ 4]=fSine; mOut.f[ 8]=PVRTF2X(0.0f); mOut.f[12]=PVRTF2X(0.0f);
- mOut.f[ 1]=-fSine; mOut.f[ 5]=fCosine; mOut.f[ 9]=PVRTF2X(0.0f); mOut.f[13]=PVRTF2X(0.0f);
- mOut.f[ 2]=PVRTF2X(0.0f); mOut.f[ 6]=PVRTF2X(0.0f); mOut.f[10]=PVRTF2X(1.0f); mOut.f[14]=PVRTF2X(0.0f);
- mOut.f[ 3]=PVRTF2X(0.0f); mOut.f[ 7]=PVRTF2X(0.0f); mOut.f[11]=PVRTF2X(0.0f); mOut.f[15]=PVRTF2X(1.0f);
- }
- /*!***************************************************************************
- @Function Name PVRTMatrixTransposeX
- @Output mOut Transposed matrix
- @Input mIn Original matrix
- @Description Compute the transpose matrix of mIn.
- *****************************************************************************/
- void PVRTMatrixTransposeX(
- PVRTMATRIXx &mOut,
- const PVRTMATRIXx &mIn)
- {
- PVRTMATRIXx mTmp;
- mTmp.f[ 0]=mIn.f[ 0]; mTmp.f[ 4]=mIn.f[ 1]; mTmp.f[ 8]=mIn.f[ 2]; mTmp.f[12]=mIn.f[ 3];
- mTmp.f[ 1]=mIn.f[ 4]; mTmp.f[ 5]=mIn.f[ 5]; mTmp.f[ 9]=mIn.f[ 6]; mTmp.f[13]=mIn.f[ 7];
- mTmp.f[ 2]=mIn.f[ 8]; mTmp.f[ 6]=mIn.f[ 9]; mTmp.f[10]=mIn.f[10]; mTmp.f[14]=mIn.f[11];
- mTmp.f[ 3]=mIn.f[12]; mTmp.f[ 7]=mIn.f[13]; mTmp.f[11]=mIn.f[14]; mTmp.f[15]=mIn.f[15];
- mOut = mTmp;
- }
- /*!***************************************************************************
- @Function PVRTMatrixInverseX
- @Output mOut Inversed matrix
- @Input mIn Original matrix
- @Description Compute the inverse matrix of mIn.
- The matrix must be of the form :
- A 0
- C 1
- Where A is a 3x3 matrix and C is a 1x3 matrix.
- *****************************************************************************/
- void PVRTMatrixInverseX(
- PVRTMATRIXx &mOut,
- const PVRTMATRIXx &mIn)
- {
- PVRTMATRIXx mDummyMatrix;
- int det_1;
- int pos, neg, temp;
- /* Calculate the determinant of submatrix A and determine if the
- the matrix is singular as limited by the double precision
- floating-point data representation. */
- pos = neg = 0;
- temp = PVRTXMUL(PVRTXMUL(mIn.f[ 0], mIn.f[ 5]), mIn.f[10]);
- if (temp >= 0) pos += temp; else neg += temp;
- temp = PVRTXMUL(PVRTXMUL(mIn.f[ 4], mIn.f[ 9]), mIn.f[ 2]);
- if (temp >= 0) pos += temp; else neg += temp;
- temp = PVRTXMUL(PVRTXMUL(mIn.f[ 8], mIn.f[ 1]), mIn.f[ 6]);
- if (temp >= 0) pos += temp; else neg += temp;
- temp = PVRTXMUL(PVRTXMUL(-mIn.f[ 8], mIn.f[ 5]), mIn.f[ 2]);
- if (temp >= 0) pos += temp; else neg += temp;
- temp = PVRTXMUL(PVRTXMUL(-mIn.f[ 4], mIn.f[ 1]), mIn.f[10]);
- if (temp >= 0) pos += temp; else neg += temp;
- temp = PVRTXMUL(PVRTXMUL(-mIn.f[ 0], mIn.f[ 9]), mIn.f[ 6]);
- if (temp >= 0) pos += temp; else neg += temp;
- det_1 = pos + neg;
- /* Is the submatrix A singular? */
- if (det_1 == 0)
- {
- /* Matrix M has no inverse */
- _RPT0(_CRT_WARN, "Matrix has no inverse : singular matrix\n");
- return;
- }
- else
- {
- /* Calculate inverse(A) = adj(A) / det(A) */
- //det_1 = 1.0 / det_1;
- det_1 = PVRTXDIV(PVRTF2X(1.0f), det_1);
- mDummyMatrix.f[ 0] = PVRTXMUL(( PVRTXMUL(mIn.f[ 5], mIn.f[10]) - PVRTXMUL(mIn.f[ 9], mIn.f[ 6]) ), det_1);
- mDummyMatrix.f[ 1] = - PVRTXMUL(( PVRTXMUL(mIn.f[ 1], mIn.f[10]) - PVRTXMUL(mIn.f[ 9], mIn.f[ 2]) ), det_1);
- mDummyMatrix.f[ 2] = PVRTXMUL(( PVRTXMUL(mIn.f[ 1], mIn.f[ 6]) - PVRTXMUL(mIn.f[ 5], mIn.f[ 2]) ), det_1);
- mDummyMatrix.f[ 4] = - PVRTXMUL(( PVRTXMUL(mIn.f[ 4], mIn.f[10]) - PVRTXMUL(mIn.f[ 8], mIn.f[ 6]) ), det_1);
- mDummyMatrix.f[ 5] = PVRTXMUL(( PVRTXMUL(mIn.f[ 0], mIn.f[10]) - PVRTXMUL(mIn.f[ 8], mIn.f[ 2]) ), det_1);
- mDummyMatrix.f[ 6] = - PVRTXMUL(( PVRTXMUL(mIn.f[ 0], mIn.f[ 6]) - PVRTXMUL(mIn.f[ 4], mIn.f[ 2]) ), det_1);
- mDummyMatrix.f[ 8] = PVRTXMUL(( PVRTXMUL(mIn.f[ 4], mIn.f[ 9]) - PVRTXMUL(mIn.f[ 8], mIn.f[ 5]) ), det_1);
- mDummyMatrix.f[ 9] = - PVRTXMUL(( PVRTXMUL(mIn.f[ 0], mIn.f[ 9]) - PVRTXMUL(mIn.f[ 8], mIn.f[ 1]) ), det_1);
- mDummyMatrix.f[10] = PVRTXMUL(( PVRTXMUL(mIn.f[ 0], mIn.f[ 5]) - PVRTXMUL(mIn.f[ 4], mIn.f[ 1]) ), det_1);
- /* Calculate -C * inverse(A) */
- mDummyMatrix.f[12] = - ( PVRTXMUL(mIn.f[12], mDummyMatrix.f[ 0]) + PVRTXMUL(mIn.f[13], mDummyMatrix.f[ 4]) + PVRTXMUL(mIn.f[14], mDummyMatrix.f[ 8]) );
- mDummyMatrix.f[13] = - ( PVRTXMUL(mIn.f[12], mDummyMatrix.f[ 1]) + PVRTXMUL(mIn.f[13], mDummyMatrix.f[ 5]) + PVRTXMUL(mIn.f[14], mDummyMatrix.f[ 9]) );
- mDummyMatrix.f[14] = - ( PVRTXMUL(mIn.f[12], mDummyMatrix.f[ 2]) + PVRTXMUL(mIn.f[13], mDummyMatrix.f[ 6]) + PVRTXMUL(mIn.f[14], mDummyMatrix.f[10]) );
- /* Fill in last row */
- mDummyMatrix.f[ 3] = PVRTF2X(0.0f);
- mDummyMatrix.f[ 7] = PVRTF2X(0.0f);
- mDummyMatrix.f[11] = PVRTF2X(0.0f);
- mDummyMatrix.f[15] = PVRTF2X(1.0f);
- }
- /* Copy contents of dummy matrix in pfMatrix */
- mOut = mDummyMatrix;
- }
- /*!***************************************************************************
- @Function PVRTMatrixInverseExX
- @Output mOut Inversed matrix
- @Input mIn Original matrix
- @Description Compute the inverse matrix of mIn.
- Uses a linear equation solver and the knowledge that M.M^-1=I.
- Use this fn to calculate the inverse of matrices that
- PVRTMatrixInverse() cannot.
- *****************************************************************************/
- void PVRTMatrixInverseExX(
- PVRTMATRIXx &mOut,
- const PVRTMATRIXx &mIn)
- {
- PVRTMATRIXx mTmp;
- int *ppfRows[4], pfRes[4], pfIn[20];
- int i, j;
- for (i = 0; i < 4; ++i)
- {
- ppfRows[i] = &pfIn[i * 5];
- }
- /* Solve 4 sets of 4 linear equations */
- for (i = 0; i < 4; ++i)
- {
- for (j = 0; j < 4; ++j)
- {
- ppfRows[j][0] = c_mIdentity.f[i + 4 * j];
- memcpy(&ppfRows[j][1], &mIn.f[j * 4], 4 * sizeof(float));
- }
- PVRTMatrixLinearEqSolveX(pfRes, (int**)ppfRows, 4);
- for(j = 0; j < 4; ++j)
- {
- mTmp.f[i + 4 * j] = pfRes[j];
- }
- }
- mOut = mTmp;
- }
- /*!***************************************************************************
- @Function PVRTMatrixLookAtLHX
- @Output mOut Look-at view matrix
- @Input vEye Position of the camera
- @Input vAt Point the camera is looking at
- @Input vUp Up direction for the camera
- @Description Create a look-at view matrix.
- *****************************************************************************/
- void PVRTMatrixLookAtLHX(
- PVRTMATRIXx &mOut,
- const PVRTVECTOR3x &vEye,
- const PVRTVECTOR3x &vAt,
- const PVRTVECTOR3x &vUp)
- {
- PVRTVECTOR3x f, vUpActual, s, u;
- PVRTMATRIXx t;
- f.x = vEye.x - vAt.x;
- f.y = vEye.y - vAt.y;
- f.z = vEye.z - vAt.z;
- PVRTMatrixVec3NormalizeX(f, f);
- PVRTMatrixVec3NormalizeX(vUpActual, vUp);
- PVRTMatrixVec3CrossProductX(s, f, vUpActual);
- PVRTMatrixVec3CrossProductX(u, s, f);
- mOut.f[ 0] = s.x;
- mOut.f[ 1] = u.x;
- mOut.f[ 2] = -f.x;
- mOut.f[ 3] = PVRTF2X(0.0f);
- mOut.f[ 4] = s.y;
- mOut.f[ 5] = u.y;
- mOut.f[ 6] = -f.y;
- mOut.f[ 7] = PVRTF2X(0.0f);
- mOut.f[ 8] = s.z;
- mOut.f[ 9] = u.z;
- mOut.f[10] = -f.z;
- mOut.f[11] = PVRTF2X(0.0f);
- mOut.f[12] = PVRTF2X(0.0f);
- mOut.f[13] = PVRTF2X(0.0f);
- mOut.f[14] = PVRTF2X(0.0f);
- mOut.f[15] = PVRTF2X(1.0f);
- PVRTMatrixTranslationX(t, -vEye.x, -vEye.y, -vEye.z);
- PVRTMatrixMultiplyX(mOut, t, mOut);
- }
- /*!***************************************************************************
- @Function PVRTMatrixLookAtRHX
- @Output mOut Look-at view matrix
- @Input vEye Position of the camera
- @Input vAt Point the camera is looking at
- @Input vUp Up direction for the camera
- @Description Create a look-at view matrix.
- *****************************************************************************/
- void PVRTMatrixLookAtRHX(
- PVRTMATRIXx &mOut,
- const PVRTVECTOR3x &vEye,
- const PVRTVECTOR3x &vAt,
- const PVRTVECTOR3x &vUp)
- {
- PVRTVECTOR3x f, vUpActual, s, u;
- PVRTMATRIXx t;
- f.x = vAt.x - vEye.x;
- f.y = vAt.y - vEye.y;
- f.z = vAt.z - vEye.z;
- PVRTMatrixVec3NormalizeX(f, f);
- PVRTMatrixVec3NormalizeX(vUpActual, vUp);
- PVRTMatrixVec3CrossProductX(s, f, vUpActual);
- PVRTMatrixVec3CrossProductX(u, s, f);
- mOut.f[ 0] = s.x;
- mOut.f[ 1] = u.x;
- mOut.f[ 2] = -f.x;
- mOut.f[ 3] = PVRTF2X(0.0f);
- mOut.f[ 4] = s.y;
- mOut.f[ 5] = u.y;
- mOut.f[ 6] = -f.y;
- mOut.f[ 7] = PVRTF2X(0.0f);
- mOut.f[ 8] = s.z;
- mOut.f[ 9] = u.z;
- mOut.f[10] = -f.z;
- mOut.f[11] = PVRTF2X(0.0f);
- mOut.f[12] = PVRTF2X(0.0f);
- mOut.f[13] = PVRTF2X(0.0f);
- mOut.f[14] = PVRTF2X(0.0f);
- mOut.f[15] = PVRTF2X(1.0f);
- PVRTMatrixTranslationX(t, -vEye.x, -vEye.y, -vEye.z);
- PVRTMatrixMultiplyX(mOut, t, mOut);
- }
- /*!***************************************************************************
- @Function PVRTMatrixPerspectiveFovLHX
- @Output mOut Perspective matrix
- @Input fFOVy Field of view
- @Input fAspect Aspect ratio
- @Input fNear Near clipping distance
- @Input fFar Far clipping distance
- @Input bRotate Should we rotate it ? (for upright screens)
- @Description Create a perspective matrix.
- *****************************************************************************/
- void PVRTMatrixPerspectiveFovLHX(
- PVRTMATRIXx &mOut,
- const int fFOVy,
- const int fAspect,
- const int fNear,
- const int fFar,
- const bool bRotate)
- {
- int f, fRealAspect;
- if (bRotate)
- fRealAspect = PVRTXDIV(PVRTF2X(1.0f), fAspect);
- else
- fRealAspect = fAspect;
- f = PVRTXDIV(PVRTF2X(1.0f), PVRTXTAN(PVRTXMUL(fFOVy, PVRTF2X(0.5f))));
- mOut.f[ 0] = PVRTXDIV(f, fRealAspect);
- mOut.f[ 1] = PVRTF2X(0.0f);
- mOut.f[ 2] = PVRTF2X(0.0f);
- mOut.f[ 3] = PVRTF2X(0.0f);
- mOut.f[ 4] = PVRTF2X(0.0f);
- mOut.f[ 5] = f;
- mOut.f[ 6] = PVRTF2X(0.0f);
- mOut.f[ 7] = PVRTF2X(0.0f);
- mOut.f[ 8] = PVRTF2X(0.0f);
- mOut.f[ 9] = PVRTF2X(0.0f);
- mOut.f[10] = PVRTXDIV(fFar, fFar - fNear);
- mOut.f[11] = PVRTF2X(1.0f);
- mOut.f[12] = PVRTF2X(0.0f);
- mOut.f[13] = PVRTF2X(0.0f);
- mOut.f[14] = -PVRTXMUL(PVRTXDIV(fFar, fFar - fNear), fNear);
- mOut.f[15] = PVRTF2X(0.0f);
- if (bRotate)
- {
- PVRTMATRIXx mRotation, mTemp = mOut;
- PVRTMatrixRotationZX(mRotation, PVRTF2X(90.0f*PVRT_PIf/180.0f));
- PVRTMatrixMultiplyX(mOut, mTemp, mRotation);
- }
- }
- /*!***************************************************************************
- @Function PVRTMatrixPerspectiveFovRHX
- @Output mOut Perspective matrix
- @Input fFOVy Field of view
- @Input fAspect Aspect ratio
- @Input fNear Near clipping distance
- @Input fFar Far clipping distance
- @Input bRotate Should we rotate it ? (for upright screens)
- @Description Create a perspective matrix.
- *****************************************************************************/
- void PVRTMatrixPerspectiveFovRHX(
- PVRTMATRIXx &mOut,
- const int fFOVy,
- const int fAspect,
- const int fNear,
- const int fFar,
- const bool bRotate)
- {
- int f;
- int fCorrectAspect = fAspect;
- if (bRotate)
- {
- fCorrectAspect = PVRTXDIV(PVRTF2X(1.0f), fAspect);
- }
- f = PVRTXDIV(PVRTF2X(1.0f), PVRTXTAN(PVRTXMUL(fFOVy, PVRTF2X(0.5f))));
- mOut.f[ 0] = PVRTXDIV(f, fCorrectAspect);
- mOut.f[ 1] = PVRTF2X(0.0f);
- mOut.f[ 2] = PVRTF2X(0.0f);
- mOut.f[ 3] = PVRTF2X(0.0f);
- mOut.f[ 4] = PVRTF2X(0.0f);
- mOut.f[ 5] = f;
- mOut.f[ 6] = PVRTF2X(0.0f);
- mOut.f[ 7] = PVRTF2X(0.0f);
- mOut.f[ 8] = PVRTF2X(0.0f);
- mOut.f[ 9] = PVRTF2X(0.0f);
- mOut.f[10] = PVRTXDIV(fFar + fNear, fNear - fFar);
- mOut.f[11] = PVRTF2X(-1.0f);
- mOut.f[12] = PVRTF2X(0.0f);
- mOut.f[13] = PVRTF2X(0.0f);
- mOut.f[14] = PVRTXMUL(PVRTXDIV(fFar, fNear - fFar), fNear) << 1; // Cheap 2x
- mOut.f[15] = PVRTF2X(0.0f);
- if (bRotate)
- {
- PVRTMATRIXx mRotation, mTemp = mOut;
- PVRTMatrixRotationZX(mRotation, PVRTF2X(-90.0f*PVRT_PIf/180.0f));
- PVRTMatrixMultiplyX(mOut, mTemp, mRotation);
- }
- }
- /*!***************************************************************************
- @Function PVRTMatrixOrthoLHX
- @Output mOut Orthographic matrix
- @Input w Width of the screen
- @Input h Height of the screen
- @Input zn Near clipping distance
- @Input zf Far clipping distance
- @Input bRotate Should we rotate it ? (for upright screens)
- @Description Create an orthographic matrix.
- *****************************************************************************/
- void PVRTMatrixOrthoLHX(
- PVRTMATRIXx &mOut,
- const int w,
- const int h,
- const int zn,
- const int zf,
- const bool bRotate)
- {
- int fCorrectW = w;
- int fCorrectH = h;
- if (bRotate)
- {
- fCorrectW = h;
- fCorrectH = w;
- }
- mOut.f[ 0] = PVRTXDIV(PVRTF2X(2.0f), fCorrectW);
- mOut.f[ 1] = PVRTF2X(0.0f);
- mOut.f[ 2] = PVRTF2X(0.0f);
- mOut.f[ 3] = PVRTF2X(0.0f);
- mOut.f[ 4] = PVRTF2X(0.0f);
- mOut.f[ 5] = PVRTXDIV(PVRTF2X(2.0f), fCorrectH);
- mOut.f[ 6] = PVRTF2X(0.0f);
- mOut.f[ 7] = PVRTF2X(0.0f);
- mOut.f[ 8] = PVRTF2X(0.0f);
- mOut.f[ 9] = PVRTF2X(0.0f);
- mOut.f[10] = PVRTXDIV(PVRTF2X(1.0f), zf - zn);
- mOut.f[11] = PVRTXDIV(zn, zn - zf);
- mOut.f[12] = PVRTF2X(0.0f);
- mOut.f[13] = PVRTF2X(0.0f);
- mOut.f[14] = PVRTF2X(0.0f);
- mOut.f[15] = PVRTF2X(1.0f);
- if (bRotate)
- {
- PVRTMATRIXx mRotation, mTemp = mOut;
- PVRTMatrixRotationZX(mRotation, PVRTF2X(-90.0f*PVRT_PIf/180.0f));
- PVRTMatrixMultiplyX(mOut, mRotation, mTemp);
- }
- }
- /*!***************************************************************************
- @Function PVRTMatrixOrthoRHX
- @Output mOut Orthographic matrix
- @Input w Width of the screen
- @Input h Height of the screen
- @Input zn Near clipping distance
- @Input zf Far clipping distance
- @Input bRotate Should we rotate it ? (for upright screens)
- @Description Create an orthographic matrix.
- *****************************************************************************/
- void PVRTMatrixOrthoRHX(
- PVRTMATRIXx &mOut,
- const int w,
- const int h,
- const int zn,
- const int zf,
- const bool bRotate)
- {
- int fCorrectW = w;
- int fCorrectH = h;
- if (bRotate)
- {
- fCorrectW = h;
- fCorrectH = w;
- }
- mOut.f[ 0] = PVRTXDIV(PVRTF2X(2.0f), fCorrectW);
- mOut.f[ 1] = PVRTF2X(0.0f);
- mOut.f[ 2] = PVRTF2X(0.0f);
- mOut.f[ 3] = PVRTF2X(0.0f);
- mOut.f[ 4] = PVRTF2X(0.0f);
- mOut.f[ 5] = PVRTXDIV(PVRTF2X(2.0f), fCorrectH);
- mOut.f[ 6] = PVRTF2X(0.0f);
- mOut.f[ 7] = PVRTF2X(0.0f);
- mOut.f[ 8] = PVRTF2X(0.0f);
- mOut.f[ 9] = PVRTF2X(0.0f);
- mOut.f[10] = PVRTXDIV(PVRTF2X(1.0f), zn - zf);
- mOut.f[11] = PVRTXDIV(zn, zn - zf);
- mOut.f[12] = PVRTF2X(0.0f);
- mOut.f[13] = PVRTF2X(0.0f);
- mOut.f[14] = PVRTF2X(0.0f);
- mOut.f[15] = PVRTF2X(1.0f);
- if (bRotate)
- {
- PVRTMATRIXx mRotation, mTemp = mOut;
- PVRTMatrixRotationZX(mRotation, PVRTF2X(-90.0f*PVRT_PIf/180.0f));
- PVRTMatrixMultiplyX(mOut, mRotation, mTemp);
- }
- }
- /*!***************************************************************************
- @Function PVRTMatrixVec3LerpX
- @Output vOut Result of the interpolation
- @Input v1 First vector to interpolate from
- @Input v2 Second vector to interpolate form
- @Input s Coefficient of interpolation
- @Description This function performs the linear interpolation based on
- the following formula: V1 + s(V2-V1).
- *****************************************************************************/
- void PVRTMatrixVec3LerpX(
- PVRTVECTOR3x &vOut,
- const PVRTVECTOR3x &v1,
- const PVRTVECTOR3x &v2,
- const int s)
- {
- vOut.x = v1.x + PVRTXMUL(s, v2.x - v1.x);
- vOut.y = v1.y + PVRTXMUL(s, v2.y - v1.y);
- vOut.z = v1.z + PVRTXMUL(s, v2.z - v1.z);
- }
- /*!***************************************************************************
- @Function PVRTMatrixVec3DotProductX
- @Input v1 First vector
- @Input v2 Second vector
- @Return Dot product of the two vectors.
- @Description This function performs the dot product of the two
- supplied vectors.
- A single >> 16 shift could be applied to the final accumulated
- result however this runs the risk of overflow between the
- results of the intermediate additions.
- *****************************************************************************/
- int PVRTMatrixVec3DotProductX(
- const PVRTVECTOR3x &v1,
- const PVRTVECTOR3x &v2)
- {
- return (PVRTXMUL(v1.x, v2.x) + PVRTXMUL(v1.y, v2.y) + PVRTXMUL(v1.z, v2.z));
- }
- /*!***************************************************************************
- @Function PVRTMatrixVec3CrossProductX
- @Output vOut Cross product of the two vectors
- @Input v1 First vector
- @Input v2 Second vector
- @Description This function performs the cross product of the two
- supplied vectors.
- *****************************************************************************/
- void PVRTMatrixVec3CrossProductX(
- PVRTVECTOR3x &vOut,
- const PVRTVECTOR3x &v1,
- const PVRTVECTOR3x &v2)
- {
- PVRTVECTOR3x result;
- /* Perform calculation on a dummy VECTOR (result) */
- result.x = PVRTXMUL(v1.y, v2.z) - PVRTXMUL(v1.z, v2.y);
- result.y = PVRTXMUL(v1.z, v2.x) - PVRTXMUL(v1.x, v2.z);
- result.z = PVRTXMUL(v1.x, v2.y) - PVRTXMUL(v1.y, v2.x);
- /* Copy result in pOut */
- vOut = result;
- }
- /*!***************************************************************************
- @Function PVRTMatrixVec3NormalizeX
- @Output vOut Normalized vector
- @Input vIn Vector to normalize
- @Description Normalizes the supplied vector.
- The square root function is currently still performed
- in floating-point.
- Original vector is scaled down prior to be normalized in
- order to avoid overflow issues.
- ****************************************************************************/
- void PVRTMatrixVec3NormalizeX(
- PVRTVECTOR3x &vOut,
- const PVRTVECTOR3x &vIn)
- {
- int f, n;
- PVRTVECTOR3x vTemp;
- /* Scale vector by uniform value */
- n = PVRTABS(vIn.x) + PVRTABS(vIn.y) + PVRTABS(vIn.z);
- vTemp.x = PVRTXDIV(vIn.x, n);
- vTemp.y = PVRTXDIV(vIn.y, n);
- vTemp.z = PVRTXDIV(vIn.z, n);
- /* Calculate x2+y2+z2/sqrt(x2+y2+z2) */
- f = PVRTMatrixVec3DotProductX(vTemp, vTemp);
- f = PVRTXDIV(PVRTF2X(1.0f), PVRTF2X(sqrt(PVRTX2F(f))));
- /* Multiply vector components by f */
- vOut.x = PVRTXMUL(vTemp.x, f);
- vOut.y = PVRTXMUL(vTemp.y, f);
- vOut.z = PVRTXMUL(vTemp.z, f);
- }
- /*!***************************************************************************
- @Function PVRTMatrixVec3LengthX
- @Input vIn Vector to get the length of
- @Return The length of the vector
- @Description Gets the length of the supplied vector
- *****************************************************************************/
- int PVRTMatrixVec3LengthX(
- const PVRTVECTOR3x &vIn)
- {
- int temp;
- temp = PVRTXMUL(vIn.x,vIn.x) + PVRTXMUL(vIn.y,vIn.y) + PVRTXMUL(vIn.z,vIn.z);
- return PVRTF2X(sqrt(PVRTX2F(temp)));
- }
- /*!***************************************************************************
- @Function PVRTMatrixLinearEqSolveX
- @Input pSrc 2D array of floats. 4 Eq linear problem is 5x4
- matrix, constants in first column
- @Input nCnt Number of equations to solve
- @Output pRes Result
- @Description Solves 'nCnt' simultaneous equations of 'nCnt' variables.
- pRes should be an array large enough to contain the
- results: the values of the 'nCnt' variables.
- This fn recursively uses Gaussian Elimination.
- *****************************************************************************/
- void PVRTMatrixLinearEqSolveX(
- int * const pRes,
- int ** const pSrc,
- const int nCnt)
- {
- int i, j, k;
- int f;
- if (nCnt == 1)
- {
- _ASSERT(pSrc[0][1] != 0);
- pRes[0] = PVRTXDIV(pSrc[0][0], pSrc[0][1]);
- return;
- }
- // Loop backwards in an attempt avoid the need to swap rows
- i = nCnt;
- while(i)
- {
- --i;
- if(pSrc[i][nCnt] != PVRTF2X(0.0f))
- {
- // Row i can be used to zero the other rows; let's move it to the bottom
- if(i != (nCnt-1))
- {
- for(j = 0; j <= nCnt; ++j)
- {
- // Swap the two values
- f = pSrc[nCnt-1][j];
- pSrc[nCnt-1][j] = pSrc[i][j];
- pSrc[i][j] = f;
- }
- }
- // Now zero the last columns of the top rows
- for(j = 0; j < (nCnt-1); ++j)
- {
- _ASSERT(pSrc[nCnt-1][nCnt] != PVRTF2X(0.0f));
- f = PVRTXDIV(pSrc[j][nCnt], pSrc[nCnt-1][nCnt]);
- // No need to actually calculate a zero for the final column
- for(k = 0; k < nCnt; ++k)
- {
- pSrc[j][k] -= PVRTXMUL(f, pSrc[nCnt-1][k]);
- }
- }
- break;
- }
- }
- // Solve the top-left sub matrix
- PVRTMatrixLinearEqSolveX(pRes, pSrc, nCnt - 1);
- // Now calc the solution for the bottom row
- f = pSrc[nCnt-1][0];
- for(k = 1; k < nCnt; ++k)
- {
- f -= PVRTXMUL(pSrc[nCnt-1][k], pRes[k-1]);
- }
- _ASSERT(pSrc[nCnt-1][nCnt] != PVRTF2X(0));
- f = PVRTXDIV(f, pSrc[nCnt-1][nCnt]);
- pRes[nCnt-1] = f;
- }
- /*****************************************************************************
- End of file (PVRTMatrixX.cpp)
- *****************************************************************************/
|