Add new "World Coordinate" types.
These types provide fixed-point representations of distances, angles, positions, vectors, and rotations in 3d space. WAngle (and WRot) represents 360 degrees in 1024 units. WRange (and WPos, WVec) represents 1 cell in 1024 units. Distance types in yaml can be written as <cell>c<subcell>, e.g. "4c512" for 4.5 cells.
This commit is contained in:
@@ -161,6 +161,61 @@ namespace OpenRA.FileFormats
|
||||
return InvalidValueAction(x, fieldType, field);
|
||||
}
|
||||
|
||||
else if (fieldType == typeof(WRange))
|
||||
{
|
||||
WRange res;
|
||||
if (WRange.TryParse(x, out res))
|
||||
return res;
|
||||
|
||||
return InvalidValueAction(x, fieldType, field);
|
||||
}
|
||||
|
||||
else if (fieldType == typeof(WVec))
|
||||
{
|
||||
var parts = x.Split(',');
|
||||
if (parts.Length == 3)
|
||||
{
|
||||
WRange rx, ry, rz;
|
||||
if (WRange.TryParse(parts[0], out rx) && WRange.TryParse(parts[1], out ry) && WRange.TryParse(parts[2], out rz))
|
||||
return new WVec(rx, ry, rz);
|
||||
}
|
||||
|
||||
return InvalidValueAction(x, fieldType, field);
|
||||
}
|
||||
|
||||
else if (fieldType == typeof(WPos))
|
||||
{
|
||||
var parts = x.Split(',');
|
||||
if (parts.Length == 3)
|
||||
{
|
||||
WRange rx, ry, rz;
|
||||
if (WRange.TryParse(parts[0], out rx) && WRange.TryParse(parts[1], out ry) && WRange.TryParse(parts[2], out rz))
|
||||
return new WPos(rx, ry, rz);
|
||||
}
|
||||
|
||||
return InvalidValueAction(x, fieldType, field);
|
||||
}
|
||||
|
||||
else if (fieldType == typeof(WAngle))
|
||||
{
|
||||
int res;
|
||||
if (int.TryParse(x, out res))
|
||||
return new WAngle(res);
|
||||
return InvalidValueAction(x, fieldType, field);
|
||||
}
|
||||
|
||||
else if (fieldType == typeof(WRot))
|
||||
{
|
||||
var parts = x.Split(',');
|
||||
if (parts.Length == 3)
|
||||
{
|
||||
int rr, rp, ry;
|
||||
if (int.TryParse(x, out rr) && int.TryParse(x, out rp) && int.TryParse(x, out ry))
|
||||
return new WRot(new WAngle(rr), new WAngle(rp), new WAngle(ry));
|
||||
}
|
||||
return InvalidValueAction(x, fieldType, field);
|
||||
}
|
||||
|
||||
else if (fieldType.IsEnum)
|
||||
{
|
||||
if (!Enum.GetNames(fieldType).Select(a => a.ToLower()).Contains(x.ToLower()))
|
||||
|
||||
@@ -132,6 +132,11 @@
|
||||
<Compile Include="Support\Timer.cs" />
|
||||
<Compile Include="Thirdparty\Random.cs" />
|
||||
<Compile Include="TypeDictionary.cs" />
|
||||
<Compile Include="WPos.cs" />
|
||||
<Compile Include="WVec.cs" />
|
||||
<Compile Include="WAngle.cs" />
|
||||
<Compile Include="WRot.cs" />
|
||||
<Compile Include="WRange.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
|
||||
123
OpenRA.FileFormats/WAngle.cs
Normal file
123
OpenRA.FileFormats/WAngle.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
/// <summary>
|
||||
/// 1D angle - 1024 units = 360 degrees.
|
||||
/// </summary>
|
||||
public struct WAngle
|
||||
{
|
||||
public readonly int Angle;
|
||||
|
||||
public WAngle(int a)
|
||||
{
|
||||
Angle = a % 1024;
|
||||
if (Angle < 0)
|
||||
Angle += 1024;
|
||||
}
|
||||
public static readonly WAngle Zero = new WAngle(0);
|
||||
public static WAngle FromFacing(int facing) { return new WAngle(facing*4); }
|
||||
public static WAngle FromDegrees(int degrees) { return new WAngle(degrees*1024/360); }
|
||||
public static WAngle operator +(WAngle a, WAngle b) { return new WAngle(a.Angle + b.Angle); }
|
||||
public static WAngle operator -(WAngle a, WAngle b) { return new WAngle(a.Angle - b.Angle); }
|
||||
public static WAngle operator -(WAngle a) { return new WAngle(-a.Angle); }
|
||||
|
||||
public static bool operator ==(WAngle me, WAngle other) { return (me.Angle == other.Angle); }
|
||||
public static bool operator !=(WAngle me, WAngle other) { return !(me == other); }
|
||||
|
||||
public override int GetHashCode() { return Angle.GetHashCode(); }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return false;
|
||||
|
||||
WAngle o = (WAngle)obj;
|
||||
return o == this;
|
||||
}
|
||||
|
||||
public int Sin() { return new WAngle(Angle - 256).Cos(); }
|
||||
|
||||
public int Cos()
|
||||
{
|
||||
if (Angle <= 256)
|
||||
return CosineTable[Angle];
|
||||
if (Angle <= 512)
|
||||
return -CosineTable[512 - Angle];
|
||||
return -new WAngle(Angle - 512).Cos();
|
||||
}
|
||||
|
||||
public int Tan()
|
||||
{
|
||||
if (Angle <= 256)
|
||||
return TanTable[Angle];
|
||||
if (Angle <= 512)
|
||||
return -TanTable[512 - Angle];
|
||||
return new WAngle(Angle - 512).Tan();
|
||||
}
|
||||
|
||||
// Must not be used outside rendering code
|
||||
public float RendererRadians() { return (float)(Angle * Math.PI / 512f); }
|
||||
public float RendererDegrees() { return Angle * 0.3515625f; }
|
||||
|
||||
public override string ToString() { return "{0}".F(Angle); }
|
||||
|
||||
static int[] CosineTable =
|
||||
{
|
||||
1024, 1023, 1023, 1023, 1023, 1023, 1023, 1023, 1022, 1022, 1022, 1021,
|
||||
1021, 1020, 1020, 1019, 1019, 1018, 1017, 1017, 1016, 1015, 1014, 1013,
|
||||
1012, 1011, 1010, 1009, 1008, 1007, 1006, 1005, 1004, 1003, 1001, 1000,
|
||||
999, 997, 996, 994, 993, 991, 990, 988, 986, 985, 983, 981, 979, 978,
|
||||
976, 974, 972, 970, 968, 966, 964, 962, 959, 957, 955, 953, 950, 948,
|
||||
946, 943, 941, 938, 936, 933, 930, 928, 925, 922, 920, 917, 914, 911,
|
||||
908, 906, 903, 900, 897, 894, 890, 887, 884, 881, 878, 875, 871, 868,
|
||||
865, 861, 858, 854, 851, 847, 844, 840, 837, 833, 829, 826, 822, 818,
|
||||
814, 811, 807, 803, 799, 795, 791, 787, 783, 779, 775, 771, 767, 762,
|
||||
758, 754, 750, 745, 741, 737, 732, 728, 724, 719, 715, 710, 706, 701,
|
||||
696, 692, 687, 683, 678, 673, 668, 664, 659, 654, 649, 644, 639, 634,
|
||||
629, 625, 620, 615, 609, 604, 599, 594, 589, 584, 579, 574, 568, 563,
|
||||
558, 553, 547, 542, 537, 531, 526, 521, 515, 510, 504, 499, 493, 488,
|
||||
482, 477, 471, 466, 460, 454, 449, 443, 437, 432, 426, 420, 414, 409,
|
||||
403, 397, 391, 386, 380, 374, 368, 362, 356, 350, 344, 339, 333, 327,
|
||||
321, 315, 309, 303, 297, 291, 285, 279, 273, 267, 260, 254, 248, 242,
|
||||
236, 230, 224, 218, 212, 205, 199, 193, 187, 181, 175, 168, 162, 156,
|
||||
150, 144, 137, 131, 125, 119, 112, 106, 100, 94, 87, 81, 75, 69, 62,
|
||||
56, 50, 43, 37, 31, 25, 18, 12, 6, 0
|
||||
};
|
||||
|
||||
static int[] TanTable =
|
||||
{
|
||||
0, 6, 12, 18, 25, 31, 37, 44, 50, 56, 62, 69, 75, 81, 88, 94, 100, 107,
|
||||
113, 119, 126, 132, 139, 145, 151, 158, 164, 171, 177, 184, 190, 197,
|
||||
203, 210, 216, 223, 229, 236, 243, 249, 256, 263, 269, 276, 283, 290,
|
||||
296, 303, 310, 317, 324, 331, 338, 345, 352, 359, 366, 373, 380, 387,
|
||||
395, 402, 409, 416, 424, 431, 438, 446, 453, 461, 469, 476, 484, 492,
|
||||
499, 507, 515, 523, 531, 539, 547, 555, 563, 571, 580, 588, 596, 605,
|
||||
613, 622, 630, 639, 648, 657, 666, 675, 684, 693, 702, 711, 721, 730,
|
||||
740, 749, 759, 769, 779, 789, 799, 809, 819, 829, 840, 850, 861, 872,
|
||||
883, 894, 905, 916, 928, 939, 951, 963, 974, 986, 999, 1011, 1023, 1036,
|
||||
1049, 1062, 1075, 1088, 1102, 1115, 1129, 1143, 1158, 1172, 1187, 1201,
|
||||
1216, 1232, 1247, 1263, 1279, 1295, 1312, 1328, 1345, 1363, 1380, 1398,
|
||||
1416, 1435, 1453, 1473, 1492, 1512, 1532, 1553, 1574, 1595, 1617, 1639,
|
||||
1661, 1684, 1708, 1732, 1756, 1782, 1807, 1833, 1860, 1887, 1915, 1944,
|
||||
1973, 2003, 2034, 2065, 2098, 2131, 2165, 2199, 2235, 2272, 2310, 2348,
|
||||
2388, 2429, 2472, 2515, 2560, 2606, 2654, 2703, 2754, 2807, 2861, 2918,
|
||||
2976, 3036, 3099, 3164, 3232, 3302, 3375, 3451, 3531, 3613, 3700, 3790,
|
||||
3885, 3984, 4088, 4197, 4311, 4432, 4560, 4694, 4836, 4987, 5147, 5318,
|
||||
5499, 5693, 5901, 6124, 6364, 6622, 6903, 7207, 7539, 7902, 8302, 8743,
|
||||
9233, 9781, 10396, 11094, 11891, 12810, 13882, 15148, 16667, 18524, 20843,
|
||||
23826, 27801, 33366, 41713, 55622, 83438, 166883, int.MaxValue
|
||||
};
|
||||
}
|
||||
}
|
||||
50
OpenRA.FileFormats/WPos.cs
Normal file
50
OpenRA.FileFormats/WPos.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
/// <summary>
|
||||
/// 3d World position - 1024 units = 1 cell.
|
||||
/// </summary>
|
||||
public struct WPos
|
||||
{
|
||||
public readonly int X, Y, Z;
|
||||
|
||||
public WPos(int x, int y, int z) { X = x; Y = y; Z = z; }
|
||||
public WPos(WRange x, WRange y, WRange z) { X = x.Range; Y = y.Range; Z = z.Range; }
|
||||
|
||||
public static readonly WPos Zero = new WPos(0, 0, 0);
|
||||
|
||||
public static explicit operator WVec(WPos a) { return new WVec(a.X, a.Y, a.Z); }
|
||||
|
||||
public static WPos operator +(WPos a, WVec b) { return new WPos(a.X + b.X, a.Y + b.Y, a.Z + b.Z); }
|
||||
public static WPos operator -(WPos a, WVec b) { return new WPos(a.X - b.X, a.Y - b.Y, a.Z - b.Z); }
|
||||
public static WVec operator -(WPos a, WPos b) { return new WVec(a.X - b.X, a.Y - b.Y, a.Z - b.Z); }
|
||||
|
||||
public static bool operator ==(WPos me, WPos other) { return (me.X == other.X && me.Y == other.Y && me.Z == other.Z); }
|
||||
public static bool operator !=(WPos me, WPos other) { return !(me == other); }
|
||||
|
||||
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode(); }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return false;
|
||||
|
||||
WPos o = (WPos)obj;
|
||||
return o == this;
|
||||
}
|
||||
|
||||
public override string ToString() { return "{0},{1},{2}".F(X, Y, Z); }
|
||||
}
|
||||
}
|
||||
72
OpenRA.FileFormats/WRange.cs
Normal file
72
OpenRA.FileFormats/WRange.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
/// <summary>
|
||||
/// 1d world distance - 1024 units = 1 cell.
|
||||
/// </summary>
|
||||
public struct WRange
|
||||
{
|
||||
public readonly int Range;
|
||||
|
||||
public WRange(int r) { Range = r; }
|
||||
public static readonly WRange Zero = new WRange(0);
|
||||
|
||||
public static WRange operator +(WRange a, WRange b) { return new WRange(a.Range + b.Range); }
|
||||
public static WRange operator -(WRange a, WRange b) { return new WRange(a.Range - b.Range); }
|
||||
public static WRange operator -(WRange a) { return new WRange(-a.Range); }
|
||||
|
||||
public static bool operator ==(WRange me, WRange other) { return (me.Range == other.Range); }
|
||||
public static bool operator !=(WRange me, WRange other) { return !(me == other); }
|
||||
|
||||
public static bool TryParse(string s, out WRange result)
|
||||
{
|
||||
s = s.ToLowerInvariant();
|
||||
var components = s.Split('c');
|
||||
int cell = 0;
|
||||
int subcell = 0;
|
||||
result = WRange.Zero;
|
||||
|
||||
switch (components.Length)
|
||||
{
|
||||
case 2:
|
||||
if (!int.TryParse(components[0], out cell) ||
|
||||
!int.TryParse(components[1], out subcell))
|
||||
return false;
|
||||
break;
|
||||
case 1:
|
||||
if (!int.TryParse(components[0], out subcell))
|
||||
return false;
|
||||
break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
result = new WRange(1024*cell + subcell);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override int GetHashCode() { return Range.GetHashCode(); }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return false;
|
||||
|
||||
WRange o = (WRange)obj;
|
||||
return o == this;
|
||||
}
|
||||
|
||||
public override string ToString() { return "{0}".F(Range); }
|
||||
}
|
||||
}
|
||||
109
OpenRA.FileFormats/WRot.cs
Normal file
109
OpenRA.FileFormats/WRot.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
/// <summary>
|
||||
/// 3d World rotation.
|
||||
/// </summary>
|
||||
public struct WRot
|
||||
{
|
||||
public readonly WAngle Roll, Pitch, Yaw;
|
||||
|
||||
public WRot(WAngle roll, WAngle pitch, WAngle yaw) { Roll = roll; Pitch = pitch; Yaw = yaw; }
|
||||
public static readonly WRot Zero = new WRot(WAngle.Zero, WAngle.Zero, WAngle.Zero);
|
||||
|
||||
public static WRot FromFacing(int facing) { return new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facing)); }
|
||||
public static WRot FromYaw(WAngle yaw) { return new WRot(WAngle.Zero, WAngle.Zero, yaw); }
|
||||
public static WRot operator +(WRot a, WRot b) { return new WRot(a.Roll + b.Roll, a.Pitch + b.Pitch, a.Yaw + b.Yaw); }
|
||||
public static WRot operator -(WRot a, WRot b) { return new WRot(a.Roll - b.Roll, a.Pitch - b.Pitch, a.Yaw - b.Yaw); }
|
||||
public static WRot operator -(WRot a) { return new WRot(-a.Roll, -a.Pitch, -a.Yaw); }
|
||||
|
||||
public static bool operator ==(WRot me, WRot other) { return (me.Roll == other.Roll &&
|
||||
me.Pitch == other.Pitch && me.Yaw == other.Yaw); }
|
||||
public static bool operator !=(WRot me, WRot other) { return !(me == other); }
|
||||
|
||||
public WRot WithYaw(WAngle yaw)
|
||||
{
|
||||
return new WRot(Roll, Pitch, yaw);
|
||||
}
|
||||
|
||||
public int[] AsQuarternion()
|
||||
{
|
||||
// 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();
|
||||
|
||||
// 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
|
||||
};
|
||||
}
|
||||
|
||||
public int[] AsMatrix()
|
||||
{
|
||||
var q = AsQuarternion();
|
||||
|
||||
// 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];
|
||||
|
||||
// Quarternion 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[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;
|
||||
|
||||
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;
|
||||
|
||||
mtx[12] = 0;
|
||||
mtx[13] = 0;
|
||||
mtx[14] = 0;
|
||||
mtx[15] = lsq;
|
||||
|
||||
return mtx;
|
||||
}
|
||||
|
||||
public override int GetHashCode() { return Roll.GetHashCode() ^ Pitch.GetHashCode() ^ Yaw.GetHashCode(); }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return false;
|
||||
|
||||
WRot o = (WRot)obj;
|
||||
return o == this;
|
||||
}
|
||||
|
||||
public override string ToString() { return "{0},{1},{2}".F(Roll, Pitch, Yaw); }
|
||||
}
|
||||
}
|
||||
64
OpenRA.FileFormats/WVec.cs
Normal file
64
OpenRA.FileFormats/WVec.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2013 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenRA
|
||||
{
|
||||
/// <summary>
|
||||
/// 3d World vector for describing offsets and distances - 1024 units = 1 cell.
|
||||
/// </summary>
|
||||
public struct WVec
|
||||
{
|
||||
public readonly int X, Y, Z;
|
||||
|
||||
public WVec(int x, int y, int z) { X = x; Y = y; Z = z; }
|
||||
public WVec(WRange x, WRange y, WRange z) { X = x.Range; Y = y.Range; Z = z.Range; }
|
||||
|
||||
public static readonly WVec Zero = new WVec(0, 0, 0);
|
||||
|
||||
public static WVec operator +(WVec a, WVec b) { return new WVec(a.X + b.X, a.Y + b.Y, a.Z + b.Z); }
|
||||
public static WVec operator -(WVec a, WVec b) { return new WVec(a.X - b.X, a.Y - b.Y, a.Y - b.Y); }
|
||||
public static WVec operator -(WVec a) { return new WVec(-a.X, -a.Y, -a.Z); }
|
||||
|
||||
public static bool operator ==(WVec me, WVec other) { return (me.X == other.X && me.Y == other.Y && me.Z == other.Z); }
|
||||
public static bool operator !=(WVec me, WVec other) { return !(me == other); }
|
||||
|
||||
public static int Dot(WVec a, WVec b) { return a.X * b.X + a.Y * b.Y + a.Z * b.Z; }
|
||||
public int LengthSquared { get { return X * X + Y * Y + Z * Z; } }
|
||||
public int Length { get { return (int)Math.Sqrt(LengthSquared); } }
|
||||
|
||||
public WVec Rotate(WRot rot)
|
||||
{
|
||||
var mtx = rot.AsMatrix();
|
||||
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]));
|
||||
}
|
||||
|
||||
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode(); }
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return false;
|
||||
|
||||
WVec o = (WVec)obj;
|
||||
return o == this;
|
||||
}
|
||||
|
||||
public override string ToString() { return "{0},{1},{2}".F(X, Y, Z); }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user