// 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 Vec3 Center;
///
/// The extent of this bounding box.
///
public Vec3 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( Vec3 minimum, Vec3 maximum )
{
this.Center = ( minimum + maximum ) / 2;
this.Extent = ( maximum - minimum ) / 2;
}
///
/// Gets the minimum.
///
/// The minimum.
public Vec3 Minimum
{
get
{
return Center - Extent;
}
}
///
/// Gets the maximum.
///
/// The maximum.
public Vec3 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;
Vec3.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;
}
}
Vec3.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 = Vec3.Max( value1.Maximum, value2.Maximum );
var minimum = Vec3.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 );
}
}
}