![]() |
Beaming Scene Service
2.0
RakNet wrapper for managing data communications between multiple Beaming clients
|
00001 /* 00002 * utilmath.h 00003 * 00004 */ 00005 #ifndef _UTIL_MATH_H_ 00006 #define _UTIL_MATH_H_ 00007 00008 #include <math.h> 00009 00010 #ifndef M_PI 00011 #define M_PI 3.1415926532 00012 #endif 00013 00014 #define RAD_TO_DEG(X) (X / M_PI * 180) 00015 #define DEG_TO_RAD(X) (X / 180 * M_PI) 00016 00017 00019 // 00020 // vector 00021 // 00024 class CVec3 00025 { 00026 public: 00027 // Data 00028 float x, y, z; 00029 00030 // Ctors 00031 CVec3( float InX, float InY, float InZ ) : x( InX ), y( InY ), z( InZ ) 00032 { 00033 } 00034 CVec3( ) : x(0), y(0), z(0) 00035 { 00036 } 00037 00038 // Operator Overloads 00039 inline bool operator== (const CVec3& V2) const 00040 { 00041 return (x == V2.x && y == V2.y && z == V2.z); 00042 } 00043 00044 inline CVec3 operator+ (const CVec3& V2) const 00045 { 00046 return CVec3( x + V2.x, y + V2.y, z + V2.z); 00047 } 00048 inline CVec3 operator- (const CVec3& V2) const 00049 { 00050 return CVec3( x - V2.x, y - V2.y, z - V2.z); 00051 } 00052 inline CVec3 operator- ( ) const 00053 { 00054 return CVec3(-x, -y, -z); 00055 } 00056 00057 inline CVec3 operator/ (float S ) const 00058 { 00059 float fInv = 1.0f / S; 00060 return CVec3 (x * fInv , y * fInv, z * fInv); 00061 } 00062 inline CVec3 operator/ (const CVec3& V2) const 00063 { 00064 return CVec3 (x / V2.x, y / V2.y, z / V2.z); 00065 } 00066 inline CVec3 operator* (const CVec3& V2) const 00067 { 00068 return CVec3 (x * V2.x, y * V2.y, z * V2.z); 00069 } 00070 inline CVec3 operator* (float S) const 00071 { 00072 return CVec3 (x * S, y * S, z * S); 00073 } 00074 00075 inline void operator+= ( const CVec3& V2 ) 00076 { 00077 x += V2.x; 00078 y += V2.y; 00079 z += V2.z; 00080 } 00081 inline void operator-= ( const CVec3& V2 ) 00082 { 00083 x -= V2.x; 00084 y -= V2.y; 00085 z -= V2.z; 00086 } 00087 00088 inline float operator[] ( int i ) 00089 { 00090 if ( i == 0 ) return x; 00091 else if ( i == 1 ) return y; 00092 else return z; 00093 } 00094 00095 // Functions 00096 inline float Dot( const CVec3 &V1 ) const 00097 { 00098 return V1.x*x + V1.y*y + V1.z*z; 00099 } 00100 00101 inline CVec3 Cross( const CVec3 &V2 ) const 00102 { 00103 return CVec3( 00104 y * V2.z - z * V2.y, 00105 z * V2.x - x * V2.z, 00106 x * V2.y - y * V2.x ); 00107 } 00108 00109 // Return vector rotated by the 3x3 portion of matrix m 00110 CVec3 RotByMatrix( const float m[16] ) const 00111 { 00112 return CVec3( 00113 x*m[0] + y*m[4] + z*m[8], 00114 x*m[1] + y*m[5] + z*m[9], 00115 x*m[2] + y*m[6] + z*m[10] ); 00116 } 00117 00118 // These require math.h for the sqrtf function 00119 float Magnitude( ) const 00120 { 00121 return sqrtf( x*x + y*y + z*z ); 00122 } 00123 00124 float Distance( const CVec3 &V1 ) const 00125 { 00126 return ( *this - V1 ).Magnitude(); 00127 } 00128 00129 inline void Normalize() 00130 { 00131 float fMag = ( x*x + y*y + z*z ); 00132 if (fMag == 0) {return;} 00133 00134 float fMult = 1.0f/sqrtf(fMag); 00135 x *= fMult; 00136 y *= fMult; 00137 z *= fMult; 00138 return; 00139 } 00140 00141 float enclosedAngle(const CVec3 &V1 ) const 00142 { 00143 float returnValue = Dot(V1); 00144 returnValue /= (Magnitude() * V1.Magnitude()); 00145 returnValue = acos(returnValue); 00146 return returnValue; 00147 } 00148 00149 }; 00150 00152 // 00153 // quaternion 00154 // 00156 00157 const float TO_HALF_RAD = 3.14159265f / 360.0f; 00158 00160 class CQuat 00161 { 00162 public: 00163 float x,y,z,w; 00164 00165 CQuat( ) : x(0), y(0), z(0), w(1) 00166 { 00167 } 00168 00169 CQuat( float fx, float fy, float fz, float fw ) : x(fx), y(fy), z(fz), w(fw) 00170 { 00171 } 00172 00173 // This just took four floats initially to avoid dependence on the vector class 00174 // but I decided avoiding confusion with the value setting constructor was more important 00175 CQuat( float Angle, const CVec3& Axis ) 00176 { 00177 SetAxis( Angle, Axis.x, Axis.y, Axis.z ); 00178 } 00179 00181 void Reset( ) 00182 { 00183 x = 0; 00184 y = 0; 00185 z = 0; 00186 w = 1; 00187 } 00189 int IsIdentity( ) const 00190 { 00191 return (x == 0.0f && y == 0.0f && z == 0.0f && w==1.0f); 00192 } 00193 00195 void SetAxis( float degrees, float fX, float fY, float fZ ) 00196 { 00197 float HalfAngle = degrees * TO_HALF_RAD; // Get half angle in radians from angle in degrees 00198 float sinA = (float)sin( HalfAngle ) ; 00199 w = (float)cos( HalfAngle ); 00200 x = fX * sinA; 00201 y = fY * sinA; 00202 z = fZ * sinA; 00203 } 00204 // ------------------------------------ 00206 // ------------------------------------ 00207 void FromEuler( float rx, float ry, float rz ) 00208 { 00209 CQuat qx(-rx, CVec3( 1, 0, 0 ) ); 00210 CQuat qy(-ry, CVec3( 0, 1, 0 ) ); 00211 CQuat qz(-rz, CVec3( 0, 0, 1 ) ); 00212 qz = qy * qz; 00213 *this = qx * qz; 00214 } 00215 // ------------------------------------ 00217 // ------------------------------------ 00218 void inline ToMatrix( float mf[16] ) const 00219 { 00220 float x2 = 2.0f * x, y2 = 2.0f * y, z2 = 2.0f * z; 00221 00222 float xy = x2 * y, xz = x2 * z; 00223 float yy = y2 * y, yw = y2 * w; 00224 float zw = z2 * w, zz = z2 * z; 00225 00226 mf[ 0] = 1.0f - ( yy + zz ); 00227 mf[ 1] = ( xy - zw ); 00228 mf[ 2] = ( xz + yw ); 00229 mf[ 3] = 0.0f; 00230 00231 float xx = x2 * x, xw = x2 * w, yz = y2 * z; 00232 00233 mf[ 4] = ( xy + zw ); 00234 mf[ 5] = 1.0f - ( xx + zz ); 00235 mf[ 6] = ( yz - xw ); 00236 mf[ 7] = 0.0f; 00237 00238 mf[ 8] = ( xz - yw ); 00239 mf[ 9] = ( yz + xw ); 00240 mf[10] = 1.0f - ( xx + yy ); 00241 mf[11] = 0.0f; 00242 00243 mf[12] = 0.0f; 00244 mf[13] = 0.0f; 00245 mf[14] = 0.0f; 00246 mf[15] = 1.0f; 00247 } 00248 00250 CQuat Invert( ) const 00251 { 00252 return CQuat( -x, -y, -z, w ); 00253 } 00254 00256 inline bool operator== ( const CQuat &b ) const 00257 { 00258 return (x == b.x && y == b.y && z == b.z && w == b.w); 00259 } 00260 00262 CQuat operator+ ( const CQuat& b ) const 00263 { 00264 return CQuat( x + b.x, y + b.y, z + b.z, w + b.w ); 00265 } 00266 00268 inline CQuat operator* (const CQuat &b) const 00269 { 00270 CQuat r; 00271 00272 r.w = w*b.w - x*b.x - y*b.y - z*b.z; 00273 r.x = w*b.x + x*b.w + y*b.z - z*b.y; 00274 r.y = w*b.y + y*b.w + z*b.x - x*b.z; 00275 r.z = w*b.z + z*b.w + x*b.y - y*b.x; 00276 00277 return r; 00278 } 00279 00281 inline CVec3 operator* (const CVec3 &v) const 00282 { 00283 CVec3 t; 00284 CQuat q,r,a; 00285 q.x = v.x; 00286 q.y = v.y; 00287 q.z = v.z; 00288 q.w = 0.0f; 00289 00290 a.x = x; 00291 a.y = y; 00292 a.z = z; 00293 a.w = w; 00294 00295 r = q * a.Invert(); 00296 r = a * r; 00297 00298 t.x = r.x; 00299 t.y = r.y; 00300 t.z = r.z; 00301 00302 return t; 00303 } 00304 00306 CQuat operator*( float s ) const 00307 { 00308 return CQuat(x * s, y * s, z * s, w * s ); 00309 } 00310 00311 00313 float Dot( const CQuat& a ) const 00314 { 00315 return x * a.x + y * a.y + z * a.z + w * a.w; 00316 } 00317 00318 // ------------------------------------ 00320 // ------------------------------------ 00321 int Normalize( ) 00322 { 00323 float lengthSq = x * x + y * y + z * z + w * w; 00324 00325 if (lengthSq == 0.0 ) return -1; 00326 if (lengthSq != 1.0 ) 00327 { 00328 float scale = ( 1.0f / sqrtf( lengthSq ) ); 00329 x *= scale; 00330 y *= scale; 00331 z *= scale; 00332 w *= scale; 00333 return 1; 00334 } 00335 return 0; 00336 } 00337 00338 // ------------------------------------ 00341 // ------------------------------------ 00342 void Slerp(const CQuat& a, const CQuat& b, float t) 00343 { 00344 float w1, w2; 00345 00346 float cosTheta = a.Dot(b); 00347 float theta = (float)acos(cosTheta); 00348 float sinTheta = (float)sin(theta); 00349 00350 if( sinTheta > 0.001f ) 00351 { 00352 w1 = float( sin( (1.0f-t)*theta ) / sinTheta); 00353 w2 = float( sin( t*theta) / sinTheta); 00354 } 00355 else 00356 { 00357 // CQuat a ~= CQuat b 00358 w1 = 1.0f - t; 00359 w2 = t; 00360 } 00361 00362 *this = a*w1 + b*w2; 00363 } 00364 00365 // ------------------------------------ 00369 // ------------------------------------ 00370 void NLerp( const CQuat& a, const CQuat& b, float w2) 00371 { 00372 float w1 = 1.0f - w2; 00373 00374 *this = a*w1 + b*w2; 00375 Normalize(); 00376 } 00377 00378 00379 // ------------------------------------ 00381 // ------------------------------------ 00382 void AimZAxis( const CVec3& P1, const CVec3& P2 ) 00383 { 00384 CVec3 vAim = P2 - P1; 00385 vAim.Normalize(); 00386 00387 x = vAim.y; 00388 y = -vAim.x; 00389 z = 0.0f; 00390 w = 1.0f + vAim.z; 00391 00392 if ( x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f ) { 00393 *this = CQuat( 0, 1, 0, 0 ); // If we can't normalize it, just set it 00394 } else { 00395 Normalize(); 00396 } 00397 } 00398 }; 00399 00401 // 00402 // matrix 00403 // 00405 const float PI = 3.14159265f; 00406 const float TO_RAD = PI / 180.0f; 00407 00409 class CMatrix 00410 { 00411 public: 00412 // Data 00413 float mf[ 16 ]; 00414 00415 // Functions 00417 CMatrix( const int bIdentity = true ) 00418 { 00419 if ( bIdentity ) Identity(); 00420 } 00422 void Identity( ) 00423 { 00424 mf[ 0] = 1.0f; mf[ 1] = 0.0f; mf[ 2] = 0.0f; mf[ 3] = 0.0f; 00425 mf[ 4] = 0.0f; mf[ 5] = 1.0f; mf[ 6] = 0.0f; mf[ 7] = 0.0f; 00426 mf[ 8] = 0.0f; mf[ 9] = 0.0f; mf[10] = 1.0f; mf[11] = 0.0f; 00427 mf[12] = 0.0f; mf[13] = 0.0f; mf[14] = 0.0f; mf[15] = 1.0f; 00428 } 00429 00431 inline CMatrix operator* (const CMatrix &InM) const 00432 { 00433 CMatrix Result( 0 ); 00434 for (int i=0;i<16;i+=4) 00435 { 00436 for (int j=0;j<4;j++) 00437 { 00438 Result.mf[i + j] = mf[ i + 0] * InM.mf[ 0 + j] + mf[ i + 1] * InM.mf[ 4 + j] 00439 + mf[ i + 2] * InM.mf[ 8 + j] + mf[ i + 3] * InM.mf[ 12 + j]; 00440 } 00441 } 00442 return Result; 00443 } 00444 00446 inline CVec3 operator* (const CVec3 &Point ) const 00447 { 00448 float x = Point.x*mf[0] + Point.y*mf[4] + Point.z*mf[8] + mf[12]; 00449 float y = Point.x*mf[1] + Point.y*mf[5] + Point.z*mf[9] + mf[13]; 00450 float z = Point.x*mf[2] + Point.y*mf[6] + Point.z*mf[10] + mf[14]; 00451 return CVec3( x, y, z ); 00452 } 00453 00455 void Rotate( float fDegrees, int x, int y, int z ) 00456 { 00457 CMatrix Temp; 00458 if (x == 1) Temp.RotX( -fDegrees ); 00459 if (y == 1) Temp.RotY( -fDegrees ); 00460 if (z == 1) Temp.RotZ( -fDegrees ); 00461 *this = Temp * (*this); 00462 } 00463 00464 void Scale( float sx, float sy, float sz ) 00465 { 00466 int x; 00467 for (x = 0; x < 4; x++) mf[x]*=sx; 00468 for (x = 4; x < 8; x++) mf[x]*=sy; 00469 for (x = 8; x < 12; x++) mf[x]*=sz; 00470 } 00471 00472 void Translate( const CVec3 &Test ) 00473 { 00474 for (int j=0;j<4;j++) 00475 { 00476 mf[12+j] += Test.x * mf[j] + Test.y * mf[4+j] + Test.z * mf[8+j]; 00477 } 00478 } 00480 CVec3 GetTranslate( ) 00481 { 00482 return CVec3( mf[12], mf[13], mf[14] ); 00483 } 00484 00486 CMatrix RotationOnly( ) 00487 { 00488 CMatrix Temp = *this; 00489 Temp.mf[12] = 0; 00490 Temp.mf[13] = 0; 00491 Temp.mf[14] = 0; 00492 return Temp; 00493 } 00494 00496 void RotateMatrix( float fDegrees, float x, float y, float z) 00497 { 00498 Identity(); 00499 float cosA = cosf(fDegrees*TO_RAD); 00500 float sinA = sinf(fDegrees*TO_RAD); 00501 float m = 1.0f - cosA; 00502 mf[0] = cosA + x*x*m; 00503 mf[5] = cosA + y*y*m; 00504 mf[10]= cosA + z*z*m; 00505 00506 float tmp1 = x*y*m; 00507 float tmp2 = z*sinA; 00508 mf[4] = tmp1 + tmp2; 00509 mf[1] = tmp1 - tmp2; 00510 00511 tmp1 = x*z*m; 00512 tmp2 = y*sinA; 00513 mf[8] = tmp1 - tmp2; 00514 mf[2] = tmp1 + tmp2; 00515 00516 tmp1 = y*z*m; 00517 tmp2 = x*sinA; 00518 mf[9] = tmp1 + tmp2; 00519 mf[6] = tmp1 - tmp2; 00520 } 00521 00523 inline CMatrix InvertSimple() 00524 { 00525 CMatrix R(0); 00526 R.mf[0] = mf[0]; R.mf[1] = mf[4]; R.mf[2] = mf[8]; R.mf[3] = 0.0f; 00527 R.mf[4] = mf[1]; R.mf[5] = mf[5]; R.mf[6] = mf[9]; R.mf[7] = 0.0f; 00528 R.mf[8] = mf[2]; R.mf[9] = mf[6]; R.mf[10] = mf[10]; R.mf[11] = 0.0f; 00529 R.mf[12] = -(mf[12]*mf[0]) - (mf[13]*mf[1]) - (mf[14]*mf[2]); 00530 R.mf[13] = -(mf[12]*mf[4]) - (mf[13]*mf[5]) - (mf[14]*mf[6]); 00531 R.mf[14] = -(mf[12]*mf[8]) - (mf[13]*mf[9]) - (mf[14]*mf[10]); 00532 R.mf[15] = 1.0f; 00533 return R; 00534 } 00535 00537 CMatrix InvertRot( ) 00538 { 00539 CMatrix R( 0 ); 00540 R.mf[0] = mf[0]; R.mf[1] = mf[4]; R.mf[2] = mf[8]; R.mf[3] = 0.0f; 00541 R.mf[4] = mf[1]; R.mf[5] = mf[5]; R.mf[6] = mf[9]; R.mf[7] = 0.0f; 00542 R.mf[8] = mf[2]; R.mf[9] = mf[6]; R.mf[10] = mf[10]; R.mf[11] = 0.0f; 00543 R.mf[12] = 0; R.mf[13] = 0; R.mf[14] = 0; R.mf[15] = 1.0f; 00544 return R; 00545 } 00546 00547 void ToEuler(float *h, float *p, float *r) 00548 { 00549 if (mf[4] > 0.99998) { // singularity at north pole 00550 *h = atan2(mf[2],mf[10]); 00551 *p = M_PI/2; 00552 *r = 0; 00553 } 00554 else if (mf[4] < -0.99998) { // singularity at south pole 00555 *h = atan2(mf[2],mf[10]); 00556 *p = -M_PI/2; 00557 *r = 0; 00558 }else{ 00559 *h = atan2(-mf[8],mf[0]); // heading 00560 *r = atan2(-mf[6],mf[5]); // bank 00561 *p = asin(mf[4]); // attitude 00562 } 00563 00564 *h *= -180.0/M_PI; 00565 *p *= -180.0/M_PI; 00566 *r *= -180.0/M_PI; 00567 } 00568 00569 00570 private: 00572 void RotX(float angle) 00573 { 00574 mf[5] = cosf(angle*TO_RAD); 00575 mf[6] = sinf(angle*TO_RAD); 00576 mf[9] = -sinf(angle*TO_RAD); 00577 mf[10] = cosf(angle*TO_RAD); 00578 } 00580 void RotY(float angle) 00581 { 00582 mf[0] = cosf(angle*TO_RAD); 00583 mf[2] = -sinf(angle*TO_RAD); 00584 mf[8] = sinf(angle*TO_RAD); 00585 mf[10] = cosf(angle*TO_RAD); 00586 } 00588 void RotZ(float angle) 00589 { 00590 mf[0] = cosf(angle*TO_RAD); 00591 mf[1] = sinf(angle*TO_RAD); 00592 mf[4] = -sinf(angle*TO_RAD); 00593 mf[5] = cosf(angle*TO_RAD); 00594 } 00595 }; 00596 00597 #endif