glh_linear.h
Go to the documentation of this file.
00001 /*
00002     glh - is a platform-indepenedent C++ OpenGL helper library 
00003 
00004 
00005     Copyright (c) 2000 Cass Everitt
00006         Copyright (c) 2000 NVIDIA Corporation
00007     All rights reserved.
00008 
00009     Redistribution and use in source and binary forms, with or
00010         without modification, are permitted provided that the following
00011         conditions are met:
00012 
00013      * Redistributions of source code must retain the above
00014            copyright notice, this list of conditions and the following
00015            disclaimer.
00016 
00017      * Redistributions in binary form must reproduce the above
00018            copyright notice, this list of conditions and the following
00019            disclaimer in the documentation and/or other materials
00020            provided with the distribution.
00021 
00022      * The names of contributors to this software may not be used
00023            to endorse or promote products derived from this software
00024            without specific prior written permission. 
00025 
00026        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027            ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028            LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00029            FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00030            REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00031            INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00032            BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00033            LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00034            CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00035            LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00036            ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
00037            POSSIBILITY OF SUCH DAMAGE. 
00038 
00039 
00040     Cass Everitt - cass@r3.nu
00041 */
00042 
00043 /*
00044 glh_linear.h
00045 */
00046 
00047 // Author:  Cass W. Everitt
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 // only supports float for now...
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                 //friend bool operator == TEMPLATE_FUNCTION ( const vec<N,T> &v1, const vec<N,T> &v2 );
00180                 //friend bool operator != TEMPLATE_FUNCTION ( const vec<N,T> &v1, const vec<N,T> &v2 );
00181                 
00182                 
00183         //protected:
00184                 T v[N];
00185         };
00186         
00187         
00188         
00189         // vector friend operators
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           // quick check to see if parallel -- if so, quit.
00365           if(fabs(direction.dot(line2.direction)) == 1.0)
00366                   return 0;
00367           line l2 = line2;
00368   
00369           // Algorithm: Brian Jean
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     //protected:
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   // matrix
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; // singular matrix!
00637                 }
00638                 
00639                 int pivot_to;
00640                 real scp_max;
00641                 for(i=0;i<4;i++)
00642                 {
00643                         // select pivot row
00644                         pivot_to = i;
00645                         scp_max = real(fabs(s[i][i]/scp[i]));
00646                         // find out which row should be on top
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                                 // Pivot if necessary
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                                 // perform gaussian elimination
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; // singular matrix!
00673                 
00674                 //
00675                 // Now we have an upper triangular matrix.
00676                 //
00677                 //  x x x x | y y y y
00678                 //  0 x x x | y y y y 
00679                 //  0 0 x x | y y y y
00680                 //  0 0 0 x | y y y y
00681                 //
00682                 //  we'll back substitute to get the inverse
00683                 //
00684                 //  1 0 0 0 | z z z z
00685                 //  0 1 0 0 | z z z z
00686                 //  0 0 1 0 | z z z z
00687                 //  0 0 0 1 | z z z z 
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         // dst = M * src
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     // dst = src * M
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         // dst = M * src
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     // dst = src * M
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     // dst = M * src
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         // dst = src * M
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   //protected:
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             // axis too small.
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         // ensures that the anti-parallel case leads to a positive dot
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     // Quaternion multiplication with cartesian vector
01333     // v' = q*v*q(star)
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         // if B is on opposite hemisphere from A, use -B instead
01367       
01368         int bflip;
01369         if ( ( bflip = (cos_omega < GLH_ZERO)) )
01370             cos_omega = -cos_omega;
01371 
01372         // complementary interpolation parameter
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         // renormalization counter
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                   // now we're talking about a plane passing through the origin
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   //protected:
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   } // "ns_##GLH_REAL"
01596 
01597   // make common typedefs...
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 }  // namespace glh
01613 
01614 
01615 
01616 #endif
01617 


nao_openni
Author(s): Bener SUAY
autogenerated on Mon Jan 6 2014 11:27:50