vecmath.cpp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  1. //
  2. //
  3. // Typical 3d vector math code.
  4. // By S Melax 1998-2008
  5. //
  6. //
  7. //
  8. #include "vecmath.h"
  9. #include <memory.h> // for memcpy
  10. #include <float.h>
  11. float squared(float a){return a*a;}
  12. float clamp(float a,const float minval, const float maxval) {return Min(maxval,Max(minval,a));}
  13. int clamp(int a,const int minval, const int maxval) {return Min(maxval,Max(minval,a));}
  14. float Round(float a,float precision)
  15. {
  16. return floorf(0.5f+a/precision)*precision;
  17. }
  18. float Interpolate(const float &f0,const float &f1,float alpha)
  19. {
  20. return f0*(1-alpha) + f1*alpha;
  21. }
  22. int argmin(const float a[],int n)
  23. {
  24. int r=0;
  25. for(int i=1;i<n;i++)
  26. {
  27. if(a[i]<a[r])
  28. {
  29. r = i;
  30. }
  31. }
  32. return r;
  33. }
  34. int argmax(const float a[],int n)
  35. {
  36. int r=0;
  37. for(int i=1;i<n;i++)
  38. {
  39. if(a[i]>a[r])
  40. {
  41. r = i;
  42. }
  43. }
  44. return r;
  45. }
  46. //------------ float3 (3D) --------------
  47. float3 vabs(const float3 &v)
  48. {
  49. return float3(fabsf(v.x),fabsf(v.y),fabsf(v.z));
  50. }
  51. float3 safenormalize(const float3 &v)
  52. {
  53. if(magnitude(v)<=0.0f)
  54. {
  55. return float3(1,0,0);
  56. }
  57. return normalize(v);
  58. }
  59. float3 Round(const float3 &a,float precision)
  60. {
  61. return float3(Round(a.x,precision),Round(a.y,precision),Round(a.z,precision));
  62. }
  63. float3 Interpolate(const float3 &v0,const float3 &v1,float alpha)
  64. {
  65. return v0*(1-alpha) + v1*alpha;
  66. }
  67. float3 Orth(const float3& v)
  68. {
  69. float3 absv=vabs(v);
  70. float3 u(1,1,1);
  71. u[argmax(&absv[0],3)] =0.0f;
  72. return normalize(cross(u,v));
  73. }
  74. void BoxLimits(const float3 *verts,int verts_count, float3 &bmin,float3 &bmax)
  75. {
  76. bmin=float3( FLT_MAX, FLT_MAX, FLT_MAX);
  77. bmax=float3(-FLT_MAX,-FLT_MAX,-FLT_MAX);
  78. for(int i=0;i<verts_count;i++)
  79. {
  80. bmin = VectorMin(bmin,verts[i]);
  81. bmax = VectorMax(bmax,verts[i]);
  82. }
  83. }
  84. void BoxLimits(const float4 *verts,int verts_count, float3 &bmin,float3 &bmax)
  85. {
  86. bmin=float3( FLT_MAX, FLT_MAX, FLT_MAX);
  87. bmax=float3(-FLT_MAX,-FLT_MAX,-FLT_MAX);
  88. for(int i=0;i<verts_count;i++)
  89. {
  90. bmin = VectorMin(bmin,verts[i].xyz());
  91. bmax = VectorMax(bmax,verts[i].xyz());
  92. }
  93. }
  94. int overlap(const float3 &bmina,const float3 &bmaxa,const float3 &bminb,const float3 &bmaxb)
  95. {
  96. for(int j=0;j<3;j++)
  97. {
  98. if(bmina[j]>bmaxb[j]) return 0;
  99. if(bminb[j]>bmaxa[j]) return 0;
  100. }
  101. return 1;
  102. }
  103. // the statement v1*v2 is ambiguous since there are 3 types
  104. // of vector multiplication
  105. // - componantwise (for example combining colors)
  106. // - dot product
  107. // - cross product
  108. // Therefore we never declare/implement this function.
  109. // So we will never see: float3 operator*(float3 a,float3 b)
  110. //------------ float3x3 ---------------
  111. float Determinant(const float3x3 &m)
  112. {
  113. return m.x.x*m.y.y*m.z.z + m.y.x*m.z.y*m.x.z + m.z.x*m.x.y*m.y.z
  114. -m.x.x*m.z.y*m.y.z - m.y.x*m.x.y*m.z.z - m.z.x*m.y.y*m.x.z ;
  115. }
  116. float3x3 Inverse(const float3x3 &a)
  117. {
  118. float3x3 b;
  119. float d=Determinant(a);
  120. assert(d!=0);
  121. for(int i=0;i<3;i++)
  122. {
  123. for(int j=0;j<3;j++)
  124. {
  125. int i1=(i+1)%3;
  126. int i2=(i+2)%3;
  127. int j1=(j+1)%3;
  128. int j2=(j+2)%3;
  129. // reverse indexs i&j to take transpose
  130. b[j][i] = (a[i1][j1]*a[i2][j2]-a[i1][j2]*a[i2][j1])/d;
  131. }
  132. }
  133. // Matrix check=a*b; // Matrix 'check' should be the identity (or close to it)
  134. return b;
  135. }
  136. float3x3 Transpose( const float3x3& m )
  137. {
  138. return float3x3( float3(m.x.x,m.y.x,m.z.x),
  139. float3(m.x.y,m.y.y,m.z.y),
  140. float3(m.x.z,m.y.z,m.z.z));
  141. }
  142. float3 operator*(const float3& v , const float3x3 &m ) {
  143. return float3((m.x.x*v.x + m.y.x*v.y + m.z.x*v.z),
  144. (m.x.y*v.x + m.y.y*v.y + m.z.y*v.z),
  145. (m.x.z*v.x + m.y.z*v.y + m.z.z*v.z));
  146. }
  147. float3 operator*(const float3x3 &m,const float3& v ) {
  148. return float3(dot(m.x,v),dot(m.y,v),dot(m.z,v));
  149. }
  150. float3x3 operator*( const float3x3& a, const float3x3& b )
  151. {
  152. return float3x3(a.x*b,a.y*b,a.z*b);
  153. }
  154. float3x3 operator*( const float3x3& a, const float& s )
  155. {
  156. return float3x3(a.x*s, a.y*s ,a.z*s);
  157. }
  158. float3x3 operator/( const float3x3& a, const float& s )
  159. {
  160. float t=1/s;
  161. return float3x3(a.x*t, a.y*t ,a.z*t);
  162. }
  163. float3x3 operator+( const float3x3& a, const float3x3& b )
  164. {
  165. return float3x3(a.x+b.x, a.y+b.y, a.z+b.z);
  166. }
  167. float3x3 operator-( const float3x3& a, const float3x3& b )
  168. {
  169. return float3x3(a.x-b.x, a.y-b.y, a.z-b.z);
  170. }
  171. float3x3 &operator+=( float3x3& a, const float3x3& b )
  172. {
  173. a.x+=b.x;
  174. a.y+=b.y;
  175. a.z+=b.z;
  176. return a;
  177. }
  178. float3x3 &operator-=( float3x3& a, const float3x3& b )
  179. {
  180. a.x-=b.x;
  181. a.y-=b.y;
  182. a.z-=b.z;
  183. return a;
  184. }
  185. float3x3 &operator*=( float3x3& a, const float& s )
  186. {
  187. a.x*=s;
  188. a.y*=s;
  189. a.z*=s;
  190. return a;
  191. }
  192. float3x3 outerprod(const float3& a,const float3& b)
  193. {
  194. return float3x3(a.x*b,a.y*b,a.z*b); // a is a column vector b is a row vector
  195. }
  196. //--------------- 4D ----------------
  197. float4 operator*( const float4& v, const float4x4& m )
  198. {
  199. return v.x*m.x + v.y*m.y + v.z*m.z + v.w*m.w; // yes this actually works
  200. }
  201. // Dont implement m*v for now, since that might confuse us
  202. // All our transforms are based on multiplying the "row" vector on the left
  203. //float4 operator*(const float4x4& m , const float4& v )
  204. //{
  205. // return float4(dot(v,m.x),dot(v,m.y),dot(v,m.z),dot(v,m.w));
  206. //}
  207. float4x4 operator*( const float4x4& a, const float4x4& b )
  208. {
  209. return float4x4(a.x*b,a.y*b,a.z*b,a.w*b);
  210. }
  211. float4x4 MatrixTranspose(const float4x4 &m)
  212. {
  213. return float4x4(
  214. m.x.x, m.y.x, m.z.x, m.w.x,
  215. m.x.y, m.y.y, m.z.y, m.w.y,
  216. m.x.z, m.y.z, m.z.z, m.w.z,
  217. m.x.w, m.y.w, m.z.w, m.w.w );
  218. }
  219. float4x4 MatrixRigidInverse(const float4x4 &m)
  220. {
  221. float4x4 trans_inverse = MatrixTranslation(-m.w.xyz());
  222. float4x4 rot = m;
  223. rot.w = float4(0,0,0,1);
  224. return trans_inverse * MatrixTranspose(rot);
  225. }
  226. float4x4 MatrixPerspectiveFov(float fovy, float aspect, float zn, float zf )
  227. {
  228. float h = 1.0f/tanf(fovy/2.0f); // view space height
  229. float w = h / aspect ; // view space width
  230. return float4x4(
  231. w, 0, 0 , 0,
  232. 0, h, 0 , 0,
  233. 0, 0, zf/(zn-zf) , -1,
  234. 0, 0, zn*zf/(zn-zf) , 0 );
  235. }
  236. float4x4 MatrixLookAt(const float3& eye, const float3& at, const float3& up)
  237. {
  238. float4x4 m;
  239. m.w.w = 1.0f;
  240. m.w.xyz() = eye;
  241. m.z.xyz() = normalize(eye-at);
  242. m.x.xyz() = normalize(cross(up,m.z.xyz()));
  243. m.y.xyz() = cross(m.z.xyz(),m.x.xyz());
  244. return MatrixRigidInverse(m);
  245. }
  246. float4x4 MatrixTranslation(const float3 &t)
  247. {
  248. return float4x4(
  249. 1, 0, 0, 0,
  250. 0, 1, 0, 0,
  251. 0, 0, 1, 0,
  252. t.x,t.y,t.z,1 );
  253. }
  254. float4x4 MatrixRotationZ(const float angle_radians)
  255. {
  256. float s = sinf(angle_radians);
  257. float c = cosf(angle_radians);
  258. return float4x4(
  259. c, s, 0, 0,
  260. -s, c, 0, 0,
  261. 0, 0, 1, 0,
  262. 0, 0, 0, 1 );
  263. }
  264. int operator==( const float4x4 &a, const float4x4 &b )
  265. {
  266. return (a.x==b.x && a.y==b.y && a.z==b.z && a.w==b.w);
  267. }
  268. float4x4 Inverse(const float4x4 &m)
  269. {
  270. float4x4 d;
  271. float *dst = &d.x.x;
  272. float tmp[12]; /* temp array for pairs */
  273. float src[16]; /* array of transpose source matrix */
  274. float det; /* determinant */
  275. /* transpose matrix */
  276. for ( int i = 0; i < 4; i++) {
  277. src[i] = m(i,0) ;
  278. src[i + 4] = m(i,1);
  279. src[i + 8] = m(i,2);
  280. src[i + 12] = m(i,3);
  281. }
  282. /* calculate pairs for first 8 elements (cofactors) */
  283. tmp[0] = src[10] * src[15];
  284. tmp[1] = src[11] * src[14];
  285. tmp[2] = src[9] * src[15];
  286. tmp[3] = src[11] * src[13];
  287. tmp[4] = src[9] * src[14];
  288. tmp[5] = src[10] * src[13];
  289. tmp[6] = src[8] * src[15];
  290. tmp[7] = src[11] * src[12];
  291. tmp[8] = src[8] * src[14];
  292. tmp[9] = src[10] * src[12];
  293. tmp[10] = src[8] * src[13];
  294. tmp[11] = src[9] * src[12];
  295. /* calculate first 8 elements (cofactors) */
  296. dst[0] = tmp[0]*src[5] + tmp[3]*src[6] + tmp[4]*src[7];
  297. dst[0] -= tmp[1]*src[5] + tmp[2]*src[6] + tmp[5]*src[7];
  298. dst[1] = tmp[1]*src[4] + tmp[6]*src[6] + tmp[9]*src[7];
  299. dst[1] -= tmp[0]*src[4] + tmp[7]*src[6] + tmp[8]*src[7];
  300. dst[2] = tmp[2]*src[4] + tmp[7]*src[5] + tmp[10]*src[7];
  301. dst[2] -= tmp[3]*src[4] + tmp[6]*src[5] + tmp[11]*src[7];
  302. dst[3] = tmp[5]*src[4] + tmp[8]*src[5] + tmp[11]*src[6];
  303. dst[3] -= tmp[4]*src[4] + tmp[9]*src[5] + tmp[10]*src[6];
  304. dst[4] = tmp[1]*src[1] + tmp[2]*src[2] + tmp[5]*src[3];
  305. dst[4] -= tmp[0]*src[1] + tmp[3]*src[2] + tmp[4]*src[3];
  306. dst[5] = tmp[0]*src[0] + tmp[7]*src[2] + tmp[8]*src[3];
  307. dst[5] -= tmp[1]*src[0] + tmp[6]*src[2] + tmp[9]*src[3];
  308. dst[6] = tmp[3]*src[0] + tmp[6]*src[1] + tmp[11]*src[3];
  309. dst[6] -= tmp[2]*src[0] + tmp[7]*src[1] + tmp[10]*src[3];
  310. dst[7] = tmp[4]*src[0] + tmp[9]*src[1] + tmp[10]*src[2];
  311. dst[7] -= tmp[5]*src[0] + tmp[8]*src[1] + tmp[11]*src[2];
  312. /* calculate pairs for second 8 elements (cofactors) */
  313. tmp[0] = src[2]*src[7];
  314. tmp[1] = src[3]*src[6];
  315. tmp[2] = src[1]*src[7];
  316. tmp[3] = src[3]*src[5];
  317. tmp[4] = src[1]*src[6];
  318. tmp[5] = src[2]*src[5];
  319. tmp[6] = src[0]*src[7];
  320. tmp[7] = src[3]*src[4];
  321. tmp[8] = src[0]*src[6];
  322. tmp[9] = src[2]*src[4];
  323. tmp[10] = src[0]*src[5];
  324. tmp[11] = src[1]*src[4];
  325. /* calculate second 8 elements (cofactors) */
  326. dst[8] = tmp[0]*src[13] + tmp[3]*src[14] + tmp[4]*src[15];
  327. dst[8] -= tmp[1]*src[13] + tmp[2]*src[14] + tmp[5]*src[15];
  328. dst[9] = tmp[1]*src[12] + tmp[6]*src[14] + tmp[9]*src[15];
  329. dst[9] -= tmp[0]*src[12] + tmp[7]*src[14] + tmp[8]*src[15];
  330. dst[10] = tmp[2]*src[12] + tmp[7]*src[13] + tmp[10]*src[15];
  331. dst[10]-= tmp[3]*src[12] + tmp[6]*src[13] + tmp[11]*src[15];
  332. dst[11] = tmp[5]*src[12] + tmp[8]*src[13] + tmp[11]*src[14];
  333. dst[11]-= tmp[4]*src[12] + tmp[9]*src[13] + tmp[10]*src[14];
  334. dst[12] = tmp[2]*src[10] + tmp[5]*src[11] + tmp[1]*src[9];
  335. dst[12]-= tmp[4]*src[11] + tmp[0]*src[9] + tmp[3]*src[10];
  336. dst[13] = tmp[8]*src[11] + tmp[0]*src[8] + tmp[7]*src[10];
  337. dst[13]-= tmp[6]*src[10] + tmp[9]*src[11] + tmp[1]*src[8];
  338. dst[14] = tmp[6]*src[9] + tmp[11]*src[11] + tmp[3]*src[8];
  339. dst[14]-= tmp[10]*src[11] + tmp[2]*src[8] + tmp[7]*src[9];
  340. dst[15] = tmp[10]*src[10] + tmp[4]*src[8] + tmp[9]*src[9];
  341. dst[15]-= tmp[8]*src[9] + tmp[11]*src[10] + tmp[5]*src[8];
  342. /* calculate determinant */
  343. det=src[0]*dst[0]+src[1]*dst[1]+src[2]*dst[2]+src[3]*dst[3];
  344. /* calculate matrix inverse */
  345. det = 1/det;
  346. for ( int j = 0; j < 16; j++)
  347. dst[j] *= det;
  348. return d;
  349. }
  350. //--------- Quaternion --------------
  351. template<> void Quaternion::Normalize()
  352. {
  353. float m = sqrtf(squared(w)+squared(x)+squared(y)+squared(z));
  354. if(m<0.000000001f) {
  355. w=1.0f;
  356. x=y=z=0.0f;
  357. return;
  358. }
  359. (*this) *= (1.0f/m);
  360. }
  361. float3 rotate( const Quaternion& q, const float3& v )
  362. {
  363. // The following is equivalent to:
  364. //return (q.getmatrix() * v);
  365. float qx2 = q.x*q.x;
  366. float qy2 = q.y*q.y;
  367. float qz2 = q.z*q.z;
  368. float qxqy = q.x*q.y;
  369. float qxqz = q.x*q.z;
  370. float qxqw = q.x*q.w;
  371. float qyqz = q.y*q.z;
  372. float qyqw = q.y*q.w;
  373. float qzqw = q.z*q.w;
  374. return float3(
  375. (1-2*(qy2+qz2))*v.x + (2*(qxqy-qzqw))*v.y + (2*(qxqz+qyqw))*v.z ,
  376. (2*(qxqy+qzqw))*v.x + (1-2*(qx2+qz2))*v.y + (2*(qyqz-qxqw))*v.z ,
  377. (2*(qxqz-qyqw))*v.x + (2*(qyqz+qxqw))*v.y + (1-2*(qx2+qy2))*v.z );
  378. }
  379. Quaternion slerp(const Quaternion &_a, const Quaternion& b, float interp )
  380. {
  381. Quaternion a=_a;
  382. if(dot(a,b) <0.0)
  383. {
  384. a.w=-a.w;
  385. a.x=-a.x;
  386. a.y=-a.y;
  387. a.z=-a.z;
  388. }
  389. float d = dot(a,b);
  390. if(d>=1.0) {
  391. return a;
  392. }
  393. float theta = acosf(d);
  394. if(theta==0.0f) { return(a);}
  395. return a*(sinf(theta-interp*theta)/sinf(theta)) + b*(sinf(interp*theta)/sinf(theta));
  396. }
  397. Quaternion Interpolate(const Quaternion &q0,const Quaternion &q1,float alpha) {
  398. return slerp(q0,q1,alpha);
  399. }
  400. Quaternion YawPitchRoll( float yaw, float pitch, float roll )
  401. {
  402. return QuatFromAxisAngle(float3(0.0f,0.0f,1.0f),DegToRad(yaw ))
  403. * QuatFromAxisAngle(float3(1.0f,0.0f,0.0f),DegToRad(pitch))
  404. * QuatFromAxisAngle(float3(0.0f,1.0f,0.0f),DegToRad(roll ));
  405. }
  406. float Yaw( const Quaternion& q )
  407. {
  408. static float3 v;
  409. v=q.ydir();
  410. return (v.y==0.0&&v.x==0.0) ? 0.0f: RadToDeg(atan2f(-v.x,v.y));
  411. }
  412. float Pitch( const Quaternion& q )
  413. {
  414. static float3 v;
  415. v=q.ydir();
  416. return RadToDeg(atan2f(v.z,sqrtf(squared(v.x)+squared(v.y))));
  417. }
  418. float Roll( const Quaternion &_q )
  419. {
  420. Quaternion q=_q;
  421. q = QuatFromAxisAngle(float3(0.0f,0.0f,1.0f),-DegToRad(Yaw(q))) *q;
  422. q = QuatFromAxisAngle(float3(1.0f,0.0f,0.0f),-DegToRad(Pitch(q))) *q;
  423. return RadToDeg(atan2f(-q.xdir().z,q.xdir().x));
  424. }
  425. float Yaw( const float3& v )
  426. {
  427. return (v.y==0.0&&v.x==0.0) ? 0.0f: RadToDeg(atan2f(-v.x,v.y));
  428. }
  429. float Pitch( const float3& v )
  430. {
  431. return RadToDeg(atan2f(v.z,sqrtf(squared(v.x)+squared(v.y))));
  432. }
  433. //--------- utility functions -------------
  434. // RotationArc()
  435. // Given two vectors v0 and v1 this function
  436. // returns quaternion q where q*v0==v1.
  437. // Routine taken from game programming gems.
  438. Quaternion RotationArc(float3 v0,float3 v1){
  439. static Quaternion q;
  440. v0 = normalize(v0); // Comment these two lines out if you know its not needed.
  441. v1 = normalize(v1); // If vector is already unit length then why do it again?
  442. float3 c = cross(v0,v1);
  443. float d = dot(v0,v1);
  444. if(d<=-1.0f) { float3 a=Orth(v0); return Quaternion(a.x,a.y,a.z,0);} // 180 about any orthogonal axis axis
  445. float s = sqrtf((1+d)*2);
  446. q.x = c.x / s;
  447. q.y = c.y / s;
  448. q.z = c.z / s;
  449. q.w = s /2.0f;
  450. return q;
  451. }
  452. float4x4 MatrixFromQuatVec(const Quaternion &q, const float3 &v)
  453. {
  454. // builds a 4x4 transformation matrix based on orientation q and translation v
  455. float qx2 = q.x*q.x;
  456. float qy2 = q.y*q.y;
  457. float qz2 = q.z*q.z;
  458. float qxqy = q.x*q.y;
  459. float qxqz = q.x*q.z;
  460. float qxqw = q.x*q.w;
  461. float qyqz = q.y*q.z;
  462. float qyqw = q.y*q.w;
  463. float qzqw = q.z*q.w;
  464. return float4x4(
  465. 1-2*(qy2+qz2),
  466. 2*(qxqy+qzqw),
  467. 2*(qxqz-qyqw),
  468. 0 ,
  469. 2*(qxqy-qzqw),
  470. 1-2*(qx2+qz2),
  471. 2*(qyqz+qxqw),
  472. 0 ,
  473. 2*(qxqz+qyqw),
  474. 2*(qyqz-qxqw),
  475. 1-2*(qx2+qy2),
  476. 0 ,
  477. v.x ,
  478. v.y ,
  479. v.z ,
  480. 1.0f );
  481. }
  482. float3 PlaneLineIntersection(const float3 &normal,const float dist, const float3 &p0, const float3 &p1)
  483. {
  484. // returns the point where the line p0-p1 intersects the plane n&d
  485. float3 dif;
  486. dif = p1-p0;
  487. float dn= dot(normal,dif);
  488. float t = -(dist+dot(normal,p0) )/dn;
  489. return p0 + (dif*t);
  490. }
  491. float3 LineProject(const float3 &p0, const float3 &p1, const float3 &a)
  492. {
  493. // project point a on segment [p0,p1]
  494. float3 d= p1-p0;
  495. float t= dot(d,(a-p0)) / dot(d,d);
  496. return p0+ d*t;
  497. }
  498. float LineProjectTime(const float3 &p0, const float3 &p1, const float3 &a)
  499. {
  500. // project point a on segment [p0,p1]
  501. float3 d= p1-p0;
  502. float t= dot(d,(a-p0)) / dot(d,d);
  503. return t;
  504. }
  505. float3 TriNormal(const float3 &v0, const float3 &v1, const float3 &v2)
  506. {
  507. // return the normal of the triangle
  508. // inscribed by v0, v1, and v2
  509. float3 cp=cross(v1-v0,v2-v1);
  510. float m=magnitude(cp);
  511. if(m==0) return float3(1,0,0);
  512. return cp*(1.0f/m);
  513. }
  514. int BoxInside(const float3 &p, const float3 &bmin, const float3 &bmax)
  515. {
  516. return (p.x >= bmin.x && p.x <=bmax.x &&
  517. p.y >= bmin.y && p.y <=bmax.y &&
  518. p.z >= bmin.z && p.z <=bmax.z );
  519. }
  520. int BoxIntersect(const float3 &v0, const float3 &v1, const float3 &bmin, const float3 &bmax,float3 *impact)
  521. {
  522. if(BoxInside(v0,bmin,bmax))
  523. {
  524. *impact=v0;
  525. return 1;
  526. }
  527. if(v0.x<=bmin.x && v1.x>=bmin.x)
  528. {
  529. float a = (bmin.x-v0.x)/(v1.x-v0.x);
  530. //v.x = bmin.x;
  531. float vy = (1-a) *v0.y + a*v1.y;
  532. float vz = (1-a) *v0.z + a*v1.z;
  533. if(vy>=bmin.y && vy<=bmax.y && vz>=bmin.z && vz<=bmax.z)
  534. {
  535. impact->x = bmin.x;
  536. impact->y = vy;
  537. impact->z = vz;
  538. return 1;
  539. }
  540. }
  541. else if(v0.x >= bmax.x && v1.x <= bmax.x)
  542. {
  543. float a = (bmax.x-v0.x)/(v1.x-v0.x);
  544. //v.x = bmax.x;
  545. float vy = (1-a) *v0.y + a*v1.y;
  546. float vz = (1-a) *v0.z + a*v1.z;
  547. if(vy>=bmin.y && vy<=bmax.y && vz>=bmin.z && vz<=bmax.z)
  548. {
  549. impact->x = bmax.x;
  550. impact->y = vy;
  551. impact->z = vz;
  552. return 1;
  553. }
  554. }
  555. if(v0.y<=bmin.y && v1.y>=bmin.y)
  556. {
  557. float a = (bmin.y-v0.y)/(v1.y-v0.y);
  558. float vx = (1-a) *v0.x + a*v1.x;
  559. //v.y = bmin.y;
  560. float vz = (1-a) *v0.z + a*v1.z;
  561. if(vx>=bmin.x && vx<=bmax.x && vz>=bmin.z && vz<=bmax.z)
  562. {
  563. impact->x = vx;
  564. impact->y = bmin.y;
  565. impact->z = vz;
  566. return 1;
  567. }
  568. }
  569. else if(v0.y >= bmax.y && v1.y <= bmax.y)
  570. {
  571. float a = (bmax.y-v0.y)/(v1.y-v0.y);
  572. float vx = (1-a) *v0.x + a*v1.x;
  573. // vy = bmax.y;
  574. float vz = (1-a) *v0.z + a*v1.z;
  575. if(vx>=bmin.x && vx<=bmax.x && vz>=bmin.z && vz<=bmax.z)
  576. {
  577. impact->x = vx;
  578. impact->y = bmax.y;
  579. impact->z = vz;
  580. return 1;
  581. }
  582. }
  583. if(v0.z<=bmin.z && v1.z>=bmin.z)
  584. {
  585. float a = (bmin.z-v0.z)/(v1.z-v0.z);
  586. float vx = (1-a) *v0.x + a*v1.x;
  587. float vy = (1-a) *v0.y + a*v1.y;
  588. // v.z = bmin.z;
  589. if(vy>=bmin.y && vy<=bmax.y && vx>=bmin.x && vx<=bmax.x)
  590. {
  591. impact->x = vx;
  592. impact->y = vy;
  593. impact->z = bmin.z;
  594. return 1;
  595. }
  596. }
  597. else if(v0.z >= bmax.z && v1.z <= bmax.z)
  598. {
  599. float a = (bmax.z-v0.z)/(v1.z-v0.z);
  600. float vx = (1-a) *v0.x + a*v1.x;
  601. float vy = (1-a) *v0.y + a*v1.y;
  602. // v.z = bmax.z;
  603. if(vy>=bmin.y && vy<=bmax.y && vx>=bmin.x && vx<=bmax.x)
  604. {
  605. impact->x = vx;
  606. impact->y = vy;
  607. impact->z = bmax.z;
  608. return 1;
  609. }
  610. }
  611. return 0;
  612. }
  613. float DistanceBetweenLines(const float3 &ustart, const float3 &udir, const float3 &vstart, const float3 &vdir, float3 *upoint, float3 *vpoint)
  614. {
  615. static float3 cp;
  616. cp = normalize(cross(udir,vdir));
  617. float distu = -dot(cp,ustart);
  618. float distv = -dot(cp,vstart);
  619. float dist = (float)fabs(distu-distv);
  620. if(upoint)
  621. {
  622. float3 normal = normalize(cross(vdir,cp));
  623. *upoint = PlaneLineIntersection(normal,-dot(normal,vstart),ustart,ustart+udir);
  624. }
  625. if(vpoint)
  626. {
  627. float3 normal = normalize(cross(udir,cp));
  628. *vpoint = PlaneLineIntersection(normal,-dot(normal,ustart),vstart,vstart+vdir);
  629. }
  630. return dist;
  631. }
  632. Quaternion VirtualTrackBall(const float3 &cop, const float3 &cor, const float3 &dir1, const float3 &dir2)
  633. {
  634. // routine taken from game programming gems.
  635. // Implement track ball functionality to spin stuf on the screen
  636. // cop center of projection
  637. // cor center of rotation
  638. // dir1 old mouse direction
  639. // dir2 new mouse direction
  640. // pretend there is a sphere around cor. Then find the points
  641. // where dir1 and dir2 intersect that sphere. Find the
  642. // rotation that takes the first point to the second.
  643. float m;
  644. // compute plane
  645. float3 nrml = cor - cop;
  646. float fudgefactor = 1.0f/(magnitude(nrml) * 0.25f); // since trackball proportional to distance from cop
  647. nrml = normalize(nrml);
  648. float dist = -dot(nrml,cor);
  649. float3 u= PlaneLineIntersection(nrml,dist,cop,cop+dir1);
  650. u=u-cor;
  651. u=u*fudgefactor;
  652. m= magnitude(u);
  653. if(m>1)
  654. {
  655. u/=m;
  656. }
  657. else
  658. {
  659. u=u - (nrml * sqrtf(1-m*m));
  660. }
  661. float3 v= PlaneLineIntersection(nrml,dist,cop,cop+dir2);
  662. v=v-cor;
  663. v=v*fudgefactor;
  664. m= magnitude(v);
  665. if(m>1)
  666. {
  667. v/=m;
  668. }
  669. else
  670. {
  671. v=v - (nrml * sqrtf(1-m*m));
  672. }
  673. return RotationArc(u,v);
  674. }
  675. int countpolyhit=0;
  676. int HitCheckPoly(const float3 *vert, const int n, const float3 &v0, const float3 &v1, float3 *impact, float3 *normal)
  677. {
  678. countpolyhit++;
  679. int i;
  680. float3 nrml(0,0,0);
  681. for(i=0;i<n;i++)
  682. {
  683. int i1=(i+1)%n;
  684. int i2=(i+2)%n;
  685. nrml = nrml + cross(vert[i1]-vert[i],vert[i2]-vert[i1]);
  686. }
  687. float m = magnitude(nrml);
  688. if(m==0.0)
  689. {
  690. return 0;
  691. }
  692. nrml = nrml * (1.0f/m);
  693. float dist = -dot(nrml,vert[0]);
  694. float d0,d1;
  695. if((d0=dot(v0,nrml)+dist) <0 || (d1=dot(v1,nrml)+dist) >0)
  696. {
  697. return 0;
  698. }
  699. static float3 the_point;
  700. // By using the cached plane distances d0 and d1
  701. // we can optimize the following:
  702. // the_point = planelineintersection(nrml,dist,v0,v1);
  703. float a = d0/(d0-d1);
  704. the_point = v0*(1-a) + v1*a;
  705. int inside=1;
  706. for(int j=0;inside && j<n;j++)
  707. {
  708. // let inside = 0 if outside
  709. float3 pp1,pp2,side;
  710. pp1 = vert[j] ;
  711. pp2 = vert[(j+1)%n];
  712. side = cross((pp2-pp1),(the_point-pp1));
  713. inside = (dot(nrml,side) >= 0.0);
  714. }
  715. if(inside)
  716. {
  717. if(normal){*normal=nrml;}
  718. if(impact){*impact=the_point;}
  719. }
  720. return inside;
  721. }
  722. int SolveQuadratic(float a,float b,float c,float *ta,float *tb) // if true returns roots ta,tb where ta<=tb
  723. {
  724. assert(ta);
  725. assert(tb);
  726. float d = b*b-4.0f*a*c; // discriminant
  727. if(d<0.0f) return 0;
  728. float sqd = sqrtf(d);
  729. *ta = (-b-sqd) / (2.0f * a);
  730. *tb = (-b+sqd) / (2.0f * a);
  731. return 1;
  732. }
  733. int HitCheckRaySphere(const float3& sphereposition,float radius, const float3& _v0, const float3& _v1, float3 *impact,float3 *normal)
  734. {
  735. assert(impact);
  736. assert(normal);
  737. float3 dv = _v1-_v0;
  738. float3 v0 = _v0 - sphereposition; // solve in coord system of the sphere
  739. if(radius<=0.0f || _v0==_v1) return 0; // only true if point moves from outside to inside sphere.
  740. float a = dot(dv,dv);
  741. float b = 2.0f * dot(dv,v0);
  742. float c = dot(v0,v0) - radius*radius;
  743. if(c<0.0f) return 0; // we are already inside the sphere.
  744. float ta, tb;
  745. int doesIntersect = SolveQuadratic(a, b, c, &ta, &tb);
  746. if (!doesIntersect) return 0;
  747. if (ta >= 0.0f && ta <= 1.0f && (ta <= tb || tb<=0.0f))
  748. {
  749. *impact = _v0 + dv * ta;
  750. *normal = (v0 + dv*ta)/radius;
  751. return 1;
  752. }
  753. if (tb >= 0.0f && tb <= 1.0f)
  754. {
  755. assert(tb <= ta || ta <=0.0f); // tb must be better than ta
  756. *impact = _v0 + dv * tb;
  757. *normal = (v0 + dv*tb)/radius;
  758. return 1;
  759. }
  760. return 0;
  761. }
  762. int HitCheckRayCylinder(const float3 &p0,const float3 &p1,float radius,const float3& _v0,const float3& _v1, float3 *impact,float3 *normal)
  763. {
  764. assert(impact);
  765. assert(normal);
  766. // only concerned about hitting the sides, not the caps for now
  767. float3x3 m=RotationArc(p1-p0,float3(0,0,1.0f)).getmatrix();
  768. float h = ((p1-p0)*m ).z;
  769. float3 v0 = (_v0-p0) *m;
  770. float3 v1 = (_v1-p0) *m;
  771. if(v0.z <= 0.0f && v1.z <= 0.0f) return 0; // entirely below cylinder
  772. if(v0.z >= h && v1.z >= h ) return 0; // ray is above cylinder
  773. if(v0.z <0.0f ) v0 = PlaneLineIntersection(float3(0,0,1.0f), 0,v0,v1); // crop to cylinder range
  774. if(v1.z <0.0f ) v1 = PlaneLineIntersection(float3(0,0,1.0f), 0,v0,v1);
  775. if(v0.z > h ) v0 = PlaneLineIntersection(float3(0,0,1.0f),-h,v0,v1);
  776. if(v1.z > h ) v1 = PlaneLineIntersection(float3(0,0,1.0f),-h,v0,v1);
  777. if(v0.x==v1.x && v0.y==v1.y) return 0;
  778. float3 dv = v1-v0;
  779. float a = dv.x*dv.x+dv.y*dv.y;
  780. float b = 2.0f * (dv.x*v0.x+dv.y*v0.y);
  781. float c = (v0.x*v0.x+v0.y*v0.y) - radius*radius;
  782. if(c<0.0f) return 0; // we are already inside the cylinder .
  783. float ta, tb;
  784. int doesIntersect = SolveQuadratic(a, b, c, &ta, &tb);
  785. if (!doesIntersect) return 0;
  786. if (ta >= 0.0f && ta <= 1.0f && (ta <= tb || tb<=0.0f))
  787. {
  788. *impact = (v0 + dv * ta)*Transpose(m) + p0;
  789. *normal = (float3(v0.x,v0.y,0.0f) + float3(dv.x,dv.y,0) * ta) /radius * Transpose(m);
  790. return 1;
  791. }
  792. if (tb >= 0.0f && tb <= 1.0f)
  793. {
  794. assert(tb <= ta || ta <=0.0f); // tb must be better than ta
  795. *impact = (v0 + dv * tb)*Transpose(m) + p0; // compute intersection in original space
  796. *normal = (float3(v0.x,v0.y,0.0f) + float3(dv.x,dv.y,0) * tb) /radius * Transpose(m);
  797. return 1;
  798. }
  799. return 0;
  800. }
  801. int HitCheckSweptSphereTri(const float3 &p0,const float3 &p1,const float3 &p2,float radius, const float3& v0,const float3& _v1, float3 *impact,float3 *normal)
  802. {
  803. float3 unused;
  804. if(!normal) normal=&unused;
  805. float3 v1=_v1; // so we can update v1 after each sub intersection test if necessary
  806. int hit=0;
  807. float3 cp = cross(p1-p0,p2-p0);
  808. if(dot(cp,v1-v0)>=0.0f) return 0; // coming from behind and/or moving away
  809. float3 n = normalize(cp);
  810. float3 tv[3];
  811. tv[0] = p0 + n*radius;
  812. tv[1] = p1 + n*radius;
  813. tv[2] = p2 + n*radius;
  814. hit += HitCheckPoly(tv,3,v0,v1,&v1,normal);
  815. hit += HitCheckRayCylinder(p0,p1,radius,v0,v1,&v1,normal);
  816. hit += HitCheckRayCylinder(p1,p2,radius,v0,v1,&v1,normal);
  817. hit += HitCheckRayCylinder(p2,p0,radius,v0,v1,&v1,normal);
  818. hit += HitCheckRaySphere(p0,radius,v0,v1,&v1,normal);
  819. hit += HitCheckRaySphere(p1,radius,v0,v1,&v1,normal);
  820. hit += HitCheckRaySphere(p2,radius,v0,v1,&v1,normal);
  821. if(hit && impact) *impact = v1 + *normal * 0.001f;
  822. return hit;
  823. }
  824. float3 PlanesIntersection(const Plane &p0,const Plane &p1, const Plane &p2)
  825. {
  826. float3x3 mp =Transpose(float3x3(p0.normal(),p1.normal(),p2.normal()));
  827. float3x3 mi = Inverse(mp);
  828. float3 b(p0.dist(),p1.dist(),p2.dist());
  829. return -b * mi;
  830. }
  831. float3 PlanesIntersection(const Plane *planes,int planes_count,const float3 &seed)
  832. {
  833. int i;
  834. float3x3 A; // gets initilized to 0 matrix
  835. float3 b(0,0,0);
  836. for(i=0;i<planes_count;i++)
  837. {
  838. const Plane &p=planes[i];
  839. A += outerprod(p.normal(),p.normal());
  840. b += p.normal() * -p.dist();
  841. }
  842. float3x3 evecs = Diagonalizer(A).getmatrix(); // eigenvectors
  843. float3 evals = Diagonal(evecs*A*Transpose(evecs)); // eigenvalues
  844. for(i=0;i<3;i++)
  845. {
  846. if(fabsf(evals[i])<1.0f) // not sure if they are necessarily positive
  847. {
  848. Plane p;
  849. p.normal() = evecs[i]* squared(1.0f-evals[i]);
  850. p.dist() = -dot(seed,p.normal());
  851. A += outerprod(p.normal(),p.normal());
  852. b += p.normal() * -p.dist();
  853. }
  854. }
  855. return Inverse(A) * b;
  856. }
  857. Plane Transform(const Plane &p, const float3 &translation, const Quaternion &rotation)
  858. {
  859. // Transforms the plane by the given translation/rotation.
  860. float3 newnormal = rotate(rotation,p.normal());
  861. return Plane(newnormal, p.dist() - dot(newnormal,translation));
  862. }
  863. float3 PlaneProject(const Plane &plane, const float3 &point)
  864. {
  865. return point - plane.normal() * (dot(point,plane.normal())+plane.dist());
  866. }
  867. float3 PlaneLineIntersection(const Plane &plane, const float3 &p0, const float3 &p1)
  868. {
  869. // returns the point where the line p0-p1 intersects the plane n&d
  870. float3 dif;
  871. dif = p1-p0;
  872. float dn= dot(plane.normal(),dif);
  873. float t = -(plane.dist()+dot(plane.normal(),p0) )/dn;
  874. return p0 + (dif*t);
  875. }
  876. int Clip(const float3 &plane_normal,float plane_dist,const float3 *verts_in,int count_in,float3* verts_out)
  877. {
  878. // clips a polygon specified by the non-indexed vertex list verts_in.
  879. // verts_out must be preallocated with a size >= count+1
  880. assert(verts_out);
  881. int n=0;
  882. int prev_status = (dot(plane_normal,verts_in[count_in-1])+plane_dist > 0) ;
  883. for(int i=0;i<count_in;i++)
  884. {
  885. int status = (dot(plane_normal,verts_in[i])+plane_dist > 0) ;
  886. if(status != prev_status)
  887. {
  888. verts_out[n++] = PlaneLineIntersection(plane_normal,plane_dist,verts_in[(i==0)?count_in-1:i-1],verts_in[i]);
  889. }
  890. if(status==0) // under
  891. {
  892. verts_out[n++] = verts_in[i];
  893. }
  894. }
  895. assert(n<=count_in+1); // remove if intention to use this routine on convex polygons
  896. return n;
  897. }
  898. int ClipPolyPoly(const float3 &normal,const float3 *clipper,int clipper_count,const float3 *verts_in, int in_count,float3 *scratch)
  899. {
  900. // clips polys against each other.
  901. // requires sufficiently allocated temporary memory in scratch buffer
  902. // function returns final number of vertices in clipped polygon.
  903. // Resulting vertices are returned in the scratch buffer.
  904. // if the arrays are the same &verts_in==&scratch the routine should still work anyways.
  905. // the first argument (normal) is the normal of polygon clipper.
  906. // its generally assumed both are convex polygons.
  907. assert(scratch); // size should be >= 2*(clipper_count+in_count)
  908. int i;
  909. int bsize = clipper_count+in_count;
  910. int count = in_count;
  911. for(i=0;i<clipper_count;i++)
  912. {
  913. int i1 = (i+1)%clipper_count;
  914. float3 n = cross(clipper[i1]-clipper[i],normal);
  915. if(n==float3(0,0,0)) continue;
  916. n=normalize(n);
  917. count = Clip(n,-dot(clipper[i],n),(i==0)?verts_in:(i%2)?scratch:scratch+bsize,count,(i%2)?scratch+bsize:scratch);
  918. assert(count<bsize);
  919. }
  920. if(clipper_count%2) memcpy(scratch,scratch+bsize,count*sizeof(float3));
  921. return count;
  922. }
  923. float Volume(const float3 *vertices, const int3 *tris, const int count)
  924. {
  925. // count is the number of triangles (tris)
  926. float volume=0;
  927. for(int i=0; i<count; i++) // for each triangle
  928. {
  929. volume += Determinant(float3x3(vertices[tris[i][0]],vertices[tris[i][1]],vertices[tris[i][2]])); //divide by 6 later for efficiency
  930. }
  931. return volume/6.0f; // since the determinant give 6 times tetra volume
  932. }
  933. float3 CenterOfMass(const float3 *vertices, const int3 *tris, const int count)
  934. {
  935. // count is the number of triangles (tris)
  936. float3 com(0,0,0);
  937. float volume=0; // actually accumulates the volume*6
  938. for(int i=0; i<count; i++) // for each triangle
  939. {
  940. float3x3 A(vertices[tris[i][0]],vertices[tris[i][1]],vertices[tris[i][2]]);
  941. float vol=Determinant(A); // dont bother to divide by 6
  942. com += vol * (A.x+A.y+A.z); // divide by 4 at end
  943. volume+=vol;
  944. }
  945. com /= volume*4.0f;
  946. return com;
  947. }
  948. float3x3 Inertia(const float3 *vertices, const int3 *tris, const int count, const float3& com /* =float3(0,0,0) */ )
  949. {
  950. // count is the number of triangles (tris)
  951. // The moments are calculated based on the center of rotation (com) which defaults to [0,0,0] if unsupplied
  952. // assume mass==1.0 you can multiply by mass later.
  953. // for improved accuracy the next 3 variables, the determinant d, and its calculation should be changed to double
  954. float volume=0; // technically this variable accumulates the volume times 6
  955. float3 diag(0,0,0); // accumulate matrix main diagonal integrals [x*x, y*y, z*z]
  956. float3 offd(0,0,0); // accumulate matrix off-diagonal integrals [y*z, x*z, x*y]
  957. for(int i=0; i<count; i++) // for each triangle
  958. {
  959. float3x3 A(vertices[tris[i][0]]-com,vertices[tris[i][1]]-com,vertices[tris[i][2]]-com); // matrix trick for volume calc by taking determinant
  960. float d = Determinant(A); // vol of tiny parallelapiped= d * dr * ds * dt (the 3 partials of my tetral triple integral equasion)
  961. volume +=d; // add vol of current tetra (note it could be negative - that's ok we need that sometimes)
  962. for(int j=0;j<3;j++)
  963. {
  964. int j1=(j+1)%3;
  965. int j2=(j+2)%3;
  966. diag[j] += (A[0][j]*A[1][j] + A[1][j]*A[2][j] + A[2][j]*A[0][j] +
  967. A[0][j]*A[0][j] + A[1][j]*A[1][j] + A[2][j]*A[2][j] ) *d; // divide by 60.0f later;
  968. offd[j] += (A[0][j1]*A[1][j2] + A[1][j1]*A[2][j2] + A[2][j1]*A[0][j2] +
  969. A[0][j1]*A[2][j2] + A[1][j1]*A[0][j2] + A[2][j1]*A[1][j2] +
  970. A[0][j1]*A[0][j2]*2+ A[1][j1]*A[1][j2]*2+ A[2][j1]*A[2][j2]*2 ) *d; // divide by 120.0f later
  971. }
  972. }
  973. diag /= volume*(60.0f /6.0f); // divide by total volume (vol/6) since density=1/volume
  974. offd /= volume*(120.0f/6.0f);
  975. return float3x3(diag.y+diag.z , -offd.z , -offd.y,
  976. -offd.z , diag.x+diag.z, -offd.x,
  977. -offd.y , -offd.x , diag.x+diag.y );
  978. }
  979. float3x3 ShapeInertiaContrib(const float3& cor, const float3& position, const Quaternion &orientation,
  980. const float3& shape_com, const float3x3& shape_inertia, float shape_mass)
  981. {
  982. // transforms 3x3 inertia tensor from local reference frame to a more global one.
  983. // essentially returns the contribution of a subshape to the inertia of a larger rigid body
  984. // typical usage:
  985. // foreach shape s { totalinertia += InertiaContribution(...); }
  986. // cor - new center of rotation that we are translating to.
  987. // This could be the center of mass of the compound object.
  988. // Another application is when an object is attached to something (nail-joint) that is static, in which
  989. // one easy way to implement this is to lock the center of rotation and adjust the inertia accordingly.
  990. // position & orientation - is the current pose or transform of the shape.
  991. // Obviously position, orientation and cor are all described wrt the same reference frame.
  992. // shape_com and shape_inertia are the center of mass and the inertia of the shape in the local coordinate system of that shape.
  993. // To clarify, if a shape happened to be located somewhere else then position or orientation would be different, but
  994. // com and inertia would be the same.
  995. float3x3 Identity(1.0f,0,0,0,1.0f,0,0,0,1.0f);
  996. float3x3 R = orientation.getmatrix();
  997. float3 r = (shape_com*R + position) - cor;
  998. return Transpose(R)*shape_inertia*R + (Identity*dot(r,r)-outerprod(r,r))*shape_mass;
  999. }
  1000. Quaternion Diagonalizer(const float3x3 &A)
  1001. {
  1002. // A must be a symmetric matrix.
  1003. // returns quaternion q such that its corresponding matrix Q
  1004. // can be used to Diagonalize A
  1005. // Diagonal matrix D = Q * A * Transpose(Q); and A = QT*D*Q
  1006. // The rows of q are the eigenvectors D's diagonal is the eigenvalues
  1007. // As per 'row' convention if float3x3 Q = q.getmatrix(); then v*Q = q*v*conj(q)
  1008. int maxsteps=24; // certainly wont need that many.
  1009. int i;
  1010. Quaternion q(0,0,0,1);
  1011. for(i=0;i<maxsteps;i++)
  1012. {
  1013. float3x3 Q = q.getmatrix(); // v*Q == q*v*conj(q)
  1014. float3x3 D = Q * A * Transpose(Q); // A = Q^T*D*Q
  1015. float3 offdiag(D[1][2],D[0][2],D[0][1]); // elements not on the diagonal
  1016. float3 om(fabsf(offdiag.x),fabsf(offdiag.y),fabsf(offdiag.z)); // mag of each offdiag elem
  1017. int k = (om.x>om.y&&om.x>om.z)?0: (om.y>om.z)? 1 : 2; // index of largest element of offdiag
  1018. int k1 = (k+1)%3;
  1019. int k2 = (k+2)%3;
  1020. if(offdiag[k]==0.0f) break; // diagonal already
  1021. float thet = (D[k2][k2]-D[k1][k1])/(2.0f*offdiag[k]);
  1022. float sgn = (thet>0.0f)?1.0f:-1.0f;
  1023. thet *= sgn; // make it positive
  1024. float t = sgn /(thet +((thet<1.E6f)?sqrtf(squared(thet)+1.0f):thet)) ; // sign(T)/(|T|+sqrt(T^2+1))
  1025. float c = 1.0f/sqrtf(squared(t)+1.0f); // c= 1/(t^2+1) , t=s/c
  1026. if(c==1.0f) break; // no room for improvement - reached machine precision.
  1027. Quaternion jr(0,0,0,0); // jacobi rotation for this iteration.
  1028. jr[k] = sgn*sqrtf((1.0f-c)/2.0f); // using 1/2 angle identity sin(a/2) = sqrt((1-cos(a))/2)
  1029. jr[k] *= -1.0f; // since our quat-to-matrix convention was for v*M instead of M*v
  1030. jr.w = sqrtf(1.0f - squared(jr[k]));
  1031. if(jr.w==1.0f) break; // reached limits of floating point precision
  1032. q = q*jr;
  1033. q.Normalize();
  1034. }
  1035. return q;
  1036. }
  1037. float3 Diagonal(const float3x3 &M)
  1038. {
  1039. return float3(M[0][0],M[1][1],M[2][2]);
  1040. }