Vector.hpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /*
  2. Copyright (c) 2009 Christopher A. Taylor. All rights reserved.
  3. Redistribution and use in source and binary forms, with or without
  4. modification, are permitted provided that the following conditions are met:
  5. * Redistributions of source code must retain the above copyright notice,
  6. this list of conditions and the following disclaimer.
  7. * Redistributions in binary form must reproduce the above copyright notice,
  8. this list of conditions and the following disclaimer in the documentation
  9. and/or other materials provided with the distribution.
  10. * Neither the name of LibCat nor the names of its contributors may be used
  11. to endorse or promote products derived from this software without
  12. specific prior written permission.
  13. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  14. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16. ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  17. LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  18. CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  19. SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20. INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  21. CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  22. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  23. POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #ifndef CAT_VECTOR_HPP
  26. #define CAT_VECTOR_HPP
  27. #include <cat/gfx/Scalar.hpp>
  28. namespace cat {
  29. #define FOR_EACH_DIMENSION(index) for (int index = 0; index < DIM; ++index)
  30. // Generic vector class for linear algebra
  31. template<int DIM, typename Scalar, typename Double> class Vector
  32. {
  33. protected:
  34. // Protected internal storage of vector components
  35. Scalar _elements[DIM];
  36. public:
  37. // Short-hand for the current vector type
  38. typedef Vector<DIM, Scalar, Double> mytype;
  39. // Uninitialized vector is not cleared
  40. Vector() {}
  41. // Component-wise initializing constructors
  42. Vector(Scalar x, Scalar y)
  43. {
  44. _elements[0] = x;
  45. _elements[1] = y;
  46. }
  47. Vector(Scalar x, Scalar y, Scalar z)
  48. {
  49. _elements[0] = x;
  50. _elements[1] = y;
  51. _elements[2] = z;
  52. }
  53. Vector(Scalar x, Scalar y, Scalar z, Scalar w)
  54. {
  55. _elements[0] = x;
  56. _elements[1] = y;
  57. _elements[2] = z;
  58. _elements[3] = w;
  59. }
  60. // Make the vector a copy of a given vector
  61. mytype &copy(const mytype &u)
  62. {
  63. memcpy(_elements, u._elements, sizeof(_elements));
  64. return *this;
  65. }
  66. // Copy constructor
  67. Vector(const mytype &u)
  68. {
  69. copy(u);
  70. }
  71. // Assignment operator
  72. mytype &operator=(const mytype &u)
  73. {
  74. return copy(u);
  75. }
  76. // Magnitude calculation
  77. Double magnitude() const
  78. {
  79. Double element, sum = 0;
  80. FOR_EACH_DIMENSION(ii)
  81. {
  82. element = _elements[ii];
  83. sum += element * element;
  84. }
  85. return static_cast<Double>( sqrt(sum) );
  86. }
  87. // Fast normalization for 32-bit floating point elements in-place
  88. mytype &normalize_fast_f32()
  89. {
  90. f32 element = _elements[0];
  91. f32 sum = element * element;
  92. for (int ii = 1; ii < DIM; ++ii)
  93. {
  94. element = _elements[ii];
  95. sum += element * element;
  96. }
  97. // If sum is not close to 1, then perform normalization:
  98. if (sum > 1.005f || sum < 0.995f)
  99. {
  100. f32 inv = InvSqrt(sum);
  101. FOR_EACH_DIMENSION(ii) _elements[ii] *= inv;
  102. }
  103. return *this;
  104. }
  105. // Normalization in-place
  106. mytype &normalize()
  107. {
  108. Double m = magnitude();
  109. Double inv = static_cast<Double>( 1 ) / m;
  110. FOR_EACH_DIMENSION(ii) _elements[ii] *= inv;
  111. return *this;
  112. }
  113. // Zero elements
  114. void zero()
  115. {
  116. OBJCLR(_elements);
  117. }
  118. // Is zero?
  119. bool isZero()
  120. {
  121. FOR_EACH_DIMENSION(ii)
  122. if (_elements[ii] != static_cast<Scalar>( 0 ))
  123. return false;
  124. return true;
  125. }
  126. // For consistency with Matrix class, use the () operator instead of [] to index it
  127. inline Scalar &operator()(int ii) { return _elements[ii]; }
  128. inline Scalar &x() { return _elements[0]; }
  129. inline Scalar &y() { return _elements[1]; }
  130. inline Scalar &z() { return _elements[2]; }
  131. inline Scalar &w() { return _elements[3]; }
  132. // Const version for accessors
  133. inline const Scalar &operator()(int ii) const { return _elements[ii]; }
  134. inline const Scalar &x() const { return _elements[0]; }
  135. inline const Scalar &y() const { return _elements[1]; }
  136. inline const Scalar &z() const { return _elements[2]; }
  137. inline const Scalar &w() const { return _elements[3]; }
  138. // Negation
  139. mytype operator-() const
  140. {
  141. mytype x;
  142. FOR_EACH_DIMENSION(ii) x._elements[ii] = -_elements[ii];
  143. return x;
  144. }
  145. // Negation in-place
  146. mytype &negate()
  147. {
  148. FOR_EACH_DIMENSION(ii) _elements[ii] = -_elements[ii];
  149. return *this;
  150. }
  151. // Addition
  152. mytype operator+(const mytype &u) const
  153. {
  154. mytype x;
  155. FOR_EACH_DIMENSION(ii) x._elements[ii] = _elements[ii] + u._elements[ii];
  156. return x;
  157. }
  158. // Addition in-place
  159. mytype &operator+=(const mytype &u)
  160. {
  161. FOR_EACH_DIMENSION(ii) _elements[ii] += u._elements[ii];
  162. return *this;
  163. }
  164. // Add a scalar to each element in-place
  165. mytype &addToEachElement(Scalar u)
  166. {
  167. FOR_EACH_DIMENSION(ii) _elements[ii] += u;
  168. return *this;
  169. }
  170. // Subtraction
  171. mytype operator-(const mytype &u) const
  172. {
  173. mytype x;
  174. FOR_EACH_DIMENSION(ii) x._elements[ii] = _elements[ii] - u._elements[ii];
  175. return x;
  176. }
  177. // Subtraction in-place
  178. mytype &operator-=(const mytype &u)
  179. {
  180. FOR_EACH_DIMENSION(ii) _elements[ii] -= u._elements[ii];
  181. return *this;
  182. }
  183. // Subtract a scalar from each element in-place
  184. mytype &subtractFromEachElement(Scalar u)
  185. {
  186. FOR_EACH_DIMENSION(ii) _elements[ii] -= u;
  187. return *this;
  188. }
  189. // Scalar multiplication
  190. mytype operator*(Scalar u) const
  191. {
  192. mytype x;
  193. FOR_EACH_DIMENSION(ii) x._elements[ii] = u * _elements[ii];
  194. return x;
  195. }
  196. // Scalar multiplication in-place
  197. mytype &operator*=(Scalar u)
  198. {
  199. FOR_EACH_DIMENSION(ii) _elements[ii] *= u;
  200. return *this;
  201. }
  202. // Component-wise multiply in-place
  203. mytype &componentMultiply(const mytype &u)
  204. {
  205. FOR_EACH_DIMENSION(ii) _elements[ii] *= u._elements[ii];
  206. return *this;
  207. }
  208. // Scalar division
  209. mytype operator/(Scalar u) const
  210. {
  211. mytype x;
  212. Scalar inv_u = static_cast<Scalar>( 1 ) / static_cast<Scalar>( u );
  213. FOR_EACH_DIMENSION(ii) x._elements[ii] = _elements[ii] * inv_u;
  214. return x;
  215. }
  216. // Scalar division in-place
  217. mytype &operator/=(Scalar u)
  218. {
  219. Scalar inv_u = static_cast<Scalar>( 1 ) / static_cast<Scalar>( u );
  220. FOR_EACH_DIMENSION(ii) _elements[ii] *= inv_u;
  221. return *this;
  222. }
  223. // Component-wise divide in-place
  224. mytype &componentDivide(const mytype &u)
  225. {
  226. FOR_EACH_DIMENSION(ii) _elements[ii] /= u._elements[ii];
  227. return *this;
  228. }
  229. // Dot product
  230. Double dotProduct(const mytype &u) const
  231. {
  232. Double sum = 0;
  233. FOR_EACH_DIMENSION(ii)
  234. sum += static_cast<Double>( _elements[ii] )
  235. * static_cast<Double>( u._elements[ii] );
  236. return sum;
  237. }
  238. public:
  239. // Only for 2-element vectors:
  240. // Generate a 2D rotation vector in-place
  241. void generateRotation2D(f32 angle)
  242. {
  243. x() = cos(angle);
  244. y() = sin(angle);
  245. }
  246. // Add rotation vector in-place
  247. mytype &addRotation2D(const mytype &r)
  248. {
  249. Double ax = x(), ay = y();
  250. Double rx = r.x(), ry = r.y();
  251. x() = static_cast<Scalar>( ax*rx - ay*ry ); // cos(a+r) = cos(a)*cos(r) - sin(a)*sin(r)
  252. y() = static_cast<Scalar>( ay*rx + ax*ry ); // sin(a+r) = sin(a)*cos(r) + cos(a)*sin(r)
  253. return *this;
  254. }
  255. // Subtract rotation vector in-place
  256. mytype &subtractRotation2D(const mytype &r)
  257. {
  258. Double ax = x(), ay = y();
  259. Double rx = r.x(), ry = r.y();
  260. x() = static_cast<Scalar>( ax*rx + ay*ry ); // cos(a-r) = cos(a)*cos(r) + sin(a)*sin(r)
  261. y() = static_cast<Scalar>( ay*rx - ax*ry ); // sin(a-r) = sin(a)*cos(r) - cos(a)*sin(r)
  262. return *this;
  263. }
  264. // Cross product: Result is a scalar
  265. f32 crossProduct2D(const mytype &u)
  266. {
  267. return x() * u.y() - y() * u.x();
  268. }
  269. public:
  270. // Only for 3-element vectors:
  271. // Cross product: Result is a 3D vector
  272. mytype crossProduct3D(const mytype &u)
  273. {
  274. mytype result;
  275. result.x() = y() * u.z() - z() * u.y();
  276. result.y() = z() * u.x() - x() * u.z();
  277. result.z() = x() * u.y() - y() * u.x();
  278. return result;
  279. }
  280. };
  281. // Short-hand for common usages:
  282. typedef Vector<2, u32, u32> Vector2u;
  283. typedef Vector<3, u32, u32> Vector3u;
  284. typedef Vector<4, u32, u32> Vector4u;
  285. typedef Vector<2, s32, s32> Vector2s;
  286. typedef Vector<3, s32, s32> Vector3s;
  287. typedef Vector<4, s32, s32> Vector4s;
  288. typedef Vector<2, f32, f64> Vector2f;
  289. typedef Vector<3, f32, f64> Vector3f;
  290. typedef Vector<4, f32, f64> Vector4f;
  291. typedef Vector<2, f64, f64> Vector2d;
  292. typedef Vector<3, f64, f64> Vector3d;
  293. typedef Vector<4, f64, f64> Vector4d;
  294. #undef FOR_EACH_DIMENSION
  295. } // namespace cat
  296. #endif // CAT_VECTOR_HPP
粤ICP备19079148号