Beaming Scene Service  2.0
RakNet wrapper for managing data communications between multiple Beaming clients
utilMath.h
Go to the documentation of this file.
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
 All Classes Files Functions Variables Enumerations Enumerator Defines