home *** CD-ROM | disk | FTP | other *** search
- /** 3DGPL *************************************************\
- * () *
- * 3-D transformations of coordinates using fixed point. *
- * *
- * Defines: *
- * T_init_math Creating sin/cos tables; *
- * *
- * T_translation Shifting of coordinates; *
- * T_scaling Scaling coordinates; *
- * *
- * T_set_world_rotation Viewer's rotation; *
- * T_world_rotation Transforming coordinates; *
- * T_set_self_rotation Object rotation; *
- * T_self_rotation Transforming coordinates; *
- * *
- * T_perspective Transform to perspective. *
- * *
- * Internals: *
- * TI_float2fixed Converting float to fixed. *
- * *
- * (6/1995) By Sergei Savchenko. (savs@cs.mcgill.ca). *
- * Copyright (c) 1995 Sergei Savchenko. *
- * THIS SOURCE CODE CAN'T BE USED FOR COMERCIAL PURPOSES *
- * WITHOUT AUTHORISATION *
- \**********************************************************/
-
- #include <math.h> /* sin & cos */
-
- #ifdef __MWERKS__
- #include "hardware.h" /* 32bit int name */
- #include "trans.h" /* 3D mathematics */
- #else
- #include "../hardware/hardware.h" /* 32bit int name */
- #include "../trans/trans.h" /* 3D mathematics */
- #endif
-
- typedef signed_32_bit fixed; /* better be 32bit machine */
-
- #define T_RADS 40.7436642 /* pseudo-grads into rads */
- #define T_P 14 /* fixed math precision */
-
- fixed T_wx1,T_wx2,T_wx3,T_wy1,T_wy2,T_wy3,T_wz1,T_wz2,T_wz3;
- fixed T_sx1,T_sx2,T_sx3,T_sy1,T_sy2,T_sy3,T_sz1,T_sz2,T_sz3;
- fixed T_sin[256],T_cos[256]; /* precalculated */
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
- * INTERNAL: Converting [-1,1] float into fixed. *
- * --------- *
- \* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
- fixed TI_float2fixed(float a)
- {
- fixed res=0;
- int i,dv,sign;
-
- if((sign=a<0.0)==1) a=-a;
-
- for(i=1,dv=2;i<=T_P;i++,dv*=2)
- if(a>=1.0/dv) { a-=1.0/dv; res|=(0x1<<(T_P-i)); };
-
- if(sign==1) res=-res;
-
- return(res);
- }
-
- /**********************************************************\
- * Initializing tables. *
- \**********************************************************/
-
- void T_init_math(void)
- {
- int i;
-
- for(i=0;i<256;i++)
- {
- T_sin[i]=TI_float2fixed(sin(i/T_RADS));
- T_cos[i]=TI_float2fixed(cos(i/T_RADS));
- }
- }
-
- /**********************************************************\
- * Translation of coordinates. *
- \**********************************************************/
-
- void T_translation(register int *from,register int *to,int length,
- int addx,int addy,int addz
- )
- {
- register int i;
-
- for(i=0;i<length;i++)
- {
- (*to++)=(*from++)+addx;
- (*to++)=(*from++)+addy;
- (*to++)=(*from++)+addz; /* translation */
- }
- }
-
- /**********************************************************\
- * Scaling coordinates. (takes in float parameters). *
- \**********************************************************/
-
- void T_scaling(register int *from,register int *to,int length,
- int mulx,int muly,int mulz
- )
- {
- register int i;
-
- for(i=0;i<length;i++)
- {
- (*to++)=(int)(*from++)*mulx;
- (*to++)=(int)(*from++)*muly;
- (*to++)=(int)(*from++)*mulz;
- } /* scaling */
- }
-
- /**********************************************************\
- * Constructing rotation matrix. (gam-bet-alp), rotation *
- * then pitch then roll sequence. gam-rotation, bet-pitch*
- * alp-roll. *
- * *
- * 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" *
- * | *
- \**********************************************************/
-
- void T_set_world_rotation(int alp,int bet,int gam)
- {
- fixed cosalp,sinalp,cosbet,sinbet,cosgam,singam;
-
- 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 */
-
- 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 */
- }
-
- /**********************************************************\
- * Rotating coordinates. *
- * |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;
- register int xt,yt,zt;
-
- for(i=0;i<length;i++)
- {
- xt=*from++;
- yt=*from++;
- zt=*from++;
-
- *to++=((T_wx1*xt)>>T_P) + ((T_wy1*yt)>>T_P) + ((T_wz1*zt)>>T_P);
- *to++=((T_wx2*xt)>>T_P) + ((T_wy2*yt)>>T_P) + ((T_wz2*zt)>>T_P);
- *to++=((T_wx3*xt)>>T_P) + ((T_wy3*yt)>>T_P) + ((T_wz3*zt)>>T_P);
- }
- }
-
- /**********************************************************\
- * Constructing rotation matrix. (alp-bet-gam), roll *
- * then pitch then rotation sequence. gam-rotation, *
- * bet-pitch, alp-roll*
- * *
- * Y^ Z x'=y*sin(alp)+x*cos(alp) *
- * | / y'=y*cos(alp)-x*sin(alp) *
- * | / alp z'=z *
- * /|<---+ *
- * | |/ | x"=x' *
- * -------|-+-----------> 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) *
- * | *
- \**********************************************************/
-
- void T_set_self_rotation(int alp,int bet,int gam)
- {
- fixed cosalp,sinalp,cosbet,sinbet,cosgam,singam;
-
- 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 */
-
- 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 */
- }
-
- /**********************************************************\
- * Rotating coordinates. *
- * |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;
- register int xt,yt,zt;
-
- for(i=0;i<length;i++)
- {
- xt=*from++;
- yt=*from++;
- zt=*from++;
-
- *to++=((T_sx1*xt)>>T_P) + ((T_sy1*yt)>>T_P) + ((T_sz1*zt)>>T_P);
- *to++=((T_sx2*xt)>>T_P) + ((T_sy2*yt)>>T_P) + ((T_sz2*zt)>>T_P);
- *to++=((T_sx3*xt)>>T_P) + ((T_sy3*yt)>>T_P) + ((T_sz3*zt)>>T_P);
- }
- }
-
- /**********************************************************\
- * Transforming to perspective, coordinates passed ase *
- * supposed to be both volume, and *
- * * Z-clipped, otherwise division *
- * /|X by 0 or overflow can occur. *
- * / | *
- * / | *
- * * | *
- * /|X' | X' X *
- * / | | ------- = --- *
- * / | | focus Z *
- * *---+---+ *
- * 0 ^ Z X'= X*focus/Z *
- * | *
- * focus *
- * *
- * ADDITIONAL FUNCTIONS: 1) changing formats: *
- * --------------------- *
- * source: x, y ,z,a1,...,aN where N==dimension-3*
- * destanation: x',y', a1,...,aN *
- * *
- * 2) performs translation to the screen centre. *
- \**********************************************************/
-
- void T_perspective(register int *from,register int *to,
- int dimension,int length
- )
- {
- register int i;
-
- dimension-=3; /* other then X,Y */
-
- for(i=0;i<length;i++,from+=dimension,to+=dimension)
- { /* Z is not being changed */
- to[0]=((((long)from[0])<<T_LOG_FOCUS)/from[2])+HW_SCREEN_X_CENTRE;
- to[1]=((((long)from[1])<<T_LOG_FOCUS)/from[2])+HW_SCREEN_Y_CENTRE;
- HW_copy_int(from+=3,to+=2,dimension);
- }
- }
-
- /**********************************************************/
-