www.pudn.com > LightTrack.rar > TransBs.cpp
/** 3DGPL *************************************************\ * () * * 3-D transformations of coordinates. * * * * Ifdefs: * * _FLOAT_ Use float implementation; * * _FIXED_ Use fixed implementation; * * _Z_BUFFER_ Depth array; * * _PAINTER_ Back to front order. * * * * Defines: * * T_init_math Creating sin/cos tables; * * * * T_translation Translation of coordinates; * * T_scaling Scaling coordinates; * * * * T_set_self_rotation Setting object rotation; * * T_self_rotation Rotation of coordinates; * * T_set_world_rotation Setting viewer's rotation; * * T_world_rotation Rotation of coordinates; * * T_cancatinate_self_world The two above matrices; * * T_cancatinated_rotation From object into view space; * * * * T_perspective Transform to perspective; * * * * T_linear_solve Gaussian elimination. * * * * (c) 1995-98 Sergei Savchenko, (savs@cs.mcgill.ca) * \**********************************************************/ //TransBs.cpp #include "LightTrack.h" /* fast copy routines */ #include "Trans.h" /* 3D mathematics */ #include/* sin & cos */ #define T_RADS 40.7436642 /* pseudo-grads into rads */ int T_log_focus; /* foreshortening */ #if defined(_FIXED_) typedef HW_32_bit T_fixed; /* better be 32bit machine */ T_fixed T_wx1,T_wx2,T_wx3,T_wy1,T_wy2,T_wy3,T_wz1,T_wz2,T_wz3; T_fixed T_sx1,T_sx2,T_sx3,T_sy1,T_sy2,T_sy3,T_sz1,T_sz2,T_sz3; T_fixed T_cx1,T_cx2,T_cx3,T_cy1,T_cy2,T_cy3,T_cz1,T_cz2,T_cz3; T_fixed T_tx,T_ty,T_tz; T_fixed T_sin[256],T_cos[256]; /* precalculated */ #endif #if defined(_FLOAT_) float T_wx1,T_wx2,T_wx3,T_wy1,T_wy2,T_wy3,T_wz1,T_wz2,T_wz3; float T_sx1,T_sx2,T_sx3,T_sy1,T_sy2,T_sy3,T_sz1,T_sz2,T_sz3; float T_cx1,T_cx2,T_cx3,T_cy1,T_cy2,T_cy3,T_cz1,T_cz2,T_cz3; float T_tx,T_ty,T_tz; float T_sin[256],T_cos[256]; /* precalculated */ #endif /**********************************************************\ * Initializing tables of trigonometric functions. * * * * SETS: T_sin and T_cos arrays. * * ----- * \**********************************************************/ void T_init_math(void) { int i; for(i=0;i<256;i++) { #if defined(_FIXED_) T_sin[i]=(int)sin(i/T_RADS)*(1< X y"=y'*cos(bet)-z'*sin(bet) * * bet | | __ z"=y'*sin(bet)+z'*cos(bet) * * V/| /| gam * * /----+ x"'=z"*sin(gam)+x"*cos(gam) * * / | y"'=y" * * / | z"'=z"*cos(gam)-x"*sin(gam) * * | * * * * SETS: T_sx1,...,T_sz3. * * ----- * \**********************************************************/ void T_set_self_rotation(unsigned char alp,unsigned char bet, unsigned char gam) { #if defined(_FIXED_) T_fixed cosalp,sinalp,cosbet,sinbet,cosgam,singam; #endif #if defined(_FLOAT_) float cosalp,sinalp,cosbet,sinbet,cosgam,singam; #endif cosalp=T_cos[alp]; sinalp=T_sin[alp]; cosbet=T_cos[bet]; sinbet=T_sin[bet]; cosgam=T_cos[gam]; singam=T_sin[gam]; /* initializing */ #if defined(_FIXED_) T_sx1=((cosalp*cosgam)>>T_P)-((sinalp*((sinbet*singam)>>T_P))>>T_P); T_sy1=((sinalp*cosgam)>>T_P)+((cosalp*((sinbet*singam)>>T_P))>>T_P); T_sz1=((cosbet*singam)>>T_P); T_sx2=-((sinalp*cosbet)>>T_P); T_sy2=((cosalp*cosbet)>>T_P); T_sz2=-sinbet; T_sx3=-((cosalp*singam)>>T_P)-((sinalp*((sinbet*cosgam)>>T_P))>>T_P); T_sy3=((cosalp*((sinbet*cosgam)>>T_P))>>T_P)-((sinalp*singam)>>T_P); T_sz3=((cosbet*cosgam)>>T_P); /* calculating the matrix */ #endif #if defined(_FLOAT_) T_sx1=cosalp*cosgam-sinalp*sinbet*singam; T_sy1=sinalp*cosgam+cosalp*sinbet*singam; T_sz1=cosbet*singam; T_sx2=-sinalp*cosbet; T_sy2=cosalp*cosbet; T_sz2=-sinbet; T_sx3=-cosalp*singam-sinalp*sinbet*cosgam; T_sy3=cosalp*sinbet*cosgam-sinalp*singam; T_sz3=cosbet*cosgam; /* calculating the matrix */ #endif } /**********************************************************\ * Rotating the coordinates object to world. * * * * |sx1 sx2 sx3| * * T'=T[S] where: [x' y' z'] = [x y z]*|sy1 sy2 sy3| * * |sz1 sz2 sz3| * * * \**********************************************************/ void T_self_rotation(int *from,register int *to,int length) { register int i,xt,yt,zt; for(i=0;i >T_P) + ((T_sy1*yt)>>T_P) + ((T_sz1*zt)>>T_P)); *to++=(int)(((T_sx2*xt)>>T_P) + ((T_sy2*yt)>>T_P) + ((T_sz2*zt)>>T_P)); *to++=(int)(((T_sx3*xt)>>T_P) + ((T_sy3*yt)>>T_P) + ((T_sz3*zt)>>T_P)); #endif #if defined(_FLOAT_) *to++=(int)(T_sx1*xt + T_sy1*yt + T_sz1*zt); *to++=(int)(T_sx2*xt + T_sy2*yt + T_sz2*zt); *to++=(int)(T_sx3*xt + T_sy3*yt + T_sz3*zt); #endif to++; from++; /* 4th element */ } } /**********************************************************\ * Constructing rotation matrix world to view: * * (gam-bet-alp), yaw, then pitch then roll sequence. * * gam-yaw, bet-pitch alp-roll. NB! angles assumed to be * * in pseudo-degrees in the range [0,256). * * * * Y^ Z x'=z*sin(gam)+x*cos(gam) * * | / y'=y * * | / alp z'=z*cos(gam)-x*sin(gam) * * /|<---+ * * | |/ | x"=x' * * -------|-+-----------> X y"=y'*cos(bet)-z'*sin(bet) * * bet | | __ z"=y'*sin(bet)+z'*cos(bet) * * V/| /| gam * * /----+ x"'=y"*sin(alp)+x"*cos(alp) * * / | y"'=y"*cos(alp)-x"*sin(alp) * * / | z"'=z" * * | * * * * SETS: T_wx1,...,T_wz3. * * ----- * \**********************************************************/ void T_set_world_rotation(unsigned char alp,unsigned char bet, unsigned char gam) { #if defined(_FIXED_) T_fixed cosalp,sinalp,cosbet,sinbet,cosgam,singam; #endif #if defined(_FLOAT_) float cosalp,sinalp,cosbet,sinbet,cosgam,singam; #endif cosalp=T_cos[alp]; sinalp=T_sin[alp]; cosbet=T_cos[bet]; sinbet=T_sin[bet]; cosgam=T_cos[gam]; singam=T_sin[gam]; /* initializing */ #if defined(_FIXED_) T_wx1=((singam*((sinbet*sinalp)>>T_P))>>T_P) + ((cosgam*cosalp)>>T_P); T_wy1=((cosbet*sinalp)>>T_P); T_wz1=((singam*cosalp)>>T_P) - ((cosgam*((sinbet*sinalp)>>T_P))>>T_P); T_wx2=((singam*((sinbet*cosalp)>>T_P))>>T_P) - ((cosgam*sinalp)>>T_P); T_wy2=((cosbet*cosalp)>>T_P); T_wz2=-((cosgam*((sinbet*cosalp)>>T_P))>>T_P) - ((singam*sinalp)>>T_P); T_wx3=-((singam*cosbet)>>T_P); T_wy3=sinbet; T_wz3=((cosgam*cosbet)>>T_P); /* calculating the matrix */ #endif #if defined(_FLOAT_) T_wx1=singam*sinbet*sinalp + cosgam*cosalp; T_wy1=cosbet*sinalp; T_wz1=singam*cosalp - cosgam*sinbet*sinalp; T_wx2=singam*sinbet*cosalp - cosgam*sinalp; T_wy2=cosbet*cosalp; T_wz2=-cosgam*sinbet*cosalp - singam*sinalp; T_wx3=-singam*cosbet; T_wy3=sinbet; T_wz3=cosgam*cosbet; /* calculating the matrix */ #endif } /**********************************************************\ * Rotating the coordinates world to view. * * * * |wx1 wx2 wx3| * * T'=T[W] where: [x' y' z'] = [x y z]*|wy1 wy2 wy3| * * |wz1 wz2 wz3| * * * \**********************************************************/ void T_world_rotation(int *from,register int *to,int length) { register int i,xt,yt,zt; for(i=0;i >T_P) + ((T_wy1*yt)>>T_P) + ((T_wz1*zt)>>T_P)); *to++=(int)(((T_wx2*xt)>>T_P) + ((T_wy2*yt)>>T_P) + ((T_wz2*zt)>>T_P)); *to++=(int)(((T_wx3*xt)>>T_P) + ((T_wy3*yt)>>T_P) + ((T_wz3*zt)>>T_P)); #endif #if defined(_FLOAT_) *to++=(int)(T_wx1*xt+T_wy1*yt+T_wz1*zt); *to++=(int)(T_wx2*xt+T_wy2*yt+T_wz2*zt); *to++=(int)(T_wx3*xt+T_wy3*yt+T_wz3*zt); #endif to++; from++; /* 4th element */ } } /**********************************************************\ * Cancatinating matrices of object to world rotation, * * some translation (may have been object and camera * * translations combined earlier) and world to view * * rotation to obtain a single transformation from object * * to view space. * * * * [K]=[S][T][W] * * * * * * SETS: T_kx1,...,T_kz3,T_tx,T_ty,T_tz. * * ----- * \**********************************************************/ void T_cancatinate_self_world(int addx,int addy,int addz) { #if defined(_FIXED_) T_cx1=(int)(((T_sx1*T_wx1)>>T_P)+((T_sx2*T_wy1)>>T_P)+((T_sx3*T_wz1)>>T_P)); T_cx2=(int)(((T_sx1*T_wx2)>>T_P)+((T_sx2*T_wy2)>>T_P)+((T_sx3*T_wz2)>>T_P)); T_cx3=(int)(((T_sx1*T_wx3)>>T_P)+((T_sx2*T_wy3)>>T_P)+((T_sx3*T_wz3)>>T_P)); T_cy1=(int)(((T_sy1*T_wx1)>>T_P)+((T_sy2*T_wy1)>>T_P)+((T_sy3*T_wz1)>>T_P)); T_cy2=(int)(((T_sy1*T_wx2)>>T_P)+((T_sy2*T_wy2)>>T_P)+((T_sy3*T_wz2)>>T_P)); T_cy3=(int)(((T_sy1*T_wx3)>>T_P)+((T_sy2*T_wy3)>>T_P)+((T_sy3*T_wz3)>>T_P)); T_cz1=(int)(((T_sz1*T_wx1)>>T_P)+((T_sz2*T_wy1)>>T_P)+((T_sz3*T_wz1)>>T_P)); T_cz2=(int)(((T_sz1*T_wx2)>>T_P)+((T_sz2*T_wy2)>>T_P)+((T_sz3*T_wz2)>>T_P)); T_cz3=(int)(((T_sz1*T_wx3)>>T_P)+((T_sz2*T_wy3)>>T_P)+((T_sz3*T_wz3)>>T_P)); T_tx=(int)(((addx*T_wx1)>>T_P)+((addy*T_wy1)>>T_P)+((addz*T_wz1)>>T_P)); T_ty=(int)(((addx*T_wx2)>>T_P)+((addy*T_wy2)>>T_P)+((addz*T_wz2)>>T_P)); T_tz=(int)(((addx*T_wx3)>>T_P)+((addy*T_wy3)>>T_P)+((addz*T_wz3)>>T_P)); #endif #if defined(_FLOAT_) T_cx1=T_sx1*T_wx1+T_sx2*T_wy1+T_sx3*T_wz1; T_cx2=T_sx1*T_wx2+T_sx2*T_wy2+T_sx3*T_wz2; T_cx3=T_sx1*T_wx3+T_sx2*T_wy3+T_sx3*T_wz3; T_cy1=T_sy1*T_wx1+T_sy2*T_wy1+T_sy3*T_wz1; T_cy2=T_sy1*T_wx2+T_sy2*T_wy2+T_sy3*T_wz2; T_cy3=T_sy1*T_wx3+T_sy2*T_wy3+T_sy3*T_wz3; T_cz1=T_sz1*T_wx1+T_sz2*T_wy1+T_sz3*T_wz1; T_cz2=T_sz1*T_wx2+T_sz2*T_wy2+T_sz3*T_wz2; T_cz3=T_sz1*T_wx3+T_sz2*T_wy3+T_sz3*T_wz3; T_tx=addx*T_wx1+addy*T_wy1+addz*T_wz1; T_ty=addx*T_wx2+addy*T_wy2+addz*T_wz2; T_tz=addx*T_wx3+addy*T_wy3+addz*T_wz3; #endif } /**********************************************************\ * Transforming the coordinates object to view. * * * * |cx1 cx2 cx3 0| * * T'=T[K] where: [x' y' z' 1]=[x y z 1]*|cy1 cy2 cy3 0| * * |cz1 cz2 cz3 0| * * |tx ty tz 1| * * * \**********************************************************/ void T_cancatinated_rotation(int *from,register int *to,int length) { register int i,xt,yt,zt; for(i=0;i >T_P)+((T_cy1*yt)>>T_P)+((T_cz1*zt)>>T_P)+T_tx); *to++=(int)(((T_cx2*xt)>>T_P)+((T_cy2*yt)>>T_P)+((T_cz2*zt)>>T_P)+T_ty); *to++=(int)(((T_cx3*xt)>>T_P)+((T_cy3*yt)>>T_P)+((T_cz3*zt)>>T_P)+T_tz); #endif #if defined(_FLOAT_) *to++=(int)(T_cx1*xt+T_cy1*yt+T_cz1*zt+T_tx); *to++=(int)(T_cx2*xt+T_cy2*yt+T_cz2*zt+T_ty); *to++=(int)(T_cx3*xt+T_cy3*yt+T_cz3*zt+T_tz); #endif to++; from++; /* 4th element */ } } /**********************************************************\ * Transforming to perspective, the coordinates passed * * are supposed to be both volume, and Z-clipped, * * otherwise division by 0 or overflow may occur. * * Also, performs the screen centre translation. * * * * * * * /|X * * / | * * / | * * * | * * /|X' | X' X * * / | | ------- = --- * * / | | focus Z * * *---+---+ * * 0 ^ Z X'= X*focus/Z * * | * * focus * * * \**********************************************************/ void T_perspective(int *from,register int *to,int dimension, int length,int log_focus ) { register int i; int rem_dim=dimension-3; /* other then X Y Z */ for(i=0;i >log_source_multiplyer); for(j=0;j >log_source_multiplyer); for(j=0;j =0) pivot=a[j][i]; else pivot=-a[j][i]; if(pivot>max) { max=pivot; num=j; } } if(max!=0) /* for non zero pivots */ { if(num!=i) /* swap is requied */ { for(j=0;j =0;i--) /* reversed direction */ { for(k=0;k >log_result_multiplyer); x[i][k]=(((b[i][k])-sum)<