Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/g4tools/include/tools/lina/qrot

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /externals/g4tools/include/tools/lina/qrot (Version 11.3.0) and /externals/g4tools/include/tools/lina/qrot (Version 11.2.2)


  1 // Copyright (C) 2010, Guy Barrand. All rights      1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
  2 // See the file tools.license for terms.            2 // See the file tools.license for terms.
  3                                                     3 
  4 #ifndef tools_qrot                                  4 #ifndef tools_qrot
  5 #define tools_qrot                                  5 #define tools_qrot
  6                                                     6 
  7 // rotation done with quaternion.                   7 // rotation done with quaternion.
  8                                                     8 
  9 namespace tools {                                   9 namespace tools {
 10                                                    10 
 11 template <class VEC3,class VEC4>                   11 template <class VEC3,class VEC4>
 12 class qrot {                                       12 class qrot {
 13 protected:                                         13 protected:
 14 //typedef typename VEC3::elem_t T3;                14 //typedef typename VEC3::elem_t T3;
 15   typedef typename VEC4::elem_t T; //we assume     15   typedef typename VEC4::elem_t T; //we assume = T3
 16 public:                                            16 public:
 17   qrot()                                           17   qrot()
 18   :m_quat(0,0,0,1)   //zero rotation around th     18   :m_quat(0,0,0,1)   //zero rotation around the positive Z axis.
 19   {}                                               19   {}
 20   qrot(const VEC3& a_axis,T a_radians,T(*a_sin     20   qrot(const VEC3& a_axis,T a_radians,T(*a_sin)(T),T(*a_cos)(T)){
 21     if(!set_value(a_axis,a_radians,a_sin,a_cos     21     if(!set_value(a_axis,a_radians,a_sin,a_cos)) {} //FIXME : throw
 22   }                                                22   }
 23   qrot(const VEC3& a_from,const VEC3& a_to,T(*     23   qrot(const VEC3& a_from,const VEC3& a_to,T(*a_sqrt)(T),T(*a_fabs)(T)){set_value(a_from,a_to,a_sqrt,a_fabs);}
 24   virtual ~qrot(){}                                24   virtual ~qrot(){}
 25 public:                                            25 public:
 26   qrot(const qrot& a_from)                         26   qrot(const qrot& a_from)
 27   :m_quat(a_from.m_quat)                           27   :m_quat(a_from.m_quat)
 28   {}                                               28   {}
 29   qrot& operator=(const qrot& a_from){             29   qrot& operator=(const qrot& a_from){
 30     m_quat = a_from.m_quat;                        30     m_quat = a_from.m_quat;
 31     return *this;                                  31     return *this;
 32   }                                                32   }
 33 protected:                                         33 protected:
 34   qrot(T a_q0,T a_q1,T a_q2,T a_q3)                34   qrot(T a_q0,T a_q1,T a_q2,T a_q3)
 35   :m_quat(a_q0,a_q1,a_q2,a_q3)                     35   :m_quat(a_q0,a_q1,a_q2,a_q3)
 36   {                                                36   {
 37     if(!m_quat.normalize()) {} //FIXME throw       37     if(!m_quat.normalize()) {} //FIXME throw
 38   }                                                38   }
 39                                                    39 
 40 public:                                            40 public:
 41   qrot& operator*=(const qrot& a_q) {              41   qrot& operator*=(const qrot& a_q) {
 42     //Multiplies the quaternions.                  42     //Multiplies the quaternions.
 43     //Note that order is important when combin     43     //Note that order is important when combining quaternions with the
 44     //multiplication operator.                     44     //multiplication operator.
 45     // Formula from <http://www.lboro.ac.uk/de     45     // Formula from <http://www.lboro.ac.uk/departments/ma/gallery/quat/>
 46                                                    46 
 47     T tx = m_quat.v0();                            47     T tx = m_quat.v0();
 48     T ty = m_quat.v1();                            48     T ty = m_quat.v1();
 49     T tz = m_quat.v2();                            49     T tz = m_quat.v2();
 50     T tw = m_quat.v3();                            50     T tw = m_quat.v3();
 51                                                    51 
 52     T qx = a_q.m_quat.v0();                        52     T qx = a_q.m_quat.v0();
 53     T qy = a_q.m_quat.v1();                        53     T qy = a_q.m_quat.v1();
 54     T qz = a_q.m_quat.v2();                        54     T qz = a_q.m_quat.v2();
 55     T qw = a_q.m_quat.v3();                        55     T qw = a_q.m_quat.v3();
 56                                                    56 
 57     m_quat.set_value(qw*tx + qx*tw + qy*tz - q     57     m_quat.set_value(qw*tx + qx*tw + qy*tz - qz*ty,
 58                      qw*ty - qx*tz + qy*tw + q     58                      qw*ty - qx*tz + qy*tw + qz*tx,
 59                      qw*tz + qx*ty - qy*tx + q     59                      qw*tz + qx*ty - qy*tx + qz*tw,
 60                      qw*tw - qx*tx - qy*ty - q     60                      qw*tw - qx*tx - qy*ty - qz*tz);
 61     m_quat.normalize();                            61     m_quat.normalize();
 62     return *this;                                  62     return *this;
 63   }                                                63   }
 64                                                    64 
 65   bool operator==(const qrot& a_r) const {         65   bool operator==(const qrot& a_r) const {
 66     return m_quat.equal(a_r.m_quat);               66     return m_quat.equal(a_r.m_quat);
 67   }                                                67   }
 68   bool operator!=(const qrot& a_r) const {         68   bool operator!=(const qrot& a_r) const {
 69     return !operator==(a_r);                       69     return !operator==(a_r);
 70   }                                                70   }
 71   qrot operator*(const qrot& a_r) const {          71   qrot operator*(const qrot& a_r) const {
 72     qrot tmp(*this);                               72     qrot tmp(*this);
 73     tmp *= a_r;                                    73     tmp *= a_r;
 74     return tmp;                                    74     return tmp;
 75   }                                                75   }
 76                                                    76 
 77   bool invert(){                                   77   bool invert(){
 78     T length = m_quat.length();                    78     T length = m_quat.length();
 79     if(length==T()) return false;                  79     if(length==T()) return false;
 80                                                    80 
 81     // Optimize by doing 1 div and 4 muls inst     81     // Optimize by doing 1 div and 4 muls instead of 4 divs.
 82     T inv = one() / length;                        82     T inv = one() / length;
 83                                                    83 
 84     m_quat.set_value(-m_quat.v0() * inv,           84     m_quat.set_value(-m_quat.v0() * inv,
 85                      -m_quat.v1() * inv,           85                      -m_quat.v1() * inv,
 86                      -m_quat.v2() * inv,           86                      -m_quat.v2() * inv,
 87                       m_quat.v3() * inv);          87                       m_quat.v3() * inv);
 88                                                    88 
 89     return true;                                   89     return true;
 90   }                                                90   }
 91                                                    91 
 92   bool inverse(qrot& a_r) const {                  92   bool inverse(qrot& a_r) const {
 93     //Non-destructively inverses the rotation      93     //Non-destructively inverses the rotation and returns the result.
 94     T length = m_quat.length();                    94     T length = m_quat.length();
 95     if(length==T()) return false;                  95     if(length==T()) return false;
 96                                                    96 
 97     // Optimize by doing 1 div and 4 muls inst     97     // Optimize by doing 1 div and 4 muls instead of 4 divs.
 98     T inv = one() / length;                        98     T inv = one() / length;
 99                                                    99 
100     a_r.m_quat.set_value(-m_quat.v0() * inv,      100     a_r.m_quat.set_value(-m_quat.v0() * inv,
101                          -m_quat.v1() * inv,      101                          -m_quat.v1() * inv,
102                          -m_quat.v2() * inv,      102                          -m_quat.v2() * inv,
103                           m_quat.v3() * inv);     103                           m_quat.v3() * inv);
104                                                   104 
105     return true;                                  105     return true;
106   }                                               106   }
107                                                   107 
108                                                   108 
109   bool set_value(const VEC3& a_axis,T a_radian    109   bool set_value(const VEC3& a_axis,T a_radians,T(*a_sin)(T),T(*a_cos)(T)) {
110     // Reset rotation with the given axis-of-r    110     // Reset rotation with the given axis-of-rotation and rotation angle.
111     // Make sure axis is not the null vector w    111     // Make sure axis is not the null vector when calling this method.
112     // From <http://www.automation.hut.fi/~jar    112     // From <http://www.automation.hut.fi/~jaro/thesis/hyper/node9.html>.
113     if(a_axis.length()==T()) return false;        113     if(a_axis.length()==T()) return false;
114     m_quat.v3(a_cos(a_radians/2));                114     m_quat.v3(a_cos(a_radians/2));
115     T sineval = a_sin(a_radians/2);               115     T sineval = a_sin(a_radians/2);
116     VEC3 a = a_axis;                              116     VEC3 a = a_axis;
117     a.normalize();                                117     a.normalize();
118     m_quat.v0(a.v0() * sineval);                  118     m_quat.v0(a.v0() * sineval);
119     m_quat.v1(a.v1() * sineval);                  119     m_quat.v1(a.v1() * sineval);
120     m_quat.v2(a.v2() * sineval);                  120     m_quat.v2(a.v2() * sineval);
121     return true;                                  121     return true;
122   }                                               122   }
123                                                   123 
124   bool set_value(const VEC3& a_from,const VEC3    124   bool set_value(const VEC3& a_from,const VEC3& a_to,T(*a_sqrt)(T),T(*a_fabs)(T)) {
125     // code taken from coin3d/SbRotation.         125     // code taken from coin3d/SbRotation.
126     //NOTE : coin3d/SbMatrix logic is transpos    126     //NOTE : coin3d/SbMatrix logic is transposed relative to us.
127                                                   127 
128     VEC3 from(a_from);                            128     VEC3 from(a_from);
129     if(from.normalize()==T()) return false;       129     if(from.normalize()==T()) return false;
130     VEC3 to(a_to);                                130     VEC3 to(a_to);
131     if(to.normalize()==T()) return false;         131     if(to.normalize()==T()) return false;
132                                                   132 
133     T dot = from.dot(to);                         133     T dot = from.dot(to);
134     VEC3 crossvec;from.cross(to,crossvec);        134     VEC3 crossvec;from.cross(to,crossvec);
135     T crosslen = crossvec.normalize();            135     T crosslen = crossvec.normalize();
136                                                   136 
137     if(crosslen == T()) { // Parallel vectors     137     if(crosslen == T()) { // Parallel vectors
138       // Check if they are pointing in the sam    138       // Check if they are pointing in the same direction.
139       if (dot > T()) {                            139       if (dot > T()) {
140         m_quat.set_value(0,0,0,1);                140         m_quat.set_value(0,0,0,1);
141       } else {                                    141       } else {
142         // Ok, so they are parallel and pointi    142         // Ok, so they are parallel and pointing in the opposite direction
143         // of each other.                         143         // of each other.
144         // Try crossing with x axis.              144         // Try crossing with x axis.
145         VEC3 t;from.cross(VEC3(1,0,0),t);         145         VEC3 t;from.cross(VEC3(1,0,0),t);
146         // If not ok, cross with y axis.          146         // If not ok, cross with y axis.
147         if(t.normalize() == T()) {                147         if(t.normalize() == T()) {
148           from.cross(VEC3(0,1,0),t);              148           from.cross(VEC3(0,1,0),t);
149           t.normalize();                          149           t.normalize();
150         }                                         150         }
151         m_quat.set_value(t[0],t[1],t[2],0);       151         m_quat.set_value(t[0],t[1],t[2],0);
152       }                                           152       }
153     } else { // Vectors are not parallel          153     } else { // Vectors are not parallel
154       // The fabs() wrapping is to avoid probl    154       // The fabs() wrapping is to avoid problems when `dot' "overflows"
155       // a tiny wee bit, which can lead to sqr    155       // a tiny wee bit, which can lead to sqrt() returning NaN.
156       crossvec *= (T)a_sqrt(half() * a_fabs(on    156       crossvec *= (T)a_sqrt(half() * a_fabs(one() - dot));
157       // The fabs() wrapping is to avoid probl    157       // The fabs() wrapping is to avoid problems when `dot' "underflows"
158       // a tiny wee bit, which can lead to sqr    158       // a tiny wee bit, which can lead to sqrt() returning NaN.
159       m_quat.set_value(crossvec[0], crossvec[1    159       m_quat.set_value(crossvec[0], crossvec[1], crossvec[2],(T)a_sqrt(half()*a_fabs(one()+dot)));
160     }                                             160     }
161                                                   161 
162     return true;                                  162     return true;
163   }                                               163   }
164                                                   164 
165                                                   165 
166   bool value(VEC3& a_axis,T& a_radians,T(*a_si    166   bool value(VEC3& a_axis,T& a_radians,T(*a_sin)(T),T(*a_acos)(T)) const { //WARNING a_acos and NOT a_cos
167     //WARNING : can fail.                         167     //WARNING : can fail.
168     if( (m_quat.v3()<minus_one()) || (m_quat.v    168     if( (m_quat.v3()<minus_one()) || (m_quat.v3()> one()) ) {
169       a_axis.set_value(0,0,1);                    169       a_axis.set_value(0,0,1);
170       a_radians = 0;                              170       a_radians = 0;
171       return false;                               171       return false;
172     }                                             172     }
173                                                   173 
174     a_radians = a_acos(m_quat.v3()) * 2; //in     174     a_radians = a_acos(m_quat.v3()) * 2; //in [0,2*pi]
175     T sineval = a_sin(a_radians/2);               175     T sineval = a_sin(a_radians/2);
176                                                   176 
177     if(sineval==T()) { //a_radian = 0 or 2*pi.    177     if(sineval==T()) { //a_radian = 0 or 2*pi.
178       a_axis.set_value(0,0,1);                    178       a_axis.set_value(0,0,1);
179       a_radians = 0;                              179       a_radians = 0;
180       return false;                               180       return false;
181     }                                             181     }
182     a_axis.set_value(m_quat.v0()/sineval,         182     a_axis.set_value(m_quat.v0()/sineval,
183                      m_quat.v1()/sineval,         183                      m_quat.v1()/sineval,
184                      m_quat.v2()/sineval);        184                      m_quat.v2()/sineval);
185     return true;                                  185     return true;
186   }                                               186   }
187                                                   187 
188   template <class MAT4>                           188   template <class MAT4>
189   void set_value(const MAT4& a_m,T(*a_sqrt)(T)    189   void set_value(const MAT4& a_m,T(*a_sqrt)(T)) {
190     // See tests/qrot.icc.                        190     // See tests/qrot.icc.
191     // code taken from coin3d/SbRotation.         191     // code taken from coin3d/SbRotation.
192                                                   192 
193     //Set the rotation from the components of     193     //Set the rotation from the components of the given matrix.
194                                                   194 
195     T scalerow = a_m.v00() + a_m.v11() + a_m.v    195     T scalerow = a_m.v00() + a_m.v11() + a_m.v22();
196     if (scalerow > T()) {                         196     if (scalerow > T()) {
197       T _s = a_sqrt(scalerow + a_m.v33());        197       T _s = a_sqrt(scalerow + a_m.v33());
198       m_quat.v3(_s * half());                     198       m_quat.v3(_s * half());
199       _s = half() / _s;                           199       _s = half() / _s;
200                                                   200 
201       m_quat.v0((a_m.v21() - a_m.v12()) * _s);    201       m_quat.v0((a_m.v21() - a_m.v12()) * _s);
202       m_quat.v1((a_m.v02() - a_m.v20()) * _s);    202       m_quat.v1((a_m.v02() - a_m.v20()) * _s);
203       m_quat.v2((a_m.v10() - a_m.v01()) * _s);    203       m_quat.v2((a_m.v10() - a_m.v01()) * _s);
204     } else {                                      204     } else {
205       unsigned int i = 0;                         205       unsigned int i = 0;
206       if (a_m.v11() > a_m.v00()) i = 1;           206       if (a_m.v11() > a_m.v00()) i = 1;
207       if (a_m.v22() > a_m.value(i,i)) i = 2;      207       if (a_m.v22() > a_m.value(i,i)) i = 2;
208                                                   208 
209       unsigned int j = (i+1)%3;                   209       unsigned int j = (i+1)%3;
210       unsigned int k = (j+1)%3;                   210       unsigned int k = (j+1)%3;
211                                                   211 
212       T _s = a_sqrt((a_m.value(i,i) - (a_m.val    212       T _s = a_sqrt((a_m.value(i,i) - (a_m.value(j,j) + a_m.value(k,k))) + a_m.v33());
213                                                   213 
214       m_quat.set_value(i,_s * half());            214       m_quat.set_value(i,_s * half());
215       _s = half() / _s;                           215       _s = half() / _s;
216                                                   216 
217       m_quat.v3((a_m.value(k,j) - a_m.value(j,    217       m_quat.v3((a_m.value(k,j) - a_m.value(j,k)) * _s);
218       m_quat.set_value(j,(a_m.value(j,i) + a_m    218       m_quat.set_value(j,(a_m.value(j,i) + a_m.value(i,j)) * _s);
219       m_quat.set_value(k,(a_m.value(k,i) + a_m    219       m_quat.set_value(k,(a_m.value(k,i) + a_m.value(i,k)) * _s);
220     }                                             220     }
221                                                   221 
222     if (a_m.v33()!=one()) {                       222     if (a_m.v33()!=one()) {
223       m_quat.multiply(one()/a_sqrt(a_m.v33()))    223       m_quat.multiply(one()/a_sqrt(a_m.v33()));
224     }                                             224     }
225   }                                               225   }
226                                                   226 
227   template <class MAT4>                           227   template <class MAT4>
228   void value(MAT4& a_m) const {                   228   void value(MAT4& a_m) const {
229     //Return this rotation in the form of a ma    229     //Return this rotation in the form of a matrix.
230     //NOTE : in coin3d/SbRotation, it looks as    230     //NOTE : in coin3d/SbRotation, it looks as if "w <-> -w", but coin3d/SbMatrix logic is transposed relative to us.
231                                                   231 
232     const T x = m_quat.v0();                      232     const T x = m_quat.v0();
233     const T y = m_quat.v1();                      233     const T y = m_quat.v1();
234     const T z = m_quat.v2();                      234     const T z = m_quat.v2();
235     const T w = m_quat.v3();                      235     const T w = m_quat.v3();
236     // q = w + x * i + y * j + z * k              236     // q = w + x * i + y * j + z * k
237                                                   237 
238     // first row :                                238     // first row :
239     a_m.v00(w*w + x*x - y*y - z*z);               239     a_m.v00(w*w + x*x - y*y - z*z);
240     a_m.v01(2*x*y - 2*w*z);                       240     a_m.v01(2*x*y - 2*w*z);
241     a_m.v02(2*x*z + 2*w*y);                       241     a_m.v02(2*x*z + 2*w*y);
242     a_m.v03(0);                                   242     a_m.v03(0);
243                                                   243 
244     // second row :                               244     // second row :
245     a_m.v10(2*x*y + 2*w*z);                       245     a_m.v10(2*x*y + 2*w*z);
246     a_m.v11(w*w - x*x + y*y - z*z);               246     a_m.v11(w*w - x*x + y*y - z*z);
247     a_m.v12(2*y*z - 2*w*x);                       247     a_m.v12(2*y*z - 2*w*x);
248     a_m.v13(0);                                   248     a_m.v13(0);
249                                                   249 
250     // third row :                                250     // third row :
251     a_m.v20(2*x*z - 2*w*y);                       251     a_m.v20(2*x*z - 2*w*y);
252     a_m.v21(2*y*z + 2*w*x);                       252     a_m.v21(2*y*z + 2*w*x);
253     a_m.v22(w*w - x*x - y*y + z*z);               253     a_m.v22(w*w - x*x - y*y + z*z);
254     a_m.v23(0);                                   254     a_m.v23(0);
255                                                   255 
256     // fourth row :                               256     // fourth row :
257     a_m.v30(0);                                   257     a_m.v30(0);
258     a_m.v31(0);                                   258     a_m.v31(0);
259     a_m.v32(0);                                   259     a_m.v32(0);
260     a_m.v33(w*w + x*x + y*y + z*z);               260     a_m.v33(w*w + x*x + y*y + z*z);
261   }                                               261   }
262                                                   262 
263   template <class MAT3>                           263   template <class MAT3>
264   T value_3(MAT3& a_m) const {                    264   T value_3(MAT3& a_m) const {
265     //Return this rotation in the form of a 3D    265     //Return this rotation in the form of a 3D matrix.
266     //NOTE : in coin3d/SbRotation, it looks as    266     //NOTE : in coin3d/SbRotation, it looks as if "w <-> -w", but coin3d/SbMatrix logic is transposed relative to us.
267                                                   267 
268     const T x = m_quat.v0();                      268     const T x = m_quat.v0();
269     const T y = m_quat.v1();                      269     const T y = m_quat.v1();
270     const T z = m_quat.v2();                      270     const T z = m_quat.v2();
271     const T w = m_quat.v3();                      271     const T w = m_quat.v3();
272     // q = w + x * i + y * j + z * k              272     // q = w + x * i + y * j + z * k
273                                                   273 
274     // first row :                                274     // first row :
275     a_m.v00(w*w + x*x - y*y - z*z);               275     a_m.v00(w*w + x*x - y*y - z*z);
276     a_m.v01(2*x*y - 2*w*z);                       276     a_m.v01(2*x*y - 2*w*z);
277     a_m.v02(2*x*z + 2*w*y);                       277     a_m.v02(2*x*z + 2*w*y);
278                                                   278 
279     // second row :                               279     // second row :
280     a_m.v10(2*x*y + 2*w*z);                       280     a_m.v10(2*x*y + 2*w*z);
281     a_m.v11(w*w - x*x + y*y - z*z);               281     a_m.v11(w*w - x*x + y*y - z*z);
282     a_m.v12(2*y*z - 2*w*x);                       282     a_m.v12(2*y*z - 2*w*x);
283                                                   283 
284     // third row :                                284     // third row :
285     a_m.v20(2*x*z - 2*w*y);                       285     a_m.v20(2*x*z - 2*w*y);
286     a_m.v21(2*y*z + 2*w*x);                       286     a_m.v21(2*y*z + 2*w*x);
287     a_m.v22(w*w - x*x - y*y + z*z);               287     a_m.v22(w*w - x*x - y*y + z*z);
288                                                   288 
289     // fourth row :                               289     // fourth row :
290     //a_m.v30(0);                                 290     //a_m.v30(0);
291     //a_m.v31(0);                                 291     //a_m.v31(0);
292     //a_m.v32(0);                                 292     //a_m.v32(0);
293     //a_m.v33(w*w + x*x + y*y + z*z);             293     //a_m.v33(w*w + x*x + y*y + z*z);
294     return w*w + x*x + y*y + z*z;  //should be    294     return w*w + x*x + y*y + z*z;  //should be 1.
295   }                                               295   }
296                                                   296 
297   void mul_vec(const VEC3& a_in,VEC3& a_out) c    297   void mul_vec(const VEC3& a_in,VEC3& a_out) const {
298     const T x = m_quat.v0();                      298     const T x = m_quat.v0();
299     const T y = m_quat.v1();                      299     const T y = m_quat.v1();
300     const T z = m_quat.v2();                      300     const T z = m_quat.v2();
301     const T w = m_quat.v3();                      301     const T w = m_quat.v3();
302                                                   302 
303     // first row :                                303     // first row :
304     T v0 =     (w*w + x*x - y*y - z*z) * a_in.    304     T v0 =     (w*w + x*x - y*y - z*z) * a_in.v0()
305               +        (2*x*y - 2*w*z) * a_in.    305               +        (2*x*y - 2*w*z) * a_in.v1()
306               +        (2*x*z + 2*w*y) * a_in.    306               +        (2*x*z + 2*w*y) * a_in.v2();
307                                                   307 
308     T v1 =             (2*x*y + 2*w*z) * a_in.    308     T v1 =             (2*x*y + 2*w*z) * a_in.v0()
309               +(w*w - x*x + y*y - z*z) * a_in.    309               +(w*w - x*x + y*y - z*z) * a_in.v1()
310               +        (2*y*z - 2*w*x) * a_in.    310               +        (2*y*z - 2*w*x) * a_in.v2();
311                                                   311 
312     T v2 =             (2*x*z - 2*w*y) * a_in.    312     T v2 =             (2*x*z - 2*w*y) * a_in.v0()
313               +        (2*y*z + 2*w*x) * a_in.    313               +        (2*y*z + 2*w*x) * a_in.v1()
314               +(w*w - x*x - y*y + z*z) * a_in.    314               +(w*w - x*x - y*y + z*z) * a_in.v2();
315                                                   315 
316     a_out.set_value(v0,v1,v2);                    316     a_out.set_value(v0,v1,v2);
317   }                                               317   }
318                                                   318 
319   void mul_vec(VEC3& a_v) const {                 319   void mul_vec(VEC3& a_v) const {
320     const T x = m_quat.v0();                      320     const T x = m_quat.v0();
321     const T y = m_quat.v1();                      321     const T y = m_quat.v1();
322     const T z = m_quat.v2();                      322     const T z = m_quat.v2();
323     const T w = m_quat.v3();                      323     const T w = m_quat.v3();
324                                                   324 
325     // first row :                                325     // first row :
326     T v0 =     (w*w + x*x - y*y - z*z) * a_v.v    326     T v0 =     (w*w + x*x - y*y - z*z) * a_v.v0()
327               +        (2*x*y - 2*w*z) * a_v.v    327               +        (2*x*y - 2*w*z) * a_v.v1()
328               +        (2*x*z + 2*w*y) * a_v.v    328               +        (2*x*z + 2*w*y) * a_v.v2();
329                                                   329 
330     T v1 =             (2*x*y + 2*w*z) * a_v.v    330     T v1 =             (2*x*y + 2*w*z) * a_v.v0()
331               +(w*w - x*x + y*y - z*z) * a_v.v    331               +(w*w - x*x + y*y - z*z) * a_v.v1()
332               +        (2*y*z - 2*w*x) * a_v.v    332               +        (2*y*z - 2*w*x) * a_v.v2();
333                                                   333 
334     T v2 =             (2*x*z - 2*w*y) * a_v.v    334     T v2 =             (2*x*z - 2*w*y) * a_v.v0()
335               +        (2*y*z + 2*w*x) * a_v.v    335               +        (2*y*z + 2*w*x) * a_v.v1()
336               +(w*w - x*x - y*y + z*z) * a_v.v    336               +(w*w - x*x - y*y + z*z) * a_v.v2();
337                                                   337 
338     a_v.set_value(v0,v1,v2);                      338     a_v.set_value(v0,v1,v2);
339   }                                               339   }
340                                                   340 
341   void mul_3(T& a_x,T& a_y,T& a_z) const {        341   void mul_3(T& a_x,T& a_y,T& a_z) const {
342     const T x = m_quat.v0();                      342     const T x = m_quat.v0();
343     const T y = m_quat.v1();                      343     const T y = m_quat.v1();
344     const T z = m_quat.v2();                      344     const T z = m_quat.v2();
345     const T w = m_quat.v3();                      345     const T w = m_quat.v3();
346                                                   346 
347     // first row :                                347     // first row :
348     T v0 =     (w*w + x*x - y*y - z*z) * a_x      348     T v0 =     (w*w + x*x - y*y - z*z) * a_x
349               +        (2*x*y - 2*w*z) * a_y      349               +        (2*x*y - 2*w*z) * a_y
350               +        (2*x*z + 2*w*y) * a_z;     350               +        (2*x*z + 2*w*y) * a_z;
351                                                   351 
352     T v1 =             (2*x*y + 2*w*z) * a_x      352     T v1 =             (2*x*y + 2*w*z) * a_x
353               +(w*w - x*x + y*y - z*z) * a_y      353               +(w*w - x*x + y*y - z*z) * a_y
354               +        (2*y*z - 2*w*x) * a_z;     354               +        (2*y*z - 2*w*x) * a_z;
355                                                   355 
356     T v2 =             (2*x*z - 2*w*y) * a_x      356     T v2 =             (2*x*z - 2*w*y) * a_x
357               +        (2*y*z + 2*w*x) * a_y      357               +        (2*y*z + 2*w*x) * a_y
358               +(w*w - x*x - y*y + z*z) * a_z;     358               +(w*w - x*x - y*y + z*z) * a_z;
359                                                   359 
360     a_x = v0;                                     360     a_x = v0;
361     a_y = v1;                                     361     a_y = v1;
362     a_z = v2;                                     362     a_z = v2;
363   }                                               363   }
364                                                   364 
365 public: //for io::streamer                        365 public: //for io::streamer
366   const VEC4& quat() const {return m_quat;}       366   const VEC4& quat() const {return m_quat;}
367   VEC4& quat() {return m_quat;}                   367   VEC4& quat() {return m_quat;}
368                                                   368 
369 protected:                                        369 protected:
370   static T one() {return T(1);}                   370   static T one() {return T(1);}
371   static T minus_one() {return T(-1);}            371   static T minus_one() {return T(-1);}
372   static T half() {return T(0.5);}                372   static T half() {return T(0.5);}
373                                                   373 
374 protected:                                        374 protected:
375   VEC4 m_quat;                                    375   VEC4 m_quat;
376                                                   376 
377 public:                                           377 public:
378   //NOTE : don't handle a static object becaus    378   //NOTE : don't handle a static object because of mem balance.
379   //static const qrot<double>& identity() {       379   //static const qrot<double>& identity() {
380   //  static const qrot<double> s_v(0,0,0,1);     380   //  static const qrot<double> s_v(0,0,0,1);
381   //  return s_v;                                 381   //  return s_v;
382   //}                                             382   //}
383                                                   383 
384 //private:static void check_instantiation() {q    384 //private:static void check_instantiation() {qrot<float> v;}
385 };                                                385 };
386                                                   386 
387 }                                                 387 }
388                                                   388 
389 #endif                                            389 #endif