typedef struct {
union {
struct { double x, y, z; };
struct { double a[3]; };
};
} Vector3;
typedef struct {
union {
struct { Vector3 xyz; };
struct { double x, y, z, w; };
struct { double a[4]; };
};
} Vector4;
typedef struct {
union {
struct { double m[4][4]; };
struct { double m00, m01, m02, m03,
m10, m11, m12, m13,
m20, m21, m22, m23,
m30, m31, m32, m33; };
struct { Vector4 ox, oy, oz, ow; };
struct { double a[16]; };
};
} Matrix;
void vector3Set(Vector3 *vector, double x, double y, double z)
{ vector->x = x; vector->y = y; vector->z = z; }
void vector3Copy(Vector3 *vector, const Vector3 *a)
{ vector3Set(vector, a->x, a->y, a->z); }
void vector3Zero(Vector3 *vector)
{ vector3Set(vector, 0, 0, 0); }
double vector3Dot(Vector3 *a, Vector3 *b)
{ return a->x*b->x + a->y*b->y + a->z*b->z; }
void vector4Set(Vector4 *vector, double x, double y, double z, double w)
{ vector->x = x; vector->y = y; vector->z = z; vector->w = w; }
void vector4Copy(Vector4 *vector, const Vector4 *a)
{ vector4Set(vector, a->x, a->y, a->z, a->w); }
void vector4Zero(Vector4 *vector)
{ vector4Set(vector, 0, 0, 0, 0); }
void vector4PespectiveDivide(Vector4 *vector, const Vector4 *a)
{ double k = 1/a->w; vector4Set(vector, a->x*k, a->y*k, a->z*k, 1); }
void vector4MultMatrix(Vector4 *vector, const Vector4 *a, const Matrix *b) {
vector4Set(vector, b->ox.x*a->x + b->oy.x*a->y + b->oz.x*a->z + b->ow.x*a->w,
b->ox.y*a->x + b->oy.y*a->y + b->oz.y*a->z + b->ow.y*a->w,
b->ox.z*a->x + b->oy.z*a->y + b->oz.z*a->z + b->ow.z*a->w,
b->ox.w*a->x + b->oy.w*a->y + b->oz.w*a->z + b->ow.w*a->w );
}
void matrixCopy(Matrix *matrix, const Matrix *a) {
vector4Copy(&matrix->ox, &a->ox);
vector4Copy(&matrix->oy, &a->oy);
vector4Copy(&matrix->oz, &a->oz);
vector4Copy(&matrix->ow, &a->ow);
}
void matrixMultMatrix(Matrix *matrix, const Matrix *a, const Matrix *b) {
if (matrix == a || matrix == b) {
Matrix m;
matrixMultMatrix(&m, a, b);
matrixCopy(matrix, &m);
return;
}
vector4MultMatrix(&matrix->ox, &a->ox, b);
vector4MultMatrix(&matrix->oy, &a->oy, b);
vector4MultMatrix(&matrix->oz, &a->oz, b);
vector4MultMatrix(&matrix->ow, &a->ow, b);
}
void matrixZero(Matrix *matrix) {
vector4Zero( &matrix->ox );
vector4Zero( &matrix->oy );
vector4Zero( &matrix->oz );
vector4Zero( &matrix->ow );
}
void matrixSetIdentity(Matrix *matrix) {
vector4Set( &matrix->ox, 1, 0, 0, 0 );
vector4Set( &matrix->oy, 0, 1, 0, 0 );
vector4Set( &matrix->oz, 0, 0, 1, 0 );
vector4Set( &matrix->ow, 0, 0, 0, 1 );
}
void matrixSetRotation(Matrix *matrix, double angle, double x, double y, double z) {
double s = sin(angle/180.0*PI);
double c = cos(angle/180.0*PI);
double cc = 1 - c, cx = x*cc, cy = y*cc, cz=z*cc;
vector4Set( &matrix->ox, x*cx + c , y*cx + z*s, z*cx - y*s, 0 );
vector4Set( &matrix->oy, x*cy - z*s, y*cy + c , z*cy + x*s, 0 );
vector4Set( &matrix->oz, x*cz + y*s, y*cz - x*s, z*cz + c , 0 );
vector4Set( &matrix->ow, 0 , 0 , 0 , 1 );
}
void matrixSetPerspective(Matrix *matrix, double fovy, double aspect, double zNear, double zFar) {
double f = 1/tan(0.5*fovy/180.0*PI);
double d = 1/(zNear - zFar);
vector4Set( &matrix->ox, f/aspect, 0, 0 , 0 );
vector4Set( &matrix->oy, 0 , f, 0 , 0 );
vector4Set( &matrix->oz, 0 , 0, (zNear + zFar)*d, -1 );
vector4Set( &matrix->ow, 0 , 0, 2*zNear*zFar*d , 0 );
}
void matrixInvert(Matrix *matrix, const Matrix *a) {
if (matrix == a) {
Matrix m;
matrixInvert(&m, a);
matrixCopy(matrix, &m);
return;
}
matrix->m00 = a->m11*(a->m22*a->m33 - a->m23*a->m32) + a->m12*(a->m23*a->m31 - a->m21*a->m33) + a->m13*(a->m21*a->m32 - a->m22*a->m31);
matrix->m10 = a->m10*(a->m23*a->m32 - a->m22*a->m33) + a->m12*(a->m20*a->m33 - a->m23*a->m30) + a->m13*(a->m22*a->m30 - a->m20*a->m32);
matrix->m20 = a->m10*(a->m21*a->m33 - a->m23*a->m31) + a->m11*(a->m23*a->m30 - a->m20*a->m33) + a->m13*(a->m20*a->m31 - a->m21*a->m30);
matrix->m30 = a->m10*(a->m22*a->m31 - a->m21*a->m32) + a->m11*(a->m20*a->m32 - a->m22*a->m30) + a->m12*(a->m21*a->m30 - a->m20*a->m31);
double det = a->m00*matrix->m00 + a->m01*matrix->m10 + a->m02*matrix->m20 + a->m03*matrix->m30;
if (fabs(det) <= 1e-10)
{ matrixZero(matrix); return; }
det = 1/det;
matrix->m00 *= det;
matrix->m10 *= det;
matrix->m20 *= det;
matrix->m30 *= det;
matrix->m01 = det*(a->m01*(a->m23*a->m32 - a->m22*a->m33) + a->m02*(a->m21*a->m33 - a->m23*a->m31) + a->m03*(a->m22*a->m31 - a->m21*a->m32));
matrix->m11 = det*(a->m00*(a->m22*a->m33 - a->m23*a->m32) + a->m02*(a->m23*a->m30 - a->m20*a->m33) + a->m03*(a->m20*a->m32 - a->m22*a->m30));
matrix->m21 = det*(a->m00*(a->m23*a->m31 - a->m21*a->m33) + a->m01*(a->m20*a->m33 - a->m23*a->m30) + a->m03*(a->m21*a->m30 - a->m20*a->m31));
matrix->m31 = det*(a->m00*(a->m21*a->m32 - a->m22*a->m31) + a->m01*(a->m22*a->m30 - a->m20*a->m32) + a->m02*(a->m20*a->m31 - a->m21*a->m30));
matrix->m02 = det*(a->m01*(a->m12*a->m33 - a->m13*a->m32) + a->m02*(a->m13*a->m31 - a->m11*a->m33) + a->m03*(a->m11*a->m32 - a->m12*a->m31));
matrix->m12 = det*(a->m00*(a->m13*a->m32 - a->m12*a->m33) + a->m02*(a->m10*a->m33 - a->m13*a->m30) + a->m03*(a->m12*a->m30 - a->m10*a->m32));
matrix->m22 = det*(a->m00*(a->m11*a->m33 - a->m13*a->m31) + a->m01*(a->m13*a->m30 - a->m10*a->m33) + a->m03*(a->m10*a->m31 - a->m11*a->m30));
matrix->m32 = det*(a->m00*(a->m12*a->m31 - a->m11*a->m32) + a->m01*(a->m10*a->m32 - a->m12*a->m30) + a->m02*(a->m11*a->m30 - a->m10*a->m31));
matrix->m03 = det*(a->m01*(a->m13*a->m22 - a->m12*a->m23) + a->m02*(a->m11*a->m23 - a->m13*a->m21) + a->m03*(a->m12*a->m21 - a->m11*a->m22));
matrix->m13 = det*(a->m00*(a->m12*a->m23 - a->m13*a->m22) + a->m02*(a->m13*a->m20 - a->m10*a->m23) + a->m03*(a->m10*a->m22 - a->m12*a->m20));
matrix->m23 = det*(a->m00*(a->m13*a->m21 - a->m11*a->m23) + a->m01*(a->m10*a->m23 - a->m13*a->m20) + a->m03*(a->m11*a->m20 - a->m10*a->m21));
matrix->m33 = det*(a->m00*(a->m11*a->m22 - a->m12*a->m21) + a->m01*(a->m12*a->m20 - a->m10*a->m22) + a->m02*(a->m10*a->m21 - a->m11*a->m20));
}