/xbmc/screensavers/rsxs-0.9/src/vector.hh

http://github.com/xbmc/xbmc · C++ Header · 797 lines · 668 code · 101 blank · 28 comment · 19 complexity · da00a397ca2381f701e962ae1b9fcf17 MD5 · raw file

  1. /*
  2. * Really Slick XScreenSavers
  3. * Copyright (C) 2002-2006 Michael Chapman
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  17. *
  18. *****************************************************************************
  19. *
  20. * This is a Linux port of the Really Slick Screensavers,
  21. * Copyright (C) 2002 Terence M. Welsh, available from www.reallyslick.com
  22. */
  23. #ifndef _VECTOR_HH
  24. #define _VECTOR_HH
  25. #include <common.hh>
  26. #define R2D (180.0f / M_PI)
  27. #define D2R (M_PI / 180.0f)
  28. template <typename T>
  29. class VectorBase {
  30. protected:
  31. T _v[3];
  32. public:
  33. VectorBase(const T* v) {
  34. set(v[0], v[1], v[2]);
  35. }
  36. VectorBase(const T& x, const T& y, const T& z) {
  37. set(x, y, z);
  38. }
  39. void set(const T& x, const T& y, const T& z) {
  40. _v[0] = x;
  41. _v[1] = y;
  42. _v[2] = z;
  43. }
  44. const T& x() const { return _v[0]; }
  45. T& x() { return _v[0]; }
  46. const T& y() const { return _v[1]; }
  47. T& y() { return _v[1]; }
  48. const T& z() const { return _v[2]; }
  49. T& z() { return _v[2]; }
  50. const T* get() const {
  51. return _v;
  52. }
  53. T lengthSquared() const {
  54. return _v[0] * _v[0] + _v[1] * _v[1] + _v[2] * _v[2];
  55. }
  56. };
  57. class Vector : public VectorBase<float> {
  58. public:
  59. Vector(const float* v) : VectorBase<float>(v) {}
  60. Vector(float x = 0.0f, float y = 0.0f, float z = 0.0f)
  61. : VectorBase<float>(x, y, z) {}
  62. float length() const {
  63. return std::sqrt(lengthSquared());
  64. }
  65. float normalize() {
  66. float l = length();
  67. if (l == 0.0f)
  68. return 0.0f;
  69. _v[0] /= l;
  70. _v[1] /= l;
  71. _v[2] /= l;
  72. return l;
  73. }
  74. Vector operator+(const Vector& v) const {
  75. return Vector(_v[0] + v._v[0], _v[1] + v._v[1], _v[2] + v._v[2]);
  76. }
  77. Vector operator-(const Vector& v) const {
  78. return Vector(_v[0] - v._v[0], _v[1] - v._v[1], _v[2] - v._v[2]);
  79. }
  80. Vector operator*(float f) const {
  81. return Vector(_v[0] * f, _v[1] * f, _v[2] * f);
  82. }
  83. Vector operator/(float f) const {
  84. return Vector(_v[0] / f, _v[1] / f, _v[2] / f);
  85. }
  86. Vector& operator+=(const Vector& v) {
  87. _v[0] += v._v[0];
  88. _v[1] += v._v[1];
  89. _v[2] += v._v[2];
  90. return *this;
  91. }
  92. Vector& operator-=(const Vector& v) {
  93. _v[0] -= v._v[0];
  94. _v[1] -= v._v[1];
  95. _v[2] -= v._v[2];
  96. return *this;
  97. }
  98. Vector& operator*=(float f) {
  99. _v[0] *= f;
  100. _v[1] *= f;
  101. _v[2] *= f;
  102. return *this;
  103. }
  104. Vector& operator/=(float f) {
  105. _v[0] /= f;
  106. _v[1] /= f;
  107. _v[2] /= f;
  108. return *this;
  109. }
  110. static float dot(const Vector& a, const Vector& b) {
  111. return a.x() * b.x() + a.y() * b.y() + a.z() * b.z();
  112. }
  113. static Vector cross(const Vector& a, const Vector& b) {
  114. return Vector(
  115. a.y() * b.z() - b.y() * a.z(),
  116. a.z() * b.x() - b.z() * a.x(),
  117. a.x() * b.y() - b.x() * a.y()
  118. );
  119. };
  120. };
  121. class UVector : public VectorBase<unsigned int> {
  122. public:
  123. UVector(const unsigned int* v) : VectorBase<unsigned int>(v) {}
  124. UVector(unsigned int x = 0, unsigned int y = 0, unsigned int z = 0)
  125. : VectorBase<unsigned int>(x, y, z) {}
  126. UVector operator+(const UVector& v) const {
  127. return UVector(_v[0] + v._v[0], _v[1] + v._v[1], _v[2] + v._v[2]);
  128. }
  129. UVector operator-(const UVector& v) const {
  130. return UVector(_v[0] - v._v[0], _v[1] - v._v[1], _v[2] - v._v[2]);
  131. }
  132. UVector& operator+=(const UVector& v) {
  133. _v[0] += v._v[0];
  134. _v[1] += v._v[1];
  135. _v[2] += v._v[2];
  136. return *this;
  137. }
  138. UVector& operator-=(const UVector& v) {
  139. _v[0] -= v._v[0];
  140. _v[1] -= v._v[1];
  141. _v[2] -= v._v[2];
  142. return *this;
  143. }
  144. };
  145. class UnitVector : public Vector {
  146. protected:
  147. using Vector::set;
  148. using Vector::length;
  149. using Vector::lengthSquared;
  150. using Vector::normalize;
  151. UnitVector(const float* v) {
  152. set(v[0], v[1], v[2]);
  153. }
  154. UnitVector(float x, float y, float z) {
  155. set(x, y, z);
  156. }
  157. friend class Vector;
  158. friend class RotationMatrix;
  159. friend class UnitQuat;
  160. public:
  161. UnitVector(const Vector& v) {
  162. float l = v.length();
  163. if (l == 0.0f)
  164. set(1.0f, 0.0f, 0.0f);
  165. else
  166. set(v.x() / l, v.y() / l, v.z() / l);
  167. }
  168. UnitVector() {
  169. set(1.0f, 0.0f, 0.0f);
  170. }
  171. static UnitVector of(const Vector& v) {
  172. float l = v.length();
  173. if (l == 0.0f)
  174. return UnitVector();
  175. return UnitVector(
  176. v.x() / l,
  177. v.y() / l,
  178. v.z() / l
  179. );
  180. }
  181. };
  182. class Matrix {
  183. protected:
  184. float _m[16];
  185. public:
  186. Matrix(
  187. float m0 = 1.0f, float m1 = 0.0f, float m2 = 0.0f, float m3 = 0.0f,
  188. float m4 = 0.0f, float m5 = 1.0f, float m6 = 0.0f, float m7 = 0.0f,
  189. float m8 = 0.0f, float m9 = 0.0f, float m10 = 1.0f, float m11 = 0.0f,
  190. float m12 = 0.0f, float m13 = 0.0f, float m14 = 0.0f, float m15 = 1.0f
  191. ) {
  192. _m[0] = m0; _m[1] = m1; _m[2] = m2; _m[3] = m3;
  193. _m[4] = m4; _m[5] = m5; _m[6] = m6; _m[7] = m7;
  194. _m[8] = m8; _m[9] = m9; _m[10] = m10; _m[11] = m11;
  195. _m[12] = m12; _m[13] = m13; _m[14] = m14; _m[15] = m15;
  196. }
  197. float get(int i) const {
  198. return _m[i];
  199. }
  200. const float* get() const {
  201. return _m;
  202. }
  203. Matrix transposed() const {
  204. return Matrix(
  205. _m[0], _m[4], _m[8], _m[12],
  206. _m[1], _m[5], _m[9], _m[13],
  207. _m[2], _m[6], _m[10], _m[14],
  208. _m[3], _m[7], _m[11], _m[15]
  209. );
  210. }
  211. Vector transform(const Vector& v) const {
  212. float w = _m[3] * v.x() + _m[7] * v.y() + _m[11] * v.z() + _m[15];
  213. return Vector(
  214. (_m[0] * v.x() + _m[4] * v.y() + _m[8] * v.z() + _m[12]) / w,
  215. (_m[1] * v.x() + _m[5] * v.y() + _m[9] * v.z() + _m[13]) / w,
  216. (_m[2] * v.x() + _m[6] * v.y() + _m[10] * v.z() + _m[14]) / w
  217. );
  218. }
  219. Matrix operator*(const Matrix& m) const {
  220. return Matrix(
  221. _m[0] * m._m[0] + _m[1] * m._m[4] +
  222. _m[2] * m._m[8] + _m[3] * m._m[12],
  223. _m[0] * m._m[1] + _m[1] * m._m[5] +
  224. _m[2] * m._m[9] + _m[3] * m._m[13],
  225. _m[0] * m._m[2] + _m[1] * m._m[6] +
  226. _m[2] * m._m[10] + _m[3] * m._m[14],
  227. _m[0] * m._m[3] + _m[1] * m._m[7] +
  228. _m[2] * m._m[11] + _m[3] * m._m[15]
  229. ,
  230. _m[4] * m._m[0] + _m[5] * m._m[4] +
  231. _m[6] * m._m[8] + _m[7] * m._m[12],
  232. _m[4] * m._m[1] + _m[5] * m._m[5] +
  233. _m[6] * m._m[9] + _m[7] * m._m[13],
  234. _m[4] * m._m[2] + _m[5] * m._m[6] +
  235. _m[6] * m._m[10] + _m[7] * m._m[14],
  236. _m[4] * m._m[3] + _m[5] * m._m[7] +
  237. _m[6] * m._m[11] + _m[7] * m._m[15]
  238. ,
  239. _m[8] * m._m[0] + _m[9] * m._m[4] +
  240. _m[10] * m._m[8] + _m[11] * m._m[12],
  241. _m[8] * m._m[1] + _m[9] * m._m[5] +
  242. _m[10] * m._m[9] + _m[11] * m._m[13],
  243. _m[8] * m._m[2] + _m[9] * m._m[6] +
  244. _m[10] * m._m[10] + _m[11] * m._m[14],
  245. _m[8] * m._m[3] + _m[9] * m._m[7] +
  246. _m[10] * m._m[11] + _m[11] * m._m[15]
  247. ,
  248. _m[12] * m._m[0] + _m[13] * m._m[4] +
  249. _m[14] * m._m[8] + _m[15] * m._m[12],
  250. _m[12] * m._m[1] + _m[13] * m._m[5] +
  251. _m[14] * m._m[9] + _m[15] * m._m[13],
  252. _m[12] * m._m[2] + _m[13] * m._m[6] +
  253. _m[14] * m._m[10] + _m[15] * m._m[14],
  254. _m[12] * m._m[3] + _m[13] * m._m[7] +
  255. _m[14] * m._m[11] + _m[15] * m._m[15]
  256. );
  257. }
  258. };
  259. class TranslationMatrix : public Matrix {
  260. protected:
  261. float _dx, _dy, _dz;
  262. public:
  263. TranslationMatrix(float dx = 0.0f, float dy = 0.0f, float dz = 0.0f) :
  264. Matrix(
  265. 1.0f, 0.0f, 0.0f, 0.0f,
  266. 0.0f, 1.0f, 0.0f, 0.0f,
  267. 0.0f, 0.0f, 1.0f, 0.0f,
  268. dz, dy, dz, 1.0f
  269. ), _dx(dx), _dy(dy), _dz(dz) {}
  270. TranslationMatrix inverted() const {
  271. return TranslationMatrix(-_dx, -_dy, -_dz);
  272. }
  273. Vector transform(const Vector& v) const {
  274. return v + Vector(_dx, _dy, _dz);
  275. }
  276. TranslationMatrix operator*(const TranslationMatrix& m) const {
  277. return TranslationMatrix(_dx + m._dx, _dy + m._dy, _dz + m._dz);
  278. }
  279. };
  280. class ScalingMatrix : public Matrix {
  281. protected:
  282. float _sx, _sy, _sz;
  283. public:
  284. ScalingMatrix(float sx = 0.0f, float sy = 0.0f, float sz = 0.0f) :
  285. Matrix(
  286. sx, 0.0f, 0.0f, 0.0f,
  287. 0.0f, sy, 0.0f, 0.0f,
  288. 0.0f, 0.0f, sz, 0.0f,
  289. 0.0f, 0.0f, 0.0f, 1.0f
  290. ), _sx(sx), _sy(sy), _sz(sz) {}
  291. ScalingMatrix inverted() const {
  292. return ScalingMatrix(-_sx, -_sy, -_sz);
  293. }
  294. ScalingMatrix transposed() const {
  295. return ScalingMatrix(*this);
  296. }
  297. Vector transform(const Vector& v) const {
  298. return Vector(_sx * v.x(), _sy * v.y(), _sz * v.z());
  299. }
  300. ScalingMatrix operator*(const ScalingMatrix& m) const {
  301. return ScalingMatrix(_sx + m._sx, _sy + m._sy, _sz + m._sz);
  302. }
  303. };
  304. class ShearingMatrix : public Matrix {
  305. protected:
  306. float _sxy, _sxz, _syx, _syz, _szx, _szy;
  307. public:
  308. ShearingMatrix(
  309. float sxy = 0.0f, float sxz = 0.0f,
  310. float syx = 0.0f, float syz = 0.0f,
  311. float szx = 0.0f, float szy = 0.0f
  312. ) :
  313. Matrix(
  314. 1.0f, sxy, sxz, 0.0f,
  315. syx, 1.0f, syz, 0.0f,
  316. szx, szy, 1.0f, 0.0f,
  317. 0.0f, 0.0f, 0.0f, 1.0f
  318. ),
  319. _sxy(sxy), _sxz(sxz), _syx(syx),
  320. _syz(syz), _szx(szx), _szy(szy) {}
  321. ShearingMatrix transposed() const {
  322. return ShearingMatrix(_syx, _szx, _sxy, _szy, _sxz, _syz);
  323. }
  324. Vector transform(const Vector& v) const {
  325. return Vector(
  326. v.x() + _syx * v.y() + _szx * v.z(),
  327. v.y() + _sxy * v.x() + _szy * v.z(),
  328. v.z() + _sxz * v.x() + _syz * v.y()
  329. );
  330. }
  331. };
  332. class RotationMatrix : public Matrix {
  333. protected:
  334. RotationMatrix(
  335. float m0, float m1, float m2,
  336. float m4, float m5, float m6,
  337. float m8, float m9, float m10
  338. ) : Matrix(
  339. m0, m1, m2, 0.0f,
  340. m4, m5, m6, 0.0f,
  341. m8, m9, m10, 0.0f,
  342. 0.0f, 0.0f, 0.0f, 1.0f
  343. ) {}
  344. RotationMatrix(const Vector& x, const Vector& y, const Vector& z) :
  345. Matrix(
  346. x.x(), x.y(), x.z(), 0.0f,
  347. y.x(), y.y(), y.z(), 0.0f,
  348. z.x(), z.y(), z.z(), 0.0f,
  349. 0.0f, 0.0f, 0.0f, 1.0f
  350. ) {}
  351. friend class UnitQuat;
  352. public:
  353. RotationMatrix() :
  354. Matrix(
  355. 1.0f, 0.0f, 0.0f, 0.0f,
  356. 0.0f, 1.0f, 0.0f, 0.0f,
  357. 0.0f, 0.0f, 1.0f, 0.0f,
  358. 0.0f, 0.0f, 0.0f, 1.0f
  359. ) {}
  360. // Emulate gluLookAt
  361. static RotationMatrix lookAt(
  362. const Vector& eye, const Vector& center, const Vector& up
  363. ) {
  364. Vector f(eye - center);
  365. f.normalize();
  366. Vector x(Vector::cross(up, f));
  367. x.normalize();
  368. return RotationMatrix(x, Vector::cross(f, x), f);
  369. }
  370. static RotationMatrix heading(float a) {
  371. float sa = std::sin(a);
  372. float ca = std::cos(a);
  373. return RotationMatrix(
  374. 1.0f, 0.0f, 0.0f,
  375. 0.0f, ca, -sa,
  376. 0.0f, sa, ca
  377. );
  378. }
  379. static RotationMatrix pitch(float a) {
  380. float sa = std::sin(a);
  381. float ca = std::cos(a);
  382. return RotationMatrix(
  383. ca, 0.0f, -sa,
  384. 0.0f, 1.0f, 0.0f,
  385. sa, 0.0f, ca
  386. );
  387. }
  388. static RotationMatrix roll(float a) {
  389. float sa = std::sin(a);
  390. float ca = std::cos(a);
  391. return RotationMatrix(
  392. ca, -sa, 0.0f,
  393. sa, ca, 0.0f,
  394. 0.0f, 0.0f, 1.0f
  395. );
  396. }
  397. RotationMatrix inverted() const {
  398. return RotationMatrix(
  399. _m[0], _m[4], _m[8],
  400. _m[1], _m[5], _m[9],
  401. _m[2], _m[6], _m[10]
  402. );
  403. }
  404. RotationMatrix transposed() const {
  405. return RotationMatrix(
  406. _m[0], _m[4], _m[8],
  407. _m[1], _m[5], _m[9],
  408. _m[2], _m[6], _m[10]
  409. );
  410. }
  411. Vector transform(const Vector& v) const {
  412. return Vector(
  413. _m[0] * v.x() + _m[4] * v.y() + _m[8] * v.z(),
  414. _m[1] * v.x() + _m[5] * v.y() + _m[9] * v.z(),
  415. _m[2] * v.x() + _m[6] * v.y() + _m[10] * v.z()
  416. );
  417. }
  418. UnitVector transform(const UnitVector& v) const {
  419. return UnitVector(
  420. _m[0] * v.x() + _m[4] * v.y() + _m[8] * v.z(),
  421. _m[1] * v.x() + _m[5] * v.y() + _m[9] * v.z(),
  422. _m[2] * v.x() + _m[6] * v.y() + _m[10] * v.z()
  423. );
  424. }
  425. RotationMatrix operator*(const RotationMatrix& m) const {
  426. return RotationMatrix(
  427. _m[0] * m._m[0] + _m[1] * m._m[4] + _m[2] * m._m[8],
  428. _m[0] * m._m[1] + _m[1] * m._m[5] + _m[2] * m._m[9],
  429. _m[0] * m._m[2] + _m[1] * m._m[6] + _m[2] * m._m[10]
  430. ,
  431. _m[4] * m._m[0] + _m[5] * m._m[4] + _m[6] * m._m[8],
  432. _m[4] * m._m[1] + _m[5] * m._m[5] + _m[6] * m._m[9],
  433. _m[4] * m._m[2] + _m[5] * m._m[6] + _m[6] * m._m[10]
  434. ,
  435. _m[8] * m._m[0] + _m[9] * m._m[4] + _m[10] * m._m[8],
  436. _m[8] * m._m[1] + _m[9] * m._m[5] + _m[10] * m._m[9],
  437. _m[8] * m._m[2] + _m[9] * m._m[6] + _m[10] * m._m[10]
  438. );
  439. }
  440. };
  441. class UnitQuat {
  442. protected:
  443. float _q[4];
  444. unsigned int _renormalizeCount;
  445. // These two are internal, since they do not guarantee length == 1
  446. UnitQuat(float x, float y, float z, float w) : _renormalizeCount(0) {
  447. _q[0] = x;
  448. _q[1] = y;
  449. _q[2] = z;
  450. _q[3] = w;
  451. }
  452. void set(float x, float y, float z, float w) {
  453. _q[0] = x;
  454. _q[1] = y;
  455. _q[2] = z;
  456. _q[3] = w;
  457. }
  458. public:
  459. UnitQuat() : _renormalizeCount(0) {
  460. _q[0] = _q[1] = _q[2] = 0.0f;
  461. _q[3] = 1.0f;
  462. }
  463. UnitQuat(float a, const UnitVector& axis) : _renormalizeCount(0) {
  464. a *= 0.5f;
  465. float sinA = std::sin(a);
  466. set(
  467. sinA * axis.x(),
  468. sinA * axis.y(),
  469. sinA * axis.z(),
  470. std::cos(a)
  471. );
  472. }
  473. UnitQuat(const RotationMatrix& r) : _renormalizeCount(0) {
  474. float trace = r.get(0) + r.get(5) + r.get(10) + 1.0f;
  475. if (trace > 0) {
  476. float s = 2.0f * std::sqrt(trace);
  477. set(
  478. (r.get(9) - r.get(6)) / s,
  479. (r.get(2) - r.get(8)) / s,
  480. (r.get(4) - r.get(1)) / s,
  481. s / 4.0f
  482. );
  483. } else {
  484. if (r.get(0) > r.get(5)) {
  485. if (r.get(0) > r.get(10)) {
  486. // r.get(0) is largest
  487. float s = 2.0f *
  488. std::sqrt(1.0f + r.get(0) - r.get(5) - r.get(10));
  489. set(
  490. s / 4.0f,
  491. (r.get(1) + r.get(4)) / s,
  492. (r.get(2) + r.get(8)) / s,
  493. (r.get(9) - r.get(6)) / s
  494. );
  495. } else {
  496. // r.get(10) is largest
  497. float s = 2.0f *
  498. std::sqrt(1.0f + r.get(10) - r.get(0) - r.get(5));
  499. set(
  500. (r.get(2) + r.get(8)) / s,
  501. (r.get(6) + r.get(9)) / s,
  502. s / 4,
  503. (r.get(4) - r.get(1)) / s
  504. );
  505. }
  506. } else {
  507. if (r.get(5) > r.get(10)) {
  508. // r.get(5) is largest
  509. float s = 2.0f *
  510. std::sqrt(1.0f + r.get(5) - r.get(0) - r.get(10));
  511. set(
  512. (r.get(1) + r.get(4)) / s,
  513. s / 4,
  514. (r.get(6) + r.get(9)) / s,
  515. (r.get(2) - r.get(8)) / s
  516. );
  517. } else {
  518. // r.get(10) is largest
  519. float s = 2.0f *
  520. std::sqrt(1.0f + r.get(10) - r.get(0) - r.get(5));
  521. set(
  522. (r.get(2) + r.get(8)) / s,
  523. (r.get(6) + r.get(9)) / s,
  524. s / 4,
  525. (r.get(4) - r.get(1)) / s
  526. );
  527. }
  528. }
  529. }
  530. }
  531. operator RotationMatrix() const {
  532. float wx = _q[3] * _q[0] * 2.0f;
  533. float wy = _q[3] * _q[1] * 2.0f;
  534. float wz = _q[3] * _q[2] * 2.0f;
  535. float xx = _q[0] * _q[0] * 2.0f;
  536. float xy = _q[0] * _q[1] * 2.0f;
  537. float xz = _q[0] * _q[2] * 2.0f;
  538. float yy = _q[1] * _q[1] * 2.0f;
  539. float yz = _q[1] * _q[2] * 2.0f;
  540. float zz = _q[2] * _q[2] * 2.0f;
  541. return RotationMatrix(
  542. 1.0f - yy - zz, xy + wz, xz - wy,
  543. xy - wz, 1.0f - xx - zz, yz + wx,
  544. xz + wy, yz - wx, 1.0f - xx - yy
  545. );
  546. }
  547. void toAngleAxis(float* a, UnitVector* axis) const {
  548. *a = 2.0f * std::acos(_q[3]);
  549. float sinA = std::sqrt(1.0f - _q[3] * _q[3]);
  550. if (std::abs(sinA) < 0.00001f)
  551. axis->set(1.0f, 0.0f, 0.0f);
  552. else
  553. axis->set(
  554. _q[0] / sinA,
  555. _q[1] / sinA,
  556. _q[2] / sinA
  557. );
  558. }
  559. UnitVector forward() const {
  560. float wx = _q[3] * _q[0] * 2.0f;
  561. float wy = _q[3] * _q[1] * 2.0f;
  562. float xx = _q[0] * _q[0] * 2.0f;
  563. float xz = _q[0] * _q[2] * 2.0f;
  564. float yy = _q[1] * _q[1] * 2.0f;
  565. float yz = _q[1] * _q[2] * 2.0f;
  566. return UnitVector(-xz - wy, -yz + wx, -1.0f + xx + yy);
  567. }
  568. UnitVector backward() const {
  569. float wx = _q[3] * _q[0] * 2.0f;
  570. float wy = _q[3] * _q[1] * 2.0f;
  571. float xx = _q[0] * _q[0] * 2.0f;
  572. float xz = _q[0] * _q[2] * 2.0f;
  573. float yy = _q[1] * _q[1] * 2.0f;
  574. float yz = _q[1] * _q[2] * 2.0f;
  575. return UnitVector(xz + wy, yz - wx, 1.0f - xx - yy);
  576. }
  577. UnitVector left() const {
  578. float wy = _q[3] * _q[1] * 2.0f;
  579. float wz = _q[3] * _q[2] * 2.0f;
  580. float xy = _q[0] * _q[1] * 2.0f;
  581. float xz = _q[0] * _q[2] * 2.0f;
  582. float yy = _q[1] * _q[1] * 2.0f;
  583. float zz = _q[2] * _q[2] * 2.0f;
  584. return UnitVector(-1.0f + yy + zz, -xy - wz, -xz + wy);
  585. }
  586. UnitVector right() const {
  587. float wy = _q[3] * _q[1] * 2.0f;
  588. float wz = _q[3] * _q[2] * 2.0f;
  589. float xy = _q[0] * _q[1] * 2.0f;
  590. float xz = _q[0] * _q[2] * 2.0f;
  591. float yy = _q[1] * _q[1] * 2.0f;
  592. float zz = _q[2] * _q[2] * 2.0f;
  593. return UnitVector(1.0f - yy - zz, xy + wz, xz - wy);
  594. }
  595. UnitVector up() const {
  596. float wx = _q[3] * _q[0] * 2.0f;
  597. float wz = _q[3] * _q[2] * 2.0f;
  598. float xx = _q[0] * _q[0] * 2.0f;
  599. float xy = _q[0] * _q[1] * 2.0f;
  600. float yz = _q[1] * _q[2] * 2.0f;
  601. float zz = _q[2] * _q[2] * 2.0f;
  602. return UnitVector(xy - wz, 1.0f - xx - zz, yz + wx);
  603. }
  604. UnitVector down() const {
  605. float wx = _q[3] * _q[0] * 2.0f;
  606. float wz = _q[3] * _q[2] * 2.0f;
  607. float xx = _q[0] * _q[0] * 2.0f;
  608. float xy = _q[0] * _q[1] * 2.0f;
  609. float yz = _q[1] * _q[2] * 2.0f;
  610. float zz = _q[2] * _q[2] * 2.0f;
  611. return UnitVector(-xy + wz, -1.0f + xx + zz, -yz + wx);
  612. }
  613. float getX() const {
  614. return _q[0];
  615. }
  616. float getY() const {
  617. return _q[1];
  618. }
  619. float getZ() const {
  620. return _q[2];
  621. }
  622. float getW() const {
  623. return _q[3];
  624. }
  625. void multiplyBy(const UnitQuat& q) {
  626. float tempX = _q[0];
  627. float tempY = _q[1];
  628. float tempZ = _q[2];
  629. float tempW = _q[3];
  630. _q[0] = tempW * q._q[0] + q._q[3] * tempX
  631. + tempY * q._q[2] - q._q[1] * tempZ;
  632. _q[1] = tempW * q._q[1] + q._q[3] * tempY
  633. + tempZ * q._q[0] - q._q[2] * tempX;
  634. _q[2] = tempW * q._q[2] + q._q[3] * tempZ
  635. + tempX * q._q[1] - q._q[0] * tempY;
  636. _q[3] = tempW * q._q[3]
  637. - tempX * q._q[0]
  638. - tempY * q._q[1]
  639. - tempZ * q._q[2];
  640. if (++_renormalizeCount == 5) {
  641. float length = std::sqrt(
  642. _q[0] * _q[0] +
  643. _q[1] * _q[1] +
  644. _q[2] * _q[2] +
  645. _q[3] * _q[3]
  646. );
  647. _q[0] /= length;
  648. _q[1] /= length;
  649. _q[2] /= length;
  650. _q[3] /= length;
  651. _renormalizeCount = 0;
  652. }
  653. }
  654. void preMultiplyBy(const UnitQuat& q) {
  655. float tempX = _q[0];
  656. float tempY = _q[1];
  657. float tempZ = _q[2];
  658. float tempW = _q[3];
  659. _q[0] = q._q[3] * tempX + tempW * q._q[0]
  660. + q._q[1] * tempZ - tempY * q._q[2];
  661. _q[1] = q._q[3] * tempY + tempW * q._q[1]
  662. + q._q[2] * tempX - tempZ * q._q[0];
  663. _q[2] = q._q[3] * tempZ + tempW * q._q[2]
  664. + q._q[0] * tempY - tempX * q._q[1];
  665. _q[3] = q._q[3] * tempW
  666. - q._q[0] * tempX
  667. - q._q[1] * tempY
  668. - q._q[2] * tempZ;
  669. if (++_renormalizeCount == 5) {
  670. float length = std::sqrt(
  671. _q[0] * _q[0] +
  672. _q[1] * _q[1] +
  673. _q[2] * _q[2] +
  674. _q[3] * _q[3]
  675. );
  676. _q[0] /= length;
  677. _q[1] /= length;
  678. _q[2] /= length;
  679. _q[3] /= length;
  680. _renormalizeCount = 0;
  681. }
  682. }
  683. static UnitQuat pitch(float a) {
  684. a *= 0.5f;
  685. return UnitQuat(std::sin(a), 0.0f, 0.0f, std::cos(a));
  686. }
  687. static UnitQuat heading(float a) {
  688. a *= 0.5f;
  689. return UnitQuat(0.0f, std::sin(a), 0.0f, std::cos(a));
  690. }
  691. static UnitQuat roll(float a) {
  692. a *= 0.5f;
  693. return UnitQuat(0.0f, 0.0f, std::sin(a), std::cos(a));
  694. }
  695. };
  696. #endif // _VECTOR_HH