-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Basis25D.cs
207 lines (187 loc) · 5.73 KB
/
Basis25D.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
using Godot;
using System;
using System.Runtime.InteropServices;
#if GODOT_REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
/// <summary>
/// Basis25D structure for performing 2.5D transform math.
/// Note: All code assumes that Y is UP in 3D, and DOWN in 2D.
/// A top-down view has a Y axis component of (0, 0), with a Z axis component of (0, 1).
/// For a front side view, Y is (0, -1) and Z is (0, 0).
/// Remember that Godot's 2D mode has the Y axis pointing DOWN on the screen.
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Basis25D : IEquatable<Basis25D>
{
// Also matrix columns, the directions to move on screen for each unit change in 3D.
public Vector2 x;
public Vector2 y;
public Vector2 z;
// Also matrix rows, the parts of each vector that contribute to moving in a screen direction.
// Setting a row to zero means no movement in that direction.
public Vector3 Row0
{
get { return new Vector3(x.x, y.x, z.x); }
set
{
x.x = value.x;
y.x = value.y;
z.x = value.z;
}
}
public Vector3 Row1
{
get { return new Vector3(x.y, y.y, z.y); }
set
{
x.y = value.x;
y.y = value.y;
z.y = value.z;
}
}
public Vector2 this[int columnIndex]
{
get
{
switch (columnIndex)
{
case 0: return x;
case 1: return y;
case 2: return z;
default: throw new IndexOutOfRangeException();
}
}
set
{
switch (columnIndex)
{
case 0: x = value; return;
case 1: y = value; return;
case 2: z = value; return;
default: throw new IndexOutOfRangeException();
}
}
}
public real_t this[int columnIndex, int rowIndex]
{
get
{
return this[columnIndex][rowIndex];
}
set
{
Vector2 v = this[columnIndex];
v[rowIndex] = value;
this[columnIndex] = v;
}
}
private static readonly Basis25D _topDown = new Basis25D(1, 0, 0, 0, 0, 1);
private static readonly Basis25D _frontSide = new Basis25D(1, 0, 0, -1, 0, 0);
private static readonly Basis25D _fortyFive = new Basis25D(1, 0, 0, -0.70710678118f, 0, 0.70710678118f);
private static readonly Basis25D _isometric = new Basis25D(0.86602540378f, 0.5f, 0, -1, -0.86602540378f, 0.5f);
private static readonly Basis25D _obliqueY = new Basis25D(1, 0, -0.70710678118f, -0.70710678118f, 0, 1);
private static readonly Basis25D _obliqueZ = new Basis25D(1, 0, 0, -1, -0.70710678118f, 0.70710678118f);
public static Basis25D TopDown { get { return _topDown; } }
public static Basis25D FrontSide { get { return _frontSide; } }
public static Basis25D FortyFive { get { return _fortyFive; } }
public static Basis25D Isometric { get { return _isometric; } }
public static Basis25D ObliqueY { get { return _obliqueY; } }
public static Basis25D ObliqueZ { get { return _obliqueZ; } }
/// <summary>
/// Creates a Dimetric Basis25D from the angle between the Y axis and the others.
/// Dimetric(Tau/3) or Dimetric(2.09439510239) is the same as Isometric.
/// Try to keep this number away from a multiple of Tau/4 (or Pi/2) radians.
/// </summary>
/// <param name="angle">The angle, in radians, between the Y axis and the X/Z axes.</param>
public static Basis25D Dimetric(real_t angle)
{
real_t sin = Mathf.Sin(angle);
real_t cos = Mathf.Cos(angle);
return new Basis25D(sin, -cos, 0, -1, -sin, -cos);
}
// Constructors
public Basis25D(Basis25D b)
{
x = b.x;
y = b.y;
z = b.z;
}
public Basis25D(Vector2 xAxis, Vector2 yAxis, Vector2 zAxis)
{
x = xAxis;
y = yAxis;
z = zAxis;
}
public Basis25D(real_t xx, real_t xy, real_t yx, real_t yy, real_t zx, real_t zy)
{
x = new Vector2(xx, xy);
y = new Vector2(yx, yy);
z = new Vector2(zx, zy);
}
public static Basis25D operator *(Basis25D b, real_t s)
{
b.x *= s;
b.y *= s;
b.z *= s;
return b;
}
public static Basis25D operator /(Basis25D b, real_t s)
{
b.x /= s;
b.y /= s;
b.z /= s;
return b;
}
public static bool operator ==(Basis25D left, Basis25D right)
{
return left.Equals(right);
}
public static bool operator !=(Basis25D left, Basis25D right)
{
return !left.Equals(right);
}
public override bool Equals(object obj)
{
if (obj is Basis25D)
{
return Equals((Basis25D)obj);
}
return false;
}
public bool Equals(Basis25D other)
{
return x.Equals(other.x) && y.Equals(other.y) && z.Equals(other.z);
}
public bool IsEqualApprox(Basis25D other)
{
return x.IsEqualApprox(other.x) && y.IsEqualApprox(other.y) && z.IsEqualApprox(other.z);
}
public override int GetHashCode()
{
return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode();
}
public override string ToString()
{
string s = String.Format("({0}, {1}, {2})", new object[]
{
x.ToString(),
y.ToString(),
z.ToString()
});
return s;
}
public string ToString(string format)
{
string s = String.Format("({0}, {1}, {2})", new object[]
{
x.ToString(format),
y.ToString(format),
z.ToString(format)
});
return s;
}
}