| /****************************************************************************** | |
| @File PVRTMatrixF.cpp | |
| @Title PVRTMatrixF | |
| @Version | |
| @Copyright Copyright (c) Imagination Technologies Limited. | |
| @Platform ANSI compatible | |
| @Description Set of mathematical functions involving matrices, vectors and | |
| quaternions. The general matrix format used is directly compatible | |
| with, for example, both DirectX and OpenGL. For the reasons why, | |
| read this: | |
| http://research.microsoft.com/~hollasch/cgindex/math/matrix/column-vec.html | |
| ******************************************************************************/ | |
| #include "PVRTGlobal.h" | |
| #include <math.h> | |
| #include <string.h> | |
| #include "PVRTFixedPoint.h" // Only needed for trig function float lookups | |
| #include "PVRTMatrix.h" | |
| /**************************************************************************** | |
| ** Constants | |
| ****************************************************************************/ | |
| static const PVRTMATRIXf c_mIdentity = { | |
| { | |
| 1, 0, 0, 0, | |
| 0, 1, 0, 0, | |
| 0, 0, 1, 0, | |
| 0, 0, 0, 1 | |
| } | |
| }; | |
| /**************************************************************************** | |
| ** Functions | |
| ****************************************************************************/ | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixIdentityF | |
| @Output mOut Set to identity | |
| @Description Reset matrix to identity matrix. | |
| *****************************************************************************/ | |
| void PVRTMatrixIdentityF(PVRTMATRIXf &mOut) | |
| { | |
| mOut.f[ 0]=1.0f; mOut.f[ 4]=0.0f; mOut.f[ 8]=0.0f; mOut.f[12]=0.0f; | |
| mOut.f[ 1]=0.0f; mOut.f[ 5]=1.0f; mOut.f[ 9]=0.0f; mOut.f[13]=0.0f; | |
| mOut.f[ 2]=0.0f; mOut.f[ 6]=0.0f; mOut.f[10]=1.0f; mOut.f[14]=0.0f; | |
| mOut.f[ 3]=0.0f; mOut.f[ 7]=0.0f; mOut.f[11]=0.0f; mOut.f[15]=1.0f; | |
| } | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixMultiplyF | |
| @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. | |
| *****************************************************************************/ | |
| void PVRTMatrixMultiplyF( | |
| PVRTMATRIXf &mOut, | |
| const PVRTMATRIXf &mA, | |
| const PVRTMATRIXf &mB) | |
| { | |
| PVRTMATRIXf mRet; | |
| /* Perform calculation on a dummy matrix (mRet) */ | |
| mRet.f[ 0] = mA.f[ 0]*mB.f[ 0] + mA.f[ 1]*mB.f[ 4] + mA.f[ 2]*mB.f[ 8] + mA.f[ 3]*mB.f[12]; | |
| mRet.f[ 1] = mA.f[ 0]*mB.f[ 1] + mA.f[ 1]*mB.f[ 5] + mA.f[ 2]*mB.f[ 9] + mA.f[ 3]*mB.f[13]; | |
| mRet.f[ 2] = mA.f[ 0]*mB.f[ 2] + mA.f[ 1]*mB.f[ 6] + mA.f[ 2]*mB.f[10] + mA.f[ 3]*mB.f[14]; | |
| mRet.f[ 3] = mA.f[ 0]*mB.f[ 3] + mA.f[ 1]*mB.f[ 7] + mA.f[ 2]*mB.f[11] + mA.f[ 3]*mB.f[15]; | |
| mRet.f[ 4] = mA.f[ 4]*mB.f[ 0] + mA.f[ 5]*mB.f[ 4] + mA.f[ 6]*mB.f[ 8] + mA.f[ 7]*mB.f[12]; | |
| mRet.f[ 5] = mA.f[ 4]*mB.f[ 1] + mA.f[ 5]*mB.f[ 5] + mA.f[ 6]*mB.f[ 9] + mA.f[ 7]*mB.f[13]; | |
| mRet.f[ 6] = mA.f[ 4]*mB.f[ 2] + mA.f[ 5]*mB.f[ 6] + mA.f[ 6]*mB.f[10] + mA.f[ 7]*mB.f[14]; | |
| mRet.f[ 7] = mA.f[ 4]*mB.f[ 3] + mA.f[ 5]*mB.f[ 7] + mA.f[ 6]*mB.f[11] + mA.f[ 7]*mB.f[15]; | |
| mRet.f[ 8] = mA.f[ 8]*mB.f[ 0] + mA.f[ 9]*mB.f[ 4] + mA.f[10]*mB.f[ 8] + mA.f[11]*mB.f[12]; | |
| mRet.f[ 9] = mA.f[ 8]*mB.f[ 1] + mA.f[ 9]*mB.f[ 5] + mA.f[10]*mB.f[ 9] + mA.f[11]*mB.f[13]; | |
| mRet.f[10] = mA.f[ 8]*mB.f[ 2] + mA.f[ 9]*mB.f[ 6] + mA.f[10]*mB.f[10] + mA.f[11]*mB.f[14]; | |
| mRet.f[11] = mA.f[ 8]*mB.f[ 3] + mA.f[ 9]*mB.f[ 7] + mA.f[10]*mB.f[11] + mA.f[11]*mB.f[15]; | |
| mRet.f[12] = mA.f[12]*mB.f[ 0] + mA.f[13]*mB.f[ 4] + mA.f[14]*mB.f[ 8] + mA.f[15]*mB.f[12]; | |
| mRet.f[13] = mA.f[12]*mB.f[ 1] + mA.f[13]*mB.f[ 5] + mA.f[14]*mB.f[ 9] + mA.f[15]*mB.f[13]; | |
| mRet.f[14] = mA.f[12]*mB.f[ 2] + mA.f[13]*mB.f[ 6] + mA.f[14]*mB.f[10] + mA.f[15]*mB.f[14]; | |
| mRet.f[15] = mA.f[12]*mB.f[ 3] + mA.f[13]*mB.f[ 7] + mA.f[14]*mB.f[11] + mA.f[15]*mB.f[15]; | |
| /* Copy result to mOut */ | |
| mOut = mRet; | |
| } | |
| /*!*************************************************************************** | |
| @Function Name PVRTMatrixTranslationF | |
| @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 PVRTMatrixTranslationF( | |
| PVRTMATRIXf &mOut, | |
| const float fX, | |
| const float fY, | |
| const float fZ) | |
| { | |
| mOut.f[ 0]=1.0f; mOut.f[ 4]=0.0f; mOut.f[ 8]=0.0f; mOut.f[12]=fX; | |
| mOut.f[ 1]=0.0f; mOut.f[ 5]=1.0f; mOut.f[ 9]=0.0f; mOut.f[13]=fY; | |
| mOut.f[ 2]=0.0f; mOut.f[ 6]=0.0f; mOut.f[10]=1.0f; mOut.f[14]=fZ; | |
| mOut.f[ 3]=0.0f; mOut.f[ 7]=0.0f; mOut.f[11]=0.0f; mOut.f[15]=1.0f; | |
| } | |
| /*!*************************************************************************** | |
| @Function Name PVRTMatrixScalingF | |
| @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 PVRTMatrixScalingF( | |
| PVRTMATRIXf &mOut, | |
| const float fX, | |
| const float fY, | |
| const float fZ) | |
| { | |
| mOut.f[ 0]=fX; mOut.f[ 4]=0.0f; mOut.f[ 8]=0.0f; mOut.f[12]=0.0f; | |
| mOut.f[ 1]=0.0f; mOut.f[ 5]=fY; mOut.f[ 9]=0.0f; mOut.f[13]=0.0f; | |
| mOut.f[ 2]=0.0f; mOut.f[ 6]=0.0f; mOut.f[10]=fZ; mOut.f[14]=0.0f; | |
| mOut.f[ 3]=0.0f; mOut.f[ 7]=0.0f; mOut.f[11]=0.0f; mOut.f[15]=1.0f; | |
| } | |
| /*!*************************************************************************** | |
| @Function Name PVRTMatrixRotationXF | |
| @Output mOut Rotation matrix | |
| @Input fAngle Angle of the rotation | |
| @Description Create an X rotation matrix mOut. | |
| *****************************************************************************/ | |
| void PVRTMatrixRotationXF( | |
| PVRTMATRIXf &mOut, | |
| const float fAngle) | |
| { | |
| float fCosine, fSine; | |
| /* Precompute cos and sin */ | |
| #if defined(BUILD_DX11) | |
| fCosine = (float)PVRTFCOS(-fAngle); | |
| fSine = (float)PVRTFSIN(-fAngle); | |
| #else | |
| fCosine = (float)PVRTFCOS(fAngle); | |
| fSine = (float)PVRTFSIN(fAngle); | |
| #endif | |
| /* Create the trigonometric matrix corresponding to X Rotation */ | |
| mOut.f[ 0]=1.0f; mOut.f[ 4]=0.0f; mOut.f[ 8]=0.0f; mOut.f[12]=0.0f; | |
| mOut.f[ 1]=0.0f; mOut.f[ 5]=fCosine; mOut.f[ 9]=fSine; mOut.f[13]=0.0f; | |
| mOut.f[ 2]=0.0f; mOut.f[ 6]=-fSine; mOut.f[10]=fCosine; mOut.f[14]=0.0f; | |
| mOut.f[ 3]=0.0f; mOut.f[ 7]=0.0f; mOut.f[11]=0.0f; mOut.f[15]=1.0f; | |
| } | |
| /*!*************************************************************************** | |
| @Function Name PVRTMatrixRotationYF | |
| @Output mOut Rotation matrix | |
| @Input fAngle Angle of the rotation | |
| @Description Create an Y rotation matrix mOut. | |
| *****************************************************************************/ | |
| void PVRTMatrixRotationYF( | |
| PVRTMATRIXf &mOut, | |
| const float fAngle) | |
| { | |
| float fCosine, fSine; | |
| /* Precompute cos and sin */ | |
| #if defined(BUILD_DX11) | |
| fCosine = (float)PVRTFCOS(-fAngle); | |
| fSine = (float)PVRTFSIN(-fAngle); | |
| #else | |
| fCosine = (float)PVRTFCOS(fAngle); | |
| fSine = (float)PVRTFSIN(fAngle); | |
| #endif | |
| /* Create the trigonometric matrix corresponding to Y Rotation */ | |
| mOut.f[ 0]=fCosine; mOut.f[ 4]=0.0f; mOut.f[ 8]=-fSine; mOut.f[12]=0.0f; | |
| mOut.f[ 1]=0.0f; mOut.f[ 5]=1.0f; mOut.f[ 9]=0.0f; mOut.f[13]=0.0f; | |
| mOut.f[ 2]=fSine; mOut.f[ 6]=0.0f; mOut.f[10]=fCosine; mOut.f[14]=0.0f; | |
| mOut.f[ 3]=0.0f; mOut.f[ 7]=0.0f; mOut.f[11]=0.0f; mOut.f[15]=1.0f; | |
| } | |
| /*!*************************************************************************** | |
| @Function Name PVRTMatrixRotationZF | |
| @Output mOut Rotation matrix | |
| @Input fAngle Angle of the rotation | |
| @Description Create an Z rotation matrix mOut. | |
| *****************************************************************************/ | |
| void PVRTMatrixRotationZF( | |
| PVRTMATRIXf &mOut, | |
| const float fAngle) | |
| { | |
| float fCosine, fSine; | |
| /* Precompute cos and sin */ | |
| #if defined(BUILD_DX11) | |
| fCosine = (float)PVRTFCOS(-fAngle); | |
| fSine = (float)PVRTFSIN(-fAngle); | |
| #else | |
| fCosine = (float)PVRTFCOS(fAngle); | |
| fSine = (float)PVRTFSIN(fAngle); | |
| #endif | |
| /* Create the trigonometric matrix corresponding to Z Rotation */ | |
| mOut.f[ 0]=fCosine; mOut.f[ 4]=fSine; mOut.f[ 8]=0.0f; mOut.f[12]=0.0f; | |
| mOut.f[ 1]=-fSine; mOut.f[ 5]=fCosine; mOut.f[ 9]=0.0f; mOut.f[13]=0.0f; | |
| mOut.f[ 2]=0.0f; mOut.f[ 6]=0.0f; mOut.f[10]=1.0f; mOut.f[14]=0.0f; | |
| mOut.f[ 3]=0.0f; mOut.f[ 7]=0.0f; mOut.f[11]=0.0f; mOut.f[15]=1.0f; | |
| } | |
| /*!*************************************************************************** | |
| @Function Name PVRTMatrixTransposeF | |
| @Output mOut Transposed matrix | |
| @Input mIn Original matrix | |
| @Description Compute the transpose matrix of mIn. | |
| *****************************************************************************/ | |
| void PVRTMatrixTransposeF( | |
| PVRTMATRIXf &mOut, | |
| const PVRTMATRIXf &mIn) | |
| { | |
| PVRTMATRIXf 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 PVRTMatrixInverseF | |
| @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 PVRTMatrixInverseF( | |
| PVRTMATRIXf &mOut, | |
| const PVRTMATRIXf &mIn) | |
| { | |
| PVRTMATRIXf mDummyMatrix; | |
| double det_1; | |
| double 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.0; | |
| temp = mIn.f[ 0] * mIn.f[ 5] * mIn.f[10]; | |
| if (temp >= 0.0) pos += temp; else neg += temp; | |
| temp = mIn.f[ 4] * mIn.f[ 9] * mIn.f[ 2]; | |
| if (temp >= 0.0) pos += temp; else neg += temp; | |
| temp = mIn.f[ 8] * mIn.f[ 1] * mIn.f[ 6]; | |
| if (temp >= 0.0) pos += temp; else neg += temp; | |
| temp = -mIn.f[ 8] * mIn.f[ 5] * mIn.f[ 2]; | |
| if (temp >= 0.0) pos += temp; else neg += temp; | |
| temp = -mIn.f[ 4] * mIn.f[ 1] * mIn.f[10]; | |
| if (temp >= 0.0) pos += temp; else neg += temp; | |
| temp = -mIn.f[ 0] * mIn.f[ 9] * mIn.f[ 6]; | |
| if (temp >= 0.0) pos += temp; else neg += temp; | |
| det_1 = pos + neg; | |
| /* Is the submatrix A singular? */ | |
| if ((det_1 == 0.0) || (PVRTABS(det_1 / (pos - neg)) < 1.0e-15)) | |
| { | |
| /* 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; | |
| mDummyMatrix.f[ 0] = ( mIn.f[ 5] * mIn.f[10] - mIn.f[ 9] * mIn.f[ 6] ) * (float)det_1; | |
| mDummyMatrix.f[ 1] = - ( mIn.f[ 1] * mIn.f[10] - mIn.f[ 9] * mIn.f[ 2] ) * (float)det_1; | |
| mDummyMatrix.f[ 2] = ( mIn.f[ 1] * mIn.f[ 6] - mIn.f[ 5] * mIn.f[ 2] ) * (float)det_1; | |
| mDummyMatrix.f[ 4] = - ( mIn.f[ 4] * mIn.f[10] - mIn.f[ 8] * mIn.f[ 6] ) * (float)det_1; | |
| mDummyMatrix.f[ 5] = ( mIn.f[ 0] * mIn.f[10] - mIn.f[ 8] * mIn.f[ 2] ) * (float)det_1; | |
| mDummyMatrix.f[ 6] = - ( mIn.f[ 0] * mIn.f[ 6] - mIn.f[ 4] * mIn.f[ 2] ) * (float)det_1; | |
| mDummyMatrix.f[ 8] = ( mIn.f[ 4] * mIn.f[ 9] - mIn.f[ 8] * mIn.f[ 5] ) * (float)det_1; | |
| mDummyMatrix.f[ 9] = - ( mIn.f[ 0] * mIn.f[ 9] - mIn.f[ 8] * mIn.f[ 1] ) * (float)det_1; | |
| mDummyMatrix.f[10] = ( mIn.f[ 0] * mIn.f[ 5] - mIn.f[ 4] * mIn.f[ 1] ) * (float)det_1; | |
| /* Calculate -C * inverse(A) */ | |
| mDummyMatrix.f[12] = - ( mIn.f[12] * mDummyMatrix.f[ 0] + mIn.f[13] * mDummyMatrix.f[ 4] + mIn.f[14] * mDummyMatrix.f[ 8] ); | |
| mDummyMatrix.f[13] = - ( mIn.f[12] * mDummyMatrix.f[ 1] + mIn.f[13] * mDummyMatrix.f[ 5] + mIn.f[14] * mDummyMatrix.f[ 9] ); | |
| mDummyMatrix.f[14] = - ( mIn.f[12] * mDummyMatrix.f[ 2] + mIn.f[13] * mDummyMatrix.f[ 6] + mIn.f[14] * mDummyMatrix.f[10] ); | |
| /* Fill in last row */ | |
| mDummyMatrix.f[ 3] = 0.0f; | |
| mDummyMatrix.f[ 7] = 0.0f; | |
| mDummyMatrix.f[11] = 0.0f; | |
| mDummyMatrix.f[15] = 1.0f; | |
| } | |
| /* Copy contents of dummy matrix in pfMatrix */ | |
| mOut = mDummyMatrix; | |
| } | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixInverseExF | |
| @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 PVRTMatrixInverseExF( | |
| PVRTMATRIXf &mOut, | |
| const PVRTMATRIXf &mIn) | |
| { | |
| PVRTMATRIXf mTmp = {0}; | |
| float *ppfRows[4]; | |
| float pfRes[4]; | |
| float 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)); | |
| } | |
| PVRTMatrixLinearEqSolveF(pfRes, (float**)ppfRows, 4); | |
| for(j = 0; j < 4; ++j) | |
| { | |
| mTmp.f[i + 4 * j] = pfRes[j]; | |
| } | |
| } | |
| mOut = mTmp; | |
| } | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixLookAtLHF | |
| @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 PVRTMatrixLookAtLHF( | |
| PVRTMATRIXf &mOut, | |
| const PVRTVECTOR3f &vEye, | |
| const PVRTVECTOR3f &vAt, | |
| const PVRTVECTOR3f &vUp) | |
| { | |
| PVRTVECTOR3f f, s, u; | |
| PVRTMATRIXf t; | |
| f.x = vEye.x - vAt.x; | |
| f.y = vEye.y - vAt.y; | |
| f.z = vEye.z - vAt.z; | |
| PVRTMatrixVec3NormalizeF(f, f); | |
| PVRTMatrixVec3CrossProductF(s, f, vUp); | |
| PVRTMatrixVec3NormalizeF(s, s); | |
| PVRTMatrixVec3CrossProductF(u, s, f); | |
| PVRTMatrixVec3NormalizeF(u, u); | |
| mOut.f[ 0] = s.x; | |
| mOut.f[ 1] = u.x; | |
| mOut.f[ 2] = -f.x; | |
| mOut.f[ 3] = 0; | |
| mOut.f[ 4] = s.y; | |
| mOut.f[ 5] = u.y; | |
| mOut.f[ 6] = -f.y; | |
| mOut.f[ 7] = 0; | |
| mOut.f[ 8] = s.z; | |
| mOut.f[ 9] = u.z; | |
| mOut.f[10] = -f.z; | |
| mOut.f[11] = 0; | |
| mOut.f[12] = 0; | |
| mOut.f[13] = 0; | |
| mOut.f[14] = 0; | |
| mOut.f[15] = 1; | |
| PVRTMatrixTranslationF(t, -vEye.x, -vEye.y, -vEye.z); | |
| PVRTMatrixMultiplyF(mOut, t, mOut); | |
| } | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixLookAtRHF | |
| @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 PVRTMatrixLookAtRHF( | |
| PVRTMATRIXf &mOut, | |
| const PVRTVECTOR3f &vEye, | |
| const PVRTVECTOR3f &vAt, | |
| const PVRTVECTOR3f &vUp) | |
| { | |
| PVRTVECTOR3f f, s, u; | |
| PVRTMATRIXf t; | |
| f.x = vAt.x - vEye.x; | |
| f.y = vAt.y - vEye.y; | |
| f.z = vAt.z - vEye.z; | |
| PVRTMatrixVec3NormalizeF(f, f); | |
| PVRTMatrixVec3CrossProductF(s, f, vUp); | |
| PVRTMatrixVec3NormalizeF(s, s); | |
| PVRTMatrixVec3CrossProductF(u, s, f); | |
| PVRTMatrixVec3NormalizeF(u, u); | |
| mOut.f[ 0] = s.x; | |
| mOut.f[ 1] = u.x; | |
| mOut.f[ 2] = -f.x; | |
| mOut.f[ 3] = 0; | |
| mOut.f[ 4] = s.y; | |
| mOut.f[ 5] = u.y; | |
| mOut.f[ 6] = -f.y; | |
| mOut.f[ 7] = 0; | |
| mOut.f[ 8] = s.z; | |
| mOut.f[ 9] = u.z; | |
| mOut.f[10] = -f.z; | |
| mOut.f[11] = 0; | |
| mOut.f[12] = 0; | |
| mOut.f[13] = 0; | |
| mOut.f[14] = 0; | |
| mOut.f[15] = 1; | |
| PVRTMatrixTranslationF(t, -vEye.x, -vEye.y, -vEye.z); | |
| PVRTMatrixMultiplyF(mOut, t, mOut); | |
| } | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixPerspectiveFovLHF | |
| @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 PVRTMatrixPerspectiveFovLHF( | |
| PVRTMATRIXf &mOut, | |
| const float fFOVy, | |
| const float fAspect, | |
| const float fNear, | |
| const float fFar, | |
| const bool bRotate) | |
| { | |
| float f, n, fRealAspect; | |
| if (bRotate) | |
| fRealAspect = 1.0f / fAspect; | |
| else | |
| fRealAspect = fAspect; | |
| // cotangent(a) == 1.0f / tan(a); | |
| f = 1.0f / (float)PVRTFTAN(fFOVy * 0.5f); | |
| n = 1.0f / (fFar - fNear); | |
| mOut.f[ 0] = f / fRealAspect; | |
| mOut.f[ 1] = 0; | |
| mOut.f[ 2] = 0; | |
| mOut.f[ 3] = 0; | |
| mOut.f[ 4] = 0; | |
| mOut.f[ 5] = f; | |
| mOut.f[ 6] = 0; | |
| mOut.f[ 7] = 0; | |
| mOut.f[ 8] = 0; | |
| mOut.f[ 9] = 0; | |
| mOut.f[10] = fFar * n; | |
| mOut.f[11] = 1; | |
| mOut.f[12] = 0; | |
| mOut.f[13] = 0; | |
| mOut.f[14] = -fFar * fNear * n; | |
| mOut.f[15] = 0; | |
| if (bRotate) | |
| { | |
| PVRTMATRIXf mRotation, mTemp = mOut; | |
| PVRTMatrixRotationZF(mRotation, 90.0f*PVRT_PIf/180.0f); | |
| PVRTMatrixMultiplyF(mOut, mTemp, mRotation); | |
| } | |
| } | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixPerspectiveFovRHF | |
| @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 PVRTMatrixPerspectiveFovRHF( | |
| PVRTMATRIXf &mOut, | |
| const float fFOVy, | |
| const float fAspect, | |
| const float fNear, | |
| const float fFar, | |
| const bool bRotate) | |
| { | |
| float f, n, fRealAspect; | |
| if (bRotate) | |
| fRealAspect = 1.0f / fAspect; | |
| else | |
| fRealAspect = fAspect; | |
| // cotangent(a) == 1.0f / tan(a); | |
| f = 1.0f / (float)PVRTFTAN(fFOVy * 0.5f); | |
| n = 1.0f / (fNear - fFar); | |
| mOut.f[ 0] = f / fRealAspect; | |
| mOut.f[ 1] = 0; | |
| mOut.f[ 2] = 0; | |
| mOut.f[ 3] = 0; | |
| mOut.f[ 4] = 0; | |
| mOut.f[ 5] = f; | |
| mOut.f[ 6] = 0; | |
| mOut.f[ 7] = 0; | |
| mOut.f[ 8] = 0; | |
| mOut.f[ 9] = 0; | |
| mOut.f[10] = (fFar + fNear) * n; | |
| mOut.f[11] = -1; | |
| mOut.f[12] = 0; | |
| mOut.f[13] = 0; | |
| mOut.f[14] = (2 * fFar * fNear) * n; | |
| mOut.f[15] = 0; | |
| if (bRotate) | |
| { | |
| PVRTMATRIXf mRotation, mTemp = mOut; | |
| PVRTMatrixRotationZF(mRotation, -90.0f*PVRT_PIf/180.0f); | |
| PVRTMatrixMultiplyF(mOut, mTemp, mRotation); | |
| } | |
| } | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixOrthoLHF | |
| @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 PVRTMatrixOrthoLHF( | |
| PVRTMATRIXf &mOut, | |
| const float w, | |
| const float h, | |
| const float zn, | |
| const float zf, | |
| const bool bRotate) | |
| { | |
| mOut.f[ 0] = 2 / w; | |
| mOut.f[ 1] = 0; | |
| mOut.f[ 2] = 0; | |
| mOut.f[ 3] = 0; | |
| mOut.f[ 4] = 0; | |
| mOut.f[ 5] = 2 / h; | |
| mOut.f[ 6] = 0; | |
| mOut.f[ 7] = 0; | |
| mOut.f[ 8] = 0; | |
| mOut.f[ 9] = 0; | |
| mOut.f[10] = 1 / (zf - zn); | |
| mOut.f[11] = zn / (zn - zf); | |
| mOut.f[12] = 0; | |
| mOut.f[13] = 0; | |
| mOut.f[14] = 0; | |
| mOut.f[15] = 1; | |
| if (bRotate) | |
| { | |
| PVRTMATRIXf mRotation, mTemp = mOut; | |
| PVRTMatrixRotationZF(mRotation, -90.0f*PVRT_PIf/180.0f); | |
| PVRTMatrixMultiplyF(mOut, mRotation, mTemp); | |
| } | |
| } | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixOrthoRHF | |
| @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 PVRTMatrixOrthoRHF( | |
| PVRTMATRIXf &mOut, | |
| const float w, | |
| const float h, | |
| const float zn, | |
| const float zf, | |
| const bool bRotate) | |
| { | |
| mOut.f[ 0] = 2 / w; | |
| mOut.f[ 1] = 0; | |
| mOut.f[ 2] = 0; | |
| mOut.f[ 3] = 0; | |
| mOut.f[ 4] = 0; | |
| mOut.f[ 5] = 2 / h; | |
| mOut.f[ 6] = 0; | |
| mOut.f[ 7] = 0; | |
| mOut.f[ 8] = 0; | |
| mOut.f[ 9] = 0; | |
| mOut.f[10] = 1 / (zn - zf); | |
| mOut.f[11] = zn / (zn - zf); | |
| mOut.f[12] = 0; | |
| mOut.f[13] = 0; | |
| mOut.f[14] = 0; | |
| mOut.f[15] = 1; | |
| if (bRotate) | |
| { | |
| PVRTMATRIXf mRotation, mTemp = mOut; | |
| PVRTMatrixRotationZF(mRotation, -90.0f*PVRT_PIf/180.0f); | |
| PVRTMatrixMultiplyF(mOut, mRotation, mTemp); | |
| } | |
| } | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixVec3LerpF | |
| @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 PVRTMatrixVec3LerpF( | |
| PVRTVECTOR3f &vOut, | |
| const PVRTVECTOR3f &v1, | |
| const PVRTVECTOR3f &v2, | |
| const float s) | |
| { | |
| vOut.x = v1.x + s * (v2.x - v1.x); | |
| vOut.y = v1.y + s * (v2.y - v1.y); | |
| vOut.z = v1.z + s * (v2.z - v1.z); | |
| } | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixVec3DotProductF | |
| @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. | |
| *****************************************************************************/ | |
| float PVRTMatrixVec3DotProductF( | |
| const PVRTVECTOR3f &v1, | |
| const PVRTVECTOR3f &v2) | |
| { | |
| return (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); | |
| } | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixVec3CrossProductF | |
| @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 PVRTMatrixVec3CrossProductF( | |
| PVRTVECTOR3f &vOut, | |
| const PVRTVECTOR3f &v1, | |
| const PVRTVECTOR3f &v2) | |
| { | |
| PVRTVECTOR3f result; | |
| /* Perform calculation on a dummy VECTOR (result) */ | |
| result.x = v1.y * v2.z - v1.z * v2.y; | |
| result.y = v1.z * v2.x - v1.x * v2.z; | |
| result.z = v1.x * v2.y - v1.y * v2.x; | |
| /* Copy result in pOut */ | |
| vOut = result; | |
| } | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixVec3NormalizeF | |
| @Output vOut Normalized vector | |
| @Input vIn Vector to normalize | |
| @Description Normalizes the supplied vector. | |
| *****************************************************************************/ | |
| void PVRTMatrixVec3NormalizeF( | |
| PVRTVECTOR3f &vOut, | |
| const PVRTVECTOR3f &vIn) | |
| { | |
| float f; | |
| double temp; | |
| temp = (double)(vIn.x * vIn.x + vIn.y * vIn.y + vIn.z * vIn.z); | |
| temp = 1.0 / sqrt(temp); | |
| f = (float)temp; | |
| vOut.x = vIn.x * f; | |
| vOut.y = vIn.y * f; | |
| vOut.z = vIn.z * f; | |
| } | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixVec3LengthF | |
| @Input vIn Vector to get the length of | |
| @Return The length of the vector | |
| @Description Gets the length of the supplied vector. | |
| *****************************************************************************/ | |
| float PVRTMatrixVec3LengthF( | |
| const PVRTVECTOR3f &vIn) | |
| { | |
| double temp; | |
| temp = (double)(vIn.x * vIn.x + vIn.y * vIn.y + vIn.z * vIn.z); | |
| return (float) sqrt(temp); | |
| } | |
| /*!*************************************************************************** | |
| @Function PVRTMatrixLinearEqSolveF | |
| @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 PVRTMatrixLinearEqSolveF( | |
| float * const pRes, | |
| float ** const pSrc, // 2D array of floats. 4 Eq linear problem is 5x4 matrix, constants in first column. | |
| const int nCnt) | |
| { | |
| int i, j, k; | |
| float f; | |
| #if 0 | |
| /* | |
| Show the matrix in debug output | |
| */ | |
| _RPT1(_CRT_WARN, "LinearEqSolve(%d)\n", nCnt); | |
| for(i = 0; i < nCnt; ++i) | |
| { | |
| _RPT1(_CRT_WARN, "%.8f |", pSrc[i][0]); | |
| for(j = 1; j <= nCnt; ++j) | |
| _RPT1(_CRT_WARN, " %.8f", pSrc[i][j]); | |
| _RPT0(_CRT_WARN, "\n"); | |
| } | |
| #endif | |
| if(nCnt == 1) | |
| { | |
| _ASSERT(pSrc[0][1] != 0); | |
| pRes[0] = 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] != 0) | |
| { | |
| // 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] != 0); | |
| f = 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] -= f * pSrc[nCnt-1][k]; | |
| } | |
| } | |
| break; | |
| } | |
| } | |
| // Solve the top-left sub matrix | |
| PVRTMatrixLinearEqSolveF(pRes, pSrc, nCnt - 1); | |
| // Now calc the solution for the bottom row | |
| f = pSrc[nCnt-1][0]; | |
| for(k = 1; k < nCnt; ++k) | |
| { | |
| f -= pSrc[nCnt-1][k] * pRes[k-1]; | |
| } | |
| _ASSERT(pSrc[nCnt-1][nCnt] != 0); | |
| f /= pSrc[nCnt-1][nCnt]; | |
| pRes[nCnt-1] = f; | |
| #if 0 | |
| { | |
| float fCnt; | |
| /* | |
| Verify that the result is correct | |
| */ | |
| fCnt = 0; | |
| for(i = 1; i <= nCnt; ++i) | |
| fCnt += pSrc[nCnt-1][i] * pRes[i-1]; | |
| _ASSERT(abs(fCnt - pSrc[nCnt-1][0]) < 1e-3); | |
| } | |
| #endif | |
| } | |
| /***************************************************************************** | |
| End of file (PVRTMatrixF.cpp) | |
| *****************************************************************************/ | |