Add Int32Matrix4x4 struct.
This allows matrices to be represented as a value type, and additionally allows avoiding array allocations when calculating rotations.
This commit is contained in:
@@ -323,12 +323,31 @@ namespace OpenRA.Graphics
|
|||||||
return mtx;
|
return mtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float[] MakeFloatMatrix(int[] imtx)
|
public static float[] MakeFloatMatrix(Int32Matrix4x4 imtx)
|
||||||
{
|
{
|
||||||
var fmtx = new float[16];
|
var multipler = 1f / imtx.M44;
|
||||||
for (var i = 0; i < 16; i++)
|
return new float[]
|
||||||
fmtx[i] = imtx[i] * 1f / imtx[15];
|
{
|
||||||
return fmtx;
|
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)
|
public static float[] MatrixAABBMultiply(float[] mtx, float[] bounds)
|
||||||
|
|||||||
@@ -106,6 +106,7 @@
|
|||||||
<Compile Include="Actor.cs" />
|
<Compile Include="Actor.cs" />
|
||||||
<Compile Include="CacheStorage.cs" />
|
<Compile Include="CacheStorage.cs" />
|
||||||
<Compile Include="FileSystem\IPackage.cs" />
|
<Compile Include="FileSystem\IPackage.cs" />
|
||||||
|
<Compile Include="Primitives\Int32Matrix4x4.cs" />
|
||||||
<Compile Include="LogProxy.cs" />
|
<Compile Include="LogProxy.cs" />
|
||||||
<Compile Include="Map\MapGrid.cs" />
|
<Compile Include="Map\MapGrid.cs" />
|
||||||
<Compile Include="Map\MapPlayers.cs" />
|
<Compile Include="Map\MapPlayers.cs" />
|
||||||
|
|||||||
72
OpenRA.Game/Primitives/Int32Matrix4x4.cs
Normal file
72
OpenRA.Game/Primitives/Int32Matrix4x4.cs
Normal file
@@ -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<Int32Matrix4x4>
|
||||||
|
{
|
||||||
|
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 + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,58 +41,61 @@ namespace OpenRA
|
|||||||
return new WRot(Roll, Pitch, yaw);
|
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
|
// Angles increase clockwise
|
||||||
var r = new WAngle(-Roll.Angle / 2);
|
var roll = new WAngle(-Roll.Angle / 2);
|
||||||
var p = new WAngle(-Pitch.Angle / 2);
|
var pitch = new WAngle(-Pitch.Angle / 2);
|
||||||
var y = new WAngle(-Yaw.Angle / 2);
|
var yaw = new WAngle(-Yaw.Angle / 2);
|
||||||
var cr = (long)r.Cos();
|
var cr = (long)roll.Cos();
|
||||||
var sr = (long)r.Sin();
|
var sr = (long)roll.Sin();
|
||||||
var cp = (long)p.Cos();
|
var cp = (long)pitch.Cos();
|
||||||
var sp = (long)p.Sin();
|
var sp = (long)pitch.Sin();
|
||||||
var cy = (long)y.Cos();
|
var cy = (long)yaw.Cos();
|
||||||
var sy = (long)y.Sin();
|
var sy = (long)yaw.Sin();
|
||||||
|
|
||||||
// Normalized to 1024 == 1.0
|
// Normalized to 1024 == 1.0
|
||||||
return new int[4]
|
x = (int)((sr * cp * cy - cr * sp * sy) / 1048576);
|
||||||
{
|
y = (int)((cr * sp * cy + sr * cp * sy) / 1048576);
|
||||||
(int)((sr * cp * cy - cr * sp * sy) / 1048576), // x
|
z = (int)((cr * cp * sy - sr * sp * cy) / 1048576);
|
||||||
(int)((cr * sp * cy + sr * cp * sy) / 1048576), // y
|
w = (int)((cr * cp * cy + sr * sp * sy) / 1048576);
|
||||||
(int)((cr * cp * sy - sr * sp * cy) / 1048576), // z
|
|
||||||
(int)((cr * cp * cy + sr * sp * sy) / 1048576) // w
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// 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
|
// Quaternion components use 10 bits, so there's no risk of overflow
|
||||||
var mtx = new int[16];
|
mtx = new Int32Matrix4x4(
|
||||||
mtx[0] = lsq - 2 * (q[1] * q[1] + q[2] * q[2]);
|
lsq - 2 * (y * y + z * z),
|
||||||
mtx[1] = 2 * (q[0] * q[1] + q[2] * q[3]);
|
2 * (x * y + z * w),
|
||||||
mtx[2] = 2 * (q[0] * q[2] - q[1] * q[3]);
|
2 * (x * z - y * w),
|
||||||
mtx[3] = 0;
|
0,
|
||||||
|
|
||||||
mtx[4] = 2 * (q[0] * q[1] - q[2] * q[3]);
|
2 * (x * y - z * w),
|
||||||
mtx[5] = lsq - 2 * (q[0] * q[0] + q[2] * q[2]);
|
lsq - 2 * (x * x + z * z),
|
||||||
mtx[6] = 2 * (q[1] * q[2] + q[0] * q[3]);
|
2 * (y * z + x * w),
|
||||||
mtx[7] = 0;
|
0,
|
||||||
|
|
||||||
mtx[8] = 2 * (q[0] * q[2] + q[1] * q[3]);
|
2 * (x * z + y * w),
|
||||||
mtx[9] = 2 * (q[1] * q[2] - q[0] * q[3]);
|
2 * (y * z - x * w),
|
||||||
mtx[10] = lsq - 2 * (q[0] * q[0] + q[1] * q[1]);
|
lsq - 2 * (x * x + y * y),
|
||||||
mtx[11] = 0;
|
0,
|
||||||
|
|
||||||
mtx[12] = 0;
|
0,
|
||||||
mtx[13] = 0;
|
0,
|
||||||
mtx[14] = 0;
|
0,
|
||||||
mtx[15] = lsq;
|
lsq);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Int32Matrix4x4 AsMatrix()
|
||||||
|
{
|
||||||
|
Int32Matrix4x4 mtx;
|
||||||
|
AsMatrix(out mtx);
|
||||||
return mtx;
|
return mtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,19 +46,20 @@ namespace OpenRA
|
|||||||
|
|
||||||
public WVec Rotate(WRot rot)
|
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 lx = (long)X;
|
||||||
var ly = (long)Y;
|
var ly = (long)Y;
|
||||||
var lz = (long)Z;
|
var lz = (long)Z;
|
||||||
return new WVec(
|
return new WVec(
|
||||||
(int)((lx * mtx[0] + ly * mtx[4] + lz * mtx[8]) / mtx[15]),
|
(int)((lx * mtx.M11 + ly * mtx.M21 + lz * mtx.M31) / mtx.M44),
|
||||||
(int)((lx * mtx[1] + ly * mtx[5] + lz * mtx[9]) / mtx[15]),
|
(int)((lx * mtx.M12 + ly * mtx.M22 + lz * mtx.M32) / mtx.M44),
|
||||||
(int)((lx * mtx[2] + ly * mtx[6] + lz * mtx[10]) / mtx[15]));
|
(int)((lx * mtx.M13 + ly * mtx.M23 + lz * mtx.M33) / mtx.M44));
|
||||||
}
|
}
|
||||||
|
|
||||||
public WAngle Yaw
|
public WAngle Yaw
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ namespace OpenRA.Mods.Common.Graphics
|
|||||||
public struct RangeCircleRenderable : IRenderable, IFinalizedRenderable
|
public struct RangeCircleRenderable : IRenderable, IFinalizedRenderable
|
||||||
{
|
{
|
||||||
const int RangeCircleSegments = 32;
|
const int RangeCircleSegments = 32;
|
||||||
static readonly int[][] RangeCircleStartRotations = Exts.MakeArray(RangeCircleSegments, i => WRot.FromFacing(8 * i).AsMatrix());
|
static readonly Int32Matrix4x4[] 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[] RangeCircleEndRotations = Exts.MakeArray(RangeCircleSegments, i => WRot.FromFacing(8 * i + 6).AsMatrix());
|
||||||
|
|
||||||
readonly WPos centerPosition;
|
readonly WPos centerPosition;
|
||||||
readonly WDist radius;
|
readonly WDist radius;
|
||||||
@@ -58,8 +58,8 @@ namespace OpenRA.Mods.Common.Graphics
|
|||||||
var offset = new WVec(radius.Length, 0, 0);
|
var offset = new WVec(radius.Length, 0, 0);
|
||||||
for (var i = 0; i < RangeCircleSegments; i++)
|
for (var i = 0; i < RangeCircleSegments; i++)
|
||||||
{
|
{
|
||||||
var a = wr.Screen3DPosition(centerPosition + offset.Rotate(RangeCircleStartRotations[i]));
|
var a = wr.Screen3DPosition(centerPosition + offset.Rotate(ref RangeCircleStartRotations[i]));
|
||||||
var b = wr.Screen3DPosition(centerPosition + offset.Rotate(RangeCircleEndRotations[i]));
|
var b = wr.Screen3DPosition(centerPosition + offset.Rotate(ref RangeCircleEndRotations[i]));
|
||||||
|
|
||||||
if (contrastWidth > 0)
|
if (contrastWidth > 0)
|
||||||
wcr.DrawLine(a, b, contrastWidth / wr.Viewport.Zoom, contrastColor);
|
wcr.DrawLine(a, b, contrastWidth / wr.Viewport.Zoom, contrastColor);
|
||||||
|
|||||||
Reference in New Issue
Block a user