00001
00014
00015
00016
00017
00018
00019 #ifndef GFX_MATH_HH
00020 #define GFX_MATH_HH 1
00021
00022 namespace gfx {
00023
00027
00028
00029
00030
00031 #if __GNUC__ && defined(__USE_ISOC99)
00032 #define IF_NAN(N) (UX(!isfinite(N)))
00033 #else
00034
00035
00036 INLINE bool IF_NAN( volatile fp n ) { return !(n==n); }
00037 #endif
00038
00042
00043
00044
00045
00046
00047
00048 const fpx PI = 3.14159265358979323846L;
00049 const fpx PI2 = 6.28318530717958647692L;
00050 const fpx PI_90 = 1.57079632679489661926L;
00051
00052
00053
00054 #if SPEED
00057 DECLARE_DISTINCT_TYPE( Radian, fp )
00060 DECLARE_DISTINCT_TYPE( Degree, fp )
00061 #else
00062 DECLARE_DISTINCT_TYPE( Radian, fpx )
00063 DECLARE_DISTINCT_TYPE( Degree, fpx )
00064 #endif
00065
00066 const Radian RADIAN_180 = gfx::PI;
00067 const Radian RADIAN_360 = gfx::PI2;
00068
00069
00070 #define IF_DEG_GT( DEG1, DEG2 ) (ABS(DEG1) > ABS(DEG2))
00071 #define IF_DEG_LT( DEG1, DEG2 ) (ABS(DEG1) < ABS(DEG2))
00072 #define IF_RAD_GT( RAD1, RAD2 ) (ABS(RAD1) > ABS(RAD2))
00073 #define IF_RAD_LT( RAD1, RAD2 ) (ABS(RAD1) < ABS(RAD2))
00074
00082 template<typename FP>
00083 pair<FP,FP>
00084 SinCos( const Radian rad )
00085 {
00086 #if defined(__GNUC__) && defined(CPU_X86)
00087 pair<FP,FP> si_co;
00088 asm("fsincos" : "=t" (si_co.second), "=u" (si_co.first) : "0" (rad));
00089 return si_co;
00090 #elif defined(__GNUC__) && _GLIBCXX_HAVE_SINCOS
00091 pair<double,double> si_co;
00092 sincos( rad, &si_co.first, &si_co.second );
00093 return make_pair<FP,FP>( si_co.first, si_co.second );
00094 #else
00095 pair<FP,FP> si_co;
00096 si_co.first = sin( rad );
00097 si_co.second = cos( rad );
00098 return si_co;
00099 #endif
00100 }
00101
00105 INLINE Degree
00106 TruncateDeg( Degree deg )
00107 {
00108 if ( EX(deg < 360.0) )
00109 return deg;
00110 else
00111 return deg - 360.0;
00112 }
00113
00118 INTERN const fpx degRadRatio = (1.0 / 360.0) * (gfx::PI2);
00119 #define DEG2RAD( DEG ) ((DEG) * (degRadRatio))
00120
00121 INLINE Radian
00122 Deg2Rad( Degree deg )
00123 {
00124 return DEG2RAD( deg );
00125
00126 }
00127
00132 INTERN const fpx radDegRatio = (1.0 / gfx::PI2) * 360.0;
00133 #define RAD2DEG( RAD ) ((RAD) * (radDegRatio))
00134
00135 INLINE Degree
00136 Rad2Deg( Radian rad )
00137 {
00138 return RAD2DEG( rad );
00139
00140 }
00141
00145 INLINE fpx
00146 Sin( Degree deg )
00147 {
00148 return sin( Deg2Rad( deg ) );
00149 }
00150
00154 INLINE fpx
00155 Cos( Degree deg )
00156 {
00157 return cos( Deg2Rad( deg ) );
00158 }
00159
00163
00164 }
00165
00166 #include "gfx_math_matrix.hh"
00167
00168 namespace gfx {
00169
00173
00177 INLINE fp
00178 Distance( const Vector2& v )
00179 {
00180 return sqrtf( v.x * v.x
00181 + v.y * v.y );
00182 }
00183
00184 INLINE fp
00185 Distance( const Vector3& v )
00186 {
00187 return sqrtf( v.x * v.x
00188 + v.y * v.y
00189 + v.z * v.z );
00190 }
00191
00195 template<typename VECTOR3A,typename VECTOR3B>
00196 fp
00197 Distance( const VECTOR3A& v1, const VECTOR3B& v2 )
00198 {
00199 const fp dx = v2.x - v1.x;
00200 const fp dy = v2.y - v1.y;
00201 const fp dz = v2.z - v1.z;
00202 return sqrtf( dx * dx
00203 + dy * dy
00204 + dz * dz );
00205 }
00206
00213 INLINE fpx
00214 DistanceSquared( const Vector3& v1, const Vector3& v2 )
00215 {
00216 fpx xd = v2.x - v1.x;
00217 fpx yd = v2.y - v1.y;
00218 fpx zd = v2.z - v1.z;
00219 return xd*xd + yd*yd + zd*zd;
00220 }
00221
00222
00223
00224 template<typename MATRIX1, typename MATRIX2>
00225 fpx
00226 DistanceSquaredMatrix( const MATRIX1& m1, const MATRIX2& m2 )
00227 {
00228 Vector3 v1( m1[Ox], m1[Oy], m1[Oz] );
00229 Vector3 v2( m2[Ox], m2[Oy], m2[Oz] );
00230 return DistanceSquared( v1, v2 );
00231 }
00232
00237 INLINE Vector3
00238 Normalize( const Vector3& v )
00239 {
00240 fp dist = Distance( v );
00241 return Vector3( v.x / dist,
00242 v.y / dist,
00243 v.z / dist );
00244 }
00245
00250 INLINE fp
00251 NormalizeCoord( uint axis, const Vector3& v )
00252 {
00253 fp dist = Distance( v );
00254 if ( axis == XX ) return v.x / dist;
00255 else if ( axis == YY ) return v.y / dist;
00256 else return v.z / dist;
00257 }
00258
00264 INLINE Vector3
00265 CrossProduct( const Vector3& v0,
00266 const Vector3& v1,
00267 const Vector3& v2 )
00268 {
00269 const fp xd1 = v1.x - v0.x;
00270 const fp yd1 = v1.y - v0.y;
00271 const fp zd1 = v1.z - v0.z;
00272 const fp xd2 = v2.x - v0.x;
00273 const fp yd2 = v2.y - v0.y;
00274 const fp zd2 = v2.z - v0.z;
00275 return Vector3( yd1 * zd2 - yd2 * zd1,
00276 zd1 * xd2 - zd2 * xd1,
00277 xd1 * yd2 - xd2 * yd1 );
00278 }
00279
00285 INLINE fp
00286 DotProduct2( const Vector2& v1, const Vector2& v2 )
00287 {
00288 return v1.x * v2.x
00289 + v1.y * v2.y;
00290 }
00291
00292 template<typename VECTOR3A,typename VECTOR3B>
00293 fp
00294 DotProduct3( const VECTOR3A& v1, const VECTOR3B& v2 )
00295 {
00296 return v1.x * v2.x
00297 + v1.y * v2.y
00298 + v1.z * v2.z;
00299 }
00300
00301
00302 template<typename VECTOR3A,typename VECTOR3B>
00303 fpx
00304 DotProduct3_fpx( const VECTOR3A& v1, const VECTOR3B& v2 )
00305 {
00306 return fpx(v1.x) * fpx(v2.x)
00307 + fpx(v1.y) * fpx(v2.y)
00308 + fpx(v1.z) * fpx(v2.z);
00309 }
00310
00314 INLINE Radian
00315 Angle2( const Vector2& u, const Vector2& v )
00316 {
00317
00318
00319 fp uv = Distance(u) * Distance(v);
00320 if ( ABS(uv) < 0.1 ) return 0.0;
00321 fp theta = DotProduct2(u,v) / uv;
00322 theta = Clamp( theta, -1.0, 1.0 );
00323
00324 fp rad = acos( theta );
00325 ASSERT(errno == 0);
00326 return rad;
00327 }
00328
00329 template<typename VECTOR>
00330 Radian
00331 Angle3( const VECTOR& u, const VECTOR& v )
00332 {
00333
00334
00335 fp uv = Distance(u) * Distance(v);
00336 if ( ABS(uv) < 0.1 ) return 0.0;
00337 fp theta = DotProduct3(u,v) / uv;
00338 theta = Clamp( theta, -1.0, 1.0 );
00339
00340 fp rad = acos( theta );
00341 ASSERT(errno == 0);
00342 return rad;
00343 }
00344
00355 INLINE Vector3
00356 Interpolate( const Vector3& v1, const Vector3& v2, const fp fraction )
00357 {
00358 ASSERT( fraction >= 0.0 && fraction <= 1.0 );
00359 return Vector3( v1 + ((v2-v1) * fraction) );
00360 }
00361
00365 template<typename T>
00366 T
00367 Midpoint( T x1, T x2 )
00368 {
00369
00370 return (x1 + x2) / 2;
00371 }
00372
00373 INLINE Vector3
00374 Midpoint( const Vector3& v1, const Vector3& v2 )
00375 {
00376 return Vector3( Midpoint(v1.x, v2.x),
00377 Midpoint(v1.y, v2.y),
00378 Midpoint(v1.z, v2.z) );
00379 }
00380
00384
00388 template<typename T>
00389 T
00390 SQUARE( T x )
00391 {
00392 return x * x;
00393 }
00394
00398 template<typename T>
00399 T
00400 AVG( T x, T y )
00401 {
00402 return (x + y) / 2;
00403 }
00404
00408 template<typename T>
00409 T
00410 Range( T val, T lo, T hi )
00411 {
00412 if ( val < lo ) return lo;
00413 if ( val > hi ) return hi;
00414 return val;
00415 }
00416
00420 template<typename T>
00421 T
00422 IfInRange( T a0, T a1, T b0, T b1 )
00423 {
00424
00425 if ( a0 > b1 )
00426 return false;
00427 else if ( a1 < b0 )
00428 return false;
00429 else if ( b0 > a1 )
00430 return false;
00431 else if ( b1 < a0 )
00432 return false;
00433 else
00434 return true;
00435 }
00436
00440 INLINE fp
00441 Remap( fp value, fp rangeOld, fp rangeNew )
00442 {
00443 return value / rangeOld * rangeNew;
00444 }
00445
00450 INLINE fp
00451 Truncate( fp val, fp interval )
00452 {
00453 float integral;
00454 modff( val/interval, &integral );
00455 return integral*interval;
00456 }
00457
00458 }
00459
00460 #endif // GFX_MATH_HH