Shadowrun: Awakened 29 September 2011 - Build 871
Vector.hpp
Go to the documentation of this file.
00001 /*
00002     Copyright (c) 2009 Christopher A. Taylor.  All rights reserved.
00003 
00004     Redistribution and use in source and binary forms, with or without
00005     modification, are permitted provided that the following conditions are met:
00006 
00007     * Redistributions of source code must retain the above copyright notice,
00008       this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice,
00010       this list of conditions and the following disclaimer in the documentation
00011       and/or other materials provided with the distribution.
00012     * Neither the name of LibCat nor the names of its contributors may be used
00013       to endorse or promote products derived from this software without
00014       specific prior written permission.
00015 
00016     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00019     ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00020     LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00021     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00022     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00023     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00024     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00025     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00026     POSSIBILITY OF SUCH DAMAGE.
00027 */
00028 
00029 #ifndef CAT_VECTOR_HPP
00030 #define CAT_VECTOR_HPP
00031 
00032 #include <cat/gfx/Scalar.hpp>
00033 
00034 namespace cat {
00035 
00036 #define FOR_EACH_DIMENSION(index) for (int index = 0; index < DIM; ++index)
00037 
00038 
00039 // Generic vector class for linear algebra
00040 template<int DIM, typename Scalar, typename Double> class Vector
00041 {
00042 protected:
00043     // Protected internal storage of vector components
00044     Scalar _elements[DIM];
00045 
00046 public:
00047     // Short-hand for the current vector type
00048     typedef Vector<DIM, Scalar, Double> mytype;
00049 
00050     // Uninitialized vector is not cleared
00051     Vector() {}
00052 
00053     // Component-wise initializing constructors
00054     Vector(Scalar x, Scalar y)
00055     {
00056         _elements[0] = x;
00057         _elements[1] = y;
00058     }
00059     Vector(Scalar x, Scalar y, Scalar z)
00060     {
00061         _elements[0] = x;
00062         _elements[1] = y;
00063         _elements[2] = z;
00064     }
00065     Vector(Scalar x, Scalar y, Scalar z, Scalar w)
00066     {
00067         _elements[0] = x;
00068         _elements[1] = y;
00069         _elements[2] = z;
00070         _elements[3] = w;
00071     }
00072 
00073     // Make the vector a copy of a given vector
00074     mytype &copy(const mytype &u)
00075     {
00076         memcpy(_elements, u._elements, sizeof(_elements));
00077 
00078         return *this;
00079     }
00080 
00081     // Copy constructor
00082     Vector(const mytype &u)
00083     {
00084         copy(u);
00085     }
00086 
00087     // Assignment operator
00088     mytype &operator=(const mytype &u)
00089     {
00090         return copy(u);
00091     }
00092 
00093     // Magnitude calculation
00094     Double magnitude() const
00095     {
00096         Double element, sum = 0;
00097 
00098         FOR_EACH_DIMENSION(ii)
00099         {
00100             element = _elements[ii];
00101             sum += element * element;
00102         }
00103 
00104         return static_cast<Double>( sqrt(sum) );
00105     }
00106 
00107     // Fast normalization for 32-bit floating point elements in-place
00108     mytype &normalize_fast_f32()
00109     {
00110         f32 element = _elements[0];
00111         f32 sum = element * element;
00112 
00113         for (int ii = 1; ii < DIM; ++ii)
00114         {
00115             element = _elements[ii];
00116             sum += element * element;
00117         }
00118 
00119         // If sum is not close to 1, then perform normalization:
00120         if (sum > 1.005f || sum < 0.995f)
00121         {
00122             f32 inv = InvSqrt(sum);
00123 
00124             FOR_EACH_DIMENSION(ii) _elements[ii] *= inv;
00125         }
00126 
00127         return *this;
00128     }
00129 
00130     // Normalization in-place
00131     mytype &normalize()
00132     {
00133         Double m = magnitude();
00134         Double inv = static_cast<Double>( 1 ) / m;
00135 
00136         FOR_EACH_DIMENSION(ii) _elements[ii] *= inv;
00137 
00138         return *this;
00139     }
00140 
00141     // Zero elements
00142     void zero()
00143     {
00144         OBJCLR(_elements);
00145     }
00146 
00147     // Is zero?
00148     bool isZero()
00149     {
00150         FOR_EACH_DIMENSION(ii)
00151             if (_elements[ii] != static_cast<Scalar>( 0 ))
00152                 return false;
00153 
00154         return true;
00155     }
00156 
00157     // For consistency with Matrix class, use the () operator instead of [] to index it
00158     inline Scalar &operator()(int ii) { return _elements[ii]; }
00159     inline Scalar &x() { return _elements[0]; }
00160     inline Scalar &y() { return _elements[1]; }
00161     inline Scalar &z() { return _elements[2]; }
00162     inline Scalar &w() { return _elements[3]; }
00163 
00164     // Const version for accessors
00165     inline const Scalar &operator()(int ii) const { return _elements[ii]; }
00166     inline const Scalar &x() const { return _elements[0]; }
00167     inline const Scalar &y() const { return _elements[1]; }
00168     inline const Scalar &z() const { return _elements[2]; }
00169     inline const Scalar &w() const { return _elements[3]; }
00170 
00171     // Negation
00172     mytype operator-() const
00173     {
00174         mytype x;
00175 
00176         FOR_EACH_DIMENSION(ii) x._elements[ii] = -_elements[ii];
00177 
00178         return x;
00179     }
00180 
00181     // Negation in-place
00182     mytype &negate()
00183     {
00184         FOR_EACH_DIMENSION(ii) _elements[ii] = -_elements[ii];
00185 
00186         return *this;
00187     }
00188 
00189     // Addition
00190     mytype operator+(const mytype &u) const
00191     {
00192         mytype x;
00193 
00194         FOR_EACH_DIMENSION(ii) x._elements[ii] = _elements[ii] + u._elements[ii];
00195 
00196         return x;
00197     }
00198 
00199     // Addition in-place
00200     mytype &operator+=(const mytype &u)
00201     {
00202         FOR_EACH_DIMENSION(ii) _elements[ii] += u._elements[ii];
00203 
00204         return *this;
00205     }
00206 
00207     // Add a scalar to each element in-place
00208     mytype &addToEachElement(Scalar u)
00209     {
00210         FOR_EACH_DIMENSION(ii) _elements[ii] += u;
00211 
00212         return *this;
00213     }
00214 
00215     // Subtraction
00216     mytype operator-(const mytype &u) const
00217     {
00218         mytype x;
00219 
00220         FOR_EACH_DIMENSION(ii) x._elements[ii] = _elements[ii] - u._elements[ii];
00221 
00222         return x;
00223     }
00224 
00225     // Subtraction in-place
00226     mytype &operator-=(const mytype &u)
00227     {
00228         FOR_EACH_DIMENSION(ii) _elements[ii] -= u._elements[ii];
00229 
00230         return *this;
00231     }
00232 
00233     // Subtract a scalar from each element in-place
00234     mytype &subtractFromEachElement(Scalar u)
00235     {
00236         FOR_EACH_DIMENSION(ii) _elements[ii] -= u;
00237 
00238         return *this;
00239     }
00240 
00241     // Scalar multiplication
00242     mytype operator*(Scalar u) const
00243     {
00244         mytype x;
00245 
00246         FOR_EACH_DIMENSION(ii) x._elements[ii] = u * _elements[ii];
00247 
00248         return x;
00249     }
00250 
00251     // Scalar multiplication in-place
00252     mytype &operator*=(Scalar u)
00253     {
00254         FOR_EACH_DIMENSION(ii) _elements[ii] *= u;
00255 
00256         return *this;
00257     }
00258 
00259     // Component-wise multiply in-place
00260     mytype &componentMultiply(const mytype &u)
00261     {
00262         FOR_EACH_DIMENSION(ii) _elements[ii] *= u._elements[ii];
00263 
00264         return *this;
00265     }
00266 
00267     // Scalar division
00268     mytype operator/(Scalar u) const
00269     {
00270         mytype x;
00271 
00272         Scalar inv_u = static_cast<Scalar>( 1 ) / static_cast<Scalar>( u );
00273 
00274         FOR_EACH_DIMENSION(ii) x._elements[ii] = _elements[ii] * inv_u;
00275 
00276         return x;
00277     }
00278 
00279     // Scalar division in-place
00280     mytype &operator/=(Scalar u)
00281     {
00282         Scalar inv_u = static_cast<Scalar>( 1 ) / static_cast<Scalar>( u );
00283 
00284         FOR_EACH_DIMENSION(ii) _elements[ii] *= inv_u;
00285 
00286         return *this;
00287     }
00288 
00289     // Component-wise divide in-place
00290     mytype &componentDivide(const mytype &u)
00291     {
00292         FOR_EACH_DIMENSION(ii) _elements[ii] /= u._elements[ii];
00293 
00294         return *this;
00295     }
00296 
00297     // Dot product
00298     Double dotProduct(const mytype &u) const
00299     {
00300         Double sum = 0;
00301 
00302         FOR_EACH_DIMENSION(ii)
00303             sum += static_cast<Double>( _elements[ii] )
00304                 * static_cast<Double>( u._elements[ii] );
00305 
00306         return sum;
00307     }
00308 
00309 public:
00310     // Only for 2-element vectors:
00311 
00312     // Generate a 2D rotation vector in-place
00313     void generateRotation2D(f32 angle)
00314     {
00315         x() = cos(angle);
00316         y() = sin(angle);
00317     }
00318 
00319     // Add rotation vector in-place
00320     mytype &addRotation2D(const mytype &r)
00321     {
00322         Double ax = x(), ay = y();
00323         Double rx = r.x(), ry = r.y();
00324 
00325         x() = static_cast<Scalar>( ax*rx - ay*ry ); // cos(a+r) = cos(a)*cos(r) - sin(a)*sin(r)
00326         y() = static_cast<Scalar>( ay*rx + ax*ry ); // sin(a+r) = sin(a)*cos(r) + cos(a)*sin(r)
00327 
00328         return *this;
00329     }
00330 
00331     // Subtract rotation vector in-place
00332     mytype &subtractRotation2D(const mytype &r)
00333     {
00334         Double ax = x(), ay = y();
00335         Double rx = r.x(), ry = r.y();
00336 
00337         x() = static_cast<Scalar>( ax*rx + ay*ry ); // cos(a-r) = cos(a)*cos(r) + sin(a)*sin(r)
00338         y() = static_cast<Scalar>( ay*rx - ax*ry ); // sin(a-r) = sin(a)*cos(r) - cos(a)*sin(r)
00339 
00340         return *this;
00341     }
00342 
00343     // Cross product: Result is a scalar
00344     f32 crossProduct2D(const mytype &u)
00345     {
00346         return x() * u.y() - y() * u.x();
00347     }
00348 
00349 public:
00350     // Only for 3-element vectors:
00351 
00352     // Cross product: Result is a 3D vector
00353     mytype crossProduct3D(const mytype &u)
00354     {
00355         mytype result;
00356 
00357         result.x() = y() * u.z() - z() * u.y();
00358         result.y() = z() * u.x() - x() * u.z();
00359         result.z() = x() * u.y() - y() * u.x();
00360 
00361         return result;
00362     }
00363 };
00364 
00365 
00366 // Short-hand for common usages:
00367 
00368 typedef Vector<2, u32, u32> Vector2u;
00369 typedef Vector<3, u32, u32> Vector3u;
00370 typedef Vector<4, u32, u32> Vector4u;
00371 
00372 typedef Vector<2, s32, s32> Vector2s;
00373 typedef Vector<3, s32, s32> Vector3s;
00374 typedef Vector<4, s32, s32> Vector4s;
00375 
00376 typedef Vector<2, f32, f64> Vector2f;
00377 typedef Vector<3, f32, f64> Vector3f;
00378 typedef Vector<4, f32, f64> Vector4f;
00379 
00380 typedef Vector<2, f64, f64> Vector2d;
00381 typedef Vector<3, f64, f64> Vector3d;
00382 typedef Vector<4, f64, f64> Vector4d;
00383 
00384 
00385 #undef FOR_EACH_DIMENSION
00386 
00387 } // namespace cat
00388 
00389 #endif // CAT_VECTOR_HPP

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net