home *** CD-ROM | disk | FTP | other *** search
- #include <xforms.h>
- #include <stdio.h>
-
-
-
- /* if your compiler supports some form of function inlining, you can try
- removing the comment below (doubt it will work though) */
-
- /* For the two next functions, in a real program they would probably
- be implemented as macros for more speed */
- fixedpoint fixed_mul(fixedpoint a, fixedpoint b)
- {
- #ifdef __TURBOC__
- #pragma inline
-
- /* Note:
- The following asm code is very fast for a PC. Ideally, you should
- make it so that you use this code instead of the code after the
- #else (of course, ideally it should be inlined...) */
-
- long c;
- asm{
- mov eax,a /*first operand*/
- mov edx,b /*second operand*/
- imul edx /*multiply them*/
- shl edx,16 /* put integer value in upper 16 bits*/
- shr eax,16 /* truncate fraction part*/
- or eax,edx /* fuse integer and fractional part*/
- mov c,eax
- }
- return c;
- #else
- return ((a/256)*(b/256)); /* a poor patch*/
- #endif
- }
-
-
-
- fixedpoint fixed_div(fixedpoint a, fixedpoint b)
- {
- #ifdef __TURBOC__
- /* Note:
- The following asm code is very fast for a PC. Ideally, you should
- make it so that you use this code instead of the code after the
- #else (of course, ideally it should be inlined...) */
- long c;
- asm{
- mov edx,a /*load a in edx:eax, 64 bits*/
- mov eax,edx
- sar edx,16
- shl eax,16
- mov ecx,b /* load b in ecx*/
- idiv ecx /* divide edx:eax by ecx*/
- mov c,eax
- }
- return c;
- #else
- return ((a*256)/(b/256)); /* poor patch*/
- #endif
- }
-
-
- void mat_add(matrix r, matrix a, matrix b)
- {
- int x,y;
-
- for(x=0;x<3;x++)
- for(y=0;y<3;y++)
- r[x][y]=add(a[x][y],b[x][y]);
- }
-
-
-
- void mat_sub(matrix r, matrix a, matrix b)
- {
- int x,y;
-
- for(x=0;x<3;x++)
- for(y=0;y<3;y++)
- r[x][y]=sub(a[x][y],b[x][y]);
- }
-
-
-
- void mat_mul(matrix r, matrix a, matrix b)
- {
- int x,y,z;
-
- for(x=0;x<3;x++)
- for(y=0;y<3;y++)
- {
- r[y][x]=floattoreal(0.0);
- for(z=0;z<3;z++)
- r[y][x]=add(r[y][x],mul(a[z][x],b[y][z]));
- }
- }
-
-
-
- void mat_mul_vec(vector r, matrix a, vector b)
- {
- int x,y;
-
- for(x=0;x<3;x++)
- {
- r[x]=floattoreal(0.0);
- for(y=0;y<3;y++)
- r[x]=add(r[x],mul(a[y][x],b[y]));
- }
- }
-
-
-
- void vec_add(vector r, vector a, vector b)
- {
- int x;
-
- for(x=0;x<3;x++)
- r[x]=add(a[x],b[x]);
- }
-
-
-
-
- void vec_sub(vector r, vector a, vector b)
- {
- int x;
-
- for(x=0;x<3;x++)
- r[x]=sub(a[x],b[x]);
- }
-
-
-
-
- REAL vec_dot(vector a, vector b)
- {
- /* a dot b is a[0]*b[0]+a[1]*b[1]+a[2]*b[2] */
- REAL dot;
- int x;
-
- dot=floattoreal(0.0);
- for(x=0;x<3;x++)
- dot=add(dot,mul(a[x],b[x]));
- return dot;
- }
-
-
-
- void vec_normalize(vector a)
- {
- REAL length;
- int x;
-
- /* first use find euclidian length of vector. It is the square root
- of the sum of the square of the vector components. E.g. in 2d, this
- simplifies to pythagora's theorem, a^2+b^2=c^2. In 3d, it's
- a^2+b^2+c^2=d^2 */
-
- #ifdef use_fixed
- do {
- #endif
- length=floattoreal(0.0);
-
- for(x=0;x<3;x++)
- length=add(length,mul(a[x],a[x])); /* calculate sum */
-
- length=SQRT(length); /* extract square root */
- #ifdef use_fixed
- if(length<=floattoreal(0.001))
- vec_mul_scl(a,a,floattoreal(1000));
- } while(length<=floattoreal(0.001));
- #endif
-
- /* second divide each component of the vector by the length of the
- vector */
- for(x=0;x<3;x++)
- a[x]=div(a[x],length);
- }
-
-
-
- void vec_mul_scl(vector r, vector a, REAL b)
- {
- int x;
-
- for(x=0;x<3;x++)
- r[x]=mul(a[x],b);
- }
-
-
-
- void vec_crs(vector r, vector a, vector b)
- {
- /* (a0,a1,a2) cross (b0,b1,b2) is
- (a1b2-a2b1 , a2b0,a0b2 , a0b1-a1b0) */
- r[0]=sub(mul(a[1],b[2]),mul(a[2],b[1]));
- r[1]=sub(mul(a[2],b[0]),mul(a[0],b[2]));
- r[2]=sub(mul(a[0],b[1]),mul(a[1],b[0]));
- }
-
-
-
-
- void mat_orthonormalize(matrix a)
- {
- vector temp;
- /* normalize first vector */
- vec_normalize(a[0]);
-
- /* make second vector perpendicular to the first */
- vec_mul_scl(temp,
- a[0],
- vec_dot(a[1],a[0])
- );
- vec_sub(a[1],
- a[1],
- temp
- );
-
- /* normalize second vector */
- vec_normalize(a[1]);
-
- /* third vector is first cross second */
- vec_crs(a[2],a[0],a[1]);
- /* no need to normalize this third one since the first two are
- normalized*/
- }
-
-
- #define z(x,y) m[x][y]=floattoreal(a##y##x)
-
- void initmatrix(matrix m,
- float a00, float a01, float a02,
- float a10, float a11, float a12,
- float a20, float a21, float a22)
- {
- z(0,0);
- z(0,1);
- z(0,2);
-
- z(1,0);
- z(1,1);
- z(1,2);
-
- z(2,0);
- z(2,1);
- z(2,2);
- }
-
- void printmatrix(matrix m)
- {
- int x;
-
- for(x=0;x<3;x++)
- {
- printf("\n%13.5f %13.5f %13.5f",
- realtofloat(m[0][x]),
- realtofloat(m[1][x]),
- realtofloat(m[2][x])
- );
- }
-
- printf("\n");
- }
-
-
-
- void initvector(vector v,
- float i, float j, float k)
- {
- v[0]=i;
- v[1]=j;
- v[2]=k;
- }
-
-
-
-
- void printvector(vector v)
- {
- printf("\n(%f,%f,%f)\n",
- realtofloat(v[0]),
- realtofloat(v[1]),
- realtofloat(v[2]));
- }
-
-
-
-
- void copymatrix(matrix dest, matrix src)
- {
- copyvector(dest[0],src[0]);
- copyvector(dest[1],src[1]);
- copyvector(dest[2],src[2]);
- }
-
-
-
- void copyvector(vector dest, vector src)
- {
- dest[0]=src[0];
- dest[1]=src[1];
- dest[2]=src[2];
- }
-
-
-
- void rotatevectors(vector v1, vector v2,
- vector u1, vector u2,
- REAL theta)
- {
- REAL s,c; /* sintheta and costheta respectively */
- vector t1,t2,g1,g2;
-
- s=SIN(theta);
- c=COS(theta);
-
- /* formula is: u1=v1costheta-v2sintheta
- u2=v1sintheta+v2costheta */
-
- vec_mul_scl(t1,v1,c);
- vec_mul_scl(t2,v2,s);
-
- vec_mul_scl(g1,v1,s);
- vec_mul_scl(g2,v2,c);
-
- vec_sub(u1,t1,t2);
- vec_add(u2,g1,g2);
- }
-
-
-
- void rotatebase(matrix m, int axis, REAL theta)
- {
- int a,b;
-
- a=axis+1;
- if(a>=3)
- a-=3;
- b=a+1;
- if(b>=3)
- b-=3;
-
- rotatevectors(m[a],m[b],m[a],m[b],theta);
- }
-
-
- REAL determinant(matrix m)
- {
- /* det m is:
- m[0][0]*m[1][1]*m[2][2]+
- m[0][1]*m[1][2]*m[2][0]+
- m[0][2]*m[1][0]*m[2][1]
- -
- m[0][0]*m[1][2]*m[2][1]-
- m[0][1]*m[1][0]*m[2][2]-
- m[0][2]*m[1][1]*m[2][0]
- */
-
- return
- mul(mul(m[0][0],m[1][1]),m[2][2])+
- mul(mul(m[0][1],m[1][2]),m[2][0])+
- mul(mul(m[0][2],m[1][0]),m[2][1])
- -
- mul(mul(m[0][0],m[1][2]),m[2][1])-
- mul(mul(m[0][1],m[1][0]),m[2][2])-
- mul(mul(m[0][2],m[1][1]),m[2][0]);
- }
-
-
- void mat_mul_scl(matrix r, matrix a, REAL b)
- {
- int x,y;
-
- for(x=0;x<3;x++)
- for(y=0;y<3;y++)
- r[x][y]=mul(a[x][y],b);
- }
-
-
-
- int invert(matrix m, matrix r)
- {
- /* inverse matrix is cofactors matrix divided by determinant if
- determinant is nonzero. so first calculate determinant, if
- zero return error. then calculate cofactor matrix and divide by
- determinant */
- matrix cof;
- REAL det;
-
-
- det=determinant(m);
- if(!det)
- {
- return -1; /* error, matrix inverse does not exist */
- }
-
- /* matrix of cofactors is hard wired here for 3x3 matrices */
- initmatrix(r,
- mul(m[1][1],m[2][2])-mul(m[1][2],m[2][1]),
- mul(m[2][0],m[1][2])-mul(m[1][0],m[2][2]),
- mul(m[1][0],m[2][1])-mul(m[2][0],m[1][1]),
-
- mul(m[2][1],m[0][2])-mul(m[0][1],m[2][2]),
- mul(m[0][0],m[2][2])-mul(m[0][2],m[2][0]),
- mul(m[2][0],m[0][1])-mul(m[0][0],m[2][1]),
-
- mul(m[0][1],m[1][2])-mul(m[1][1],m[0][2]),
- mul(m[1][0],m[0][2])-mul(m[0][0],m[1][2]),
- mul(m[0][0],m[1][1])-mul(m[1][0],m[0][1]));
-
- /* now we have matrix of cofactors. multiply it by 1/det */
-
- det=div(floattoreal(1.0),det);
-
- mat_mul_scl(r,r,det);
-
- /* return success */
- return 0;
- }
-
-
-
- int invert_affine(affine *a, affine *r)
- {
- if(invert(a->m,r->m))
- return -1;
-
- mat_mul_vec(r->v,a->m,a->v);
- r->v[0]=-r->v[0];
- r->v[1]=-r->v[1];
- r->v[2]=-r->v[2];
- return 0;
- }
-
-
-
-
- void affine_xform(affine *a, vector i, vector j)
- {
- mat_mul_vec(j,a->m,i);
- vec_add(j,j,a->v);
- }
-
-