diff --git a/OpenRA.Game/Graphics/Util.cs b/OpenRA.Game/Graphics/Util.cs
index 8abdedbe53..cb99bd0039 100644
--- a/OpenRA.Game/Graphics/Util.cs
+++ b/OpenRA.Game/Graphics/Util.cs
@@ -323,12 +323,31 @@ namespace OpenRA.Graphics
return mtx;
}
- public static float[] MakeFloatMatrix(int[] imtx)
+ public static float[] MakeFloatMatrix(Int32Matrix4x4 imtx)
{
- var fmtx = new float[16];
- for (var i = 0; i < 16; i++)
- fmtx[i] = imtx[i] * 1f / imtx[15];
- return fmtx;
+ var multipler = 1f / imtx.M44;
+ return new float[]
+ {
+ imtx.M11 * multipler,
+ imtx.M12 * multipler,
+ imtx.M13 * multipler,
+ imtx.M14 * multipler,
+
+ imtx.M21 * multipler,
+ imtx.M22 * multipler,
+ imtx.M23 * multipler,
+ imtx.M24 * multipler,
+
+ imtx.M31 * multipler,
+ imtx.M32 * multipler,
+ imtx.M33 * multipler,
+ imtx.M34 * multipler,
+
+ imtx.M41 * multipler,
+ imtx.M42 * multipler,
+ imtx.M43 * multipler,
+ imtx.M44 * multipler,
+ };
}
public static float[] MatrixAABBMultiply(float[] mtx, float[] bounds)
diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj
index 94cc61b8e9..42091b6c03 100644
--- a/OpenRA.Game/OpenRA.Game.csproj
+++ b/OpenRA.Game/OpenRA.Game.csproj
@@ -106,6 +106,7 @@
+
diff --git a/OpenRA.Game/Primitives/Int32Matrix4x4.cs b/OpenRA.Game/Primitives/Int32Matrix4x4.cs
new file mode 100644
index 0000000000..6a6068bffd
--- /dev/null
+++ b/OpenRA.Game/Primitives/Int32Matrix4x4.cs
@@ -0,0 +1,72 @@
+#region Copyright & License Information
+/*
+ * Copyright 2007-2018 The OpenRA Developers (see AUTHORS)
+ * This file is part of OpenRA, which is free software. It is made
+ * available to you under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version. For more
+ * information, see COPYING.
+ */
+#endregion
+
+using System;
+
+namespace OpenRA
+{
+ public struct Int32Matrix4x4 : IEquatable
+ {
+ public readonly int M11, M12, M13, M14, M21, M22, M23, M24, M31, M32, M33, M34, M41, M42, M43, M44;
+
+ public Int32Matrix4x4(
+ int m11, int m12, int m13, int m14,
+ int m21, int m22, int m23, int m24,
+ int m31, int m32, int m33, int m34,
+ int m41, int m42, int m43, int m44)
+ {
+ M11 = m11;
+ M12 = m12;
+ M13 = m13;
+ M14 = m14;
+
+ M21 = m21;
+ M22 = m22;
+ M23 = m23;
+ M24 = m24;
+
+ M31 = m31;
+ M32 = m32;
+ M33 = m33;
+ M34 = m34;
+
+ M41 = m41;
+ M42 = m42;
+ M43 = m43;
+ M44 = m44;
+ }
+
+ public static bool operator ==(Int32Matrix4x4 me, Int32Matrix4x4 other)
+ {
+ return
+ me.M11 == other.M11 && me.M12 == other.M12 && me.M13 == other.M13 && me.M14 == other.M14 &&
+ me.M21 == other.M21 && me.M22 == other.M22 && me.M23 == other.M23 && me.M24 == other.M24 &&
+ me.M31 == other.M31 && me.M32 == other.M32 && me.M33 == other.M33 && me.M34 == other.M34 &&
+ me.M41 == other.M41 && me.M42 == other.M42 && me.M43 == other.M43 && me.M44 == other.M44;
+ }
+
+ public static bool operator !=(Int32Matrix4x4 me, Int32Matrix4x4 other) { return !(me == other); }
+
+ public override int GetHashCode() { return M11 ^ M22 ^ M33 ^ M44; }
+
+ public bool Equals(Int32Matrix4x4 other) { return other == this; }
+ public override bool Equals(object obj) { return obj is Int32Matrix4x4 && Equals((Int32Matrix4x4)obj); }
+
+ public override string ToString()
+ {
+ return
+ "[" + M11 + " " + M12 + " " + M13 + " " + M14 + "],[" +
+ "[" + M21 + " " + M22 + " " + M23 + " " + M24 + "],[" +
+ "[" + M31 + " " + M32 + " " + M33 + " " + M34 + "],[" +
+ "[" + M41 + " " + M42 + " " + M43 + " " + M44 + "]";
+ }
+ }
+}
diff --git a/OpenRA.Game/WRot.cs b/OpenRA.Game/WRot.cs
index c7ff79d867..998aca4212 100644
--- a/OpenRA.Game/WRot.cs
+++ b/OpenRA.Game/WRot.cs
@@ -41,58 +41,61 @@ namespace OpenRA
return new WRot(Roll, Pitch, yaw);
}
- public int[] AsQuarternion()
+ void AsQuarternion(out int x, out int y, out int z, out int w)
{
// Angles increase clockwise
- var r = new WAngle(-Roll.Angle / 2);
- var p = new WAngle(-Pitch.Angle / 2);
- var y = new WAngle(-Yaw.Angle / 2);
- var cr = (long)r.Cos();
- var sr = (long)r.Sin();
- var cp = (long)p.Cos();
- var sp = (long)p.Sin();
- var cy = (long)y.Cos();
- var sy = (long)y.Sin();
+ var roll = new WAngle(-Roll.Angle / 2);
+ var pitch = new WAngle(-Pitch.Angle / 2);
+ var yaw = new WAngle(-Yaw.Angle / 2);
+ var cr = (long)roll.Cos();
+ var sr = (long)roll.Sin();
+ var cp = (long)pitch.Cos();
+ var sp = (long)pitch.Sin();
+ var cy = (long)yaw.Cos();
+ var sy = (long)yaw.Sin();
// Normalized to 1024 == 1.0
- return new int[4]
- {
- (int)((sr * cp * cy - cr * sp * sy) / 1048576), // x
- (int)((cr * sp * cy + sr * cp * sy) / 1048576), // y
- (int)((cr * cp * sy - sr * sp * cy) / 1048576), // z
- (int)((cr * cp * cy + sr * sp * sy) / 1048576) // w
- };
+ x = (int)((sr * cp * cy - cr * sp * sy) / 1048576);
+ y = (int)((cr * sp * cy + sr * cp * sy) / 1048576);
+ z = (int)((cr * cp * sy - sr * sp * cy) / 1048576);
+ w = (int)((cr * cp * cy + sr * sp * sy) / 1048576);
}
- public int[] AsMatrix()
+ public void AsMatrix(out Int32Matrix4x4 mtx)
{
- var q = AsQuarternion();
+ int x, y, z, w;
+ AsQuarternion(out x, out y, out z, out w);
// Theoretically 1024 * * 2, but may differ slightly due to rounding
- var lsq = q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3];
+ var lsq = x * x + y * y + z * z + w * w;
// Quaternion components use 10 bits, so there's no risk of overflow
- var mtx = new int[16];
- mtx[0] = lsq - 2 * (q[1] * q[1] + q[2] * q[2]);
- mtx[1] = 2 * (q[0] * q[1] + q[2] * q[3]);
- mtx[2] = 2 * (q[0] * q[2] - q[1] * q[3]);
- mtx[3] = 0;
+ mtx = new Int32Matrix4x4(
+ lsq - 2 * (y * y + z * z),
+ 2 * (x * y + z * w),
+ 2 * (x * z - y * w),
+ 0,
- mtx[4] = 2 * (q[0] * q[1] - q[2] * q[3]);
- mtx[5] = lsq - 2 * (q[0] * q[0] + q[2] * q[2]);
- mtx[6] = 2 * (q[1] * q[2] + q[0] * q[3]);
- mtx[7] = 0;
+ 2 * (x * y - z * w),
+ lsq - 2 * (x * x + z * z),
+ 2 * (y * z + x * w),
+ 0,
- mtx[8] = 2 * (q[0] * q[2] + q[1] * q[3]);
- mtx[9] = 2 * (q[1] * q[2] - q[0] * q[3]);
- mtx[10] = lsq - 2 * (q[0] * q[0] + q[1] * q[1]);
- mtx[11] = 0;
+ 2 * (x * z + y * w),
+ 2 * (y * z - x * w),
+ lsq - 2 * (x * x + y * y),
+ 0,
- mtx[12] = 0;
- mtx[13] = 0;
- mtx[14] = 0;
- mtx[15] = lsq;
+ 0,
+ 0,
+ 0,
+ lsq);
+ }
+ public Int32Matrix4x4 AsMatrix()
+ {
+ Int32Matrix4x4 mtx;
+ AsMatrix(out mtx);
return mtx;
}
diff --git a/OpenRA.Game/WVec.cs b/OpenRA.Game/WVec.cs
index 49dddb7426..f7830f33c9 100644
--- a/OpenRA.Game/WVec.cs
+++ b/OpenRA.Game/WVec.cs
@@ -46,19 +46,20 @@ namespace OpenRA
public WVec Rotate(WRot rot)
{
- return Rotate(rot.AsMatrix());
+ Int32Matrix4x4 mtx;
+ rot.AsMatrix(out mtx);
+ return Rotate(ref mtx);
}
- public WVec Rotate(int[] rotationMatrix)
+ public WVec Rotate(ref Int32Matrix4x4 mtx)
{
- var mtx = rotationMatrix;
var lx = (long)X;
var ly = (long)Y;
var lz = (long)Z;
return new WVec(
- (int)((lx * mtx[0] + ly * mtx[4] + lz * mtx[8]) / mtx[15]),
- (int)((lx * mtx[1] + ly * mtx[5] + lz * mtx[9]) / mtx[15]),
- (int)((lx * mtx[2] + ly * mtx[6] + lz * mtx[10]) / mtx[15]));
+ (int)((lx * mtx.M11 + ly * mtx.M21 + lz * mtx.M31) / mtx.M44),
+ (int)((lx * mtx.M12 + ly * mtx.M22 + lz * mtx.M32) / mtx.M44),
+ (int)((lx * mtx.M13 + ly * mtx.M23 + lz * mtx.M33) / mtx.M44));
}
public WAngle Yaw
diff --git a/OpenRA.Mods.Common/Graphics/RangeCircleRenderable.cs b/OpenRA.Mods.Common/Graphics/RangeCircleRenderable.cs
index f68cc03133..6b289c1a94 100644
--- a/OpenRA.Mods.Common/Graphics/RangeCircleRenderable.cs
+++ b/OpenRA.Mods.Common/Graphics/RangeCircleRenderable.cs
@@ -17,8 +17,8 @@ namespace OpenRA.Mods.Common.Graphics
public struct RangeCircleRenderable : IRenderable, IFinalizedRenderable
{
const int RangeCircleSegments = 32;
- static readonly int[][] RangeCircleStartRotations = Exts.MakeArray(RangeCircleSegments, i => WRot.FromFacing(8 * i).AsMatrix());
- static readonly int[][] RangeCircleEndRotations = Exts.MakeArray(RangeCircleSegments, i => WRot.FromFacing(8 * i + 6).AsMatrix());
+ static readonly Int32Matrix4x4[] RangeCircleStartRotations = Exts.MakeArray(RangeCircleSegments, i => WRot.FromFacing(8 * i).AsMatrix());
+ static readonly Int32Matrix4x4[] RangeCircleEndRotations = Exts.MakeArray(RangeCircleSegments, i => WRot.FromFacing(8 * i + 6).AsMatrix());
readonly WPos centerPosition;
readonly WDist radius;
@@ -58,8 +58,8 @@ namespace OpenRA.Mods.Common.Graphics
var offset = new WVec(radius.Length, 0, 0);
for (var i = 0; i < RangeCircleSegments; i++)
{
- var a = wr.Screen3DPosition(centerPosition + offset.Rotate(RangeCircleStartRotations[i]));
- var b = wr.Screen3DPosition(centerPosition + offset.Rotate(RangeCircleEndRotations[i]));
+ var a = wr.Screen3DPosition(centerPosition + offset.Rotate(ref RangeCircleStartRotations[i]));
+ var b = wr.Screen3DPosition(centerPosition + offset.Rotate(ref RangeCircleEndRotations[i]));
if (contrastWidth > 0)
wcr.DrawLine(a, b, contrastWidth / wr.Viewport.Zoom, contrastColor);