00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #ifndef GLH_LINEAR_H
00050 #define GLH_LINEAR_H
00051
00052 #include <memory.h>
00053 #include <math.h>
00054 #include <assert.h>
00055
00056
00057 #define GLH_REAL_IS_FLOAT
00058
00059 #ifdef GLH_REAL_IS_FLOAT
00060 # define GLH_REAL float
00061 # define GLH_REAL_NAMESPACE ns_float
00062 #endif
00063
00064 #ifdef _WIN32
00065 # define TEMPLATE_FUNCTION
00066 #else
00067 # define TEMPLATE_FUNCTION <>
00068 #endif
00069
00070 #define GLH_QUATERNION_NORMALIZATION_THRESHOLD 64
00071
00072 #define GLH_RAD_TO_DEG GLH_REAL(57.2957795130823208767981548141052)
00073 #define GLH_DEG_TO_RAD GLH_REAL(0.0174532925199432957692369076848861)
00074 #define GLH_ZERO GLH_REAL(0.0)
00075 #define GLH_ONE GLH_REAL(1.0)
00076 #define GLH_TWO GLH_REAL(2.0)
00077 #define GLH_EPSILON GLH_REAL(10e-6)
00078 #define GLH_PI GLH_REAL(3.1415926535897932384626433832795)
00079
00080 #define equivalent(a,b) (((a < b + GLH_EPSILON) && (a > b - GLH_EPSILON)) ? true : false)
00081
00082 namespace glh
00083 {
00084
00085 inline GLH_REAL to_degrees(GLH_REAL radians) { return radians*GLH_RAD_TO_DEG; }
00086 inline GLH_REAL to_radians(GLH_REAL degrees) { return degrees*GLH_DEG_TO_RAD; }
00087
00088
00089 template <int N, class T>
00090 class vec
00091 {
00092 public:
00093 int size() const { return N; }
00094
00095 vec(const T & t = T())
00096 { for(int i = 0; i < N; i++) v[i] = t; }
00097 vec(const T * tp)
00098 { for(int i = 0; i < N; i++) v[i] = tp[i]; }
00099
00100 const T * get_value() const
00101 { return v; }
00102
00103
00104 T dot( const vec<N,T> & rhs ) const
00105 {
00106 T r = 0;
00107 for(int i = 0; i < N; i++) r += v[i]*rhs.v[i];
00108 return r;
00109 }
00110
00111 T length() const
00112 {
00113 T r = 0;
00114 for(int i = 0; i < N; i++) r += v[i]*v[i];
00115 return T(sqrt(r));
00116 }
00117
00118 T square_norm() const
00119 {
00120 T r = 0;
00121 for(int i = 0; i < N; i++) r += v[i]*v[i];
00122 return r;
00123 }
00124
00125 void negate()
00126 { for(int i = 0; i < N; i++) v[i] = -v[i]; }
00127
00128
00129 T normalize()
00130 {
00131 T sum(0);
00132 for(int i = 0; i < N; i++)
00133 sum += v[i]*v[i];
00134 sum = T(sqrt(sum));
00135 if (sum > GLH_EPSILON)
00136 for(int i = 0; i < N; i++)
00137 v[i] /= sum;
00138 return sum;
00139 }
00140
00141
00142 vec<N,T> & set_value( const T * rhs )
00143 { for(int i = 0; i < N; i++) v[i] = rhs[i]; return *this; }
00144
00145 T & operator [] ( int i )
00146 { return v[i]; }
00147
00148 const T & operator [] ( int i ) const
00149 { return v[i]; }
00150
00151 vec<N,T> & operator *= ( T d )
00152 { for(int i = 0; i < N; i++) v[i] *= d; return *this;}
00153
00154 vec<N,T> & operator *= ( const vec<N,T> & u )
00155 { for(int i = 0; i < N; i++) v[i] *= u[i]; return *this;}
00156
00157 vec<N,T> & operator /= ( T d )
00158 { if(d == 0) return *this; for(int i = 0; i < N; i++) v[i] /= d; return *this;}
00159
00160 vec<N,T> & operator += ( const vec<N,T> & u )
00161 { for(int i = 0; i < N; i++) v[i] += u.v[i]; return *this;}
00162
00163 vec<N,T> & operator -= ( const vec<N,T> & u )
00164 { for(int i = 0; i < N; i++) v[i] -= u.v[i]; return *this;}
00165
00166
00167 vec<N,T> operator - () const
00168 { vec<N,T> rv = v; rv.negate(); return rv; }
00169
00170 vec<N,T> operator + ( const vec<N,T> &v) const
00171 { vec<N,T> rt(*this); return rt += v; }
00172
00173 vec<N,T> operator - ( const vec<N,T> &v) const
00174 { vec<N,T> rt(*this); return rt -= v; }
00175
00176 vec<N,T> operator * ( T d) const
00177 { vec<N,T> rt(*this); return rt *= d; }
00178
00179
00180
00181
00182
00183
00184 T v[N];
00185 };
00186
00187
00188
00189
00190
00191 template <int N, class T> inline
00192 vec<N,T> operator * ( const vec<N,T> & b, T d )
00193 {
00194 vec<N,T> rt(b);
00195 return rt *= d;
00196 }
00197
00198 template <int N, class T> inline
00199 vec<N,T> operator * ( T d, const vec<N,T> & b )
00200 { return b*d; }
00201
00202 template <int N, class T> inline
00203 vec<N,T> operator * ( const vec<N,T> & b, const vec<N,T> & d )
00204 {
00205 vec<N,T> rt(b);
00206 return rt *= d;
00207 }
00208
00209 template <int N, class T> inline
00210 vec<N,T> operator / ( const vec<N,T> & b, T d )
00211 { vec<N,T> rt(b); return rt /= d; }
00212
00213 template <int N, class T> inline
00214 vec<N,T> operator + ( const vec<N,T> & v1, const vec<N,T> & v2 )
00215 { vec<N,T> rt(v1); return rt += v2; }
00216
00217 template <int N, class T> inline
00218 vec<N,T> operator - ( const vec<N,T> & v1, const vec<N,T> & v2 )
00219 { vec<N,T> rt(v1); return rt -= v2; }
00220
00221
00222 template <int N, class T> inline
00223 bool operator == ( const vec<N,T> & v1, const vec<N,T> & v2 )
00224 {
00225 for(int i = 0; i < N; i++)
00226 if(v1.v[i] != v2.v[i])
00227 return false;
00228 return true;
00229 }
00230
00231 template <int N, class T> inline
00232 bool operator != ( const vec<N,T> & v1, const vec<N,T> & v2 )
00233 { return !(v1 == v2); }
00234
00235
00236 typedef vec<3,unsigned char> vec3ub;
00237 typedef vec<4,unsigned char> vec4ub;
00238
00239
00240
00241
00242
00243 namespace GLH_REAL_NAMESPACE
00244 {
00245 typedef GLH_REAL real;
00246
00247 class line;
00248 class plane;
00249 class matrix4;
00250 class quaternion;
00251 typedef quaternion rotation;
00252
00253 class vec2 : public vec<2,real>
00254 {
00255 public:
00256 vec2(const real & t = real()) : vec<2,real>(t)
00257 {}
00258 vec2(const vec<2,real> & t) : vec<2,real>(t)
00259 {}
00260 vec2(const real * tp) : vec<2,real>(tp)
00261 {}
00262
00263 vec2(real x, real y )
00264 { v[0] = x; v[1] = y; }
00265
00266 void get_value(real & x, real & y) const
00267 { x = v[0]; y = v[1]; }
00268
00269 vec2 & set_value( const real & x, const real & y)
00270 { v[0] = x; v[1] = y; return *this; }
00271
00272 };
00273
00274
00275 class vec3 : public vec<3,real>
00276 {
00277 public:
00278 vec3(const real & t = real()) : vec<3,real>(t)
00279 {}
00280 vec3(const vec<3,real> & t) : vec<3,real>(t)
00281 {}
00282 vec3(const real * tp) : vec<3,real>(tp)
00283 {}
00284
00285 vec3(real x, real y, real z)
00286 { v[0] = x; v[1] = y; v[2] = z; }
00287
00288 void get_value(real & x, real & y, real & z) const
00289 { x = v[0]; y = v[1]; z = v[2]; }
00290
00291 vec3 cross( const vec3 &rhs ) const
00292 {
00293 vec3 rt;
00294 rt.v[0] = v[1]*rhs.v[2]-v[2]*rhs.v[1];
00295 rt.v[1] = v[2]*rhs.v[0]-v[0]*rhs.v[2];
00296 rt.v[2] = v[0]*rhs.v[1]-v[1]*rhs.v[0];
00297 return rt;
00298 }
00299
00300 vec3 & set_value( const real & x, const real & y, const real & z)
00301 { v[0] = x; v[1] = y; v[2] = z; return *this; }
00302
00303 };
00304
00305
00306 class vec4 : public vec<4,real>
00307 {
00308 public:
00309 vec4(const real & t = real()) : vec<4,real>(t)
00310 {}
00311 vec4(const vec<4,real> & t) : vec<4,real>(t)
00312 {}
00313
00314 vec4(const vec<3,real> & t, real fourth)
00315
00316 { v[0] = t.v[0]; v[1] = t.v[1]; v[2] = t.v[2]; v[3] = fourth; }
00317 vec4(const real * tp) : vec<4,real>(tp)
00318 {}
00319 vec4(real x, real y, real z, real w)
00320 { v[0] = x; v[1] = y; v[2] = z; v[3] = w; }
00321
00322 void get_value(real & x, real & y, real & z, real & w) const
00323 { x = v[0]; y = v[1]; z = v[2]; w = v[3]; }
00324
00325 vec4 & set_value( const real & x, const real & y, const real & z, const real & w)
00326 { v[0] = x; v[1] = y; v[2] = z; v[3] = w; return *this; }
00327 };
00328
00329 inline
00330 vec3 homogenize(const vec4 & v)
00331 {
00332 vec3 rt;
00333 assert(v.v[3] != GLH_ZERO);
00334 rt.v[0] = v.v[0]/v.v[3];
00335 rt.v[1] = v.v[1]/v.v[3];
00336 rt.v[2] = v.v[2]/v.v[3];
00337 return rt;
00338 }
00339
00340
00341
00342 class line
00343 {
00344 public:
00345
00346 line()
00347 { set_value(vec3(0,0,0),vec3(0,0,1)); }
00348
00349 line( const vec3 & p0, const vec3 &p1)
00350 { set_value(p0,p1); }
00351
00352 void set_value( const vec3 &p0, const vec3 &p1)
00353 {
00354 position = p0;
00355 direction = p1-p0;
00356 direction.normalize();
00357 }
00358
00359 bool get_closest_points(const line &line2,
00360 vec3 &pointOnThis,
00361 vec3 &pointOnThat)
00362 {
00363
00364
00365 if(fabs(direction.dot(line2.direction)) == 1.0)
00366 return 0;
00367 line l2 = line2;
00368
00369
00370
00371 register real u;
00372 register real v;
00373 vec3 Vr = direction;
00374 vec3 Vs = l2.direction;
00375 register real Vr_Dot_Vs = Vr.dot(Vs);
00376 register real detA = real(1.0 - (Vr_Dot_Vs * Vr_Dot_Vs));
00377 vec3 C = l2.position - position;
00378 register real C_Dot_Vr = C.dot(Vr);
00379 register real C_Dot_Vs = C.dot(Vs);
00380
00381 u = (C_Dot_Vr - Vr_Dot_Vs * C_Dot_Vs)/detA;
00382 v = (C_Dot_Vr * Vr_Dot_Vs - C_Dot_Vs)/detA;
00383
00384 pointOnThis = position;
00385 pointOnThis += direction * u;
00386 pointOnThat = l2.position;
00387 pointOnThat += l2.direction * v;
00388
00389 return 1;
00390 }
00391
00392 vec3 get_closest_point(const vec3 &point)
00393 {
00394 vec3 np = point - position;
00395 vec3 rp = direction*direction.dot(np)+position;
00396 return rp;
00397 }
00398
00399 const vec3 & get_position() const {return position;}
00400
00401 const vec3 & get_direction() const {return direction;}
00402
00403
00404 vec3 position;
00405 vec3 direction;
00406 };
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439 class matrix4
00440 {
00441
00442 public:
00443
00444 matrix4() { make_identity(); }
00445
00446 matrix4( real r )
00447 { set_value(r); }
00448
00449 matrix4( real * m )
00450 { set_value(m); }
00451
00452 matrix4( real a00, real a01, real a02, real a03,
00453 real a10, real a11, real a12, real a13,
00454 real a20, real a21, real a22, real a23,
00455 real a30, real a31, real a32, real a33 )
00456 {
00457 element(0,0) = a00;
00458 element(0,1) = a01;
00459 element(0,2) = a02;
00460 element(0,3) = a03;
00461
00462 element(1,0) = a10;
00463 element(1,1) = a11;
00464 element(1,2) = a12;
00465 element(1,3) = a13;
00466
00467 element(2,0) = a20;
00468 element(2,1) = a21;
00469 element(2,2) = a22;
00470 element(2,3) = a23;
00471
00472 element(3,0) = a30;
00473 element(3,1) = a31;
00474 element(3,2) = a32;
00475 element(3,3) = a33;
00476 }
00477
00478
00479 void get_value( real * mp ) const
00480 {
00481 int c = 0;
00482 for(int j=0; j < 4; j++)
00483 for(int i=0; i < 4; i++)
00484 mp[c++] = element(i,j);
00485 }
00486
00487
00488 const real * get_value() const
00489 { return m; }
00490
00491 void set_value( real * mp)
00492 {
00493 int c = 0;
00494 for(int j=0; j < 4; j++)
00495 for(int i=0; i < 4; i++)
00496 element(i,j) = mp[c++];
00497 }
00498
00499 void set_value( real r )
00500 {
00501 for(int i=0; i < 4; i++)
00502 for(int j=0; j < 4; j++)
00503 element(i,j) = r;
00504 }
00505
00506 void make_identity()
00507 {
00508 element(0,0) = 1.0;
00509 element(0,1) = 0.0;
00510 element(0,2) = 0.0;
00511 element(0,3) = 0.0;
00512
00513 element(1,0) = 0.0;
00514 element(1,1) = 1.0;
00515 element(1,2) = 0.0;
00516 element(1,3) = 0.0;
00517
00518 element(2,0) = 0.0;
00519 element(2,1) = 0.0;
00520 element(2,2) = 1.0;
00521 element(2,3) = 0.0;
00522
00523 element(3,0) = 0.0;
00524 element(3,1) = 0.0;
00525 element(3,2) = 0.0;
00526 element(3,3) = 1.0;
00527 }
00528
00529
00530 static matrix4 identity()
00531 {
00532 static matrix4 mident (
00533 1.0, 0.0, 0.0, 0.0,
00534 0.0, 1.0, 0.0, 0.0,
00535 0.0, 0.0, 1.0, 0.0,
00536 0.0, 0.0, 0.0, 1.0 );
00537 return mident;
00538 }
00539
00540
00541 void set_scale( real s )
00542 {
00543 element(0,0) = s;
00544 element(1,1) = s;
00545 element(2,2) = s;
00546 }
00547
00548 void set_scale( const vec3 & s )
00549 {
00550 element(0,0) = s.v[0];
00551 element(1,1) = s.v[1];
00552 element(2,2) = s.v[2];
00553 }
00554
00555
00556 void set_translate( const vec3 & t )
00557 {
00558 element(0,3) = t.v[0];
00559 element(1,3) = t.v[1];
00560 element(2,3) = t.v[2];
00561 }
00562
00563 void set_row(int r, const vec4 & t)
00564 {
00565 element(r,0) = t.v[0];
00566 element(r,1) = t.v[1];
00567 element(r,2) = t.v[2];
00568 element(r,3) = t.v[3];
00569 }
00570
00571 void set_column(int c, const vec4 & t)
00572 {
00573 element(0,c) = t.v[0];
00574 element(1,c) = t.v[1];
00575 element(2,c) = t.v[2];
00576 element(3,c) = t.v[3];
00577 }
00578
00579
00580 void get_row(int r, vec4 & t) const
00581 {
00582 t.v[0] = element(r,0);
00583 t.v[1] = element(r,1);
00584 t.v[2] = element(r,2);
00585 t.v[3] = element(r,3);
00586 }
00587
00588 vec4 get_row(int r) const
00589 {
00590 vec4 v; get_row(r, v);
00591 return v;
00592 }
00593
00594 void get_column(int c, vec4 & t) const
00595 {
00596 t.v[0] = element(0,c);
00597 t.v[1] = element(1,c);
00598 t.v[2] = element(2,c);
00599 t.v[3] = element(3,c);
00600 }
00601
00602 vec4 get_column(int c) const
00603 {
00604 vec4 v; get_column(c, v);
00605 return v;
00606 }
00607
00608 matrix4 inverse() const
00609 {
00610 matrix4 minv;
00611
00612 real r1[8], r2[8], r3[8], r4[8];
00613 real *s[4], *tmprow;
00614
00615 s[0] = &r1[0];
00616 s[1] = &r2[0];
00617 s[2] = &r3[0];
00618 s[3] = &r4[0];
00619
00620 register int i,j,p,jj;
00621 for(i=0;i<4;i++)
00622 {
00623 for(j=0;j<4;j++)
00624 {
00625 s[i][j] = element(i,j);
00626 if(i==j) s[i][j+4] = 1.0;
00627 else s[i][j+4] = 0.0;
00628 }
00629 }
00630 real scp[4];
00631 for(i=0;i<4;i++)
00632 {
00633 scp[i] = real(fabs(s[i][0]));
00634 for(j=1;j<4;j++)
00635 if(real(fabs(s[i][j])) > scp[i]) scp[i] = real(fabs(s[i][j]));
00636 if(scp[i] == 0.0) return minv;
00637 }
00638
00639 int pivot_to;
00640 real scp_max;
00641 for(i=0;i<4;i++)
00642 {
00643
00644 pivot_to = i;
00645 scp_max = real(fabs(s[i][i]/scp[i]));
00646
00647 for(p=i+1;p<4;p++)
00648 if(real(fabs(s[p][i]/scp[p])) > scp_max)
00649 { scp_max = real(fabs(s[p][i]/scp[p])); pivot_to = p; }
00650
00651 if(pivot_to != i)
00652 {
00653 tmprow = s[i];
00654 s[i] = s[pivot_to];
00655 s[pivot_to] = tmprow;
00656 real tmpscp;
00657 tmpscp = scp[i];
00658 scp[i] = scp[pivot_to];
00659 scp[pivot_to] = tmpscp;
00660 }
00661
00662 real mji;
00663
00664 for(j=i+1;j<4;j++)
00665 {
00666 mji = s[j][i]/s[i][i];
00667 s[j][i] = 0.0;
00668 for(jj=i+1;jj<8;jj++)
00669 s[j][jj] -= mji*s[i][jj];
00670 }
00671 }
00672 if(s[3][3] == 0.0) return minv;
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 real mij;
00691 for(i=3;i>0;i--)
00692 {
00693 for(j=i-1;j > -1; j--)
00694 {
00695 mij = s[j][i]/s[i][i];
00696 for(jj=j+1;jj<8;jj++)
00697 s[j][jj] -= mij*s[i][jj];
00698 }
00699 }
00700
00701 for(i=0;i<4;i++)
00702 for(j=0;j<4;j++)
00703 minv(i,j) = s[i][j+4] / s[i][i];
00704
00705 return minv;
00706 }
00707
00708
00709 matrix4 transpose() const
00710 {
00711 matrix4 mtrans;
00712
00713 for(int i=0;i<4;i++)
00714 for(int j=0;j<4;j++)
00715 mtrans(i,j) = element(j,i);
00716 return mtrans;
00717 }
00718
00719 matrix4 & mult_right( const matrix4 & b )
00720 {
00721 matrix4 mt(*this);
00722 set_value(real(0));
00723
00724 for(int i=0; i < 4; i++)
00725 for(int j=0; j < 4; j++)
00726 for(int c=0; c < 4; c++)
00727 element(i,j) += mt(i,c) * b(c,j);
00728 return *this;
00729 }
00730
00731 matrix4 & mult_left( const matrix4 & b )
00732 {
00733 matrix4 mt(*this);
00734 set_value(real(0));
00735
00736 for(int i=0; i < 4; i++)
00737 for(int j=0; j < 4; j++)
00738 for(int c=0; c < 4; c++)
00739 element(i,j) += b(i,c) * mt(c,j);
00740 return *this;
00741 }
00742
00743
00744 void mult_matrix_vec( const vec3 &src, vec3 &dst ) const
00745 {
00746 real w = (
00747 src.v[0] * element(3,0) +
00748 src.v[1] * element(3,1) +
00749 src.v[2] * element(3,2) +
00750 element(3,3) );
00751
00752 assert(w != GLH_ZERO);
00753
00754 dst.v[0] = (
00755 src.v[0] * element(0,0) +
00756 src.v[1] * element(0,1) +
00757 src.v[2] * element(0,2) +
00758 element(0,3) ) / w;
00759 dst.v[1] = (
00760 src.v[0] * element(1,0) +
00761 src.v[1] * element(1,1) +
00762 src.v[2] * element(1,2) +
00763 element(1,3) ) / w;
00764 dst.v[2] = (
00765 src.v[0] * element(2,0) +
00766 src.v[1] * element(2,1) +
00767 src.v[2] * element(2,2) +
00768 element(2,3) ) / w;
00769 }
00770
00771 void mult_matrix_vec( vec3 & src_and_dst) const
00772 { mult_matrix_vec(vec3(src_and_dst), src_and_dst); }
00773
00774
00775
00776 void mult_vec_matrix( const vec3 &src, vec3 &dst ) const
00777 {
00778 real w = (
00779 src.v[0] * element(0,3) +
00780 src.v[1] * element(1,3) +
00781 src.v[2] * element(2,3) +
00782 element(3,3) );
00783
00784 assert(w != GLH_ZERO);
00785
00786 dst.v[0] = (
00787 src.v[0] * element(0,0) +
00788 src.v[1] * element(1,0) +
00789 src.v[2] * element(2,0) +
00790 element(3,0) ) / w;
00791 dst.v[1] = (
00792 src.v[0] * element(0,1) +
00793 src.v[1] * element(1,1) +
00794 src.v[2] * element(2,1) +
00795 element(3,1) ) / w;
00796 dst.v[2] = (
00797 src.v[0] * element(0,2) +
00798 src.v[1] * element(1,2) +
00799 src.v[2] * element(2,2) +
00800 element(3,2) ) / w;
00801 }
00802
00803
00804 void mult_vec_matrix( vec3 & src_and_dst) const
00805 { mult_vec_matrix(vec3(src_and_dst), src_and_dst); }
00806
00807
00808 void mult_matrix_vec( const vec4 &src, vec4 &dst ) const
00809 {
00810 dst.v[0] = (
00811 src.v[0] * element(0,0) +
00812 src.v[1] * element(0,1) +
00813 src.v[2] * element(0,2) +
00814 src.v[3] * element(0,3));
00815 dst.v[1] = (
00816 src.v[0] * element(1,0) +
00817 src.v[1] * element(1,1) +
00818 src.v[2] * element(1,2) +
00819 src.v[3] * element(1,3));
00820 dst.v[2] = (
00821 src.v[0] * element(2,0) +
00822 src.v[1] * element(2,1) +
00823 src.v[2] * element(2,2) +
00824 src.v[3] * element(2,3));
00825 dst.v[3] = (
00826 src.v[0] * element(3,0) +
00827 src.v[1] * element(3,1) +
00828 src.v[2] * element(3,2) +
00829 src.v[3] * element(3,3));
00830 }
00831
00832 void mult_matrix_vec( vec4 & src_and_dst) const
00833 { mult_matrix_vec(vec4(src_and_dst), src_and_dst); }
00834
00835
00836
00837 void mult_vec_matrix( const vec4 &src, vec4 &dst ) const
00838 {
00839 dst.v[0] = (
00840 src.v[0] * element(0,0) +
00841 src.v[1] * element(1,0) +
00842 src.v[2] * element(2,0) +
00843 src.v[3] * element(3,0));
00844 dst.v[1] = (
00845 src.v[0] * element(0,1) +
00846 src.v[1] * element(1,1) +
00847 src.v[2] * element(2,1) +
00848 src.v[3] * element(3,1));
00849 dst.v[2] = (
00850 src.v[0] * element(0,2) +
00851 src.v[1] * element(1,2) +
00852 src.v[2] * element(2,2) +
00853 src.v[3] * element(3,2));
00854 dst.v[3] = (
00855 src.v[0] * element(0,3) +
00856 src.v[1] * element(1,3) +
00857 src.v[2] * element(2,3) +
00858 src.v[3] * element(3,3));
00859 }
00860
00861
00862 void mult_vec_matrix( vec4 & src_and_dst) const
00863 { mult_vec_matrix(vec4(src_and_dst), src_and_dst); }
00864
00865
00866
00867 void mult_matrix_dir( const vec3 &src, vec3 &dst ) const
00868 {
00869 dst.v[0] = (
00870 src.v[0] * element(0,0) +
00871 src.v[1] * element(0,1) +
00872 src.v[2] * element(0,2) ) ;
00873 dst.v[1] = (
00874 src.v[0] * element(1,0) +
00875 src.v[1] * element(1,1) +
00876 src.v[2] * element(1,2) ) ;
00877 dst.v[2] = (
00878 src.v[0] * element(2,0) +
00879 src.v[1] * element(2,1) +
00880 src.v[2] * element(2,2) ) ;
00881 }
00882
00883
00884 void mult_matrix_dir( vec3 & src_and_dst) const
00885 { mult_matrix_dir(vec3(src_and_dst), src_and_dst); }
00886
00887
00888
00889 void mult_dir_matrix( const vec3 &src, vec3 &dst ) const
00890 {
00891 dst.v[0] = (
00892 src.v[0] * element(0,0) +
00893 src.v[1] * element(1,0) +
00894 src.v[2] * element(2,0) ) ;
00895 dst.v[1] = (
00896 src.v[0] * element(0,1) +
00897 src.v[1] * element(1,1) +
00898 src.v[2] * element(2,1) ) ;
00899 dst.v[2] = (
00900 src.v[0] * element(0,2) +
00901 src.v[1] * element(1,2) +
00902 src.v[2] * element(2,2) ) ;
00903 }
00904
00905
00906 void mult_dir_matrix( vec3 & src_and_dst) const
00907 { mult_dir_matrix(vec3(src_and_dst), src_and_dst); }
00908
00909
00910 real & operator () (int row, int col)
00911 { return element(row,col); }
00912
00913 const real & operator () (int row, int col) const
00914 { return element(row,col); }
00915
00916 real & element (int row, int col)
00917 { return m[row | (col<<2)]; }
00918
00919 const real & element (int row, int col) const
00920 { return m[row | (col<<2)]; }
00921
00922 matrix4 & operator *= ( const matrix4 & mat )
00923 {
00924 mult_right( mat );
00925 return *this;
00926 }
00927
00928 matrix4 & operator *= ( const real & r )
00929 {
00930 for (int i = 0; i < 4; ++i)
00931 {
00932 element(0,i) *= r;
00933 element(1,i) *= r;
00934 element(2,i) *= r;
00935 element(3,i) *= r;
00936 }
00937 return *this;
00938 }
00939
00940 matrix4 & operator += ( const matrix4 & mat )
00941 {
00942 for (int i = 0; i < 4; ++i)
00943 {
00944 element(0,i) += mat.element(0,i);
00945 element(1,i) += mat.element(1,i);
00946 element(2,i) += mat.element(2,i);
00947 element(3,i) += mat.element(3,i);
00948 }
00949 return *this;
00950 }
00951
00952 friend matrix4 operator * ( const matrix4 & m1, const matrix4 & m2 );
00953 friend bool operator == ( const matrix4 & m1, const matrix4 & m2 );
00954 friend bool operator != ( const matrix4 & m1, const matrix4 & m2 );
00955
00956
00957 real m[16];
00958 };
00959
00960 inline
00961 matrix4 operator * ( const matrix4 & m1, const matrix4 & m2 )
00962 {
00963 matrix4 product;
00964
00965 product = m1;
00966 product.mult_right(m2);
00967
00968 return product;
00969 }
00970
00971 inline
00972 bool operator ==( const matrix4 &m1, const matrix4 &m2 )
00973 {
00974 return (
00975 m1(0,0) == m2(0,0) &&
00976 m1(0,1) == m2(0,1) &&
00977 m1(0,2) == m2(0,2) &&
00978 m1(0,3) == m2(0,3) &&
00979 m1(1,0) == m2(1,0) &&
00980 m1(1,1) == m2(1,1) &&
00981 m1(1,2) == m2(1,2) &&
00982 m1(1,3) == m2(1,3) &&
00983 m1(2,0) == m2(2,0) &&
00984 m1(2,1) == m2(2,1) &&
00985 m1(2,2) == m2(2,2) &&
00986 m1(2,3) == m2(2,3) &&
00987 m1(3,0) == m2(3,0) &&
00988 m1(3,1) == m2(3,1) &&
00989 m1(3,2) == m2(3,2) &&
00990 m1(3,3) == m2(3,3) );
00991 }
00992
00993 inline
00994 bool operator != ( const matrix4 & m1, const matrix4 & m2 )
00995 { return !( m1 == m2 ); }
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009 class quaternion
01010 {
01011 public:
01012
01013 quaternion()
01014 {
01015 *this = identity();
01016 }
01017
01018 quaternion( const real v[4] )
01019 {
01020 set_value( v );
01021 }
01022
01023
01024 quaternion( real q0, real q1, real q2, real q3 )
01025 {
01026 set_value( q0, q1, q2, q3 );
01027 }
01028
01029
01030 quaternion( const matrix4 & m )
01031 {
01032 set_value( m );
01033 }
01034
01035
01036 quaternion( const vec3 &axis, real radians )
01037 {
01038 set_value( axis, radians );
01039 }
01040
01041
01042 quaternion( const vec3 &rotateFrom, const vec3 &rotateTo )
01043 {
01044 set_value( rotateFrom, rotateTo );
01045 }
01046
01047 quaternion( const vec3 & from_look, const vec3 & from_up,
01048 const vec3 & to_look, const vec3& to_up)
01049 {
01050 set_value(from_look, from_up, to_look, to_up);
01051 }
01052
01053 const real * get_value() const
01054 {
01055 return &q[0];
01056 }
01057
01058 void get_value( real &q0, real &q1, real &q2, real &q3 ) const
01059 {
01060 q0 = q[0];
01061 q1 = q[1];
01062 q2 = q[2];
01063 q3 = q[3];
01064 }
01065
01066 quaternion & set_value( real q0, real q1, real q2, real q3 )
01067 {
01068 q[0] = q0;
01069 q[1] = q1;
01070 q[2] = q2;
01071 q[3] = q3;
01072 counter = 0;
01073 return *this;
01074 }
01075
01076 void get_value( vec3 &axis, real &radians ) const
01077 {
01078 radians = real(acos( q[3] ) * GLH_TWO);
01079 if ( radians == GLH_ZERO )
01080 axis = vec3( 0.0, 0.0, 1.0 );
01081 else
01082 {
01083 axis.v[0] = q[0];
01084 axis.v[1] = q[1];
01085 axis.v[2] = q[2];
01086 axis.normalize();
01087 }
01088 }
01089
01090 void get_value( matrix4 & m ) const
01091 {
01092 real s, xs, ys, zs, wx, wy, wz, xx, xy, xz, yy, yz, zz;
01093
01094 real norm = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3];
01095
01096 s = (equivalent(norm,GLH_ZERO)) ? GLH_ZERO : ( GLH_TWO / norm );
01097
01098 xs = q[0] * s;
01099 ys = q[1] * s;
01100 zs = q[2] * s;
01101
01102 wx = q[3] * xs;
01103 wy = q[3] * ys;
01104 wz = q[3] * zs;
01105
01106 xx = q[0] * xs;
01107 xy = q[0] * ys;
01108 xz = q[0] * zs;
01109
01110 yy = q[1] * ys;
01111 yz = q[1] * zs;
01112 zz = q[2] * zs;
01113
01114 m(0,0) = real( GLH_ONE - ( yy + zz ));
01115 m(1,0) = real ( xy + wz );
01116 m(2,0) = real ( xz - wy );
01117
01118 m(0,1) = real ( xy - wz );
01119 m(1,1) = real ( GLH_ONE - ( xx + zz ));
01120 m(2,1) = real ( yz + wx );
01121
01122 m(0,2) = real ( xz + wy );
01123 m(1,2) = real ( yz - wx );
01124 m(2,2) = real ( GLH_ONE - ( xx + yy ));
01125
01126 m(3,0) = m(3,1) = m(3,2) = m(0,3) = m(1,3) = m(2,3) = GLH_ZERO;
01127 m(3,3) = GLH_ONE;
01128 }
01129
01130 quaternion & set_value( const real * qp )
01131 {
01132 memcpy(q,qp,sizeof(real) * 4);
01133
01134 counter = 0;
01135 return *this;
01136 }
01137
01138 quaternion & set_value( const matrix4 & m )
01139 {
01140 real tr, s;
01141 int i, j, k;
01142 const int nxt[3] = { 1, 2, 0 };
01143
01144 tr = m(0,0) + m(1,1) + m(2,2);
01145
01146 if ( tr > GLH_ZERO )
01147 {
01148 s = real(sqrt( tr + m(3,3) ));
01149 q[3] = real ( s * 0.5 );
01150 s = real(0.5) / s;
01151
01152 q[0] = real ( ( m(1,2) - m(2,1) ) * s );
01153 q[1] = real ( ( m(2,0) - m(0,2) ) * s );
01154 q[2] = real ( ( m(0,1) - m(1,0) ) * s );
01155 }
01156 else
01157 {
01158 i = 0;
01159 if ( m(1,1) > m(0,0) )
01160 i = 1;
01161
01162 if ( m(2,2) > m(i,i) )
01163 i = 2;
01164
01165 j = nxt[i];
01166 k = nxt[j];
01167
01168 s = real(sqrt( ( m(i,j) - ( m(j,j) + m(k,k) )) + GLH_ONE ));
01169
01170 q[i] = real ( s * 0.5 );
01171 s = real(0.5 / s);
01172
01173 q[3] = real ( ( m(j,k) - m(k,j) ) * s );
01174 q[j] = real ( ( m(i,j) + m(j,i) ) * s );
01175 q[k] = real ( ( m(i,k) + m(k,i) ) * s );
01176 }
01177
01178 counter = 0;
01179 return *this;
01180 }
01181
01182 quaternion & set_value( const vec3 &axis, real theta )
01183 {
01184 real sqnorm = axis.square_norm();
01185
01186 if (sqnorm <= GLH_EPSILON)
01187 {
01188
01189 x = y = z = 0.0;
01190 w = 1.0;
01191 }
01192 else
01193 {
01194 theta *= real(0.5);
01195 real sin_theta = real(sin(theta));
01196
01197 if (!equivalent(sqnorm,GLH_ONE))
01198 sin_theta /= real(sqrt(sqnorm));
01199 x = sin_theta * axis.v[0];
01200 y = sin_theta * axis.v[1];
01201 z = sin_theta * axis.v[2];
01202 w = real(cos(theta));
01203 }
01204 return *this;
01205 }
01206
01207 quaternion & set_value( const vec3 & rotateFrom, const vec3 & rotateTo )
01208 {
01209 vec3 p1, p2;
01210 real alpha;
01211
01212 p1 = rotateFrom;
01213 p1.normalize();
01214 p2 = rotateTo;
01215 p2.normalize();
01216
01217 alpha = p1.dot(p2);
01218
01219 if(equivalent(alpha,GLH_ONE))
01220 {
01221 *this = identity();
01222 return *this;
01223 }
01224
01225
01226 if(equivalent(alpha,-GLH_ONE))
01227 {
01228 vec3 v;
01229
01230 if(p1.v[0] != p1.v[1] || p1.v[0] != p1.v[2])
01231 v = vec3(p1.v[1], p1.v[2], p1.v[0]);
01232 else
01233 v = vec3(-p1.v[0], p1.v[1], p1.v[2]);
01234
01235 v -= p1 * p1.dot(v);
01236 v.normalize();
01237
01238 set_value(v, GLH_PI);
01239 return *this;
01240 }
01241
01242 p1 = p1.cross(p2);
01243 p1.normalize();
01244 set_value(p1,real(acos(alpha)));
01245
01246 counter = 0;
01247 return *this;
01248 }
01249
01250 quaternion & set_value( const vec3 & from_look, const vec3 & from_up,
01251 const vec3 & to_look, const vec3 & to_up)
01252 {
01253 quaternion r_look = quaternion(from_look, to_look);
01254
01255 vec3 rotated_from_up(from_up);
01256 r_look.mult_vec(rotated_from_up);
01257
01258 quaternion r_twist = quaternion(rotated_from_up, to_up);
01259
01260 *this = r_twist;
01261 *this *= r_look;
01262 return *this;
01263 }
01264
01265 quaternion & operator *= ( const quaternion & qr )
01266 {
01267 quaternion ql(*this);
01268
01269 w = ql.w * qr.w - ql.x * qr.x - ql.y * qr.y - ql.z * qr.z;
01270 x = ql.w * qr.x + ql.x * qr.w + ql.y * qr.z - ql.z * qr.y;
01271 y = ql.w * qr.y + ql.y * qr.w + ql.z * qr.x - ql.x * qr.z;
01272 z = ql.w * qr.z + ql.z * qr.w + ql.x * qr.y - ql.y * qr.x;
01273
01274 counter += qr.counter;
01275 counter++;
01276 counter_normalize();
01277 return *this;
01278 }
01279
01280 void normalize()
01281 {
01282 real rnorm = GLH_ONE / real(sqrt(w * w + x * x + y * y + z * z));
01283 if (equivalent(rnorm, GLH_ZERO))
01284 return;
01285 x *= rnorm;
01286 y *= rnorm;
01287 z *= rnorm;
01288 w *= rnorm;
01289 counter = 0;
01290 }
01291
01292 friend bool operator == ( const quaternion & q1, const quaternion & q2 );
01293
01294 friend bool operator != ( const quaternion & q1, const quaternion & q2 );
01295
01296 friend quaternion operator * ( const quaternion & q1, const quaternion & q2 );
01297
01298 bool equals( const quaternion & r, real tolerance ) const
01299 {
01300 real t;
01301
01302 t = (
01303 (q[0]-r.q[0])*(q[0]-r.q[0]) +
01304 (q[1]-r.q[1])*(q[1]-r.q[1]) +
01305 (q[2]-r.q[2])*(q[2]-r.q[2]) +
01306 (q[3]-r.q[3])*(q[3]-r.q[3]) );
01307 if(t > GLH_EPSILON)
01308 return false;
01309 return 1;
01310 }
01311
01312 quaternion & conjugate()
01313 {
01314 q[0] *= -GLH_ONE;
01315 q[1] *= -GLH_ONE;
01316 q[2] *= -GLH_ONE;
01317 return *this;
01318 }
01319
01320 quaternion & invert()
01321 {
01322 return conjugate();
01323 }
01324
01325 quaternion inverse() const
01326 {
01327 quaternion r = *this;
01328 return r.invert();
01329 }
01330
01331
01332
01333
01334
01335 void mult_vec( const vec3 &src, vec3 &dst ) const
01336 {
01337 real v_coef = w * w - x * x - y * y - z * z;
01338 real u_coef = GLH_TWO * (src.v[0] * x + src.v[1] * y + src.v[2] * z);
01339 real c_coef = GLH_TWO * w;
01340
01341 dst.v[0] = v_coef * src.v[0] + u_coef * x + c_coef * (y * src.v[2] - z * src.v[1]);
01342 dst.v[1] = v_coef * src.v[1] + u_coef * y + c_coef * (z * src.v[0] - x * src.v[2]);
01343 dst.v[2] = v_coef * src.v[2] + u_coef * z + c_coef * (x * src.v[1] - y * src.v[0]);
01344 }
01345
01346 void mult_vec( vec3 & src_and_dst) const
01347 {
01348 mult_vec(vec3(src_and_dst), src_and_dst);
01349 }
01350
01351 void scale_angle( real scaleFactor )
01352 {
01353 vec3 axis;
01354 real radians;
01355
01356 get_value(axis, radians);
01357 radians *= scaleFactor;
01358 set_value(axis, radians);
01359 }
01360
01361 static quaternion slerp( const quaternion & p, const quaternion & q, real alpha )
01362 {
01363 quaternion r;
01364
01365 real cos_omega = p.x * q.x + p.y * q.y + p.z * q.z + p.w * q.w;
01366
01367
01368 int bflip;
01369 if ( ( bflip = (cos_omega < GLH_ZERO)) )
01370 cos_omega = -cos_omega;
01371
01372
01373 real beta = GLH_ONE - alpha;
01374
01375 if(cos_omega >= GLH_ONE - GLH_EPSILON)
01376 return p;
01377
01378 real omega = real(acos(cos_omega));
01379 real one_over_sin_omega = GLH_ONE / real(sin(omega));
01380
01381 beta = real(sin(omega*beta) * one_over_sin_omega);
01382 alpha = real(sin(omega*alpha) * one_over_sin_omega);
01383
01384 if (bflip)
01385 alpha = -alpha;
01386
01387 r.x = beta * p.q[0]+ alpha * q.q[0];
01388 r.y = beta * p.q[1]+ alpha * q.q[1];
01389 r.z = beta * p.q[2]+ alpha * q.q[2];
01390 r.w = beta * p.q[3]+ alpha * q.q[3];
01391 return r;
01392 }
01393
01394 static quaternion identity()
01395 {
01396 static quaternion ident( vec3( 0.0, 0.0, 0.0 ), GLH_ONE );
01397 return ident;
01398 }
01399
01400 real & operator []( int i )
01401 {
01402 assert(i < 4);
01403 return q[i];
01404 }
01405
01406 const real & operator []( int i ) const
01407 {
01408 assert(i < 4);
01409 return q[i];
01410 }
01411
01412 protected:
01413
01414 void counter_normalize()
01415 {
01416 if (counter > GLH_QUATERNION_NORMALIZATION_THRESHOLD)
01417 normalize();
01418 }
01419
01420 union
01421 {
01422 struct
01423 {
01424 real q[4];
01425 };
01426 struct
01427 {
01428 real x;
01429 real y;
01430 real z;
01431 real w;
01432 };
01433 };
01434
01435
01436 unsigned char counter;
01437 };
01438
01439 inline
01440 bool operator == ( const quaternion & q1, const quaternion & q2 )
01441 {
01442 return (equivalent(q1.x, q2.x) &&
01443 equivalent(q1.y, q2.y) &&
01444 equivalent(q1.z, q2.z) &&
01445 equivalent(q1.w, q2.w) );
01446 }
01447
01448 inline
01449 bool operator != ( const quaternion & q1, const quaternion & q2 )
01450 {
01451 return ! ( q1 == q2 );
01452 }
01453
01454 inline
01455 quaternion operator * ( const quaternion & q1, const quaternion & q2 )
01456 {
01457 quaternion r(q1);
01458 r *= q2;
01459 return r;
01460 }
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471 class plane
01472 {
01473 public:
01474
01475 plane()
01476 {
01477 planedistance = 0.0;
01478 planenormal.set_value( 0.0, 0.0, 1.0 );
01479 }
01480
01481
01482 plane( const vec3 &p0, const vec3 &p1, const vec3 &p2 )
01483 {
01484 vec3 v0 = p1 - p0;
01485 vec3 v1 = p2 - p0;
01486 planenormal = v0.cross(v1);
01487 planenormal.normalize();
01488 planedistance = p0.dot(planenormal);
01489 }
01490
01491 plane( const vec3 &normal, real distance )
01492 {
01493 planedistance = distance;
01494 planenormal = normal;
01495 planenormal.normalize();
01496 }
01497
01498 plane( const vec3 &normal, const vec3 &point )
01499 {
01500 planenormal = normal;
01501 planenormal.normalize();
01502 planedistance = point.dot(planenormal);
01503 }
01504
01505 void offset( real d )
01506 {
01507 planedistance += d;
01508 }
01509
01510 bool intersect( const line &l, vec3 &intersection ) const
01511 {
01512 vec3 pos, dir;
01513 vec3 pn = planenormal;
01514 real pd = planedistance;
01515
01516 pos = l.get_position();
01517 dir = l.get_direction();
01518
01519 if(dir.dot(pn) == 0.0) return 0;
01520 pos -= pn*pd;
01521
01522 if(pos.dot(pn) < 0.0) pn.negate();
01523 if(dir.dot(pn) > 0.0) dir.negate();
01524 vec3 ppos = pn * pos.dot(pn);
01525 pos = (ppos.length()/dir.dot(-pn))*dir;
01526 intersection = l.get_position();
01527 intersection += pos;
01528 return 1;
01529 }
01530 void transform( const matrix4 &matrix )
01531 {
01532 matrix4 invtr = matrix.inverse();
01533 invtr = invtr.transpose();
01534
01535 vec3 pntOnplane = planenormal * planedistance;
01536 vec3 newPntOnplane;
01537 vec3 newnormal;
01538
01539 invtr.mult_dir_matrix(planenormal, newnormal);
01540 matrix.mult_vec_matrix(pntOnplane, newPntOnplane);
01541
01542 newnormal.normalize();
01543 planenormal = newnormal;
01544 planedistance = newPntOnplane.dot(planenormal);
01545 }
01546
01547 bool is_in_half_space( const vec3 &point ) const
01548 {
01549
01550 if(( point.dot(planenormal) - planedistance) < 0.0)
01551 return 0;
01552 return 1;
01553 }
01554
01555
01556 real distance( const vec3 & point ) const
01557 {
01558 return planenormal.dot(point - planenormal*planedistance);
01559 }
01560
01561 const vec3 &get_normal() const
01562 {
01563 return planenormal;
01564 }
01565
01566
01567 real get_distance_from_origin() const
01568 {
01569 return planedistance;
01570 }
01571
01572
01573 friend bool operator == ( const plane & p1, const plane & p2 );
01574
01575
01576 friend bool operator != ( const plane & p1, const plane & p2 );
01577
01578
01579 vec3 planenormal;
01580 real planedistance;
01581 };
01582
01583 inline
01584 bool operator == (const plane & p1, const plane & p2 )
01585 {
01586 return ( p1.planedistance == p2.planedistance && p1.planenormal == p2.planenormal);
01587 }
01588
01589 inline
01590 bool operator != ( const plane & p1, const plane & p2 )
01591 { return ! (p1 == p2); }
01592
01593
01594
01595 }
01596
01597
01598 #ifdef GLH_REAL_IS_FLOAT
01599 typedef GLH_REAL_NAMESPACE::vec2 vec2f;
01600 typedef GLH_REAL_NAMESPACE::vec3 vec3f;
01601 typedef GLH_REAL_NAMESPACE::vec4 vec4f;
01602 typedef GLH_REAL_NAMESPACE::quaternion quaternionf;
01603 typedef GLH_REAL_NAMESPACE::quaternion rotationf;
01604 typedef GLH_REAL_NAMESPACE::line linef;
01605 typedef GLH_REAL_NAMESPACE::plane planef;
01606 typedef GLH_REAL_NAMESPACE::matrix4 matrix4f;
01607 #endif
01608
01609
01610
01611
01612 }
01613
01614
01615
01616 #endif
01617