using System; using System.Collections.Generic; namespace Oni { internal struct BoundingBox : IEquatable { public Vector3 Min; public Vector3 Max; public BoundingBox(Vector3 min, Vector3 max) { Min = min; Max = max; } public static BoundingBox CreateFromSphere(BoundingSphere sphere) { var radius = new Vector3(sphere.Radius); return new BoundingBox(sphere.Center - radius, sphere.Center + radius); } public static BoundingBox CreateFromPoints(IEnumerable points) { var min = new Vector3(float.MaxValue); var max = new Vector3(float.MinValue); foreach (var point in points) { var p = point; Vector3.Min(ref min, ref p, out min); Vector3.Max(ref max, ref p, out max); } return new BoundingBox(min, max); } public bool Contains(Vector3 point) => point.X >= Min.X && point.X <= Max.X && point.Y >= Min.Y && point.Y <= Max.Y && point.Z >= Min.Z && point.Z <= Max.Z; public bool Contains(BoundingBox box) => Min.X <= box.Min.X && box.Max.X <= Max.X && Min.Y <= box.Min.Y && box.Max.Y <= Max.Y && Min.Z <= box.Min.Z && box.Max.Z <= Max.Z; public bool Intersects(BoundingBox box) => Max.X >= box.Min.X && Min.X <= box.Max.X && Max.Y >= box.Min.Y && Min.Y <= box.Max.Y && Max.Z >= box.Min.Z && Min.Z <= box.Max.Z; public bool Intersects(Plane plane) { Vector3 v0, v1; v0.X = (plane.Normal.X >= 0.0f) ? Max.X : Min.X; v1.X = (plane.Normal.X >= 0.0f) ? Min.X : Max.X; v0.Y = (plane.Normal.Y >= 0.0f) ? Max.Y : Min.Y; v1.Y = (plane.Normal.Y >= 0.0f) ? Min.Y : Max.Y; v0.Z = (plane.Normal.Z >= 0.0f) ? Max.Z : Min.Z; v1.Z = (plane.Normal.Z >= 0.0f) ? Min.Z : Max.Z; return plane.Normal.Dot(ref v1) <= -plane.D && plane.Normal.Dot(ref v0) >= -plane.D; } public Vector3[] GetCorners() => new[] { new Vector3(Min.X, Max.Y, Max.Z), new Vector3(Max.X, Max.Y, Max.Z), new Vector3(Max.X, Min.Y, Max.Z), new Vector3(Min.X, Min.Y, Max.Z), new Vector3(Min.X, Max.Y, Min.Z), new Vector3(Max.X, Max.Y, Min.Z), new Vector3(Max.X, Min.Y, Min.Z), new Vector3(Min.X, Min.Y, Min.Z) }; public static bool operator ==(BoundingBox b1, BoundingBox b2) => b1.Min == b2.Min && b1.Max == b2.Max; public static bool operator !=(BoundingBox b1, BoundingBox b2) => b1.Min != b2.Min || b1.Max != b2.Max; public bool Equals(BoundingBox other) => Min == other.Min && Max == other.Max; public override bool Equals(object obj) => obj is BoundingBox && Equals((BoundingBox)obj); public override int GetHashCode() => Min.GetHashCode() ^ Max.GetHashCode(); public override string ToString() => $"{{{Min} {Max}}}"; public float Volume() { Vector3 size = Max - Min; return size.X * size.Y * size.Z; } public void Inflate(Vector3 v) { Min -= v; Max += v; } public float Height => Max.Y - Min.Y; public float Width => Max.X - Min.X; public float Depth => Max.Z - Min.Z; public Vector3 Size => Max - Min; } }