⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decompose.c

📁 [Game.Programming].Academic - Graphics Gems (6 books source code)
💻 C
📖 第 1 页 / 共 2 页
字号:
/**** Decompose.c ****//* Ken Shoemake, 1993 */#include <math.h>#include "Decompose.h"/******* Matrix Preliminaries *******//** Fill out 3x3 matrix to 4x4 **/#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)/** Copy nxn matrix A to C using "gets" for assignment **/#define mat_copy(C,gets,A,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\    C[i][j] gets (A[i][j]);}/** Copy transpose of nxn matrix A to C using "gets" for assignment **/#define mat_tpose(AT,gets,A,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\    AT[i][j] gets (A[j][i]);}/** Assign nxn matrix C the element-wise combination of A and B using "op" **/#define mat_binop(C,gets,A,op,B,n) {int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++)\    C[i][j] gets (A[i][j]) op (B[i][j]);}/** Multiply the upper left 3x3 parts of A and B to get AB **/void mat_mult(HMatrix A, HMatrix B, HMatrix AB){    int i, j;    for (i=0; i<3; i++) for (j=0; j<3; j++)	AB[i][j] = A[i][0]*B[0][j] + A[i][1]*B[1][j] + A[i][2]*B[2][j];}/** Return dot product of length 3 vectors va and vb **/float vdot(float *va, float *vb){    return (va[0]*vb[0] + va[1]*vb[1] + va[2]*vb[2]);}/** Set v to cross product of length 3 vectors va and vb **/void vcross(float *va, float *vb, float *v){    v[0] = va[1]*vb[2] - va[2]*vb[1];    v[1] = va[2]*vb[0] - va[0]*vb[2];    v[2] = va[0]*vb[1] - va[1]*vb[0];}/** Set MadjT to transpose of inverse of M times determinant of M **/void adjoint_transpose(HMatrix M, HMatrix MadjT){    vcross(M[1], M[2], MadjT[0]);    vcross(M[2], M[0], MadjT[1]);    vcross(M[0], M[1], MadjT[2]);}/******* Quaternion Preliminaries *******//* Construct a (possibly non-unit) quaternion from real components. */Quat Qt_(float x, float y, float z, float w){    Quat qq;    qq.x = x; qq.y = y; qq.z = z; qq.w = w;    return (qq);}/* Return conjugate of quaternion. */Quat Qt_Conj(Quat q){    Quat qq;    qq.x = -q.x; qq.y = -q.y; qq.z = -q.z; qq.w = q.w;    return (qq);}/* Return quaternion product qL * qR.  Note: order is important! * To combine rotations, use the product Mul(qSecond, qFirst), * which gives the effect of rotating by qFirst then qSecond. */Quat Qt_Mul(Quat qL, Quat qR){    Quat qq;    qq.w = qL.w*qR.w - qL.x*qR.x - qL.y*qR.y - qL.z*qR.z;    qq.x = qL.w*qR.x + qL.x*qR.w + qL.y*qR.z - qL.z*qR.y;    qq.y = qL.w*qR.y + qL.y*qR.w + qL.z*qR.x - qL.x*qR.z;    qq.z = qL.w*qR.z + qL.z*qR.w + qL.x*qR.y - qL.y*qR.x;    return (qq);}/* Return product of quaternion q by scalar w. */Quat Qt_Scale(Quat q, float w){    Quat qq;    qq.w = q.w*w; qq.x = q.x*w; qq.y = q.y*w; qq.z = q.z*w;    return (qq);}/* Construct a unit quaternion from rotation matrix.  Assumes matrix is * used to multiply column vector on the left: vnew = mat vold.	 Works * correctly for right-handed coordinate system and right-handed rotations. * Translation and perspective components ignored. */Quat Qt_FromMatrix(HMatrix mat){    /* This algorithm avoids near-zero divides by looking for a large component     * - first w, then x, y, or z.  When the trace is greater than zero,     * |w| is greater than 1/2, which is as small as a largest component can be.     * Otherwise, the largest diagonal entry corresponds to the largest of |x|,     * |y|, or |z|, one of which must be larger than |w|, and at least 1/2. */    Quat qu;    register double tr, s;    tr = mat[X][X] + mat[Y][Y]+ mat[Z][Z];    if (tr >= 0.0) {	    s = sqrt(tr + mat[W][W]);	    qu.w = s*0.5;	    s = 0.5 / s;	    qu.x = (mat[Z][Y] - mat[Y][Z]) * s;	    qu.y = (mat[X][Z] - mat[Z][X]) * s;	    qu.z = (mat[Y][X] - mat[X][Y]) * s;	} else {	    int h = X;	    if (mat[Y][Y] > mat[X][X]) h = Y;	    if (mat[Z][Z] > mat[h][h]) h = Z;	    switch (h) {#define caseMacro(i,j,k,I,J,K) \	    case I:\		s = sqrt( (mat[I][I] - (mat[J][J]+mat[K][K])) + mat[W][W] );\		qu.i = s*0.5;\		s = 0.5 / s;\		qu.j = (mat[I][J] + mat[J][I]) * s;\		qu.k = (mat[K][I] + mat[I][K]) * s;\		qu.w = (mat[K][J] - mat[J][K]) * s;\		break	    caseMacro(x,y,z,X,Y,Z);	    caseMacro(y,z,x,Y,Z,X);	    caseMacro(z,x,y,Z,X,Y);	    }	}    if (mat[W][W] != 1.0) qu = Qt_Scale(qu, 1/sqrt(mat[W][W]));    return (qu);}/******* Decomp Auxiliaries *******/static HMatrix mat_id = {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};/** Compute either the 1 or infinity norm of M, depending on tpose **/float mat_norm(HMatrix M, int tpose){    int i;    float sum, max;    max = 0.0;    for (i=0; i<3; i++) {	if (tpose) sum = fabs(M[0][i])+fabs(M[1][i])+fabs(M[2][i]);	else	   sum = fabs(M[i][0])+fabs(M[i][1])+fabs(M[i][2]);	if (max<sum) max = sum;    }    return max;}float norm_inf(HMatrix M) {return mat_norm(M, 0);}float norm_one(HMatrix M) {return mat_norm(M, 1);}/** Return index of column of M containing maximum abs entry, or -1 if M=0 **/int find_max_col(HMatrix M){    float abs, max;    int i, j, col;    max = 0.0; col = -1;    for (i=0; i<3; i++) for (j=0; j<3; j++) {	abs = M[i][j]; if (abs<0.0) abs = -abs;	if (abs>max) {max = abs; col = j;}    }    return col;}/** Setup u for Household reflection to zero all v components but first **/void make_reflector(float *v, float *u){    float s = sqrt(vdot(v, v));    u[0] = v[0]; u[1] = v[1];    u[2] = v[2] + ((v[2]<0.0) ? -s : s);    s = sqrt(2.0/vdot(u, u));    u[0] = u[0]*s; u[1] = u[1]*s; u[2] = u[2]*s;}/** Apply Householder reflection represented by u to column vectors of M **/void reflect_cols(HMatrix M, float *u){    int i, j;    for (i=0; i<3; i++) {	float s = u[0]*M[0][i] + u[1]*M[1][i] + u[2]*M[2][i];	for (j=0; j<3; j++) M[j][i] -= u[j]*s;    }}/** Apply Householder reflection represented by u to row vectors of M **/void reflect_rows(HMatrix M, float *u){    int i, j;    for (i=0; i<3; i++) {	float s = vdot(u, M[i]);	for (j=0; j<3; j++) M[i][j] -= u[j]*s;    }}/** Find orthogonal factor Q of rank 1 (or less) M **/void do_rank1(HMatrix M, HMatrix Q){    float v1[3], v2[3], s;    int col;    mat_copy(Q,=,mat_id,4);    /* If rank(M) is 1, we should find a non-zero column in M */    col = find_max_col(M);    if (col<0) return; /* Rank is 0 */    v1[0] = M[0][col]; v1[1] = M[1][col]; v1[2] = M[2][col];    make_reflector(v1, v1); reflect_cols(M, v1);    v2[0] = M[2][0]; v2[1] = M[2][1]; v2[2] = M[2][2];    make_reflector(v2, v2); reflect_rows(M, v2);    s = M[2][2];    if (s<0.0) Q[2][2] = -1.0;    reflect_cols(Q, v1); reflect_rows(Q, v2);}/** Find orthogonal factor Q of rank 2 (or less) M using adjoint transpose **/void do_rank2(HMatrix M, HMatrix MadjT, HMatrix Q){    float v1[3], v2[3];    float w, x, y, z, c, s, d;    int col;    /* If rank(M) is 2, we should find a non-zero column in MadjT */    col = find_max_col(MadjT);    if (col<0) {do_rank1(M, Q); return;} /* Rank<2 */    v1[0] = MadjT[0][col]; v1[1] = MadjT[1][col]; v1[2] = MadjT[2][col];    make_reflector(v1, v1); reflect_cols(M, v1);    vcross(M[0], M[1], v2);    make_reflector(v2, v2); reflect_rows(M, v2);    w = M[0][0]; x = M[0][1]; y = M[1][0]; z = M[1][1];    if (w*z>x*y) {	c = z+w; s = y-x; d = sqrt(c*c+s*s); c = c/d; s = s/d;	Q[0][0] = Q[1][1] = c; Q[0][1] = -(Q[1][0] = s);    } else {	c = z-w; s = y+x; d = sqrt(c*c+s*s); c = c/d; s = s/d;	Q[0][0] = -(Q[1][1] = c); Q[0][1] = Q[1][0] = s;    }    Q[0][2] = Q[2][0] = Q[1][2] = Q[2][1] = 0.0; Q[2][2] = 1.0;    reflect_cols(Q, v1); reflect_rows(Q, v2);}/******* Polar Decomposition *******//* Polar Decomposition of 3x3 matrix in 4x4, * M = QS.  See Nicholas Higham and Robert S. Schreiber, * Fast Polar Decomposition of An Arbitrary Matrix, * Technical Report 88-942, October 1988, * Department of Computer Science, Cornell University. */float polar_decomp(HMatrix M, HMatrix Q, HMatrix S)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -