Indexof

IndexofOptimizing OBB SAT Collision Detection with Pre-Scaled Basis Vectors › Last update: Mar 17, 2026@bheytehAbout › #OptimizingOBBSATCollisionDetection

The Precision Edge: OBB SAT Test Using Pre-Scaled Basis Vectors

In the high-performance landscape of 2026 physics engines, collision detection efficiency is measured in nanoseconds. The Separating Axis Theorem (SAT) remains the industry standard for detecting intersections between convex shapes, specifically Oriented Bounding Boxes (OBB). However, the traditional approach involves frequent normalization and scalar-vector multiplications that can bog down the CPU. By utilizing pre-scaled basis vectors—where the box's orientation axes already incorporate the half-extents—we can eliminate multiple square root operations and divisions during the overlap test. This tutorial explores the mathematical transition from unit-vector SAT to pre-scaled SAT, providing a streamlined path for modern game physics implementation.

Table of Content

Purpose

Traditional SAT requires 15 axis tests for two OBBs (3 face normals of A, 3 face normals of B, and 9 cross products). Using pre-scaled basis vectors serves to:

  • Eliminate Half-Extent Lookups: By baking the box dimensions into the basis vectors, you reduce memory fetches.
  • Simplify Projection Math: The projection radius of a box onto an axis becomes a simple sum of absolute dot products without explicit multiplication by extents.
  • Improve Cache Locality: Storing scaled axes as a single matrix-like structure speeds up the iterative testing process.

The Logic: Dot Products and Scaled Projections

Standard SAT defines an OBB by a center $C$, unit axes $u_x, u_y, u_z$, and half-extents $e_x, e_y, e_z$. The "Pre-Scaled" approach replaces these with three vectors:

$A_0 = u_x \times e_x$, $A_1 = u_y \times e_y$, and $A_2 = u_z \times e_z$.

When projecting Box A onto an axis $L$, the radius $R_a$ is simply: $R_a = |A_0 \cdot L| + |A_1 \cdot L| + |A_2 \cdot L|$. This removes the need to store or multiply by $e_i$ during the 15-axis loop, as the magnitude of the axis itself carries the "size" of the box.

Step-by-Step

1. Data Structure Setup

Define your OBB using the center and the pre-scaled axes. Ensure these axes are updated only when the object's transform or scale changes.

struct ScaledOBB {
    Vector3 center;
    Vector3 axes[3]; // Pre-multiplied: axis  halfExtent
};

2. Generate the Rotation Matrix

To test Box A against Box B, you need the relative orientation. Calculate the dot products between the unit versions of the axes to build a $3 \times 3$ rotation matrix $R$, where $R_{ij} = uA_i \cdot uB_j$.

3. Test the 6 Face Normals

Test the axes of Box A and Box B. For each axis $L$:

  1. Calculate the projection radius $R_a$ and $R_b$.
  2. Calculate the distance between centers $D = |(CenterB - CenterA) \cdot L|$.
  3. If $D > R_a + R_b$, return False (No Collision).

4. Test the 9 Cross Products

Test the axes formed by $L = A_i \times B_j$. Note: With pre-scaled vectors, you must be careful with the magnitude of $L$. If the cross product results in a near-zero vector (parallel axes), skip that specific test to avoid floating-point errors.

Use Case

A developer is creating a high-speed racing game where hundreds of debris pieces (OBB colliders) are scattered across the track.

  • The Action: The physics engine performs thousands of narrow-phase checks per frame.
  • The Implementation: By using pre-scaled basis vectors, the developer reduces the per-test instruction count by approximately 20%.
  • The Result: The game maintains a stable 144 FPS even during multi-car pileups, as the SAT overhead is minimized.

Best Results

Optimization Traditional SAT Pre-Scaled SAT
Arithmetic Extent multiplications in loop Baked into basis
Normalization Required for axis logic Deferred or minimized
Cross Products Standard $u \times v$ Scaled $A \times B$ (Watch precision)
SIMD Friendly Moderate High (Vectorized Dot Products)

FAQ

Does this handle non-uniform scaling?

Yes. Because the half-extents are baked into the basis vectors, non-uniform scaling of the GameObject is naturally represented by the length of $A_0, A_1,$ and $A_2$.

Why skip the cross product if axes are parallel?

If two axes are parallel, their cross product is a zero vector. Attempting to project onto a zero vector will result in $D=0, R=0$, which fails the separation test and can lead to "false positives" in collision detection.

Is this faster than AABB?

No. AABB (Axis-Aligned Bounding Box) is always faster because it only tests 3 fixed axes. OBB SAT is used only when objects are rotated and require tighter collision bounds than an AABB can provide.

Disclaimer

Pre-scaling basis vectors can lead to very large or very small values in the cross-product phase if the boxes have extreme size differences. This can cause floating-point precision issues (catastrophic cancellation). Always implement an epsilon check when computing cross-product axes. This tutorial assumes a standard right-handed coordinate system. March 2026.

Tags: CollisionDetection, PhysicsEngine, SATAlgorithm, OBBColliders



What’s new

Close [x]
Loading special offers...