Struct OBB3D
Oriented 3D bounding box represented as Center + HalfExtents + Rotation. Use this for tight bounds on rotated meshes, rotated trigger volumes, or any "box that does not sit on world axes" use case. Intersection tests use the Separating Axis Theorem.
Implements
Inherited Members
Namespace: Scylla.Core.Util.Geom
Assembly: ScyllaCore.dll
Syntax
[Serializable]
public struct OBB3D : IEquatable<OBB3D>
Remarks
HalfExtents are measured in the box's own local frame (before the rotation is applied). Rotation describes how that local frame is oriented in world space. Setting Rotation to UnityEngine.Quaternion.identity produces a box that behaves identically to an AABB3D with the same center and half-extents.
HalfExtents components are expected to be non-negative. Behaviour with negative half-extents is undefined.
Equality comparisons use Approximately(float, float, float) for each component of Center, HalfExtents, and Rotation, so two boxes that differ only by floating-point rounding are considered equal.
For broad-phase culling, convert this box to its enclosing AABB3D via ToAABB3D() and test that first before running the full 15-axis SAT.
Constructors
OBB3D(Vector3, Vector3, Quaternion)
Initializes a new OBB3D with the supplied center, half-extents, and rotation.
Declaration
public OBB3D(Vector3 center, Vector3 halfExtents, Quaternion rotation)
Parameters
| Type | Name | Description |
|---|---|---|
| Vector3 | center | The box center in world space. |
| Vector3 | halfExtents | Half-extents in the box's local frame before rotation. Each component should be non-negative. |
| Quaternion | rotation | The orientation of the box. Pass UnityEngine.Quaternion.identity for an axis-aligned box. |
Fields
Center
Center of the box in world space.
Declaration
[SerializeField]
public Vector3 Center
Field Value
| Type | Description |
|---|---|
| Vector3 |
HalfExtents
Half-extents of the box measured in its own local (pre-rotation) coordinate frame. Each component should be non-negative.
Declaration
[SerializeField]
public Vector3 HalfExtents
Field Value
| Type | Description |
|---|---|
| Vector3 |
Rotation
The orientation of the box expressed as a quaternion that rotates from the box's local frame into world space. UnityEngine.Quaternion.identity reduces this oriented box to an axis-aligned one equivalent to AABB3D.
Declaration
[SerializeField]
public Quaternion Rotation
Field Value
| Type | Description |
|---|---|
| Quaternion |
Properties
AxisX
The world-space unit direction of the box's local X axis, computed by rotating UnityEngine.Vector3.right by Rotation.
Declaration
public readonly Vector3 AxisX { get; }
Property Value
| Type | Description |
|---|---|
| Vector3 |
AxisY
The world-space unit direction of the box's local Y axis, computed by rotating UnityEngine.Vector3.up by Rotation.
Declaration
public readonly Vector3 AxisY { get; }
Property Value
| Type | Description |
|---|---|
| Vector3 |
AxisZ
The world-space unit direction of the box's local Z axis, computed by rotating UnityEngine.Vector3.forward by Rotation.
Declaration
public readonly Vector3 AxisZ { get; }
Property Value
| Type | Description |
|---|---|
| Vector3 |
Size
The full size of the box along each of its local axes, equal to
HalfExtents * 2.
Declaration
public readonly Vector3 Size { get; }
Property Value
| Type | Description |
|---|---|
| Vector3 |
SurfaceArea
The total surface area of the box, in square world units, computed as
2 * (wh + hd + d*w) where w, h, and d are the
box's local-axis extents.
Declaration
public readonly float SurfaceArea { get; }
Property Value
| Type | Description |
|---|---|
| float |
Volume
The total volume enclosed by the box, in cubic world units, computed as
Size.x * Size.y * Size.z.
Declaration
public readonly float Volume { get; }
Property Value
| Type | Description |
|---|---|
| float |
Methods
ClosestPoint(Vector3)
Returns the closest point on or inside the box to point. If
point is already inside the box, it is returned unchanged.
Declaration
public readonly Vector3 ClosestPoint(Vector3 point)
Parameters
| Type | Name | Description |
|---|---|---|
| Vector3 | point | The query point in world space. |
Returns
| Type | Description |
|---|---|
| Vector3 | The nearest point on or inside this oriented box to |
Remarks
The implementation uses an explicit per-component absolute comparison to detect
interior points rather than comparing the clamped and original local-space
vectors via Vector3 ==. Unity's Vector3 equality uses a fixed
1e-5 tolerance, which can misclassify interior points that are very
close to a face after non-trivial quaternion operations accumulate rounding
error, causing Distance(Vector3) to return a small positive value instead
of zero for genuinely interior points.
Contains(Vector3)
Returns true if point is inside or exactly on the
surface of this box. The test is performed in the box's local frame.
Declaration
public readonly bool Contains(Vector3 point)
Parameters
| Type | Name | Description |
|---|---|---|
| Vector3 | point | The world-space point to test. |
Returns
| Type | Description |
|---|---|
| bool |
|
Distance(Vector3)
Returns the Euclidean distance from point to the nearest surface
point of the box. Returns zero if point is inside or touching
the box.
Declaration
public readonly float Distance(Vector3 point)
Parameters
| Type | Name | Description |
|---|---|---|
| Vector3 | point | The query point in world space. |
Returns
| Type | Description |
|---|---|
| float | A non-negative distance in world units. Zero indicates the point is on or inside the box. |
Equals(OBB3D)
Returns true if this box and other are approximately
equal, comparing each component of Center, HalfExtents,
and Rotation using
Approximately(float, float, float).
Declaration
public readonly bool Equals(OBB3D other)
Parameters
| Type | Name | Description |
|---|---|---|
| OBB3D | other | The box to compare against. |
Returns
| Type | Description |
|---|---|
| bool |
|
Equals(object)
Declaration
public override bool Equals(object obj)
Parameters
| Type | Name | Description |
|---|---|---|
| object | obj |
Returns
| Type | Description |
|---|---|
| bool |
Overrides
FromAABB(in AABB3D)
Creates an OBB3D from an AABB3D using identity rotation, producing an axis-aligned oriented box with the same center and half-extents.
Declaration
public static OBB3D FromAABB(in AABB3D box)
Parameters
| Type | Name | Description |
|---|---|---|
| AABB3D | box | The axis-aligned source box. |
Returns
| Type | Description |
|---|---|
| OBB3D | An OBB3D with the same center and half-extents as |
FromAABB(in AABB3D, Quaternion)
Creates an OBB3D from an AABB3D and a custom rotation, reusing the AABB's center and half-extents but applying the supplied orientation.
Declaration
public static OBB3D FromAABB(in AABB3D box, Quaternion rotation)
Parameters
| Type | Name | Description |
|---|---|---|
| AABB3D | box | The axis-aligned source box whose center and half-extents are used. |
| Quaternion | rotation | The desired orientation of the new OBB. |
Returns
| Type | Description |
|---|---|
| OBB3D | An OBB3D with the same center and half-extents as |
GetCorner(int)
Returns one of the eight corner points of this box in world space. The
index encoding matches GetCorner(int): bit 0
selects the positive-X half-extent, bit 1 the positive-Y half-extent, and bit 2
the positive-Z half-extent. Valid indices are in the range [0, 7].
Declaration
public readonly Vector3 GetCorner(int index)
Parameters
| Type | Name | Description |
|---|---|---|
| int | index | A value from 0 to 7 that bit-encodes which corner to retrieve. Bit 0: local X axis sign (0 = negative, 1 = positive). Bit 1: local Y axis sign. Bit 2: local Z axis sign. |
Returns
| Type | Description |
|---|---|
| Vector3 | The world-space position of the selected corner. |
GetHashCode()
Declaration
public override int GetHashCode()
Returns
| Type | Description |
|---|---|
| int |
Overrides
Intersects(in AABB3D)
Returns true if this oriented box overlaps the axis-aligned box
box. Internally promotes box to an
OBB3D with identity rotation and delegates to
Intersects(in OBB3D).
Declaration
public readonly bool Intersects(in AABB3D box)
Parameters
| Type | Name | Description |
|---|---|---|
| AABB3D | box | The axis-aligned box to test against. |
Returns
| Type | Description |
|---|---|
| bool |
|
Intersects(in OBB3D)
Returns true if this oriented box overlaps other. Uses
the full 15-axis Separating Axis Theorem: 3 face-normal axes from this box, 3
face-normal axes from other, and 9 cross-product axes (one per
pair of local axes from the two boxes).
Declaration
public readonly bool Intersects(in OBB3D other)
Parameters
| Type | Name | Description |
|---|---|---|
| OBB3D | other | The oriented box to test against. |
Returns
| Type | Description |
|---|---|
| bool |
|
Remarks
Cross-product axes whose squared magnitude is below Mathf.Epsilon are
skipped; this correctly handles parallel or near-parallel face pairs where the
cross product is degenerate (near-zero vector).
The two 3-element axis frames are stack-allocated to avoid per-call heap allocations that would otherwise fire on every intersection test.
For a cheaper first-pass rejection, call ToAABB3D() on both boxes and use Intersects(in AABB3D) before calling this method.
LocalToWorld(Vector3)
Converts a point from the box's local coordinate frame back into world space. This is the inverse of WorldToLocal(Vector3).
Declaration
public readonly Vector3 LocalToWorld(Vector3 localPoint)
Parameters
| Type | Name | Description |
|---|---|---|
| Vector3 | localPoint | A point in the box's local frame to transform. |
Returns
| Type | Description |
|---|---|
| Vector3 | The equivalent world-space position. |
ToAABB3D()
Computes and returns the smallest axis-aligned bounding box that fully encloses this oriented box. Useful for broad-phase culling before performing the more expensive SAT-based Intersects(in OBB3D) test.
Declaration
public readonly AABB3D ToAABB3D()
Returns
| Type | Description |
|---|---|
| AABB3D | An AABB3D that encloses all eight world-space corners of this box. The result is always a conservative (potentially oversized) enclosure; it is exact only when Rotation is identity. |
Remarks
All eight corners are stack-allocated and fed into FromPoints(ReadOnlySpan<Vector3>) to avoid any heap allocation.
ToString()
Returns a human-readable string representation of this box in the format
OBB3D[Center=(x,y,z), HalfExtents=(x,y,z), Rotation=(ex,ey,ez)] where
rotation is expressed as Euler angles in degrees.
Declaration
public override string ToString()
Returns
| Type | Description |
|---|---|
| string | A formatted string describing the box's center, half-extents, and orientation. |
Overrides
WorldToLocal(Vector3)
Converts a world-space point into the box's local coordinate frame. The result is
relative to the box center and oriented along the box's local axes, so a point on
the +X face of the box maps to approximately (HalfExtents.x, 0, 0).
Declaration
public readonly Vector3 WorldToLocal(Vector3 worldPoint)
Parameters
| Type | Name | Description |
|---|---|---|
| Vector3 | worldPoint | The point in world space to transform. |
Returns
| Type | Description |
|---|---|
| Vector3 | The point expressed in the box's local coordinate frame. |
Operators
operator ==(OBB3D, OBB3D)
Approximate equality operator. Delegates to Equals(OBB3D); two boxes that differ only by floating-point rounding are considered equal.
Declaration
public static bool operator ==(OBB3D left, OBB3D right)
Parameters
| Type | Name | Description |
|---|---|---|
| OBB3D | left | The left operand. |
| OBB3D | right | The right operand. |
Returns
| Type | Description |
|---|---|
| bool |
|
operator !=(OBB3D, OBB3D)
Approximate inequality operator. Returns the negation of operator ==(OBB3D, OBB3D).
Declaration
public static bool operator !=(OBB3D left, OBB3D right)
Parameters
| Type | Name | Description |
|---|---|---|
| OBB3D | left | The left operand. |
| OBB3D | right | The right operand. |
Returns
| Type | Description |
|---|---|
| bool |
|