Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

vecmath.h

Go to the documentation of this file.
00001 // vecmath.h
00002 //
00003 // Copyright (C) 2000, Chris Laurel <claurel@shatters.net>
00004 //
00005 // Basic templatized vector and matrix math library.
00006 //
00007 // This program is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2
00010 // of the License, or (at your option) any later version.
00011 
00012 
00013 #ifndef _VECMATH_H_
00014 #define _VECMATH_H_
00015 
00016 #include <cmath>
00017 
00018 
00019 template<class T> class Point3;
00020 
00021 template<class T> class Vector3
00022 {
00023 public:
00024     inline Vector3();
00025     inline Vector3(const Vector3<T>&);
00026     inline Vector3(T, T, T);
00027     inline Vector3(T*);
00028 
00029     inline T& operator[](int) const;
00030     inline Vector3& operator+=(const Vector3<T>&);
00031     inline Vector3& operator-=(const Vector3<T>&);
00032     inline Vector3& operator*=(T);
00033 
00034     inline Vector3 operator-() const;
00035     inline Vector3 operator+() const;
00036 
00037     inline T length() const;
00038     inline T lengthSquared() const;
00039     inline void normalize();
00040 
00041     T x, y, z;
00042 };
00043 
00044 template<class T> class Point3
00045 {
00046 public:
00047     inline Point3();
00048     inline Point3(const Point3&);
00049     inline Point3(T, T, T);
00050     inline Point3(T*);
00051 
00052     inline T& operator[](int) const;
00053     inline Point3& operator+=(const Vector3<T>&);
00054     inline Point3& operator-=(const Vector3<T>&);
00055     inline Point3& operator*=(T);
00056 
00057     inline T distanceTo(const Point3&) const;
00058     inline T distanceToSquared(const Point3&) const;
00059     inline T distanceFromOrigin() const;
00060     inline T distanceFromOriginSquared() const;
00061 
00062     T x, y, z;
00063 };
00064 
00065 
00066 template<class T> class Point2;
00067 
00068 template<class T> class Vector2
00069 {
00070 public:
00071     inline Vector2();
00072     inline Vector2(T, T);
00073 
00074     T x, y;
00075 };
00076 
00077 template<class T> class Point2
00078 {
00079 public:
00080     inline Point2();
00081     inline Point2(T, T);
00082 
00083     T x, y;
00084 };
00085 
00086 
00087 template<class T> class Vector4
00088 {
00089  public:
00090     inline Vector4();
00091     inline Vector4(T, T, T, T);
00092 
00093     inline T& operator[](int) const;
00094     inline Vector4& operator+=(const Vector4&);
00095     inline Vector4& operator-=(const Vector4&);
00096     inline Vector4& operator*=(T);
00097 
00098     inline Vector4 operator-() const;
00099     inline Vector4 operator+() const;
00100 
00101     T x, y, z, w;
00102 };
00103 
00104 
00105 template<class T> class Matrix4
00106 {
00107  public:
00108     Matrix4();
00109     Matrix4(const Vector4<T>&, const Vector4<T>&,
00110             const Vector4<T>&, const Vector4<T>&);
00111     Matrix4(const Matrix4<T>& m);
00112 
00113     inline const Vector4<T>& operator[](int) const;
00114     inline Vector4<T> row(int) const;
00115     inline Vector4<T> column(int) const;
00116 
00117     static Matrix4<T> identity();
00118     static Matrix4<T> translation(const Point3<T>&);
00119     static Matrix4<T> translation(const Vector3<T>&);
00120     static Matrix4<T> rotation(const Vector3<T>&, T);
00121     static Matrix4<T> xrotation(T);
00122     static Matrix4<T> yrotation(T);
00123     static Matrix4<T> zrotation(T);
00124     static Matrix4<T> scaling(const Vector3<T>&);
00125     static Matrix4<T> scaling(T);
00126 
00127     void translate(const Point3<T>&);
00128 
00129     Matrix4<T> transpose() const;
00130     Matrix4<T> inverse() const;
00131 
00132     Vector4<T> r[4];
00133 };
00134 
00135 
00136 template<class T> class Matrix3
00137 {
00138  public:
00139     Matrix3();
00140     Matrix3(const Vector3<T>&, const Vector3<T>&, const Vector3<T>&);
00141     template<class U> Matrix3(const Matrix3<U>&);
00142 
00143     static Matrix3<T> xrotation(T);
00144     static Matrix3<T> yrotation(T);
00145     static Matrix3<T> zrotation(T);
00146     static Matrix3<T> scaling(const Vector3<T>&);
00147     static Matrix3<T> scaling(T);
00148 
00149     inline const Vector3<T>& operator[](int) const;
00150     inline Vector3<T> row(int) const;
00151     inline Vector3<T> column(int) const;
00152 
00153     inline Matrix3& operator*=(T);
00154 
00155     static Matrix3<T> identity();
00156 
00157     Matrix3<T> transpose() const;
00158     Matrix3<T> inverse() const;
00159     T determinant() const;
00160 
00161     //    template<class U> operator Matrix3<U>() const;
00162 
00163     Vector3<T> r[3];
00164 };
00165 
00166 
00167 typedef Vector3<float>   Vec3f;
00168 typedef Vector3<double>  Vec3d;
00169 typedef Point3<float>    Point3f;
00170 typedef Point3<double>   Point3d;
00171 typedef Vector2<float>   Vec2f;
00172 typedef Point2<float>    Point2f;
00173 typedef Vector4<float>   Vec4f;
00174 typedef Vector4<double>  Vec4d;
00175 typedef Matrix4<float>   Mat4f;
00176 typedef Matrix4<double>  Mat4d;
00177 typedef Matrix3<float>   Mat3f;
00178 typedef Matrix3<double>  Mat3d;
00179 
00180 
00181 //**** Vector3 constructors
00182 
00183 template<class T> Vector3<T>::Vector3() : x(0), y(0), z(0)
00184 {
00185 }
00186 
00187 template<class T> Vector3<T>::Vector3(const Vector3<T>& v) :
00188     x(v.x), y(v.y), z(v.z)
00189 {
00190 }
00191 
00192 template<class T> Vector3<T>::Vector3(T _x, T _y, T _z) : x(_x), y(_y), z(_z)
00193 {
00194 }
00195 
00196 template<class T> Vector3<T>::Vector3(T* v) : x(v[0]), y(v[1]), z(v[2])
00197 {
00198 }
00199 
00200 //**** Vector3 operators
00201 
00202 template<class T> T& Vector3<T>::operator[](int n) const
00203 {
00204     // Not portable--I'll write a new version when I try to compile on a
00205     // platform where it bombs.
00206     return ((T*) this)[n];
00207 }
00208 
00209 template<class T> Vector3<T>& Vector3<T>::operator+=(const Vector3<T>& a)
00210 {
00211     x += a.x; y += a.y; z += a.z;
00212     return *this;
00213 }
00214 
00215 template<class T> Vector3<T>& Vector3<T>::operator-=(const Vector3<T>& a)
00216 {
00217     x -= a.x; y -= a.y; z -= a.z;
00218     return *this;
00219 }
00220 
00221 template<class T> Vector3<T>& Vector3<T>::operator*=(T s)
00222 {
00223     x *= s; y *= s; z *= s;
00224     return *this;
00225 }
00226 
00227 template<class T> Vector3<T> Vector3<T>::operator-() const
00228 {
00229     return Vector3<T>(-x, -y, -z);
00230 }
00231 
00232 template<class T> Vector3<T> Vector3<T>::operator+() const
00233 {
00234     return *this;
00235 }
00236 
00237 
00238 template<class T> Vector3<T> operator+(const Vector3<T>& a, const Vector3<T>& b)
00239 {
00240     return Vector3<T>(a.x + b.x, a.y + b.y, a.z + b.z);
00241 }
00242 
00243 template<class T> Vector3<T> operator-(const Vector3<T>& a, const Vector3<T>& b)
00244 {
00245     return Vector3<T>(a.x - b.x, a.y - b.y, a.z - b.z);
00246 }
00247 
00248 template<class T> Vector3<T> operator*(T s, const Vector3<T>& v)
00249 {
00250     return Vector3<T>(s * v.x, s * v.y, s * v.z);
00251 }
00252 
00253 template<class T> Vector3<T> operator*(const Vector3<T>& v, T s)
00254 {
00255     return Vector3<T>(s * v.x, s * v.y, s * v.z);
00256 }
00257 
00258 // dot product
00259 template<class T> T operator*(const Vector3<T>& a, const Vector3<T>& b)
00260 {
00261     return a.x * b.x + a.y * b.y + a.z * b.z;
00262 }
00263 
00264 // cross product
00265 template<class T> Vector3<T> operator^(const Vector3<T>& a, const Vector3<T>& b)
00266 {
00267     return Vector3<T>(a.y * b.z - a.z * b.y,
00268                       a.z * b.x - a.x * b.z,
00269                       a.x * b.y - a.y * b.x);
00270 }
00271 
00272 template<class T> bool operator==(const Vector3<T>& a, const Vector3<T>& b)
00273 {
00274     return a.x == b.x && a.y == b.y && a.z == b.z;
00275 }
00276 
00277 template<class T> bool operator!=(const Vector3<T>& a, const Vector3<T>& b)
00278 {
00279     return a.x != b.x || a.y != b.y || a.z != b.z;
00280 }
00281 
00282 template<class T> Vector3<T> operator/(const Vector3<T>& v, T s)
00283 {
00284     T is = 1 / s;
00285     return Vector3<T>(is * v.x, is * v.y, is * v.z);
00286 }
00287 
00288 template<class T> T dot(const Vector3<T>& a, const Vector3<T>& b)
00289 {
00290     return a.x * b.x + a.y * b.y + a.z * b.z;
00291 }
00292 
00293 template<class T> Vector3<T> cross(const Vector3<T>& a, const Vector3<T>& b)
00294 {
00295     return Vector3<T>(a.y * b.z - a.z * b.y,
00296                       a.z * b.x - a.x * b.z,
00297                       a.x * b.y - a.y * b.x);
00298 }
00299 
00300 template<class T> T Vector3<T>::length() const
00301 {
00302     return (T) sqrt(x * x + y * y + z * z);
00303 }
00304 
00305 template<class T> T Vector3<T>::lengthSquared() const
00306 {
00307     return x * x + y * y + z * z;
00308 }
00309 
00310 template<class T> void Vector3<T>::normalize()
00311 {
00312     T s = 1 / (T) sqrt(x * x + y * y + z * z);
00313     x *= s;
00314     y *= s;
00315     z *= s;
00316 }
00317 
00318 
00319 //**** Point3 constructors
00320 
00321 template<class T> Point3<T>::Point3() : x(0), y(0), z(0)
00322 {
00323 }
00324 
00325 template<class T> Point3<T>::Point3(const Point3<T>& p) :
00326     x(p.x), y(p.y), z(p.z)
00327 {
00328 }
00329 
00330 template<class T> Point3<T>::Point3(T _x, T _y, T _z) : x(_x), y(_y), z(_z)
00331 {
00332 }
00333 
00334 template<class T> Point3<T>::Point3(T* p) : x(p[0]), y(p[1]), z(p[2])
00335 {
00336 }
00337 
00338 
00339 //**** Point3 operators
00340 
00341 template<class T> T& Point3<T>::operator[](int n) const
00342 {
00343     // Not portable--I'll write a new version when I try to compile on a
00344     // platform where it bombs.
00345     return ((T*) this)[n];
00346 }
00347 
00348 template<class T> Vector3<T> operator-(const Point3<T>& a, const Point3<T>& b)
00349 {
00350     return Vector3<T>(a.x - b.x, a.y - b.y, a.z - b.z);
00351 }
00352 
00353 template<class T> Point3<T>& Point3<T>::operator+=(const Vector3<T>& v)
00354 {
00355     x += v.x; y += v.y; z += v.z;
00356     return *this;
00357 }
00358 
00359 template<class T> Point3<T>& Point3<T>::operator-=(const Vector3<T>& v)
00360 {
00361     x -= v.x; y -= v.y; z -= v.z;
00362     return *this;
00363 }
00364 
00365 template<class T> Point3<T>& Point3<T>::operator*=(T s)
00366 {
00367     x *= s; y *= s; z *= s;
00368     return *this;
00369 }
00370 
00371 template<class T> bool operator==(const Point3<T>& a, const Point3<T>& b)
00372 {
00373     return a.x == b.x && a.y == b.y && a.z == b.z;
00374 }
00375 
00376 template<class T> bool operator!=(const Point3<T>& a, const Point3<T>& b)
00377 {
00378     return a.x != b.x || a.y != b.y || a.z != b.z;
00379 }
00380 
00381 template<class T> Point3<T> operator+(const Point3<T>& p, const Vector3<T>& v)
00382 {
00383     return Point3<T>(p.x + v.x, p.y + v.y, p.z + v.z);
00384 }
00385 
00386 template<class T> Point3<T> operator-(const Point3<T>& p, const Vector3<T>& v)
00387 {
00388     return Point3<T>(p.x - v.x, p.y - v.y, p.z - v.z);
00389 }
00390 
00391 // Naughty naughty . . .  remove these since they aren't proper
00392 // point methods--changing the implicit homogenous coordinate isn't
00393 // allowed.
00394 template<class T> Point3<T> operator*(const Point3<T>& p, T s)
00395 {
00396     return Point3<T>(p.x * s, p.y * s, p.z * s);
00397 }
00398 
00399 template<class T> Point3<T> operator*(T s, const Point3<T>& p)
00400 {
00401     return Point3<T>(p.x * s, p.y * s, p.z * s);
00402 }
00403 
00404 
00405 //**** Point3 methods
00406 
00407 template<class T> T Point3<T>::distanceTo(const Point3& p) const
00408 {
00409     return (T) sqrt((p.x - x) * (p.x - x) +
00410                     (p.y - y) * (p.y - y) +
00411                     (p.z - z) * (p.z - z));
00412 }
00413 
00414 template<class T> T Point3<T>::distanceToSquared(const Point3& p) const
00415 {
00416     return ((p.x - x) * (p.x - x) +
00417             (p.y - y) * (p.y - y) +
00418             (p.z - z) * (p.z - z));
00419 }
00420 
00421 template<class T> T Point3<T>::distanceFromOrigin() const
00422 {
00423     return (T) sqrt(x * x + y * y + z * z);
00424 }
00425 
00426 template<class T> T Point3<T>::distanceFromOriginSquared() const
00427 {
00428     return x * x + y * y + z * z;
00429 }
00430 
00431 
00432 
00433 //**** Vector2 constructors
00434 template<class T> Vector2<T>::Vector2() : x(0), y(0)
00435 {
00436 }
00437 
00438 template<class T> Vector2<T>::Vector2(T _x, T _y) : x(_x), y(_y)
00439 {
00440 }
00441 
00442 
00443 //**** Vector2 operators
00444 template<class T> bool operator==(const Vector2<T>& a, const Vector2<T>& b)
00445 {
00446     return a.x == b.x && a.y == b.y;
00447 }
00448 
00449 template<class T> bool operator!=(const Vector2<T>& a, const Vector2<T>& b)
00450 {
00451     return a.x != b.x || a.y != b.y;
00452 }
00453 
00454 
00455 //**** Point2 constructors
00456 
00457 template<class T> Point2<T>::Point2() : x(0), y(0)
00458 {
00459 }
00460 
00461 template<class T> Point2<T>::Point2(T _x, T _y) : x(_x), y(_y)
00462 {
00463 }
00464 
00465 
00466 //**** Point2 operators
00467 
00468 template<class T> bool operator==(const Point2<T>& a, const Point2<T>& b)
00469 {
00470     return a.x == b.x && a.y == b.y;
00471 }
00472 
00473 template<class T> bool operator!=(const Point2<T>& a, const Point2<T>& b)
00474 {
00475     return a.x != b.x || a.y != b.y;
00476 }
00477 
00478 
00479 //**** Vector4 constructors
00480 
00481 template<class T> Vector4<T>::Vector4() : x(0), y(0), z(0), w(0)
00482 {
00483 }
00484 
00485 template<class T> Vector4<T>::Vector4(T _x, T _y, T _z, T _w) :
00486     x(_x), y(_y), z(_z), w(_w)
00487 {
00488 }
00489 
00490 
00491 //**** Vector4 operators
00492 
00493 template<class T> T& Vector4<T>::operator[](int n) const
00494 {
00495     // Not portable--I'll write a new version when I try to compile on a
00496     // platform where it bombs.
00497     return ((T*) this)[n];
00498 }
00499 
00500 template<class T> bool operator==(const Vector4<T>& a, const Vector4<T>& b)
00501 {
00502     return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w;
00503 }
00504 
00505 template<class T> bool operator!=(const Vector4<T>& a, const Vector4<T>& b)
00506 {
00507     return a.x != b.x || a.y != b.y || a.z != b.z || a.w != b.w;
00508 }
00509 
00510 template<class T> Vector4<T>& Vector4<T>::operator+=(const Vector4<T>& a)
00511 {
00512     x += a.x; y += a.y; z += a.z; w += a.w;
00513     return *this;
00514 }
00515 
00516 template<class T> Vector4<T>& Vector4<T>::operator-=(const Vector4<T>& a)
00517 {
00518     x -= a.x; y -= a.y; z -= a.z; w -= a.w;
00519     return *this;
00520 }
00521 
00522 template<class T> Vector4<T>& Vector4<T>::operator*=(T s)
00523 {
00524     x *= s; y *= s; z *= s; w *= s;
00525     return *this;
00526 }
00527 
00528 template<class T> Vector4<T> Vector4<T>::operator-() const
00529 {
00530     return Vector4<T>(-x, -y, -z, -w);
00531 }
00532 
00533 template<class T> Vector4<T> Vector4<T>::operator+() const
00534 {
00535     return *this;
00536 }
00537 
00538 template<class T> Vector4<T> operator+(const Vector4<T>& a, const Vector4<T>& b)
00539 {
00540     return Vector4<T>(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
00541 }
00542 
00543 template<class T> Vector4<T> operator-(const Vector4<T>& a, const Vector4<T>& b)
00544 {
00545     return Vector4<T>(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
00546 }
00547 
00548 template<class T> Vector4<T> operator*(T s, const Vector4<T>& v)
00549 {
00550     return Vector4<T>(s * v.x, s * v.y, s * v.z, s * v.w);
00551 }
00552 
00553 template<class T> Vector4<T> operator*(const Vector4<T>& v, T s)
00554 {
00555     return Vector4<T>(s * v.x, s * v.y, s * v.z, s * v.w);
00556 }
00557 
00558 // dot product
00559 template<class T> T operator*(const Vector4<T>& a, const Vector4<T>& b)
00560 {
00561     return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
00562 }
00563 
00564 template<class T> T dot(const Vector4<T>& a, const Vector4<T>& b)
00565 {
00566     return a * b;
00567 }
00568 
00569 
00570 
00571 //**** Matrix3 constructors
00572 
00573 template<class T> Matrix3<T>::Matrix3()
00574 {
00575     r[0] = Vector3<T>(0, 0, 0);
00576     r[1] = Vector3<T>(0, 0, 0);
00577     r[2] = Vector3<T>(0, 0, 0);
00578 }
00579 
00580 
00581 template<class T> Matrix3<T>::Matrix3(const Vector3<T>& r0,
00582                                       const Vector3<T>& r1,
00583                                       const Vector3<T>& r2)
00584 {
00585     r[0] = r0;
00586     r[1] = r1;
00587     r[2] = r2;
00588 }
00589 
00590 
00591 #if 0
00592 template<class T, class U> Matrix3<T>::Matrix3(const Matrix3<U>& m)
00593 {
00594 #if 0
00595     r[0] = m.r[0];
00596     r[1] = m.r[1];
00597     r[2] = m.r[2];
00598 #endif
00599     r[0].x = m.r[0].x; r[0].y = m.r[0].y; r[0].z = m.r[0].z;
00600     r[1].x = m.r[1].x; r[1].y = m.r[1].y; r[1].z = m.r[1].z;
00601     r[2].x = m.r[2].x; r[2].y = m.r[2].y; r[2].z = m.r[2].z;
00602 }
00603 #endif
00604 
00605 
00606 //**** Matrix3 operators
00607 
00608 template<class T> const Vector3<T>& Matrix3<T>::operator[](int n) const
00609 {
00610     //    return const_cast<Vector3<T>&>(r[n]);
00611     return r[n];
00612 }
00613 
00614 template<class T> Vector3<T> Matrix3<T>::row(int n) const
00615 {
00616     return r[n];
00617 }
00618 
00619 template<class T> Vector3<T> Matrix3<T>::column(int n) const
00620 {
00621     return Vector3<T>(r[0][n], r[1][n], r[2][n]);
00622 }
00623 
00624 template<class T> Matrix3<T>& Matrix3<T>::operator*=(T s)
00625 {
00626     r[0] *= s;
00627     r[1] *= s;
00628     r[2] *= s;
00629     return *this;
00630 }
00631 
00632 
00633 // pre-multiply column vector by a 3x3 matrix
00634 template<class T> Vector3<T> operator*(const Matrix3<T>& m, const Vector3<T>& v)
00635 {
00636     return Vector3<T>(m.r[0].x * v.x + m.r[0].y * v.y + m.r[0].z * v.z,
00637                       m.r[1].x * v.x + m.r[1].y * v.y + m.r[1].z * v.z,
00638                       m.r[2].x * v.x + m.r[2].y * v.y + m.r[2].z * v.z);
00639 }
00640 
00641 
00642 // post-multiply row vector by a 3x3 matrix
00643 template<class T> Vector3<T> operator*(const Vector3<T>& v, const Matrix3<T>& m)
00644 {
00645     return Vector3<T>(m.r[0].x * v.x + m.r[1].x * v.y + m.r[2].x * v.z,
00646                       m.r[0].y * v.x + m.r[1].y * v.y + m.r[2].y * v.z,
00647                       m.r[0].z * v.x + m.r[1].z * v.y + m.r[2].z * v.z);
00648 }
00649 
00650 
00651 // pre-multiply column point by a 3x3 matrix
00652 template<class T> Point3<T> operator*(const Matrix3<T>& m, const Point3<T>& p)
00653 {
00654     return Point3<T>(m.r[0].x * p.x + m.r[0].y * p.y + m.r[0].z * p.z,
00655                      m.r[1].x * p.x + m.r[1].y * p.y + m.r[1].z * p.z,
00656                      m.r[2].x * p.x + m.r[2].y * p.y + m.r[2].z * p.z);
00657 }
00658 
00659 
00660 // post-multiply row point by a 3x3 matrix
00661 template<class T> Point3<T> operator*(const Point3<T>& p, const Matrix3<T>& m)
00662 {
00663     return Point3<T>(m.r[0].x * p.x + m.r[1].x * p.y + m.r[2].x * p.z,
00664                      m.r[0].y * p.x + m.r[1].y * p.y + m.r[2].y * p.z,
00665                      m.r[0].z * p.x + m.r[1].z * p.y + m.r[2].z * p.z);
00666 }
00667 
00668 
00669 template<class T> Matrix3<T> operator*(const Matrix3<T>& a,
00670                                        const Matrix3<T>& b)
00671 {
00672 #define MATMUL(R, C) (a[R].x * b[0].C + a[R].y * b[1].C + a[R].z * b[2].C)
00673     return Matrix3<T>(Vector3<T>(MATMUL(0, x), MATMUL(0, y), MATMUL(0, z)),
00674                       Vector3<T>(MATMUL(1, x), MATMUL(1, y), MATMUL(1, z)),
00675                       Vector3<T>(MATMUL(2, x), MATMUL(2, y), MATMUL(2, z)));
00676 #undef MATMUL
00677 }
00678 
00679 
00680 template<class T> Matrix3<T> operator+(const Matrix3<T>& a,
00681                                        const Matrix3<T>& b)
00682 {
00683     return Matrix3<T>(a.r[0] + b.r[0],
00684                       a.r[1] + b.r[1],
00685                       a.r[2] + b.r[2]);
00686 }
00687 
00688 
00689 template<class T> Matrix3<T> Matrix3<T>::identity()
00690 {
00691     return Matrix3<T>(Vector3<T>(1, 0, 0),
00692                       Vector3<T>(0, 1, 0),
00693                       Vector3<T>(0, 0, 1));
00694 }
00695 
00696 
00697 template<class T> Matrix3<T> Matrix3<T>::transpose() const
00698 {
00699     return Matrix3<T>(Vector3<T>(r[0].x, r[1].x, r[2].x),
00700                       Vector3<T>(r[0].y, r[1].y, r[2].y),
00701                       Vector3<T>(r[0].z, r[1].z, r[2].z));
00702 }
00703 
00704 
00705 template<class T> T det2x2(T a, T b, T c, T d)
00706 {
00707     return a * d - b * c;
00708 }
00709 
00710 template<class T> T Matrix3<T>::determinant() const
00711 {
00712     return (r[0].x * r[1].y * r[2].z +
00713             r[0].y * r[1].z * r[2].x +
00714             r[0].z * r[1].x * r[2].y -
00715             r[0].z * r[1].y * r[2].x -
00716             r[0].x * r[1].z * r[2].y -
00717             r[0].y * r[1].x * r[2].z);
00718 }
00719 
00720 
00721 template<class T> Matrix3<T> Matrix3<T>::inverse() const
00722 {
00723     Matrix3<T> adjoint;
00724 
00725     // Just use Cramer's rule for now . . .
00726     adjoint.r[0].x =  det2x2(r[1].y, r[1].z, r[2].y, r[2].z);
00727     adjoint.r[0].y = -det2x2(r[1].x, r[1].z, r[2].x, r[2].z);
00728     adjoint.r[0].z =  det2x2(r[1].x, r[1].y, r[2].x, r[2].y);
00729     adjoint.r[1].x = -det2x2(r[0].y, r[0].z, r[2].y, r[2].z);
00730     adjoint.r[1].y =  det2x2(r[0].x, r[0].z, r[2].x, r[2].z);
00731     adjoint.r[1].z = -det2x2(r[0].x, r[0].y, r[2].x, r[2].y);
00732     adjoint.r[2].x =  det2x2(r[0].y, r[0].z, r[1].y, r[1].z);
00733     adjoint.r[2].y = -det2x2(r[0].x, r[0].z, r[1].x, r[1].z);
00734     adjoint.r[2].z =  det2x2(r[0].x, r[0].y, r[1].x, r[1].y);
00735     adjoint *= 1 / determinant();
00736 
00737     return adjoint;
00738 }
00739 
00740 
00741 template<class T> Matrix3<T> Matrix3<T>::xrotation(T angle)
00742 {
00743     T c = (T) cos(angle);
00744     T s = (T) sin(angle);
00745 
00746     return Matrix3<T>(Vector3<T>(1, 0, 0),
00747                       Vector3<T>(0, c, -s),
00748                       Vector3<T>(0, s, c));
00749 }
00750 
00751 
00752 template<class T> Matrix3<T> Matrix3<T>::yrotation(T angle)
00753 {
00754     T c = (T) cos(angle);
00755     T s = (T) sin(angle);
00756 
00757     return Matrix3<T>(Vector3<T>(c, 0, s),
00758                       Vector3<T>(0, 1, 0),
00759                       Vector3<T>(-s, 0, c));
00760 }
00761 
00762 
00763 template<class T> Matrix3<T> Matrix3<T>::zrotation(T angle)
00764 {
00765     T c = (T) cos(angle);
00766     T s = (T) sin(angle);
00767 
00768     return Matrix3<T>(Vector3<T>(c, -s, 0),
00769                       Vector3<T>(s, c, 0),
00770                       Vector3<T>(0, 0, 1));
00771 }
00772 
00773 
00774 template<class T> Matrix3<T> Matrix3<T>::scaling(const Vector3<T>& scale)
00775 {
00776     return Matrix3<T>(Vector3<T>(scale.x, 0, 0),
00777                       Vector3<T>(0, scale.y, 0),
00778                       Vector3<T>(0, 0, scale.z));
00779 }
00780 
00781 
00782 template<class T> Matrix3<T> Matrix3<T>::scaling(T scale)
00783 {
00784     return scaling(Vector3<T>(scale, scale, scale));
00785 }
00786 
00787 
00788 /***********************************************
00789  **
00790  **  Matrix4 methods
00791  **
00792  ***********************************************/
00793 
00794 template<class T> Matrix4<T>::Matrix4()
00795 {
00796     r[0] = Vector4<T>(0, 0, 0, 0);
00797     r[1] = Vector4<T>(0, 0, 0, 0);
00798     r[2] = Vector4<T>(0, 0, 0, 0);
00799     r[3] = Vector4<T>(0, 0, 0, 0);
00800 }
00801 
00802 
00803 template<class T> Matrix4<T>::Matrix4(const Vector4<T>& v0,
00804                                       const Vector4<T>& v1,
00805                                       const Vector4<T>& v2,
00806                                       const Vector4<T>& v3)
00807 {
00808     r[0] = v0;
00809     r[1] = v1;
00810     r[2] = v2;
00811     r[3] = v3;
00812 }
00813 
00814 
00815 template<class T> Matrix4<T>::Matrix4(const Matrix4<T>& m)
00816 {
00817     r[0] = m.r[0];
00818     r[1] = m.r[1];
00819     r[2] = m.r[2];
00820     r[3] = m.r[3];
00821 }
00822 
00823 
00824 template<class T> const Vector4<T>& Matrix4<T>::operator[](int n) const
00825 {
00826     return r[n];
00827     //    return const_cast<Vector4<T>&>(r[n]);
00828 }
00829 
00830 template<class T> Vector4<T> Matrix4<T>::row(int n) const
00831 {
00832     return r[n];
00833 }
00834 
00835 template<class T> Vector4<T> Matrix4<T>::column(int n) const
00836 {
00837     return Vector4<T>(r[0][n], r[1][n], r[2][n], r[3][n]);
00838 }
00839 
00840 
00841 template<class T> Matrix4<T> Matrix4<T>::identity()
00842 {
00843     return Matrix4<T>(Vector4<T>(1, 0, 0, 0),
00844                       Vector4<T>(0, 1, 0, 0),
00845                       Vector4<T>(0, 0, 1, 0),
00846                       Vector4<T>(0, 0, 0, 1));
00847 }
00848 
00849 
00850 template<class T> Matrix4<T> Matrix4<T>::translation(const Point3<T>& p)
00851 {
00852     return Matrix4<T>(Vector4<T>(1, 0, 0, 0),
00853                       Vector4<T>(0, 1, 0, 0),
00854                       Vector4<T>(0, 0, 1, 0),
00855                       Vector4<T>(p.x, p.y, p.z, 1));
00856 }
00857 
00858 
00859 template<class T> Matrix4<T> Matrix4<T>::translation(const Vector3<T>& v)
00860 {
00861     return Matrix4<T>(Vector4<T>(1, 0, 0, 0),
00862                       Vector4<T>(0, 1, 0, 0),
00863                       Vector4<T>(0, 0, 1, 0),
00864                       Vector4<T>(v.x, v.y, v.z, 1));
00865 }
00866 
00867 
00868 template<class T> void Matrix4<T>::translate(const Point3<T>& p)
00869 {
00870     r[3].x += p.x;
00871     r[3].y += p.y;
00872     r[3].z += p.z;
00873 }
00874 
00875 
00876 template<class T> Matrix4<T> Matrix4<T>::rotation(const Vector3<T>& axis,
00877                                                   T angle)
00878 {
00879     T c = (T) cos(angle);
00880     T s = (T) sin(angle);
00881     T t = 1 - c;
00882 
00883     return Matrix4<T>(Vector4<T>(t * axis.x * axis.x + c,
00884                                  t * axis.x * axis.y - s * axis.z,
00885                                  t * axis.x * axis.z + s * axis.y,
00886                                  0),
00887                       Vector4<T>(t * axis.x * axis.y + s * axis.z,
00888                                  t * axis.y * axis.y + c,
00889                                  t * axis.y * axis.z - s * axis.x,
00890                                  0),
00891                       Vector4<T>(t * axis.x * axis.z - s * axis.y,
00892                                  t * axis.y * axis.z + s * axis.x,
00893                                  t * axis.z * axis.z + c,
00894                                  0),
00895                       Vector4<T>(0, 0, 0, 1));
00896 }
00897 
00898 
00899 template<class T> Matrix4<T> Matrix4<T>::xrotation(T angle)
00900 {
00901     T c = (T) cos(angle);
00902     T s = (T) sin(angle);
00903 
00904     return Matrix4<T>(Vector4<T>(1, 0, 0, 0),
00905                       Vector4<T>(0, c, -s, 0),
00906                       Vector4<T>(0, s, c, 0),
00907                       Vector4<T>(0, 0, 0, 1));
00908 }
00909 
00910 
00911 template<class T> Matrix4<T> Matrix4<T>::yrotation(T angle)
00912 {
00913     T c = (T) cos(angle);
00914     T s = (T) sin(angle);
00915 
00916     return Matrix4<T>(Vector4<T>(c, 0, s, 0),
00917                       Vector4<T>(0, 1, 0, 0),
00918                       Vector4<T>(-s, 0, c, 0),
00919                       Vector4<T>(0, 0, 0, 1));
00920 }
00921 
00922 
00923 template<class T> Matrix4<T> Matrix4<T>::zrotation(T angle)
00924 {
00925     T c = (T) cos(angle);
00926     T s = (T) sin(angle);
00927 
00928     return Matrix4<T>(Vector4<T>(c, -s, 0, 0),
00929                       Vector4<T>(s, c, 0, 0),
00930                       Vector4<T>(0, 0, 1, 0),
00931                       Vector4<T>(0, 0, 0, 1));
00932 }
00933 
00934 
00935 template<class T> Matrix4<T> Matrix4<T>::scaling(const Vector3<T>& scale)
00936 {
00937     return Matrix4<T>(Vector4<T>(scale.x, 0, 0, 0),
00938                       Vector4<T>(0, scale.y, 0, 0),
00939                       Vector4<T>(0, 0, scale.z, 0),
00940                       Vector4<T>(0, 0, 0, 1));
00941 }
00942 
00943 
00944 template<class T> Matrix4<T> Matrix4<T>::scaling(T scale)
00945 {
00946     return scaling(Vector3<T>(scale, scale, scale));
00947 }
00948 
00949 
00950 // multiply column vector by a 4x4 matrix
00951 template<class T> Vector3<T> operator*(const Matrix4<T>& m, const Vector3<T>& v)
00952 {
00953     return Vector3<T>(m.r[0].x * v.x + m.r[0].y * v.y + m.r[0].z * v.z,
00954                       m.r[1].x * v.x + m.r[1].y * v.y + m.r[1].z * v.z,
00955                       m.r[2].x * v.x + m.r[2].y * v.y + m.r[2].z * v.z);
00956 }
00957 
00958 // multiply row vector by a 4x4 matrix
00959 template<class T> Vector3<T> operator*(const Vector3<T>& v, const Matrix4<T>& m)
00960 {
00961     return Vector3<T>(m.r[0].x * v.x + m.r[1].x * v.y + m.r[2].x * v.z,
00962                       m.r[0].y * v.x + m.r[1].y * v.y + m.r[2].y * v.z,
00963                       m.r[0].z * v.x + m.r[1].z * v.y + m.r[2].z * v.z);
00964 }
00965 
00966 // multiply column point by a 4x4 matrix; no projection is performed
00967 template<class T> Point3<T> operator*(const Matrix4<T>& m, const Point3<T>& p)
00968 {
00969     return Point3<T>(m.r[0].x * p.x + m.r[0].y * p.y + m.r[0].z * p.z + m.r[0].w,
00970                      m.r[1].x * p.x + m.r[1].y * p.y + m.r[1].z * p.z + m.r[1].w,
00971                      m.r[2].x * p.x + m.r[2].y * p.y + m.r[2].z * p.z + m.r[2].w);
00972 }
00973 
00974 // multiply row point by a 4x4 matrix; no projection is performed
00975 template<class T> Point3<T> operator*(const Point3<T>& p, const Matrix4<T>& m)
00976 {
00977     return Point3<T>(m.r[0].x * p.x + m.r[1].x * p.y + m.r[2].x * p.z + m.r[3].x,
00978                      m.r[0].y * p.x + m.r[1].y * p.y + m.r[2].y * p.z + m.r[3].y,
00979                      m.r[0].z * p.x + m.r[1].z * p.y + m.r[2].z * p.z + m.r[3].z);
00980 }
00981 
00982 // multiply column vector by a 4x4 matrix
00983 template<class T> Vector4<T> operator*(const Matrix4<T>& m, const Vector4<T>& v)
00984 {
00985     return Vector4<T>(m.r[0].x * v.x + m.r[0].y * v.y + m.r[0].z * v.z + m.r[0].w * v.w,
00986                       m.r[1].x * v.x + m.r[1].y * v.y + m.r[1].z * v.z + m.r[1].w * v.w,
00987                       m.r[2].x * v.x + m.r[2].y * v.y + m.r[2].z * v.z + m.r[2].w * v.w,
00988                       m.r[3].x * v.x + m.r[3].y * v.y + m.r[3].z * v.z + m.r[3].w * v.w);
00989 }
00990 
00991 // multiply row vector by a 4x4 matrix
00992 template<class T> Vector4<T> operator*(const Vector4<T>& v, const Matrix4<T>& m)
00993 {
00994     return Vector4<T>(m.r[0].x * v.x + m.r[1].x * v.y + m.r[2].x * v.z + m.r[3].x * v.w,
00995                       m.r[0].y * v.x + m.r[1].y * v.y + m.r[2].y * v.z + m.r[3].y * v.w,
00996                       m.r[0].z * v.x + m.r[1].z * v.y + m.r[2].z * v.z + m.r[3].z * v.w,
00997                       m.r[0].w * v.x + m.r[1].w * v.y + m.r[2].w * v.z + m.r[3].w * v.w);
00998 }
00999 
01000 
01001 
01002 template<class T> Matrix4<T> Matrix4<T>::transpose() const
01003 {
01004     return Matrix4<T>(Vector4<T>(r[0].x, r[1].x, r[2].x, r[3].x),
01005                       Vector4<T>(r[0].y, r[1].y, r[2].y, r[3].y),
01006                       Vector4<T>(r[0].z, r[1].z, r[2].z, r[3].z),
01007                       Vector4<T>(r[0].w, r[1].w, r[2].w, r[3].w));
01008 }
01009 
01010 
01011 template<class T> Matrix4<T> operator*(const Matrix4<T>& a,
01012                                        const Matrix4<T>& b)
01013 {
01014 #define MATMUL(R, C) (a[R].x * b[0].C + a[R].y * b[1].C + a[R].z * b[2].C + a[R].w * b[3].C)
01015     return Matrix4<T>(Vector4<T>(MATMUL(0, x), MATMUL(0, y), MATMUL(0, z), MATMUL(0, w)),
01016                       Vector4<T>(MATMUL(1, x), MATMUL(1, y), MATMUL(1, z), MATMUL(1, w)),
01017                       Vector4<T>(MATMUL(2, x), MATMUL(2, y), MATMUL(2, z), MATMUL(2, w)),
01018                       Vector4<T>(MATMUL(3, x), MATMUL(3, y), MATMUL(3, z), MATMUL(3, w)));
01019 #undef MATMUL
01020 }
01021 
01022 
01023 template<class T> Matrix4<T> operator+(const Matrix4<T>& a, const Matrix4<T>& b)
01024 {
01025     return Matrix4<T>(a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]);
01026 }
01027 
01028 
01029 // Compute inverse using Gauss-Jordan elimination; caller is responsible
01030 // for ensuring that the matrix isn't singular.
01031 template<class T> Matrix4<T> Matrix4<T>::inverse() const
01032 {
01033     Matrix4<T> a(*this);
01034     Matrix4<T> b(Matrix4<T>::identity());
01035     int i, j;
01036     int p;
01037 
01038     for (j = 0; j < 4; j++)
01039     {
01040         p = j;
01041         for (i = j + 1; i < 4; i++)
01042         {
01043             if (fabs(a.r[i][j]) > fabs(a.r[p][j]))
01044                 p = i;
01045         }
01046 
01047         // Swap rows p and j
01048         Vector4<T> t = a.r[p];
01049         a.r[p] = a.r[j];
01050         a.r[j] = t;
01051 
01052         t = b.r[p];
01053         b.r[p] = b.r[j];
01054         b.r[j] = t;
01055 
01056         T s = a.r[j][j];  // if s == 0, the matrix is singular
01057         a.r[j] *= (1.0f / s);
01058         b.r[j] *= (1.0f / s);
01059 
01060         // Eliminate off-diagonal elements
01061         for (i = 0; i < 4; i++)
01062         {
01063             if (i != j)
01064             {
01065                 b.r[i] -= a.r[i][j] * b.r[j];
01066                 a.r[i] -= a.r[i][j] * a.r[j];
01067             }
01068         }
01069     }
01070 
01071     return b;
01072 }
01073 
01074 
01075 #endif // _VECMATH_H_

Generated on Sat Jan 14 22:30:32 2006 for Celestia by  doxygen 1.4.1