1 |
using System; |
2 |
using System.Collections.Generic; |
3 |
|
4 |
namespace Oni |
5 |
{ |
6 |
internal struct BoundingBox : IEquatable<BoundingBox> |
7 |
{ |
8 |
public Vector3 Min; |
9 |
public Vector3 Max; |
10 |
|
11 |
public BoundingBox(Vector3 min, Vector3 max) |
12 |
{ |
13 |
Min = min; |
14 |
Max = max; |
15 |
} |
16 |
|
17 |
public static BoundingBox CreateFromSphere(BoundingSphere sphere) |
18 |
{ |
19 |
var radius = new Vector3(sphere.Radius); |
20 |
|
21 |
return new BoundingBox(sphere.Center - radius, sphere.Center + radius); |
22 |
} |
23 |
|
24 |
public static BoundingBox CreateFromPoints(IEnumerable<Vector3> points) |
25 |
{ |
26 |
var min = new Vector3(float.MaxValue); |
27 |
var max = new Vector3(float.MinValue); |
28 |
|
29 |
foreach (var point in points) |
30 |
{ |
31 |
var p = point; |
32 |
|
33 |
Vector3.Min(ref min, ref p, out min); |
34 |
Vector3.Max(ref max, ref p, out max); |
35 |
} |
36 |
|
37 |
return new BoundingBox(min, max); |
38 |
} |
39 |
|
40 |
public bool Contains(Vector3 point) => |
41 |
point.X >= Min.X && point.X <= Max.X |
42 |
&& point.Y >= Min.Y && point.Y <= Max.Y |
43 |
&& point.Z >= Min.Z && point.Z <= Max.Z; |
44 |
|
45 |
public bool Contains(BoundingBox box) => |
46 |
Min.X <= box.Min.X && box.Max.X <= Max.X |
47 |
&& Min.Y <= box.Min.Y && box.Max.Y <= Max.Y |
48 |
&& Min.Z <= box.Min.Z && box.Max.Z <= Max.Z; |
49 |
|
50 |
public bool Intersects(BoundingBox box) => |
51 |
Max.X >= box.Min.X && Min.X <= box.Max.X |
52 |
&& Max.Y >= box.Min.Y && Min.Y <= box.Max.Y |
53 |
&& Max.Z >= box.Min.Z && Min.Z <= box.Max.Z; |
54 |
|
55 |
public bool Intersects(Plane plane) |
56 |
{ |
57 |
Vector3 v0, v1; |
58 |
|
59 |
v0.X = (plane.Normal.X >= 0.0f) ? Max.X : Min.X; |
60 |
v1.X = (plane.Normal.X >= 0.0f) ? Min.X : Max.X; |
61 |
|
62 |
v0.Y = (plane.Normal.Y >= 0.0f) ? Max.Y : Min.Y; |
63 |
v1.Y = (plane.Normal.Y >= 0.0f) ? Min.Y : Max.Y; |
64 |
|
65 |
v0.Z = (plane.Normal.Z >= 0.0f) ? Max.Z : Min.Z; |
66 |
v1.Z = (plane.Normal.Z >= 0.0f) ? Min.Z : Max.Z; |
67 |
|
68 |
return plane.Normal.Dot(ref v1) <= -plane.D |
69 |
&& plane.Normal.Dot(ref v0) >= -plane.D; |
70 |
} |
71 |
|
72 |
public Vector3[] GetCorners() => new[] |
73 |
{ |
74 |
new Vector3(Min.X, Max.Y, Max.Z), |
75 |
new Vector3(Max.X, Max.Y, Max.Z), |
76 |
new Vector3(Max.X, Min.Y, Max.Z), |
77 |
new Vector3(Min.X, Min.Y, Max.Z), |
78 |
new Vector3(Min.X, Max.Y, Min.Z), |
79 |
new Vector3(Max.X, Max.Y, Min.Z), |
80 |
new Vector3(Max.X, Min.Y, Min.Z), |
81 |
new Vector3(Min.X, Min.Y, Min.Z) |
82 |
}; |
83 |
|
84 |
public static bool operator ==(BoundingBox b1, BoundingBox b2) => b1.Min == b2.Min && b1.Max == b2.Max; |
85 |
public static bool operator !=(BoundingBox b1, BoundingBox b2) => b1.Min != b2.Min || b1.Max != b2.Max; |
86 |
|
87 |
public bool Equals(BoundingBox other) => Min == other.Min && Max == other.Max; |
88 |
|
89 |
public override bool Equals(object obj) => obj is BoundingBox && Equals((BoundingBox)obj); |
90 |
public override int GetHashCode() => Min.GetHashCode() ^ Max.GetHashCode(); |
91 |
|
92 |
public override string ToString() => $"{{{Min} {Max}}}"; |
93 |
|
94 |
public float Volume() |
95 |
{ |
96 |
Vector3 size = Max - Min; |
97 |
return size.X * size.Y * size.Z; |
98 |
} |
99 |
|
100 |
public void Inflate(Vector3 v) |
101 |
{ |
102 |
Min -= v; |
103 |
Max += v; |
104 |
} |
105 |
|
106 |
public float Height => Max.Y - Min.Y; |
107 |
public float Width => Max.X - Min.X; |
108 |
public float Depth => Max.Z - Min.Z; |
109 |
|
110 |
public Vector3 Size => Max - Min; |
111 |
} |
112 |
} |