//vectors.cpp //vector and matrix math functions #include "vectors.h" #include "gamemem.h" #include //Add and Subtract Matrices void MatrixAdd(tMatrix3 x,tMatrix3 y,tMatrix3 m) { int i,j; for(i=0;i<3;i++) for(j=0;j<3;j++) m[i][j]=x[i][j]+y[i][j]; } void MatrixAdd(tMatrix4 x,tMatrix4 y,tMatrix4 m) { int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) m[i][j]=x[i][j]+y[i][j]; } void MatrixSub(tMatrix3 x,tMatrix3 y,tMatrix3 m) { int i,j; for(i=0;i<3;i++) for(j=0;j<3;j++) m[i][j]=x[i][j]-y[i][j]; } void MatrixSub(tMatrix4 x,tMatrix4 y,tMatrix4 m) { int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) m[i][j]=x[i][j]-y[i][j]; } //Multiplay Matrices with Scalars void MatrixMult(tMatrix3 x,float y,tMatrix3 m) { int i,j; for(i=0;i<3;i++) for(j=0;j<3;j++) m[i][j]=x[i][j]*y; } void MatrixMult(tMatrix4 x,float y,tMatrix4 m) { int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) m[i][j]=x[i][j]*y; } void MatrixMult(float y,tMatrix3 x,tMatrix3 m) { int i,j; for(i=0;i<3;i++) for(j=0;j<3;j++) m[i][j]=x[i][j]*y; } void MatrixMult(float y,tMatrix4 x,tMatrix4 m) { int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) m[i][j]=x[i][j]*y; } //Convert a 3x3 matrix to a 4x4 matrix void Matrix3ToMatrix4(tMatrix3 x,tMatrix4 m) { m[0][0]=x[0][0];m[0][1]=x[0][1];m[0][2]=x[0][2];m[0][3]=0; m[1][0]=x[1][0];m[1][1]=x[1][1];m[1][2]=x[1][2];m[1][3]=0; m[2][0]=x[2][0];m[2][1]=x[2][1];m[2][2]=x[2][2];m[2][3]=0; m[3][0]=0; m[3][1]=0; m[3][2]=0; m[3][3]=1; } //Copy matrices void MatrixCopy(tMatrix3 src,tMatrix3 dst) { MemoryMove(dst,src,sizeof(tMatrix3)); } void MatrixCopy(tMatrix4 src,tMatrix4 dst) { MemoryMove(dst,src,sizeof(tMatrix4)); } void MatrixCopy(tMatrix3 src,tMatrix4 dst) { Matrix3ToMatrix4(src,dst); } //Convert a vector of euler angles to a matrix void EulerAnglesToMatrix(tVector3 euler,tMatrix3 dst) { MatrixIdentity(dst); MatrixRotX(dst,euler.x); MatrixRotY(dst,euler.y); MatrixRotZ(dst,euler.z); } void EulerAnglesToMatrix(tVector3 euler,tMatrix4 dst) { MatrixIdentity(dst); MatrixRotX(dst,euler.x); MatrixRotY(dst,euler.y); MatrixRotZ(dst,euler.z); } //Convert a matrix to a vector of euler angles tVector3 MatrixToEulerAngles(tMatrix3 m) { tVector3 euler; if(fabs(m[0][2])<=1) euler.y=-asin(m[0][2]); else euler.y=-asin(sign(m[0][2])); float C=cos(euler.y); float trX,trY; if(fabs(C)>0.005) { trX=m[2][2]/C; trY=-m[1][2]/C; euler.x=-atan2(trY,trX); trX=m[0][0]/C; trY=-m[0][1]/C; euler.z=-atan2(trY,trX); } else //Gimbal Lock { euler.x=0; trX=m[1][1]; trY=m[1][0]; euler.z=atan2(trY,trX); } return euler; } tVector3 MatrixToEulerAngles(tMatrix4 m) { tVector3 euler; euler.y=-asin(m[0][2]); float C=cos(euler.y); float trX,trY; if(fabs(C)>0.005) { trX=m[2][2]/C; trY=-m[1][2]/C; euler.x=-atan2(trY,trX); trX=m[0][0]/C; trY=-m[0][1]/C; euler.z=-atan2(trY,trX); } else //Gimbal Lock { euler.x=0; trX=m[1][1]; trY=m[1][0]; euler.z=atan2(trY,trX); } return euler; } //Multiply matrices void MatrixMult(tMatrix3 x,tMatrix3 y,tMatrix3 m) { int i,j,k; if(x==m||y==m){ tMatrix3 target; for(j=0;j<3;j++) { target[0][j]=x[0][0]*y[0][j] +x[0][1]*y[1][j] +x[0][2]*y[2][j]; target[1][j]=x[1][0]*y[0][j] +x[1][1]*y[1][j] +x[1][2]*y[2][j]; target[2][j]=x[2][0]*y[0][j] +x[2][1]*y[1][j] +x[2][2]*y[2][j]; } MemoryMove(m,target,sizeof(tMatrix3)); } else for(j=0;j<3;j++) { m[0][j]=x[0][0]*y[0][j] +x[0][1]*y[1][j] +x[0][2]*y[2][j]; m[1][j]=x[1][0]*y[0][j] +x[1][1]*y[1][j] +x[1][2]*y[2][j]; m[2][j]=x[2][0]*y[0][j] +x[2][1]*y[1][j] +x[2][2]*y[2][j]; } } void MatrixMult(tMatrix3 x,tMatrix4 y,tMatrix4 m) { tMatrix4 x4; Matrix3ToMatrix4(x,x4); MatrixMult(x4,y,m); } void MatrixMult(tMatrix4 x,tMatrix3 y,tMatrix4 m) { tMatrix4 y4; Matrix3ToMatrix4(y,y4); MatrixMult(x,y4,m); } void MatrixMult(tMatrix4 x,tMatrix4 y,tMatrix4 m) { int i,j,k; if(x==m||y==m){ tMatrix4 target; for(j=0;j<4;j++) { target[0][j]=x[0][0]*y[0][j] +x[0][1]*y[1][j] +x[0][2]*y[2][j] +x[0][3]*y[3][j]; target[1][j]=x[1][0]*y[0][j] +x[1][1]*y[1][j] +x[1][2]*y[2][j] +x[1][3]*y[3][j]; target[2][j]=x[2][0]*y[0][j] +x[2][1]*y[1][j] +x[2][2]*y[2][j] +x[2][3]*y[3][j]; target[3][j]=x[3][0]*y[0][j] +x[3][1]*y[1][j] +x[3][2]*y[2][j] +x[3][3]*y[3][j]; } MemoryMove(m,target,sizeof(tMatrix4)); } else { for(j=0;j<4;j++) { m[0][j]=x[0][0]*y[0][j] +x[0][1]*y[1][j] +x[0][2]*y[2][j] +x[0][3]*y[3][j]; m[1][j]=x[1][0]*y[0][j] +x[1][1]*y[1][j] +x[1][2]*y[2][j] +x[1][3]*y[3][j]; m[2][j]=x[2][0]*y[0][j] +x[2][1]*y[1][j] +x[2][2]*y[2][j] +x[2][3]*y[3][j]; m[3][j]=x[3][0]*y[0][j] +x[3][1]*y[1][j] +x[3][2]*y[2][j] +x[3][3]*y[3][j]; } } } //makes an identity matrix void MatrixIdentity(tMatrix3 m) { m[0][0]=1;m[0][1]=0;m[0][2]=0; m[1][0]=0;m[1][1]=1;m[1][2]=0; m[2][0]=0;m[2][1]=0;m[2][2]=1; } void MatrixIdentity(tMatrix4 m) { m[0][0]=1;m[0][1]=0;m[0][2]=0;m[0][3]=0; m[1][0]=0;m[1][1]=1;m[1][2]=0;m[1][3]=0; m[2][0]=0;m[2][1]=0;m[2][2]=1;m[2][3]=0; m[3][0]=0;m[3][1]=0;m[3][2]=0;m[3][3]=1; } //Translates a matrix void MatrixTranslate(tMatrix4 target,float x,float y,float z) { tMatrix4 m; m[0][0]=1;m[0][1]=0;m[0][2]=0;m[0][3]=0; m[1][0]=0;m[1][1]=1;m[1][2]=0;m[1][3]=0; m[2][0]=0;m[2][1]=0;m[2][2]=1;m[2][3]=0; m[3][0]=x;m[3][1]=y;m[3][2]=z;m[3][3]=1; MatrixMult(target,m,target); } void MatrixTranslateVector(tMatrix4 target,tVector3 v) { tMatrix4 m; m[0][0]=1;m[0][1]=0;m[0][2]=0;m[0][3]=0; m[1][0]=0;m[1][1]=1;m[1][2]=0;m[1][3]=0; m[2][0]=0;m[2][1]=0;m[2][2]=1;m[2][3]=0; m[3][0]=v.x;m[3][1]=v.y;m[3][2]=v.z;m[3][3]=1; MatrixMult(target,m,target); } //Scales a matrix void MatrixScale(tMatrix3 target,float x,float y,float z) { tMatrix3 m; m[0][0]=x;m[0][1]=0;m[0][2]=0; m[1][0]=0;m[1][1]=y;m[1][2]=0; m[2][0]=0;m[2][1]=0;m[2][2]=z; MatrixMult(target,m,target); } void MatrixScale(tMatrix4 target,float x,float y,float z) { tMatrix4 m; m[0][0]=x;m[0][1]=0;m[0][2]=0;m[0][3]=0; m[1][0]=0;m[1][1]=y;m[1][2]=0;m[1][3]=0; m[2][0]=0;m[2][1]=0;m[2][2]=z;m[2][3]=0; m[3][0]=0;m[3][1]=0;m[3][2]=0;m[3][3]=1; MatrixMult(target,m,target); } void MatrixScaleVector(tMatrix3 target,tVector3 v) { tMatrix3 m; m[0][0]=v.x;m[0][1]=0;m[0][2]=0; m[1][0]=0;m[1][1]=v.y;m[1][2]=0; m[2][0]=0;m[2][1]=0;m[2][2]=v.z; MatrixMult(target,m,target); } void MatrixScaleVector(tMatrix4 target,tVector3 v) { tMatrix4 m; m[0][0]=v.x;m[0][1]=0;m[0][2]=0;m[0][3]=0; m[1][0]=0;m[1][1]=v.y;m[1][2]=0;m[1][3]=0; m[2][0]=0;m[2][1]=0;m[2][2]=v.z;m[2][3]=0; m[3][0]=0;m[3][1]=0;m[3][2]=0;m[3][3]=1; MatrixMult(target,m,target); } //Rotates a matrix void MatrixRotX(tMatrix3 target,float r) { tMatrix3 m; m[0][0]=1;m[0][1]=0;m[0][2]=0; m[1][0]=0;m[1][1]=cos(r);m[1][2]=sin(r); m[2][0]=0;m[2][1]=-sin(r);m[2][2]=cos(r); MatrixMult(target,m,target); } void MatrixRotX(tMatrix4 target,float r) { tMatrix4 m; m[0][0]=1;m[0][1]=0;m[0][2]=0;m[0][3]=0; m[1][0]=0;m[1][1]=cos(r);m[1][2]=sin(r);m[1][3]=0; m[2][0]=0;m[2][1]=-sin(r);m[2][2]=cos(r);m[2][3]=0; m[3][0]=0;m[3][1]=0;m[3][2]=0;m[3][3]=1; MatrixMult(target,m,target); } void MatrixRotY(tMatrix3 target,float r) { tMatrix3 m; m[0][0]=cos(r);m[0][1]=0;m[0][2]=-sin(r); m[1][0]=0;m[1][1]=1;m[1][2]=0; m[2][0]=sin(r);m[2][1]=0;m[2][2]=cos(r); MatrixMult(target,m,target); } void MatrixRotY(tMatrix4 target,float r) { tMatrix4 m; m[0][0]=cos(r);m[0][1]=0;m[0][2]=-sin(r);m[0][3]=0; m[1][0]=0;m[1][1]=1;m[1][2]=0;m[1][3]=0; m[2][0]=sin(r);m[2][1]=0;m[2][2]=cos(r);m[2][3]=0; m[3][0]=0;m[3][1]=0;m[3][2]=0;m[3][3]=1; MatrixMult(target,m,target); } void MatrixRotZ(tMatrix3 target,float r) { tMatrix3 m; m[0][0]=cos(r);m[0][1]=sin(r);m[0][2]=0; m[1][0]=-sin(r);m[1][1]=cos(r);m[1][2]=0; m[2][0]=0;m[2][1]=0;m[2][2]=1; MatrixMult(target,m,target); } void MatrixRotZ(tMatrix4 target,float r) { tMatrix4 m; m[0][0]=cos(r);m[0][1]=sin(r);m[0][2]=0;m[0][3]=0; m[1][0]=-sin(r);m[1][1]=cos(r);m[1][2]=0;m[1][3]=0; m[2][0]=0;m[2][1]=0;m[2][2]=1;m[2][3]=0; m[3][0]=0;m[3][1]=0;m[3][2]=0;m[3][3]=1; MatrixMult(target,m,target); } //Transposes a matrix void MatrixTranspose(tMatrix3 x,tMatrix3 dst) { int i,j; for(i=0;i<3;i++) for(j=0;j<3;j++) dst[i][j]=x[j][i]; } void MatrixTranspose(tMatrix4 x,tMatrix4 dst) { int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) dst[i][j]=x[j][i]; } //Verifies if a matrix is a valid rotation matrix (Orthonormal base). int MatrixVerify(tMatrix3 m) { tVector3 *m0=(tVector3*)m[0]; float len=m0->x*m0->x+m0->y*m0->y+m0->z*m0->z; if(len>=1+kMatrixTolerance||len<=1-kMatrixTolerance)return false; tVector3 v=(*(tVector3*)m[1]%*(tVector3*)m[2])-*(tVector3*)m[0]; return(v.x*v.x+v.y*v.y+v.z*v.z<=kMatrixTolerance); } int MatrixVerify(tMatrix4 m) { tVector3 v=(*(tVector3*)m[1]%*(tVector3*)m[2])-*(tVector3*)m[0]; return(v.x*v.x+v.y*v.y+v.z*v.z<=kMatrixTolerance); } //Readjusts matrices to be a valid rotation matrix //needed as floating point calculations always carry small errors, so matrices //will drift apart more and more void MatrixReAdjust(tMatrix3 m) { *(tVector3*)m[2]=!*(tVector3*)m[2]; *(tVector3*)m[0]=!(*(tVector3*)m[1]%*(tVector3*)m[2]); *(tVector3*)m[1]=!(*(tVector3*)m[2]%*(tVector3*)m[0]); } void MatrixReAdjust(tMatrix4 m) { *(tVector3*)m[2]=!*(tVector3*)m[2]; *(tVector3*)m[0]=!(*(tVector3*)m[1]%*(tVector3*)m[2]); *(tVector3*)m[1]=!(*(tVector3*)m[2]%*(tVector3*)m[0]); } //converts a rotation vector to a rotation matrix. //a rotation vector defines a rotation by the length of a vector //around the axis given by the direction of a vector. void RotationVectorToMatrix(tVector3 axis,tMatrix4 mat) { float angle=~axis; if(!angle) { MatrixIdentity(mat); return; } else axis=axis/angle; tMatrix3 axist; int i,j; for(i=0;i<3;i++) for(j=0;j<3;j++) axist[i][j]=((float*)&axis)[i]*((float*)&axis)[j]; tMatrix3 m1,m2,s; s[0][0]=0; s[0][1]=-axis.z; s[0][2]=axis.y; s[1][0]=axis.z; s[1][1]=0; s[1][2]=-axis.x; s[2][0]=-axis.y;s[2][1]=axis.x; s[2][2]=0; MatrixIdentity(m1); MatrixSub(m1,axist,m1); MatrixMult(m1,cos(-angle),m1); MatrixAdd(m1,axist,m1); MatrixMult(s,sin(-angle),m2); MatrixAdd(m1,m2,m1); Matrix3ToMatrix4(m1,mat); } void RotationVectorToMatrix(tVector3 axis,tMatrix3 mat) { float angle=~axis; if(!angle) { MatrixIdentity(mat); return; } else axis=axis/angle; tMatrix3 axist; int i,j; for(i=0;i<3;i++) for(j=0;j<3;j++) axist[i][j]=((float*)&axis)[i]*((float*)&axis)[j]; tMatrix3 m1,m2,s; s[0][0]=0; s[0][1]=-axis.z; s[0][2]=axis.y; s[1][0]=axis.z; s[1][1]=0; s[1][2]=-axis.x; s[2][0]=-axis.y;s[2][1]=axis.x; s[2][2]=0; MatrixIdentity(m1); MatrixSub(m1,axist,m1); MatrixMult(m1,cos(-angle),m1); MatrixAdd(m1,axist,m1); MatrixMult(s,sin(-angle),m2); MatrixAdd(m1,m2,mat); } //tests if two vectors are equal int VectorEqual(tVector3 a,tVector3 b) { return(a.x==b.x&&a.y==b.y&&a.z==b.z); } int VectorEqual(tVector2 a,tVector2 b) { return(a.x==b.x&&a.y==b.y); } //tests if a vector is zero int VectorZero(tVector2 v) { return v.x==0&&v.y==0; } int VectorZero(tVector3 v) { return v.x==0&&v.y==0&&v.z==0; }