diff --git a/src/control/Replay.cpp b/src/control/Replay.cpp
index 2e87d1a7..2dd66333 100644
--- a/src/control/Replay.cpp
+++ b/src/control/Replay.cpp
@@ -305,7 +305,7 @@ void CReplay::RecordThisFrame(void)
 #endif
 	tGeneralPacket* general = (tGeneralPacket*)&Record.m_pBase[Record.m_nOffset];
 	general->type = REPLAYPACKET_GENERAL;
-	general->camera_pos.CopyOnlyMatrix(&TheCamera.GetMatrix());
+	general->camera_pos.CopyOnlyMatrix(TheCamera.GetMatrix());
 	general->player_pos = FindPlayerCoors();
 	general->in_rcvehicle = CWorld::Players[CWorld::PlayerInFocus].m_pRemoteVehicle ? true : false;
 	Record.m_nOffset += sizeof(*general);
diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp
index 7a831068..9d169716 100644
--- a/src/core/Camera.cpp
+++ b/src/core/Camera.cpp
@@ -3629,9 +3629,17 @@ CCamera::CalculateDerivedValues(void)
 bool
 CCamera::IsPointVisible(const CVector &center, const CMatrix *mat)
 {
-	RwV3d c;
-	c = center;
-	RwV3dTransformPoints(&c, &c, 1, &mat->m_matrix);
+#ifdef GTA_PS2
+	CVuVector c;
+	TransformPoint(c, *mat, center);
+#else
+	CVector c = center;
+	#ifdef FIX_BUGS
+		c = *mat * center;
+	#else
+		RwV3dTransformPoints(&c, &c, 1, (RwMatrix*)mat);
+	#endif
+#endif
 	if(c.y < CDraw::GetNearClipZ()) return false;
 	if(c.y > CDraw::GetFarClipZ()) return false;
 	if(c.x*m_vecFrustumNormals[0].x + c.y*m_vecFrustumNormals[0].y > 0.0f) return false;
@@ -3644,9 +3652,17 @@ CCamera::IsPointVisible(const CVector &center, const CMatrix *mat)
 bool
 CCamera::IsSphereVisible(const CVector &center, float radius, const CMatrix *mat)
 {
-	RwV3d c;
-	c = center;
-	RwV3dTransformPoints(&c, &c, 1, &mat->m_matrix);
+#ifdef GTA_PS2
+	CVuVector c;
+	TransformPoint(c, *mat, center);
+#else
+	CVector c = center;
+	#ifdef FIX_BUGS
+		c = *mat * center;
+	#else
+		RwV3dTransformPoints(&c, &c, 1, (RwMatrix*)mat);
+	#endif
+#endif
 	if(c.y + radius < CDraw::GetNearClipZ()) return false;
 	if(c.y - radius > CDraw::GetFarClipZ()) return false;
 	if(c.x*m_vecFrustumNormals[0].x + c.y*m_vecFrustumNormals[0].y > radius) return false;
@@ -3664,11 +3680,24 @@ CCamera::IsSphereVisible(const CVector &center, float radius)
 }
 
 bool
-CCamera::IsBoxVisible(RwV3d *box, const CMatrix *mat)
+#ifdef GTA_PS2
+CCamera::IsBoxVisible(CVuVector *box, const CMatrix *mat)
+#else
+CCamera::IsBoxVisible(CVector *box, const CMatrix *mat)
+#endif
 {
 	int i;
 	int frustumTests[6] = { 0 };
-	RwV3dTransformPoints(box, box, 8, &mat->m_matrix);
+#ifdef GTA_PS2
+	TransformPoints(box, 8, *mat, box);
+#else
+	#ifdef FIX_BUGS
+		for (i = 0; i < 8; i++)
+			box[i] = *mat * box[i];
+	#else
+		RwV3dTransformPoints(box, box, 8, (RwMatrix*)mat);
+	#endif
+#endif
 
 	for(i = 0; i < 8; i++){
 		if(box[i].y < CDraw::GetNearClipZ()) frustumTests[0]++;
diff --git a/src/core/Camera.h b/src/core/Camera.h
index ca1bd135..d7293e20 100644
--- a/src/core/Camera.h
+++ b/src/core/Camera.h
@@ -641,7 +641,11 @@ public:
 	bool IsPointVisible(const CVector &center, const CMatrix *mat);
 	bool IsSphereVisible(const CVector &center, float radius, const CMatrix *mat);
 	bool IsSphereVisible(const CVector &center, float radius);
-	bool IsBoxVisible(RwV3d *box, const CMatrix *mat);
+#ifdef GTA_PS2
+	bool IsBoxVisible(CVuVector *box, const CMatrix *mat);
+#else
+	bool IsBoxVisible(CVector *box, const CMatrix *mat);
+#endif
 };
 
 VALIDATE_SIZE(CCamera, 0xE9D8);
diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp
index 709f91c1..4885d631 100644
--- a/src/entities/Entity.cpp
+++ b/src/entities/Entity.cpp
@@ -407,7 +407,11 @@ CEntity::GetIsOnScreen(void)
 bool
 CEntity::GetIsOnScreenComplex(void)
 {
-	RwV3d boundBox[8];
+#ifdef GTA_PS2
+	CVuVector boundBox[8];
+#else
+	CVector boundBox[8];
+#endif
 
 	if(TheCamera.IsPointVisible(GetBoundCentre(), &TheCamera.GetCameraMatrix()))
 		return true;
diff --git a/src/math/Matrix.cpp b/src/math/Matrix.cpp
index a8b1b182..b11e8a1c 100644
--- a/src/math/Matrix.cpp
+++ b/src/math/Matrix.cpp
@@ -60,14 +60,20 @@ CMatrix::Detach(void)
 void
 CMatrix::Update(void)
 {
-	m_matrix = *m_attachment;
+	GetRight() = m_attachment->right;
+	GetForward() = m_attachment->up;
+	GetUp() = m_attachment->at;
+	GetPosition() = m_attachment->pos;
 }
 
 void
 CMatrix::UpdateRW(void)
 {
 	if (m_attachment) {
-		*m_attachment = m_matrix;
+		m_attachment->right = GetRight();
+		m_attachment->up = GetForward();
+		m_attachment->at = GetUp();
+		m_attachment->pos = GetPosition();
 		RwMatrixUpdate(m_attachment);
 	}
 }
@@ -75,104 +81,96 @@ CMatrix::UpdateRW(void)
 void
 CMatrix::operator=(CMatrix const &rhs)
 {
-	m_matrix = rhs.m_matrix;
+	memcpy(this, &rhs, sizeof(f));
 	if (m_attachment)
 		UpdateRW();
 }
 
 void
-CMatrix::CopyOnlyMatrix(CMatrix *other)
+CMatrix::CopyOnlyMatrix(const CMatrix &other)
 {
-	m_matrix = other->m_matrix;
+	memcpy(this, &other, sizeof(f));
 }
 
 CMatrix &
 CMatrix::operator+=(CMatrix const &rhs)
 {
-	m_matrix.right.x += rhs.m_matrix.right.x;
-	m_matrix.up.x += rhs.m_matrix.up.x;
-	m_matrix.at.x += rhs.m_matrix.at.x;
-	m_matrix.right.y += rhs.m_matrix.right.y;
-	m_matrix.up.y += rhs.m_matrix.up.y;
-	m_matrix.at.y += rhs.m_matrix.at.y;
-	m_matrix.right.z += rhs.m_matrix.right.z;
-	m_matrix.up.z += rhs.m_matrix.up.z;
-	m_matrix.at.z += rhs.m_matrix.at.z;
-	m_matrix.pos.x += rhs.m_matrix.pos.x;
-	m_matrix.pos.y += rhs.m_matrix.pos.y;
-	m_matrix.pos.z += rhs.m_matrix.pos.z;
+	GetRight() += rhs.GetRight();
+	GetForward() += rhs.GetForward();
+	GetUp() += rhs.GetUp();
+	GetPosition() += rhs.GetPosition();
 	return *this;
 }
 
 void
 CMatrix::SetUnity(void)
 {
-	m_matrix.right.x = 1.0f;
-	m_matrix.right.y = 0.0f;
-	m_matrix.right.z = 0.0f;
-	m_matrix.up.x = 0.0f;
-	m_matrix.up.y = 1.0f;
-	m_matrix.up.z = 0.0f;
-	m_matrix.at.x = 0.0f;
-	m_matrix.at.y = 0.0f;
-	m_matrix.at.z = 1.0f;
-	m_matrix.pos.x = 0.0f;
-	m_matrix.pos.y = 0.0f;
-	m_matrix.pos.z = 0.0f;
+	rx = 1.0f;
+	ry = 0.0f;
+	rz = 0.0f;
+	fx = 0.0f;
+	fy = 1.0f;
+	fz = 0.0f;
+	ux = 0.0f;
+	uy = 0.0f;
+	uz = 1.0f;
+	px = 0.0f;
+	py = 0.0f;
+	pz = 0.0f;
 }
 
 void
 CMatrix::ResetOrientation(void)
 {
-	m_matrix.right.x = 1.0f;
-	m_matrix.right.y = 0.0f;
-	m_matrix.right.z = 0.0f;
-	m_matrix.up.x = 0.0f;
-	m_matrix.up.y = 1.0f;
-	m_matrix.up.z = 0.0f;
-	m_matrix.at.x = 0.0f;
-	m_matrix.at.y = 0.0f;
-	m_matrix.at.z = 1.0f;
+	rx = 1.0f;
+	ry = 0.0f;
+	rz = 0.0f;
+	fx = 0.0f;
+	fy = 1.0f;
+	fz = 0.0f;
+	ux = 0.0f;
+	uy = 0.0f;
+	uz = 1.0f;
 }
 
 void
 CMatrix::SetScale(float s)
 {
-	m_matrix.right.x = s;
-	m_matrix.right.y = 0.0f;
-	m_matrix.right.z = 0.0f;
+	rx = s;
+	ry = 0.0f;
+	rz = 0.0f;
 
-	m_matrix.up.x = 0.0f;
-	m_matrix.up.y = s;
-	m_matrix.up.z = 0.0f;
+	fx = 0.0f;
+	fy = s;
+	fz = 0.0f;
 
-	m_matrix.at.x = 0.0f;
-	m_matrix.at.y = 0.0f;
-	m_matrix.at.z = s;
+	ux = 0.0f;
+	uy = 0.0f;
+	uz = s;
 
-	m_matrix.pos.x = 0.0f;
-	m_matrix.pos.y = 0.0f;
-	m_matrix.pos.z = 0.0f;
+	px = 0.0f;
+	py = 0.0f;
+	pz = 0.0f;
 }
 
 void
 CMatrix::SetTranslate(float x, float y, float z)
 {
-	m_matrix.right.x = 1.0f;
-	m_matrix.right.y = 0.0f;
-	m_matrix.right.z = 0.0f;
+	rx = 1.0f;
+	ry = 0.0f;
+	rz = 0.0f;
 
-	m_matrix.up.x = 0.0f;
-	m_matrix.up.y = 1.0f;
-	m_matrix.up.z = 0.0f;
+	fx = 0.0f;
+	fy = 1.0f;
+	fz = 0.0f;
 
-	m_matrix.at.x = 0.0f;
-	m_matrix.at.y = 0.0f;
-	m_matrix.at.z = 1.0f;
+	ux = 0.0f;
+	uy = 0.0f;
+	uz = 1.0f;
 
-	m_matrix.pos.x = x;
-	m_matrix.pos.y = y;
-	m_matrix.pos.z = z;
+	px = x;
+	py = y;
+	pz = z;
 }
 
 void
@@ -181,17 +179,17 @@ CMatrix::SetRotateXOnly(float angle)
 	float c = Cos(angle);
 	float s = Sin(angle);
 
-	m_matrix.right.x = 1.0f;
-	m_matrix.right.y = 0.0f;
-	m_matrix.right.z = 0.0f;
+	rx = 1.0f;
+	ry = 0.0f;
+	rz = 0.0f;
 
-	m_matrix.up.x = 0.0f;
-	m_matrix.up.y = c;
-	m_matrix.up.z = s;
+	fx = 0.0f;
+	fy = c;
+	fz = s;
 
-	m_matrix.at.x = 0.0f;
-	m_matrix.at.y = -s;
-	m_matrix.at.z = c;
+	ux = 0.0f;
+	uy = -s;
+	uz = c;
 }
 
 void
@@ -200,17 +198,17 @@ CMatrix::SetRotateYOnly(float angle)
 	float c = Cos(angle);
 	float s = Sin(angle);
 
-	m_matrix.right.x = c;
-	m_matrix.right.y = 0.0f;
-	m_matrix.right.z = -s;
+	rx = c;
+	ry = 0.0f;
+	rz = -s;
 
-	m_matrix.up.x = 0.0f;
-	m_matrix.up.y = 1.0f;
-	m_matrix.up.z = 0.0f;
+	fx = 0.0f;
+	fy = 1.0f;
+	fz = 0.0f;
 
-	m_matrix.at.x = s;
-	m_matrix.at.y = 0.0f;
-	m_matrix.at.z = c;
+	ux = s;
+	uy = 0.0f;
+	uz = c;
 }
 
 void
@@ -219,26 +217,26 @@ CMatrix::SetRotateZOnly(float angle)
 	float c = Cos(angle);
 	float s = Sin(angle);
 
-	m_matrix.right.x = c;
-	m_matrix.right.y = s;
-	m_matrix.right.z = 0.0f;
+	rx = c;
+	ry = s;
+	rz = 0.0f;
 
-	m_matrix.up.x = -s;
-	m_matrix.up.y = c;
-	m_matrix.up.z = 0.0f;
+	fx = -s;
+	fy = c;
+	fz = 0.0f;
 
-	m_matrix.at.x = 0.0f;
-	m_matrix.at.y = 0.0f;
-	m_matrix.at.z = 1.0f;
+	ux = 0.0f;
+	uy = 0.0f;
+	uz = 1.0f;
 }
 
 void
 CMatrix::SetRotateX(float angle)
 {
 	SetRotateXOnly(angle);
-	m_matrix.pos.x = 0.0f;
-	m_matrix.pos.y = 0.0f;
-	m_matrix.pos.z = 0.0f;
+	px = 0.0f;
+	py = 0.0f;
+	pz = 0.0f;
 }
 
 
@@ -246,18 +244,18 @@ void
 CMatrix::SetRotateY(float angle)
 {
 	SetRotateYOnly(angle);
-	m_matrix.pos.x = 0.0f;
-	m_matrix.pos.y = 0.0f;
-	m_matrix.pos.z = 0.0f;
+	px = 0.0f;
+	py = 0.0f;
+	pz = 0.0f;
 }
 
 void
 CMatrix::SetRotateZ(float angle)
 {
 	SetRotateZOnly(angle);
-	m_matrix.pos.x = 0.0f;
-	m_matrix.pos.y = 0.0f;
-	m_matrix.pos.z = 0.0f;
+	px = 0.0f;
+	py = 0.0f;
+	pz = 0.0f;
 }
 
 void
@@ -270,21 +268,21 @@ CMatrix::SetRotate(float xAngle, float yAngle, float zAngle)
 	float cZ = Cos(zAngle);
 	float sZ = Sin(zAngle);
 
-	m_matrix.right.x = cZ * cY - (sZ * sX) * sY;
-	m_matrix.right.y = (cZ * sX) * sY + sZ * cY;
-	m_matrix.right.z = -cX * sY;
+	rx = cZ * cY - (sZ * sX) * sY;
+	ry = (cZ * sX) * sY + sZ * cY;
+	rz = -cX * sY;
 
-	m_matrix.up.x = -sZ * cX;
-	m_matrix.up.y = cZ * cX;
-	m_matrix.up.z = sX;
+	fx = -sZ * cX;
+	fy = cZ * cX;
+	fz = sX;
 
-	m_matrix.at.x = (sZ * sX) * cY + cZ * sY;
-	m_matrix.at.y = sZ * sY - (cZ * sX) * cY;
-	m_matrix.at.z = cX * cY;
+	ux = (sZ * sX) * cY + cZ * sY;
+	uy = sZ * sY - (cZ * sX) * cY;
+	uz = cX * cY;
 
-	m_matrix.pos.x = 0.0f;
-	m_matrix.pos.y = 0.0f;
-	m_matrix.pos.z = 0.0f;
+	px = 0.0f;
+	py = 0.0f;
+	pz = 0.0f;
 }
 
 void
@@ -293,23 +291,23 @@ CMatrix::RotateX(float x)
 	float c = Cos(x);
 	float s = Sin(x);
 
-	float ry = m_matrix.right.y;
-	float rz = m_matrix.right.z;
-	float uy = m_matrix.up.y;
-	float uz = m_matrix.up.z;
-	float ay = m_matrix.at.y;
-	float az = m_matrix.at.z;
-	float py = m_matrix.pos.y;
-	float pz = m_matrix.pos.z;
+	float ry = this->ry;
+	float rz = this->rz;
+	float uy = this->fy;
+	float uz = this->fz;
+	float ay = this->uy;
+	float az = this->uz;
+	float py = this->py;
+	float pz = this->pz;
 
-	m_matrix.right.y = c * ry - s * rz;
-	m_matrix.right.z = c * rz + s * ry;
-	m_matrix.up.y = c * uy - s * uz;
-	m_matrix.up.z = c * uz + s * uy;
-	m_matrix.at.y = c * ay - s * az;
-	m_matrix.at.z = c * az + s * ay;
-	m_matrix.pos.y = c * py - s * pz;
-	m_matrix.pos.z = c * pz + s * py;
+	this->ry = c * ry - s * rz;
+	this->rz = c * rz + s * ry;
+	this->fy = c * uy - s * uz;
+	this->fz = c * uz + s * uy;
+	this->uy = c * ay - s * az;
+	this->uz = c * az + s * ay;
+	this->py = c * py - s * pz;
+	this->pz = c * pz + s * py;
 }
 
 void
@@ -318,23 +316,23 @@ CMatrix::RotateY(float y)
 	float c = Cos(y);
 	float s = Sin(y);
 
-	float rx = m_matrix.right.x;
-	float rz = m_matrix.right.z;
-	float ux = m_matrix.up.x;
-	float uz = m_matrix.up.z;
-	float ax = m_matrix.at.x;
-	float az = m_matrix.at.z;
-	float px = m_matrix.pos.x;
-	float pz = m_matrix.pos.z;
+	float rx = this->rx;
+	float rz = this->rz;
+	float ux = this->fx;
+	float uz = this->fz;
+	float ax = this->ux;
+	float az = this->uz;
+	float px = this->px;
+	float pz = this->pz;
 
-	m_matrix.right.x = c * rx + s * rz;
-	m_matrix.right.z = c * rz - s * rx;
-	m_matrix.up.x = c * ux + s * uz;
-	m_matrix.up.z = c * uz - s * ux;
-	m_matrix.at.x = c * ax + s * az;
-	m_matrix.at.z = c * az - s * ax;
-	m_matrix.pos.x = c * px + s * pz;
-	m_matrix.pos.z = c * pz - s * px;
+	this->rx = c * rx + s * rz;
+	this->rz = c * rz - s * rx;
+	this->fx = c * ux + s * uz;
+	this->fz = c * uz - s * ux;
+	this->ux = c * ax + s * az;
+	this->uz = c * az - s * ax;
+	this->px = c * px + s * pz;
+	this->pz = c * pz - s * px;
 }
 
 void
@@ -343,23 +341,23 @@ CMatrix::RotateZ(float z)
 	float c = Cos(z);
 	float s = Sin(z);
 
-	float ry = m_matrix.right.y;
-	float rx = m_matrix.right.x;
-	float uy = m_matrix.up.y;
-	float ux = m_matrix.up.x;
-	float ay = m_matrix.at.y;
-	float ax = m_matrix.at.x;
-	float py = m_matrix.pos.y;
-	float px = m_matrix.pos.x;
+	float ry = this->ry;
+	float rx = this->rx;
+	float uy = this->fy;
+	float ux = this->fx;
+	float ay = this->uy;
+	float ax = this->ux;
+	float py = this->py;
+	float px = this->px;
 
-	m_matrix.right.x = c * rx - s * ry;
-	m_matrix.right.y = c * ry + s * rx;
-	m_matrix.up.x = c * ux - s * uy;
-	m_matrix.up.y = c * uy + s * ux;
-	m_matrix.at.x = c * ax - s * ay;
-	m_matrix.at.y = c * ay + s * ax;
-	m_matrix.pos.x = c * px - s * py;
-	m_matrix.pos.y = c * py + s * px;
+	this->rx = c * rx - s * ry;
+	this->ry = c * ry + s * rx;
+	this->fx = c * ux - s * uy;
+	this->fy = c * uy + s * ux;
+	this->ux = c * ax - s * ay;
+	this->uy = c * ay + s * ax;
+	this->px = c * px - s * py;
+	this->py = c * py + s * px;
 
 }
 
@@ -373,18 +371,18 @@ CMatrix::Rotate(float x, float y, float z)
 	float cZ = Cos(z);
 	float sZ = Sin(z);
 	
-	float rx = m_matrix.right.x;
-	float ry = m_matrix.right.y;
-	float rz = m_matrix.right.z;
-	float ux = m_matrix.up.x;
-	float uy = m_matrix.up.y;
-	float uz = m_matrix.up.z;
-	float ax = m_matrix.at.x;
-	float ay = m_matrix.at.y;
-	float az = m_matrix.at.z;
-	float px = m_matrix.pos.x;
-	float py = m_matrix.pos.y;
-	float pz = m_matrix.pos.z;
+	float rx = this->rx;
+	float ry = this->ry;
+	float rz = this->rz;
+	float ux = this->fx;
+	float uy = this->fy;
+	float uz = this->fz;
+	float ax = this->ux;
+	float ay = this->uy;
+	float az = this->uz;
+	float px = this->px;
+	float py = this->py;
+	float pz = this->pz;
 
 	float x1 = cZ * cY - (sZ * sX) * sY;
 	float x2 = (cZ * sX) * sY + sZ * cY;
@@ -396,18 +394,18 @@ CMatrix::Rotate(float x, float y, float z)
 	float z2 = sZ * sY - (cZ * sX) * cY;
 	float z3 = cX * cY;
 
-	m_matrix.right.x = x1 * rx + y1 * ry + z1 * rz;
-	m_matrix.right.y = x2 * rx + y2 * ry + z2 * rz;
-	m_matrix.right.z = x3 * rx + y3 * ry + z3 * rz;
-	m_matrix.up.x = x1 * ux + y1 * uy + z1 * uz;
-	m_matrix.up.y = x2 * ux + y2 * uy + z2 * uz;
-	m_matrix.up.z = x3 * ux + y3 * uy + z3 * uz;
-	m_matrix.at.x = x1 * ax + y1 * ay + z1 * az;
-	m_matrix.at.y = x2 * ax + y2 * ay + z2 * az;
-	m_matrix.at.z = x3 * ax + y3 * ay + z3 * az;
-	m_matrix.pos.x = x1 * px + y1 * py + z1 * pz;
-	m_matrix.pos.y = x2 * px + y2 * py + z2 * pz;
-	m_matrix.pos.z = x3 * px + y3 * py + z3 * pz;
+	this->rx = x1 * rx + y1 * ry + z1 * rz;
+	this->ry = x2 * rx + y2 * ry + z2 * rz;
+	this->rz = x3 * rx + y3 * ry + z3 * rz;
+	this->fx = x1 * ux + y1 * uy + z1 * uz;
+	this->fy = x2 * ux + y2 * uy + z2 * uz;
+	this->fz = x3 * ux + y3 * uy + z3 * uz;
+	this->ux = x1 * ax + y1 * ay + z1 * az;
+	this->uy = x2 * ax + y2 * ay + z2 * az;
+	this->uz = x3 * ax + y3 * ay + z3 * az;
+	this->px = x1 * px + y1 * py + z1 * pz;
+	this->py = x2 * px + y2 * py + z2 * pz;
+	this->pz = x3 * px + y3 * py + z3 * pz;
 }
 
 CMatrix &
@@ -436,21 +434,18 @@ operator*(const CMatrix &m1, const CMatrix &m2)
 {
 	// TODO: VU0 code
 	CMatrix out;
-	RwMatrix *dst = &out.m_matrix;
-	const RwMatrix *src1 = &m1.m_matrix;
-	const RwMatrix *src2 = &m2.m_matrix;
-	dst->right.x = src1->right.x * src2->right.x + src1->up.x * src2->right.y + src1->at.x * src2->right.z;
-	dst->right.y = src1->right.y * src2->right.x + src1->up.y * src2->right.y + src1->at.y * src2->right.z;
-	dst->right.z = src1->right.z * src2->right.x + src1->up.z * src2->right.y + src1->at.z * src2->right.z;
-	dst->up.x = src1->right.x * src2->up.x + src1->up.x * src2->up.y + src1->at.x * src2->up.z;
-	dst->up.y = src1->right.y * src2->up.x + src1->up.y * src2->up.y + src1->at.y * src2->up.z;
-	dst->up.z = src1->right.z * src2->up.x + src1->up.z * src2->up.y + src1->at.z * src2->up.z;
-	dst->at.x = src1->right.x * src2->at.x + src1->up.x * src2->at.y + src1->at.x * src2->at.z;
-	dst->at.y = src1->right.y * src2->at.x + src1->up.y * src2->at.y + src1->at.y * src2->at.z;
-	dst->at.z = src1->right.z * src2->at.x + src1->up.z * src2->at.y + src1->at.z * src2->at.z;
-	dst->pos.x = src1->right.x * src2->pos.x + src1->up.x * src2->pos.y + src1->at.x * src2->pos.z + src1->pos.x;
-	dst->pos.y = src1->right.y * src2->pos.x + src1->up.y * src2->pos.y + src1->at.y * src2->pos.z + src1->pos.y;
-	dst->pos.z = src1->right.z * src2->pos.x + src1->up.z * src2->pos.y + src1->at.z * src2->pos.z + src1->pos.z;
+	out.rx = m1.rx * m2.rx + m1.fx * m2.ry + m1.ux * m2.rz;
+	out.ry = m1.ry * m2.rx + m1.fy * m2.ry + m1.uy * m2.rz;
+	out.rz = m1.rz * m2.rx + m1.fz * m2.ry + m1.uz * m2.rz;
+	out.fx = m1.rx * m2.fx + m1.fx * m2.fy + m1.ux * m2.fz;
+	out.fy = m1.ry * m2.fx + m1.fy * m2.fy + m1.uy * m2.fz;
+	out.fz = m1.rz * m2.fx + m1.fz * m2.fy + m1.uz * m2.fz;
+	out.ux = m1.rx * m2.ux + m1.fx * m2.uy + m1.ux * m2.uz;
+	out.uy = m1.ry * m2.ux + m1.fy * m2.uy + m1.uy * m2.uz;
+	out.uz = m1.rz * m2.ux + m1.fz * m2.uy + m1.uz * m2.uz;
+	out.px = m1.rx * m2.px + m1.fx * m2.py + m1.ux * m2.pz + m1.px;
+	out.py = m1.ry * m2.px + m1.fy * m2.py + m1.uy * m2.pz + m1.py;
+	out.pz = m1.rz * m2.px + m1.fz * m2.py + m1.uz * m2.pz + m1.pz;
 	return out;
 }
 
@@ -460,59 +455,56 @@ Invert(const CMatrix &src, CMatrix &dst)
 	// TODO: VU0 code
 	// GTA handles this as a raw 4x4 orthonormal matrix
 	// and trashes the RW flags, let's not do that
-	float (*scr_fm)[4] = (float (*)[4])&src.m_matrix;
-	float (*dst_fm)[4] = (float (*)[4])&dst.m_matrix;
-
-	dst_fm[3][0] = dst_fm[3][1] = dst_fm[3][2] = 0.0f;
+	dst.f[3][0] = dst.f[3][1] = dst.f[3][2] = 0.0f;
 #ifndef FIX_BUGS
-	dst_fm[3][3] = scr_fm[3][3];
+	dst.f[3][3] = src.f[3][3];
 #endif
 
-	dst_fm[0][0] = scr_fm[0][0];
-	dst_fm[0][1] = scr_fm[1][0];
-	dst_fm[0][2] = scr_fm[2][0];
+	dst.f[0][0] = src.f[0][0];
+	dst.f[0][1] = src.f[1][0];
+	dst.f[0][2] = src.f[2][0];
 #ifndef FIX_BUGS
-	dst_fm[0][3] = scr_fm[3][0];
+	dst.f[0][3] = src.f[3][0];
 #endif
-	dst_fm[1][0] = scr_fm[0][1];
-	dst_fm[1][1] = scr_fm[1][1];
-	dst_fm[1][2] = scr_fm[2][1];
+	dst.f[1][0] = src.f[0][1];
+	dst.f[1][1] = src.f[1][1];
+	dst.f[1][2] = src.f[2][1];
 #ifndef FIX_BUGS
-	dst_fm[1][3] = scr_fm[3][1];
+	dst.f[1][3] = src.f[3][1];
 #endif
-	dst_fm[2][0] = scr_fm[0][2];
-	dst_fm[2][1] = scr_fm[1][2];
-	dst_fm[2][2] = scr_fm[2][2];
+	dst.f[2][0] = src.f[0][2];
+	dst.f[2][1] = src.f[1][2];
+	dst.f[2][2] = src.f[2][2];
 #ifndef FIX_BUGS
-	dst_fm[2][3] = scr_fm[3][2];
+	dst.f[2][3] = src.f[3][2];
 #endif
 
-	dst_fm[3][0] += dst_fm[0][0] * scr_fm[3][0];
-	dst_fm[3][1] += dst_fm[0][1] * scr_fm[3][0];
-	dst_fm[3][2] += dst_fm[0][2] * scr_fm[3][0];
+	dst.f[3][0] += dst.f[0][0] * src.f[3][0];
+	dst.f[3][1] += dst.f[0][1] * src.f[3][0];
+	dst.f[3][2] += dst.f[0][2] * src.f[3][0];
 #ifndef FIX_BUGS
-	dst_fm[3][3] += dst_fm[0][3] * scr_fm[3][0];
+	dst.f[3][3] += dst.f[0][3] * src.f[3][0];
 #endif
 
-	dst_fm[3][0] += dst_fm[1][0] * scr_fm[3][1];
-	dst_fm[3][1] += dst_fm[1][1] * scr_fm[3][1];
-	dst_fm[3][2] += dst_fm[1][2] * scr_fm[3][1];
+	dst.f[3][0] += dst.f[1][0] * src.f[3][1];
+	dst.f[3][1] += dst.f[1][1] * src.f[3][1];
+	dst.f[3][2] += dst.f[1][2] * src.f[3][1];
 #ifndef FIX_BUGS
-	dst_fm[3][3] += dst_fm[1][3] * scr_fm[3][1];
+	dst.f[3][3] += dst.f[1][3] * src.f[3][1];
 #endif
 
-	dst_fm[3][0] += dst_fm[2][0] * scr_fm[3][2];
-	dst_fm[3][1] += dst_fm[2][1] * scr_fm[3][2];
-	dst_fm[3][2] += dst_fm[2][2] * scr_fm[3][2];
+	dst.f[3][0] += dst.f[2][0] * src.f[3][2];
+	dst.f[3][1] += dst.f[2][1] * src.f[3][2];
+	dst.f[3][2] += dst.f[2][2] * src.f[3][2];
 #ifndef FIX_BUGS
-	dst_fm[3][3] += dst_fm[2][3] * scr_fm[3][2];
+	dst.f[3][3] += dst.f[2][3] * src.f[3][2];
 #endif
 
-	dst_fm[3][0] = -dst_fm[3][0];
-	dst_fm[3][1] = -dst_fm[3][1];
-	dst_fm[3][2] = -dst_fm[3][2];
+	dst.f[3][0] = -dst.f[3][0];
+	dst.f[3][1] = -dst.f[3][1];
+	dst.f[3][2] = -dst.f[3][2];
 #ifndef FIX_BUGS
-	dst_fm[3][3] = scr_fm[3][3] - dst_fm[3][3];
+	dst.f[3][3] = src.f[3][3] - dst.f[3][3];
 #endif
 
 	return dst;
diff --git a/src/math/Matrix.h b/src/math/Matrix.h
index d8f6388d..9d50a4f6 100644
--- a/src/math/Matrix.h
+++ b/src/math/Matrix.h
@@ -3,7 +3,18 @@
 class CMatrix
 {
 public:
-	RwMatrix m_matrix;
+	union
+	{
+		float f[4][4];
+		struct
+		{
+			float rx, ry, rz, rw;
+			float fx, fy, fz, fw;
+			float ux, uy, uz, uw;
+			float px, py, pz, pw;
+		};
+	};
+
 	RwMatrix *m_attachment;
 	bool m_hasRwMatrix;	// are we the owner?
 
@@ -25,31 +36,36 @@ public:
 	CMatrix &operator+=(CMatrix const &rhs);
 	CMatrix &operator*=(CMatrix const &rhs);
 
-	CVector &GetPosition(void){ return *(CVector*)&m_matrix.pos; }
-	CVector &GetRight(void) { return *(CVector*)&m_matrix.right; }
-	CVector &GetForward(void) { return *(CVector*)&m_matrix.up; }
-	CVector &GetUp(void) { return *(CVector*)&m_matrix.at; }
+	CVector &GetPosition(void) { return *(CVector*)&px; }
+	CVector &GetRight(void) { return *(CVector*)&rx; }
+	CVector &GetForward(void) { return *(CVector*)&fx; }
+	CVector &GetUp(void) { return *(CVector*)&ux; }
+
+	const CVector &GetPosition(void) const { return *(CVector*)&px; }
+	const CVector &GetRight(void) const { return *(CVector*)&rx; }
+	const CVector &GetForward(void) const { return *(CVector*)&fx; }
+	const CVector &GetUp(void) const { return *(CVector*)&ux; }
+
 
 	void SetTranslate(float x, float y, float z);
 	void SetTranslate(const CVector &trans){ SetTranslate(trans.x, trans.y, trans.z); }
 	void Translate(float x, float y, float z){
-		m_matrix.pos.x += x;
-		m_matrix.pos.y += y;
-		m_matrix.pos.z += z;
+		px += x;
+		py += y;
+		pz += z;
 	}
 	void Translate(const CVector &trans){ Translate(trans.x, trans.y, trans.z); }
 
 	void SetScale(float s);
 	void Scale(float scale)
 	{
-		float *pFloatMatrix = (float*)&m_matrix;
 		for (int i = 0; i < 3; i++)
 #ifdef FIX_BUGS // BUGFIX from VC
 			for (int j = 0; j < 3; j++)
 #else
 			for (int j = 0; j < 4; j++)
 #endif
-				pFloatMatrix[i * 4 + j] *= scale;
+				f[i][j] *= scale;
 	}
 
 
@@ -60,17 +76,17 @@ public:
 		float c = Cos(angle);
 		float s = Sin(angle);
 
-		m_matrix.right.x = c * scale;
-		m_matrix.right.y = s * scale;
-		m_matrix.right.z = 0.0f;
+		rx = c * scale;
+		ry = s * scale;
+		rz = 0.0f;
 
-		m_matrix.up.x = -s * scale;
-		m_matrix.up.y = c * scale;
-		m_matrix.up.z = 0.0f;
+		fx = -s * scale;
+		fy = c * scale;
+		fz = 0.0f;
 
-		m_matrix.at.x = 0.0f;
-		m_matrix.at.y = 0.0f;
-		m_matrix.at.z = scale;
+		ux = 0.0f;
+		uy = 0.0f;
+		uz = scale;
 	}
 	void SetRotateX(float angle);
 	void SetRotateY(float angle);
@@ -82,13 +98,13 @@ public:
 	void RotateZ(float z);
 
 	void Reorthogonalise(void);
-	void CopyOnlyMatrix(CMatrix *other);
+	void CopyOnlyMatrix(const CMatrix &other);
 	void SetUnity(void);
 	void ResetOrientation(void);
 	void SetTranslateOnly(float x, float y, float z) {
-		m_matrix.pos.x = x;
-		m_matrix.pos.y = y;
-		m_matrix.pos.z = z;
+		px = x;
+		py = y;
+		pz = z;
 	}
 	void SetTranslateOnly(const CVector& pos) {
 		SetTranslateOnly(pos.x, pos.y, pos.z);
@@ -102,11 +118,11 @@ CMatrix Invert(const CMatrix &matrix);
 CMatrix operator*(const CMatrix &m1, const CMatrix &m2);
 inline CVector MultiplyInverse(const CMatrix &mat, const CVector &vec)
 {
-	CVector v(vec.x - mat.m_matrix.pos.x, vec.y - mat.m_matrix.pos.y, vec.z - mat.m_matrix.pos.z);
+	CVector v(vec.x - mat.px, vec.y - mat.py, vec.z - mat.pz);
 	return CVector(
-		mat.m_matrix.right.x * v.x + mat.m_matrix.right.y * v.y + mat.m_matrix.right.z * v.z,
-		mat.m_matrix.up.x * v.x + mat.m_matrix.up.y * v.y + mat.m_matrix.up.z * v.z,
-		mat.m_matrix.at.x * v.x + mat.m_matrix.at.y * v.y + mat.m_matrix.at.z * v.z);
+		mat.rx * v.x + mat.ry * v.y + mat.rz * v.z,
+		mat.fx * v.x + mat.fy * v.y + mat.fz * v.z,
+		mat.ux * v.x + mat.uy * v.y + mat.uz * v.z);
 }
 
 
diff --git a/src/math/Vector.cpp b/src/math/Vector.cpp
index 42e1828e..ee76e555 100644
--- a/src/math/Vector.cpp
+++ b/src/math/Vector.cpp
@@ -23,24 +23,24 @@ CVector
 Multiply3x3(const CMatrix &mat, const CVector &vec)
 {
 	// TODO: VU0 code
-	return CVector(mat.m_matrix.right.x * vec.x + mat.m_matrix.up.x * vec.y + mat.m_matrix.at.x * vec.z,
-	               mat.m_matrix.right.y * vec.x + mat.m_matrix.up.y * vec.y + mat.m_matrix.at.y * vec.z,
-	               mat.m_matrix.right.z * vec.x + mat.m_matrix.up.z * vec.y + mat.m_matrix.at.z * vec.z);
+	return CVector(mat.rx * vec.x + mat.fx * vec.y + mat.ux * vec.z,
+	               mat.ry * vec.x + mat.fy * vec.y + mat.uy * vec.z,
+	               mat.rz * vec.x + mat.fz * vec.y + mat.uz * vec.z);
 }
 
 CVector
 Multiply3x3(const CVector &vec, const CMatrix &mat)
 {
-	return CVector(mat.m_matrix.right.x * vec.x + mat.m_matrix.right.y * vec.y + mat.m_matrix.right.z * vec.z,
-	               mat.m_matrix.up.x * vec.x + mat.m_matrix.up.y * vec.y + mat.m_matrix.up.z * vec.z,
-	               mat.m_matrix.at.x * vec.x + mat.m_matrix.at.y * vec.y + mat.m_matrix.at.z * vec.z);
+	return CVector(mat.rx * vec.x + mat.ry * vec.y + mat.rz * vec.z,
+	               mat.fx * vec.x + mat.fy * vec.y + mat.fz * vec.z,
+	               mat.ux * vec.x + mat.uy * vec.y + mat.uz * vec.z);
 }
 
 CVector
 operator*(const CMatrix &mat, const CVector &vec)
 {
 	// TODO: VU0 code
-	return CVector(mat.m_matrix.right.x * vec.x + mat.m_matrix.up.x * vec.y + mat.m_matrix.at.x * vec.z + mat.m_matrix.pos.x,
-	               mat.m_matrix.right.y * vec.x + mat.m_matrix.up.y * vec.y + mat.m_matrix.at.y * vec.z + mat.m_matrix.pos.y,
-	               mat.m_matrix.right.z * vec.x + mat.m_matrix.up.z * vec.y + mat.m_matrix.at.z * vec.z + mat.m_matrix.pos.z);
+	return CVector(mat.rx * vec.x + mat.fx * vec.y + mat.ux * vec.z + mat.px,
+	               mat.ry * vec.x + mat.fy * vec.y + mat.uy * vec.z + mat.py,
+	               mat.rz * vec.x + mat.fz * vec.y + mat.uz * vec.z + mat.pz);
 }
diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp
index e3d2ffa6..13afadb6 100644
--- a/src/render/SpecialFX.cpp
+++ b/src/render/SpecialFX.cpp
@@ -587,7 +587,7 @@ C3dMarkers::PlaceMarker(uint32 identifier, uint16 type, CVector &pos, float size
 				pMarker->m_Color.alpha = (float)a * 0.4f * someSin + a;
 		}
 		if (pMarker->m_nRotateRate) {
-			RwV3d pos = pMarker->m_Matrix.m_matrix.pos;
+			CVector pos = pMarker->m_Matrix.GetPosition();
 			pMarker->m_Matrix.RotateZ(DEGTORAD(pMarker->m_nRotateRate * CTimer::GetTimeStep()));
 			pMarker->m_Matrix.GetPosition() = pos;
 		}