ccGLMatrixTpl.h 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277
  1. #pragma once
  2. //##########################################################################
  3. //# #
  4. //# CLOUDCOMPARE #
  5. //# #
  6. //# This program is free software; you can redistribute it and/or modify #
  7. //# it under the terms of the GNU General Public License as published by #
  8. //# the Free Software Foundation; version 2 or later of the License. #
  9. //# #
  10. //# This program is distributed in the hope that it will be useful, #
  11. //# but WITHOUT ANY WARRANTY; without even the implied warranty of #
  12. //# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
  13. //# GNU General Public License for more details. #
  14. //# #
  15. //# COPYRIGHT: EDF R&D / TELECOM ParisTech (ENST-TSI) #
  16. //# #
  17. //##########################################################################
  18. //Local
  19. #include "ccSerializableObject.h"
  20. //CCCoreLib
  21. #include <CCGeom.h>
  22. #include <CCMath.h>
  23. //Qt
  24. #include <QTextStream>
  25. //! Model view matrix size (OpenGL)
  26. static const unsigned OPENGL_MATRIX_SIZE = 16;
  27. //Matrix element shortcuts in (line,column) order
  28. #define CC_MAT_R11 m_mat[0]
  29. #define CC_MAT_R21 m_mat[1]
  30. #define CC_MAT_R31 m_mat[2]
  31. #define CC_MAT_R41 m_mat[3]
  32. #define CC_MAT_R12 m_mat[4]
  33. #define CC_MAT_R22 m_mat[5]
  34. #define CC_MAT_R32 m_mat[6]
  35. #define CC_MAT_R42 m_mat[7]
  36. #define CC_MAT_R13 m_mat[8]
  37. #define CC_MAT_R23 m_mat[9]
  38. #define CC_MAT_R33 m_mat[10]
  39. #define CC_MAT_R43 m_mat[11]
  40. #define CC_MAT_R14 m_mat[12]
  41. #define CC_MAT_R24 m_mat[13]
  42. #define CC_MAT_R34 m_mat[14]
  43. #define CC_MAT_R44 m_mat[15]
  44. //! A 4x4 'transformation' matrix (column major order)
  45. /** Transformation (M) is composed by a rotation (R) and a translation (T):
  46. M*X = R*X + T
  47. **/
  48. template <typename T> class ccGLMatrixTpl : public ccSerializableObject
  49. {
  50. public:
  51. //! Default constructor
  52. /** Matrix is set to identity (see toIdentity) by default.
  53. **/
  54. ccGLMatrixTpl() { toIdentity(); }
  55. //! Copy constructor
  56. ccGLMatrixTpl(const ccGLMatrixTpl<T>& mat) { for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i) m_mat[i] = mat.m_mat[i]; }
  57. //! Constructor from a float GL matrix array
  58. /** \param mat16f a 16 elements array (column major order)
  59. **/
  60. explicit ccGLMatrixTpl(const float* mat16f) { for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i) m_mat[i] = static_cast<T>(mat16f[i]); internalRescale(); }
  61. //! Constructor from a double GL matrix array
  62. /** \warning Will implicitly cast the elements to float!
  63. \param mat16d a 16 elements array (column major order)
  64. **/
  65. explicit ccGLMatrixTpl(const double* mat16d) { for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i) m_mat[i] = static_cast<T>(mat16d[i]); internalRescale(); }
  66. //! Constructor from 4 columns (X,Y,Z,T)
  67. /** \param X 3 first elements of the 1st column (last one is 0)
  68. \param Y 3 first elements of the 2nd column (last one is 0)
  69. \param Z 3 first elements of the 3rd column (last one is 0)
  70. \param Tr 3 first elements of the last column (last one is 1)
  71. **/
  72. ccGLMatrixTpl(const Vector3Tpl<T>& X, const Vector3Tpl<T>& Y, const Vector3Tpl<T>& Z, const Vector3Tpl<T>& Tr)
  73. {
  74. CC_MAT_R11 = X.x; CC_MAT_R21 = X.y; CC_MAT_R31 = X.z; CC_MAT_R41 = 0;
  75. CC_MAT_R12 = Y.x; CC_MAT_R22 = Y.y; CC_MAT_R32 = Y.z; CC_MAT_R42 = 0;
  76. CC_MAT_R13 = Z.x; CC_MAT_R23 = Z.y; CC_MAT_R33 = Z.z; CC_MAT_R43 = 0;
  77. CC_MAT_R14 = Tr.x; CC_MAT_R24 = Tr.y; CC_MAT_R34 = Tr.z; CC_MAT_R44 = static_cast<T>(1);
  78. }
  79. //! Interpolates two matrices at relative position 'coef'
  80. /** \param coef interpolation position (should be between 0 and 1).
  81. \param glMat1 'left' matrix
  82. \param glMat2 'right' matrix
  83. **/
  84. static ccGLMatrixTpl Interpolate(T coef, const ccGLMatrixTpl<T>& glMat1, const ccGLMatrixTpl<T>& glMat2)
  85. {
  86. //we compute the transformation matrix between glMat1 and glMat2
  87. ccGLMatrixTpl<T> invTrans1 = glMat1.inverse();
  88. ccGLMatrixTpl<T> m12 = invTrans1 * glMat2;
  89. Vector3Tpl<T> axis,Tr;
  90. T alpha;
  91. m12.getParameters(alpha, axis, Tr);
  92. //we only have to interpolate the angle value
  93. alpha *= coef;
  94. //and the translation
  95. Tr *= coef;
  96. //we build-up the resulting matrix
  97. m12.initFromParameters(alpha, axis, Tr);
  98. //eventually we build-up resulting transformation
  99. return glMat1 * m12;
  100. }
  101. //! Creates a transformation matrix that rotates a vector to another
  102. /** Adapted from "Efficiently Building a Matrix to Rotate One Vector to Another"
  103. By Tomas Möller, John Hughes, Journal of Graphics Tools, 4(4):1-4, 1999
  104. \param from normalized non-zero source vector
  105. \param to normalized non-zero destination vector
  106. **/
  107. static ccGLMatrixTpl<T> FromToRotation(const Vector3Tpl<T>& from, const Vector3Tpl<T>& to)
  108. {
  109. T c = from.dot(to);
  110. T f = (c < 0 ? -c : c);
  111. ccGLMatrixTpl<T> result;
  112. if ( CCCoreLib::LessThanEpsilon( 1.0 - f ) ) //"from" and "to"-vector almost parallel
  113. {
  114. // "to" vector most nearly orthogonal to "from"
  115. Vector3Tpl<T> x(0, 0, 0);
  116. if (std::abs(from.x) < std::abs(from.y))
  117. {
  118. if (std::abs(from.x) < std::abs(from.z))
  119. x.x = static_cast<T>(1);
  120. else
  121. x.z = static_cast<T>(1);
  122. }
  123. else
  124. {
  125. if (std::abs(from.y) < std::abs(from.z))
  126. x.y = static_cast<T>(1);
  127. else
  128. x.z = static_cast<T>(1);
  129. }
  130. Vector3Tpl<T> u = x - from;
  131. Vector3Tpl<T> v = x - to;
  132. T c1 = 2 / u.dot(u);
  133. T c2 = 2 / v.dot(v);
  134. T c3 = c1 * c2 * u.dot(v);
  135. T* mat = result.data();
  136. for (unsigned i = 0; i < 3; i++)
  137. {
  138. for (unsigned j = 0; j < 3; j++)
  139. {
  140. mat[i * 4 + j] = c3 * v.u[i] * u.u[j]
  141. - c2 * v.u[i] * v.u[j]
  142. - c1 * u.u[i] * u.u[j];
  143. }
  144. mat[i * 4 + i] += static_cast<T>(1);
  145. }
  146. }
  147. else // the most common case, unless "from"="to", or "from"=-"to"
  148. {
  149. //see Efficiently Building a Matrix to Rotate One Vector to Another
  150. //T. Moller and J.F. Hugues (1999)
  151. Vector3Tpl<T> v = from.cross(to);
  152. T h = 1 / (1 + c);
  153. T hvx = h * v.x;
  154. T hvz = h * v.z;
  155. T hvxy = hvx * v.y;
  156. T hvxz = hvx * v.z;
  157. T hvyz = hvz * v.y;
  158. T* mat = result.data();
  159. mat[0] = c + hvx * v.x;
  160. mat[1] = hvxy + v.z;
  161. mat[2] = hvxz - v.y;
  162. mat[4] = hvxy - v.z;
  163. mat[5] = c + h * v.y * v.y;
  164. mat[6] = hvyz + v.x;
  165. mat[8] = hvxz + v.y;
  166. mat[9] = hvyz - v.x;
  167. mat[10] = c + hvz * v.z;
  168. }
  169. return result;
  170. }
  171. //! Converts a quaternion to a rotation matrix
  172. /** \param q quaternion (4 values: w,x,y,z)
  173. \return corresponding rotation matrix
  174. **/
  175. template<class Tq> static ccGLMatrixTpl<T> FromQuaternion(const Tq q[])
  176. {
  177. assert(q);
  178. ccGLMatrixTpl<T> rotMat;
  179. T* mat = rotMat.data();
  180. //diagonal
  181. {
  182. Tq q00 = q[0] * q[0];
  183. Tq q11 = q[1] * q[1];
  184. Tq q22 = q[2] * q[2];
  185. Tq q33 = q[3] * q[3];
  186. mat[0] = static_cast<T>(q00 + q11 - q22 - q33);
  187. mat[5] = static_cast<T>(q00 - q11 + q22 - q33);
  188. mat[10] = static_cast<T>(q00 - q11 - q22 + q33);
  189. mat[15] = static_cast<T>(1);
  190. }
  191. //non-diagonal elements
  192. {
  193. Tq q03 = q[0] * q[3];
  194. Tq q13 = q[1] * q[3];
  195. Tq q23 = q[2] * q[3];
  196. Tq q02 = q[0] * q[2];
  197. Tq q12 = q[1] * q[2];
  198. Tq q01 = q[0] * q[1];
  199. mat[1] = static_cast<T>((q12 + q03) * 2);
  200. mat[2] = static_cast<T>((q13 - q02) * 2);
  201. mat[4] = static_cast<T>((q12 - q03) * 2);
  202. mat[6] = static_cast<T>((q23 + q01) * 2);
  203. mat[8] = static_cast<T>((q13 + q02) * 2);
  204. mat[9] = static_cast<T>((q23 - q01) * 2);
  205. }
  206. return rotMat;
  207. }
  208. //! Generates a 'viewing' matrix from a looking vector and a 'up' direction
  209. /** \warning No translation is applied (pure rotation matrix)
  210. \param forward forward 'view' vector
  211. \param up up vector
  212. \return corresponding rotation matrix
  213. **/
  214. static ccGLMatrixTpl<T> FromViewDirAndUpDir(const Vector3Tpl<T>& forward, const Vector3Tpl<T>& up)
  215. {
  216. //normalize forward
  217. Vector3Tpl<T> uForward = forward;
  218. uForward.normalize();
  219. //side = forward x up
  220. Vector3Tpl<T> uSide = uForward.cross(up);
  221. uSide.normalize();
  222. //recompute 'up' as: up = side x forward
  223. Vector3Tpl<T> uUp = uSide.cross(uForward);
  224. uUp.normalize();
  225. ccGLMatrixTpl<T> matrix;
  226. {
  227. T* mat = matrix.data();
  228. mat[ 0] = uSide.x;
  229. mat[ 4] = uSide.y;
  230. mat[ 8] = uSide.z;
  231. mat[12] = 0;
  232. mat[ 1] = uUp.x;
  233. mat[ 5] = uUp.y;
  234. mat[ 9] = uUp.z;
  235. mat[13] = 0 ;
  236. mat[ 2] = -uForward.x;
  237. mat[ 6] = -uForward.y;
  238. mat[10] = -uForward.z;
  239. mat[14] = 0 ;
  240. mat[ 3] = 0;
  241. mat[ 7] = 0;
  242. mat[11] = 0;
  243. mat[15] = static_cast<T>(1) ;
  244. }
  245. return matrix;
  246. }
  247. //! Converts a 'text' matrix to a ccGLMatrix
  248. /** \param[in] matText matrix in text format
  249. \param[out] success whether input matrix text is valid or not
  250. **/
  251. static ccGLMatrixTpl<T> FromString(const QString& matText, bool& success)
  252. {
  253. QStringList valuesStr = matText.simplified().split(QChar(' '), QString::SkipEmptyParts);
  254. if (valuesStr.size() != OPENGL_MATRIX_SIZE)
  255. {
  256. success = false;
  257. return ccGLMatrixTpl<T>();
  258. }
  259. ccGLMatrixTpl<T> matrix;
  260. T* matValues = matrix.data();
  261. for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i)
  262. {
  263. matValues[i] = static_cast<T>(valuesStr[(i % 4) * 4 + (i >> 2)].toDouble(&success));
  264. if (!success)
  265. return ccGLMatrixTpl<T>();
  266. }
  267. matrix.internalRescale();
  268. success = true;
  269. return matrix;
  270. }
  271. //! Returns matrix as a string
  272. /** \param precision numerical precision
  273. \param separator separator
  274. \return string
  275. **/
  276. QString toString(int precision = 12, QChar separator = ' ') const
  277. {
  278. QString str;
  279. for (unsigned l = 0; l < 4; ++l) //lines
  280. {
  281. for (unsigned c = 0; c < 4; ++c) //columns
  282. {
  283. str.append(QString::number(m_mat[c * 4 + l], 'f', precision));
  284. if (c != 3)
  285. str.append(separator);
  286. }
  287. if (l != 3)
  288. str.append("\n");
  289. }
  290. return str;
  291. }
  292. //! Saves matrix to an ASCII file
  293. /** \param filename output file name
  294. \param precision output digits precision
  295. ***/
  296. virtual bool toAsciiFile(QString filename, int precision = 12) const
  297. {
  298. QFile fp(filename);
  299. if (!fp.open(QFile::WriteOnly | QFile::Text))
  300. return false;
  301. QTextStream stream(&fp);
  302. stream.setRealNumberPrecision(precision);
  303. stream.setRealNumberNotation(QTextStream::FixedNotation);
  304. for (unsigned i = 0; i < 4; ++i)
  305. {
  306. stream << m_mat[i] << " " << m_mat[i + 4] << " " << m_mat[i + 8] << " " << m_mat[i + 12] << endl;
  307. }
  308. return (fp.error() == QFile::NoError);
  309. }
  310. //! Loads matrix from an ASCII file
  311. /** \param filename input file name
  312. ***/
  313. virtual bool fromAsciiFile(QString filename)
  314. {
  315. QFile fp(filename);
  316. if (!fp.open(QFile::ReadOnly | QFile::Text))
  317. return false;
  318. QTextStream stream(&fp);
  319. for (unsigned i = 0; i < 4; ++i)
  320. {
  321. stream >> m_mat[i ];
  322. stream >> m_mat[i + 4];
  323. stream >> m_mat[i + 8];
  324. stream >> m_mat[i + 12];
  325. }
  326. internalRescale();
  327. return (fp.error() == QFile::NoError);
  328. }
  329. //! Returns the rotation component around X only
  330. ccGLMatrixTpl<T> xRotation() const
  331. {
  332. ccGLMatrixTpl<T> newRotMat;
  333. newRotMat.toIdentity();
  334. //we use a specific Euler angles convention here
  335. if (CC_MAT_R13 >= 1)
  336. {
  337. //simpler/faster to ignore this (very) specific case!
  338. return newRotMat;
  339. }
  340. T phi = -asin(CC_MAT_R13);
  341. T cos_phi = cos(phi);
  342. T theta = atan2(CC_MAT_R23 / cos_phi, CC_MAT_R33 / cos_phi);
  343. newRotMat.CC_MAT_R22 = newRotMat.CC_MAT_R33 = cos(theta);
  344. newRotMat.CC_MAT_R32 = newRotMat.CC_MAT_R23 = sin(theta);
  345. newRotMat.CC_MAT_R23 *= static_cast<T>(-1);
  346. newRotMat.setTranslation(getTranslation());
  347. return newRotMat;
  348. }
  349. //! Returns the rotation component around Y only
  350. ccGLMatrixTpl<T> yRotation() const
  351. {
  352. ccGLMatrixTpl<T> newRotMat;
  353. newRotMat.toIdentity();
  354. //we use a specific Euler angles convention here
  355. if (CC_MAT_R32 >= 1)
  356. {
  357. //simpler/faster to ignore this (very) specific case!
  358. return newRotMat;
  359. }
  360. T theta = asin(CC_MAT_R32);
  361. T cos_theta = cos(theta);
  362. T phi = atan2(-CC_MAT_R31 / cos_theta, CC_MAT_R33 / cos_theta);
  363. newRotMat.CC_MAT_R11 = newRotMat.CC_MAT_R33 = cos(phi);
  364. newRotMat.CC_MAT_R31 = newRotMat.CC_MAT_R13 = sin(phi);
  365. newRotMat.CC_MAT_R31 *= static_cast<T>(-1);
  366. newRotMat.setTranslation(getTranslation());
  367. return newRotMat;
  368. }
  369. //! Returns the rotation component around Z only
  370. ccGLMatrixTpl<T> zRotation() const
  371. {
  372. //we can use the standard Euler angles convention here
  373. T phi, theta, psi;
  374. Vector3Tpl<T> Tr;
  375. getParameters(phi, theta, psi, Tr);
  376. assert(Tr.norm2() == 0);
  377. ccGLMatrixTpl<T> newRotMat;
  378. newRotMat.initFromParameters(phi, 0, 0, Tr);
  379. return newRotMat;
  380. }
  381. //! Clears matrix
  382. /** Matrix is set to 0.
  383. **/
  384. inline virtual void toZero() { memset(m_mat, 0, OPENGL_MATRIX_SIZE * sizeof(T)); }
  385. //! Sets matrix to identity
  386. inline virtual void toIdentity() { toZero(); CC_MAT_R11 = CC_MAT_R22 = CC_MAT_R33 = CC_MAT_R44 = static_cast<T>(1); }
  387. //! Returns whether this matrix is equal to identity
  388. inline virtual bool isIdentity() const
  389. {
  390. for (unsigned l = 0; l < 4; ++l) //lines
  391. {
  392. for (unsigned c = 0; c < 4; ++c) //columns
  393. {
  394. if (m_mat[c * 4 + l] != static_cast<T>(l == c ? 1 : 0))
  395. return false;
  396. }
  397. }
  398. return true;
  399. }
  400. //! Clears translation
  401. /** Translation is set to (0,0,0).
  402. **/
  403. inline void clearTranslation() { CC_MAT_R14 = CC_MAT_R24 = CC_MAT_R34 = 0; }
  404. //! Inits transformation from a rotation axis, an angle and a translation
  405. /** \param[in] alpha_rad rotation angle (in radians)
  406. \param[in] axis3D rotation axis
  407. \param[in] t3D translation
  408. **/
  409. void initFromParameters(T alpha_rad,
  410. const Vector3Tpl<T>& axis3D,
  411. const Vector3Tpl<T>& t3D)
  412. {
  413. T cos_t = cos(alpha_rad);
  414. T sin_t = sin(alpha_rad);
  415. T inv_cos_t = static_cast<T>(1) - cos_t;
  416. //normalize rotation axis
  417. Vector3Tpl<T> uAxis3D = axis3D;
  418. uAxis3D.normalize();
  419. const T& l1 = uAxis3D.x;
  420. const T& l2 = uAxis3D.y;
  421. const T& l3 = uAxis3D.z;
  422. T l1_inv_cos_t = l1 * inv_cos_t;
  423. T l3_inv_cos_t = l3 * inv_cos_t;
  424. //1st column
  425. CC_MAT_R11 = cos_t + l1 * l1_inv_cos_t;
  426. CC_MAT_R21 = l2 * l1_inv_cos_t + l3 * sin_t;
  427. CC_MAT_R31 = l3 * l1_inv_cos_t - l2 * sin_t;
  428. CC_MAT_R41 = 0;
  429. //2nd column
  430. CC_MAT_R12 = l2 * l1_inv_cos_t - l3 * sin_t;
  431. CC_MAT_R22 = cos_t + l2 * l2*inv_cos_t;
  432. CC_MAT_R32 = l2 * l3_inv_cos_t + l1 * sin_t;
  433. CC_MAT_R42 = 0;
  434. //3rd column
  435. CC_MAT_R13 = l3 * l1_inv_cos_t + l2 * sin_t;
  436. CC_MAT_R23 = l2 * l3_inv_cos_t - l1 * sin_t;
  437. CC_MAT_R33 = cos_t + l3 * l3_inv_cos_t;
  438. CC_MAT_R43 = 0;
  439. //4th column
  440. CC_MAT_R14 = t3D.x;
  441. CC_MAT_R24 = t3D.y;
  442. CC_MAT_R34 = t3D.z;
  443. CC_MAT_R44 = static_cast<T>(1);
  444. }
  445. //! Inits transformation from 3 rotation angles and a translation
  446. /** See http://en.wikipedia.org/wiki/Euler_angles (Tait-Bryan Z1Y2X3)
  447. \param[in] phi_rad Phi angle (in radians)
  448. \param[in] theta_rad Theta angle (in radians)
  449. \param[in] psi_rad Psi angle (in radians)
  450. \param[in] t3D translation
  451. \param[in] scale rotation scale
  452. **/
  453. void initFromParameters( T phi_rad,
  454. T theta_rad,
  455. T psi_rad,
  456. const Vector3Tpl<T>& t3D)
  457. {
  458. T c1 = cos(phi_rad);
  459. T c2 = cos(theta_rad);
  460. T c3 = cos(psi_rad);
  461. T s1 = sin(phi_rad);
  462. T s2 = sin(theta_rad);
  463. T s3 = sin(psi_rad);
  464. //1st column
  465. CC_MAT_R11 = c2 * c1;
  466. CC_MAT_R21 = c2 * s1;
  467. CC_MAT_R31 = -s2;
  468. CC_MAT_R41 = 0;
  469. //2nd column
  470. CC_MAT_R12 = s3 * s2*c1 - c3 * s1;
  471. CC_MAT_R22 = s3 * s2*s1 + c3 * c1;
  472. CC_MAT_R32 = s3 * c2;
  473. CC_MAT_R42 = 0;
  474. //3rd column
  475. CC_MAT_R13 = c3 * s2*c1 + s3 * s1;
  476. CC_MAT_R23 = c3 * s2*s1 - s3 * c1;
  477. CC_MAT_R33 = c3 * c2;
  478. CC_MAT_R43 = 0;
  479. //4th column
  480. CC_MAT_R14 = t3D.x;
  481. CC_MAT_R24 = t3D.y;
  482. CC_MAT_R34 = t3D.z;
  483. CC_MAT_R44 = static_cast<T>(1);
  484. }
  485. //! Returns equivalent parameters: a rotation axis, an angle and a translation
  486. /** \param[out] alpha_rad rotation angle in radians (in [0;pi])
  487. \param[out] axis3D unit rotation axis
  488. \param[out] t3D translation
  489. \param[out] scale [optional] scale
  490. **/
  491. void getParameters( T& alpha_rad,
  492. Vector3Tpl<T>& axis3D,
  493. Vector3Tpl<T>& t3D,
  494. T* scale = nullptr) const
  495. {
  496. T trace = CC_MAT_R11 + CC_MAT_R22 + CC_MAT_R33;
  497. // we arbitrarily consider the first column to read the scale
  498. Vector3Tpl<T> rotX = getColumnAsVec3D(0);
  499. T _scale = rotX.norm();
  500. if (scale)
  501. {
  502. *scale = _scale;
  503. }
  504. if (_scale != static_cast<T>(1) && CCCoreLib::GreaterThanEpsilon(_scale))
  505. {
  506. trace /= _scale;
  507. }
  508. T cos_t = (trace - 1) / 2;
  509. if (std::abs(cos_t) <= 1)
  510. {
  511. alpha_rad = acos(cos_t); //result in [0;pi]
  512. }
  513. else
  514. {
  515. alpha_rad = 0;
  516. }
  517. axis3D.x = CC_MAT_R32 - CC_MAT_R23;
  518. axis3D.y = CC_MAT_R13 - CC_MAT_R31;
  519. axis3D.z = CC_MAT_R21 - CC_MAT_R12;
  520. //normalize axis
  521. T n2 = axis3D.norm2();
  522. if (CCCoreLib::GreaterThanEpsilon(n2))
  523. {
  524. axis3D /= sqrt(n2);
  525. }
  526. else
  527. {
  528. //axis is too small!
  529. axis3D = Vector3Tpl<T>(0, 0, 1);
  530. }
  531. t3D.x = CC_MAT_R14;
  532. t3D.y = CC_MAT_R24;
  533. t3D.z = CC_MAT_R34;
  534. }
  535. //! Returns equivalent parameters: 3 rotation angles and a translation
  536. /** See http://en.wikipedia.org/wiki/Euler_angles (Tait-Bryan Z1Y2X3)
  537. \param[out] phi_rad Phi angle (in radians)
  538. \param[out] theta_rad Theta angle (in radians)
  539. \param[out] psi_rad Psi angle (in radians)
  540. \param[out] t3D translation
  541. \param[out] scale [optional] scale
  542. **/
  543. void getParameters( T &phi_rad,
  544. T &theta_rad,
  545. T &psi_rad,
  546. Vector3Tpl<T>& t3D,
  547. T* scale = nullptr) const
  548. {
  549. Vector3Tpl<T> rotX = getColumnAsVec3D(0);
  550. Vector3Tpl<T> rotY = getColumnAsVec3D(1);
  551. Vector3Tpl<T> rotZ = getColumnAsVec3D(2);
  552. // we arbitrarily consider the first column to read the scale
  553. T _scale = rotX.norm();
  554. if (scale)
  555. {
  556. *scale = _scale;
  557. }
  558. if (_scale != static_cast<T>(1) && CCCoreLib::GreaterThanEpsilon(_scale))
  559. {
  560. rotX /= _scale;
  561. rotY /= _scale;
  562. rotZ /= _scale;
  563. }
  564. if (std::abs(rotX.z) != 1)
  565. {
  566. theta_rad = -asin(rotX.z);
  567. T cos_theta = cos(theta_rad);
  568. psi_rad = atan2(rotY.z / cos_theta, rotZ.z / cos_theta);
  569. phi_rad = atan2(rotX.y / cos_theta, rotX.x / cos_theta);
  570. //Other solution
  571. //theta = M_PI + asin(rotX.z);
  572. //T cos_theta = cos(theta);
  573. //psi = atan2(rotY.z / cos_theta, rotZ.z / cos_theta);
  574. //phi = atan2(rotX.y / cos_theta, rotX.x / cos_theta);
  575. }
  576. else
  577. {
  578. phi_rad = 0;
  579. if (rotX.z == -1)
  580. {
  581. theta_rad = static_cast<T>(M_PI_2);
  582. psi_rad = atan2(rotY.x, rotZ.x);
  583. }
  584. else
  585. {
  586. theta_rad = -static_cast<T>(M_PI_2);
  587. psi_rad = -atan2(rotY.x, rotZ.x);
  588. }
  589. }
  590. t3D.x = CC_MAT_R14;
  591. t3D.y = CC_MAT_R24;
  592. t3D.z = CC_MAT_R34;
  593. }
  594. //! Returns a pointer to internal data
  595. inline T* data() { return m_mat; }
  596. //! Returns a const pointer to internal data
  597. inline const T* data() const { return m_mat; }
  598. //! Returns a pointer to internal translation
  599. /** Translation corresponds to the beginning of the
  600. third column of the matrix.
  601. **/
  602. inline T* getTranslation() { return m_mat+12; }
  603. //! Returns a const pointer to internal translation
  604. /** Translation corresponds to the beginning of the
  605. third column of the matrix.
  606. **/
  607. inline const T* getTranslation() const { return m_mat+12; }
  608. //! Returns a copy of the translation as a CCVector3
  609. /** \return translation vector
  610. **/
  611. inline Vector3Tpl<T> getTranslationAsVec3D() const { return getColumnAsVec3D(3); }
  612. //! Sets translation (float version)
  613. /** \param Tr 3D vector **/
  614. inline void setTranslation(const Vector3Tpl<float>& Tr) { CC_MAT_R14 = static_cast<T>(Tr.x); CC_MAT_R24 = static_cast<T>(Tr.y); CC_MAT_R34 = static_cast<T>(Tr.z); }
  615. //! Sets translation (double version)
  616. /** \param Tr 3D vector **/
  617. inline void setTranslation(const Vector3Tpl<double>& Tr) { CC_MAT_R14 = static_cast<T>(Tr.x); CC_MAT_R24 = static_cast<T>(Tr.y); CC_MAT_R34 = static_cast<T>(Tr.z); }
  618. //! Sets translation from a float array
  619. /** \param Tr 3D vector as a float array
  620. **/
  621. void setTranslation(const float Tr[3]) { CC_MAT_R14 = static_cast<T>(Tr[0]); CC_MAT_R24 = static_cast<T>(Tr[1]); CC_MAT_R34 = static_cast<T>(Tr[2]); }
  622. //! Sets translation from a double array
  623. /** \param Tr 3D vector as a double array
  624. **/
  625. void setTranslation(const double Tr[3]) { CC_MAT_R14 = static_cast<T>(Tr[0]); CC_MAT_R24 = static_cast<T>(Tr[1]); CC_MAT_R34 = static_cast<T>(Tr[2]); }
  626. //! Returns a pointer to a given column
  627. /** \param index column index (between 0 and 3)
  628. \return pointer to the first element of the corresponding column
  629. **/
  630. inline T* getColumn(unsigned index) { return m_mat + (index << 2); }
  631. //! Returns a const pointer to a given column
  632. /** \param index column index (between 0 and 3)
  633. \return pointer to the first element of the corresponding column
  634. **/
  635. inline const T* getColumn(unsigned index) const { return m_mat + (index << 2); }
  636. //! Returns a copy of a given column as a CCVector3
  637. /** 4th value is ignored.
  638. \param index column index (between 0 and 3)
  639. \return copy of the three first elements of the corresponding column
  640. **/
  641. inline Vector3Tpl<T> getColumnAsVec3D(unsigned index) const { return Vector3Tpl<T>::fromArray(getColumn(index)); }
  642. //! Sets the content of a given column
  643. /** \param index column index (between 0 and 3)
  644. \param v new column values
  645. **/
  646. inline void setColumn(unsigned index, const Vector3Tpl<T>& v) { T* col = m_mat + (index << 2); col[0] = v.x; col[1] = v.y; col[2] = v.z; }
  647. //! Sets the content of a given column
  648. /** \param index column index (between 0 and 3)
  649. \param v new column values
  650. **/
  651. inline void setColumn(unsigned index, const Tuple4Tpl<T>& v) { T* col = m_mat + (index << 2); col[0] = v.x; col[1] = v.y; col[2] = v.z; col[3] = v.w; }
  652. //! Multiplication by a matrix operator
  653. ccGLMatrixTpl<T> operator * (const ccGLMatrixTpl<T>& mat) const
  654. {
  655. ccGLMatrixTpl<T> result;
  656. const T* A = m_mat;
  657. const T* B = mat.m_mat;
  658. T* C = result.m_mat;
  659. for (unsigned j = 0; j < 4; ++j, B += 4)
  660. for (unsigned i = 0; i < 4; ++i)
  661. *C++ = A[i] * B[0] + A[i + 4] * B[1] + A[i + 8] * B[2] + A[i + 12] * B[3];
  662. return result;
  663. }
  664. //! Multiplication by a vector operator (float version)
  665. inline Vector3Tpl<float> operator * (const Vector3Tpl<float>& vec) const { return Vector3Tpl<float>(applyX(vec), applyY(vec), applyZ(vec)); }
  666. //! Multiplication by a vector operator (double version)
  667. inline Vector3Tpl<double> operator * (const Vector3Tpl<double>& vec) const { return Vector3Tpl<double>(applyX(vec), applyY(vec), applyZ(vec)); }
  668. //! Multiplication by a 4D vector operator (float version)
  669. inline Tuple4Tpl<float> operator * (const Tuple4Tpl<float>& vec) const { return Tuple4Tpl<float>(applyX(vec), applyY(vec), applyZ(vec), applyW(vec)); }
  670. //! Multiplication by a 4D vector operator (double version)
  671. inline Tuple4Tpl<double> operator * (const Tuple4Tpl<double>& vec) const { return Tuple4Tpl<double>(applyX(vec), applyY(vec), applyZ(vec), applyW(vec)); }
  672. //! (in place) Addition operator
  673. ccGLMatrixTpl<T>& operator += (const ccGLMatrixTpl<T>& mat)
  674. {
  675. for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i)
  676. m_mat[i] += mat.m_mat[i];
  677. return (*this);
  678. }
  679. //! (in place) Difference operator
  680. ccGLMatrixTpl<T>& operator -= (const ccGLMatrixTpl<T>& mat)
  681. {
  682. for (unsigned i = 0; i < OPENGL_MATRIX_SIZE; ++i)
  683. m_mat[i] -= mat.m_mat[i];
  684. return (*this);
  685. }
  686. //! (in place) Multiplication operator
  687. ccGLMatrixTpl<T>& operator *= (const ccGLMatrixTpl<T>& mat)
  688. {
  689. (*this) = (*this) * mat;
  690. return (*this);
  691. }
  692. //! (in place) Forward translation operator (float version)
  693. ccGLMatrixTpl<T>& operator += (const Vector3Tpl<float>& Tr)
  694. {
  695. CC_MAT_R14 += static_cast<T>(Tr.x);
  696. CC_MAT_R24 += static_cast<T>(Tr.y);
  697. CC_MAT_R34 += static_cast<T>(Tr.z);
  698. return (*this);
  699. }
  700. //! (in place) Forward translation operator (double version)
  701. ccGLMatrixTpl<T>& operator += (const Vector3Tpl<double>& Tr)
  702. {
  703. CC_MAT_R14 += static_cast<T>(Tr.x);
  704. CC_MAT_R24 += static_cast<T>(Tr.y);
  705. CC_MAT_R34 += static_cast<T>(Tr.z);
  706. return (*this);
  707. }
  708. //! (in place) Backward translation operator (float version)
  709. ccGLMatrixTpl<T>& operator -= (const Vector3Tpl<float>& Tr)
  710. {
  711. CC_MAT_R14 -= static_cast<T>(Tr.x);
  712. CC_MAT_R24 -= static_cast<T>(Tr.y);
  713. CC_MAT_R34 -= static_cast<T>(Tr.z);
  714. return (*this);
  715. }
  716. //! (in place) Backward translation operator (double version)
  717. ccGLMatrixTpl<T>& operator -= (const Vector3Tpl<double>& Tr)
  718. {
  719. CC_MAT_R14 -= static_cast<T>(Tr.x);
  720. CC_MAT_R24 -= static_cast<T>(Tr.y);
  721. CC_MAT_R34 -= static_cast<T>(Tr.z);
  722. return (*this);
  723. }
  724. //! Returns the value at a given position
  725. T operator () (unsigned row, unsigned col) const
  726. {
  727. return m_mat[(col << 2) + row];
  728. }
  729. //! Applies transformation to a 3D vector (in place) - float version
  730. /** Input vector is directly modified after calling this method
  731. **/
  732. inline void apply(Vector3Tpl<float>& vec) const { vec = (*this)*vec; }
  733. //! Applies transformation to a 3D vector (in place) - double version
  734. /** Input vector is directly modified after calling this method
  735. **/
  736. inline void apply(Vector3Tpl<double>& vec) const { vec = (*this)*vec; }
  737. //! Applies transformation to a 4D vector (in place) - float version
  738. /** Input vector is directly modified after calling this method
  739. **/
  740. inline void apply(Tuple4Tpl<float>& vec) const { vec = (*this)*vec; }
  741. //! Applies transformation to a 3D vector (in place) - double version
  742. /** Input vector is directly modified after calling this method
  743. **/
  744. inline void apply(Tuple4Tpl<double>& vec) const { vec = (*this)*vec; }
  745. //! Get the resulting transformation along X dimension (float version)
  746. inline float applyX(const Vector3Tpl<float>& vec) const
  747. {
  748. return static_cast<float>(CC_MAT_R11) * vec.x
  749. + static_cast<float>(CC_MAT_R12) * vec.y
  750. + static_cast<float>(CC_MAT_R13) * vec.z
  751. + static_cast<float>(CC_MAT_R14);
  752. }
  753. //! Get the resulting transformation along X dimension (double version)
  754. inline double applyX(const Vector3Tpl<double>& vec) const
  755. {
  756. return static_cast<double>(CC_MAT_R11) * vec.x
  757. + static_cast<double>(CC_MAT_R12) * vec.y
  758. + static_cast<double>(CC_MAT_R13) * vec.z
  759. + static_cast<double>(CC_MAT_R14);
  760. }
  761. //! Get the resulting transformation along Y dimension (float version)
  762. inline float applyY(const Vector3Tpl<float>& vec) const
  763. {
  764. return static_cast<float>(CC_MAT_R21) * vec.x
  765. + static_cast<float>(CC_MAT_R22) * vec.y
  766. + static_cast<float>(CC_MAT_R23) * vec.z
  767. + static_cast<float>(CC_MAT_R24);
  768. }
  769. //! Get the resulting transformation along Y dimension (double version)
  770. inline double applyY(const Vector3Tpl<double>& vec) const
  771. {
  772. return static_cast<double>(CC_MAT_R21) * vec.x
  773. + static_cast<double>(CC_MAT_R22) * vec.y
  774. + static_cast<double>(CC_MAT_R23) * vec.z
  775. + static_cast<double>(CC_MAT_R24);
  776. }
  777. //! Get the resulting transformation along Z dimension (float version)
  778. inline float applyZ(const Vector3Tpl<float>& vec) const
  779. {
  780. return static_cast<float>(CC_MAT_R31) * vec.x
  781. + static_cast<float>(CC_MAT_R32) * vec.y
  782. + static_cast<float>(CC_MAT_R33) * vec.z
  783. + static_cast<float>(CC_MAT_R34);
  784. }
  785. //! Get the resulting transformation along Z dimension (double version)
  786. inline double applyZ(const Vector3Tpl<double>& vec) const
  787. {
  788. return static_cast<double>(CC_MAT_R31) * vec.x
  789. + static_cast<double>(CC_MAT_R32) * vec.y
  790. + static_cast<double>(CC_MAT_R33) * vec.z
  791. + static_cast<double>(CC_MAT_R34);
  792. }
  793. //! Get the resulting transformation along X dimension (float version)
  794. inline float applyX(const Tuple4Tpl<float>& vec) const
  795. {
  796. return static_cast<float>(CC_MAT_R11) * vec.x
  797. + static_cast<float>(CC_MAT_R12) * vec.y
  798. + static_cast<float>(CC_MAT_R13) * vec.z
  799. + static_cast<float>(CC_MAT_R14) * vec.w;
  800. }
  801. //! Get the resulting transformation along X dimension (double version)
  802. inline double applyX(const Tuple4Tpl<double>& vec) const
  803. {
  804. return static_cast<double>(CC_MAT_R11) * vec.x
  805. + static_cast<double>(CC_MAT_R12) * vec.y
  806. + static_cast<double>(CC_MAT_R13) * vec.z
  807. + static_cast<double>(CC_MAT_R14) * vec.w;
  808. }
  809. //! Get the resulting transformation along Y dimension (float version)
  810. inline float applyY(const Tuple4Tpl<float>& vec) const
  811. {
  812. return static_cast<float>(CC_MAT_R21) * vec.x
  813. + static_cast<float>(CC_MAT_R22) * vec.y
  814. + static_cast<float>(CC_MAT_R23) * vec.z
  815. + static_cast<float>(CC_MAT_R24) * vec.w;
  816. }
  817. //! Get the resulting transformation along Y dimension (double version)
  818. inline double applyY(const Tuple4Tpl<double>& vec) const
  819. {
  820. return static_cast<double>(CC_MAT_R21) * vec.x
  821. + static_cast<double>(CC_MAT_R22) * vec.y
  822. + static_cast<double>(CC_MAT_R23) * vec.z
  823. + static_cast<double>(CC_MAT_R24) * vec.w;
  824. }
  825. //! Get the resulting transformation along Z dimension (float version)
  826. inline float applyZ(const Tuple4Tpl<float>& vec) const
  827. {
  828. return static_cast<float>(CC_MAT_R31) * vec.x
  829. + static_cast<float>(CC_MAT_R32) * vec.y
  830. + static_cast<float>(CC_MAT_R33) * vec.z
  831. + static_cast<float>(CC_MAT_R34) * vec.w;
  832. }
  833. //! Get the resulting transformation along Z dimension (double version)
  834. inline double applyZ(const Tuple4Tpl<double>& vec) const
  835. {
  836. return static_cast<double>(CC_MAT_R31) * vec.x
  837. + static_cast<double>(CC_MAT_R32) * vec.y
  838. + static_cast<double>(CC_MAT_R33) * vec.z
  839. + static_cast<double>(CC_MAT_R34) * vec.w;
  840. }
  841. //! Get the resulting transformation along the 4th dimension (float version)
  842. inline float applyW(const Tuple4Tpl<float>& vec) const
  843. {
  844. return static_cast<float>(CC_MAT_R41) * vec.x
  845. + static_cast<float>(CC_MAT_R42) * vec.y
  846. + static_cast<float>(CC_MAT_R43) * vec.z
  847. + static_cast<float>(CC_MAT_R44) * vec.w;
  848. }
  849. //! Get the resulting transformation along the 4th dimension (double version)
  850. inline double applyW(const Tuple4Tpl<double>& vec) const
  851. {
  852. return static_cast<double>(CC_MAT_R41) * vec.x
  853. + static_cast<double>(CC_MAT_R42) * vec.y
  854. + static_cast<double>(CC_MAT_R43) * vec.z
  855. + static_cast<double>(CC_MAT_R44) * vec.w;
  856. }
  857. //! Applies rotation only to a 3D vector (in place) - float version
  858. /** Input vector is directly modified after calling this method
  859. **/
  860. inline void applyRotation(Vector3Tpl<float>& vec) const
  861. {
  862. float vx = vec.x;
  863. float vy = vec.y;
  864. float vz = vec.z;
  865. vec.x = static_cast<float>(CC_MAT_R11) * vx
  866. + static_cast<float>(CC_MAT_R12) * vy
  867. + static_cast<float>(CC_MAT_R13) * vz;
  868. vec.y = static_cast<float>(CC_MAT_R21) * vx
  869. + static_cast<float>(CC_MAT_R22) * vy
  870. + static_cast<float>(CC_MAT_R23) * vz;
  871. vec.z = static_cast<float>(CC_MAT_R31) * vx
  872. + static_cast<float>(CC_MAT_R32) * vy
  873. + static_cast<float>(CC_MAT_R33) * vz;
  874. }
  875. //! Applies rotation only to a 3D vector (in place) - double version
  876. /** Input vector is directly modified after calling this method
  877. **/
  878. inline void applyRotation(Vector3Tpl<double>& vec) const
  879. {
  880. double vx = vec.x;
  881. double vy = vec.y;
  882. double vz = vec.z;
  883. vec.x = static_cast<double>(CC_MAT_R11) * vx
  884. + static_cast<double>(CC_MAT_R12) * vy
  885. + static_cast<double>(CC_MAT_R13) * vz;
  886. vec.y = static_cast<double>(CC_MAT_R21) * vx
  887. + static_cast<double>(CC_MAT_R22) * vy
  888. + static_cast<double>(CC_MAT_R23) * vz;
  889. vec.z = static_cast<double>(CC_MAT_R31) * vx
  890. + static_cast<double>(CC_MAT_R32) * vy
  891. + static_cast<double>(CC_MAT_R33) * vz;
  892. }
  893. //! Applies rotation only to a 3D vector (in place) - float version
  894. /** Input array is directly modified after calling this method
  895. **/
  896. inline void applyRotation(float vec[3]) const
  897. {
  898. float vx = vec[0];
  899. float vy = vec[1];
  900. float vz = vec[2];
  901. vec[0] = static_cast<float>(CC_MAT_R11) * vx
  902. + static_cast<float>(CC_MAT_R12) * vy
  903. + static_cast<float>(CC_MAT_R13) * vz;
  904. vec[1] = static_cast<float>(CC_MAT_R21) * vx
  905. + static_cast<float>(CC_MAT_R22) * vy
  906. + static_cast<float>(CC_MAT_R23) * vz;
  907. vec[2] = static_cast<float>(CC_MAT_R31) * vx
  908. + static_cast<float>(CC_MAT_R32) * vy
  909. + static_cast<float>(CC_MAT_R33) * vz;
  910. }
  911. //! Applies rotation only to a 3D vector (in place) - float version
  912. /** Input array is directly modified after calling this method
  913. **/
  914. inline void applyRotation(double vec[3]) const
  915. {
  916. double vx = vec[0];
  917. double vy = vec[1];
  918. double vz = vec[2];
  919. vec[0] = static_cast<double>(CC_MAT_R11) * vx
  920. + static_cast<double>(CC_MAT_R12) * vy
  921. + static_cast<double>(CC_MAT_R13) * vz;
  922. vec[1] = static_cast<double>(CC_MAT_R21) * vx
  923. + static_cast<double>(CC_MAT_R22) * vy
  924. + static_cast<double>(CC_MAT_R23) * vz;
  925. vec[2] = static_cast<double>(CC_MAT_R31) * vx
  926. + static_cast<double>(CC_MAT_R32) * vy
  927. + static_cast<double>(CC_MAT_R33) * vz;
  928. }
  929. //! Shifts rotation center
  930. /** Warning, this method only applies a shift (i.e. relatively to the
  931. current rotation center). This is not a way to set an
  932. absolute rotation center 'directly'.
  933. **/
  934. void shiftRotationCenter(const Vector3Tpl<T>& vec)
  935. {
  936. //R(X-vec)+T+vec = R(X)+T + vec-R(vec)
  937. Vector3Tpl<T> Rvec = vec;
  938. applyRotation(Rvec);
  939. *this += (vec - Rvec);
  940. }
  941. //! Transposes matrix (in place)
  942. void transpose()
  943. {
  944. std::swap(CC_MAT_R21, CC_MAT_R12);
  945. std::swap(CC_MAT_R31, CC_MAT_R13);
  946. std::swap(CC_MAT_R41, CC_MAT_R14);
  947. std::swap(CC_MAT_R32, CC_MAT_R23);
  948. std::swap(CC_MAT_R42, CC_MAT_R24);
  949. std::swap(CC_MAT_R43, CC_MAT_R34);
  950. }
  951. //! Returns transposed matrix
  952. ccGLMatrixTpl<T> transposed() const
  953. {
  954. ccGLMatrixTpl<T> t(*this);
  955. t.transpose();
  956. return t;
  957. }
  958. //! Inverts transformation
  959. void invert()
  960. {
  961. //inverse scale as well!
  962. //we use the columns norm (considering is should be 1 for an 'unscaled' matrix)
  963. T sx2 = getColumnAsVec3D(0).norm2();
  964. T sy2 = getColumnAsVec3D(1).norm2();
  965. T sz2 = getColumnAsVec3D(2).norm2();
  966. //we invert rotation
  967. std::swap(CC_MAT_R21, CC_MAT_R12);
  968. std::swap(CC_MAT_R31, CC_MAT_R13);
  969. std::swap(CC_MAT_R32, CC_MAT_R23);
  970. if (std::abs(sx2) > std::numeric_limits<T>::epsilon() && sx2 != 1)
  971. {
  972. CC_MAT_R11 /= sx2;
  973. CC_MAT_R21 /= sx2;
  974. CC_MAT_R31 /= sx2;
  975. }
  976. if (std::abs(sy2) > std::numeric_limits<T>::epsilon() && sy2 != 1)
  977. {
  978. CC_MAT_R12 /= sy2;
  979. CC_MAT_R22 /= sy2;
  980. CC_MAT_R32 /= sy2;
  981. }
  982. if (std::abs(sz2) > std::numeric_limits<T>::epsilon() && sz2 != 1)
  983. {
  984. CC_MAT_R13 /= sz2;
  985. CC_MAT_R23 /= sz2;
  986. CC_MAT_R33 /= sz2;
  987. }
  988. //eventually we invert translation
  989. applyRotation(m_mat + 12);
  990. double w = CC_MAT_R44;
  991. if (std::abs(w) > std::numeric_limits<T>::epsilon())
  992. {
  993. CC_MAT_R14 = -CC_MAT_R14 / w;
  994. CC_MAT_R24 = -CC_MAT_R24 / w;
  995. CC_MAT_R34 = -CC_MAT_R34 / w;
  996. CC_MAT_R44 = 1.0 / w;
  997. }
  998. else
  999. {
  1000. assert(false);
  1001. CC_MAT_R14 = -CC_MAT_R14;
  1002. CC_MAT_R24 = -CC_MAT_R24;
  1003. CC_MAT_R34 = -CC_MAT_R34;
  1004. }
  1005. }
  1006. //! Returns inverse transformation
  1007. ccGLMatrixTpl<T> inverse() const
  1008. {
  1009. ccGLMatrixTpl<T> t(*this);
  1010. t.invert();
  1011. return t;
  1012. }
  1013. //! Scales the rotation and the translation (but not the the last row)
  1014. /** \param coef scaling coef.
  1015. **/
  1016. inline void scale(T coef)
  1017. {
  1018. CC_MAT_R11 *= coef; CC_MAT_R12 *= coef; CC_MAT_R13 *= coef; CC_MAT_R14 *= coef;
  1019. CC_MAT_R21 *= coef; CC_MAT_R22 *= coef; CC_MAT_R23 *= coef; CC_MAT_R24 *= coef;
  1020. CC_MAT_R31 *= coef; CC_MAT_R32 *= coef; CC_MAT_R33 *= coef; CC_MAT_R34 *= coef;
  1021. }
  1022. //! Scales the rotation part of the matrix
  1023. /** \param coef scaling coef.
  1024. **/
  1025. inline void scaleRotation(T coef)
  1026. {
  1027. CC_MAT_R11 *= coef; CC_MAT_R12 *= coef; CC_MAT_R13 *= coef;
  1028. CC_MAT_R21 *= coef; CC_MAT_R22 *= coef; CC_MAT_R23 *= coef;
  1029. CC_MAT_R31 *= coef; CC_MAT_R32 *= coef; CC_MAT_R33 *= coef;
  1030. }
  1031. //! Scales one row of the matrix
  1032. /** \param rowIndex tow index (0-3)
  1033. \param coef scaling coef.
  1034. **/
  1035. void scaleRow(unsigned rowIndex, T coef)
  1036. {
  1037. assert(rowIndex < 4);
  1038. m_mat[ rowIndex] *= coef;
  1039. m_mat[ 4+rowIndex] *= coef;
  1040. m_mat[ 8+rowIndex] *= coef;
  1041. m_mat[12+rowIndex] *= coef;
  1042. }
  1043. //! Scales one column of the matrix
  1044. /** \warning The last row is never scaled
  1045. \param colIndex column index (0-3)
  1046. \param coef scaling coef.
  1047. **/
  1048. void scaleColumn(unsigned colIndex, T coef)
  1049. {
  1050. assert(colIndex < 4);
  1051. T* col = getColumn(colIndex);
  1052. col[0] *= coef;
  1053. col[1] *= coef;
  1054. col[2] *= coef;
  1055. //col[3] *= coef;
  1056. }
  1057. //inherited from ccSerializableObject
  1058. bool isSerializable() const override
  1059. {
  1060. return true;
  1061. }
  1062. //inherited from ccSerializableObject
  1063. bool toFile(QFile& out, short dataVersion) const override
  1064. {
  1065. assert(out.isOpen() && (out.openMode() & QIODevice::WriteOnly));
  1066. if (dataVersion < 20)
  1067. {
  1068. assert(false);
  1069. return false;
  1070. }
  1071. //data (dataVersion>=20)
  1072. if (out.write(reinterpret_cast<const char*>(m_mat), sizeof(T)*OPENGL_MATRIX_SIZE) < 0)
  1073. {
  1074. return WriteError();
  1075. }
  1076. return true;
  1077. }
  1078. //inherited from ccSerializableObject
  1079. bool fromFile(QFile& in, short dataVersion, int flags, LoadedIDMap& oldToNewIDMap) override
  1080. {
  1081. assert(in.isOpen() && (in.openMode() & QIODevice::ReadOnly));
  1082. if (dataVersion < 20)
  1083. return CorruptError();
  1084. //data (dataVersion>=20)
  1085. if (in.read(reinterpret_cast<char*>(m_mat), sizeof(T)*OPENGL_MATRIX_SIZE) < 0)
  1086. return ReadError();
  1087. return true;
  1088. }
  1089. //inherited from ccSerializableObject
  1090. short minimumFileVersion() const override
  1091. {
  1092. return 20;
  1093. }
  1094. protected:
  1095. //! Transfers the homogenous coordinate (scale) to the whole matrix
  1096. void internalRescale()
  1097. {
  1098. if (CC_MAT_R44 != static_cast<T>(1) && CCCoreLib::GreaterThanEpsilon(CC_MAT_R44))
  1099. {
  1100. scaleRotation(1.0 / CC_MAT_R44);
  1101. CC_MAT_R44 = static_cast<T>(1);
  1102. }
  1103. }
  1104. //! Internal 4x4 GL-style matrix data
  1105. T m_mat[OPENGL_MATRIX_SIZE];
  1106. };