diff --git a/src/m_fixed.c b/src/m_fixed.c
index 70b7623da8d8ca14cf046e4279061c80a7ef6b25..ded294b0a6a0a933dc084e0c70543b98f004537e 100644
--- a/src/m_fixed.c
+++ b/src/m_fixed.c
@@ -276,6 +276,15 @@ vector3_t *FV3_Load(vector3_t *vec, fixed_t x, fixed_t y, fixed_t z)
 	return vec;
 }
 
+vector4_t *FV4_Load(vector4_t *vec, fixed_t x, fixed_t y, fixed_t z, fixed_t a)
+{
+	vec->x = x;
+	vec->y = y;
+	vec->z = z;
+	vec->a = a;
+	return vec;
+}
+
 vector3_t *FV3_UnLoad(vector3_t *vec, fixed_t *x, fixed_t *y, fixed_t *z)
 {
 	*x = vec->x;
@@ -284,11 +293,25 @@ vector3_t *FV3_UnLoad(vector3_t *vec, fixed_t *x, fixed_t *y, fixed_t *z)
 	return vec;
 }
 
+vector4_t *FV4_UnLoad(vector4_t *vec, fixed_t *x, fixed_t *y, fixed_t *z, fixed_t *a)
+{
+	*x = vec->x;
+	*y = vec->y;
+	*z = vec->z;
+	*a = vec->a;
+	return vec;
+}
+
 vector3_t *FV3_Copy(vector3_t *a_o, const vector3_t *a_i)
 {
 	return M_Memcpy(a_o, a_i, sizeof(vector3_t));
 }
 
+vector4_t *FV4_Copy(vector4_t *a_o, const vector4_t *a_i)
+{
+	return M_Memcpy(a_o, a_i, sizeof(vector4_t));
+}
+
 vector3_t *FV3_AddEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o)
 {
 	a_o->x = a_i->x + a_c->x;
@@ -297,11 +320,25 @@ vector3_t *FV3_AddEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o)
 	return a_o;
 }
 
+vector4_t *FV4_AddEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o)
+{
+	a_o->x = a_i->x + a_c->x;
+	a_o->y = a_i->y + a_c->y;
+	a_o->z = a_i->z + a_c->z;
+	a_o->a = a_i->a + a_c->a;
+	return a_o;
+}
+
 vector3_t *FV3_Add(vector3_t *a_i, const vector3_t *a_c)
 {
 	return FV3_AddEx(a_i, a_c, a_i);
 }
 
+vector4_t *FV4_Add(vector4_t *a_i, const vector4_t *a_c)
+{
+	return FV4_AddEx(a_i, a_c, a_i);
+}
+
 vector3_t *FV3_SubEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o)
 {
 	a_o->x = a_i->x - a_c->x;
@@ -310,11 +347,25 @@ vector3_t *FV3_SubEx(const vector3_t *a_i, const vector3_t *a_c, vector3_t *a_o)
 	return a_o;
 }
 
+vector4_t *FV4_SubEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o)
+{
+	a_o->x = a_i->x - a_c->x;
+	a_o->y = a_i->y - a_c->y;
+	a_o->z = a_i->z - a_c->z;
+	a_o->a = a_i->a - a_c->a;
+	return a_o;
+}
+
 vector3_t *FV3_Sub(vector3_t *a_i, const vector3_t *a_c)
 {
 	return FV3_SubEx(a_i, a_c, a_i);
 }
 
+vector4_t *FV4_Sub(vector4_t *a_i, const vector4_t *a_c)
+{
+	return FV4_SubEx(a_i, a_c, a_i);
+}
+
 vector3_t *FV3_MulEx(const vector3_t *a_i, fixed_t a_c, vector3_t *a_o)
 {
 	a_o->x = FixedMul(a_i->x, a_c);
@@ -323,11 +374,25 @@ vector3_t *FV3_MulEx(const vector3_t *a_i, fixed_t a_c, vector3_t *a_o)
 	return a_o;
 }
 
+vector4_t *FV4_MulEx(const vector4_t *a_i, fixed_t a_c, vector4_t *a_o)
+{
+	a_o->x = FixedMul(a_i->x, a_c);
+	a_o->y = FixedMul(a_i->y, a_c);
+	a_o->z = FixedMul(a_i->z, a_c);
+	a_o->a = FixedMul(a_i->a, a_c);
+	return a_o;
+}
+
 vector3_t *FV3_Mul(vector3_t *a_i, fixed_t a_c)
 {
 	return FV3_MulEx(a_i, a_c, a_i);
 }
 
+vector4_t *FV4_Mul(vector4_t *a_i, fixed_t a_c)
+{
+	return FV4_MulEx(a_i, a_c, a_i);
+}
+
 vector3_t *FV3_DivideEx(const vector3_t *a_i, fixed_t a_c, vector3_t *a_o)
 {
 	a_o->x = FixedDiv(a_i->x, a_c);
@@ -336,11 +401,25 @@ vector3_t *FV3_DivideEx(const vector3_t *a_i, fixed_t a_c, vector3_t *a_o)
 	return a_o;
 }
 
+vector4_t *FV4_DivideEx(const vector4_t *a_i, fixed_t a_c, vector4_t *a_o)
+{
+	a_o->x = FixedDiv(a_i->x, a_c);
+	a_o->y = FixedDiv(a_i->y, a_c);
+	a_o->z = FixedDiv(a_i->z, a_c);
+	a_o->a = FixedDiv(a_i->a, a_c);
+	return a_o;
+}
+
 vector3_t *FV3_Divide(vector3_t *a_i, fixed_t a_c)
 {
 	return FV3_DivideEx(a_i, a_c, a_i);
 }
 
+vector4_t *FV4_Divide(vector4_t *a_i, fixed_t a_c)
+{
+	return FV4_DivideEx(a_i, a_c, a_i);
+}
+
 // Vector Complex Math
 vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o)
 {
@@ -353,6 +432,19 @@ vector3_t *FV3_Midpoint(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a
 	return a_o;
 }
 
+vector4_t *FV4_Midpoint(const vector4_t *a_1, const vector4_t *a_2, vector4_t *a_o)
+{
+	a_o->x = FixedDiv(a_2->x - a_1->x, 2 * FRACUNIT);
+	a_o->y = FixedDiv(a_2->y - a_1->y, 2 * FRACUNIT);
+	a_o->z = FixedDiv(a_2->z - a_1->z, 2 * FRACUNIT);
+	a_o->a = FixedDiv(a_2->a - a_1->a, 2 * FRACUNIT);
+	a_o->x = a_1->x + a_o->x;
+	a_o->y = a_1->y + a_o->y;
+	a_o->z = a_1->z + a_o->z;
+	a_o->a = a_1->z + a_o->a;
+	return a_o;
+}
+
 fixed_t FV3_Distance(const vector3_t *p1, const vector3_t *p2)
 {
 	fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x);
@@ -361,6 +453,15 @@ fixed_t FV3_Distance(const vector3_t *p1, const vector3_t *p2)
 	return FixedSqrt(xs + ys + zs);
 }
 
+fixed_t FV4_Distance(const vector4_t *p1, const vector4_t *p2)
+{
+	fixed_t xs = FixedMul(p2->x - p1->x, p2->x - p1->x);
+	fixed_t ys = FixedMul(p2->y - p1->y, p2->y - p1->y);
+	fixed_t zs = FixedMul(p2->z - p1->z, p2->z - p1->z);
+	fixed_t za = FixedMul(p2->a - p1->a, p2->a - p1->a);
+	return FixedSqrt(xs + ys + zs + za);
+}
+
 fixed_t FV3_Magnitude(const vector3_t *a_normal)
 {
 	fixed_t xs = FixedMul(a_normal->x, a_normal->x);
@@ -369,6 +470,15 @@ fixed_t FV3_Magnitude(const vector3_t *a_normal)
 	return FixedSqrt(xs + ys + zs);
 }
 
+fixed_t FV4_Magnitude(const vector4_t *a_normal)
+{
+	fixed_t xs = FixedMul(a_normal->x, a_normal->x);
+	fixed_t ys = FixedMul(a_normal->y, a_normal->y);
+	fixed_t zs = FixedMul(a_normal->z, a_normal->z);
+	fixed_t as = FixedMul(a_normal->a, a_normal->a);
+	return FixedSqrt(xs + ys + zs + as);
+}
+
 // Also returns the magnitude
 fixed_t FV3_NormalizeEx(const vector3_t *a_normal, vector3_t *a_o)
 {
@@ -379,11 +489,26 @@ fixed_t FV3_NormalizeEx(const vector3_t *a_normal, vector3_t *a_o)
 	return magnitude;
 }
 
+fixed_t FV4_NormalizeEx(const vector4_t *a_normal, vector4_t *a_o)
+{
+	fixed_t magnitude = FV4_Magnitude(a_normal);
+	a_o->x = FixedDiv(a_normal->x, magnitude);
+	a_o->y = FixedDiv(a_normal->y, magnitude);
+	a_o->z = FixedDiv(a_normal->z, magnitude);
+	a_o->a = FixedDiv(a_normal->a, magnitude);
+	return magnitude;
+}
+
 fixed_t FV3_Normalize(vector3_t *a_normal)
 {
 	return FV3_NormalizeEx(a_normal, a_normal);
 }
 
+fixed_t FV4_Normalize(vector4_t *a_normal)
+{
+	return FV4_NormalizeEx(a_normal, a_normal);
+}
+
 vector3_t *FV3_NegateEx(const vector3_t *a_1, vector3_t *a_o)
 {
 	a_o->x = -a_1->x;
@@ -392,11 +517,25 @@ vector3_t *FV3_NegateEx(const vector3_t *a_1, vector3_t *a_o)
 	return a_o;
 }
 
+vector4_t *FV4_NegateEx(const vector4_t *a_1, vector4_t *a_o)
+{
+	a_o->x = -a_1->x;
+	a_o->y = -a_1->y;
+	a_o->z = -a_1->z;
+	a_o->a = -a_1->a;
+	return a_o;
+}
+
 vector3_t *FV3_Negate(vector3_t *a_1)
 {
 	return FV3_NegateEx(a_1, a_1);
 }
 
+vector4_t *FV4_Negate(vector4_t *a_1)
+{
+	return FV4_NegateEx(a_1, a_1);
+}
+
 boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2)
 {
 	fixed_t Epsilon = FRACUNIT / FRACUNIT;
@@ -411,11 +550,31 @@ boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2)
 	return false;
 }
 
+boolean FV4_Equal(const vector4_t *a_1, const vector4_t *a_2)
+{
+	fixed_t Epsilon = FRACUNIT / FRACUNIT;
+
+	if ((abs(a_2->x - a_1->x) > Epsilon) ||
+		(abs(a_2->y - a_1->y) > Epsilon) ||
+		(abs(a_2->z - a_1->z) > Epsilon) ||
+		(abs(a_2->a - a_1->a) > Epsilon))
+	{
+		return true;
+	}
+
+	return false;
+}
+
 fixed_t FV3_Dot(const vector3_t *a_1, const vector3_t *a_2)
 {
 	return (FixedMul(a_1->x, a_2->x) + FixedMul(a_1->y, a_2->y) + FixedMul(a_1->z, a_2->z));
 }
 
+fixed_t FV4_Dot(const vector4_t *a_1, const vector4_t *a_2)
+{
+	return (FixedMul(a_1->x, a_2->x) + FixedMul(a_1->y, a_2->y) + FixedMul(a_1->z, a_2->z) + FixedMul(a_1->a, a_2->a));
+}
+
 vector3_t *FV3_Cross(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o)
 {
 	a_o->x = FixedMul(a_1->y, a_2->z) - FixedMul(a_1->z, a_2->y);
@@ -432,7 +591,7 @@ vector3_t *FV3_Cross(const vector3_t *a_1, const vector3_t *a_2, vector3_t *a_o)
 //
 vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vector3_t *out)
 {
-	// Determine t (the length of the vector from �Line[0]� to �p�)
+	// Determine t (the length of the vector from "Line[0]" to "p")
 	vector3_t c, V;
 	fixed_t t, d = 0;
 	FV3_SubEx(p, &Line[0], &c);
@@ -442,7 +601,7 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec
 	d = FV3_Distance(&Line[0], &Line[1]);
 	t = FV3_Dot(&V, &c);
 
-	// Check to see if �t� is beyond the extents of the line segment
+	// Check to see if "t" is beyond the extents of the line segment
 	if (t < 0)
 	{
 		return FV3_Copy(out, &Line[0]);
@@ -452,7 +611,7 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec
 		return FV3_Copy(out, &Line[1]);
 	}
 
-	// Return the point between �Line[0]� and �Line[1]�
+	// Return the point between "Line[0]" and "Line[1]"
 	FV3_Mul(&V, t);
 
 	return FV3_AddEx(&Line[0], &V, out);
@@ -810,7 +969,7 @@ void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fi
 //
 // Multiplies a vector by the specified matrix
 //
-void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out)
+const vector3_t *FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out)
 {
 #define M(row,col)  matrix->m[col * 4 + row]
 	out->x = FixedMul(vec->x, M(0, 0))
@@ -828,6 +987,34 @@ void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *
 		+ FixedMul(vec->z, M(2, 2))
 		+ M(2, 3);
 #undef M
+	return out;
+}
+
+const vector4_t *FM_MultMatrixVec4(const matrix_t *matrix, const vector4_t *vec, vector4_t *out)
+{
+#define M(row,col)  matrix->m[col * 4 + row]
+	out->x = FixedMul(vec->x, M(0, 0))
+		+ FixedMul(vec->y, M(0, 1))
+		+ FixedMul(vec->z, M(0, 2))
+		+ FixedMul(vec->a, M(0, 3));
+
+	out->y = FixedMul(vec->x, M(1, 0))
+		+ FixedMul(vec->y, M(1, 1))
+		+ FixedMul(vec->z, M(1, 2))
+		+ FixedMul(vec->a, M(1, 3));
+
+	out->z = FixedMul(vec->x, M(2, 0))
+		+ FixedMul(vec->y, M(2, 1))
+		+ FixedMul(vec->z, M(2, 2))
+		+ FixedMul(vec->a, M(2, 3));
+
+
+	out->a = FixedMul(vec->x, M(3, 0))
+		+ FixedMul(vec->y, M(3, 1))
+		+ FixedMul(vec->z, M(3, 2))
+		+ FixedMul(vec->a, M(3, 3));
+#undef M
+	return out;
 }
 
 //
diff --git a/src/m_fixed.h b/src/m_fixed.h
index fe5efc5512e5bc23940056dc3056df04c771d10a..73e629f44e3cc69bb8ac1e7c268f0a2b5a585e5c 100644
--- a/src/m_fixed.h
+++ b/src/m_fixed.h
@@ -395,6 +395,32 @@ vector3_t *FV3_IntersectionPoint(const vector3_t *vNormal, const vector3_t *vLin
 UINT8 FV3_PointOnLineSide(const vector3_t *point, const vector3_t *line);
 boolean FV3_PointInsideBox(const vector3_t *point, const vector3_t *box);
 
+typedef struct
+{
+	fixed_t x, y, z, a;
+} vector4_t;
+
+vector4_t *FV4_Load(vector4_t *vec, fixed_t x, fixed_t y, fixed_t z, fixed_t a);
+vector4_t *FV4_UnLoad(vector4_t *vec, fixed_t *x, fixed_t *y, fixed_t *z, fixed_t *a);
+vector4_t *FV4_Copy(vector4_t *a_o, const vector4_t *a_i);
+vector4_t *FV4_AddEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o);
+vector4_t *FV4_Add(vector4_t *a_i, const vector4_t *a_c);
+vector4_t *FV4_SubEx(const vector4_t *a_i, const vector4_t *a_c, vector4_t *a_o);
+vector4_t *FV4_Sub(vector4_t *a_i, const vector4_t *a_c);
+vector4_t *FV4_MulEx(const vector4_t *a_i, fixed_t a_c, vector4_t *a_o);
+vector4_t *FV4_Mul(vector4_t *a_i, fixed_t a_c);
+vector4_t *FV4_DivideEx(const vector4_t *a_i, fixed_t a_c, vector4_t *a_o);
+vector4_t *FV4_Divide(vector4_t *a_i, fixed_t a_c);
+vector4_t *FV4_Midpoint(const vector4_t *a_1, const vector4_t *a_2, vector4_t *a_o);
+fixed_t FV4_Distance(const vector4_t *p1, const vector4_t *p2);
+fixed_t FV4_Magnitude(const vector4_t *a_normal);
+fixed_t FV4_NormalizeEx(const vector4_t *a_normal, vector4_t *a_o);
+fixed_t FV4_Normalize(vector4_t *a_normal);
+vector4_t *FV4_NegateEx(const vector4_t *a_1, vector4_t *a_o);
+vector4_t *FV4_Negate(vector4_t *a_1);
+boolean FV4_Equal(const vector4_t *a_1, const vector4_t *a_2);
+fixed_t FV4_Dot(const vector4_t *a_1, const vector4_t *a_2);
+
 typedef struct
 {
 	fixed_t m[16];
@@ -402,7 +428,8 @@ typedef struct
 
 void FM_LoadIdentity(matrix_t* matrix);
 void FM_CreateObjectMatrix(matrix_t *matrix, fixed_t x, fixed_t y, fixed_t z, fixed_t anglex, fixed_t angley, fixed_t anglez, fixed_t upx, fixed_t upy, fixed_t upz, fixed_t radius);
-void FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out);
+const vector3_t *FM_MultMatrixVec3(const matrix_t *matrix, const vector3_t *vec, vector3_t *out);
+const vector4_t *FM_MultMatrixVec4(const matrix_t *matrix, const vector4_t *vec, vector4_t *out);
 void FM_MultMatrix(matrix_t *dest, const matrix_t *multme);
 void FM_Translate(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z);
 void FM_Scale(matrix_t *dest, fixed_t x, fixed_t y, fixed_t z);
diff --git a/src/m_misc.c b/src/m_misc.c
index 6c346e5a1f17c49f85f792996849a7013f7665d8..bb5f2568728cf3f8db1d4677447d93e3692a39ba 100644
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -2164,63 +2164,6 @@ const char *GetRevisionString(void)
 	return rev;
 }
 
-// Vector/matrix math
-TVector *VectorMatrixMultiply(TVector v, TMatrix m)
-{
-	static TVector ret;
-
-	ret[0] = FixedMul(v[0],m[0][0]) + FixedMul(v[1],m[1][0]) + FixedMul(v[2],m[2][0]) + FixedMul(v[3],m[3][0]);
-	ret[1] = FixedMul(v[0],m[0][1]) + FixedMul(v[1],m[1][1]) + FixedMul(v[2],m[2][1]) + FixedMul(v[3],m[3][1]);
-	ret[2] = FixedMul(v[0],m[0][2]) + FixedMul(v[1],m[1][2]) + FixedMul(v[2],m[2][2]) + FixedMul(v[3],m[3][2]);
-	ret[3] = FixedMul(v[0],m[0][3]) + FixedMul(v[1],m[1][3]) + FixedMul(v[2],m[2][3]) + FixedMul(v[3],m[3][3]);
-
-	return &ret;
-}
-
-TMatrix *RotateXMatrix(angle_t rad)
-{
-	static TMatrix ret;
-	const angle_t fa = rad>>ANGLETOFINESHIFT;
-	const fixed_t cosrad = FINECOSINE(fa), sinrad = FINESINE(fa);
-
-	ret[0][0] = FRACUNIT; ret[0][1] =       0; ret[0][2] = 0;        ret[0][3] = 0;
-	ret[1][0] =        0; ret[1][1] =  cosrad; ret[1][2] = sinrad;   ret[1][3] = 0;
-	ret[2][0] =        0; ret[2][1] = -sinrad; ret[2][2] = cosrad;   ret[2][3] = 0;
-	ret[3][0] =        0; ret[3][1] =       0; ret[3][2] = 0;        ret[3][3] = FRACUNIT;
-
-	return &ret;
-}
-
-#if 0
-TMatrix *RotateYMatrix(angle_t rad)
-{
-	static TMatrix ret;
-	const angle_t fa = rad>>ANGLETOFINESHIFT;
-	const fixed_t cosrad = FINECOSINE(fa), sinrad = FINESINE(fa);
-
-	ret[0][0] = cosrad;   ret[0][1] =        0; ret[0][2] = -sinrad;   ret[0][3] = 0;
-	ret[1][0] = 0;        ret[1][1] = FRACUNIT; ret[1][2] = 0;         ret[1][3] = 0;
-	ret[2][0] = sinrad;   ret[2][1] =        0; ret[2][2] = cosrad;    ret[2][3] = 0;
-	ret[3][0] = 0;        ret[3][1] =        0; ret[3][2] = 0;         ret[3][3] = FRACUNIT;
-
-	return &ret;
-}
-#endif
-
-TMatrix *RotateZMatrix(angle_t rad)
-{
-	static TMatrix ret;
-	const angle_t fa = rad>>ANGLETOFINESHIFT;
-	const fixed_t cosrad = FINECOSINE(fa), sinrad = FINESINE(fa);
-
-	ret[0][0] = cosrad;    ret[0][1] = sinrad;   ret[0][2] =        0; ret[0][3] = 0;
-	ret[1][0] = -sinrad;   ret[1][1] = cosrad;   ret[1][2] =        0; ret[1][3] = 0;
-	ret[2][0] = 0;         ret[2][1] = 0;        ret[2][2] = FRACUNIT; ret[2][3] = 0;
-	ret[3][0] = 0;         ret[3][1] = 0;        ret[3][2] =        0; ret[3][3] = FRACUNIT;
-
-	return &ret;
-}
-
 /** Set of functions to take in a size_t as an argument,
   * put the argument in a character buffer, and return the
   * pointer to that buffer.
diff --git a/src/m_misc.h b/src/m_misc.h
index 5b79c6c8c4d55473053563f722504257fe3ea157..2959ba44ec4c80e60ca50c7389a3f03d4559a326 100644
--- a/src/m_misc.h
+++ b/src/m_misc.h
@@ -80,17 +80,6 @@ INT32 axtoi(const char *hexStg);
 
 const char *GetRevisionString(void);
 
-// Vector/matrix math
-typedef fixed_t TVector[4];
-typedef fixed_t TMatrix[4][4];
-
-TVector *VectorMatrixMultiply(TVector v, TMatrix m);
-TMatrix *RotateXMatrix(angle_t rad);
-#if 0
-TMatrix *RotateYMatrix(angle_t rad);
-#endif
-TMatrix *RotateZMatrix(angle_t rad);
-
 // s1 = s2+s3+s1 (1024 lenghtmax)
 void strcatbf(char *s1, const char *s2, const char *s3);
 
diff --git a/src/p_enemy.c b/src/p_enemy.c
index 4c36446af3826d65e83a5240b63d917d196fad8b..558b8a795fbdce896758d1fda49812691cc67f2b 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -1521,8 +1521,9 @@ void A_PointyThink(mobj_t *actor)
 	INT32 i;
 	player_t *player = NULL;
 	mobj_t *ball;
-	TVector v;
-	TVector *res;
+	matrix_t m;
+	vector4_t v;
+	vector4_t res;
 	angle_t fa;
 	fixed_t radius = FixedMul(actor->info->radius*actor->info->reactiontime, actor->scale);
 	boolean firsttime = true;
@@ -1592,20 +1593,21 @@ void A_PointyThink(mobj_t *actor)
 	while (ball)
 	{
 		fa = actor->lastlook+i;
-		v[0] = FixedMul(FINECOSINE(fa),radius);
-		v[1] = 0;
-		v[2] = FixedMul(FINESINE(fa),radius);
-		v[3] = FRACUNIT;
+		v.x = FixedMul(FINECOSINE(fa),radius);
+		v.y = 0;
+		v.z = FixedMul(FINESINE(fa),radius);
+		v.a = FRACUNIT;
 
-		res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(actor->lastlook+i)));
-		M_Memcpy(&v, res, sizeof (v));
-		res = VectorMatrixMultiply(v, *RotateZMatrix(actor->angle+ANGLE_180));
-		M_Memcpy(&v, res, sizeof (v));
+		FM_RotateX(&m, FixedAngle(actor->lastlook+i));
+		FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res));
+
+		FM_RotateZ(&m, actor->angle+ANGLE_180);
+		FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res));
 
 		P_UnsetThingPosition(ball);
-		ball->x = actor->x + v[0];
-		ball->y = actor->y + v[1];
-		ball->z = actor->z + (actor->height>>1) + v[2];
+		ball->x = actor->x + v.x;
+		ball->y = actor->y + v.y;
+		ball->z = actor->z + (actor->height>>1) + v.z;
 		P_SetThingPosition(ball);
 
 		ball = ball->tracer;
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 3cc3dc338e88a7165489b0008cb58a6245aaf4d0..2dbfac3bd0c5462b276e833f11d3dfe20eba99cc 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -6189,8 +6189,9 @@ static void P_MoveHoop(mobj_t *mobj)
 {
 	const fixed_t fuse = (mobj->fuse*mobj->extravalue2);
 	const angle_t fa = mobj->movedir*(FINEANGLES/mobj->extravalue1);
-	TVector v;
-	TVector *res;
+	matrix_t m;
+	vector4_t v;
+	vector4_t res;
 	fixed_t finalx, finaly, finalz;
 	fixed_t x, y, z;
 
@@ -6203,19 +6204,20 @@ static void P_MoveHoop(mobj_t *mobj)
 	z = mobj->target->z+mobj->target->height/2;
 
 	// Make the sprite travel towards the center of the hoop
-	v[0] = FixedMul(FINECOSINE(fa),fuse);
-	v[1] = 0;
-	v[2] = FixedMul(FINESINE(fa),fuse);
-	v[3] = FRACUNIT;
+	v.x = FixedMul(FINECOSINE(fa),fuse);
+	v.y = 0;
+	v.z = FixedMul(FINESINE(fa),fuse);
+	v.a = FRACUNIT;
 
-	res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(mobj->target->movedir*FRACUNIT)));
-	M_Memcpy(&v, res, sizeof (v));
-	res = VectorMatrixMultiply(v, *RotateZMatrix(FixedAngle(mobj->target->movecount*FRACUNIT)));
-	M_Memcpy(&v, res, sizeof (v));
+	FM_RotateX(&m, FixedAngle(mobj->target->movedir*FRACUNIT));
+	FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res));
 
-	finalx = x + v[0];
-	finaly = y + v[1];
-	finalz = z + v[2];
+	FM_RotateZ(&m, FixedAngle(mobj->target->movecount*FRACUNIT));
+	FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res));
+
+	finalx = x + v.x;
+	finaly = y + v.y;
+	finalz = z + v.z;
 
 	P_UnsetThingPosition(mobj);
 	mobj->x = finalx;
@@ -6228,8 +6230,9 @@ void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT
 {
 	mobj_t *mobj;
 	INT32 i;
-	TVector v;
-	TVector *res;
+	matrix_t m;
+	vector4_t v;
+	vector4_t res;
 	fixed_t finalx, finaly, finalz;
 	mobj_t hoopcenter;
 	mobj_t *axis;
@@ -6271,19 +6274,20 @@ void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT
 	for (i = 0; i < number; i++)
 	{
 		fa = (i*degrees);
-		v[0] = FixedMul(FINECOSINE(fa),radius);
-		v[1] = 0;
-		v[2] = FixedMul(FINESINE(fa),radius);
-		v[3] = FRACUNIT;
+		v.x = FixedMul(FINECOSINE(fa),radius);
+		v.y = 0;
+		v.z = FixedMul(FINESINE(fa),radius);
+		v.a = FRACUNIT;
+
+		FM_RotateX(&m, rotangle);
+		FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res));
 
-		res = VectorMatrixMultiply(v, *RotateXMatrix(rotangle));
-		M_Memcpy(&v, res, sizeof (v));
-		res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle));
-		M_Memcpy(&v, res, sizeof (v));
+		FM_RotateZ(&m, closestangle);
+		FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res));
 
-		finalx = x + v[0];
-		finaly = y + v[1];
-		finalz = z + v[2];
+		finalx = x + v.x;
+		finaly = y + v.y;
+		finalz = z + v.z;
 
 		mobj = P_SpawnMobj(finalx, finaly, finalz, type);
 		mobj->z -= mobj->height/2;
@@ -6294,8 +6298,9 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb
 {
 	mobj_t *mobj;
 	INT32 i;
-	TVector v;
-	TVector *res;
+	matrix_t m;
+	vector4_t v;
+	vector4_t res;
 	fixed_t finalx, finaly, finalz, dist;
 	angle_t degrees, fa, closestangle;
 	fixed_t mobjx, mobjy, mobjz;
@@ -6310,19 +6315,20 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb
 	for (i = 0; i < number; i++)
 	{
 		fa = (i*degrees);
-		v[0] = FixedMul(FINECOSINE(fa),radius);
-		v[1] = 0;
-		v[2] = FixedMul(FINESINE(fa),radius);
-		v[3] = FRACUNIT;
+		v.x = FixedMul(FINECOSINE(fa),radius);
+		v.y = 0;
+		v.z = FixedMul(FINESINE(fa),radius);
+		v.a = FRACUNIT;
+
+		FM_RotateX(&m, rotangle);
+		FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res));
 
-		res = VectorMatrixMultiply(v, *RotateXMatrix(rotangle));
-		M_Memcpy(&v, res, sizeof (v));
-		res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle));
-		M_Memcpy(&v, res, sizeof (v));
+		FM_RotateZ(&m, closestangle);
+		FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res));
 
-		finalx = x + v[0];
-		finaly = y + v[1];
-		finalz = z + v[2];
+		finalx = x + v.x;
+		finaly = y + v.y;
+		finalz = z + v.z;
 
 		mobj = P_SpawnMobj(finalx, finaly, finalz, type);
 
@@ -6489,9 +6495,10 @@ static void P_NightsItemChase(mobj_t *thing)
 //
 void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
 {
-	TVector unit_lengthways, unit_sideways, pos_lengthways, pos_sideways;
-	TVector *res;
-	fixed_t radius, dist, zstore;
+	matrix_t m;
+	vector4_t unit_lengthways, unit_sideways, pos_lengthways, pos_sideways;
+	vector4_t res;
+	fixed_t radius, dist = 0, zstore;
 	angle_t fa;
 	boolean dosound = false;
 	mobj_t *mobj = center->hnext, *hnext = NULL;
@@ -6502,8 +6509,9 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
 	INT32 rot;
 	INT32 prevrot;
 
-	dist = pos_sideways[0] = pos_sideways[1] = pos_sideways[2] = pos_sideways[3] = unit_sideways[3] =\
-	 pos_lengthways[0] = pos_lengthways[1] = pos_lengthways[2] = pos_lengthways[3] = 0;
+	FV4_Load(&pos_sideways, 0, 0, 0, 0);
+	FV4_Load(&unit_sideways, 0, 0, 0, 0);
+	FV4_Load(&pos_lengthways, 0, 0, 0, 0);
 
 	while (mobj)
 	{
@@ -6521,15 +6529,15 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
 			rot = (baserot + mobj->threshold) & FINEMASK;
 			prevrot = (baseprevrot + mobj->threshold) & FINEMASK;
 
-			pos_lengthways[0] = pos_lengthways[1] = pos_lengthways[2] = pos_lengthways[3] = 0;
+			FV4_Load(&pos_lengthways, 0, 0, 0, 0);
 
 			dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed);
 			dist = ((center->scale == FRACUNIT) ? dist : FixedMul(dist, center->scale));
 
 			fa = (FixedAngle(center->movefactor*FRACUNIT) >> ANGLETOFINESHIFT);
 			radius = FixedMul(dist, FINECOSINE(fa));
-			unit_lengthways[1] = -FixedMul(dist, FINESINE(fa));
-			unit_lengthways[3] = FRACUNIT;
+			unit_lengthways.y = -FixedMul(dist, FINESINE(fa));
+			unit_lengthways.a = FRACUNIT;
 
 			// Swinging Chain.
 			if (center->flags2 & MF2_STRONGBOX)
@@ -6542,8 +6550,8 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
 
 				fa = ((FixedAngle(swingmag) >> ANGLETOFINESHIFT) + mobj->friction) & FINEMASK;
 
-				unit_lengthways[0] = FixedMul(FINESINE(fa), -radius);
-				unit_lengthways[2] = FixedMul(FINECOSINE(fa), -radius);
+				unit_lengthways.x = FixedMul(FINESINE(fa), -radius);
+				unit_lengthways.z = FixedMul(FINECOSINE(fa), -radius);
 			}
 			// Rotating Chain.
 			else
@@ -6554,15 +6562,16 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
 				if (!(prevfa > (FINEMASK/2)) && (fa > (FINEMASK/2))) // completed a full swing
 					dosound = true;
 
-				unit_lengthways[0] = FixedMul(FINECOSINE(fa), radius);
-				unit_lengthways[2] = FixedMul(FINESINE(fa), radius);
+				unit_lengthways.x = FixedMul(FINECOSINE(fa), radius);
+				unit_lengthways.z = FixedMul(FINESINE(fa), radius);
 			}
 
 			// Calculate the angle matrixes for the link.
-			res = VectorMatrixMultiply(unit_lengthways, *RotateXMatrix(center->threshold << ANGLETOFINESHIFT));
-			M_Memcpy(&unit_lengthways, res, sizeof(unit_lengthways));
-			res = VectorMatrixMultiply(unit_lengthways, *RotateZMatrix(center->angle));
-			M_Memcpy(&unit_lengthways, res, sizeof(unit_lengthways));
+			FM_RotateX(&m, center->threshold << ANGLETOFINESHIFT);
+			FV4_Copy(&unit_lengthways, FM_MultMatrixVec4(&m, &unit_lengthways, &res));
+
+			FM_RotateZ(&m, center->angle);
+			FV4_Copy(&unit_lengthways, FM_MultMatrixVec4(&m, &unit_lengthways, &res));
 
 			lastthreshold = mobj->threshold;
 			lastfriction = mobj->friction;
@@ -6574,63 +6583,64 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
 			dosound = false;
 		}
 
-		if (pos_sideways[3] != mobj->movefactor)
+		if (pos_sideways.a != mobj->movefactor)
 		{
-			if (!unit_sideways[3])
+			if (!unit_sideways.a)
 			{
-				unit_sideways[1] = dist;
-				unit_sideways[0] = unit_sideways[2] = 0;
-				unit_sideways[3] = FRACUNIT;
+				unit_sideways.y = dist;
+				unit_sideways.x = unit_sideways.z = 0;
+				unit_sideways.a = FRACUNIT;
+
+				FM_RotateX(&m, center->threshold << ANGLETOFINESHIFT);
+				FV4_Copy(&unit_sideways, FM_MultMatrixVec4(&m, &unit_sideways, &res));
 
-				res = VectorMatrixMultiply(unit_sideways, *RotateXMatrix(center->threshold << ANGLETOFINESHIFT));
-				M_Memcpy(&unit_sideways, res, sizeof(unit_sideways));
-				res = VectorMatrixMultiply(unit_sideways, *RotateZMatrix(center->angle));
-				M_Memcpy(&unit_sideways, res, sizeof(unit_sideways));
+				FM_RotateZ(&m, center->angle);
+				FV4_Copy(&unit_sideways, FM_MultMatrixVec4(&m, &unit_sideways, &res));
 			}
 
-			if (pos_sideways[3] > mobj->movefactor)
+			if (pos_sideways.a > mobj->movefactor)
 			{
 				do
 				{
-					pos_sideways[0] -= unit_sideways[0];
-					pos_sideways[1] -= unit_sideways[1];
-					pos_sideways[2] -= unit_sideways[2];
+					pos_sideways.x -= unit_sideways.x;
+					pos_sideways.y -= unit_sideways.y;
+					pos_sideways.z -= unit_sideways.z;
 				}
-				while ((--pos_sideways[3]) != mobj->movefactor);
+				while ((--pos_sideways.a) != mobj->movefactor);
 			}
 			else
 			{
 				do
 				{
-					pos_sideways[0] += unit_sideways[0];
-					pos_sideways[1] += unit_sideways[1];
-					pos_sideways[2] += unit_sideways[2];
+					pos_sideways.x += unit_sideways.x;
+					pos_sideways.y += unit_sideways.y;
+					pos_sideways.z += unit_sideways.z;
 				}
-				while ((++pos_sideways[3]) != mobj->movefactor);
+				while ((++pos_sideways.a) != mobj->movefactor);
 			}
 		}
 
 		hnext = mobj->hnext; // just in case the mobj is removed
 
-		if (pos_lengthways[3] > mobj->movecount)
+		if (pos_lengthways.a > mobj->movecount)
 		{
 			do
 			{
-				pos_lengthways[0] -= unit_lengthways[0];
-				pos_lengthways[1] -= unit_lengthways[1];
-				pos_lengthways[2] -= unit_lengthways[2];
+				pos_lengthways.x -= unit_lengthways.x;
+				pos_lengthways.y -= unit_lengthways.y;
+				pos_lengthways.z -= unit_lengthways.z;
 			}
-			while ((--pos_lengthways[3]) != mobj->movecount);
+			while ((--pos_lengthways.a) != mobj->movecount);
 		}
-		else if (pos_lengthways[3] < mobj->movecount)
+		else if (pos_lengthways.a < mobj->movecount)
 		{
 			do
 			{
-				pos_lengthways[0] += unit_lengthways[0];
-				pos_lengthways[1] += unit_lengthways[1];
-				pos_lengthways[2] += unit_lengthways[2];
+				pos_lengthways.x += unit_lengthways.x;
+				pos_lengthways.y += unit_lengthways.y;
+				pos_lengthways.z += unit_lengthways.z;
 			}
-			while ((++pos_lengthways[3]) != mobj->movecount);
+			while ((++pos_lengthways.a) != mobj->movecount);
 		}
 
 		P_UnsetThingPosition(mobj);
@@ -6640,17 +6650,17 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
 		mobj->z = center->z;
 
 		// Add on the appropriate distances to the center's co-ordinates.
-		if (pos_lengthways[3])
+		if (pos_lengthways.a)
 		{
-			mobj->x += pos_lengthways[0];
-			mobj->y += pos_lengthways[1];
-			zstore = pos_lengthways[2] + pos_sideways[2];
+			mobj->x += pos_lengthways.x;
+			mobj->y += pos_lengthways.y;
+			zstore = pos_lengthways.z + pos_sideways.z;
 		}
 		else
-			zstore = pos_sideways[2];
+			zstore = pos_sideways.z;
 
-		mobj->x += pos_sideways[0];
-		mobj->y += pos_sideways[1];
+		mobj->x += pos_sideways.x;
+		mobj->y += pos_sideways.y;
 
 		// Cut the height to align the link with the axis.
 		if (mobj->type == MT_SMALLMACECHAIN || mobj->type == MT_BIGMACECHAIN || mobj->type == MT_SMALLGRABCHAIN || mobj->type == MT_BIGGRABCHAIN)
@@ -6668,7 +6678,7 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
 		P_SetThingPosition(mobj);
 
 #if 0 // toaster's height-clipping dealie!
-		if (!pos_lengthways[3] || P_MobjWasRemoved(mobj) || (mobj->flags & MF_NOCLIPHEIGHT))
+		if (!pos_lengthways.a || P_MobjWasRemoved(mobj) || (mobj->flags & MF_NOCLIPHEIGHT))
 			goto cont;
 
 		if ((fa = ((center->threshold & (FINEMASK/2)) << ANGLETOFINESHIFT)) > ANGLE_45 && fa < ANGLE_135) // only move towards center when the motion is towards/away from the ground, rather than alongside it
@@ -6688,8 +6698,8 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
 
 		P_UnsetThingPosition(mobj);
 
-		mobj->x -= FixedMul(unit_lengthways[0], zstore);
-		mobj->y -= FixedMul(unit_lengthways[1], zstore);
+		mobj->x -= FixedMul(unit_lengthways.x, zstore);
+		mobj->y -= FixedMul(unit_lengthways.y, zstore);
 
 		P_SetThingPosition(mobj);
 
@@ -13342,13 +13352,13 @@ void P_SpawnHoop(mapthing_t *mthing)
 	mobj_t *mobj = NULL;
 	mobj_t *nextmobj = NULL;
 	mobj_t *hoopcenter;
-	TMatrix *pitchmatrix, *yawmatrix;
+	matrix_t pitchmatrix, yawmatrix;
 	fixed_t radius = mthing->args[0] << FRACBITS;
 	fixed_t sizefactor = 4*FRACUNIT;
 	fixed_t hoopsize = radius/sizefactor;
 	INT32 i;
 	angle_t fa;
-	TVector v, *res;
+	vector4_t v, res;
 	fixed_t x = mthing->x << FRACBITS;
 	fixed_t y = mthing->y << FRACBITS;
 	fixed_t z = P_GetMobjSpawnHeight(MT_HOOP, x, y, mthing->z << FRACBITS, 0, false, mthing->scale);
@@ -13363,9 +13373,9 @@ void P_SpawnHoop(mapthing_t *mthing)
 	P_SetThingPosition(hoopcenter);
 
 	hoopcenter->movedir = mthing->pitch;
-	pitchmatrix = RotateXMatrix(FixedAngle(hoopcenter->movedir << FRACBITS));
+	FM_RotateX(&pitchmatrix, FixedAngle(hoopcenter->movedir << FRACBITS));
 	hoopcenter->movecount = mthing->angle;
-	yawmatrix = RotateZMatrix(FixedAngle(hoopcenter->movecount << FRACBITS));
+	FM_RotateZ(&yawmatrix, FixedAngle(hoopcenter->movecount << FRACBITS));
 
 	// For the hoop when it flies away
 	hoopcenter->extravalue1 = hoopsize;
@@ -13375,17 +13385,15 @@ void P_SpawnHoop(mapthing_t *mthing)
 	for (i = 0; i < hoopsize; i++)
 	{
 		fa = i*(FINEANGLES/hoopsize);
-		v[0] = FixedMul(FINECOSINE(fa), radius);
-		v[1] = 0;
-		v[2] = FixedMul(FINESINE(fa), radius);
-		v[3] = FRACUNIT;
+		v.x = FixedMul(FINECOSINE(fa), radius);
+		v.y = 0;
+		v.z = FixedMul(FINESINE(fa), radius);
+		v.a = FRACUNIT;
 
-		res = VectorMatrixMultiply(v, *pitchmatrix);
-		M_Memcpy(&v, res, sizeof(v));
-		res = VectorMatrixMultiply(v, *yawmatrix);
-		M_Memcpy(&v, res, sizeof(v));
+		FV4_Copy(&v, FM_MultMatrixVec4(&pitchmatrix, &v, &res));
+		FV4_Copy(&v, FM_MultMatrixVec4(&yawmatrix, &v, &res));
 
-		mobj = P_SpawnMobj(x + v[0], y + v[1], z + v[2], MT_HOOP);
+		mobj = P_SpawnMobj(x + v.x, y + v.y, z + v.z, MT_HOOP);
 		mobj->z -= mobj->height/2;
 
 		if (maptol & TOL_XMAS)
@@ -13421,17 +13429,15 @@ void P_SpawnHoop(mapthing_t *mthing)
 		for (i = 0; i < hoopsize; i++)
 		{
 			fa = i*(FINEANGLES/hoopsize);
-			v[0] = FixedMul(FINECOSINE(fa), radius);
-			v[1] = 0;
-			v[2] = FixedMul(FINESINE(fa), radius);
-			v[3] = FRACUNIT;
+			v.x = FixedMul(FINECOSINE(fa), radius);
+			v.y = 0;
+			v.z = FixedMul(FINESINE(fa), radius);
+			v.a = FRACUNIT;
 
-			res = VectorMatrixMultiply(v, *pitchmatrix);
-			M_Memcpy(&v, res, sizeof(v));
-			res = VectorMatrixMultiply(v, *yawmatrix);
-			M_Memcpy(&v, res, sizeof(v));
+			FV4_Copy(&v, FM_MultMatrixVec4(&pitchmatrix, &v, &res));
+			FV4_Copy(&v, FM_MultMatrixVec4(&yawmatrix, &v, &res));
 
-			mobj = P_SpawnMobj(x + v[0], y + v[1], z + v[2], MT_HOOPCOLLIDE);
+			mobj = P_SpawnMobj(x + v.x, y + v.y, z + v.z, MT_HOOPCOLLIDE);
 			mobj->z -= mobj->height/2;
 
 			// Link all the collision sprites together.
@@ -13522,7 +13528,8 @@ static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 n
 	angle_t angle = FixedAngle(mthing->angle << FRACBITS);
 	angle_t fa;
 	INT32 i;
-	TVector v, *res;
+	matrix_t m;
+	vector4_t v, res;
 
 	for (i = 0; i < numitemtypes; i++)
 	{
@@ -13550,15 +13557,15 @@ static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 n
 		dummything.type = mobjinfo[itemtype].doomednum;
 
 		fa = i*FINEANGLES/numitems;
-		v[0] = FixedMul(FINECOSINE(fa), size);
-		v[1] = 0;
-		v[2] = FixedMul(FINESINE(fa), size);
-		v[3] = FRACUNIT;
+		v.x = FixedMul(FINECOSINE(fa), size);
+		v.y = 0;
+		v.z = FixedMul(FINESINE(fa), size);
+		v.a = FRACUNIT;
 
-		res = VectorMatrixMultiply(v, *RotateZMatrix(angle));
-		M_Memcpy(&v, res, sizeof(v));
+		FM_RotateZ(&m, angle);
+		FV4_Copy(&v, FM_MultMatrixVec4(&m, &v, &res));
 
-		mobj = P_SpawnMobjFromMapThing(&dummything, x + v[0], y + v[1], z + v[2], itemtype);
+		mobj = P_SpawnMobjFromMapThing(&dummything, x + v.x, y + v.y, z + v.z, itemtype);
 
 		if (!mobj)
 			continue;
diff --git a/src/tables.c b/src/tables.c
index 13949b6a78c337a9183a7fd857c04135899acc7e..f8b8030c956bfef7f63f526a13e66e65b327e86e 100644
--- a/src/tables.c
+++ b/src/tables.c
@@ -407,9 +407,9 @@ void FV3_Rotate(vector3_t *rotVec, const vector3_t *axisVec, const angle_t angle
 	rotVec->z = az+dz+ez;
 }
 
-void FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z)
-{
 #define M(row,col) dest->m[row * 4 + col]
+matrix_t *FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z)
+{
 	const fixed_t sinA = FINESINE(angle>>ANGLETOFINESHIFT);
 	const fixed_t cosA = FINECOSINE(angle>>ANGLETOFINESHIFT);
 	const fixed_t invCosA = FRACUNIT - cosA;
@@ -459,5 +459,84 @@ void FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z)
 	M(1, 3) = 0;
 	M(2, 3) = 0;
 	M(3, 3) = FRACUNIT;
-#undef M
+
+	return dest;
+}
+
+
+matrix_t *FM_RotateX(matrix_t *dest, angle_t rad)
+{
+	const angle_t fa = rad>>ANGLETOFINESHIFT;
+	const fixed_t cosrad = FINECOSINE(fa), sinrad = FINESINE(fa);
+
+	M(0, 0) = FRACUNIT;
+	M(0, 1) = 0;
+	M(0, 2) = 0;
+	M(0, 3) = 0;
+	M(1, 0) = 0;
+	M(1, 1) = cosrad;
+	M(1, 2) = sinrad;
+	M(1, 3) = 0;
+	M(2, 0) = 0;
+	M(2, 1) = -sinrad;
+	M(2, 2) = cosrad;
+	M(2, 3) = 0;
+	M(3, 0) = 0;
+	M(3, 1) = 0;
+	M(3, 2) = 0;
+	M(3, 3) = FRACUNIT;
+
+	return dest;
+}
+
+matrix_t *FM_RotateY(matrix_t *dest, angle_t rad)
+{
+	const angle_t fa = rad>>ANGLETOFINESHIFT;
+	const fixed_t cosrad = FINECOSINE(fa), sinrad = FINESINE(fa);
+
+	M(0, 0) = cosrad;
+	M(0, 1) = 0;
+	M(0, 2) = -sinrad;
+	M(0, 3) = 0;
+	M(1, 0) = 0;
+	M(1, 1) = FRACUNIT;
+	M(1, 2) = 0;
+	M(1, 3) = 0;
+	M(2, 0) = sinrad;
+	M(2, 1) = 0;
+	M(2, 2) = cosrad;
+	M(2, 3) = 0;
+	M(3, 0) = 0;
+	M(3, 1) = 0;
+	M(3, 2) = 0;
+	M(3, 3) =  FRACUNIT;
+
+	return dest;
 }
+
+matrix_t *FM_RotateZ(matrix_t *dest, angle_t rad)
+{
+	const angle_t fa = rad>>ANGLETOFINESHIFT;
+	const fixed_t cosrad = FINECOSINE(fa), sinrad = FINESINE(fa);
+
+	M(0, 0) = cosrad;
+	M(0, 1) = sinrad;
+	M(0, 2) = 0;
+	M(0, 3) = 0;
+	M(1, 0) = -sinrad;
+	M(1, 1) = cosrad;
+	M(1, 2) = 0;
+	M(1, 3) = 0;
+	M(2, 0) = 0;
+	M(2, 1) = 0;
+	M(2, 2) = FRACUNIT;
+	M(2, 3) = 0;
+	M(3, 0) = 0;
+	M(3, 1) = 0;
+	M(3, 2) = 0;
+	M(3, 3) = FRACUNIT;
+
+	return dest;
+}
+
+#undef M
diff --git a/src/tables.h b/src/tables.h
index c44c7d525b5d205197843ad083bb84d1fc257a68..172ade3785672d28c95e2812d5d5f00cf06b4b4c 100644
--- a/src/tables.h
+++ b/src/tables.h
@@ -107,7 +107,10 @@ boolean FV3_InsidePolygon(const vector3_t *vIntersection, const vector3_t *Poly,
 boolean FV3_IntersectedPolygon(const vector3_t *vPoly, const vector3_t *vLine, const INT32 vertexCount, vector3_t *collisionPoint);
 void FV3_Rotate(vector3_t *rotVec, const vector3_t *axisVec, const angle_t angle);
 /// Fixed Point Matrix functions
-void FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z);
+matrix_t *FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z);
+matrix_t *FM_RotateX(matrix_t *dest, angle_t rad);
+matrix_t *FM_RotateY(matrix_t *dest, angle_t rad);
+matrix_t *FM_RotateZ(matrix_t *dest, angle_t rad);
 
 // The table values in tables.c are calculated with this many fractional bits.
 #define FINE_FRACBITS 16