123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- /******************************************************************************
- @File PVRTVector.cpp
- @Title PVRTVector
- @Version
- @Copyright Copyright (C) Imagination Technologies Limited.
- @Platform ANSI compatible
- @Description Vector and matrix mathematics library
- ******************************************************************************/
- #include "PVRTVector.h"
- #include <math.h>
- /*!***************************************************************************
- ** PVRTVec2 2 component vector
- ****************************************************************************/
- /*!***************************************************************************
- @Function PVRTVec2
- @Input v3Vec a Vec3
- @Description Constructor from a Vec3
- *****************************************************************************/
- PVRTVec2::PVRTVec2(const PVRTVec3& vec3)
- {
- x = vec3.x; y = vec3.y;
- }
- /*!***************************************************************************
- ** PVRTVec3 3 component vector
- ****************************************************************************/
- /*!***************************************************************************
- @Function PVRTVec3
- @Input v4Vec a PVRTVec4
- @Description Constructor from a PVRTVec4
- *****************************************************************************/
- PVRTVec3::PVRTVec3(const PVRTVec4& vec4)
- {
- x = vec4.x; y = vec4.y; z = vec4.z;
- }
- /*!***************************************************************************
- @Function *
- @Input rhs a PVRTMat3
- @Returns result of multiplication
- @Description matrix multiplication operator PVRTVec3 and PVRTMat3
- ****************************************************************************/
- PVRTVec3 PVRTVec3::operator*(const PVRTMat3& rhs) const
- {
- PVRTVec3 out;
- out.x = VERTTYPEMUL(x,rhs.f[0])+VERTTYPEMUL(y,rhs.f[1])+VERTTYPEMUL(z,rhs.f[2]);
- out.y = VERTTYPEMUL(x,rhs.f[3])+VERTTYPEMUL(y,rhs.f[4])+VERTTYPEMUL(z,rhs.f[5]);
- out.z = VERTTYPEMUL(x,rhs.f[6])+VERTTYPEMUL(y,rhs.f[7])+VERTTYPEMUL(z,rhs.f[8]);
- return out;
- }
- /*!***************************************************************************
- @Function *=
- @Input rhs a PVRTMat3
- @Returns result of multiplication and assignment
- @Description matrix multiplication and assignment operator for PVRTVec3 and PVRTMat3
- ****************************************************************************/
- PVRTVec3& PVRTVec3::operator*=(const PVRTMat3& rhs)
- {
- VERTTYPE tx = VERTTYPEMUL(x,rhs.f[0])+VERTTYPEMUL(y,rhs.f[1])+VERTTYPEMUL(z,rhs.f[2]);
- VERTTYPE ty = VERTTYPEMUL(x,rhs.f[3])+VERTTYPEMUL(y,rhs.f[4])+VERTTYPEMUL(z,rhs.f[5]);
- z = VERTTYPEMUL(x,rhs.f[6])+VERTTYPEMUL(y,rhs.f[7])+VERTTYPEMUL(z,rhs.f[8]);
- x = tx;
- y = ty;
- return *this;
- }
- /*!***************************************************************************
- ** PVRTVec4 4 component vector
- ****************************************************************************/
- /*!***************************************************************************
- @Function *
- @Input rhs a PVRTMat4
- @Returns result of multiplication
- @Description matrix multiplication operator PVRTVec4 and PVRTMat4
- ****************************************************************************/
- PVRTVec4 PVRTVec4::operator*(const PVRTMat4& rhs) const
- {
- PVRTVec4 out;
- out.x = VERTTYPEMUL(x,rhs.f[0])+VERTTYPEMUL(y,rhs.f[1])+VERTTYPEMUL(z,rhs.f[2])+VERTTYPEMUL(w,rhs.f[3]);
- out.y = VERTTYPEMUL(x,rhs.f[4])+VERTTYPEMUL(y,rhs.f[5])+VERTTYPEMUL(z,rhs.f[6])+VERTTYPEMUL(w,rhs.f[7]);
- out.z = VERTTYPEMUL(x,rhs.f[8])+VERTTYPEMUL(y,rhs.f[9])+VERTTYPEMUL(z,rhs.f[10])+VERTTYPEMUL(w,rhs.f[11]);
- out.w = VERTTYPEMUL(x,rhs.f[12])+VERTTYPEMUL(y,rhs.f[13])+VERTTYPEMUL(z,rhs.f[14])+VERTTYPEMUL(w,rhs.f[15]);
- return out;
- }
- /*!***************************************************************************
- @Function *=
- @Input rhs a PVRTMat4
- @Returns result of multiplication and assignment
- @Description matrix multiplication and assignment operator for PVRTVec4 and PVRTMat4
- ****************************************************************************/
- PVRTVec4& PVRTVec4::operator*=(const PVRTMat4& rhs)
- {
- VERTTYPE tx = VERTTYPEMUL(x,rhs.f[0])+VERTTYPEMUL(y,rhs.f[1])+VERTTYPEMUL(z,rhs.f[2])+VERTTYPEMUL(w,rhs.f[3]);
- VERTTYPE ty = VERTTYPEMUL(x,rhs.f[4])+VERTTYPEMUL(y,rhs.f[5])+VERTTYPEMUL(z,rhs.f[6])+VERTTYPEMUL(w,rhs.f[7]);
- VERTTYPE tz = VERTTYPEMUL(x,rhs.f[8])+VERTTYPEMUL(y,rhs.f[9])+VERTTYPEMUL(z,rhs.f[10])+VERTTYPEMUL(w,rhs.f[11]);
- w = VERTTYPEMUL(x,rhs.f[12])+VERTTYPEMUL(y,rhs.f[13])+VERTTYPEMUL(z,rhs.f[14])+VERTTYPEMUL(w,rhs.f[15]);
- x = tx;
- y = ty;
- z = tz;
- return *this;
- }
- /*!***************************************************************************
- ** PVRTMat3 3x3 matrix
- ****************************************************************************/
- /*!***************************************************************************
- @Function PVRTMat3
- @Input mat a PVRTMat4
- @Description constructor to form a PVRTMat3 from a PVRTMat4
- ****************************************************************************/
- PVRTMat3::PVRTMat3(const PVRTMat4& mat)
- {
- VERTTYPE *dest = (VERTTYPE*)f, *src = (VERTTYPE*)mat.f;
- for(int i=0;i<3;i++)
- {
- for(int j=0;j<3;j++)
- {
- (*dest++) = (*src++);
- }
- src++;
- }
- }
- /*!***************************************************************************
- @Function RotationX
- @Input angle the angle of rotation
- @Returns rotation matrix
- @Description generates a 3x3 rotation matrix about the X axis
- ****************************************************************************/
- PVRTMat3 PVRTMat3::RotationX(VERTTYPE angle)
- {
- PVRTMat4 out;
- PVRTMatrixRotationX(out,angle);
- return PVRTMat3(out);
- }
- /*!***************************************************************************
- @Function RotationY
- @Input angle the angle of rotation
- @Returns rotation matrix
- @Description generates a 3x3 rotation matrix about the Y axis
- ****************************************************************************/
- PVRTMat3 PVRTMat3::RotationY(VERTTYPE angle)
- {
- PVRTMat4 out;
- PVRTMatrixRotationY(out,angle);
- return PVRTMat3(out);
- }
- /*!***************************************************************************
- @Function RotationZ
- @Input angle the angle of rotation
- @Returns rotation matrix
- @Description generates a 3x3 rotation matrix about the Z axis
- ****************************************************************************/
- PVRTMat3 PVRTMat3::RotationZ(VERTTYPE angle)
- {
- PVRTMat4 out;
- PVRTMatrixRotationZ(out,angle);
- return PVRTMat3(out);
- }
- /*!***************************************************************************
- ** PVRTMat4 4x4 matrix
- ****************************************************************************/
- /*!***************************************************************************
- @Function RotationX
- @Input angle the angle of rotation
- @Returns rotation matrix
- @Description generates a 4x4 rotation matrix about the X axis
- ****************************************************************************/
- PVRTMat4 PVRTMat4::RotationX(VERTTYPE angle)
- {
- PVRTMat4 out;
- PVRTMatrixRotationX(out,angle);
- return out;
- }
- /*!***************************************************************************
- @Function RotationY
- @Input angle the angle of rotation
- @Returns rotation matrix
- @Description generates a 4x4 rotation matrix about the Y axis
- ****************************************************************************/
- PVRTMat4 PVRTMat4::RotationY(VERTTYPE angle)
- {
- PVRTMat4 out;
- PVRTMatrixRotationY(out,angle);
- return out;
- }
- /*!***************************************************************************
- @Function RotationZ
- @Input angle the angle of rotation
- @Returns rotation matrix
- @Description generates a 4x4 rotation matrix about the Z axis
- ****************************************************************************/
- PVRTMat4 PVRTMat4::RotationZ(VERTTYPE angle)
- {
- PVRTMat4 out;
- PVRTMatrixRotationZ(out,angle);
- return out;
- }
- /*!***************************************************************************
- @Function *
- @Input rhs another PVRTMat4
- @Returns result of multiplication
- @Description Matrix multiplication of two 4x4 matrices.
- *****************************************************************************/
- PVRTMat4 PVRTMat4::operator*(const PVRTMat4& rhs) const
- {
- PVRTMat4 out;
- // col 1
- out.f[0] = VERTTYPEMUL(f[0],rhs.f[0])+VERTTYPEMUL(f[4],rhs.f[1])+VERTTYPEMUL(f[8],rhs.f[2])+VERTTYPEMUL(f[12],rhs.f[3]);
- out.f[1] = VERTTYPEMUL(f[1],rhs.f[0])+VERTTYPEMUL(f[5],rhs.f[1])+VERTTYPEMUL(f[9],rhs.f[2])+VERTTYPEMUL(f[13],rhs.f[3]);
- out.f[2] = VERTTYPEMUL(f[2],rhs.f[0])+VERTTYPEMUL(f[6],rhs.f[1])+VERTTYPEMUL(f[10],rhs.f[2])+VERTTYPEMUL(f[14],rhs.f[3]);
- out.f[3] = VERTTYPEMUL(f[3],rhs.f[0])+VERTTYPEMUL(f[7],rhs.f[1])+VERTTYPEMUL(f[11],rhs.f[2])+VERTTYPEMUL(f[15],rhs.f[3]);
- // col 2
- out.f[4] = VERTTYPEMUL(f[0],rhs.f[4])+VERTTYPEMUL(f[4],rhs.f[5])+VERTTYPEMUL(f[8],rhs.f[6])+VERTTYPEMUL(f[12],rhs.f[7]);
- out.f[5] = VERTTYPEMUL(f[1],rhs.f[4])+VERTTYPEMUL(f[5],rhs.f[5])+VERTTYPEMUL(f[9],rhs.f[6])+VERTTYPEMUL(f[13],rhs.f[7]);
- out.f[6] = VERTTYPEMUL(f[2],rhs.f[4])+VERTTYPEMUL(f[6],rhs.f[5])+VERTTYPEMUL(f[10],rhs.f[6])+VERTTYPEMUL(f[14],rhs.f[7]);
- out.f[7] = VERTTYPEMUL(f[3],rhs.f[4])+VERTTYPEMUL(f[7],rhs.f[5])+VERTTYPEMUL(f[11],rhs.f[6])+VERTTYPEMUL(f[15],rhs.f[7]);
- // col3
- out.f[8] = VERTTYPEMUL(f[0],rhs.f[8])+VERTTYPEMUL(f[4],rhs.f[9])+VERTTYPEMUL(f[8],rhs.f[10])+VERTTYPEMUL(f[12],rhs.f[11]);
- out.f[9] = VERTTYPEMUL(f[1],rhs.f[8])+VERTTYPEMUL(f[5],rhs.f[9])+VERTTYPEMUL(f[9],rhs.f[10])+VERTTYPEMUL(f[13],rhs.f[11]);
- out.f[10] = VERTTYPEMUL(f[2],rhs.f[8])+VERTTYPEMUL(f[6],rhs.f[9])+VERTTYPEMUL(f[10],rhs.f[10])+VERTTYPEMUL(f[14],rhs.f[11]);
- out.f[11] = VERTTYPEMUL(f[3],rhs.f[8])+VERTTYPEMUL(f[7],rhs.f[9])+VERTTYPEMUL(f[11],rhs.f[10])+VERTTYPEMUL(f[15],rhs.f[11]);
- // col3
- out.f[12] = VERTTYPEMUL(f[0],rhs.f[12])+VERTTYPEMUL(f[4],rhs.f[13])+VERTTYPEMUL(f[8],rhs.f[14])+VERTTYPEMUL(f[12],rhs.f[15]);
- out.f[13] = VERTTYPEMUL(f[1],rhs.f[12])+VERTTYPEMUL(f[5],rhs.f[13])+VERTTYPEMUL(f[9],rhs.f[14])+VERTTYPEMUL(f[13],rhs.f[15]);
- out.f[14] = VERTTYPEMUL(f[2],rhs.f[12])+VERTTYPEMUL(f[6],rhs.f[13])+VERTTYPEMUL(f[10],rhs.f[14])+VERTTYPEMUL(f[14],rhs.f[15]);
- out.f[15] = VERTTYPEMUL(f[3],rhs.f[12])+VERTTYPEMUL(f[7],rhs.f[13])+VERTTYPEMUL(f[11],rhs.f[14])+VERTTYPEMUL(f[15],rhs.f[15]);
- return out;
- }
- /*!***************************************************************************
- @Function inverse
- @Returns inverse mat4
- @Description Calculates multiplicative inverse of this matrix
- The matrix must be of the form :
- A 0
- C 1
- Where A is a 3x3 matrix and C is a 1x3 matrix.
- *****************************************************************************/
- PVRTMat4 PVRTMat4::inverse() const
- {
- PVRTMat4 out;
- VERTTYPE det_1;
- VERTTYPE 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 = f2vt(0.0);
- temp = VERTTYPEMUL(VERTTYPEMUL(f[ 0], f[ 5]), f[10]);
- if (temp >= 0) pos += temp; else neg += temp;
- temp = VERTTYPEMUL(VERTTYPEMUL(f[ 4], f[ 9]), f[ 2]);
- if (temp >= 0) pos += temp; else neg += temp;
- temp = VERTTYPEMUL(VERTTYPEMUL(f[ 8], f[ 1]), f[ 6]);
- if (temp >= 0) pos += temp; else neg += temp;
- temp = VERTTYPEMUL(VERTTYPEMUL(-f[ 8], f[ 5]), f[ 2]);
- if (temp >= 0) pos += temp; else neg += temp;
- temp = VERTTYPEMUL(VERTTYPEMUL(-f[ 4], f[ 1]), f[10]);
- if (temp >= 0) pos += temp; else neg += temp;
- temp = VERTTYPEMUL(VERTTYPEMUL(-f[ 0], f[ 9]), f[ 6]);
- if (temp >= 0) pos += temp; else neg += temp;
- det_1 = pos + neg;
- /* Is the submatrix A singular? */
- if (det_1 == f2vt(0.0)) //|| (VERTTYPEABS(det_1 / (pos - neg)) < 1.0e-15)
- {
- /* Matrix M has no inverse */
- _RPT0(_CRT_WARN, "Matrix has no inverse : singular matrix\n");
- }
- else
- {
- /* Calculate inverse(A) = adj(A) / det(A) */
- //det_1 = 1.0 / det_1;
- det_1 = VERTTYPEDIV(f2vt(1.0f), det_1);
- out.f[ 0] = VERTTYPEMUL(( VERTTYPEMUL(f[ 5], f[10]) - VERTTYPEMUL(f[ 9], f[ 6]) ), det_1);
- out.f[ 1] = - VERTTYPEMUL(( VERTTYPEMUL(f[ 1], f[10]) - VERTTYPEMUL(f[ 9], f[ 2]) ), det_1);
- out.f[ 2] = VERTTYPEMUL(( VERTTYPEMUL(f[ 1], f[ 6]) - VERTTYPEMUL(f[ 5], f[ 2]) ), det_1);
- out.f[ 4] = - VERTTYPEMUL(( VERTTYPEMUL(f[ 4], f[10]) - VERTTYPEMUL(f[ 8], f[ 6]) ), det_1);
- out.f[ 5] = VERTTYPEMUL(( VERTTYPEMUL(f[ 0], f[10]) - VERTTYPEMUL(f[ 8], f[ 2]) ), det_1);
- out.f[ 6] = - VERTTYPEMUL(( VERTTYPEMUL(f[ 0], f[ 6]) - VERTTYPEMUL(f[ 4], f[ 2]) ), det_1);
- out.f[ 8] = VERTTYPEMUL(( VERTTYPEMUL(f[ 4], f[ 9]) - VERTTYPEMUL(f[ 8], f[ 5]) ), det_1);
- out.f[ 9] = - VERTTYPEMUL(( VERTTYPEMUL(f[ 0], f[ 9]) - VERTTYPEMUL(f[ 8], f[ 1]) ), det_1);
- out.f[10] = VERTTYPEMUL(( VERTTYPEMUL(f[ 0], f[ 5]) - VERTTYPEMUL(f[ 4], f[ 1]) ), det_1);
- /* Calculate -C * inverse(A) */
- out.f[12] = - ( VERTTYPEMUL(f[12], out.f[ 0]) + VERTTYPEMUL(f[13], out.f[ 4]) + VERTTYPEMUL(f[14], out.f[ 8]) );
- out.f[13] = - ( VERTTYPEMUL(f[12], out.f[ 1]) + VERTTYPEMUL(f[13], out.f[ 5]) + VERTTYPEMUL(f[14], out.f[ 9]) );
- out.f[14] = - ( VERTTYPEMUL(f[12], out.f[ 2]) + VERTTYPEMUL(f[13], out.f[ 6]) + VERTTYPEMUL(f[14], out.f[10]) );
- /* Fill in last row */
- out.f[ 3] = f2vt(0.0f);
- out.f[ 7] = f2vt(0.0f);
- out.f[11] = f2vt(0.0f);
- out.f[15] = f2vt(1.0f);
- }
- return out;
- }
- /*!***************************************************************************
- @Function PVRTLinearEqSolve
- @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 PVRTLinearEqSolve(VERTTYPE * const pRes, VERTTYPE ** const pSrc, const int nCnt)
- {
- int i, j, k;
- VERTTYPE f;
- if (nCnt == 1)
- {
- _ASSERT(pSrc[0][1] != 0);
- pRes[0] = VERTTYPEDIV(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] != f2vt(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] != f2vt(0.0f));
- f = VERTTYPEDIV(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] -= VERTTYPEMUL(f, pSrc[nCnt-1][k]);
- }
- }
- break;
- }
- }
- // Solve the top-left sub matrix
- PVRTLinearEqSolve(pRes, pSrc, nCnt - 1);
- // Now calc the solution for the bottom row
- f = pSrc[nCnt-1][0];
- for(k = 1; k < nCnt; ++k)
- {
- f -= VERTTYPEMUL(pSrc[nCnt-1][k], pRes[k-1]);
- }
- _ASSERT(pSrc[nCnt-1][nCnt] != f2vt(0));
- f = VERTTYPEDIV(f, pSrc[nCnt-1][nCnt]);
- pRes[nCnt-1] = f;
- }
- /*****************************************************************************
- End of file (PVRTVector.cpp)
- *****************************************************************************/
|