/******************************************************************************
|
|
@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)
|
*****************************************************************************/
|