21 # pragma warning(disable: 4244 4305 4127 4701)
32 #define mat_pad(A) (A[W][X]=A[X][W]=A[W][Y]=A[Y][W]=A[W][Z]=A[Z][W]=0,A[W][W]=1)
35 #define mat_copy(C,gets,A,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
36 C[i][j] gets (A[i][j]);}
39 #define mat_tpose(AT,gets,A,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
40 AT[i][j] gets (A[j][i]);}
43 #define mat_binop(C,gets,A,op,B,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\
44 C[i][j] gets (A[i][j]) op (B[i][j]);}
50 for (i=0; i<3; i++)
for (j=0; j<3; j++)
51 AB[i][j] = A[i][0]*B[0][j] + A[i][1]*B[1][j] + A[i][2]*B[2][j];
55 float vdot(
float *va,
float *vb)
57 return (va[0]*vb[0] + va[1]*vb[1] + va[2]*vb[2]);
61 void vcross(
float *va,
float *vb,
float *v)
63 v[0] = va[1]*vb[2] - va[2]*vb[1];
64 v[1] = va[2]*vb[0] - va[0]*vb[2];
65 v[2] = va[0]*vb[1] - va[1]*vb[0];
71 vcross(M[1], M[2], MadjT[0]);
72 vcross(M[2], M[0], MadjT[1]);
73 vcross(M[0], M[1], MadjT[2]);
79 Quat Qt_(
float x,
float y,
float z,
float w)
82 qq.
x = x; qq.
y = y; qq.
z = z; qq.
w = w;
90 qq.
x = -q.
x; qq.
y = -q.
y; qq.
z = -q.
z; qq.
w = q.
w;
100 qq.
w = qL.
w*qR.
w - qL.
x*qR.
x - qL.
y*qR.
y - qL.
z*qR.
z;
101 qq.
x = qL.
w*qR.
x + qL.
x*qR.
w + qL.
y*qR.
z - qL.
z*qR.
y;
102 qq.
y = qL.
w*qR.
y + qL.
y*qR.
w + qL.
z*qR.
x - qL.
x*qR.
z;
103 qq.
z = qL.
w*qR.
z + qL.
z*qR.
w + qL.
x*qR.
y - qL.
y*qR.
x;
111 qq.
w = q.
w*w; qq.
x = q.
x*w; qq.
y = q.
y*w; qq.
z = q.
z*w;
127 register double tr, s;
129 tr = mat[
X][
X] + mat[
Y][
Y]+ mat[
Z][
Z];
131 s = sqrt(tr + mat[
W][
W]);
134 qu.
x = (mat[
Z][
Y] - mat[
Y][
Z]) * s;
135 qu.
y = (mat[
X][
Z] - mat[
Z][
X]) * s;
136 qu.
z = (mat[
Y][
X] - mat[
X][
Y]) * s;
139 if (mat[
Y][
Y] > mat[
X][
X]) h =
Y;
140 if (mat[
Z][
Z] > mat[h][h]) h =
Z;
142 #define caseMacro(i,j,k,I,J,K) \
144 s = sqrt( (mat[I][I] - (mat[J][J]+mat[K][K])) + mat[W][W] );\
147 qu.j = (mat[I][J] + mat[J][I]) * s;\
148 qu.k = (mat[K][I] + mat[I][K]) * s;\
149 qu.w = (mat[K][J] - mat[J][K]) * s;\
156 if (mat[
W][
W] != 1.0) qu =
Qt_Scale(qu, 1/sqrt(mat[
W][
W]));
161 static HMatrix mat_id = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
169 for (i=0; i<3; i++) {
170 if (tpose) sum = fabs(M[0][i])+fabs(M[1][i])+fabs(M[2][i]);
171 else sum = fabs(M[i][0])+fabs(M[i][1])+fabs(M[i][2]);
172 if (max<sum) max = sum;
186 for (i=0; i<3; i++)
for (j=0; j<3; j++) {
187 abs = M[i][j];
if (abs<0.0) abs = -abs;
188 if (abs>max) {max = abs; col = j;}
196 float s = sqrt(
vdot(v, v));
197 u[0] = v[0]; u[1] = v[1];
198 u[2] = v[2] + ((v[2]<0.0) ? -s : s);
199 s = sqrt(2.0/
vdot(u, u));
200 u[0] = u[0]*s; u[1] = u[1]*s; u[2] = u[2]*s;
207 for (i=0; i<3; i++) {
208 float s = u[0]*M[0][i] + u[1]*M[1][i] + u[2]*M[2][i];
209 for (j=0; j<3; j++) M[j][i] -= u[j]*s;
216 for (i=0; i<3; i++) {
217 float s =
vdot(u, M[i]);
218 for (j=0; j<3; j++) M[i][j] -= u[j]*s;
225 float v1[3], v2[3], s;
231 v1[0] = M[0][col]; v1[1] = M[1][col]; v1[2] = M[2][col];
233 v2[0] = M[2][0]; v2[1] = M[2][1]; v2[2] = M[2][2];
236 if (s<0.0) Q[2][2] = -1.0;
244 float w, x, y, z, c, s, d;
248 if (col<0) {
do_rank1(M, Q);
return;}
249 v1[0] = MadjT[0][col]; v1[1] = MadjT[1][col]; v1[2] = MadjT[2][col];
253 w = M[0][0]; x = M[0][1]; y = M[1][0]; z = M[1][1];
255 c = z+w; s = y-x; d = sqrt(c*c+s*s); c = c/d; s = s/d;
256 Q[0][0] = Q[1][1] = c; Q[0][1] = -(Q[1][0] = s);
258 c = z-w; s = y+x; d = sqrt(c*c+s*s); c = c/d; s = s/d;
259 Q[0][0] = -(Q[1][1] = c); Q[0][1] = Q[1][0] = s;
261 Q[0][2] = Q[2][0] = Q[1][2] = Q[2][1] = 0.0; Q[2][2] = 1.0;
278 float det, M_one, M_inf, MadjT_one, MadjT_inf, E_one, gamma, g1, g2;
284 det =
vdot(Mk[0], MadjTk[0]);
285 if (det==0.0) {
do_rank2(Mk, MadjTk, Mk);
break;}
287 gamma = sqrt(sqrt((MadjT_one*MadjT_inf)/(M_one*M_inf))/fabs(det));
289 g2 = 0.5/(gamma*det);
295 }
while (E_one>(M_one*
TOL));
298 for (i=0; i<3; i++)
for (j=i; j<3; j++)
299 S[i][j] = S[j][i] = 0.5*(S[i][j]+S[j][i]);
329 double Diag[3],OffD[3];
330 double g,h,fabsh,fabsOffDi,t,theta,c,s,tau,ta,OffDq,a,b;
331 static char nxt[] = {
Y,
Z,
X};
334 Diag[
X] = S[
X][
X]; Diag[
Y] = S[
Y][
Y]; Diag[
Z] = S[
Z][
Z];
335 OffD[
X] = S[
Y][
Z]; OffD[
Y] = S[
Z][
X]; OffD[
Z] = S[
X][
Y];
336 for (sweep=20; sweep>0; sweep--) {
337 float sm = fabs(OffD[
X])+fabs(OffD[
Y])+fabs(OffD[
Z]);
339 for (i=Z; i>=
X; i--) {
340 int p = nxt[i];
int q = nxt[p];
341 fabsOffDi = fabs(OffD[i]);
344 h = Diag[q] - Diag[p];
346 if (fabsh+g==fabsh) {
349 theta = 0.5*h/OffD[i];
350 t = 1.0/(fabs(theta)+sqrt(theta*theta+1.0));
351 if (theta<0.0) t = -t;
353 c = 1.0/sqrt(t*t+1.0); s = t*c;
355 ta = t*OffD[i]; OffD[i] = 0.0;
356 Diag[p] -= ta; Diag[q] += ta;
358 OffD[q] -= s*(OffD[p] + tau*OffD[q]);
359 OffD[p] += s*(OffDq - tau*OffD[p]);
360 for (j=Z; j>=
X; j--) {
361 a = U[j][p]; b = U[j][q];
362 U[j][p] -= s*(b + tau*a);
363 U[j][q] += s*(a - tau*b);
368 kv.
x = Diag[
X]; kv.
y = Diag[
Y]; kv.
z = Diag[
Z]; kv.
w = 1.0;
383 #define SQRTHALF (0.7071067811865475244)
384 #define sgn(n,v) ((n)?-(v):(v))
385 #define swap(a,i,j) {a[3]=a[i]; a[i]=a[j]; a[j]=a[3];}
386 #define cycle(a,p) if (p) {a[3]=a[0]; a[0]=a[1]; a[1]=a[2]; a[2]=a[3];}\
387 else {a[3]=a[2]; a[2]=a[1]; a[1]=a[0]; a[0]=a[3];}
391 ka[
X] = k->
x; ka[
Y] = k->
y; ka[
Z] = k->
z;
392 if (ka[
X]==ka[
Y]) {
if (ka[
X]==ka[
Z]) turn =
W;
else turn =
Z;}
393 else {
if (ka[
X]==ka[
Z]) turn =
Y;
else if (ka[Y]==ka[Z]) turn =
X;}
396 unsigned neg[3], win;
400 static Quat qppmm = { 0.5, 0.5,-0.5,-0.5};
401 static Quat qpppp = { 0.5, 0.5, 0.5, 0.5};
402 static Quat qmpmm = {-0.5, 0.5,-0.5,-0.5};
403 static Quat qpppm = { 0.5, 0.5, 0.5,-0.5};
404 static Quat q0001 = { 0.0, 0.0, 0.0, 1.0};
405 static Quat q1000 = { 1.0, 0.0, 0.0, 0.0};
409 case Y: q =
Qt_Mul(q, qtoz = qytoz);
swap(ka,Y,
Z)
break;
410 case Z: qtoz = q0001;
break;
413 mag[0] = (double)q.
z*q.
z+(
double)q.
w*q.
w-0.5;
414 mag[1] = (double)q.
x*q.
z-(
double)q.
y*q.
w;
415 mag[2] = (double)q.
y*q.
z+(
double)q.
x*q.
w;
416 for (i=0; i<3; i++)
if ((neg[i] = (mag[i]<0.0)) != 0) mag[i] = -mag[i];
417 if (mag[0]>mag[1]) {
if (mag[0]>mag[2]) win = 0;
else win = 2;}
418 else {
if (mag[1]>mag[2]) win = 1;
else win = 2;}
420 case 0:
if (neg[0]) p = q1000;
else p = q0001;
break;
421 case 1:
if (neg[1]) p = qppmm;
else p = qpppp;
cycle(ka,0)
break;
422 case 2:
if (neg[2]) p = qmpmm;
else p = qpppm;
cycle(ka,1)
break;
425 t = sqrt(mag[win]+0.5);
430 unsigned lo, hi, neg[4], par = 0;
431 double all, big, two;
432 qa[0] = q.
x; qa[1] = q.
y; qa[2] = q.
z; qa[3] = q.
w;
433 for (i=0; i<4; i++) {
435 if ((neg[i] = (qa[i]<0.0)) != 0) qa[i] = -qa[i];
439 if (qa[0]>qa[1]) lo = 0;
else lo = 1;
440 if (qa[2]>qa[3]) hi = 2;
else hi = 3;
442 if (qa[lo^1]>qa[hi]) {hi = lo; lo ^= 1;}
443 else {hi ^= lo; lo ^= hi; hi ^= lo;}
444 }
else {
if (qa[hi^1]>qa[lo]) lo = hi^1;}
445 all = (qa[0]+qa[1]+qa[2]+qa[3])*0.5;
450 {
int i;
for (i=0; i<4; i++) pa[i] =
sgn(neg[i], 0.5);}
452 }
else { pa[hi] =
sgn(neg[hi],1.0);}
456 if (lo>hi) {hi ^= lo; lo ^= hi; hi ^= lo;}
457 if (hi==
W) {hi =
"\001\002\000"[lo]; lo = 3-hi-lo;}
459 }
else { pa[hi] =
sgn(neg[hi],1.0);}
461 p.
x = -pa[0]; p.
y = -pa[1]; p.
z = -pa[2]; p.
w = pa[3];
463 k->
x = ka[
X]; k->
y = ka[
Y]; k->
z = ka[
Z];
491 parts->
t =
Qt_(A[
X][
W], A[
Y][W], A[
Z][W], 0);
511 inverse->
f = parts->
f;
514 inverse->
k.
x = (parts->
k.
x==0.0) ? 0.0 : 1.0/parts->
k.
x;
515 inverse->
k.
y = (parts->
k.
y==0.0) ? 0.0 : 1.0/parts->
k.
y;
516 inverse->
k.
z = (parts->
k.
z==0.0) ? 0.0 : 1.0/parts->
k.
z;
517 inverse->
k.
w = parts->
k.
w;
518 t =
Qt_(-parts->
t.
x, -parts->
t.
y, -parts->
t.
z, 0);
520 t =
Qt_(inverse->
k.
x*t.
x, inverse->
k.
y*t.
y, inverse->
k.
z*t.
z, 0);
523 inverse->
t = (inverse->
f>0.0) ? t :
Qt_(-t.
x, -t.
y, -t.
z, 0);
#define mat_binop(C, gets, A, op, B, n)
Assign nxn matrix C the element-wise combination of A and B using "op".
int find_max_col(HMatrix M)
Return index of column of M containing maximum abs entry, or -1 if M=0.
Quat Qt_Mul(Quat qL, Quat qR)
float norm_one(HMatrix M)
float polar_decomp(HMatrix M, HMatrix Q, HMatrix S)
void adjoint_transpose(HMatrix M, HMatrix MadjT)
Set MadjT to transpose of inverse of M times determinant of M.
float vdot(float *va, float *vb)
Return dot product of length 3 vectors va and vb.
#define mat_tpose(AT, gets, A, n)
Copy transpose of nxn matrix A to C using "gets" for assignment.
#define mat_copy(C, gets, A, n)
Copy nxn matrix A to C using "gets" for assignment.
void vcross(float *va, float *vb, float *v)
Set v to cross product of length 3 vectors va and vb.
#define caseMacro(i, j, k, I, J, K)
void invert_affine(AffineParts *parts, AffineParts *inverse)
void reflect_cols(HMatrix M, float *u)
Apply Householder reflection represented by u to column vectors of M.
void do_rank2(HMatrix M, HMatrix MadjT, HMatrix Q)
Find orthogonal factor Q of rank 2 (or less) M using adjoint transpose.
Quat Qt_FromMatrix(HMatrix mat)
float norm_inf(HMatrix M)
void reflect_rows(HMatrix M, float *u)
Apply Householder reflection represented by u to row vectors of M.
Quat Qt_(float x, float y, float z, float w)
HVect spect_decomp(HMatrix S, HMatrix U)
void mat_mult(HMatrix A, HMatrix B, HMatrix AB)
Multiply the upper left 3x3 parts of A and B to get AB.
void make_reflector(float *v, float *u)
Setup u for Household reflection to zero all v components but first.
Quat snuggle(Quat q, HVect *k)
void decomp_affine(HMatrix A, AffineParts *parts)
#define mat_pad(A)
Fill out 3x3 matrix to 4x4.
Quat Qt_Scale(Quat q, float w)
float mat_norm(HMatrix M, int tpose)
Compute either the 1 or infinity norm of M, depending on tpose.
void do_rank1(HMatrix M, HMatrix Q)
Find orthogonal factor Q of rank 1 (or less) M.