PageRenderTime 27ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/brlcad/tags/rel-7-16-10/src/libbn/anim.c

https://bitbucket.org/vrrm/brl-cad-copy-for-fast-history-browsing-in-git
C | 822 lines | 637 code | 121 blank | 64 comment | 68 complexity | d477470224e37f6ecb8d60c46c0c1b1a MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, LGPL-2.1, Apache-2.0, AGPL-3.0, LGPL-3.0, GPL-3.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, 0BSD, BSD-3-Clause
  1. /* A N I M . C
  2. * BRL-CAD
  3. *
  4. * Copyright (c) 1993-2010 United States Government as represented by
  5. * the U.S. Army Research Laboratory.
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public License
  9. * version 2.1 as published by the Free Software Foundation.
  10. *
  11. * This library is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this file; see the file named COPYING for more
  18. * information.
  19. */
  20. #include "common.h"
  21. #include <stdio.h>
  22. #include <math.h>
  23. #include "bu.h"
  24. #include "vmath.h"
  25. #include "bn.h"
  26. #include "anim.h"
  27. #define NORMAL 0
  28. #define ERROR1 1
  29. #define ERROR2 2
  30. void
  31. anim_v_permute(mat_t m)
  32. {
  33. int i;
  34. fastf_t store;
  35. for (i=0; i<9; i+=4) {
  36. store = m[i];
  37. m[i] = -m[i+1];
  38. m[i+1] = m[i+2];
  39. m[i+2] = -store;
  40. }
  41. }
  42. void
  43. anim_v_unpermute(mat_t m)
  44. {
  45. int i;
  46. fastf_t store;
  47. for (i=0; i<9; i+=4) {
  48. store = m[i+2];
  49. m[i+2] = m[i+1];
  50. m[i+1] = -m[i];
  51. m[i] = -store;
  52. }
  53. }
  54. void
  55. anim_tran(mat_t m)
  56. {
  57. int i;
  58. fastf_t store;
  59. int src[6] = { 1, 2, 3, 6, 7, 11 };
  60. int dst[6] = { 4, 8, 12, 9, 13, 14};
  61. for (i=0; i<6; i++) {
  62. store = m[dst[i]];
  63. m[dst[i]] = m[src[i]];
  64. m[src[i]] = store;
  65. }
  66. }
  67. /***************************************
  68. *ANIM_MAT2* - Conversions from matrices
  69. ***************************************/
  70. int
  71. anim_mat2zyx(const mat_t viewrot, vect_t angle)
  72. {
  73. int i, return_value, id_x, id_z;
  74. fastf_t sin_x, sin_z, cos_x, cos_z, big_x, big_z;
  75. static fastf_t previous[3];
  76. if (NEAR_ZERO(viewrot[1], SMALL_FASTF) && NEAR_ZERO(viewrot[0], SMALL_FASTF)) {
  77. return_value = ERROR1;
  78. angle[0] = 0.0;
  79. angle[2] = atan2(viewrot[4], viewrot[5]);
  80. } else {
  81. return_value = NORMAL;
  82. angle[2] = atan2(-viewrot[1], viewrot[0]);
  83. angle[0] = atan2(-viewrot[6], viewrot[10]);
  84. }
  85. sin_x = sin(angle[0]);
  86. sin_z = sin(angle[2]);
  87. cos_x = cos(angle[0]);
  88. cos_z = cos(angle[2]);
  89. /* in principle, we can use the sin_x or cos_x with sin_z or cos_z
  90. * to figure out angle[1], as long as they are non-zero. To avoid
  91. * ill-conditioning effects, we choose the two that are greatest
  92. * in absolute value
  93. */
  94. id_z = (fabs(sin_z) > fabs(cos_z)) ? 1 : 0;
  95. big_z = id_z ? sin_z : cos_z;
  96. id_x = (fabs(sin_x) > fabs(cos_x)) ? 1 : 0;
  97. big_x = id_x ? sin_x : cos_x;
  98. if (fabs(big_x*big_z) < VDIVIDE_TOL) {
  99. /* this should be impossible*/
  100. /* unable to calculate pitch*/
  101. return ERROR2;
  102. } else if (id_x && (!id_z))
  103. angle[1]=atan2((viewrot[4] - cos_x*sin_z)/(sin_x*cos_z), -viewrot[6]/sin_x);
  104. else if ((!id_x) && (!id_z))
  105. angle[1]=atan2((-viewrot[8] + sin_x*sin_z)/(cos_x*cos_z), viewrot[0]/cos_z);
  106. else if (id_x && id_z)
  107. angle[1]=atan2((-viewrot[5] + cos_x*cos_z)/(sin_x*sin_z), -viewrot[1]/sin_z);
  108. else if ((!id_x) && id_z)
  109. angle[1]=atan2((viewrot[9] - sin_x*cos_z)/(cos_x*sin_z), viewrot[10]/cos_x);
  110. /* assume the smallest possible arc-length from frame to frame */
  111. for (i=0; i<3; i++) {
  112. while ((angle[i] - previous[i]) > M_PI)
  113. angle[i] -= (2.0*M_PI);
  114. while ((previous[i] - angle[i]) > M_PI)
  115. angle[i] += (2.0*M_PI);
  116. previous[i] = angle[i];
  117. }
  118. return return_value;
  119. }
  120. int
  121. anim_mat2ypr(mat_t viewrot, vect_t angle)
  122. {
  123. int i, return_value, id_y, id_r;
  124. fastf_t sin_y, sin_r, cos_y, cos_r, big_y, big_r;
  125. static fastf_t prev_angle[3];
  126. if (NEAR_ZERO(viewrot[9], SMALL_FASTF) && NEAR_ZERO(viewrot[10], SMALL_FASTF)) {
  127. return_value = ERROR1;
  128. angle[2] = 0.0;
  129. angle[0] = atan2(-viewrot[1], viewrot[5]);
  130. } else {
  131. return_value = NORMAL;
  132. angle[0] = atan2(viewrot[4], viewrot[0]);
  133. angle[2] = atan2(viewrot[9], viewrot[10]);
  134. }
  135. sin_y = sin(angle[0]);
  136. sin_r = sin(angle[2]);
  137. cos_y = cos(angle[0]);
  138. cos_r = cos(angle[2]);
  139. /* in principle, we can use sin_y or cos_y with sin_r or cos_r to
  140. * figure out angle[1], as long as they are non-zero. To avoid
  141. * ill-conditioning effects, we choose the two that are greatest
  142. * in absolute value
  143. */
  144. id_y = (fabs(sin_y) > fabs(cos_y)) ? 1 : 0;
  145. big_y = id_y ? sin_y : cos_y;
  146. id_r = (fabs(sin_r) > fabs(cos_r)) ? 1 : 0;
  147. big_r = id_r ? sin_r : cos_r;
  148. if (fabs(big_y*big_r) < VDIVIDE_TOL) {
  149. /* this should not happen */
  150. /* unable to calculate pitch*/
  151. return ERROR2;
  152. } else if ((!id_y) && id_r)
  153. angle[1] = atan2(-(viewrot[1]+sin_y*cos_r)/(cos_y*sin_r), viewrot[9]/sin_r);
  154. else if (id_y && (!id_r))
  155. angle[1] = atan2(-(viewrot[6]+cos_y*sin_r)/(sin_y*cos_r), viewrot[10]/cos_r);
  156. else if (id_y && id_r)
  157. angle[1] = atan2(-(viewrot[5]-cos_y*cos_r)/(sin_y*sin_r), viewrot[4]/sin_y);
  158. else if ((!id_y) && (!id_r))
  159. angle[1] = atan2(-(viewrot[2]-sin_y*sin_r)/(cos_y*cos_r), viewrot[0]/cos_y);
  160. /* assume the smallest possible arc-length from frame to frame */
  161. for (i=0; i<3; i++) {
  162. while ((angle[i] - prev_angle[i]) > M_PI)
  163. angle[i] -= (2.0*M_PI);
  164. while ((prev_angle[i] - angle[i]) > M_PI)
  165. angle[i] += (2.0*M_PI);
  166. prev_angle[i] = angle[i];
  167. }
  168. return return_value;
  169. }
  170. int
  171. anim_mat2quat(quat_t quat, const mat_t viewrot)
  172. {
  173. int i;
  174. fastf_t qdiff[4], square, mag1, mag2;
  175. static fastf_t prev_quat[4];
  176. square = 0.25 * (1 + viewrot[0] + viewrot[5] + viewrot[10]);
  177. if (!NEAR_ZERO(square, SMALL_FASTF)) {
  178. quat[W] = sqrt(square);
  179. quat[X] = 0.25 * (viewrot[9] - viewrot[6])/ quat[W];
  180. quat[Y] = 0.25 * (viewrot[2] - viewrot[8])/ quat[W];
  181. quat[Z] = 0.25 * (viewrot[4] - viewrot[1])/ quat[W];
  182. } else {
  183. quat[W] = 0.0;
  184. square = -0.5 * (viewrot[5] + viewrot[10]);
  185. if (!NEAR_ZERO(square, SMALL_FASTF)) {
  186. quat[X] = sqrt(square);
  187. quat[Y] = 0.5 * viewrot[4] / quat[X];
  188. quat[Z] = 0.5 * viewrot[8] / quat[X];
  189. } else {
  190. quat[X] = 0.0;
  191. square = 0.5 * (1 - viewrot[10]);
  192. if (!NEAR_ZERO(square, SMALL_FASTF)) {
  193. quat[Y] = sqrt(square);
  194. quat[Z] = 0.5 * viewrot[9]/ quat[Y];
  195. } else {
  196. quat[Y] = 0.0;
  197. quat[Z] = 1.0;
  198. }
  199. }
  200. }
  201. /* quaternions on opposite sides of a four-dimensional sphere are
  202. equivalent. Take the quaternion closest to the previous one */
  203. for (i=0; i<4; i++)
  204. qdiff[i] = prev_quat[i] - quat[i];
  205. mag1 = QMAGSQ(qdiff);
  206. for (i=0; i<4; i++)
  207. qdiff[i] = prev_quat[i] + quat[i];
  208. mag2 = QMAGSQ(qdiff);
  209. for (i=0; i<4; i++) {
  210. if (mag1 > mag2) /* inverse of quat would be closer */
  211. quat[i] = -quat[i];
  212. prev_quat[i] = quat[i];
  213. }
  214. return 1;
  215. }
  216. /***************************************
  217. *ANIM_*2MAT - Conversions to matrices
  218. ***************************************/
  219. void
  220. anim_ypr2mat(mat_t m, const vect_t a)
  221. {
  222. fastf_t cos_y, cos_p, cos_r, sin_y, sin_p, sin_r;
  223. cos_y = cos(a[0]);
  224. cos_p = cos(a[1]);
  225. cos_r = cos(a[2]);
  226. sin_y = sin(a[0]);
  227. sin_p = sin(a[1]);
  228. sin_r = sin(a[2]);
  229. m[0] = cos_y*cos_p;
  230. m[1] = -cos_y*sin_p*sin_r-sin_y*cos_r;
  231. m[2] = -cos_y*sin_p*cos_r+sin_y*sin_r;
  232. m[3] = 0;
  233. m[4] = sin_y*cos_p;
  234. m[5] = -sin_y*sin_p*sin_r+cos_y*cos_r;
  235. m[6] = -sin_y*sin_p*cos_r-cos_y*sin_r;
  236. m[7] = 0;
  237. m[8]= sin_p;
  238. m[9] = cos_p*sin_r;
  239. m[10] = cos_p*cos_r;
  240. m[11] = 0.0;
  241. m[12] = 0.0;
  242. m[13] = 0.0;
  243. m[14] = 0.0;
  244. m[15] = 1.0;
  245. }
  246. void
  247. anim_ypr2vmat(mat_t m, const vect_t a)
  248. {
  249. fastf_t cos_y, cos_p, cos_r, sin_y, sin_p, sin_r;
  250. cos_y = cos(a[0]);
  251. cos_p = cos(a[1]);
  252. cos_r = cos(a[2]);
  253. sin_y = sin(a[0]);
  254. sin_p = sin(a[1]);
  255. sin_r = sin(a[2]);
  256. m[0] = -cos_y*sin_p*sin_r-sin_y*cos_r;
  257. m[1] = -sin_y*sin_p*sin_r+cos_y*cos_r;
  258. m[2] = cos_p*sin_r;
  259. m[3] = 0;
  260. m[4] = -cos_y*sin_p*cos_r+sin_y*sin_r;
  261. m[5] = -sin_y*sin_p*cos_r-cos_y*sin_r;
  262. m[6] = cos_p*cos_r;
  263. m[7] = 0;
  264. m[8] = cos_y*cos_p;
  265. m[9] = sin_y*cos_p;
  266. m[10] = sin_p;
  267. m[11] = 0.0;
  268. m[12] = 0.0;
  269. m[13] = 0.0;
  270. m[14] = 0.0;
  271. m[15] = 1.0;
  272. }
  273. void
  274. anim_y_p_r2mat(mat_t m, double y, double p, double r)
  275. {
  276. fastf_t cos_y = cos(y);
  277. fastf_t sin_y = sin(y);
  278. fastf_t cos_p = cos(p);
  279. fastf_t sin_p = sin(p);
  280. fastf_t cos_r = cos(r);
  281. fastf_t sin_r = sin(r);
  282. m[0] = cos_y*cos_p;
  283. m[1] = -cos_y*sin_p*sin_r-sin_y*cos_r;
  284. m[2] = -cos_y*sin_p*cos_r+sin_y*sin_r;
  285. m[4] = sin_y*cos_p;
  286. m[5] = -sin_y*sin_p*sin_r+cos_y*cos_r;
  287. m[6] = -sin_y*sin_p*cos_r-cos_y*sin_r;
  288. m[8]= sin_p;
  289. m[9] = cos_p*sin_r;
  290. m[10] = cos_p*cos_r;
  291. m[3]=m[7]=m[11]=m[12]=m[13]=m[14]=0;
  292. m[15]=1;
  293. }
  294. void
  295. anim_dy_p_r2mat(mat_t m, double y, double p, double r)
  296. {
  297. fastf_t radian_yaw = y*(M_PI*0.0055555555556);
  298. fastf_t radian_pitch = p*(M_PI*0.0055555555556);
  299. fastf_t radian_roll = r*(M_PI*0.0055555555556);
  300. fastf_t cos_y = cos(radian_yaw);
  301. fastf_t sin_y = sin(radian_yaw);
  302. fastf_t cos_p = cos(radian_pitch);
  303. fastf_t sin_p = sin(radian_pitch);
  304. fastf_t cos_r = cos(radian_roll);
  305. fastf_t sin_r = sin(radian_roll);
  306. m[0] = cos_y*cos_p;
  307. m[1] = -cos_y*sin_p*sin_r-sin_y*cos_r;
  308. m[2] = -cos_y*sin_p*cos_r+sin_y*sin_r;
  309. m[4] = sin_y*cos_p;
  310. m[5] = -sin_y*sin_p*sin_r+cos_y*cos_r;
  311. m[6] = -sin_y*sin_p*cos_r-cos_y*sin_r;
  312. m[8]= sin_p;
  313. m[9] = cos_p*sin_r;
  314. m[10] = cos_p*cos_r;
  315. m[3]=m[7]=m[11]=m[12]=m[13]=m[14]=0;
  316. m[15]=1;
  317. }
  318. void
  319. anim_dy_p_r2vmat(mat_t m, double yaw, double pch, double rll)
  320. {
  321. float ryaw = yaw*(M_PI*0.0055555555556);
  322. float rpch = pch*(M_PI*0.0055555555556);
  323. float rrll = rll*(M_PI*0.0055555555556);
  324. float cos_y = cos(ryaw);
  325. float sin_y = sin(ryaw);
  326. float cos_p = cos(rpch);
  327. float sin_p = sin(rpch);
  328. float cos_r = cos(rrll);
  329. float sin_r = sin(rrll);
  330. m[0] = -cos_y*sin_p*sin_r-sin_y*cos_r;
  331. m[1] = -sin_y*sin_p*sin_r+cos_y*cos_r;
  332. m[2] = cos_p*sin_r;
  333. m[4] = -cos_y*sin_p*cos_r+sin_y*sin_r;
  334. m[5] = -sin_y*sin_p*cos_r-cos_y*sin_r;
  335. m[6] = cos_p*cos_r;
  336. m[8] = cos_y*cos_p;
  337. m[9] = sin_y*cos_p;
  338. m[10]= sin_p;
  339. m[3]=m[7]=m[11]=0;
  340. m[12]=m[13]=m[14]=0;
  341. m[15]=1;
  342. }
  343. void
  344. anim_x_y_z2mat(mat_t m, double x, double y, double z)
  345. {
  346. fastf_t cosx = cos(x);
  347. fastf_t sinx = sin(x);
  348. fastf_t cosy = cos(y);
  349. fastf_t siny = sin(y);
  350. fastf_t cosz = cos(z);
  351. fastf_t sinz = sin(z);
  352. m[0] = cosz*cosy;
  353. m[1] = cosz*siny*sinx-sinz*cosx;
  354. m[2] = cosz*siny*cosx+sinz*sinx;
  355. m[4] = sinz*cosy;
  356. m[5] = sinz*siny*sinx+cosz*cosx;
  357. m[6] = sinz*siny*cosx-cosz*sinx;
  358. m[8] = -siny;
  359. m[9] = cosy*sinx;
  360. m[10] = cosy*cosx;
  361. m[3]=m[7]=m[11]=m[12]=m[13]=m[14]=0;
  362. m[15]=1;
  363. }
  364. void
  365. anim_dx_y_z2mat(mat_t m, double x, double y, double z)
  366. {
  367. fastf_t cosx, cosy, cosz, sinx, siny, sinz;
  368. x *= (M_PI*0.0055555555556);
  369. y *= (M_PI*0.0055555555556);
  370. z *= (M_PI*0.0055555555556);
  371. cosx = cos(x);
  372. sinx = sin(x);
  373. cosy = cos(y);
  374. siny = sin(y);
  375. cosz = cos(z);
  376. sinz = sin(z);
  377. m[0] = cosz*cosy;
  378. m[1] = cosz*siny*sinx-sinz*cosx;
  379. m[2] = cosz*siny*cosx+sinz*sinx;
  380. m[4] = sinz*cosy;
  381. m[5] = sinz*siny*sinx+cosz*cosx;
  382. m[6] = sinz*siny*cosx-cosz*sinx;
  383. m[8] = -siny;
  384. m[9] = cosy*sinx;
  385. m[10] = cosy*cosx;
  386. m[3]=m[7]=m[11]=m[12]=m[13]=m[14]=0.0;
  387. m[15]=1.0;
  388. }
  389. void
  390. anim_zyx2mat(mat_t m, const vect_t a)
  391. {
  392. fastf_t cosX, cosY, cosZ, sinX, sinY, sinZ;
  393. cosX = cos(a[0]);
  394. cosY = cos(a[1]);
  395. cosZ = cos(a[2]);
  396. sinX = sin(a[0]);
  397. sinY = sin(a[1]);
  398. sinZ = sin(a[2]);
  399. m[0] = cosY*cosZ;
  400. m[1] = -cosY*sinZ;
  401. m[2] = sinY;
  402. m[3] = 0;
  403. m[4] = cosX*sinZ + sinX*sinY*cosZ;
  404. m[5] = cosX*cosZ - sinX*sinY*sinZ;
  405. m[6] = -sinX*cosY;
  406. m[7] = 0;
  407. m[8] = sinX*sinZ - cosX*sinY*cosZ;
  408. m[9] = sinX*cosZ + cosX*sinY*sinZ;
  409. m[10] = cosX*cosY;
  410. m[11] = 0.0;
  411. m[12] = 0.0;
  412. m[13] = 0.0;
  413. m[14] = 0.0;
  414. m[15] = 1.0;
  415. }
  416. void
  417. anim_z_y_x2mat(mat_t m, double x, double y, double z)
  418. {
  419. fastf_t cosx = cos(x);
  420. fastf_t sinx = sin(x);
  421. fastf_t cosy = cos(y);
  422. fastf_t siny = sin(y);
  423. fastf_t cosz = cos(z);
  424. fastf_t sinz = sin(z);
  425. m[0] = cosy*cosz;
  426. m[1] = -cosy*sinz;
  427. m[2] = siny;
  428. m[4] = cosx*sinz + sinx*siny*cosz;
  429. m[5] = cosx*cosz - sinx*siny*sinz;
  430. m[6] = -sinx*cosy;
  431. m[8] = sinx*sinz - cosx*siny*cosz;
  432. m[9] = sinx*cosz + cosx*siny*sinz;
  433. m[10]= cosx*cosy;
  434. m[3]=m[7]=m[11]=m[12]=m[13]=m[14]=0.0;
  435. m[15]=1.0;
  436. }
  437. void
  438. anim_dz_y_x2mat(mat_t m, double x, double y, double z)
  439. {
  440. fastf_t cosx, cosy, cosz, sinx, siny, sinz;
  441. x *= (M_PI*0.0055555555556);
  442. y *= (M_PI*0.0055555555556);
  443. z *= (M_PI*0.0055555555556);
  444. cosx = cos(x);
  445. sinx = sin(x);
  446. cosy = cos(y);
  447. siny = sin(y);
  448. cosz = cos(z);
  449. sinz = sin(z);
  450. m[0] = cosy*cosz;
  451. m[1] = -cosy*sinz;
  452. m[2] = siny;
  453. m[4] = cosx*sinz + sinx*siny*cosz;
  454. m[5] = cosx*cosz - sinx*siny*sinz;
  455. m[6] = -sinx*cosy;
  456. m[8] = sinx*sinz - cosx*siny*cosz;
  457. m[9] = sinx*cosz + cosx*siny*sinz;
  458. m[10]= cosx*cosy;
  459. m[3]=m[7]=m[11]=m[12]=m[13]=m[14]=0;
  460. m[15]=1;
  461. }
  462. void
  463. anim_quat2mat(mat_t m, const quat_t qq)
  464. {
  465. fastf_t two_q[4];
  466. quat_t q;
  467. QMOVE(q, qq);
  468. QUNITIZE(q);
  469. VADD2N(two_q, q, q, 4);
  470. m[0] = 1.0 - two_q[Y]*q[Y] - two_q[Z]*q[Z];
  471. m[1] = two_q[X]*q[Y] - two_q[W]*q[Z];
  472. m[2] = two_q[X]*q[Z] + two_q[W]*q[Y];
  473. m[3] = 0.0;
  474. m[4] = two_q[X]*q[Y] + two_q[W]*q[Z];
  475. m[5] = 1.0 - two_q[X]*q[X] - two_q[Z]*q[Z];
  476. m[6] = two_q[Y]*q[Z] - two_q[W]*q[X];
  477. m[7] = 0.0;
  478. m[8] = two_q[X]*q[Z] - two_q[W]*q[Y];
  479. m[9] = two_q[Y]*q[Z] + two_q[W]*q[X];
  480. m[10] = 1.0 - two_q[X]*q[X] - two_q[Y]*q[Y];
  481. m[11] = 0.0;
  482. m[12] = 0.0;
  483. m[13] = 0.0;
  484. m[14] = 0.0;
  485. m[15] = 1.0;
  486. }
  487. void
  488. anim_dir2mat(mat_t m, const vect_t d, const vect_t d2b)
  489. {
  490. fastf_t hypotenuse, sign;
  491. vect_t d2;
  492. VMOVE(d2, d2b);
  493. sign = 1.0;
  494. hypotenuse = sqrt(d[0]*d[0]+d[1]*d[1]);
  495. if (hypotenuse < VDIVIDE_TOL) {
  496. /* vertical direction - use d2 to determine roll */
  497. hypotenuse = sqrt(d2[0]*d2[0]+d2[1]*d2[1]);
  498. if (hypotenuse < VDIVIDE_TOL) {
  499. /* use x-axis as default*/
  500. VSET(d2, 1, 0, 0);
  501. hypotenuse = 1;
  502. }
  503. if (d[2] < 0)
  504. sign = -1.0;
  505. m[1] = -d2[1]/hypotenuse;
  506. m[5] = d2[0]/hypotenuse;
  507. m[2] = -sign * d2[0]/hypotenuse;
  508. m[6] = -sign * d2[1]/hypotenuse;
  509. m[8] = sign;
  510. m[0]=m[4]=m[9]=m[10]=0.0;
  511. } else {
  512. /* normal - no roll*/
  513. m[0] = d[0];
  514. m[1] = -d[1]/hypotenuse;
  515. m[2] = -d[0]*d[2]/hypotenuse;
  516. m[4] = d[1];
  517. m[5] = d[0]/hypotenuse;
  518. m[6] = -d[1]*d[2]/hypotenuse;
  519. m[8] = d[2];
  520. m[9] = 0.0;
  521. m[10] = hypotenuse;
  522. }
  523. m[3]=m[7]=m[11]=0.0;
  524. m[12]=m[13]=m[14]=0.0;
  525. m[15]=1.0;
  526. }
  527. void
  528. anim_dirn2mat(mat_t m, const vect_t dx2, const vect_t dn)
  529. {
  530. vect_t temp;
  531. fastf_t hyp, sign, inv, mag;
  532. vect_t dx;
  533. VMOVE(dx, dx2);
  534. sign = 1.0;
  535. mag = MAGNITUDE(dx);
  536. if (mag < VDIVIDE_TOL) {
  537. bu_log("anim_dirn2mat: Need non-zero vector");
  538. return;
  539. }
  540. inv = 1.0/mag;
  541. dx[0] *= inv;
  542. dx[1] *= inv;
  543. dx[2] *= inv;
  544. hyp = sqrt(dx[0]*dx[0]+dx[1]*dx[1]);
  545. if (hyp < VDIVIDE_TOL) {
  546. /* vertical - special handling */
  547. sign = (dx[2] < 0) ? -1.0 : 1.0;
  548. VSET(temp, dn[0], dn[1], 0.0);
  549. mag = MAGNITUDE(temp);
  550. if (mag < VDIVIDE_TOL) {
  551. /* use default */
  552. VSET(temp, 0.0, 1.0, 0.0);
  553. mag = 1.0;
  554. } else {
  555. inv = 1.0/mag;
  556. temp[0] *= inv;
  557. temp[1] *= inv;
  558. }
  559. m[0] = 0.0;
  560. m[4] = 0.0;
  561. m[8] = sign;
  562. m[1] = temp[0];
  563. m[5] = temp[1];
  564. m[9] = 0.0;
  565. m[2] = -sign*temp[1];
  566. m[6] = sign*temp[0];
  567. m[10] = 0.0;
  568. m[3]=m[7]=m[11]=0.0;
  569. m[12]=m[13]=m[14]=0.0;
  570. m[15]=1.0;
  571. return;
  572. }
  573. /*else normal*/
  574. m[0] = dx[0];
  575. m[1] = -dx[1]/hyp;
  576. m[2] = -dx[0]*dx[2]/hyp;
  577. m[4] = dx[1];
  578. m[5] = dx[0]/hyp;
  579. m[6] = -dx[1]*dx[2]/hyp;
  580. m[8] = dx[2];
  581. m[9] = 0.0;
  582. m[10] = hyp;
  583. m[3]=m[7]=m[11]=0.0;
  584. m[12]=m[13]=m[14]=0.0;
  585. m[15]=1.0;
  586. }
  587. #define ASM_EMPTY 0
  588. #define ASM_FIRST 1
  589. #define ASM_FULL 2
  590. int
  591. anim_steer_mat(mat_t mat, vect_t point, int end)
  592. {
  593. static vect_t p1, p2, p3;
  594. vect_t dir;
  595. static vect_t norm;
  596. static int state = ASM_EMPTY;
  597. VMOVE(p1, p2);
  598. VMOVE(p2, p3);
  599. VMOVE(p3, point);
  600. switch (state) {
  601. case ASM_EMPTY:
  602. if (end) {
  603. state = ASM_EMPTY;
  604. } else {
  605. state = ASM_FIRST;
  606. /* "don't print yet */
  607. }
  608. return 0;
  609. case ASM_FIRST:
  610. if (end) {
  611. /* only one point specified, use default direction */
  612. VSET(dir, 1.0, 0.0, 0.0);
  613. VSET(norm, 0.0, 1.0, 0.0);
  614. state = ASM_EMPTY;
  615. } else {
  616. VSUBUNIT(dir, p3, p2);
  617. VSET(norm, 0.0, 1.0, 0.0);
  618. state = ASM_FULL;
  619. }
  620. break;
  621. case ASM_FULL:
  622. if (end) {
  623. VSUBUNIT(dir, p2, p1);
  624. state = ASM_EMPTY;
  625. } else {
  626. VSUBUNIT(dir, p3, p1);
  627. state = ASM_FULL;
  628. }
  629. }
  630. /* go for it */
  631. anim_dirn2mat(mat, dir, norm); /* create basic rotation matrix */
  632. VSET(norm, mat[1], mat[5], 0.0); /* save for next time */
  633. VMOVE(point, p2); /* for main's purposes, the current point is p2 */
  634. return 1; /* return signal go ahead and print */
  635. }
  636. /***************************************
  637. * Other animation routines
  638. ***************************************/
  639. void
  640. anim_add_trans(mat_t m, const vect_t post, const vect_t pre)
  641. {
  642. int i;
  643. for (i=0; i<3; i++)
  644. m[3+i*4] += m[i*4]*pre[0] + m[1+i*4]*pre[1]+m[2+i*4]*pre[2] + post[i];
  645. }
  646. void
  647. anim_rotatez(fastf_t a, vect_t d)
  648. {
  649. fastf_t temp[3];
  650. fastf_t cos_y = cos(a);
  651. fastf_t sin_y = sin(a);
  652. temp[0] = d[0]*cos_y - d[1]*sin_y;
  653. temp[1] = d[0]*sin_y + d[1]*cos_y;
  654. d[0]=temp[0];
  655. d[1]=temp[1];
  656. }
  657. void
  658. anim_mat_print(FILE *fp, const mat_t m, int s_colon)
  659. {
  660. bu_flog(fp, "%.10g %.10g %.10g %.10g\n", m[0], m[1], m[2], m[3]);
  661. bu_flog(fp, "%.10g %.10g %.10g %.10g\n", m[4], m[5], m[6], m[7]);
  662. bu_flog(fp, "%.10g %.10g %.10g %.10g\n", m[8], m[9], m[10], m[11]);
  663. bu_flog(fp, "%.10g %.10g %.10g %.10g", m[12], m[13], m[14], m[15]);
  664. if (s_colon)
  665. bu_flog(fp, ";");
  666. bu_flog(fp, "\n");
  667. }
  668. void
  669. anim_mat_printf(
  670. FILE *fp,
  671. const mat_t m,
  672. const char *formstr,
  673. const char *linestr,
  674. const char *endstr)
  675. {
  676. char mystr[80];
  677. snprintf(mystr, 80, "%s%s%s%s%%s", formstr, formstr, formstr, formstr);
  678. bu_flog(fp, mystr, m[0], m[1], m[2], m[3], linestr);
  679. bu_flog(fp, mystr, m[4], m[5], m[6], m[7], linestr);
  680. bu_flog(fp, mystr, m[8], m[9], m[10], m[11], linestr);
  681. bu_flog(fp, mystr, m[12], m[13], m[14], m[15], endstr);
  682. }
  683. void
  684. anim_view_rev(mat_t m)
  685. {
  686. m[0] = -m[0];
  687. m[1] = -m[1];
  688. m[4] = -m[4];
  689. m[5] = -m[5];
  690. m[8] = -m[8];
  691. m[9] = -m[9];
  692. }
  693. /*
  694. * Local Variables:
  695. * mode: C
  696. * tab-width: 8
  697. * indent-tabs-mode: t
  698. * c-file-style: "stroustrup"
  699. * End:
  700. * ex: shiftwidth=4 tabstop=8
  701. */