// Copyright (c) Xenko contributors (https://xenko.com) and Silicon Studio Corp. (https://www.siliconstudio.co.jp) // Distributed under the MIT license. See the LICENSE.md file in the project root for more information. using System; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; namespace math { /// /// Represents an axis-aligned bounding box in three dimensional space that store only the Center and Extent. /// [DataContract] [StructLayout(LayoutKind.Sequential, Pack = 4)] public struct BoundingBoxExt : IEquatable { /// /// A which represents an empty space. /// public static readonly BoundingBoxExt Empty = new BoundingBoxExt(BoundingBox.Empty); /// /// The center of this bounding box. /// public Vector3 Center; /// /// The extent of this bounding box. /// public Vector3 Extent; /// /// Initializes a new instance of the struct. /// /// The box. public BoundingBoxExt(BoundingBox box) { this.Center = box.Center; this.Extent = box.Extent; } /// /// Initializes a new instance of the struct. /// /// The minimum vertex of the bounding box. /// The maximum vertex of the bounding box. public BoundingBoxExt(Vector3 minimum, Vector3 maximum) { this.Center = (minimum + maximum) / 2; this.Extent = (maximum - minimum) / 2; } /// /// Gets the minimum. /// /// The minimum. public Vector3 Minimum { get { return Center - Extent; } } /// /// Gets the maximum. /// /// The maximum. public Vector3 Maximum { get { return Center + Extent; } } /// /// Transform this Bounding box /// /// The transform to apply to the bounding box. public void Transform(Matrix world) { // http://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/ // Compute transformed AABB (by world) var center = Center; var extent = Extent; Vector3.TransformCoordinate(ref center, ref world, out Center); // Update world matrix into absolute form unsafe { // Perform an abs on the matrix var matrixData = (float*)&world; for (int j = 0; j < 16; ++j) { //*matrixData &= 0x7FFFFFFF; *matrixData = Math.Abs(*matrixData); ++matrixData; } } Vector3.TransformNormal(ref extent, ref world, out Extent); } /// /// Constructs a that is as large as the total combined area of the two specified boxes. /// /// The first box to merge. /// The second box to merge. /// When the method completes, contains the newly constructed bounding box. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Merge(ref BoundingBoxExt value1, ref BoundingBoxExt value2, out BoundingBoxExt result) { var maximum = Vector3.Max(value1.Maximum, value2.Maximum); var minimum = Vector3.Min(value1.Minimum, value2.Minimum); result.Center = (minimum + maximum) / 2; result.Extent = (maximum - minimum) / 2; } /// public bool Equals(BoundingBoxExt other) { return Center.Equals(other.Center) && Extent.Equals(other.Extent); } /// public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; return obj is BoundingBoxExt && Equals((BoundingBoxExt)obj); } /// public override int GetHashCode() { unchecked { return (Center.GetHashCode() * 397) ^ Extent.GetHashCode(); } } /// /// Implements the ==. /// /// The left. /// The right. /// The result of the operator. public static bool operator ==(BoundingBoxExt left, BoundingBoxExt right) { return left.Equals(right); } /// /// Implements the !=. /// /// The left. /// The right. /// The result of the operator. public static bool operator !=(BoundingBoxExt left, BoundingBoxExt right) { return !left.Equals(right); } /// /// Performs an explicit conversion from to . /// /// The bb ext. /// The result of the conversion. public static explicit operator BoundingBox(BoundingBoxExt bbExt) { return new BoundingBox(bbExt.Minimum, bbExt.Maximum); } /// /// Performs an explicit conversion from to . /// /// The bounding box. /// The result of the conversion. public static explicit operator BoundingBoxExt(BoundingBox boundingBox) { return new BoundingBoxExt(boundingBox); } } }