/// <summary> /// Creates an <see cref="OrientedBoundingBox">OrientedBoundingBox</see> from a <see cref="BoundingBox">BoundingBox</see>. /// </summary> /// <param name="box">A <see cref="BoundingBox">BoundingBox</see> to create the <see cref="OrientedBoundingBox">OrientedBoundingBox</see> from</param> /// <returns>The generated <see cref="OrientedBoundingBox">OrientedBoundingBox</see></returns> public static OrientedBoundingBox FromAABB(BoundingBox box) { var center = BoundingVolumesExtensions.GetCenter(box); var extents = BoundingVolumesExtensions.GetExtents(box); return(new OrientedBoundingBox(center, extents)); }
/// <summary> /// Calculates an OBB with a given set of points. /// Tests every orientations between initValues and endValues, stepping through angle intervals with a given step size. /// Goes on until it reaches a step less than 0.01 /// </summary> /// <returns>A generated Oriented Bounding Box that contains the set of points</returns> private static OrientedBoundingBox ComputeFromPointsRecursive(Vector3[] points, Vector3 initValues, Vector3 endValues, float step) { var minObb = new OrientedBoundingBox(); var minimumVolume = float.MaxValue; var minInitValues = Vector3.Zero; var minEndValues = Vector3.Zero; var transformedPoints = new Vector3[points.Length]; float y, z; var x = initValues.X; while (x <= endValues.X) { y = initValues.Y; var rotationX = MathHelper.ToRadians(x); while (y <= endValues.Y) { z = initValues.Z; var rotationY = MathHelper.ToRadians(y); while (z <= endValues.Z) { // Rotation matrix var rotationZ = MathHelper.ToRadians(z); var rotationMatrix = Matrix.CreateFromYawPitchRoll(rotationY, rotationX, rotationZ); // Transform every point to OBB-Space for (var index = 0; index < transformedPoints.Length; index++) { transformedPoints[index] = Vector3.Transform(points[index], rotationMatrix); } // Obtain an AABB enclosing every transformed point var aabb = BoundingBox.CreateFromPoints(transformedPoints); // Calculate the volume of the AABB var volume = BoundingVolumesExtensions.GetVolume(aabb); // Find lesser volume if (volume < minimumVolume) { minimumVolume = volume; minInitValues = new Vector3(x, y, z); minEndValues = new Vector3(x + step, y + step, z + step); // Restore the AABB center in World-Space var center = BoundingVolumesExtensions.GetCenter(aabb); center = Vector3.Transform(center, rotationMatrix); // Create OBB minObb = new OrientedBoundingBox(center, BoundingVolumesExtensions.GetExtents(aabb)); minObb.Orientation = rotationMatrix; } z += step; } y += step; } x += step; } // Loop again if the step is higher than a given acceptance threshold if (step > 0.01f) { minObb = ComputeFromPointsRecursive(points, minInitValues, minEndValues, step / 10f); } return(minObb); }