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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
|
using UnityEngine;
using Unity.Mathematics;
using System.Runtime.CompilerServices;
namespace Pathfinding {
/// <summary>Holds a coordinate in integers</summary>
public struct Int3 : System.IEquatable<Int3> {
public int x;
public int y;
public int z;
//These should be set to the same value (only PrecisionFactor should be 1 divided by Precision)
/// <summary>
/// Precision for the integer coordinates.
/// One world unit is divided into [value] pieces. A value of 1000 would mean millimeter precision, a value of 1 would mean meter precision (assuming 1 world unit = 1 meter).
/// This value affects the maximum coordinates for nodes as well as how large the cost values are for moving between two nodes.
/// A higher value means that you also have to set all penalty values to a higher value to compensate since the normal cost of moving will be higher.
/// </summary>
public const int Precision = 1000;
/// <summary><see cref="Precision"/> as a float</summary>
public const float FloatPrecision = 1000F;
/// <summary>1 divided by <see cref="Precision"/></summary>
public const float PrecisionFactor = 0.001F;
public static Int3 zero => new Int3();
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public Int3 (Vector3 position) {
x = (int)System.Math.Round(position.x*FloatPrecision);
y = (int)System.Math.Round(position.y*FloatPrecision);
z = (int)System.Math.Round(position.z*FloatPrecision);
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public Int3 (int _x, int _y, int _z) {
x = _x;
y = _y;
z = _z;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static bool operator == (Int3 lhs, Int3 rhs) {
return lhs.x == rhs.x &&
lhs.y == rhs.y &&
lhs.z == rhs.z;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static bool operator != (Int3 lhs, Int3 rhs) {
return lhs.x != rhs.x ||
lhs.y != rhs.y ||
lhs.z != rhs.z;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static explicit operator Int3 (Vector3 ob) {
return new Int3(
(int)System.Math.Round(ob.x*FloatPrecision),
(int)System.Math.Round(ob.y*FloatPrecision),
(int)System.Math.Round(ob.z*FloatPrecision)
);
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static explicit operator Vector3 (Int3 ob) {
return new Vector3(ob.x*PrecisionFactor, ob.y*PrecisionFactor, ob.z*PrecisionFactor);
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static explicit operator float3 (Int3 ob) {
return (float3)(int3)ob*PrecisionFactor;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static explicit operator int3 (Int3 ob) {
return new int3(ob.x, ob.y, ob.z);
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static Int3 operator - (Int3 lhs, Int3 rhs) {
lhs.x -= rhs.x;
lhs.y -= rhs.y;
lhs.z -= rhs.z;
return lhs;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static Int3 operator - (Int3 lhs) {
lhs.x = -lhs.x;
lhs.y = -lhs.y;
lhs.z = -lhs.z;
return lhs;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static Int3 operator + (Int3 lhs, Int3 rhs) {
lhs.x += rhs.x;
lhs.y += rhs.y;
lhs.z += rhs.z;
return lhs;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static Int3 operator * (Int3 lhs, int rhs) {
lhs.x *= rhs;
lhs.y *= rhs;
lhs.z *= rhs;
return lhs;
}
public static Int3 operator * (Int3 lhs, float rhs) {
lhs.x = (int)System.Math.Round(lhs.x * rhs);
lhs.y = (int)System.Math.Round(lhs.y * rhs);
lhs.z = (int)System.Math.Round(lhs.z * rhs);
return lhs;
}
public static Int3 operator * (Int3 lhs, double rhs) {
lhs.x = (int)System.Math.Round(lhs.x * rhs);
lhs.y = (int)System.Math.Round(lhs.y * rhs);
lhs.z = (int)System.Math.Round(lhs.z * rhs);
return lhs;
}
public static Int3 operator / (Int3 lhs, float rhs) {
lhs.x = (int)System.Math.Round(lhs.x / rhs);
lhs.y = (int)System.Math.Round(lhs.y / rhs);
lhs.z = (int)System.Math.Round(lhs.z / rhs);
return lhs;
}
public int this[int i] {
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
get {
return i == 0 ? x : (i == 1 ? y : z);
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
set {
if (i == 0) x = value;
else if (i == 1) y = value;
else z = value;
}
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static Int3 Max (Int3 lhs, Int3 rhs) {
return new Int3(System.Math.Max(lhs.x, rhs.x), System.Math.Max(lhs.y, rhs.y), System.Math.Max(lhs.z, rhs.z));
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
public static Int3 Min (Int3 lhs, Int3 rhs) {
return new Int3(System.Math.Min(lhs.x, rhs.x), System.Math.Min(lhs.y, rhs.y), System.Math.Min(lhs.z, rhs.z));
}
/// <summary>Angle between the vectors in radians</summary>
public static float Angle (Int3 lhs, Int3 rhs) {
double cos = Dot(lhs, rhs)/ ((double)lhs.magnitude*(double)rhs.magnitude);
cos = cos < -1 ? -1 : (cos > 1 ? 1 : cos);
return (float)System.Math.Acos(cos);
}
public static int Dot (Int3 lhs, Int3 rhs) {
return
lhs.x * rhs.x +
lhs.y * rhs.y +
lhs.z * rhs.z;
}
public static long DotLong (Int3 lhs, Int3 rhs) {
return
(long)lhs.x * (long)rhs.x +
(long)lhs.y * (long)rhs.y +
(long)lhs.z * (long)rhs.z;
}
/// <summary>
/// Normal in 2D space (XZ).
/// Equivalent to Cross(this, Int3(0,1,0) )
/// except that the Y coordinate is left unchanged with this operation.
/// </summary>
public Int3 Normal2D () {
return new Int3(z, y, -x);
}
/// <summary>
/// Returns the magnitude of the vector. The magnitude is the 'length' of the vector from 0,0,0 to this point. Can be used for distance calculations:
/// <code> Debug.Log ("Distance between 3,4,5 and 6,7,8 is: "+(new Int3(3,4,5) - new Int3(6,7,8)).magnitude); </code>
/// </summary>
public float magnitude {
get {
//It turns out that using doubles is just as fast as using ints with Mathf.Sqrt. And this can also handle larger numbers (possibly with small errors when using huge numbers)!
double _x = x;
double _y = y;
double _z = z;
return (float)System.Math.Sqrt(_x*_x+_y*_y+_z*_z);
}
}
/// <summary>
/// Magnitude used for the cost between two nodes. The default cost between two nodes can be calculated like this:
/// <code> int cost = (node1.position-node2.position).costMagnitude; </code>
///
/// This is simply the magnitude, rounded to the nearest integer
/// </summary>
public int costMagnitude {
get {
return (int)System.Math.Round(magnitude);
}
}
/// <summary>The squared magnitude of the vector</summary>
public float sqrMagnitude {
get {
double _x = x;
double _y = y;
double _z = z;
return (float)(_x*_x+_y*_y+_z*_z);
}
}
/// <summary>The squared magnitude of the vector</summary>
public long sqrMagnitudeLong {
get {
long _x = x;
long _y = y;
long _z = z;
return (_x*_x+_y*_y+_z*_z);
}
}
public static implicit operator string (Int3 obj) {
return obj.ToString();
}
/// <summary>Returns a nicely formatted string representing the vector</summary>
public override string ToString () {
return "( "+x+", "+y+", "+z+")";
}
public override bool Equals (System.Object obj) {
if (!(obj is Int3)) return false;
var rhs = (Int3)obj;
return x == rhs.x &&
y == rhs.y &&
z == rhs.z;
}
#region IEquatable implementation
public bool Equals (Int3 other) {
return x == other.x && y == other.y && z == other.z;
}
#endregion
public override int GetHashCode () {
return x*73856093 ^ y*19349669 ^ z*83492791;
}
}
/// <summary>Two Dimensional Integer Coordinate Pair</summary>
public struct Int2 : System.IEquatable<Int2> {
public int x;
public int y;
public Int2 (int x, int y) {
this.x = x;
this.y = y;
}
public long sqrMagnitudeLong {
get {
return (long)x*(long)x+(long)y*(long)y;
}
}
public static explicit operator int2 (Int2 a) {
return new int2(a.x, a.y);
}
public static Int2 operator - (Int2 lhs) {
lhs.x = -lhs.x;
lhs.y = -lhs.y;
return lhs;
}
public static Int2 operator + (Int2 a, Int2 b) {
return new Int2(a.x+b.x, a.y+b.y);
}
public static Int2 operator - (Int2 a, Int2 b) {
return new Int2(a.x-b.x, a.y-b.y);
}
public static bool operator == (Int2 a, Int2 b) {
return a.x == b.x && a.y == b.y;
}
public static bool operator != (Int2 a, Int2 b) {
return a.x != b.x || a.y != b.y;
}
/// <summary>Dot product of the two coordinates</summary>
public static long DotLong (Int2 a, Int2 b) {
return (long)a.x*(long)b.x + (long)a.y*(long)b.y;
}
public override bool Equals (System.Object o) {
if (!(o is Int2)) return false;
var rhs = (Int2)o;
return x == rhs.x && y == rhs.y;
}
#region IEquatable implementation
public bool Equals (Int2 other) {
return x == other.x && y == other.y;
}
#endregion
public override int GetHashCode () {
return x*49157+y*98317;
}
public static Int2 Min (Int2 a, Int2 b) {
return new Int2(System.Math.Min(a.x, b.x), System.Math.Min(a.y, b.y));
}
public static Int2 Max (Int2 a, Int2 b) {
return new Int2(System.Math.Max(a.x, b.x), System.Math.Max(a.y, b.y));
}
public static Int2 FromInt3XZ (Int3 o) {
return new Int2(o.x, o.z);
}
public static Int3 ToInt3XZ (Int2 o) {
return new Int3(o.x, 0, o.y);
}
public override string ToString () {
return "("+x+", " +y+")";
}
}
}
|