ImathMatrixAlgo.h 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425
  1. ///////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
  4. // Digital Ltd. LLC
  5. //
  6. // All rights reserved.
  7. //
  8. // Redistribution and use in source and binary forms, with or without
  9. // modification, are permitted provided that the following conditions are
  10. // met:
  11. // * Redistributions of source code must retain the above copyright
  12. // notice, this list of conditions and the following disclaimer.
  13. // * Redistributions in binary form must reproduce the above
  14. // copyright notice, this list of conditions and the following disclaimer
  15. // in the documentation and/or other materials provided with the
  16. // distribution.
  17. // * Neither the name of Industrial Light & Magic nor the names of
  18. // its contributors may be used to endorse or promote products derived
  19. // from this software without specific prior written permission.
  20. //
  21. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  25. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  26. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  27. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  28. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  29. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  31. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32. //
  33. ///////////////////////////////////////////////////////////////////////////
  34. #ifndef INCLUDED_IMATHMATRIXALGO_H
  35. #define INCLUDED_IMATHMATRIXALGO_H
  36. //-------------------------------------------------------------------------
  37. //
  38. // This file contains algorithms applied to or in conjunction with
  39. // transformation matrices (Imath::Matrix33 and Imath::Matrix44).
  40. // The assumption made is that these functions are called much less
  41. // often than the basic point functions or these functions require
  42. // more support classes.
  43. //
  44. // This file also defines a few predefined constant matrices.
  45. //
  46. //-------------------------------------------------------------------------
  47. #include "ImathExport.h"
  48. #include "ImathMatrix.h"
  49. #include "ImathQuat.h"
  50. #include "ImathEuler.h"
  51. #include "ImathExc.h"
  52. #include "ImathVec.h"
  53. #include "ImathLimits.h"
  54. #include "ImathNamespace.h"
  55. #include <math.h>
  56. IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
  57. //------------------
  58. // Identity matrices
  59. //------------------
  60. IMATH_EXPORT_CONST M33f identity33f;
  61. IMATH_EXPORT_CONST M44f identity44f;
  62. IMATH_EXPORT_CONST M33d identity33d;
  63. IMATH_EXPORT_CONST M44d identity44d;
  64. //----------------------------------------------------------------------
  65. // Extract scale, shear, rotation, and translation values from a matrix:
  66. //
  67. // Notes:
  68. //
  69. // This implementation follows the technique described in the paper by
  70. // Spencer W. Thomas in the Graphics Gems II article: "Decomposing a
  71. // Matrix into Simple Transformations", p. 320.
  72. //
  73. // - Some of the functions below have an optional exc parameter
  74. // that determines the functions' behavior when the matrix'
  75. // scaling is very close to zero:
  76. //
  77. // If exc is true, the functions throw an Imath::ZeroScale exception.
  78. //
  79. // If exc is false:
  80. //
  81. // extractScaling (m, s) returns false, s is invalid
  82. // sansScaling (m) returns m
  83. // removeScaling (m) returns false, m is unchanged
  84. // sansScalingAndShear (m) returns m
  85. // removeScalingAndShear (m) returns false, m is unchanged
  86. // extractAndRemoveScalingAndShear (m, s, h)
  87. // returns false, m is unchanged,
  88. // (sh) are invalid
  89. // checkForZeroScaleInRow () returns false
  90. // extractSHRT (m, s, h, r, t) returns false, (shrt) are invalid
  91. //
  92. // - Functions extractEuler(), extractEulerXYZ() and extractEulerZYX()
  93. // assume that the matrix does not include shear or non-uniform scaling,
  94. // but they do not examine the matrix to verify this assumption.
  95. // Matrices with shear or non-uniform scaling are likely to produce
  96. // meaningless results. Therefore, you should use the
  97. // removeScalingAndShear() routine, if necessary, prior to calling
  98. // extractEuler...() .
  99. //
  100. // - All functions assume that the matrix does not include perspective
  101. // transformation(s), but they do not examine the matrix to verify
  102. // this assumption. Matrices with perspective transformations are
  103. // likely to produce meaningless results.
  104. //
  105. //----------------------------------------------------------------------
  106. //
  107. // Declarations for 4x4 matrix.
  108. //
  109. template <class T> bool extractScaling
  110. (const Matrix44<T> &mat,
  111. Vec3<T> &scl,
  112. bool exc = true);
  113. template <class T> Matrix44<T> sansScaling (const Matrix44<T> &mat,
  114. bool exc = true);
  115. template <class T> bool removeScaling
  116. (Matrix44<T> &mat,
  117. bool exc = true);
  118. template <class T> bool extractScalingAndShear
  119. (const Matrix44<T> &mat,
  120. Vec3<T> &scl,
  121. Vec3<T> &shr,
  122. bool exc = true);
  123. template <class T> Matrix44<T> sansScalingAndShear
  124. (const Matrix44<T> &mat,
  125. bool exc = true);
  126. template <class T> void sansScalingAndShear
  127. (Matrix44<T> &result,
  128. const Matrix44<T> &mat,
  129. bool exc = true);
  130. template <class T> bool removeScalingAndShear
  131. (Matrix44<T> &mat,
  132. bool exc = true);
  133. template <class T> bool extractAndRemoveScalingAndShear
  134. (Matrix44<T> &mat,
  135. Vec3<T> &scl,
  136. Vec3<T> &shr,
  137. bool exc = true);
  138. template <class T> void extractEulerXYZ
  139. (const Matrix44<T> &mat,
  140. Vec3<T> &rot);
  141. template <class T> void extractEulerZYX
  142. (const Matrix44<T> &mat,
  143. Vec3<T> &rot);
  144. template <class T> Quat<T> extractQuat (const Matrix44<T> &mat);
  145. template <class T> bool extractSHRT
  146. (const Matrix44<T> &mat,
  147. Vec3<T> &s,
  148. Vec3<T> &h,
  149. Vec3<T> &r,
  150. Vec3<T> &t,
  151. bool exc /*= true*/,
  152. typename Euler<T>::Order rOrder);
  153. template <class T> bool extractSHRT
  154. (const Matrix44<T> &mat,
  155. Vec3<T> &s,
  156. Vec3<T> &h,
  157. Vec3<T> &r,
  158. Vec3<T> &t,
  159. bool exc = true);
  160. template <class T> bool extractSHRT
  161. (const Matrix44<T> &mat,
  162. Vec3<T> &s,
  163. Vec3<T> &h,
  164. Euler<T> &r,
  165. Vec3<T> &t,
  166. bool exc = true);
  167. //
  168. // Internal utility function.
  169. //
  170. template <class T> bool checkForZeroScaleInRow
  171. (const T &scl,
  172. const Vec3<T> &row,
  173. bool exc = true);
  174. template <class T> Matrix44<T> outerProduct
  175. ( const Vec4<T> &a,
  176. const Vec4<T> &b);
  177. //
  178. // Returns a matrix that rotates "fromDirection" vector to "toDirection"
  179. // vector.
  180. //
  181. template <class T> Matrix44<T> rotationMatrix (const Vec3<T> &fromDirection,
  182. const Vec3<T> &toDirection);
  183. //
  184. // Returns a matrix that rotates the "fromDir" vector
  185. // so that it points towards "toDir". You may also
  186. // specify that you want the up vector to be pointing
  187. // in a certain direction "upDir".
  188. //
  189. template <class T> Matrix44<T> rotationMatrixWithUpDir
  190. (const Vec3<T> &fromDir,
  191. const Vec3<T> &toDir,
  192. const Vec3<T> &upDir);
  193. //
  194. // Constructs a matrix that rotates the z-axis so that it
  195. // points towards "targetDir". You must also specify
  196. // that you want the up vector to be pointing in a
  197. // certain direction "upDir".
  198. //
  199. // Notes: The following degenerate cases are handled:
  200. // (a) when the directions given by "toDir" and "upDir"
  201. // are parallel or opposite;
  202. // (the direction vectors must have a non-zero cross product)
  203. // (b) when any of the given direction vectors have zero length
  204. //
  205. template <class T> void alignZAxisWithTargetDir
  206. (Matrix44<T> &result,
  207. Vec3<T> targetDir,
  208. Vec3<T> upDir);
  209. // Compute an orthonormal direct frame from : a position, an x axis direction and a normal to the y axis
  210. // If the x axis and normal are perpendicular, then the normal will have the same direction as the z axis.
  211. // Inputs are :
  212. // -the position of the frame
  213. // -the x axis direction of the frame
  214. // -a normal to the y axis of the frame
  215. // Return is the orthonormal frame
  216. template <class T> Matrix44<T> computeLocalFrame( const Vec3<T>& p,
  217. const Vec3<T>& xDir,
  218. const Vec3<T>& normal);
  219. // Add a translate/rotate/scale offset to an input frame
  220. // and put it in another frame of reference
  221. // Inputs are :
  222. // - input frame
  223. // - translate offset
  224. // - rotate offset in degrees
  225. // - scale offset
  226. // - frame of reference
  227. // Output is the offsetted frame
  228. template <class T> Matrix44<T> addOffset( const Matrix44<T>& inMat,
  229. const Vec3<T>& tOffset,
  230. const Vec3<T>& rOffset,
  231. const Vec3<T>& sOffset,
  232. const Vec3<T>& ref);
  233. // Compute Translate/Rotate/Scale matrix from matrix A with the Rotate/Scale of Matrix B
  234. // Inputs are :
  235. // -keepRotateA : if true keep rotate from matrix A, use B otherwise
  236. // -keepScaleA : if true keep scale from matrix A, use B otherwise
  237. // -Matrix A
  238. // -Matrix B
  239. // Return Matrix A with tweaked rotation/scale
  240. template <class T> Matrix44<T> computeRSMatrix( bool keepRotateA,
  241. bool keepScaleA,
  242. const Matrix44<T>& A,
  243. const Matrix44<T>& B);
  244. //----------------------------------------------------------------------
  245. //
  246. // Declarations for 3x3 matrix.
  247. //
  248. template <class T> bool extractScaling
  249. (const Matrix33<T> &mat,
  250. Vec2<T> &scl,
  251. bool exc = true);
  252. template <class T> Matrix33<T> sansScaling (const Matrix33<T> &mat,
  253. bool exc = true);
  254. template <class T> bool removeScaling
  255. (Matrix33<T> &mat,
  256. bool exc = true);
  257. template <class T> bool extractScalingAndShear
  258. (const Matrix33<T> &mat,
  259. Vec2<T> &scl,
  260. T &h,
  261. bool exc = true);
  262. template <class T> Matrix33<T> sansScalingAndShear
  263. (const Matrix33<T> &mat,
  264. bool exc = true);
  265. template <class T> bool removeScalingAndShear
  266. (Matrix33<T> &mat,
  267. bool exc = true);
  268. template <class T> bool extractAndRemoveScalingAndShear
  269. (Matrix33<T> &mat,
  270. Vec2<T> &scl,
  271. T &shr,
  272. bool exc = true);
  273. template <class T> void extractEuler
  274. (const Matrix33<T> &mat,
  275. T &rot);
  276. template <class T> bool extractSHRT (const Matrix33<T> &mat,
  277. Vec2<T> &s,
  278. T &h,
  279. T &r,
  280. Vec2<T> &t,
  281. bool exc = true);
  282. template <class T> bool checkForZeroScaleInRow
  283. (const T &scl,
  284. const Vec2<T> &row,
  285. bool exc = true);
  286. template <class T> Matrix33<T> outerProduct
  287. ( const Vec3<T> &a,
  288. const Vec3<T> &b);
  289. //-----------------------------------------------------------------------------
  290. // Implementation for 4x4 Matrix
  291. //------------------------------
  292. template <class T>
  293. bool
  294. extractScaling (const Matrix44<T> &mat, Vec3<T> &scl, bool exc)
  295. {
  296. Vec3<T> shr;
  297. Matrix44<T> M (mat);
  298. if (! extractAndRemoveScalingAndShear (M, scl, shr, exc))
  299. return false;
  300. return true;
  301. }
  302. template <class T>
  303. Matrix44<T>
  304. sansScaling (const Matrix44<T> &mat, bool exc)
  305. {
  306. Vec3<T> scl;
  307. Vec3<T> shr;
  308. Vec3<T> rot;
  309. Vec3<T> tran;
  310. if (! extractSHRT (mat, scl, shr, rot, tran, exc))
  311. return mat;
  312. Matrix44<T> M;
  313. M.translate (tran);
  314. M.rotate (rot);
  315. M.shear (shr);
  316. return M;
  317. }
  318. template <class T>
  319. bool
  320. removeScaling (Matrix44<T> &mat, bool exc)
  321. {
  322. Vec3<T> scl;
  323. Vec3<T> shr;
  324. Vec3<T> rot;
  325. Vec3<T> tran;
  326. if (! extractSHRT (mat, scl, shr, rot, tran, exc))
  327. return false;
  328. mat.makeIdentity ();
  329. mat.translate (tran);
  330. mat.rotate (rot);
  331. mat.shear (shr);
  332. return true;
  333. }
  334. template <class T>
  335. bool
  336. extractScalingAndShear (const Matrix44<T> &mat,
  337. Vec3<T> &scl, Vec3<T> &shr, bool exc)
  338. {
  339. Matrix44<T> M (mat);
  340. if (! extractAndRemoveScalingAndShear (M, scl, shr, exc))
  341. return false;
  342. return true;
  343. }
  344. template <class T>
  345. Matrix44<T>
  346. sansScalingAndShear (const Matrix44<T> &mat, bool exc)
  347. {
  348. Vec3<T> scl;
  349. Vec3<T> shr;
  350. Matrix44<T> M (mat);
  351. if (! extractAndRemoveScalingAndShear (M, scl, shr, exc))
  352. return mat;
  353. return M;
  354. }
  355. template <class T>
  356. void
  357. sansScalingAndShear (Matrix44<T> &result, const Matrix44<T> &mat, bool exc)
  358. {
  359. Vec3<T> scl;
  360. Vec3<T> shr;
  361. if (! extractAndRemoveScalingAndShear (result, scl, shr, exc))
  362. result = mat;
  363. }
  364. template <class T>
  365. bool
  366. removeScalingAndShear (Matrix44<T> &mat, bool exc)
  367. {
  368. Vec3<T> scl;
  369. Vec3<T> shr;
  370. if (! extractAndRemoveScalingAndShear (mat, scl, shr, exc))
  371. return false;
  372. return true;
  373. }
  374. template <class T>
  375. bool
  376. extractAndRemoveScalingAndShear (Matrix44<T> &mat,
  377. Vec3<T> &scl, Vec3<T> &shr, bool exc)
  378. {
  379. //
  380. // This implementation follows the technique described in the paper by
  381. // Spencer W. Thomas in the Graphics Gems II article: "Decomposing a
  382. // Matrix into Simple Transformations", p. 320.
  383. //
  384. Vec3<T> row[3];
  385. row[0] = Vec3<T> (mat[0][0], mat[0][1], mat[0][2]);
  386. row[1] = Vec3<T> (mat[1][0], mat[1][1], mat[1][2]);
  387. row[2] = Vec3<T> (mat[2][0], mat[2][1], mat[2][2]);
  388. T maxVal = 0;
  389. for (int i=0; i < 3; i++)
  390. for (int j=0; j < 3; j++)
  391. if (IMATH_INTERNAL_NAMESPACE::abs (row[i][j]) > maxVal)
  392. maxVal = IMATH_INTERNAL_NAMESPACE::abs (row[i][j]);
  393. //
  394. // We normalize the 3x3 matrix here.
  395. // It was noticed that this can improve numerical stability significantly,
  396. // especially when many of the upper 3x3 matrix's coefficients are very
  397. // close to zero; we correct for this step at the end by multiplying the
  398. // scaling factors by maxVal at the end (shear and rotation are not
  399. // affected by the normalization).
  400. if (maxVal != 0)
  401. {
  402. for (int i=0; i < 3; i++)
  403. if (! checkForZeroScaleInRow (maxVal, row[i], exc))
  404. return false;
  405. else
  406. row[i] /= maxVal;
  407. }
  408. // Compute X scale factor.
  409. scl.x = row[0].length ();
  410. if (! checkForZeroScaleInRow (scl.x, row[0], exc))
  411. return false;
  412. // Normalize first row.
  413. row[0] /= scl.x;
  414. // An XY shear factor will shear the X coord. as the Y coord. changes.
  415. // There are 6 combinations (XY, XZ, YZ, YX, ZX, ZY), although we only
  416. // extract the first 3 because we can effect the last 3 by shearing in
  417. // XY, XZ, YZ combined rotations and scales.
  418. //
  419. // shear matrix < 1, YX, ZX, 0,
  420. // XY, 1, ZY, 0,
  421. // XZ, YZ, 1, 0,
  422. // 0, 0, 0, 1 >
  423. // Compute XY shear factor and make 2nd row orthogonal to 1st.
  424. shr[0] = row[0].dot (row[1]);
  425. row[1] -= shr[0] * row[0];
  426. // Now, compute Y scale.
  427. scl.y = row[1].length ();
  428. if (! checkForZeroScaleInRow (scl.y, row[1], exc))
  429. return false;
  430. // Normalize 2nd row and correct the XY shear factor for Y scaling.
  431. row[1] /= scl.y;
  432. shr[0] /= scl.y;
  433. // Compute XZ and YZ shears, orthogonalize 3rd row.
  434. shr[1] = row[0].dot (row[2]);
  435. row[2] -= shr[1] * row[0];
  436. shr[2] = row[1].dot (row[2]);
  437. row[2] -= shr[2] * row[1];
  438. // Next, get Z scale.
  439. scl.z = row[2].length ();
  440. if (! checkForZeroScaleInRow (scl.z, row[2], exc))
  441. return false;
  442. // Normalize 3rd row and correct the XZ and YZ shear factors for Z scaling.
  443. row[2] /= scl.z;
  444. shr[1] /= scl.z;
  445. shr[2] /= scl.z;
  446. // At this point, the upper 3x3 matrix in mat is orthonormal.
  447. // Check for a coordinate system flip. If the determinant
  448. // is less than zero, then negate the matrix and the scaling factors.
  449. if (row[0].dot (row[1].cross (row[2])) < 0)
  450. for (int i=0; i < 3; i++)
  451. {
  452. scl[i] *= -1;
  453. row[i] *= -1;
  454. }
  455. // Copy over the orthonormal rows into the returned matrix.
  456. // The upper 3x3 matrix in mat is now a rotation matrix.
  457. for (int i=0; i < 3; i++)
  458. {
  459. mat[i][0] = row[i][0];
  460. mat[i][1] = row[i][1];
  461. mat[i][2] = row[i][2];
  462. }
  463. // Correct the scaling factors for the normalization step that we
  464. // performed above; shear and rotation are not affected by the
  465. // normalization.
  466. scl *= maxVal;
  467. return true;
  468. }
  469. template <class T>
  470. void
  471. extractEulerXYZ (const Matrix44<T> &mat, Vec3<T> &rot)
  472. {
  473. //
  474. // Normalize the local x, y and z axes to remove scaling.
  475. //
  476. Vec3<T> i (mat[0][0], mat[0][1], mat[0][2]);
  477. Vec3<T> j (mat[1][0], mat[1][1], mat[1][2]);
  478. Vec3<T> k (mat[2][0], mat[2][1], mat[2][2]);
  479. i.normalize();
  480. j.normalize();
  481. k.normalize();
  482. Matrix44<T> M (i[0], i[1], i[2], 0,
  483. j[0], j[1], j[2], 0,
  484. k[0], k[1], k[2], 0,
  485. 0, 0, 0, 1);
  486. //
  487. // Extract the first angle, rot.x.
  488. //
  489. rot.x = Math<T>::atan2 (M[1][2], M[2][2]);
  490. //
  491. // Remove the rot.x rotation from M, so that the remaining
  492. // rotation, N, is only around two axes, and gimbal lock
  493. // cannot occur.
  494. //
  495. Matrix44<T> N;
  496. N.rotate (Vec3<T> (-rot.x, 0, 0));
  497. N = N * M;
  498. //
  499. // Extract the other two angles, rot.y and rot.z, from N.
  500. //
  501. T cy = Math<T>::sqrt (N[0][0]*N[0][0] + N[0][1]*N[0][1]);
  502. rot.y = Math<T>::atan2 (-N[0][2], cy);
  503. rot.z = Math<T>::atan2 (-N[1][0], N[1][1]);
  504. }
  505. template <class T>
  506. void
  507. extractEulerZYX (const Matrix44<T> &mat, Vec3<T> &rot)
  508. {
  509. //
  510. // Normalize the local x, y and z axes to remove scaling.
  511. //
  512. Vec3<T> i (mat[0][0], mat[0][1], mat[0][2]);
  513. Vec3<T> j (mat[1][0], mat[1][1], mat[1][2]);
  514. Vec3<T> k (mat[2][0], mat[2][1], mat[2][2]);
  515. i.normalize();
  516. j.normalize();
  517. k.normalize();
  518. Matrix44<T> M (i[0], i[1], i[2], 0,
  519. j[0], j[1], j[2], 0,
  520. k[0], k[1], k[2], 0,
  521. 0, 0, 0, 1);
  522. //
  523. // Extract the first angle, rot.x.
  524. //
  525. rot.x = -Math<T>::atan2 (M[1][0], M[0][0]);
  526. //
  527. // Remove the x rotation from M, so that the remaining
  528. // rotation, N, is only around two axes, and gimbal lock
  529. // cannot occur.
  530. //
  531. Matrix44<T> N;
  532. N.rotate (Vec3<T> (0, 0, -rot.x));
  533. N = N * M;
  534. //
  535. // Extract the other two angles, rot.y and rot.z, from N.
  536. //
  537. T cy = Math<T>::sqrt (N[2][2]*N[2][2] + N[2][1]*N[2][1]);
  538. rot.y = -Math<T>::atan2 (-N[2][0], cy);
  539. rot.z = -Math<T>::atan2 (-N[1][2], N[1][1]);
  540. }
  541. template <class T>
  542. Quat<T>
  543. extractQuat (const Matrix44<T> &mat)
  544. {
  545. Matrix44<T> rot;
  546. T tr, s;
  547. T q[4];
  548. int i, j, k;
  549. Quat<T> quat;
  550. int nxt[3] = {1, 2, 0};
  551. tr = mat[0][0] + mat[1][1] + mat[2][2];
  552. // check the diagonal
  553. if (tr > 0.0) {
  554. s = Math<T>::sqrt (tr + T(1.0));
  555. quat.r = s / T(2.0);
  556. s = T(0.5) / s;
  557. quat.v.x = (mat[1][2] - mat[2][1]) * s;
  558. quat.v.y = (mat[2][0] - mat[0][2]) * s;
  559. quat.v.z = (mat[0][1] - mat[1][0]) * s;
  560. }
  561. else {
  562. // diagonal is negative
  563. i = 0;
  564. if (mat[1][1] > mat[0][0])
  565. i=1;
  566. if (mat[2][2] > mat[i][i])
  567. i=2;
  568. j = nxt[i];
  569. k = nxt[j];
  570. s = Math<T>::sqrt ((mat[i][i] - (mat[j][j] + mat[k][k])) + T(1.0));
  571. q[i] = s * T(0.5);
  572. if (s != T(0.0))
  573. s = T(0.5) / s;
  574. q[3] = (mat[j][k] - mat[k][j]) * s;
  575. q[j] = (mat[i][j] + mat[j][i]) * s;
  576. q[k] = (mat[i][k] + mat[k][i]) * s;
  577. quat.v.x = q[0];
  578. quat.v.y = q[1];
  579. quat.v.z = q[2];
  580. quat.r = q[3];
  581. }
  582. return quat;
  583. }
  584. template <class T>
  585. bool
  586. extractSHRT (const Matrix44<T> &mat,
  587. Vec3<T> &s,
  588. Vec3<T> &h,
  589. Vec3<T> &r,
  590. Vec3<T> &t,
  591. bool exc /* = true */ ,
  592. typename Euler<T>::Order rOrder /* = Euler<T>::XYZ */ )
  593. {
  594. Matrix44<T> rot;
  595. rot = mat;
  596. if (! extractAndRemoveScalingAndShear (rot, s, h, exc))
  597. return false;
  598. extractEulerXYZ (rot, r);
  599. t.x = mat[3][0];
  600. t.y = mat[3][1];
  601. t.z = mat[3][2];
  602. if (rOrder != Euler<T>::XYZ)
  603. {
  604. IMATH_INTERNAL_NAMESPACE::Euler<T> eXYZ (r, IMATH_INTERNAL_NAMESPACE::Euler<T>::XYZ);
  605. IMATH_INTERNAL_NAMESPACE::Euler<T> e (eXYZ, rOrder);
  606. r = e.toXYZVector ();
  607. }
  608. return true;
  609. }
  610. template <class T>
  611. bool
  612. extractSHRT (const Matrix44<T> &mat,
  613. Vec3<T> &s,
  614. Vec3<T> &h,
  615. Vec3<T> &r,
  616. Vec3<T> &t,
  617. bool exc)
  618. {
  619. return extractSHRT(mat, s, h, r, t, exc, IMATH_INTERNAL_NAMESPACE::Euler<T>::XYZ);
  620. }
  621. template <class T>
  622. bool
  623. extractSHRT (const Matrix44<T> &mat,
  624. Vec3<T> &s,
  625. Vec3<T> &h,
  626. Euler<T> &r,
  627. Vec3<T> &t,
  628. bool exc /* = true */)
  629. {
  630. return extractSHRT (mat, s, h, r, t, exc, r.order ());
  631. }
  632. template <class T>
  633. bool
  634. checkForZeroScaleInRow (const T& scl,
  635. const Vec3<T> &row,
  636. bool exc /* = true */ )
  637. {
  638. for (int i = 0; i < 3; i++)
  639. {
  640. if ((abs (scl) < 1 && abs (row[i]) >= limits<T>::max() * abs (scl)))
  641. {
  642. if (exc)
  643. throw IMATH_INTERNAL_NAMESPACE::ZeroScaleExc ("Cannot remove zero scaling "
  644. "from matrix.");
  645. else
  646. return false;
  647. }
  648. }
  649. return true;
  650. }
  651. template <class T>
  652. Matrix44<T>
  653. outerProduct (const Vec4<T> &a, const Vec4<T> &b )
  654. {
  655. return Matrix44<T> (a.x*b.x, a.x*b.y, a.x*b.z, a.x*b.w,
  656. a.y*b.x, a.y*b.y, a.y*b.z, a.x*b.w,
  657. a.z*b.x, a.z*b.y, a.z*b.z, a.x*b.w,
  658. a.w*b.x, a.w*b.y, a.w*b.z, a.w*b.w);
  659. }
  660. template <class T>
  661. Matrix44<T>
  662. rotationMatrix (const Vec3<T> &from, const Vec3<T> &to)
  663. {
  664. Quat<T> q;
  665. q.setRotation(from, to);
  666. return q.toMatrix44();
  667. }
  668. template <class T>
  669. Matrix44<T>
  670. rotationMatrixWithUpDir (const Vec3<T> &fromDir,
  671. const Vec3<T> &toDir,
  672. const Vec3<T> &upDir)
  673. {
  674. //
  675. // The goal is to obtain a rotation matrix that takes
  676. // "fromDir" to "toDir". We do this in two steps and
  677. // compose the resulting rotation matrices;
  678. // (a) rotate "fromDir" into the z-axis
  679. // (b) rotate the z-axis into "toDir"
  680. //
  681. // The from direction must be non-zero; but we allow zero to and up dirs.
  682. if (fromDir.length () == 0)
  683. return Matrix44<T> ();
  684. else
  685. {
  686. Matrix44<T> zAxis2FromDir( IMATH_INTERNAL_NAMESPACE::UNINITIALIZED );
  687. alignZAxisWithTargetDir (zAxis2FromDir, fromDir, Vec3<T> (0, 1, 0));
  688. Matrix44<T> fromDir2zAxis = zAxis2FromDir.transposed ();
  689. Matrix44<T> zAxis2ToDir( IMATH_INTERNAL_NAMESPACE::UNINITIALIZED );
  690. alignZAxisWithTargetDir (zAxis2ToDir, toDir, upDir);
  691. return fromDir2zAxis * zAxis2ToDir;
  692. }
  693. }
  694. template <class T>
  695. void
  696. alignZAxisWithTargetDir (Matrix44<T> &result, Vec3<T> targetDir, Vec3<T> upDir)
  697. {
  698. //
  699. // Ensure that the target direction is non-zero.
  700. //
  701. if ( targetDir.length () == 0 )
  702. targetDir = Vec3<T> (0, 0, 1);
  703. //
  704. // Ensure that the up direction is non-zero.
  705. //
  706. if ( upDir.length () == 0 )
  707. upDir = Vec3<T> (0, 1, 0);
  708. //
  709. // Check for degeneracies. If the upDir and targetDir are parallel
  710. // or opposite, then compute a new, arbitrary up direction that is
  711. // not parallel or opposite to the targetDir.
  712. //
  713. if (upDir.cross (targetDir).length () == 0)
  714. {
  715. upDir = targetDir.cross (Vec3<T> (1, 0, 0));
  716. if (upDir.length() == 0)
  717. upDir = targetDir.cross(Vec3<T> (0, 0, 1));
  718. }
  719. //
  720. // Compute the x-, y-, and z-axis vectors of the new coordinate system.
  721. //
  722. Vec3<T> targetPerpDir = upDir.cross (targetDir);
  723. Vec3<T> targetUpDir = targetDir.cross (targetPerpDir);
  724. //
  725. // Rotate the x-axis into targetPerpDir (row 0),
  726. // rotate the y-axis into targetUpDir (row 1),
  727. // rotate the z-axis into targetDir (row 2).
  728. //
  729. Vec3<T> row[3];
  730. row[0] = targetPerpDir.normalized ();
  731. row[1] = targetUpDir .normalized ();
  732. row[2] = targetDir .normalized ();
  733. result.x[0][0] = row[0][0];
  734. result.x[0][1] = row[0][1];
  735. result.x[0][2] = row[0][2];
  736. result.x[0][3] = (T)0;
  737. result.x[1][0] = row[1][0];
  738. result.x[1][1] = row[1][1];
  739. result.x[1][2] = row[1][2];
  740. result.x[1][3] = (T)0;
  741. result.x[2][0] = row[2][0];
  742. result.x[2][1] = row[2][1];
  743. result.x[2][2] = row[2][2];
  744. result.x[2][3] = (T)0;
  745. result.x[3][0] = (T)0;
  746. result.x[3][1] = (T)0;
  747. result.x[3][2] = (T)0;
  748. result.x[3][3] = (T)1;
  749. }
  750. // Compute an orthonormal direct frame from : a position, an x axis direction and a normal to the y axis
  751. // If the x axis and normal are perpendicular, then the normal will have the same direction as the z axis.
  752. // Inputs are :
  753. // -the position of the frame
  754. // -the x axis direction of the frame
  755. // -a normal to the y axis of the frame
  756. // Return is the orthonormal frame
  757. template <class T>
  758. Matrix44<T>
  759. computeLocalFrame( const Vec3<T>& p,
  760. const Vec3<T>& xDir,
  761. const Vec3<T>& normal)
  762. {
  763. Vec3<T> _xDir(xDir);
  764. Vec3<T> x = _xDir.normalize();
  765. Vec3<T> y = (normal % x).normalize();
  766. Vec3<T> z = (x % y).normalize();
  767. Matrix44<T> L;
  768. L[0][0] = x[0];
  769. L[0][1] = x[1];
  770. L[0][2] = x[2];
  771. L[0][3] = 0.0;
  772. L[1][0] = y[0];
  773. L[1][1] = y[1];
  774. L[1][2] = y[2];
  775. L[1][3] = 0.0;
  776. L[2][0] = z[0];
  777. L[2][1] = z[1];
  778. L[2][2] = z[2];
  779. L[2][3] = 0.0;
  780. L[3][0] = p[0];
  781. L[3][1] = p[1];
  782. L[3][2] = p[2];
  783. L[3][3] = 1.0;
  784. return L;
  785. }
  786. // Add a translate/rotate/scale offset to an input frame
  787. // and put it in another frame of reference
  788. // Inputs are :
  789. // - input frame
  790. // - translate offset
  791. // - rotate offset in degrees
  792. // - scale offset
  793. // - frame of reference
  794. // Output is the offsetted frame
  795. template <class T>
  796. Matrix44<T>
  797. addOffset( const Matrix44<T>& inMat,
  798. const Vec3<T>& tOffset,
  799. const Vec3<T>& rOffset,
  800. const Vec3<T>& sOffset,
  801. const Matrix44<T>& ref)
  802. {
  803. Matrix44<T> O;
  804. Vec3<T> _rOffset(rOffset);
  805. _rOffset *= M_PI / 180.0;
  806. O.rotate (_rOffset);
  807. O[3][0] = tOffset[0];
  808. O[3][1] = tOffset[1];
  809. O[3][2] = tOffset[2];
  810. Matrix44<T> S;
  811. S.scale (sOffset);
  812. Matrix44<T> X = S * O * inMat * ref;
  813. return X;
  814. }
  815. // Compute Translate/Rotate/Scale matrix from matrix A with the Rotate/Scale of Matrix B
  816. // Inputs are :
  817. // -keepRotateA : if true keep rotate from matrix A, use B otherwise
  818. // -keepScaleA : if true keep scale from matrix A, use B otherwise
  819. // -Matrix A
  820. // -Matrix B
  821. // Return Matrix A with tweaked rotation/scale
  822. template <class T>
  823. Matrix44<T>
  824. computeRSMatrix( bool keepRotateA,
  825. bool keepScaleA,
  826. const Matrix44<T>& A,
  827. const Matrix44<T>& B)
  828. {
  829. Vec3<T> as, ah, ar, at;
  830. extractSHRT (A, as, ah, ar, at);
  831. Vec3<T> bs, bh, br, bt;
  832. extractSHRT (B, bs, bh, br, bt);
  833. if (!keepRotateA)
  834. ar = br;
  835. if (!keepScaleA)
  836. as = bs;
  837. Matrix44<T> mat;
  838. mat.makeIdentity();
  839. mat.translate (at);
  840. mat.rotate (ar);
  841. mat.scale (as);
  842. return mat;
  843. }
  844. //-----------------------------------------------------------------------------
  845. // Implementation for 3x3 Matrix
  846. //------------------------------
  847. template <class T>
  848. bool
  849. extractScaling (const Matrix33<T> &mat, Vec2<T> &scl, bool exc)
  850. {
  851. T shr;
  852. Matrix33<T> M (mat);
  853. if (! extractAndRemoveScalingAndShear (M, scl, shr, exc))
  854. return false;
  855. return true;
  856. }
  857. template <class T>
  858. Matrix33<T>
  859. sansScaling (const Matrix33<T> &mat, bool exc)
  860. {
  861. Vec2<T> scl;
  862. T shr;
  863. T rot;
  864. Vec2<T> tran;
  865. if (! extractSHRT (mat, scl, shr, rot, tran, exc))
  866. return mat;
  867. Matrix33<T> M;
  868. M.translate (tran);
  869. M.rotate (rot);
  870. M.shear (shr);
  871. return M;
  872. }
  873. template <class T>
  874. bool
  875. removeScaling (Matrix33<T> &mat, bool exc)
  876. {
  877. Vec2<T> scl;
  878. T shr;
  879. T rot;
  880. Vec2<T> tran;
  881. if (! extractSHRT (mat, scl, shr, rot, tran, exc))
  882. return false;
  883. mat.makeIdentity ();
  884. mat.translate (tran);
  885. mat.rotate (rot);
  886. mat.shear (shr);
  887. return true;
  888. }
  889. template <class T>
  890. bool
  891. extractScalingAndShear (const Matrix33<T> &mat, Vec2<T> &scl, T &shr, bool exc)
  892. {
  893. Matrix33<T> M (mat);
  894. if (! extractAndRemoveScalingAndShear (M, scl, shr, exc))
  895. return false;
  896. return true;
  897. }
  898. template <class T>
  899. Matrix33<T>
  900. sansScalingAndShear (const Matrix33<T> &mat, bool exc)
  901. {
  902. Vec2<T> scl;
  903. T shr;
  904. Matrix33<T> M (mat);
  905. if (! extractAndRemoveScalingAndShear (M, scl, shr, exc))
  906. return mat;
  907. return M;
  908. }
  909. template <class T>
  910. bool
  911. removeScalingAndShear (Matrix33<T> &mat, bool exc)
  912. {
  913. Vec2<T> scl;
  914. T shr;
  915. if (! extractAndRemoveScalingAndShear (mat, scl, shr, exc))
  916. return false;
  917. return true;
  918. }
  919. template <class T>
  920. bool
  921. extractAndRemoveScalingAndShear (Matrix33<T> &mat,
  922. Vec2<T> &scl, T &shr, bool exc)
  923. {
  924. Vec2<T> row[2];
  925. row[0] = Vec2<T> (mat[0][0], mat[0][1]);
  926. row[1] = Vec2<T> (mat[1][0], mat[1][1]);
  927. T maxVal = 0;
  928. for (int i=0; i < 2; i++)
  929. for (int j=0; j < 2; j++)
  930. if (IMATH_INTERNAL_NAMESPACE::abs (row[i][j]) > maxVal)
  931. maxVal = IMATH_INTERNAL_NAMESPACE::abs (row[i][j]);
  932. //
  933. // We normalize the 2x2 matrix here.
  934. // It was noticed that this can improve numerical stability significantly,
  935. // especially when many of the upper 2x2 matrix's coefficients are very
  936. // close to zero; we correct for this step at the end by multiplying the
  937. // scaling factors by maxVal at the end (shear and rotation are not
  938. // affected by the normalization).
  939. if (maxVal != 0)
  940. {
  941. for (int i=0; i < 2; i++)
  942. if (! checkForZeroScaleInRow (maxVal, row[i], exc))
  943. return false;
  944. else
  945. row[i] /= maxVal;
  946. }
  947. // Compute X scale factor.
  948. scl.x = row[0].length ();
  949. if (! checkForZeroScaleInRow (scl.x, row[0], exc))
  950. return false;
  951. // Normalize first row.
  952. row[0] /= scl.x;
  953. // An XY shear factor will shear the X coord. as the Y coord. changes.
  954. // There are 2 combinations (XY, YX), although we only extract the XY
  955. // shear factor because we can effect the an YX shear factor by
  956. // shearing in XY combined with rotations and scales.
  957. //
  958. // shear matrix < 1, YX, 0,
  959. // XY, 1, 0,
  960. // 0, 0, 1 >
  961. // Compute XY shear factor and make 2nd row orthogonal to 1st.
  962. shr = row[0].dot (row[1]);
  963. row[1] -= shr * row[0];
  964. // Now, compute Y scale.
  965. scl.y = row[1].length ();
  966. if (! checkForZeroScaleInRow (scl.y, row[1], exc))
  967. return false;
  968. // Normalize 2nd row and correct the XY shear factor for Y scaling.
  969. row[1] /= scl.y;
  970. shr /= scl.y;
  971. // At this point, the upper 2x2 matrix in mat is orthonormal.
  972. // Check for a coordinate system flip. If the determinant
  973. // is -1, then flip the rotation matrix and adjust the scale(Y)
  974. // and shear(XY) factors to compensate.
  975. if (row[0][0] * row[1][1] - row[0][1] * row[1][0] < 0)
  976. {
  977. row[1][0] *= -1;
  978. row[1][1] *= -1;
  979. scl[1] *= -1;
  980. shr *= -1;
  981. }
  982. // Copy over the orthonormal rows into the returned matrix.
  983. // The upper 2x2 matrix in mat is now a rotation matrix.
  984. for (int i=0; i < 2; i++)
  985. {
  986. mat[i][0] = row[i][0];
  987. mat[i][1] = row[i][1];
  988. }
  989. scl *= maxVal;
  990. return true;
  991. }
  992. template <class T>
  993. void
  994. extractEuler (const Matrix33<T> &mat, T &rot)
  995. {
  996. //
  997. // Normalize the local x and y axes to remove scaling.
  998. //
  999. Vec2<T> i (mat[0][0], mat[0][1]);
  1000. Vec2<T> j (mat[1][0], mat[1][1]);
  1001. i.normalize();
  1002. j.normalize();
  1003. //
  1004. // Extract the angle, rot.
  1005. //
  1006. rot = - Math<T>::atan2 (j[0], i[0]);
  1007. }
  1008. template <class T>
  1009. bool
  1010. extractSHRT (const Matrix33<T> &mat,
  1011. Vec2<T> &s,
  1012. T &h,
  1013. T &r,
  1014. Vec2<T> &t,
  1015. bool exc)
  1016. {
  1017. Matrix33<T> rot;
  1018. rot = mat;
  1019. if (! extractAndRemoveScalingAndShear (rot, s, h, exc))
  1020. return false;
  1021. extractEuler (rot, r);
  1022. t.x = mat[2][0];
  1023. t.y = mat[2][1];
  1024. return true;
  1025. }
  1026. template <class T>
  1027. bool
  1028. checkForZeroScaleInRow (const T& scl,
  1029. const Vec2<T> &row,
  1030. bool exc /* = true */ )
  1031. {
  1032. for (int i = 0; i < 2; i++)
  1033. {
  1034. if ((abs (scl) < 1 && abs (row[i]) >= limits<T>::max() * abs (scl)))
  1035. {
  1036. if (exc)
  1037. throw IMATH_INTERNAL_NAMESPACE::ZeroScaleExc (
  1038. "Cannot remove zero scaling from matrix.");
  1039. else
  1040. return false;
  1041. }
  1042. }
  1043. return true;
  1044. }
  1045. template <class T>
  1046. Matrix33<T>
  1047. outerProduct (const Vec3<T> &a, const Vec3<T> &b )
  1048. {
  1049. return Matrix33<T> (a.x*b.x, a.x*b.y, a.x*b.z,
  1050. a.y*b.x, a.y*b.y, a.y*b.z,
  1051. a.z*b.x, a.z*b.y, a.z*b.z );
  1052. }
  1053. // Computes the translation and rotation that brings the 'from' points
  1054. // as close as possible to the 'to' points under the Frobenius norm.
  1055. // To be more specific, let x be the matrix of 'from' points and y be
  1056. // the matrix of 'to' points, we want to find the matrix A of the form
  1057. // [ R t ]
  1058. // [ 0 1 ]
  1059. // that minimizes
  1060. // || (A*x - y)^T * W * (A*x - y) ||_F
  1061. // If doScaling is true, then a uniform scale is allowed also.
  1062. template <typename T>
  1063. IMATH_INTERNAL_NAMESPACE::M44d
  1064. procrustesRotationAndTranslation (const IMATH_INTERNAL_NAMESPACE::Vec3<T>* A, // From these
  1065. const IMATH_INTERNAL_NAMESPACE::Vec3<T>* B, // To these
  1066. const T* weights,
  1067. const size_t numPoints,
  1068. const bool doScaling = false);
  1069. // Unweighted:
  1070. template <typename T>
  1071. IMATH_INTERNAL_NAMESPACE::M44d
  1072. procrustesRotationAndTranslation (const IMATH_INTERNAL_NAMESPACE::Vec3<T>* A,
  1073. const IMATH_INTERNAL_NAMESPACE::Vec3<T>* B,
  1074. const size_t numPoints,
  1075. const bool doScaling = false);
  1076. // Compute the SVD of a 3x3 matrix using Jacobi transformations. This method
  1077. // should be quite accurate (competitive with LAPACK) even for poorly
  1078. // conditioned matrices, and because it has been written specifically for the
  1079. // 3x3/4x4 case it is much faster than calling out to LAPACK.
  1080. //
  1081. // The SVD of a 3x3/4x4 matrix A is defined as follows:
  1082. // A = U * S * V^T
  1083. // where S is the diagonal matrix of singular values and both U and V are
  1084. // orthonormal. By convention, the entries S are all positive and sorted from
  1085. // the largest to the smallest. However, some uses of this function may
  1086. // require that the matrix U*V^T have positive determinant; in this case, we
  1087. // may make the smallest singular value negative to ensure that this is
  1088. // satisfied.
  1089. //
  1090. // Currently only available for single- and double-precision matrices.
  1091. template <typename T>
  1092. void
  1093. jacobiSVD (const IMATH_INTERNAL_NAMESPACE::Matrix33<T>& A,
  1094. IMATH_INTERNAL_NAMESPACE::Matrix33<T>& U,
  1095. IMATH_INTERNAL_NAMESPACE::Vec3<T>& S,
  1096. IMATH_INTERNAL_NAMESPACE::Matrix33<T>& V,
  1097. const T tol = IMATH_INTERNAL_NAMESPACE::limits<T>::epsilon(),
  1098. const bool forcePositiveDeterminant = false);
  1099. template <typename T>
  1100. void
  1101. jacobiSVD (const IMATH_INTERNAL_NAMESPACE::Matrix44<T>& A,
  1102. IMATH_INTERNAL_NAMESPACE::Matrix44<T>& U,
  1103. IMATH_INTERNAL_NAMESPACE::Vec4<T>& S,
  1104. IMATH_INTERNAL_NAMESPACE::Matrix44<T>& V,
  1105. const T tol = IMATH_INTERNAL_NAMESPACE::limits<T>::epsilon(),
  1106. const bool forcePositiveDeterminant = false);
  1107. // Compute the eigenvalues (S) and the eigenvectors (V) of
  1108. // a real symmetric matrix using Jacobi transformation.
  1109. //
  1110. // Jacobi transformation of a 3x3/4x4 matrix A outputs S and V:
  1111. // A = V * S * V^T
  1112. // where V is orthonormal and S is the diagonal matrix of eigenvalues.
  1113. // Input matrix A must be symmetric. A is also modified during
  1114. // the computation so that upper diagonal entries of A become zero.
  1115. //
  1116. template <typename T>
  1117. void
  1118. jacobiEigenSolver (Matrix33<T>& A,
  1119. Vec3<T>& S,
  1120. Matrix33<T>& V,
  1121. const T tol);
  1122. template <typename T>
  1123. inline
  1124. void
  1125. jacobiEigenSolver (Matrix33<T>& A,
  1126. Vec3<T>& S,
  1127. Matrix33<T>& V)
  1128. {
  1129. jacobiEigenSolver(A,S,V,limits<T>::epsilon());
  1130. }
  1131. template <typename T>
  1132. void
  1133. jacobiEigenSolver (Matrix44<T>& A,
  1134. Vec4<T>& S,
  1135. Matrix44<T>& V,
  1136. const T tol);
  1137. template <typename T>
  1138. inline
  1139. void
  1140. jacobiEigenSolver (Matrix44<T>& A,
  1141. Vec4<T>& S,
  1142. Matrix44<T>& V)
  1143. {
  1144. jacobiEigenSolver(A,S,V,limits<T>::epsilon());
  1145. }
  1146. // Compute a eigenvector corresponding to the abs max/min eigenvalue
  1147. // of a real symmetric matrix using Jacobi transformation.
  1148. template <typename TM, typename TV>
  1149. void
  1150. maxEigenVector (TM& A, TV& S);
  1151. template <typename TM, typename TV>
  1152. void
  1153. minEigenVector (TM& A, TV& S);
  1154. IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
  1155. #endif // INCLUDED_IMATHMATRIXALGO_H