Matrix.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /**
  2. * Copyright (c) 2006-2021 LOVE Development Team
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty. In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. *
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. *
  12. * 1. The origin of this software must not be misrepresented; you must not
  13. * claim that you wrote the original software. If you use this software
  14. * in a product, an acknowledgment in the product documentation would be
  15. * appreciated but is not required.
  16. * 2. Altered source versions must be plainly marked as such, and must not be
  17. * misrepresented as being the original software.
  18. * 3. This notice may not be removed or altered from any source distribution.
  19. **/
  20. #include "Matrix.h"
  21. #include "common/config.h"
  22. // STD
  23. #include <cstring> // memcpy
  24. #include <cmath>
  25. #if defined(LOVE_SIMD_SSE)
  26. #include <xmmintrin.h>
  27. #endif
  28. #if defined(LOVE_SIMD_NEON)
  29. #include <arm_neon.h>
  30. #endif
  31. namespace love
  32. {
  33. // | e0 e4 e8 e12 |
  34. // | e1 e5 e9 e13 |
  35. // | e2 e6 e10 e14 |
  36. // | e3 e7 e11 e15 |
  37. // | e0 e4 e8 e12 |
  38. // | e1 e5 e9 e13 |
  39. // | e2 e6 e10 e14 |
  40. // | e3 e7 e11 e15 |
  41. void Matrix4::multiply(const Matrix4 &a, const Matrix4 &b, float t[16])
  42. {
  43. #if defined(LOVE_SIMD_SSE)
  44. // We can't guarantee 16-bit alignment (e.g. for heap-allocated Matrix4
  45. // objects) so we use unaligned loads and stores.
  46. __m128 col1 = _mm_loadu_ps(&a.e[0]);
  47. __m128 col2 = _mm_loadu_ps(&a.e[4]);
  48. __m128 col3 = _mm_loadu_ps(&a.e[8]);
  49. __m128 col4 = _mm_loadu_ps(&a.e[12]);
  50. for (int i = 0; i < 4; i++)
  51. {
  52. __m128 brod1 = _mm_set1_ps(b.e[4*i + 0]);
  53. __m128 brod2 = _mm_set1_ps(b.e[4*i + 1]);
  54. __m128 brod3 = _mm_set1_ps(b.e[4*i + 2]);
  55. __m128 brod4 = _mm_set1_ps(b.e[4*i + 3]);
  56. __m128 col = _mm_add_ps(
  57. _mm_add_ps(_mm_mul_ps(brod1, col1), _mm_mul_ps(brod2, col2)),
  58. _mm_add_ps(_mm_mul_ps(brod3, col3), _mm_mul_ps(brod4, col4))
  59. );
  60. _mm_storeu_ps(&t[4*i], col);
  61. }
  62. #elif defined(LOVE_SIMD_NEON)
  63. float32x4_t cola1 = vld1q_f32(&a.e[0]);
  64. float32x4_t cola2 = vld1q_f32(&a.e[4]);
  65. float32x4_t cola3 = vld1q_f32(&a.e[8]);
  66. float32x4_t cola4 = vld1q_f32(&a.e[12]);
  67. float32x4_t col1 = vmulq_n_f32(cola1, b.e[0]);
  68. col1 = vmlaq_n_f32(col1, cola2, b.e[1]);
  69. col1 = vmlaq_n_f32(col1, cola3, b.e[2]);
  70. col1 = vmlaq_n_f32(col1, cola4, b.e[3]);
  71. float32x4_t col2 = vmulq_n_f32(cola1, b.e[4]);
  72. col2 = vmlaq_n_f32(col2, cola2, b.e[5]);
  73. col2 = vmlaq_n_f32(col2, cola3, b.e[6]);
  74. col2 = vmlaq_n_f32(col2, cola4, b.e[7]);
  75. float32x4_t col3 = vmulq_n_f32(cola1, b.e[8]);
  76. col3 = vmlaq_n_f32(col3, cola2, b.e[9]);
  77. col3 = vmlaq_n_f32(col3, cola3, b.e[10]);
  78. col3 = vmlaq_n_f32(col3, cola4, b.e[11]);
  79. float32x4_t col4 = vmulq_n_f32(cola1, b.e[12]);
  80. col4 = vmlaq_n_f32(col4, cola2, b.e[13]);
  81. col4 = vmlaq_n_f32(col4, cola3, b.e[14]);
  82. col4 = vmlaq_n_f32(col4, cola4, b.e[15]);
  83. vst1q_f32(&t[0], col1);
  84. vst1q_f32(&t[4], col2);
  85. vst1q_f32(&t[8], col3);
  86. vst1q_f32(&t[12], col4);
  87. #else
  88. t[0] = (a.e[0]*b.e[0]) + (a.e[4]*b.e[1]) + (a.e[8]*b.e[2]) + (a.e[12]*b.e[3]);
  89. t[4] = (a.e[0]*b.e[4]) + (a.e[4]*b.e[5]) + (a.e[8]*b.e[6]) + (a.e[12]*b.e[7]);
  90. t[8] = (a.e[0]*b.e[8]) + (a.e[4]*b.e[9]) + (a.e[8]*b.e[10]) + (a.e[12]*b.e[11]);
  91. t[12] = (a.e[0]*b.e[12]) + (a.e[4]*b.e[13]) + (a.e[8]*b.e[14]) + (a.e[12]*b.e[15]);
  92. t[1] = (a.e[1]*b.e[0]) + (a.e[5]*b.e[1]) + (a.e[9]*b.e[2]) + (a.e[13]*b.e[3]);
  93. t[5] = (a.e[1]*b.e[4]) + (a.e[5]*b.e[5]) + (a.e[9]*b.e[6]) + (a.e[13]*b.e[7]);
  94. t[9] = (a.e[1]*b.e[8]) + (a.e[5]*b.e[9]) + (a.e[9]*b.e[10]) + (a.e[13]*b.e[11]);
  95. t[13] = (a.e[1]*b.e[12]) + (a.e[5]*b.e[13]) + (a.e[9]*b.e[14]) + (a.e[13]*b.e[15]);
  96. t[2] = (a.e[2]*b.e[0]) + (a.e[6]*b.e[1]) + (a.e[10]*b.e[2]) + (a.e[14]*b.e[3]);
  97. t[6] = (a.e[2]*b.e[4]) + (a.e[6]*b.e[5]) + (a.e[10]*b.e[6]) + (a.e[14]*b.e[7]);
  98. t[10] = (a.e[2]*b.e[8]) + (a.e[6]*b.e[9]) + (a.e[10]*b.e[10]) + (a.e[14]*b.e[11]);
  99. t[14] = (a.e[2]*b.e[12]) + (a.e[6]*b.e[13]) + (a.e[10]*b.e[14]) + (a.e[14]*b.e[15]);
  100. t[3] = (a.e[3]*b.e[0]) + (a.e[7]*b.e[1]) + (a.e[11]*b.e[2]) + (a.e[15]*b.e[3]);
  101. t[7] = (a.e[3]*b.e[4]) + (a.e[7]*b.e[5]) + (a.e[11]*b.e[6]) + (a.e[15]*b.e[7]);
  102. t[11] = (a.e[3]*b.e[8]) + (a.e[7]*b.e[9]) + (a.e[11]*b.e[10]) + (a.e[15]*b.e[11]);
  103. t[15] = (a.e[3]*b.e[12]) + (a.e[7]*b.e[13]) + (a.e[11]*b.e[14]) + (a.e[15]*b.e[15]);
  104. #endif
  105. }
  106. void Matrix4::multiply(const Matrix4 &a, const Matrix4 &b, Matrix4 &t)
  107. {
  108. multiply(a, b, t.e);
  109. }
  110. // | e0 e4 e8 e12 |
  111. // | e1 e5 e9 e13 |
  112. // | e2 e6 e10 e14 |
  113. // | e3 e7 e11 e15 |
  114. Matrix4::Matrix4()
  115. {
  116. setIdentity();
  117. }
  118. Matrix4::Matrix4(const float elements[16])
  119. {
  120. memcpy(e, elements, sizeof(float) * 16);
  121. }
  122. Matrix4::Matrix4(float t00, float t10, float t01, float t11, float x, float y)
  123. {
  124. setRawTransformation(t00, t10, t01, t11, x, y);
  125. }
  126. Matrix4::Matrix4(const Matrix4 &a, const Matrix4 &b)
  127. {
  128. multiply(a, b, e);
  129. }
  130. Matrix4::Matrix4(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
  131. {
  132. setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
  133. }
  134. Matrix4 Matrix4::operator * (const Matrix4 &m) const
  135. {
  136. return Matrix4(*this, m);
  137. }
  138. void Matrix4::operator *= (const Matrix4 &m)
  139. {
  140. float t[16];
  141. multiply(*this, m, t);
  142. memcpy(this->e, t, sizeof(float)*16);
  143. }
  144. const float *Matrix4::getElements() const
  145. {
  146. return e;
  147. }
  148. void Matrix4::setIdentity()
  149. {
  150. memset(e, 0, sizeof(float)*16);
  151. e[15] = e[10] = e[5] = e[0] = 1;
  152. }
  153. void Matrix4::setTranslation(float x, float y)
  154. {
  155. setIdentity();
  156. e[12] = x;
  157. e[13] = y;
  158. }
  159. void Matrix4::setRotation(float rad)
  160. {
  161. setIdentity();
  162. float c = cosf(rad), s = sinf(rad);
  163. e[0] = c;
  164. e[4] = -s;
  165. e[1] = s;
  166. e[5] = c;
  167. }
  168. void Matrix4::setScale(float sx, float sy)
  169. {
  170. setIdentity();
  171. e[0] = sx;
  172. e[5] = sy;
  173. }
  174. void Matrix4::setShear(float kx, float ky)
  175. {
  176. setIdentity();
  177. e[1] = ky;
  178. e[4] = kx;
  179. }
  180. void Matrix4::getApproximateScale(float &sx, float &sy) const
  181. {
  182. sx = sqrtf(e[0] * e[0] + e[4] * e[4]);
  183. sy = sqrtf(e[1] * e[1] + e[5] * e[5]);
  184. }
  185. void Matrix4::setRawTransformation(float t00, float t10, float t01, float t11, float x, float y)
  186. {
  187. memset(e, 0, sizeof(float)*16); // zero out matrix
  188. e[10] = e[15] = 1.0f;
  189. e[0] = t00;
  190. e[1] = t10;
  191. e[4] = t01;
  192. e[5] = t11;
  193. e[12] = x;
  194. e[13] = y;
  195. }
  196. void Matrix4::setTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
  197. {
  198. memset(e, 0, sizeof(float)*16); // zero out matrix
  199. float c = cosf(angle), s = sinf(angle);
  200. // matrix multiplication carried out on paper:
  201. // |1 x| |c -s | |sx | | 1 ky | |1 -ox|
  202. // | 1 y| |s c | | sy | |kx 1 | | 1 -oy|
  203. // | 1 | | 1 | | 1 | | 1 | | 1 |
  204. // | 1| | 1| | 1| | 1| | 1 |
  205. // move rotate scale skew origin
  206. e[10] = e[15] = 1.0f;
  207. e[0] = c * sx - ky * s * sy; // = a
  208. e[1] = s * sx + ky * c * sy; // = b
  209. e[4] = kx * c * sx - s * sy; // = c
  210. e[5] = kx * s * sx + c * sy; // = d
  211. e[12] = x - ox * e[0] - oy * e[4];
  212. e[13] = y - ox * e[1] - oy * e[5];
  213. }
  214. void Matrix4::translate(float x, float y)
  215. {
  216. Matrix4 t;
  217. t.setTranslation(x, y);
  218. this->operator *=(t);
  219. }
  220. void Matrix4::rotate(float rad)
  221. {
  222. Matrix4 t;
  223. t.setRotation(rad);
  224. this->operator *=(t);
  225. }
  226. void Matrix4::scale(float sx, float sy)
  227. {
  228. Matrix4 t;
  229. t.setScale(sx, sy);
  230. this->operator *=(t);
  231. }
  232. void Matrix4::shear(float kx, float ky)
  233. {
  234. Matrix4 t;
  235. t.setShear(kx,ky);
  236. this->operator *=(t);
  237. }
  238. bool Matrix4::isAffine2DTransform() const
  239. {
  240. return fabsf(e[2] + e[3] + e[6] + e[7] + e[8] + e[9] + e[11] + e[14]) < 0.00001f
  241. && fabsf(e[10] + e[15] - 2.0f) < 0.00001f;
  242. }
  243. Matrix4 Matrix4::inverse() const
  244. {
  245. Matrix4 inv;
  246. inv.e[0] = e[5] * e[10] * e[15] -
  247. e[5] * e[11] * e[14] -
  248. e[9] * e[6] * e[15] +
  249. e[9] * e[7] * e[14] +
  250. e[13] * e[6] * e[11] -
  251. e[13] * e[7] * e[10];
  252. inv.e[4] = -e[4] * e[10] * e[15] +
  253. e[4] * e[11] * e[14] +
  254. e[8] * e[6] * e[15] -
  255. e[8] * e[7] * e[14] -
  256. e[12] * e[6] * e[11] +
  257. e[12] * e[7] * e[10];
  258. inv.e[8] = e[4] * e[9] * e[15] -
  259. e[4] * e[11] * e[13] -
  260. e[8] * e[5] * e[15] +
  261. e[8] * e[7] * e[13] +
  262. e[12] * e[5] * e[11] -
  263. e[12] * e[7] * e[9];
  264. inv.e[12] = -e[4] * e[9] * e[14] +
  265. e[4] * e[10] * e[13] +
  266. e[8] * e[5] * e[14] -
  267. e[8] * e[6] * e[13] -
  268. e[12] * e[5] * e[10] +
  269. e[12] * e[6] * e[9];
  270. inv.e[1] = -e[1] * e[10] * e[15] +
  271. e[1] * e[11] * e[14] +
  272. e[9] * e[2] * e[15] -
  273. e[9] * e[3] * e[14] -
  274. e[13] * e[2] * e[11] +
  275. e[13] * e[3] * e[10];
  276. inv.e[5] = e[0] * e[10] * e[15] -
  277. e[0] * e[11] * e[14] -
  278. e[8] * e[2] * e[15] +
  279. e[8] * e[3] * e[14] +
  280. e[12] * e[2] * e[11] -
  281. e[12] * e[3] * e[10];
  282. inv.e[9] = -e[0] * e[9] * e[15] +
  283. e[0] * e[11] * e[13] +
  284. e[8] * e[1] * e[15] -
  285. e[8] * e[3] * e[13] -
  286. e[12] * e[1] * e[11] +
  287. e[12] * e[3] * e[9];
  288. inv.e[13] = e[0] * e[9] * e[14] -
  289. e[0] * e[10] * e[13] -
  290. e[8] * e[1] * e[14] +
  291. e[8] * e[2] * e[13] +
  292. e[12] * e[1] * e[10] -
  293. e[12] * e[2] * e[9];
  294. inv.e[2] = e[1] * e[6] * e[15] -
  295. e[1] * e[7] * e[14] -
  296. e[5] * e[2] * e[15] +
  297. e[5] * e[3] * e[14] +
  298. e[13] * e[2] * e[7] -
  299. e[13] * e[3] * e[6];
  300. inv.e[6] = -e[0] * e[6] * e[15] +
  301. e[0] * e[7] * e[14] +
  302. e[4] * e[2] * e[15] -
  303. e[4] * e[3] * e[14] -
  304. e[12] * e[2] * e[7] +
  305. e[12] * e[3] * e[6];
  306. inv.e[10] = e[0] * e[5] * e[15] -
  307. e[0] * e[7] * e[13] -
  308. e[4] * e[1] * e[15] +
  309. e[4] * e[3] * e[13] +
  310. e[12] * e[1] * e[7] -
  311. e[12] * e[3] * e[5];
  312. inv.e[14] = -e[0] * e[5] * e[14] +
  313. e[0] * e[6] * e[13] +
  314. e[4] * e[1] * e[14] -
  315. e[4] * e[2] * e[13] -
  316. e[12] * e[1] * e[6] +
  317. e[12] * e[2] * e[5];
  318. inv.e[3] = -e[1] * e[6] * e[11] +
  319. e[1] * e[7] * e[10] +
  320. e[5] * e[2] * e[11] -
  321. e[5] * e[3] * e[10] -
  322. e[9] * e[2] * e[7] +
  323. e[9] * e[3] * e[6];
  324. inv.e[7] = e[0] * e[6] * e[11] -
  325. e[0] * e[7] * e[10] -
  326. e[4] * e[2] * e[11] +
  327. e[4] * e[3] * e[10] +
  328. e[8] * e[2] * e[7] -
  329. e[8] * e[3] * e[6];
  330. inv.e[11] = -e[0] * e[5] * e[11] +
  331. e[0] * e[7] * e[9] +
  332. e[4] * e[1] * e[11] -
  333. e[4] * e[3] * e[9] -
  334. e[8] * e[1] * e[7] +
  335. e[8] * e[3] * e[5];
  336. inv.e[15] = e[0] * e[5] * e[10] -
  337. e[0] * e[6] * e[9] -
  338. e[4] * e[1] * e[10] +
  339. e[4] * e[2] * e[9] +
  340. e[8] * e[1] * e[6] -
  341. e[8] * e[2] * e[5];
  342. float det = e[0] * inv.e[0] + e[1] * inv.e[4] + e[2] * inv.e[8] + e[3] * inv.e[12];
  343. float invdet = 1.0f / det;
  344. for (int i = 0; i < 16; i++)
  345. inv.e[i] *= invdet;
  346. return inv;
  347. }
  348. Matrix4 Matrix4::ortho(float left, float right, float bottom, float top, float near, float far)
  349. {
  350. Matrix4 m;
  351. m.e[0] = 2.0f / (right - left);
  352. m.e[5] = 2.0f / (top - bottom);
  353. m.e[10] = -2.0f / (far - near);
  354. m.e[12] = -(right + left) / (right - left);
  355. m.e[13] = -(top + bottom) / (top - bottom);
  356. m.e[14] = -(far + near) / (far - near);
  357. return m;
  358. }
  359. /**
  360. * | e0 e3 e6 |
  361. * | e1 e4 e7 |
  362. * | e2 e5 e8 |
  363. **/
  364. Matrix3::Matrix3()
  365. {
  366. setIdentity();
  367. }
  368. Matrix3::Matrix3(const Matrix4 &mat4)
  369. {
  370. const float *mat4elems = mat4.getElements();
  371. // Column 0.
  372. e[0] = mat4elems[0];
  373. e[1] = mat4elems[1];
  374. e[2] = mat4elems[2];
  375. // Column 1.
  376. e[3] = mat4elems[4];
  377. e[4] = mat4elems[5];
  378. e[5] = mat4elems[6];
  379. // Column 2.
  380. e[6] = mat4elems[8];
  381. e[7] = mat4elems[9];
  382. e[8] = mat4elems[10];
  383. }
  384. Matrix3::Matrix3(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
  385. {
  386. setTransformation(x, y, angle, sx, sy, ox, oy, kx, ky);
  387. }
  388. Matrix3::~Matrix3()
  389. {
  390. }
  391. void Matrix3::setIdentity()
  392. {
  393. memset(e, 0, sizeof(float) * 9);
  394. e[8] = e[4] = e[0] = 1.0f;
  395. }
  396. Matrix3 Matrix3::operator * (const love::Matrix3 &m) const
  397. {
  398. Matrix3 t;
  399. t.e[0] = (e[0]*m.e[0]) + (e[3]*m.e[1]) + (e[6]*m.e[2]);
  400. t.e[3] = (e[0]*m.e[3]) + (e[3]*m.e[4]) + (e[6]*m.e[5]);
  401. t.e[6] = (e[0]*m.e[6]) + (e[3]*m.e[7]) + (e[6]*m.e[8]);
  402. t.e[1] = (e[1]*m.e[0]) + (e[4]*m.e[1]) + (e[7]*m.e[2]);
  403. t.e[4] = (e[1]*m.e[3]) + (e[4]*m.e[4]) + (e[7]*m.e[5]);
  404. t.e[7] = (e[1]*m.e[6]) + (e[4]*m.e[7]) + (e[7]*m.e[8]);
  405. t.e[2] = (e[2]*m.e[0]) + (e[5]*m.e[1]) + (e[8]*m.e[2]);
  406. t.e[5] = (e[2]*m.e[3]) + (e[5]*m.e[4]) + (e[8]*m.e[5]);
  407. t.e[8] = (e[2]*m.e[6]) + (e[5]*m.e[7]) + (e[8]*m.e[8]);
  408. return t;
  409. }
  410. void Matrix3::operator *= (const Matrix3 &m)
  411. {
  412. Matrix3 t = (*this) * m;
  413. memcpy(e, t.e, sizeof(float) * 9);
  414. }
  415. const float *Matrix3::getElements() const
  416. {
  417. return e;
  418. }
  419. Matrix3 Matrix3::transposedInverse() const
  420. {
  421. // e0 e3 e6
  422. // e1 e4 e7
  423. // e2 e5 e8
  424. float det = e[0] * (e[4]*e[8] - e[7]*e[5])
  425. - e[1] * (e[3]*e[8] - e[5]*e[6])
  426. + e[2] * (e[3]*e[7] - e[4]*e[6]);
  427. float invdet = 1.0f / det;
  428. Matrix3 m;
  429. m.e[0] = invdet * (e[4]*e[8] - e[7]*e[5]);
  430. m.e[3] = -invdet * (e[1]*e[8] - e[2]*e[7]);
  431. m.e[6] = invdet * (e[1]*e[5] - e[2]*e[4]);
  432. m.e[1] = -invdet * (e[3]*e[8] - e[5]*e[6]);
  433. m.e[4] = invdet * (e[0]*e[8] - e[2]*e[6]);
  434. m.e[7] = -invdet * (e[0]*e[5] - e[3]*e[2]);
  435. m.e[2] = invdet * (e[3]*e[7] - e[6]*e[4]);
  436. m.e[5] = -invdet * (e[0]*e[7] - e[6]*e[1]);
  437. m.e[8] = invdet * (e[0]*e[4] - e[3]*e[1]);
  438. return m;
  439. }
  440. void Matrix3::setTransformation(float x, float y, float angle, float sx, float sy, float ox, float oy, float kx, float ky)
  441. {
  442. float c = cosf(angle), s = sinf(angle);
  443. // matrix multiplication carried out on paper:
  444. // |1 x| |c -s | |sx | | 1 ky | |1 -ox|
  445. // | 1 y| |s c | | sy | |kx 1 | | 1 -oy|
  446. // | 1| | 1| | 1| | 1| | 1 |
  447. // move rotate scale skew origin
  448. e[0] = c * sx - ky * s * sy; // = a
  449. e[1] = s * sx + ky * c * sy; // = b
  450. e[3] = kx * c * sx - s * sy; // = c
  451. e[4] = kx * s * sx + c * sy; // = d
  452. e[6] = x - ox * e[0] - oy * e[3];
  453. e[7] = y - ox * e[1] - oy * e[4];
  454. e[2] = e[5] = 0.0f;
  455. e[8] = 1.0f;
  456. }
  457. } // love