Home | History | Annotate | Download | only in Tools
      1 /******************************************************************************
      2 
      3  @File         PVRTVector.cpp
      4 
      5  @Title        PVRTVector
      6 
      7  @Version
      8 
      9  @Copyright    Copyright (c) Imagination Technologies Limited.
     10 
     11  @Platform     ANSI compatible
     12 
     13  @Description  Vector and matrix mathematics library
     14 
     15 ******************************************************************************/
     16 
     17 #include "PVRTVector.h"
     18 
     19 #include <math.h>
     20 
     21 /*!***************************************************************************
     22 ** PVRTVec2 2 component vector
     23 ****************************************************************************/
     24 
     25 /*!***************************************************************************
     26  @Function			PVRTVec2
     27  @Input				v3Vec a Vec3
     28  @Description		Constructor from a Vec3
     29  *****************************************************************************/
     30 	PVRTVec2::PVRTVec2(const PVRTVec3& vec3)
     31 	{
     32 		x = vec3.x; y = vec3.y;
     33 	}
     34 
     35 /*!***************************************************************************
     36 ** PVRTVec3 3 component vector
     37 ****************************************************************************/
     38 
     39 /*!***************************************************************************
     40  @Function			PVRTVec3
     41  @Input				v4Vec a PVRTVec4
     42  @Description		Constructor from a PVRTVec4
     43 *****************************************************************************/
     44 	PVRTVec3::PVRTVec3(const PVRTVec4& vec4)
     45 	{
     46 		x = vec4.x; y = vec4.y; z = vec4.z;
     47 	}
     48 
     49 /*!***************************************************************************
     50  @Function			*
     51  @Input				rhs a PVRTMat3
     52  @Returns			result of multiplication
     53  @Description		matrix multiplication operator PVRTVec3 and PVRTMat3
     54 ****************************************************************************/
     55 	PVRTVec3 PVRTVec3::operator*(const PVRTMat3& rhs) const
     56 	{
     57 		PVRTVec3 out;
     58 
     59 		out.x = VERTTYPEMUL(x,rhs.f[0])+VERTTYPEMUL(y,rhs.f[1])+VERTTYPEMUL(z,rhs.f[2]);
     60 		out.y = VERTTYPEMUL(x,rhs.f[3])+VERTTYPEMUL(y,rhs.f[4])+VERTTYPEMUL(z,rhs.f[5]);
     61 		out.z = VERTTYPEMUL(x,rhs.f[6])+VERTTYPEMUL(y,rhs.f[7])+VERTTYPEMUL(z,rhs.f[8]);
     62 
     63 		return out;
     64 	}
     65 
     66 /*!***************************************************************************
     67  @Function			*=
     68  @Input				rhs a PVRTMat3
     69  @Returns			result of multiplication and assignment
     70  @Description		matrix multiplication and assignment operator for PVRTVec3 and PVRTMat3
     71 ****************************************************************************/
     72 	PVRTVec3& PVRTVec3::operator*=(const PVRTMat3& rhs)
     73 	{
     74 		VERTTYPE tx = VERTTYPEMUL(x,rhs.f[0])+VERTTYPEMUL(y,rhs.f[1])+VERTTYPEMUL(z,rhs.f[2]);
     75 		VERTTYPE ty = VERTTYPEMUL(x,rhs.f[3])+VERTTYPEMUL(y,rhs.f[4])+VERTTYPEMUL(z,rhs.f[5]);
     76 		z = VERTTYPEMUL(x,rhs.f[6])+VERTTYPEMUL(y,rhs.f[7])+VERTTYPEMUL(z,rhs.f[8]);
     77 		x = tx;
     78 		y = ty;
     79 
     80 		return *this;
     81 	}
     82 
     83 /*!***************************************************************************
     84 ** PVRTVec4 4 component vector
     85 ****************************************************************************/
     86 
     87 /*!***************************************************************************
     88  @Function			*
     89  @Input				rhs a PVRTMat4
     90  @Returns			result of multiplication
     91  @Description		matrix multiplication operator PVRTVec4 and PVRTMat4
     92 ****************************************************************************/
     93 	PVRTVec4 PVRTVec4::operator*(const PVRTMat4& rhs) const
     94 	{
     95 		PVRTVec4 out;
     96 		out.x = VERTTYPEMUL(x,rhs.f[0])+VERTTYPEMUL(y,rhs.f[1])+VERTTYPEMUL(z,rhs.f[2])+VERTTYPEMUL(w,rhs.f[3]);
     97 		out.y = VERTTYPEMUL(x,rhs.f[4])+VERTTYPEMUL(y,rhs.f[5])+VERTTYPEMUL(z,rhs.f[6])+VERTTYPEMUL(w,rhs.f[7]);
     98 		out.z = VERTTYPEMUL(x,rhs.f[8])+VERTTYPEMUL(y,rhs.f[9])+VERTTYPEMUL(z,rhs.f[10])+VERTTYPEMUL(w,rhs.f[11]);
     99 		out.w = VERTTYPEMUL(x,rhs.f[12])+VERTTYPEMUL(y,rhs.f[13])+VERTTYPEMUL(z,rhs.f[14])+VERTTYPEMUL(w,rhs.f[15]);
    100 		return out;
    101 	}
    102 
    103 /*!***************************************************************************
    104  @Function			*=
    105  @Input				rhs a PVRTMat4
    106  @Returns			result of multiplication and assignment
    107  @Description		matrix multiplication and assignment operator for PVRTVec4 and PVRTMat4
    108 ****************************************************************************/
    109 	PVRTVec4& PVRTVec4::operator*=(const PVRTMat4& rhs)
    110 	{
    111 		VERTTYPE tx = VERTTYPEMUL(x,rhs.f[0])+VERTTYPEMUL(y,rhs.f[1])+VERTTYPEMUL(z,rhs.f[2])+VERTTYPEMUL(w,rhs.f[3]);
    112 		VERTTYPE ty = VERTTYPEMUL(x,rhs.f[4])+VERTTYPEMUL(y,rhs.f[5])+VERTTYPEMUL(z,rhs.f[6])+VERTTYPEMUL(w,rhs.f[7]);
    113 		VERTTYPE tz = VERTTYPEMUL(x,rhs.f[8])+VERTTYPEMUL(y,rhs.f[9])+VERTTYPEMUL(z,rhs.f[10])+VERTTYPEMUL(w,rhs.f[11]);
    114 		w = VERTTYPEMUL(x,rhs.f[12])+VERTTYPEMUL(y,rhs.f[13])+VERTTYPEMUL(z,rhs.f[14])+VERTTYPEMUL(w,rhs.f[15]);
    115 		x = tx;
    116 		y = ty;
    117 		z = tz;
    118 		return *this;
    119 	}
    120 
    121 /*!***************************************************************************
    122 ** PVRTMat3 3x3 matrix
    123 ****************************************************************************/
    124 /*!***************************************************************************
    125  @Function			PVRTMat3
    126  @Input				mat a PVRTMat4
    127  @Description		constructor to form a PVRTMat3 from a PVRTMat4
    128 ****************************************************************************/
    129 	PVRTMat3::PVRTMat3(const PVRTMat4& mat)
    130 	{
    131 		VERTTYPE *dest = (VERTTYPE*)f, *src = (VERTTYPE*)mat.f;
    132 		for(int i=0;i<3;i++)
    133 		{
    134 			for(int j=0;j<3;j++)
    135 			{
    136 				(*dest++) = (*src++);
    137 			}
    138 			src++;
    139 		}
    140 	}
    141 
    142 /*!***************************************************************************
    143  @Function			RotationX
    144  @Input				angle the angle of rotation
    145  @Returns			rotation matrix
    146  @Description		generates a 3x3 rotation matrix about the X axis
    147 ****************************************************************************/
    148 	PVRTMat3 PVRTMat3::RotationX(VERTTYPE angle)
    149 	{
    150 		PVRTMat4 out;
    151 		PVRTMatrixRotationX(out,angle);
    152 		return PVRTMat3(out);
    153 	}
    154 /*!***************************************************************************
    155  @Function			RotationY
    156  @Input				angle the angle of rotation
    157  @Returns			rotation matrix
    158  @Description		generates a 3x3 rotation matrix about the Y axis
    159 ****************************************************************************/
    160 	PVRTMat3 PVRTMat3::RotationY(VERTTYPE angle)
    161 	{
    162 		PVRTMat4 out;
    163 		PVRTMatrixRotationY(out,angle);
    164 		return PVRTMat3(out);
    165 	}
    166 /*!***************************************************************************
    167  @Function			RotationZ
    168  @Input				angle the angle of rotation
    169  @Returns			rotation matrix
    170  @Description		generates a 3x3 rotation matrix about the Z axis
    171 ****************************************************************************/
    172 	PVRTMat3 PVRTMat3::RotationZ(VERTTYPE angle)
    173 	{
    174 		PVRTMat4 out;
    175 		PVRTMatrixRotationZ(out,angle);
    176 		return PVRTMat3(out);
    177 	}
    178 
    179 
    180 /*!***************************************************************************
    181 ** PVRTMat4 4x4 matrix
    182 ****************************************************************************/
    183 /*!***************************************************************************
    184  @Function			RotationX
    185  @Input				angle the angle of rotation
    186  @Returns			rotation matrix
    187  @Description		generates a 4x4 rotation matrix about the X axis
    188 ****************************************************************************/
    189 	PVRTMat4 PVRTMat4::RotationX(VERTTYPE angle)
    190 	{
    191 		PVRTMat4 out;
    192 		PVRTMatrixRotationX(out,angle);
    193 		return out;
    194 	}
    195 /*!***************************************************************************
    196  @Function			RotationY
    197  @Input				angle the angle of rotation
    198  @Returns			rotation matrix
    199  @Description		generates a 4x4 rotation matrix about the Y axis
    200 ****************************************************************************/
    201 	PVRTMat4 PVRTMat4::RotationY(VERTTYPE angle)
    202 	{
    203 		PVRTMat4 out;
    204 		PVRTMatrixRotationY(out,angle);
    205 		return out;
    206 	}
    207 /*!***************************************************************************
    208  @Function			RotationZ
    209  @Input				angle the angle of rotation
    210  @Returns			rotation matrix
    211  @Description		generates a 4x4 rotation matrix about the Z axis
    212 ****************************************************************************/
    213 	PVRTMat4 PVRTMat4::RotationZ(VERTTYPE angle)
    214 	{
    215 		PVRTMat4 out;
    216 		PVRTMatrixRotationZ(out,angle);
    217 		return out;
    218 	}
    219 
    220 /*!***************************************************************************
    221  @Function			*
    222  @Input				rhs another PVRTMat4
    223  @Returns			result of multiplication
    224  @Description		Matrix multiplication of two 4x4 matrices.
    225 *****************************************************************************/
    226 	PVRTMat4 PVRTMat4::operator*(const PVRTMat4& rhs) const
    227 	{
    228 		PVRTMat4 out;
    229 		// col 1
    230 		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]);
    231 		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]);
    232 		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]);
    233 		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]);
    234 
    235 		// col 2
    236 		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]);
    237 		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]);
    238 		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]);
    239 		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]);
    240 
    241 		// col3
    242 		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]);
    243 		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]);
    244 		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]);
    245 		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]);
    246 
    247 		// col3
    248 		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]);
    249 		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]);
    250 		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]);
    251 		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]);
    252 		return out;
    253 	}
    254 
    255 
    256 /*!***************************************************************************
    257  @Function			inverse
    258  @Returns			inverse mat4
    259  @Description		Calculates multiplicative inverse of this matrix
    260 					The matrix must be of the form :
    261 					A 0
    262 					C 1
    263 					Where A is a 3x3 matrix and C is a 1x3 matrix.
    264 *****************************************************************************/
    265 	PVRTMat4 PVRTMat4::inverse() const
    266 	{
    267 		PVRTMat4 out;
    268 		VERTTYPE	det_1;
    269 		VERTTYPE	pos, neg, temp;
    270 
    271 		/* Calculate the determinant of submatrix A and determine if the
    272 		   the matrix is singular as limited by the double precision
    273 		   floating-point data representation. */
    274 		pos = neg = f2vt(0.0);
    275 		temp =  VERTTYPEMUL(VERTTYPEMUL(f[ 0], f[ 5]), f[10]);
    276 		if (temp >= 0) pos += temp; else neg += temp;
    277 		temp =  VERTTYPEMUL(VERTTYPEMUL(f[ 4], f[ 9]), f[ 2]);
    278 		if (temp >= 0) pos += temp; else neg += temp;
    279 		temp =  VERTTYPEMUL(VERTTYPEMUL(f[ 8], f[ 1]), f[ 6]);
    280 		if (temp >= 0) pos += temp; else neg += temp;
    281 		temp =  VERTTYPEMUL(VERTTYPEMUL(-f[ 8], f[ 5]), f[ 2]);
    282 		if (temp >= 0) pos += temp; else neg += temp;
    283 		temp =  VERTTYPEMUL(VERTTYPEMUL(-f[ 4], f[ 1]), f[10]);
    284 		if (temp >= 0) pos += temp; else neg += temp;
    285 		temp =  VERTTYPEMUL(VERTTYPEMUL(-f[ 0], f[ 9]), f[ 6]);
    286 		if (temp >= 0) pos += temp; else neg += temp;
    287 		det_1 = pos + neg;
    288 
    289 		/* Is the submatrix A singular? */
    290 		if (det_1 == f2vt(0.0)) //|| (VERTTYPEABS(det_1 / (pos - neg)) < 1.0e-15)
    291 		{
    292 			/* Matrix M has no inverse */
    293 			_RPT0(_CRT_WARN, "Matrix has no inverse : singular matrix\n");
    294 		}
    295 		else
    296 		{
    297 			/* Calculate inverse(A) = adj(A) / det(A) */
    298 			//det_1 = 1.0 / det_1;
    299 			det_1 = VERTTYPEDIV(f2vt(1.0f), det_1);
    300 			out.f[ 0] =   VERTTYPEMUL(( VERTTYPEMUL(f[ 5], f[10]) - VERTTYPEMUL(f[ 9], f[ 6]) ), det_1);
    301 			out.f[ 1] = - VERTTYPEMUL(( VERTTYPEMUL(f[ 1], f[10]) - VERTTYPEMUL(f[ 9], f[ 2]) ), det_1);
    302 			out.f[ 2] =   VERTTYPEMUL(( VERTTYPEMUL(f[ 1], f[ 6]) - VERTTYPEMUL(f[ 5], f[ 2]) ), det_1);
    303 			out.f[ 4] = - VERTTYPEMUL(( VERTTYPEMUL(f[ 4], f[10]) - VERTTYPEMUL(f[ 8], f[ 6]) ), det_1);
    304 			out.f[ 5] =   VERTTYPEMUL(( VERTTYPEMUL(f[ 0], f[10]) - VERTTYPEMUL(f[ 8], f[ 2]) ), det_1);
    305 			out.f[ 6] = - VERTTYPEMUL(( VERTTYPEMUL(f[ 0], f[ 6]) - VERTTYPEMUL(f[ 4], f[ 2]) ), det_1);
    306 			out.f[ 8] =   VERTTYPEMUL(( VERTTYPEMUL(f[ 4], f[ 9]) - VERTTYPEMUL(f[ 8], f[ 5]) ), det_1);
    307 			out.f[ 9] = - VERTTYPEMUL(( VERTTYPEMUL(f[ 0], f[ 9]) - VERTTYPEMUL(f[ 8], f[ 1]) ), det_1);
    308 			out.f[10] =   VERTTYPEMUL(( VERTTYPEMUL(f[ 0], f[ 5]) - VERTTYPEMUL(f[ 4], f[ 1]) ), det_1);
    309 
    310 			/* Calculate -C * inverse(A) */
    311 			out.f[12] = - ( VERTTYPEMUL(f[12], out.f[ 0]) + VERTTYPEMUL(f[13], out.f[ 4]) + VERTTYPEMUL(f[14], out.f[ 8]) );
    312 			out.f[13] = - ( VERTTYPEMUL(f[12], out.f[ 1]) + VERTTYPEMUL(f[13], out.f[ 5]) + VERTTYPEMUL(f[14], out.f[ 9]) );
    313 			out.f[14] = - ( VERTTYPEMUL(f[12], out.f[ 2]) + VERTTYPEMUL(f[13], out.f[ 6]) + VERTTYPEMUL(f[14], out.f[10]) );
    314 
    315 			/* Fill in last row */
    316 			out.f[ 3] = f2vt(0.0f);
    317 			out.f[ 7] = f2vt(0.0f);
    318 			out.f[11] = f2vt(0.0f);
    319 			out.f[15] = f2vt(1.0f);
    320 		}
    321 
    322 		return out;
    323 	}
    324 
    325 /*!***************************************************************************
    326  @Function			PVRTLinearEqSolve
    327  @Input				pSrc	2D array of floats. 4 Eq linear problem is 5x4
    328 							matrix, constants in first column
    329  @Input				nCnt	Number of equations to solve
    330  @Output			pRes	Result
    331  @Description		Solves 'nCnt' simultaneous equations of 'nCnt' variables.
    332 					pRes should be an array large enough to contain the
    333 					results: the values of the 'nCnt' variables.
    334 					This fn recursively uses Gaussian Elimination.
    335 *****************************************************************************/
    336 void PVRTLinearEqSolve(VERTTYPE * const pRes, VERTTYPE ** const pSrc, const int nCnt)
    337 {
    338 	int			i, j, k;
    339 	VERTTYPE	f;
    340 
    341 	if (nCnt == 1)
    342 	{
    343 		_ASSERT(pSrc[0][1] != 0);
    344 		pRes[0] = VERTTYPEDIV(pSrc[0][0], pSrc[0][1]);
    345 		return;
    346 	}
    347 
    348 	// Loop backwards in an attempt avoid the need to swap rows
    349 	i = nCnt;
    350 	while(i)
    351 	{
    352 		--i;
    353 
    354 		if(pSrc[i][nCnt] != f2vt(0.0f))
    355 		{
    356 			// Row i can be used to zero the other rows; let's move it to the bottom
    357 			if(i != (nCnt-1))
    358 			{
    359 				for(j = 0; j <= nCnt; ++j)
    360 				{
    361 					// Swap the two values
    362 					f = pSrc[nCnt-1][j];
    363 					pSrc[nCnt-1][j] = pSrc[i][j];
    364 					pSrc[i][j] = f;
    365 				}
    366 			}
    367 
    368 			// Now zero the last columns of the top rows
    369 			for(j = 0; j < (nCnt-1); ++j)
    370 			{
    371 				_ASSERT(pSrc[nCnt-1][nCnt] != f2vt(0.0f));
    372 				f = VERTTYPEDIV(pSrc[j][nCnt], pSrc[nCnt-1][nCnt]);
    373 
    374 				// No need to actually calculate a zero for the final column
    375 				for(k = 0; k < nCnt; ++k)
    376 				{
    377 					pSrc[j][k] -= VERTTYPEMUL(f, pSrc[nCnt-1][k]);
    378 				}
    379 			}
    380 
    381 			break;
    382 		}
    383 	}
    384 
    385 	// Solve the top-left sub matrix
    386 	PVRTLinearEqSolve(pRes, pSrc, nCnt - 1);
    387 
    388 	// Now calc the solution for the bottom row
    389 	f = pSrc[nCnt-1][0];
    390 	for(k = 1; k < nCnt; ++k)
    391 	{
    392 		f -= VERTTYPEMUL(pSrc[nCnt-1][k], pRes[k-1]);
    393 	}
    394 	_ASSERT(pSrc[nCnt-1][nCnt] != f2vt(0));
    395 	f = VERTTYPEDIV(f, pSrc[nCnt-1][nCnt]);
    396 	pRes[nCnt-1] = f;
    397 }
    398 
    399 /*****************************************************************************
    400 End of file (PVRTVector.cpp)
    401 *****************************************************************************/
    402 
    403