compose_matrix_src.cxx 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. // Filename: compose_matrix_src.cxx
  2. // Created by: drose (27Jan99)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
  8. //
  9. // All use of this software is subject to the terms of the Panda 3d
  10. // Software license. You should have received a copy of this license
  11. // along with this source code; you will also find a current copy of
  12. // the license at http://www.panda3d.org/license.txt .
  13. //
  14. // To contact the maintainers of this program write to
  15. // [email protected] .
  16. //
  17. ////////////////////////////////////////////////////////////////////
  18. ////////////////////////////////////////////////////////////////////
  19. // Function: compose_matrix
  20. // Description: Computes the 3x3 matrix from scale, shear, and
  21. // rotation.
  22. ////////////////////////////////////////////////////////////////////
  23. void
  24. compose_matrix(FLOATNAME(LMatrix3) &mat,
  25. const FLOATNAME(LVecBase3) &scale,
  26. const FLOATNAME(LVecBase3) &shear,
  27. const FLOATNAME(LVecBase3) &hpr,
  28. CoordinateSystem cs) {
  29. // temp_hpr_fix blocks use the correct way. need to keep other way
  30. // as default until legacy tools are fixed to work with correct way
  31. if (temp_hpr_fix) {
  32. mat =
  33. FLOATNAME(LMatrix3)::scale_shear_mat(scale, shear, cs) *
  34. FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[2], FLOATNAME(LVector3)::forward(cs), cs) *
  35. FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[1], FLOATNAME(LVector3)::right(cs), cs) *
  36. FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[0], FLOATNAME(LVector3)::up(cs), cs);
  37. } else {
  38. mat =
  39. FLOATNAME(LMatrix3)::scale_shear_mat(scale, shear, cs) *
  40. FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[1], FLOATNAME(LVector3)::right(cs), cs) *
  41. FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[0], FLOATNAME(LVector3)::up(cs), cs) *
  42. FLOATNAME(LMatrix3)::rotate_mat_normaxis(hpr[2], FLOATNAME(LVector3)::back(cs), cs);
  43. }
  44. }
  45. ////////////////////////////////////////////////////////////////////
  46. // Function: unwind_yup_rotation
  47. // Description: Extracts the rotation about the x, y, and z axes from
  48. // the given hpr & scale matrix. Adjusts the matrix
  49. // to eliminate the rotation.
  50. //
  51. // This function assumes the matrix is stored in a
  52. // right-handed Y-up coordinate system.
  53. ////////////////////////////////////////////////////////////////////
  54. static void
  55. unwind_yup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr) {
  56. typedef FLOATNAME(LMatrix3) Matrix;
  57. if (temp_hpr_fix) {
  58. // Extract the axes from the matrix.
  59. FLOATNAME(LVector3) x, y, z;
  60. mat.get_row(x,0);
  61. mat.get_row(y,1);
  62. mat.get_row(z,2);
  63. // Project Z into the XZ plane.
  64. FLOATNAME(LVector2) xz(z[0], z[2]);
  65. xz = normalize(xz);
  66. // Compute the rotation about the +Y (up) axis. This is yaw, or
  67. // "heading".
  68. FLOATTYPE heading = rad_2_deg(((FLOATTYPE)atan2(xz[0], xz[1])));
  69. // Unwind the heading, and continue.
  70. Matrix rot_y;
  71. rot_y = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
  72. CS_yup_right);
  73. x = x * rot_y;
  74. y = y * rot_y;
  75. z = z * rot_y;
  76. // Project the rotated Z into the YZ plane.
  77. FLOATNAME(LVector2) yz(z[1], z[2]);
  78. yz = normalize(yz);
  79. // Compute the rotation about the +X (right) axis. This is pitch.
  80. FLOATTYPE pitch = rad_2_deg((FLOATTYPE)(-atan2(yz[0], yz[1])));
  81. // Unwind the pitch.
  82. Matrix rot_x;
  83. rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
  84. CS_yup_right);
  85. x = x * rot_x;
  86. y = y * rot_x;
  87. z = z * rot_x;
  88. // Project the rotated X onto the XY plane.
  89. FLOATNAME(LVector2) xy(x[0], x[1]);
  90. xy = normalize(xy);
  91. // Compute the rotation about the +Z (back) axis. This is roll.
  92. FLOATTYPE roll = -rad_2_deg(((FLOATTYPE)atan2(xy[1], xy[0])));
  93. // Unwind the roll from the axes, and continue.
  94. Matrix rot_z;
  95. rot_z = Matrix::rotate_mat_normaxis(roll, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
  96. CS_yup_right);
  97. x = x * rot_z;
  98. y = y * rot_z;
  99. z = z * rot_z;
  100. // Reset the matrix to reflect the unwinding.
  101. mat.set_row(0, x);
  102. mat.set_row(1, y);
  103. mat.set_row(2, z);
  104. // Return the three rotation components.
  105. hpr[0] = heading;
  106. hpr[1] = pitch;
  107. hpr[2] = roll;
  108. } else {
  109. // Extract the axes from the matrix.
  110. FLOATNAME(LVector3) x, y, z;
  111. mat.get_row(x,0);
  112. mat.get_row(y,1);
  113. mat.get_row(z,2);
  114. // Project X onto the XY plane.
  115. FLOATNAME(LVector2) xy(x[0], x[1]);
  116. xy = normalize(xy);
  117. // Compute the rotation about the +Z (back) axis. This is roll.
  118. FLOATTYPE roll = rad_2_deg(((FLOATTYPE)atan2(xy[1], xy[0])));
  119. // Unwind the roll from the axes, and continue.
  120. Matrix rot_z;
  121. rot_z = Matrix::rotate_mat_normaxis(-roll, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
  122. CS_yup_right);
  123. x = x * rot_z;
  124. y = y * rot_z;
  125. z = z * rot_z;
  126. // Project the rotated X into the XZ plane.
  127. FLOATNAME(LVector2) xz(x[0], x[2]);
  128. xz = normalize(xz);
  129. // Compute the rotation about the +Y (up) axis. This is yaw, or
  130. // "heading".
  131. FLOATTYPE heading = rad_2_deg(((FLOATTYPE)-atan2(xz[1], xz[0])));
  132. // Unwind the heading, and continue.
  133. Matrix rot_y;
  134. rot_y = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
  135. CS_yup_right);
  136. x = x * rot_y;
  137. y = y * rot_y;
  138. z = z * rot_y;
  139. // Project the rotated Z into the YZ plane.
  140. FLOATNAME(LVector2) yz(z[1], z[2]);
  141. yz = normalize(yz);
  142. // Compute the rotation about the +X (right) axis. This is pitch.
  143. FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)-atan2(yz[0], yz[1])));
  144. // Unwind the pitch.
  145. Matrix rot_x;
  146. rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
  147. CS_yup_right);
  148. x = x * rot_x;
  149. y = y * rot_x;
  150. z = z * rot_x;
  151. // Reset the matrix to reflect the unwinding.
  152. mat.set_row(0, x);
  153. mat.set_row(1, y);
  154. mat.set_row(2, z);
  155. // Return the three rotation components.
  156. hpr[0] = heading;
  157. hpr[1] = pitch;
  158. hpr[2] = roll;
  159. }
  160. }
  161. ////////////////////////////////////////////////////////////////////
  162. // Function: unwind_yup_rotation
  163. // Description: Extracts the rotation about the x, y, and z axes from
  164. // the given hpr & scale matrix, given the indicated
  165. // roll amount as a hint. Adjusts the matrix to
  166. // eliminate the rotation.
  167. //
  168. // This function assumes the matrix is stored in a
  169. // right-handed Y-up coordinate system.
  170. ////////////////////////////////////////////////////////////////////
  171. static void
  172. unwind_yup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr,
  173. FLOATTYPE roll) {
  174. if (temp_hpr_fix) {
  175. unwind_yup_rotation(mat, hpr);
  176. return;
  177. }
  178. typedef FLOATNAME(LMatrix3) Matrix;
  179. // Extract the axes from the matrix.
  180. FLOATNAME(LVector3) x, y, z;
  181. mat.get_row(x,0);
  182. mat.get_row(y,1);
  183. mat.get_row(z,2);
  184. // Unwind the roll from the axes, and continue.
  185. Matrix rot_z;
  186. rot_z = Matrix::rotate_mat_normaxis(-roll, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
  187. CS_yup_right);
  188. x = x * rot_z;
  189. y = y * rot_z;
  190. z = z * rot_z;
  191. // Project the rotated X into the XZ plane.
  192. FLOATNAME(LVector2) xz(x[0], x[2]);
  193. xz = normalize(xz);
  194. // Compute the rotation about the +Y (up) axis. This is yaw, or
  195. // "heading".
  196. FLOATTYPE heading = rad_2_deg(((FLOATTYPE)-atan2(xz[1], xz[0])));
  197. // Unwind the heading, and continue.
  198. Matrix rot_y;
  199. rot_y = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
  200. CS_yup_right);
  201. x = x * rot_y;
  202. y = y * rot_y;
  203. z = z * rot_y;
  204. // Project the rotated Z into the YZ plane.
  205. FLOATNAME(LVector2) yz(z[1], z[2]);
  206. yz = normalize(yz);
  207. // Compute the rotation about the +X (right) axis. This is pitch.
  208. FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)-atan2(yz[0], yz[1])));
  209. // Unwind the pitch.
  210. Matrix rot_x;
  211. rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
  212. CS_yup_right);
  213. x = x * rot_x;
  214. y = y * rot_x;
  215. z = z * rot_x;
  216. // Reset the matrix to reflect the unwinding.
  217. mat.set_row(0, x);
  218. mat.set_row(1, y);
  219. mat.set_row(2, z);
  220. // Return the three rotation components.
  221. hpr[0] = heading;
  222. hpr[1] = pitch;
  223. hpr[2] = roll;
  224. }
  225. ////////////////////////////////////////////////////////////////////
  226. // Function: unwind_zup_rotation
  227. // Description: Extracts the rotation about the x, y, and z axes from
  228. // the given hpr & scale matrix. Adjusts the matrix
  229. // to eliminate the rotation.
  230. //
  231. // This function assumes the matrix is stored in a
  232. // right-handed Z-up coordinate system.
  233. ////////////////////////////////////////////////////////////////////
  234. static void
  235. unwind_zup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr) {
  236. if (temp_hpr_fix) {
  237. typedef FLOATNAME(LMatrix3) Matrix;
  238. // Extract the axes from the matrix.
  239. FLOATNAME(LVector3) x, y, z;
  240. mat.get_row(x,0);
  241. mat.get_row(y,1);
  242. mat.get_row(z,2);
  243. // Project Y into the XY plane.
  244. FLOATNAME(LVector2) xy(y[0], y[1]);
  245. xy = normalize(xy);
  246. // Compute the rotation about the +Z (up) axis. This is yaw, or
  247. // "heading".
  248. FLOATTYPE heading = -rad_2_deg(((FLOATTYPE)atan2(xy[0], xy[1])));
  249. // Unwind the heading, and continue.
  250. Matrix rot_z;
  251. rot_z = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
  252. CS_zup_right);
  253. x = x * rot_z;
  254. y = y * rot_z;
  255. z = z * rot_z;
  256. // Project the rotated Y into the YZ plane.
  257. FLOATNAME(LVector2) yz(y[1], y[2]);
  258. yz = normalize(yz);
  259. // Compute the rotation about the +X (right) axis. This is pitch.
  260. FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)atan2(yz[1], yz[0])));
  261. // Unwind the pitch.
  262. Matrix rot_x;
  263. rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
  264. CS_zup_right);
  265. x = x * rot_x;
  266. y = y * rot_x;
  267. z = z * rot_x;
  268. // Project X into the XZ plane.
  269. FLOATNAME(LVector2) xz(x[0], x[2]);
  270. xz = normalize(xz);
  271. // Compute the rotation about the -Y (back) axis. This is roll.
  272. FLOATTYPE roll = -rad_2_deg(((FLOATTYPE)atan2(xz[1], xz[0])));
  273. // Unwind the roll from the axes, and continue.
  274. Matrix rot_y;
  275. rot_y = Matrix::rotate_mat_normaxis(-roll, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
  276. CS_zup_right);
  277. x = x * rot_y;
  278. y = y * rot_y;
  279. z = z * rot_y;
  280. // Reset the matrix to reflect the unwinding.
  281. mat.set_row(0, x);
  282. mat.set_row(1, y);
  283. mat.set_row(2, z);
  284. // Return the three rotation components.
  285. hpr[0] = heading;
  286. hpr[1] = pitch;
  287. hpr[2] = roll;
  288. } else {
  289. typedef FLOATNAME(LMatrix3) Matrix;
  290. // Extract the axes from the matrix.
  291. FLOATNAME(LVector3) x, y, z;
  292. mat.get_row(x,0);
  293. mat.get_row(y,1);
  294. mat.get_row(z,2);
  295. // Project X into the XZ plane.
  296. FLOATNAME(LVector2) xz(x[0], x[2]);
  297. xz = normalize(xz);
  298. // Compute the rotation about the -Y (back) axis. This is roll.
  299. FLOATTYPE roll = rad_2_deg(((FLOATTYPE)atan2(xz[1], xz[0])));
  300. if (y[1] < 0.0f) {
  301. if (roll < 0.0f) {
  302. roll += 180.0;
  303. } else {
  304. roll -= 180.0;
  305. }
  306. }
  307. // Unwind the roll from the axes, and continue.
  308. Matrix rot_y;
  309. rot_y = Matrix::rotate_mat_normaxis(roll, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
  310. CS_zup_right);
  311. x = x * rot_y;
  312. y = y * rot_y;
  313. z = z * rot_y;
  314. // Project the rotated X into the XY plane.
  315. FLOATNAME(LVector2) xy(x[0], x[1]);
  316. xy = normalize(xy);
  317. // Compute the rotation about the +Z (up) axis. This is yaw, or
  318. // "heading".
  319. FLOATTYPE heading = rad_2_deg(((FLOATTYPE)atan2(xy[1], xy[0])));
  320. // Unwind the heading, and continue.
  321. Matrix rot_z;
  322. rot_z = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
  323. CS_zup_right);
  324. x = x * rot_z;
  325. y = y * rot_z;
  326. z = z * rot_z;
  327. // Project the rotated Y into the YZ plane.
  328. FLOATNAME(LVector2) yz(y[1], y[2]);
  329. yz = normalize(yz);
  330. // Compute the rotation about the +X (right) axis. This is pitch.
  331. FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)atan2(yz[1], yz[0])));
  332. // Unwind the pitch.
  333. Matrix rot_x;
  334. rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
  335. CS_zup_right);
  336. x = x * rot_x;
  337. y = y * rot_x;
  338. z = z * rot_x;
  339. // Reset the matrix to reflect the unwinding.
  340. mat.set_row(0, x);
  341. mat.set_row(1, y);
  342. mat.set_row(2, z);
  343. // Return the three rotation components.
  344. hpr[0] = heading;
  345. hpr[1] = pitch;
  346. hpr[2] = roll;
  347. }
  348. }
  349. ////////////////////////////////////////////////////////////////////
  350. // Function: unwind_zup_rotation
  351. // Description: Extracts the rotation about the x, y, and z axes from
  352. // the given hpr & scale matrix, given the indicated
  353. // roll amount as a hint. Adjusts the matrix to
  354. // eliminate the rotation.
  355. //
  356. // This function assumes the matrix is stored in a
  357. // right-handed Z-up coordinate system.
  358. ////////////////////////////////////////////////////////////////////
  359. static void
  360. unwind_zup_rotation(FLOATNAME(LMatrix3) &mat, FLOATNAME(LVecBase3) &hpr,
  361. FLOATTYPE roll) {
  362. if (temp_hpr_fix) {
  363. unwind_zup_rotation(mat, hpr);
  364. return;
  365. }
  366. typedef FLOATNAME(LMatrix3) Matrix;
  367. // Extract the axes from the matrix.
  368. FLOATNAME(LVector3) x, y, z;
  369. mat.get_row(x,0);
  370. mat.get_row(y,1);
  371. mat.get_row(z,2);
  372. // Unwind the roll from the axes, and continue.
  373. Matrix rot_y;
  374. rot_y = Matrix::rotate_mat_normaxis(roll, FLOATNAME(LVector3)(0.0f, 1.0f, 0.0f),
  375. CS_zup_right);
  376. x = x * rot_y;
  377. y = y * rot_y;
  378. z = z * rot_y;
  379. // Project the rotated X into the XY plane.
  380. FLOATNAME(LVector2) xy(x[0], x[1]);
  381. xy = normalize(xy);
  382. // Compute the rotation about the +Z (up) axis. This is yaw, or
  383. // "heading".
  384. FLOATTYPE heading = rad_2_deg(((FLOATTYPE)atan2(xy[1], xy[0])));
  385. // Unwind the heading, and continue.
  386. Matrix rot_z;
  387. rot_z = Matrix::rotate_mat_normaxis(-heading, FLOATNAME(LVector3)(0.0f, 0.0f, 1.0f),
  388. CS_zup_right);
  389. x = x * rot_z;
  390. y = y * rot_z;
  391. z = z * rot_z;
  392. // Project the rotated Y into the YZ plane.
  393. FLOATNAME(LVector2) yz(y[1], y[2]);
  394. yz = normalize(yz);
  395. // Compute the rotation about the +X (right) axis. This is pitch.
  396. FLOATTYPE pitch = rad_2_deg(((FLOATTYPE)atan2(yz[1], yz[0])));
  397. // Unwind the pitch.
  398. Matrix rot_x;
  399. rot_x = Matrix::rotate_mat_normaxis(-pitch, FLOATNAME(LVector3)(1.0f, 0.0f, 0.0f),
  400. CS_zup_right);
  401. x = x * rot_x;
  402. y = y * rot_x;
  403. z = z * rot_x;
  404. // Reset the matrix to reflect the unwinding.
  405. mat.set_row(0, x);
  406. mat.set_row(1, y);
  407. mat.set_row(2, z);
  408. // Return the three rotation components.
  409. hpr[0] = heading;
  410. hpr[1] = pitch;
  411. hpr[2] = roll;
  412. }
  413. ////////////////////////////////////////////////////////////////////
  414. // Function: decompose_matrix
  415. // Description: Extracts out the components of a 3x3 rotation matrix.
  416. // Returns true if successful, or false if there was an
  417. // error. Since a 3x3 matrix always contains an affine
  418. // transform, this should succeed in the normal case;
  419. // singular transforms are not treated as an error.
  420. ////////////////////////////////////////////////////////////////////
  421. bool
  422. decompose_matrix(const FLOATNAME(LMatrix3) &mat,
  423. FLOATNAME(LVecBase3) &scale,
  424. FLOATNAME(LVecBase3) &shear,
  425. FLOATNAME(LVecBase3) &hpr,
  426. CoordinateSystem cs) {
  427. if (cs == CS_default) {
  428. cs = default_coordinate_system;
  429. }
  430. if (linmath_cat.is_debug()) {
  431. linmath_cat.debug()
  432. << "decomposing " << mat << " via cs " << cs << "\n";
  433. }
  434. // Extract the rotation and scale, according to the coordinate
  435. // system of choice.
  436. bool is_left_handed;
  437. FLOATNAME(LMatrix3) new_mat(mat);
  438. switch (cs) {
  439. case CS_zup_right:
  440. {
  441. unwind_zup_rotation(new_mat, hpr);
  442. is_left_handed = false;
  443. }
  444. break;
  445. case CS_yup_right:
  446. {
  447. unwind_yup_rotation(new_mat, hpr);
  448. is_left_handed = false;
  449. }
  450. break;
  451. case CS_zup_left:
  452. {
  453. new_mat._m.m._02 = -new_mat._m.m._02;
  454. new_mat._m.m._12 = -new_mat._m.m._12;
  455. new_mat._m.m._20 = -new_mat._m.m._20;
  456. new_mat._m.m._21 = -new_mat._m.m._21;
  457. /*
  458. FLOATNAME(LMatrix3) lm(mat(0, 0), mat(0, 1), -mat(0, 2),
  459. mat(1, 0), mat(1, 1), -mat(1, 2),
  460. -mat(2, 0), -mat(2, 1), mat(2, 2));
  461. */
  462. unwind_zup_rotation(new_mat, hpr);
  463. hpr[0] = -hpr[0];
  464. hpr[2] = -hpr[2];
  465. is_left_handed = true;
  466. }
  467. break;
  468. case CS_yup_left:
  469. {
  470. new_mat._m.m._02 = -new_mat._m.m._02;
  471. new_mat._m.m._12 = -new_mat._m.m._12;
  472. new_mat._m.m._20 = -new_mat._m.m._20;
  473. new_mat._m.m._21 = -new_mat._m.m._21;
  474. /*
  475. FLOATNAME(LMatrix3) lm(mat(0, 0), mat(0, 1), -mat(0, 2),
  476. mat(1, 0), mat(1, 1), -mat(1, 2),
  477. -mat(2, 0), -mat(2, 1), mat(2, 2));
  478. */
  479. unwind_yup_rotation(new_mat, hpr);
  480. is_left_handed = true;
  481. }
  482. break;
  483. default:
  484. linmath_cat.error()
  485. << "Unexpected coordinate system: " << (int)cs << "\n";
  486. return false;
  487. }
  488. if (linmath_cat.is_debug()) {
  489. linmath_cat.debug()
  490. << "after unwind, mat is " << new_mat << "\n";
  491. }
  492. scale.set(new_mat(0, 0), new_mat(1, 1), new_mat(2, 2));
  493. // Normalize the scale out of the shear components, and return the
  494. // shear.
  495. if (scale[0] != 0.0) {
  496. new_mat(0, 1) /= scale[0];
  497. new_mat(0, 2) /= scale[0];
  498. }
  499. if (scale[1] != 0.0) {
  500. new_mat(1, 0) /= scale[1];
  501. new_mat(1, 2) /= scale[1];
  502. }
  503. if (scale[2] != 0.0) {
  504. new_mat(2, 0) /= scale[2];
  505. new_mat(2, 1) /= scale[2];
  506. }
  507. shear.set(new_mat(0, 1) + new_mat(1, 0),
  508. new_mat(2, 0) + new_mat(0, 2),
  509. new_mat(2, 1) + new_mat(1, 2));
  510. return true;
  511. }
  512. ////////////////////////////////////////////////////////////////////
  513. // Function: decompose_matrix
  514. // Description: Extracts out the components of a 3x3 rotation matrix.
  515. // Returns true if the scale and hpr completely describe
  516. // the matrix, or false if there is also a shear
  517. // component or if the matrix is not affine.
  518. //
  519. // This flavor of the function accepts an expected roll
  520. // amount. This amount will be used as the roll
  521. // component, rather than attempting to determine roll
  522. // by examining the matrix; this helps alleviate roll
  523. // instability due to roundoff errors or gimbal lock.
  524. //
  525. // This function is deprecated and will soon be removed,
  526. // especially when the need for temp_hpr_fix is
  527. // eliminated.
  528. ////////////////////////////////////////////////////////////////////
  529. bool
  530. decompose_matrix(const FLOATNAME(LMatrix3) &mat,
  531. FLOATNAME(LVecBase3) &scale,
  532. FLOATNAME(LVecBase3) &hpr,
  533. FLOATTYPE roll,
  534. CoordinateSystem cs) {
  535. if (cs == CS_default) {
  536. cs = default_coordinate_system;
  537. }
  538. if (linmath_cat.is_debug()) {
  539. linmath_cat.debug()
  540. << "decomposing " << mat << " via cs " << cs
  541. << " with roll = " << roll << "\n";
  542. }
  543. // Extract the rotation and scale, according to the coordinate
  544. // system of choice.
  545. bool is_left_handed;
  546. FLOATNAME(LMatrix3) new_mat(mat);
  547. switch (cs) {
  548. case CS_zup_right:
  549. {
  550. unwind_zup_rotation(new_mat, hpr, roll);
  551. is_left_handed = false;
  552. }
  553. break;
  554. case CS_yup_right:
  555. {
  556. unwind_yup_rotation(new_mat, hpr, roll);
  557. is_left_handed = false;
  558. }
  559. break;
  560. case CS_zup_left:
  561. {
  562. new_mat._m.m._02 = -new_mat._m.m._02;
  563. new_mat._m.m._12 = -new_mat._m.m._12;
  564. new_mat._m.m._20 = -new_mat._m.m._20;
  565. new_mat._m.m._21 = -new_mat._m.m._21;
  566. /*
  567. FLOATNAME(LMatrix3) lm(mat(0, 0), mat(0, 1), -mat(0, 2),
  568. mat(1, 0), mat(1, 1), -mat(1, 2),
  569. -mat(2, 0), -mat(2, 1), mat(2, 2));
  570. */
  571. unwind_zup_rotation(new_mat, hpr, roll);
  572. is_left_handed = true;
  573. }
  574. break;
  575. case CS_yup_left:
  576. {
  577. new_mat._m.m._02 = -new_mat._m.m._02;
  578. new_mat._m.m._12 = -new_mat._m.m._12;
  579. new_mat._m.m._20 = -new_mat._m.m._20;
  580. new_mat._m.m._21 = -new_mat._m.m._21;
  581. /*
  582. FLOATNAME(LMatrix3) lm(mat(0, 0), mat(0, 1), -mat(0, 2),
  583. mat(1, 0), mat(1, 1), -mat(1, 2),
  584. -mat(2, 0), -mat(2, 1), mat(2, 2));
  585. */
  586. unwind_yup_rotation(new_mat, hpr, roll);
  587. is_left_handed = true;
  588. }
  589. break;
  590. default:
  591. linmath_cat.error()
  592. << "Unexpected coordinate system: " << (int)cs << "\n";
  593. return false;
  594. }
  595. if (linmath_cat.is_debug()) {
  596. linmath_cat.debug()
  597. << "after unwind, mat is " << new_mat << "\n";
  598. }
  599. scale[0] = new_mat._m.m._00;
  600. scale[1] = new_mat._m.m._11;
  601. scale[2] = new_mat._m.m._22;
  602. /*
  603. if (is_left_handed) {
  604. scale[0] = -new_mat._m.m._00;
  605. scale[1] = -new_mat._m.m._11;
  606. }
  607. */
  608. bool has_no_shear =
  609. (fabs(new_mat(0, 1)) + fabs(new_mat(0, 2)) +
  610. fabs(new_mat(1, 0)) + fabs(new_mat(1, 2)) +
  611. fabs(new_mat(2, 0)) + fabs(new_mat(2, 1))) < 0.0001;
  612. return has_no_shear;
  613. }