/* * La procedure "Matrix_to_Position" initialise la position par la matrice. * Si M est la matrice, et P la position : M = R.Sid.T, P = (R,Sid,T). * On suppose que la matrice de rotation 3x3 de M est unitaire. * Entree : * m Matrice de rotation et de translation. * pp Position a initialiser. */ void Matrix_to_Position (Matrix m, AritPosition *pp) { Matrix_to_Rotate (m, &pp->rotate); SET_COORD3(pp->scale,1.0,1.0,1.0); SET_COORD3(pp->translate,m[3][0],m[3][1],m[3][2]); }
/* * La procedure "Matrix_to_Rotate" initialise la rotation par la matrice. * Si M est la matrice, si R est la matrice de rotation : * * | m00 m01 m02 0 | * M = Rx.Ry.Rz = | m10 m11 m12 0 | * | m20 m21 m22 0 | * | 0 0 0 1 | * * et m00 = cy.cz m01 = cy.sz m02 = -sy * m10 = sx.sy.cz-cx.sz m11 = sx.sy.sz+cx.cz m12 = sx.cy * m20 = cx.sy.cz+sx.sz m21 = cx.sy.sz-sx.cz m22 = cx.cy * avec ci = cos Oi et si = sin Oi. * * R = Rx.Ry.Rz * Rx rotation autour de Ox d'angle O1 * Ry rotation autour de Oy d'angle O2 * Rz rotation autour de Oz d'angle O3 * * Singularite : si |ry| == 90 degres alors rz = 0, * soit une rotation d'axe 0z et d'angle "rx + rz". * * Entree : * m Matrice contenant la composition des rotations. * vp Rotations par rapport aux axes d'un repere droit en degres. */ void Matrix_to_Rotate (Matrix m, Vector *vp) { float sy = - m[0][2]; float cy = (float) sqrt (1.0 - (double) (sy * sy)); float cx, sx; if (FABS(cy) > M_EPSILON) { float sz = m[0][1] / cy; float cz = m[0][0] / cy; sx = m[1][2] / cy; cx = m[2][2] / cy; SET_COORD3(*vp, cosin_to_angle (cx, sx), cosin_to_angle (cy, sy), cosin_to_angle (cz, sz)); } else { /* RZ = 0 => Ry = +/- 90 degres */ sx = m[1][1]; cx = - m[2][1]; SET_COORD3(*vp, cosin_to_angle (cx, sx), (sy > (float)0.0) ? (float)M_PI_2 : (float)(- M_PI_2), (float)0.0); } vp->x *= (float)180.0 / (float)M_PI; /* passage en degres */ vp->y *= (float)180.0 / (float)M_PI; vp->z *= (float)180.0 / (float)M_PI; }
/* Create a jack shaped object, then put a smaller copy in each of the octants defined by the arms of the jack. This process is repeated until depth reaches max_depth. */ static void make_rec_jack(depth, max_depth) { double i, j, k; COORD3 scale, trans; make_jack_obj(); if (depth < max_depth) { SET_COORD3(scale, 0.5, 0.5, 0.5); for (i=-0.5;i<=0.5;i+=1) for (j=-0.5;j<=0.5;j+=1) for (k=-0.5;k<=0.5;k+=1) { if (depth==1) PLATFORM_PROGRESS(0, 4+i*4+j*2+k, 7); lib_tx_push(); SET_COORD3(trans, i, j, k); lib_tx_translate(trans); lib_tx_scale(scale); make_rec_jack(depth+1, max_depth); lib_tx_pop(); } } }
/* Create a single copy of our recursive object. The general sizing and placement of the object are maintained by the recursive routine make_rec_jack. This routine does the actual geometry building */ static void make_jack_obj() { COORD3 scale; COORD4 center, base, apex; /* Save the current transformation */ lib_tx_push(); /* Scale the object down to prevent overlaps */ SET_COORD3(scale, 0.75, 0.75, 0.75); lib_tx_scale(scale); /* Now create the object - three intersecting cylinders * with spheres at both ends */ /* Cylinders on each axis */ SET_COORD4(base, -1, 0, 0, 0.1); SET_COORD4(apex, 1, 0, 0, 0.1); lib_output_cylcone(base, apex, output_format); SET_COORD4(base, 0, -1, 0, 0.1); SET_COORD4(apex, 0, 1, 0, 0.1); lib_output_cylcone(base, apex, output_format); SET_COORD4(base, 0, 0, -1, 0.1); SET_COORD4(apex, 0, 0, 1, 0.1); lib_output_cylcone(base, apex, output_format); /* Spheres at the ends of the cylinders */ SET_COORD4(center, 1, 0, 0, 0.2); lib_output_sphere(center, output_format); SET_COORD4(center, 0, 1, 0, 0.2); lib_output_sphere(center, output_format); SET_COORD4(center, 0, 0, 1, 0.2); lib_output_sphere(center, output_format); SET_COORD4(center,-1, 0, 0, 0.2); lib_output_sphere(center, output_format); SET_COORD4(center, 0,-1, 0, 0.2); lib_output_sphere(center, output_format); SET_COORD4(center, 0, 0,-1, 0.2); lib_output_sphere(center, output_format); /* Restore the transform to what it was prior to * entering this routine. */ lib_tx_pop(); }
/* * La procedure "rotate_vector" transforme le vecteur * par la rotation de sens trigonometrique d'angle et d'axe donnes. * Entree : * vp Vecteur a transformer. * a Angle de rotation en degres. * axis Vecteur directeur de l'axe de rotation. */ void rotate_vector (Vector *vp, float a, Vector *axis) { Vector n, u, v, cross; float f; a *= (float)M_PI / (float)180.0; /* passage en radians */ n = *axis; /* norme le vecteur directeur */ norm_vector (&n); /* * Avant rotation, vp vaut : * u + v * Apres rotation, vp vaut : * u + cos(a) * v + sin(a) * (n^vp) * = u + cos(a) * v + sin(a) * (n^v) * avec u = (vp.n) * n, v = vp-u; * ou "u" est la projection de "vp" sur l'axe "axis", * et "v" est la composante de "vp" perpendiculaire a "axis". */ f = DOT_PRODUCT(*vp, n); u = n; MUL_COORD3(u,f,f,f); /* (vp.n) * n */ DIF_COORD3(v,*vp,u); /* calcule "v" */ f = (float) cos ((double) a); MUL_COORD3(v,f,f,f); /* v * cos(a) */ CROSS_PRODUCT(cross,n,*vp); f = (float) sin ((double) a); MUL_COORD3(cross,f,f,f); /* (n^v) * sin(a) */ SET_COORD3(*vp, u.x + v.x + cross.x, u.y + v.y + cross.y, u.z + v.z + cross.z); }