/********************************************************** File for vector math **********************************************************/ #include #include "qrt.h" /* #define MATHDEBUG TRUE */ /* #define MATHMAIN TRUE */ /********************************************************** Returns pseudo random number between one and 100 **********************************************************/ int PsRand() { static int val=43; val=(val*73+97); return(val%CNUM); } /********************************************************** - Vector clear to 0 **********************************************************/ VectEqZero(v) VECT_PTR v; { v->x=v->y=v->z=0.0; } /********************************************************** - - - - Vector math: V1 = V1 + k2 V2 + k3 V3 **********************************************************/ VectAddMult(v1,k2,v2,k3,v3) VECT_PTR v1,v2,v3; float k2,k3; { v1->x+=k2*(v2->x)+k3*(v3->x); v1->y+=k2*(v2->y)+k3*(v3->y); v1->z+=k2*(v2->z)+k3*(v3->z); } /********************************************************** - - Vector math: V1 = - V2 **********************************************************/ VectNegate(v1,v2) VECT_PTR v1,v2; { v1->x = -(v2->x); v1->y = -(v2->y); v1->z = -(v2->z); } /********************************************************** - - - Vector math: V1 = V2 + V3 **********************************************************/ VectorAdd(v1,v2,v3) VECT_PTR v1,v2,v3; { v1->x=v2->x+v3->x; v1->y=v2->y+v3->y; v1->z=v2->z+v3->z; } /********************************************************** - - - Vector math: V1 = V2 * V3 **********************************************************/ VectorMult(v1,v2,v3) VECT_PTR v1,v2,v3; { v1->x=v2->x*v3->x; v1->y=v2->y*v3->y; v1->z=v2->z*v3->z; } /********************************************************** - - - Vector math: V1 = V2 - V3 **********************************************************/ VecSubtract(v1,v2,v3) /* 1=2-3 */ VECT_PTR v1,v2,v3; { v1->x=v2->x-v3->x; v1->y=v2->y-v3->y; v1->z=v2->z-v3->z; } /********************************************************** - - Vector math: V1 = k V1 **********************************************************/ VectScale(v1,k,v2) /* 1=2*1 */ VECT_PTR v1; float k; { v1->x *= k; v1->y *= k; v1->z *= k; } /********************************************************** Color vector assignment **********************************************************/ SVectEQ(v1,v2) /* short vector v1=v2 */ SVECT_PTR v1,v2; { v1->r=v2->r; v1->g=v2->g; v1->b=v2->b; } /********************************************************** Vector assignment **********************************************************/ VectEQ(v1,v2) /* long vector v1=v2 */ VECT_PTR v1,v2; { v1->x=v2->x; v1->y=v2->y; v1->z=v2->z; } /********************************************************** Normalize vector V **********************************************************/ Normalize(v) VECT_PTR v; { register float l; l=sqrt(DotProd((*v),(*v))); v->x/=l; v->y/=l; v->z/=l; } /********************************************************** - - - Vector math: V1 = V2 x V3 **********************************************************/ CrossProd(v1,v2,v3) VECT_PTR v1,v2,v3; { v1->x=v2->y*v3->z-v2->z*v3->y; v1->y=v2->z*v3->x-v2->x*v3->z; v1->z=v2->x*v3->y-v2->y*v3->x; } /********************************************************** Returns position vector given line structure and parameter T **********************************************************/ FindPos(pos,line2,t) /* find position on parametric line 2 */ VECT_PTR pos; OBJ_PTR line2; float t; { # ifdef ROBUST if (line2->type!=LINE) Error(INTERNAL_ERROR,401); # endif pos->x=line2->loc.x+line2->vect1.x*t; pos->y=line2->loc.y+line2->vect1.y*t; pos->z=line2->loc.z+line2->vect1.z*t; # ifdef MATHDEBUG printf("FINDPOS: t=%f, Xout=%f, Yout=%f, Zout=%f\n", t,pos->x,pos->y,pos->z); # endif } /********************************************************** Reflects vector IN about NORM to produce OUT **********************************************************/ Reflect(out,in,norm) VECT_PTR out,in,norm; { float dot; dot = -DotProd((*in),(*norm)); # ifdef ROBUST /* CHECK THIS OUT */ /* if (dot<0) Error (INTERNAL_ERROR,402); */ # endif VectEQ(out,in); VectAddMult(out,dot,norm,dot,norm); # ifdef MATHDEBUG printf("REFLECT: in x,y,z = %f %f %f\n",in->x,in->y,in->z); printf(" norm x,y,z = %f %f %f\n",norm->x,norm->y,norm->z); printf(" out x,y,z = %f %f %f\n",out->x,out->y,out->z); # endif } /********************************************************** Arctan of 2 numbers. This *should* exist in the compiler library, but it's not there. **********************************************************/ float atan2w(x,y) float x,y; { if (x==0) { if (y>0) return(PI2); return(-PI2); } if (x>0) return(atan(y/x)); if (y>0) return(PI-atan(y/(-x))); return(-PI+atan(y/x)); } /********************************************************** DOUBLE ROTATION This is a really two multiplied transformation matricies, but this form is faster. The if statements rotate only if necessary. **********************************************************/ Rot12(invect,outvect,cos1,sin1,cos2,sin2) VECT_PTR invect, outvect; register float cos1, sin1, cos2, sin2; { #ifdef ROTATEFINISH VECTOR tempdir; /** Rotate once to YZ plane **/ if ((cos1!=0) || (sin1!=0)) { tempdir.x = invect->x * cos1 + invect->z * -sin1; tempdir.y = invect->y; tempdir.z = invect->x * sin1 + invect->z * cos1; } else { VectEQ(&tempdir,invect); } /** Rotate again to positive Y **/ if ((cos2!=0) || (sin2!=0)) { outvect->x = tempdir.x; outvect->y = tempdir.y * -cos2 + tempdir.z * sin2; outvect->z = tempdir.y * -sin2 + tempdir.z * -cos2; } else { VectEQ(outvect,&tempdir); } #endif } /********************************************************** DOUBLE ROTATION Same as above, but in reverse direction **********************************************************/ Rot21(invect,outvect,cos1,sin1,cos2,sin2) VECT_PTR invect, outvect; float cos1, sin1, cos2, sin2; { #ifdef ROTATEFINISH VECTOR tempdir; /** Rotate once from Y up direction **/ if ((cos2!=0) || (sin2!=0)) { tempdir.x = invect->x; tempdir.y = invect->y * cos2 + invect->z * -sin2; tempdir.z = invect->y * sin2 + invect->z * cos2; } else { VectEQ(&tempdir,invect); } /** Rotate again to arbitrary direction **/ if ((cos1!=0) || (sin1!=0)) { outvect->x = tempdir.x * -cos1 + tempdir.z * sin1; outvect->y = tempdir.y; outvect->z = tempdir.x * -sin1 + tempdir.z * -cos1; } else { VectEQ(outvect,&tempdir); } #endif } /********************************************************** Main for mth.c - used ONLY to test functions. **********************************************************/ # ifdef MATHMAIN Error() { } main() { VECTOR in,out; float sin1, sin2, cos1, cos2; printf("in: "); scanf("%f %f %f",&(in.x),&(in.y),&(in.z)); printf("sin1 cos1 sin2 cos2: "); scanf("%f %f %f %f",&sin1, &cos1, &sin2, &cos2); Rot12(&in,&out,cos1,sin1,cos2,sin2); printf("out12: %f %f %f\n",out.x,out.y,out.z); Rot21(&in,&out,cos1,sin1,cos2,sin2); printf("out21: %f %f %f\n",out.x,out.y,out.z); } # endif