![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
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 ©(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.