Stellarium 0.11.0
Home · All Namespaces · All Classes · Functions · Coding Style · Scripting · Plugins · File Structure

core/VecMath.hpp

00001 /*
00002  *
00003  * Copyright (C) 2003 Fabien Chereau
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018  */
00019 
00020 // Template vector and matrix library.
00021 // Use OpenGL compatible ordering ie. you can pass a matrix or vector to
00022 // openGL functions without changes in the ordering
00023 
00024 #ifndef _VECMATH_H_
00025 #define _VECMATH_H_
00026 
00027 #include <cmath>
00028 #include <QString>
00029 
00030 template<class T> class Vector2;
00031 template<class T> class Vector3;
00032 template<class T> class Vector4;
00033 template<class T> class Matrix4;
00034 
00035 typedef Vector2<double> Vec2d;
00036 typedef Vector2<float>  Vec2f;
00037 typedef Vector2<int>    Vec2i;
00038 
00041 typedef Vector3<double> Vec3d;
00042 
00045 typedef Vector3<float>  Vec3f;
00046 
00049 typedef Vector4<double> Vec4d;
00050 
00053 typedef Vector4<float>  Vec4f;
00054 
00057 typedef Vector4<int>    Vec4i;
00058 
00061 typedef Matrix4<double> Mat4d;
00062 
00065 typedef Matrix4<float>  Mat4f;
00066 
00067 
00071 template<class T> class Vector2
00072 {
00073 public:
00074     inline Vector2();
00075     inline Vector2(T, T);
00076 
00077     inline Vector2& operator=(const T*);
00078     inline void set(T, T);
00079 
00080     inline bool operator==(const Vector2<T>&) const;
00081     inline bool operator!=(const Vector2<T>&) const;
00082 
00083     inline const T& operator[](int x) const;
00084     inline T& operator[](int);
00085     inline operator const T*() const;
00086     inline operator T*();
00087 
00088     inline Vector2& operator+=(const Vector2<T>&);
00089     inline Vector2& operator-=(const Vector2<T>&);
00090     inline Vector2& operator*=(T);
00091     inline Vector2& operator/=(T);
00092 
00093     inline Vector2 operator-(const Vector2<T>&) const;
00094     inline Vector2 operator+(const Vector2<T>&) const;
00095 
00096     inline Vector2 operator-() const;
00097     inline Vector2 operator+() const;
00098 
00099     inline Vector2 operator*(T) const;
00100     inline Vector2 operator/(T) const;
00101 
00102 
00103     inline T dot(const Vector2<T>&) const;
00104 
00105     inline T length() const;
00106     inline T lengthSquared() const;
00107     inline void normalize();
00108 
00109     T v[2];
00110 };
00111 
00112 
00116 template<class T> class Vector3
00117 {
00118 public:
00119     inline Vector3();
00120     //inline Vector3(const Vector3&);
00121     //template <class T2> inline Vector3(const Vector3<T2>&);
00122     inline Vector3(T, T, T);
00123     inline Vector3(T);
00124 
00125     //inline Vector3& operator=(const Vector3&);
00126     inline Vector3& operator=(const T*);
00127     //template <class T2> inline Vector3& operator=(const Vector3<T2>&);
00128     inline void set(T, T, T);
00129 
00130     inline bool operator==(const Vector3<T>&) const;
00131     inline bool operator!=(const Vector3<T>&) const;
00132 
00133     inline T& operator[](int);
00134     inline const T& operator[](int) const;
00135     inline operator const T*() const;
00136     inline operator T*();
00137     inline const T* data() const {return v;}
00138     inline T* data() {return v;}
00139 
00140     inline Vector3& operator+=(const Vector3<T>&);
00141     inline Vector3& operator-=(const Vector3<T>&);
00142     inline Vector3& operator*=(T);
00143     inline Vector3& operator/=(T);
00144 
00145     inline Vector3 operator-(const Vector3<T>&) const;
00146     inline Vector3 operator+(const Vector3<T>&) const;
00147 
00148     inline Vector3 operator-() const;
00149     inline Vector3 operator+() const;
00150 
00151     inline Vector3 operator*(T) const;
00152     inline Vector3 operator/(T) const;
00153 
00154 
00155     inline T dot(const Vector3<T>&) const;
00156     inline Vector3 operator^(const Vector3<T>&) const;
00157 
00158     // Return latitude in rad
00159     inline T latitude() const;
00160     // Return longitude in rad
00161     inline T longitude() const;
00162 
00163     // Distance in radian between two
00164     inline T angle(const Vector3<T>&) const;
00165     inline T angleNormalized(const Vector3<T>&) const;
00166 
00167     inline T length() const;
00168     inline T lengthSquared() const;
00169     inline void normalize();
00170 
00171     inline void transfo4d(const Mat4d&);
00172     inline void transfo4d(const Mat4f&);
00173     T v[3];     // The 3 values
00174 
00175     QString toString() const {return QString("[%1, %2, %3]").arg(v[0]).arg(v[1]).arg(v[2]);}
00176     QString toStringLonLat() const {return QString("[") + QString::number(longitude()*180./M_PI, 'g', 12) + "," + QString::number(latitude()*180./M_PI, 'g', 12)+"]";}
00177 };
00178 
00179 
00183 template<class T> class Vector4
00184 {
00185 public:
00186     inline Vector4();
00187     inline Vector4(const Vector3<T>&);
00188     inline Vector4(T, T, T);
00189     inline Vector4(T, T, T, T);
00190 
00191     inline Vector4& operator=(const Vector3<T>&);
00192     inline Vector4& operator=(const T*);
00193     inline void set(T, T, T, T);
00194 
00195     inline bool operator==(const Vector4<T>&) const;
00196     inline bool operator!=(const Vector4<T>&) const;
00197 
00198     inline T& operator[](int);
00199     inline const T& operator[](int) const;
00200     inline operator T*();
00201     inline operator const T*() const;
00202 
00203     inline Vector4& operator+=(const Vector4<T>&);
00204     inline Vector4& operator-=(const Vector4<T>&);
00205     inline Vector4& operator*=(T);
00206     inline Vector4& operator/=(T);
00207 
00208     inline Vector4 operator-(const Vector4<T>&) const;
00209     inline Vector4 operator+(const Vector4<T>&) const;
00210 
00211     inline Vector4 operator-() const;
00212     inline Vector4 operator+() const;
00213 
00214     inline Vector4 operator*(T) const;
00215     inline Vector4 operator/(T) const;
00216 
00217 
00218     inline T dot(const Vector4<T>&) const;
00219 
00220     inline T length() const;
00221     inline T lengthSquared() const;
00222     inline void normalize();
00223 
00224     inline void transfo4d(const Mat4d&);
00225 
00226     T v[4];     // The 4 values
00227 };
00228 
00232 template<class T> class Matrix4
00233 {
00234  public:
00235     Matrix4();
00236     Matrix4(T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T);
00237     Matrix4(const T*);
00238     Matrix4(const Vector4<T>&, const Vector4<T>&,
00239             const Vector4<T>&, const Vector4<T>&);
00240 
00241     inline Matrix4& operator=(const T*);
00242     inline void set(T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T);
00243 
00244     inline T& operator[](int);
00245     inline operator T*();
00246     inline operator const T*() const;
00247 
00248     inline Matrix4 operator-(const Matrix4<T>&) const;
00249     inline Matrix4 operator+(const Matrix4<T>&) const;
00250     inline Matrix4 operator*(const Matrix4<T>&) const;
00251 
00252     inline Vector3<T> operator*(const Vector3<T>&) const;
00253     inline Vector3<T> multiplyWithoutTranslation(const Vector3<T>& a) const;
00254     inline Vector4<T> operator*(const Vector4<T>&) const;
00255 
00256     inline void transfo(Vector3<T>&) const;
00257 
00258     static Matrix4<T> identity();
00259     static Matrix4<T> translation(const Vector3<T>&);
00260 
00261     //    static Matrix4<T> rotation(const Vector3<T>&);
00262     static Matrix4<T> rotation(const Vector3<T>&, T);
00263     static Matrix4<T> xrotation(T);
00264     static Matrix4<T> yrotation(T);
00265     static Matrix4<T> zrotation(T);
00266     static Matrix4<T> scaling(const Vector3<T>&);
00267     static Matrix4<T> scaling(T);
00268 
00269     Matrix4<T> transpose() const;
00270     Matrix4<T> inverse() const;
00271 
00272     inline void print(void) const;
00273 
00274     T r[16];
00275 };
00276 
00278 template<class T> QDataStream& operator<<(QDataStream& out, const Vector2<T>& v) {out << v[0] << v[1]; return out;}
00279 template<class T> QDataStream& operator<<(QDataStream& out, const Vector3<T>& v) {out << v[0] << v[1] << v[2]; return out;}
00280 template<class T> QDataStream& operator<<(QDataStream& out, const Vector4<T>& v) {out << v[0] << v[1] << v[2] << v[3]; return out;}
00281 template<class T> QDataStream& operator<<(QDataStream& out, const Matrix4<T>& m) {out << m[0] << m[1] << m[2] << m[3] << m[4] << m[5] << m[6] << m[7] << m[8] << m[9] << m[10] << m[11] << m[12] << m[13] << m[14] << m[15]; return out;}
00282 
00283 template<class T> QDataStream& operator>>(QDataStream& in, Vector2<T>& v) {in >> v[0] >> v[1]; return in;}
00284 template<class T> QDataStream& operator>>(QDataStream& in, Vector3<T>& v) {in >> v[0] >> v[1] >> v[2]; return in;}
00285 template<class T> QDataStream& operator>>(QDataStream& in, Vector4<T>& v) {in >> v[0] >> v[1] >> v[2] >> v[3]; return in;}
00286 template<class T> QDataStream& operator>>(QDataStream& in, Matrix4<T>& m) {in >> m[0] >> m[1] >> m[2] >> m[3] >> m[4] >> m[5] >> m[6] >> m[7] >> m[8] >> m[9] >> m[10] >> m[11] >> m[12] >> m[13] >> m[14] >> m[15]; return in;}
00287 
00289 
00290 template<class T> Vector2<T>::Vector2() {}
00291 
00292 template<class T> Vector2<T>::Vector2(T x, T y)
00293 {
00294     v[0]=x; v[1]=y;
00295 }
00296 
00297 
00298 template<class T> Vector2<T>& Vector2<T>::operator=(const T* a)
00299 {
00300     v[0]=a[0]; v[1]=a[1];
00301     return *this;
00302 }
00303 
00304 template<class T> void Vector2<T>::set(T x, T y)
00305 {
00306     v[0]=x; v[1]=y;
00307 }
00308 
00309 
00310 template<class T> bool Vector2<T>::operator==(const Vector2<T>& a) const
00311 {
00312     return (v[0] == a.v[0] && v[1] == a.v[1]);
00313 }
00314 
00315 template<class T> bool Vector2<T>::operator!=(const Vector2<T>& a) const
00316 {
00317     return (v[0] != a.v[0] || v[1] != a.v[1]);
00318 }
00319 
00320 template<class T> const T& Vector2<T>::operator[](int x) const
00321 {
00322     return v[x];
00323 }
00324 
00325 template<class T> T& Vector2<T>::operator[](int x)
00326 {
00327     return v[x];
00328 }
00329 
00330 template<class T> Vector2<T>::operator const T*() const
00331 {
00332     return v;
00333 }
00334 
00335 template<class T> Vector2<T>::operator T*()
00336 {
00337     return v;
00338 }
00339 
00340 
00341 template<class T> Vector2<T>& Vector2<T>::operator+=(const Vector2<T>& a)
00342 {
00343     v[0] += a.v[0]; v[1] += a.v[1];
00344     return *this;
00345 }
00346 
00347 template<class T> Vector2<T>& Vector2<T>::operator-=(const Vector2<T>& a)
00348 {
00349     v[0] -= a.v[0]; v[1] -= a.v[1];
00350     return *this;
00351 }
00352 
00353 template<class T> Vector2<T>& Vector2<T>::operator*=(T s)
00354 {
00355     v[0] *= s; v[1] *= s;
00356     return *this;
00357 }
00358 
00359 template<class T> Vector2<T> Vector2<T>::operator-() const
00360 {
00361     return Vector2<T>(-v[0], -v[1]);
00362 }
00363 
00364 template<class T> Vector2<T> Vector2<T>::operator+() const
00365 {
00366     return *this;
00367 }
00368 
00369 template<class T> Vector2<T> Vector2<T>::operator+(const Vector2<T>& b) const
00370 {
00371     return Vector2<T>(v[0] + b.v[0], v[1] + b.v[1]);
00372 }
00373 
00374 template<class T> Vector2<T> Vector2<T>::operator-(const Vector2<T>& b) const
00375 {
00376     return Vector2<T>(v[0] - b.v[0], v[1] - b.v[1]);
00377 }
00378 
00379 template<class T> Vector2<T> Vector2<T>::operator*(T s) const
00380 {
00381     return Vector2<T>(s * v[0], s * v[1]);
00382 }
00383 
00384 template<class T> Vector2<T> Vector2<T>::operator/(T s) const
00385 {
00386     return Vector2<T>(v[0]/s, v[1]/s);
00387 }
00388 
00389 
00390 template<class T> T Vector2<T>::dot(const Vector2<T>& b) const
00391 {
00392     return v[0] * b.v[0] + v[1] * b.v[1];
00393 }
00394 
00395 
00396 template<class T> T Vector2<T>::length() const
00397 {
00398     return (T) std::sqrt(v[0] * v[0] + v[1] * v[1]);
00399 }
00400 
00401 template<class T> T Vector2<T>::lengthSquared() const
00402 {
00403     return v[0] * v[0] + v[1] * v[1];
00404 }
00405 
00406 template<class T> void Vector2<T>::normalize()
00407 {
00408     T s = (T) 1 / std::sqrt(v[0] * v[0] + v[1] * v[1]);
00409     v[0] *= s;
00410     v[1] *= s;
00411 }
00412 
00413 // template<class T>
00414 // std::ostream& operator<<(std::ostream &o,const Vector2<T> &v) {
00415 //   return o << '[' << v[0] << ',' << v[1] << ']';
00416 // }
00417 
00419 
00420 template<class T> Vector3<T>::Vector3() {}
00421 
00422 //template<class T> Vector3<T>::Vector3(const Vector3& a)
00423 //{
00424 //  v[0]=a.v[0]; v[1]=a.v[1]; v[2]=a.v[2];
00425 //}
00426 
00427 //template<class T> template<class T2> Vector3<T>::Vector3(const Vector3<T2>& a)
00428 //{
00429 //  v[0]=a.v[0]; v[1]=a.v[1]; v[2]=a.v[2];
00430 //}
00431 
00432 template<class T> Vector3<T>::Vector3(T x)
00433 {
00434     v[0]=x; v[1]=x; v[2]=x;
00435 }
00436 
00437 template<class T> Vector3<T>::Vector3(T x, T y, T z)
00438 {
00439     v[0]=x; v[1]=y; v[2]=z;
00440 }
00441 
00442 //template<class T> Vector3<T>& Vector3<T>::operator=(const Vector3& a)
00443 //{
00444 //  v[0]=a.v[0]; v[1]=a.v[1]; v[2]=a.v[2];
00445 //  return *this;
00446 //}
00447 
00448 //template<class T> template <class T2> Vector3<T>& Vector3<T>::operator=(const Vector3<T2>& a)
00449 //{
00450 //  v[0]=a.v[0]; v[1]=a.v[1]; v[2]=a.v[2];
00451 //  return *this;
00452 //}
00453 
00454 template<class T> Vector3<T>& Vector3<T>::operator=(const T* a)
00455 {
00456     v[0]=a[0]; v[1]=a[1]; v[2]=a[2];
00457     return *this;
00458 }
00459 
00460 template<class T> void Vector3<T>::set(T x, T y, T z)
00461 {
00462     v[0]=x; v[1]=y; v[2]=z;
00463 }
00464 
00465 
00466 template<class T> bool Vector3<T>::operator==(const Vector3<T>& a) const
00467 {
00468     return (v[0] == a.v[0] && v[1] == a.v[1] && v[2] == a.v[2]);
00469 }
00470 
00471 template<class T> bool Vector3<T>::operator!=(const Vector3<T>& a) const
00472 {
00473     return (v[0] != a.v[0] || v[1] != a.v[1] || v[2] != a.v[2]);
00474 }
00475 
00476 
00477 template<class T> T& Vector3<T>::operator[](int x)
00478 {
00479     return v[x];
00480 }
00481 
00482 template<class T> const T& Vector3<T>::operator[](int x) const
00483 {
00484     return v[x];
00485 }
00486 
00487 template<class T> Vector3<T>::operator const T*() const
00488 {
00489     return v;
00490 }
00491 
00492 template<class T> Vector3<T>::operator T*()
00493 {
00494     return v;
00495 }
00496 
00497 template<class T> Vector3<T>& Vector3<T>::operator+=(const Vector3<T>& a)
00498 {
00499     v[0] += a.v[0]; v[1] += a.v[1]; v[2] += a.v[2];
00500     return *this;
00501 }
00502 
00503 template<class T> Vector3<T>& Vector3<T>::operator-=(const Vector3<T>& a)
00504 {
00505     v[0] -= a.v[0]; v[1] -= a.v[1]; v[2] -= a.v[2];
00506     return *this;
00507 }
00508 
00509 template<class T> Vector3<T>& Vector3<T>::operator*=(T s)
00510 {
00511     v[0] *= s; v[1] *= s; v[2] *= s;
00512     return *this;
00513 }
00514 
00515 template<class T> Vector3<T>& Vector3<T>::operator/=(T s)
00516 {
00517     v[0] /= s; v[1] /= s; v[2] /= s;
00518     return *this;
00519 }
00520 
00521 template<class T> Vector3<T> Vector3<T>::operator-() const
00522 {
00523     return Vector3<T>(-v[0], -v[1], -v[2]);
00524 }
00525 
00526 template<class T> Vector3<T> Vector3<T>::operator+() const
00527 {
00528     return *this;
00529 }
00530 
00531 template<class T> Vector3<T> Vector3<T>::operator+(const Vector3<T>& b) const
00532 {
00533     return Vector3<T>(v[0] + b.v[0], v[1] + b.v[1], v[2] + b.v[2]);
00534 }
00535 
00536 template<class T> Vector3<T> Vector3<T>::operator-(const Vector3<T>& b) const
00537 {
00538     return Vector3<T>(v[0] - b.v[0], v[1] - b.v[1], v[2] - b.v[2]);
00539 }
00540 
00541 template<class T> Vector3<T> Vector3<T>::operator*(T s) const
00542 {
00543     return Vector3<T>(s * v[0], s * v[1], s * v[2]);
00544 }
00545 
00546 template<class T> Vector3<T> Vector3<T>::operator/(T s) const
00547 {
00548     return Vector3<T>(v[0]/s, v[1]/s, v[2]/s);
00549 }
00550 
00551 
00552 template<class T> T Vector3<T>::dot(const Vector3<T>& b) const
00553 {
00554     return v[0] * b.v[0] + v[1] * b.v[1] + v[2] * b.v[2];
00555 }
00556 
00557 
00558 // cross product
00559 template<class T> Vector3<T> Vector3<T>::operator^(const Vector3<T>& b) const
00560 {
00561     return Vector3<T>(v[1] * b.v[2] - v[2] * b.v[1],
00562                       v[2] * b.v[0] - v[0] * b.v[2],
00563                       v[0] * b.v[1] - v[1] * b.v[0]);
00564 }
00565 
00566 // Angle in radian between two vectors
00567 template<class T> T Vector3<T>::angle(const Vector3<T>& b) const
00568 {
00569     const T cosAngle = dot(b)/sqrt(lengthSquared()*b.lengthSquared());
00570     return cosAngle>=1 ? 0 : (cosAngle<=-1 ? M_PI : std::acos(cosAngle));
00571 }
00572 
00573 // Angle in radian between two normalized vectors
00574 template<class T> T Vector3<T>::angleNormalized(const Vector3<T>& b) const
00575 {
00576     const T cosAngle = dot(b);
00577     return cosAngle>=1 ? 0 : (cosAngle<=-1 ? M_PI : std::acos(cosAngle));
00578 }
00579 
00580 template<class T> T Vector3<T>::length() const
00581 {
00582     return (T) sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
00583 }
00584 
00585 template<class T> T Vector3<T>::lengthSquared() const
00586 {
00587     return v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
00588 }
00589 
00590 template<class T> void Vector3<T>::normalize()
00591 {
00592     T s = (T) (1. / std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]));
00593     v[0] *= s;
00594     v[1] *= s;
00595     v[2] *= s;
00596 }
00597 
00598 template<class T> void Vector3<T>::transfo4d(const Mat4d& m)
00599 {
00600     const T v0 = v[0];
00601     const T v1 = v[1];
00602     v[0]=m.r[0]*v0 + m.r[4]*v1 + m.r[8]*v[2] + m.r[12];
00603     v[1]=m.r[1]*v0 + m.r[5]*v1 +  m.r[9]*v[2] + m.r[13];
00604     v[2]=m.r[2]*v0 + m.r[6]*v1 + m.r[10]*v[2] + m.r[14];
00605 }
00606 
00607 template<class T> void Vector3<T>::transfo4d(const Mat4f& m)
00608 {
00609     const T v0 = v[0];
00610     const T v1 = v[1];
00611     v[0]=m.r[0]*v0 + m.r[4]*v1 + m.r[8]*v[2] + m.r[12];
00612     v[1]=m.r[1]*v0 + m.r[5]*v1 +  m.r[9]*v[2] + m.r[13];
00613     v[2]=m.r[2]*v0 + m.r[6]*v1 + m.r[10]*v[2] + m.r[14];
00614 }
00615 
00616 // Return latitude in rad
00617 template<class T> T Vector3<T>::latitude() const
00618 {
00619     return std::asin(v[2]/length());
00620 }
00621 
00622 // Return longitude in rad
00623 template<class T> T Vector3<T>::longitude() const
00624 {
00625     return std::atan2(v[1],v[0]);
00626 }
00627 
00628 
00630 
00631 template<class T> Vector4<T>::Vector4() {}
00632 
00633 template<class T> Vector4<T>::Vector4(const Vector3<T>& a)
00634 {
00635     v[0]=a.v[0]; v[1]=a.v[1]; v[2]=a.v[2]; v[3]=1;
00636 }
00637 
00638 template<class T> Vector4<T>::Vector4(T x, T y, T z)
00639 {
00640     v[0]=x; v[1]=y; v[2]=z; v[3]=1;
00641 }
00642 
00643 template<class T> Vector4<T>::Vector4(T x, T y, T z, T a)
00644 {
00645     v[0]=x; v[1]=y; v[2]=z; v[3]=a;
00646 }
00647 
00648 template<class T> Vector4<T>& Vector4<T>::operator=(const Vector3<T>& a)
00649 {
00650     v[0]=a.v[0]; v[1]=a.v[1]; v[2]=a.v[2]; v[3]=1;
00651     return *this;
00652 }
00653 
00654 template<class T> Vector4<T>& Vector4<T>::operator=(const T* a)
00655 {
00656     v[0]=a[0]; v[1]=a[1]; v[2]=a[2]; v[3]=a[3];
00657     return *this;
00658 }
00659 
00660 template<class T> void Vector4<T>::set(T x, T y, T z, T a)
00661 {
00662     v[0]=x; v[1]=y; v[2]=z; v[3]=a;
00663 }
00664 
00665 template<class T> bool Vector4<T>::operator==(const Vector4<T>& a) const
00666 {
00667     return (v[0] == a.v[0] && v[1] == a.v[1] && v[2] == a.v[2] && v[3] == a.v[3]);
00668 }
00669 
00670 template<class T> bool Vector4<T>::operator!=(const Vector4<T>& a) const
00671 {
00672     return (v[0] != a.v[0] || v[1] != a.v[1] || v[2] != a.v[2] || v[3] != a.v[3]);
00673 }
00674 
00675 template<class T> T& Vector4<T>::operator[](int x)
00676 {
00677     return v[x];
00678 }
00679 
00680 template<class T> const T& Vector4<T>::operator[](int x) const
00681 {
00682     return v[x];
00683 }
00684 
00685 template<class T> Vector4<T>::operator T*()
00686 {
00687     return v;
00688 }
00689 
00690 template<class T> Vector4<T>::operator const T*() const
00691 {
00692     return v;
00693 }
00694 
00695 template<class T> Vector4<T>& Vector4<T>::operator+=(const Vector4<T>& a)
00696 {
00697     v[0] += a.v[0]; v[1] += a.v[1]; v[2] += a.v[2]; v[3] += a.v[3];
00698     return *this;
00699 }
00700 
00701 template<class T> Vector4<T>& Vector4<T>::operator-=(const Vector4<T>& a)
00702 {
00703     v[0] -= a.v[0]; v[1] -= a.v[1]; v[2] -= a.v[2]; v[3] -= a/v[3];
00704     return *this;
00705 }
00706 
00707 template<class T> Vector4<T>& Vector4<T>::operator*=(T s)
00708 {
00709     v[0] *= s; v[1] *= s; v[2] *= s; v[3] *= s;
00710     return *this;
00711 }
00712 
00713 template<class T> Vector4<T> Vector4<T>::operator-() const
00714 {
00715     return Vector4<T>(-v[0], -v[1], -v[2], -v[3]);
00716 }
00717 
00718 template<class T> Vector4<T> Vector4<T>::operator+() const
00719 {
00720     return *this;
00721 }
00722 
00723 template<class T> Vector4<T> Vector4<T>::operator+(const Vector4<T>& b) const
00724 {
00725     return Vector4<T>(v[0] + b.v[0], v[1] + b.v[1], v[2] + b.v[2], v[3] + b.v[3]);
00726 }
00727 
00728 template<class T> Vector4<T> Vector4<T>::operator-(const Vector4<T>& b) const
00729 {
00730     return Vector4<T>(v[0] - b.v[0], v[1] - b.v[1], v[2] - b.v[2], v[3] - b.v[3]);
00731 }
00732 
00733 template<class T> Vector4<T> Vector4<T>::operator*(T s) const
00734 {
00735     return Vector4<T>(s * v[0], s * v[1], s * v[2], s * v[3]);
00736 }
00737 
00738 template<class T> Vector4<T> Vector4<T>::operator/(T s) const
00739 {
00740     return Vector4<T>(v[0]/s, v[1]/s, v[2]/s, v[3]/s);
00741 }
00742 
00743 template<class T> T Vector4<T>::dot(const Vector4<T>& b) const
00744 {
00745     return v[0] * b.v[0] + v[1] * b.v[1] + v[2] * b.v[2] + v[3] * b.v[3];
00746 }
00747 
00748 template<class T> T Vector4<T>::length() const
00749 {
00750     return (T) sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]);
00751 }
00752 
00753 template<class T> T Vector4<T>::lengthSquared() const
00754 {
00755     return v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3];
00756 }
00757 
00758 template<class T> void Vector4<T>::normalize()
00759 {
00760     T s = (T) (1. / sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2] + v[3] * v[3]));
00761     v[0] *= s;
00762     v[1] *= s;
00763     v[2] *= s;
00764     v[3] *= s;
00765 }
00766 
00767 template<class T> void Vector4<T>::transfo4d(const Mat4d& m)
00768 {
00769     (*this)=m*(*this);
00770 }
00771 /*
00772 template<class T>
00773 std::ostream& operator<<(std::ostream &o,const Vector4<T> &v) {
00774   return o << '[' << v[0] << ',' << v[1] << ',' << v[2] << ',' << v[3] << ']';
00775 }*/
00776 
00777 
00779 
00780 template<class T> Matrix4<T>::Matrix4() {}
00781 
00782 template<class T> Matrix4<T>::Matrix4(const T* m)
00783 {
00784     memcpy(r,m,sizeof(T)*16);
00785 }
00786 
00787 template<class T> Matrix4<T>::Matrix4(const Vector4<T>& v0,
00788                                       const Vector4<T>& v1,
00789                                       const Vector4<T>& v2,
00790                                       const Vector4<T>& v3)
00791 {
00792     r[0] = v0.v[0];
00793     r[1] = v0.v[1];
00794     r[2] = v0.v[2];
00795     r[3] = v0.v[3];
00796     r[4] = v1.v[0];
00797     r[5] = v1.v[1];
00798     r[6] = v1.v[2];
00799     r[7] = v1.v[3];
00800     r[8] = v2.v[0];
00801     r[9] = v2.v[1];
00802     r[10] = v2.v[2];
00803     r[11] = v2.v[3];
00804     r[12] = v3.v[0];
00805     r[13] = v3.v[1];
00806     r[14] = v3.v[2];
00807     r[15] = v3.v[3];
00808 }
00809 
00810 
00811 template<class T> Matrix4<T>::Matrix4(T a, T b, T c, T d, T e, T f, T g, T h, T i, T j, T k, T l, T m, T n, T o, T p)
00812 {
00813     r[0]=a; r[1]=b; r[2]=c; r[3]=d; r[4]=e; r[5]=f; r[6]=g; r[7]=h;
00814     r[8]=i; r[9]=j; r[10]=k; r[11]=l; r[12]=m; r[13]=n; r[14]=o; r[15]=p;
00815 }
00816 
00817 template<class T> void Matrix4<T>::set(T a, T b, T c, T d, T e, T f, T g, T h, T i, T j, T k, T l, T m, T n, T o, T p)
00818 {
00819     r[0]=a; r[1]=b; r[2]=c; r[3]=d; r[4]=e; r[5]=f; r[6]=g; r[7]=h;
00820     r[8]=i; r[9]=j; r[10]=k; r[11]=l; r[12]=m; r[13]=n; r[14]=o; r[15]=p;
00821 }
00822 
00823 template<class T> T& Matrix4<T>::operator[](int n)
00824 {
00825     return r[n];
00826 }
00827 
00828 template<class T> Matrix4<T>::operator T*()
00829 {
00830     return r;
00831 }
00832 
00833 template<class T> Matrix4<T>::operator const T*() const
00834 {
00835     return r;
00836 }
00837 
00838 template<class T> Matrix4<T> Matrix4<T>::identity()
00839 {
00840     return Matrix4<T>(  1, 0, 0, 0,
00841                         0, 1, 0, 0,
00842                         0, 0, 1, 0,
00843                         0, 0, 0, 1  );
00844 }
00845 
00846 
00847 template<class T> Matrix4<T> Matrix4<T>::translation(const Vector3<T>& a)
00848 {
00849     return Matrix4<T>(  1, 0, 0, 0,
00850                         0, 1, 0, 0,
00851                         0, 0, 1, 0,
00852                         a.v[0], a.v[1], a.v[2], 1);
00853 }
00854 
00855 
00856 template<class T> Matrix4<T> Matrix4<T>::rotation(const Vector3<T>& axis, T angle)
00857 {
00858     Vector3<T> a(axis);
00859     a.normalize();
00860     const T c = (T) cos(angle);
00861     const T s = (T) sin(angle);
00862     const T d = 1-c;
00863     return Matrix4<T>(  a[0]*a[0]*d+c     , a[1]*a[0]*d+a[2]*s, a[0]*a[2]*d-a[1]*s, 0,
00864                         a[0]*a[1]*d-a[2]*s, a[1]*a[1]*d+c     , a[1]*a[2]*d+a[0]*s, 0,
00865                         a[0]*a[2]*d+a[1]*s, a[1]*a[2]*d-a[0]*s, a[2]*a[2]*d+c     , 0,
00866                         0,0,0,1 );
00867 }
00868 
00869 template<class T> Matrix4<T> Matrix4<T>::xrotation(T angle)
00870 {
00871     T c = (T) cos(angle);
00872     T s = (T) sin(angle);
00873 
00874     return Matrix4<T>(1, 0, 0, 0,
00875                       0, c, s, 0,
00876                       0,-s, c, 0,
00877                       0, 0, 0, 1 );
00878 }
00879 
00880 
00881 template<class T> Matrix4<T> Matrix4<T>::yrotation(T angle)
00882 {
00883     T c = (T) cos(angle);
00884     T s = (T) sin(angle);
00885 
00886     return Matrix4<T>( c, 0,-s, 0,
00887                        0, 1, 0, 0,
00888                        s, 0, c, 0,
00889                        0, 0, 0, 1 );
00890 }
00891 
00892 
00893 template<class T> Matrix4<T> Matrix4<T>::zrotation(T angle)
00894 {
00895     T c = (T) cos(angle);
00896     T s = (T) sin(angle);
00897 
00898     return Matrix4<T>(c, s, 0, 0,
00899                      -s, c, 0, 0,
00900                       0, 0, 1, 0,
00901                       0, 0, 0, 1 );
00902 }
00903 
00904 
00905 template<class T> Matrix4<T> Matrix4<T>::scaling(const Vector3<T>& s)
00906 {
00907     return Matrix4<T>(s[0], 0  , 0  , 0,
00908                       0   ,s[1], 0  , 0,
00909                       0   , 0  ,s[2], 0,
00910                       0   , 0  , 0  , 1);
00911 }
00912 
00913 
00914 template<class T> Matrix4<T> Matrix4<T>::scaling(T scale)
00915 {
00916     return scaling(Vector3<T>(scale, scale, scale));
00917 }
00918 
00919 // multiply column vector by a 4x4 matrix in homogeneous coordinate (use a[3]=1)
00920 template<class T> Vector3<T> Matrix4<T>::operator*(const Vector3<T>& a) const
00921 {
00922     return Vector3<T>(  r[0]*a.v[0] + r[4]*a.v[1] +  r[8]*a.v[2] + r[12],
00923                         r[1]*a.v[0] + r[5]*a.v[1] +  r[9]*a.v[2] + r[13],
00924                         r[2]*a.v[0] + r[6]*a.v[1] + r[10]*a.v[2] + r[14] );
00925 }
00926 
00927 template<class T> Vector3<T> Matrix4<T>::multiplyWithoutTranslation(const Vector3<T>& a) const
00928 {
00929     return Vector3<T>(  r[0]*a.v[0] + r[4]*a.v[1] +  r[8]*a.v[2],
00930                         r[1]*a.v[0] + r[5]*a.v[1] +  r[9]*a.v[2],
00931                         r[2]*a.v[0] + r[6]*a.v[1] + r[10]*a.v[2] );
00932 }
00933 
00934 // multiply column vector by a 4x4 matrix in homogeneous coordinate (considere a[3]=1)
00935 template<class T> Vector4<T> Matrix4<T>::operator*(const Vector4<T>& a) const
00936 {
00937     return Vector4<T>(  r[0]*a.v[0] + r[4]*a.v[1] +  r[8]*a.v[2] + r[12]*a.v[3],
00938                         r[1]*a.v[0] + r[5]*a.v[1] +  r[9]*a.v[2] + r[13]*a.v[3],
00939                         r[2]*a.v[0] + r[6]*a.v[1] + r[10]*a.v[2] + r[14]*a.v[3] );
00940 }
00941 
00942 template<class T> void Matrix4<T>::transfo(Vector3<T>& a) const
00943 {
00944     a.set(  r[0]*a.v[0] + r[4]*a.v[1] +  r[8]*a.v[2] + r[12],
00945             r[1]*a.v[0] + r[5]*a.v[1] +  r[9]*a.v[2] + r[13],
00946             r[2]*a.v[0] + r[6]*a.v[1] + r[10]*a.v[2] + r[14]);
00947 }
00948 
00949 template<class T> Matrix4<T> Matrix4<T>::transpose() const
00950 {
00951     return Matrix4<T>(  r[0], r[4], r[8],  r[12],
00952                         r[1], r[5], r[9],  r[13],
00953                         r[2], r[6], r[10], r[14],
00954                         r[3], r[7], r[11], r[15]);
00955 }
00956 
00957 template<class T> Matrix4<T> Matrix4<T>::operator*(const Matrix4<T>& a) const
00958 {
00959 #define MATMUL(R, C) (r[R] * a.r[C] + r[R+4] * a.r[C+1] + r[R+8] * a.r[C+2] + r[R+12] * a.r[C+3])
00960     return Matrix4<T>(  MATMUL(0,0), MATMUL(1,0), MATMUL(2,0), MATMUL(3,0),
00961                         MATMUL(0,4), MATMUL(1,4), MATMUL(2,4), MATMUL(3,4),
00962                         MATMUL(0,8), MATMUL(1,8), MATMUL(2,8), MATMUL(3,8),
00963                         MATMUL(0,12), MATMUL(1,12), MATMUL(2,12), MATMUL(3,12) );
00964 #undef MATMUL
00965 }
00966 
00967 
00968 template<class T> Matrix4<T> Matrix4<T>::operator+(const Matrix4<T>& a) const
00969 {
00970     return Matrix4<T>(  r[0]+a.r[0], r[1]+a.r[1], r[2]+a.r[2], r[3]+a.r[3],
00971                         r[4]+a.r[4], r[5]+a.r[5], r[6]+a.r[6], r[7]+a.r[7],
00972                         r[8]+a.r[8], r[9]+a.r[9], r[10]+a.r[10], r[11]+a.r[11],
00973                         r[12]+a.r[12], r[13]+a.r[13], r[14]+a.r[14], r[15]+a.r[15] );
00974 }
00975 
00976 template<class T> Matrix4<T> Matrix4<T>::operator-(const Matrix4<T>& a) const
00977 {
00978     return Matrix4<T>(  r[0]-a.r[0], r[1]-a.r[1], r[2]-a.r[2], r[3]-a.r[3],
00979                         r[4]-a.r[4], r[5]-a.r[5], r[6]-a.r[6], r[7]-a.r[7],
00980                         r[8]-a.r[8], r[9]-a.r[9], r[10]-a.r[10], r[11]-a.r[11],
00981                         r[12]-a.r[12], r[13]-a.r[13], r[14]-a.r[14], r[15]-a.r[15] );
00982 }
00983 
00984 /*
00985  * Code ripped from the GLU library
00986  * Compute inverse of 4x4 transformation matrix.
00987  * Code contributed by Jacques Leroy jle@star.be
00988  * Return zero matrix on failure (singular matrix)
00989  */
00990 template<class T> Matrix4<T> Matrix4<T>::inverse() const
00991 {
00992     const T * m = r;
00993     T out[16];
00994 
00995 /* NB. OpenGL Matrices are COLUMN major. */
00996 #define SWAP_ROWS(a, b) { T *_tmp = a; (a)=(b); (b)=_tmp; }
00997 #define MAT(m,r,c) (m)[(c)*4+(r)]
00998 
00999    T wtmp[4][8];
01000    T m0, m1, m2, m3, s;
01001    T *r0, *r1, *r2, *r3;
01002 
01003    r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3];
01004 
01005    r0[0] = MAT(m, 0, 0), r0[1] = MAT(m, 0, 1),
01006       r0[2] = MAT(m, 0, 2), r0[3] = MAT(m, 0, 3),
01007       r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0,
01008       r1[0] = MAT(m, 1, 0), r1[1] = MAT(m, 1, 1),
01009       r1[2] = MAT(m, 1, 2), r1[3] = MAT(m, 1, 3),
01010       r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0,
01011       r2[0] = MAT(m, 2, 0), r2[1] = MAT(m, 2, 1),
01012       r2[2] = MAT(m, 2, 2), r2[3] = MAT(m, 2, 3),
01013       r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0,
01014       r3[0] = MAT(m, 3, 0), r3[1] = MAT(m, 3, 1),
01015       r3[2] = MAT(m, 3, 2), r3[3] = MAT(m, 3, 3),
01016       r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0;
01017 
01018    /* choose pivot - or die */
01019    if (fabs(r3[0]) > fabs(r2[0]))
01020       SWAP_ROWS(r3, r2);
01021    if (fabs(r2[0]) > fabs(r1[0]))
01022       SWAP_ROWS(r2, r1);
01023    if (fabs(r1[0]) > fabs(r0[0]))
01024       SWAP_ROWS(r1, r0);
01025    if (0.0 == r0[0])
01026       return Matrix4<T>();
01027 
01028    /* eliminate first variable     */
01029    m1 = r1[0] / r0[0];
01030    m2 = r2[0] / r0[0];
01031    m3 = r3[0] / r0[0];
01032    s = r0[1];
01033    r1[1] -= m1 * s;
01034    r2[1] -= m2 * s;
01035    r3[1] -= m3 * s;
01036    s = r0[2];
01037    r1[2] -= m1 * s;
01038    r2[2] -= m2 * s;
01039    r3[2] -= m3 * s;
01040    s = r0[3];
01041    r1[3] -= m1 * s;
01042    r2[3] -= m2 * s;
01043    r3[3] -= m3 * s;
01044    s = r0[4];
01045    if (s != 0.0) {
01046       r1[4] -= m1 * s;
01047       r2[4] -= m2 * s;
01048       r3[4] -= m3 * s;
01049    }
01050    s = r0[5];
01051    if (s != 0.0) {
01052       r1[5] -= m1 * s;
01053       r2[5] -= m2 * s;
01054       r3[5] -= m3 * s;
01055    }
01056    s = r0[6];
01057    if (s != 0.0) {
01058       r1[6] -= m1 * s;
01059       r2[6] -= m2 * s;
01060       r3[6] -= m3 * s;
01061    }
01062    s = r0[7];
01063    if (s != 0.0) {
01064       r1[7] -= m1 * s;
01065       r2[7] -= m2 * s;
01066       r3[7] -= m3 * s;
01067    }
01068 
01069    /* choose pivot - or die */
01070    if (fabs(r3[1]) > fabs(r2[1]))
01071       SWAP_ROWS(r3, r2);
01072    if (fabs(r2[1]) > fabs(r1[1]))
01073       SWAP_ROWS(r2, r1);
01074    if (0.0 == r1[1])
01075       return Matrix4<T>();
01076 
01077    /* eliminate second variable */
01078    m2 = r2[1] / r1[1];
01079    m3 = r3[1] / r1[1];
01080    r2[2] -= m2 * r1[2];
01081    r3[2] -= m3 * r1[2];
01082    r2[3] -= m2 * r1[3];
01083    r3[3] -= m3 * r1[3];
01084    s = r1[4];
01085    if (0.0 != s) {
01086       r2[4] -= m2 * s;
01087       r3[4] -= m3 * s;
01088    }
01089    s = r1[5];
01090    if (0.0 != s) {
01091       r2[5] -= m2 * s;
01092       r3[5] -= m3 * s;
01093    }
01094    s = r1[6];
01095    if (0.0 != s) {
01096       r2[6] -= m2 * s;
01097       r3[6] -= m3 * s;
01098    }
01099    s = r1[7];
01100    if (0.0 != s) {
01101       r2[7] -= m2 * s;
01102       r3[7] -= m3 * s;
01103    }
01104 
01105    /* choose pivot - or die */
01106    if (fabs(r3[2]) > fabs(r2[2]))
01107       SWAP_ROWS(r3, r2);
01108    if (0.0 == r2[2])
01109       return Matrix4<T>();
01110 
01111    /* eliminate third variable */
01112    m3 = r3[2] / r2[2];
01113    r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4],
01114       r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6], r3[7] -= m3 * r2[7];
01115 
01116    /* last check */
01117    if (0.0 == r3[3])
01118       return Matrix4<T>();
01119 
01120    s = 1.0 / r3[3];     /* now back substitute row 3 */
01121    r3[4] *= s;
01122    r3[5] *= s;
01123    r3[6] *= s;
01124    r3[7] *= s;
01125 
01126    m2 = r2[3];          /* now back substitute row 2 */
01127    s = 1.0 / r2[2];
01128    r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2),
01129       r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2);
01130    m1 = r1[3];
01131    r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1,
01132       r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1;
01133    m0 = r0[3];
01134    r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0,
01135       r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0;
01136 
01137    m1 = r1[2];          /* now back substitute row 1 */
01138    s = 1.0 / r1[1];
01139    r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1),
01140       r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1);
01141    m0 = r0[2];
01142    r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0,
01143       r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0;
01144 
01145    m0 = r0[1];          /* now back substitute row 0 */
01146    s = 1.0 / r0[0];
01147    r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0),
01148       r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0);
01149 
01150    MAT(out, 0, 0) = r0[4];
01151    MAT(out, 0, 1) = r0[5], MAT(out, 0, 2) = r0[6];
01152    MAT(out, 0, 3) = r0[7], MAT(out, 1, 0) = r1[4];
01153    MAT(out, 1, 1) = r1[5], MAT(out, 1, 2) = r1[6];
01154    MAT(out, 1, 3) = r1[7], MAT(out, 2, 0) = r2[4];
01155    MAT(out, 2, 1) = r2[5], MAT(out, 2, 2) = r2[6];
01156    MAT(out, 2, 3) = r2[7], MAT(out, 3, 0) = r3[4];
01157    MAT(out, 3, 1) = r3[5], MAT(out, 3, 2) = r3[6];
01158    MAT(out, 3, 3) = r3[7];
01159 
01160    return Matrix4<T>(out);
01161 
01162 #undef MAT
01163 #undef SWAP_ROWS
01164 }
01165 
01166 
01167 template<class T> void Matrix4<T>::print(void) const
01168 {
01169     printf("[%5.2lf %5.2lf %5.2lf %17.12le]\n"
01170            "[%5.2lf %5.2lf %5.2lf %17.12le]\n"
01171            "[%5.2lf %5.2lf %5.2lf %17.12le]\n"
01172            "[%5.2lf %5.2lf %5.2lf %17.12le]\n\n",
01173     r[0],r[4],r[8],r[12],
01174     r[1],r[5],r[9],r[13],
01175     r[2],r[6],r[10],r[14],
01176     r[3],r[7],r[11],r[15]);
01177 }
01178 
01179 
01180 template<class T> inline
01181 T operator*(const Vector2<T>&a,const Vector2<T>&b) {
01182   return a.v[0] * b.v[0] + a.v[1] * b.v[1];
01183 }
01184 
01185 template<class T> inline
01186 T operator*(const Vector3<T>&a,const Vector3<T>&b) {
01187   return a.v[0] * b.v[0] + a.v[1] * b.v[1] + a.v[2] * b.v[2];
01188 }
01189 
01190 template<class T> inline
01191 T operator*(const Vector4<T>&a,const Vector4<T>&b) {
01192   return a.v[0]*b.v[0] + a.v[1]*b.v[1] + a.v[2]*b.v[2] + a.v[3]*b.v[3];
01193 }
01194 
01195 template<class T> inline
01196 Vector2<T> operator*(T s,const Vector2<T>&v) {
01197   return Vector2<T>(s*v[0],s*v[1]);
01198 }
01199 
01200 template<class T> inline
01201 Vector3<T> operator*(T s,const Vector3<T>&v) {
01202   return Vector3<T>(s*v[0],s*v[1],s*v[2]);
01203 }
01204 
01205 template<class T> inline
01206 Vector4<T> operator*(T s,const Vector4<T>&v) {
01207   return Vector4<T>(s*v[0],s*v[1],s*v[2],s*v[3]);
01208 }
01209 
01210 Q_DECLARE_TYPEINFO(Vec2d, Q_PRIMITIVE_TYPE);
01211 Q_DECLARE_TYPEINFO(Vec2f, Q_PRIMITIVE_TYPE);
01212 Q_DECLARE_TYPEINFO(Vec2i, Q_PRIMITIVE_TYPE);
01213 Q_DECLARE_TYPEINFO(Vec3d, Q_PRIMITIVE_TYPE);
01214 Q_DECLARE_TYPEINFO(Vec3f, Q_PRIMITIVE_TYPE);
01215 Q_DECLARE_TYPEINFO(Vec4d, Q_PRIMITIVE_TYPE);
01216 Q_DECLARE_TYPEINFO(Vec4f, Q_PRIMITIVE_TYPE);
01217 Q_DECLARE_TYPEINFO(Vec4i, Q_PRIMITIVE_TYPE);
01218 Q_DECLARE_TYPEINFO(Mat4d, Q_PRIMITIVE_TYPE);
01219 Q_DECLARE_TYPEINFO(Mat4f, Q_PRIMITIVE_TYPE);
01220 
01221 #endif // _VECMATH_H_