Skip to content

Game.Rendering.FrustumPlanes

Assembly: Assembly-CSharp (in-game)
Namespace: Game.Rendering

Type: struct

Base: System.ValueType

Summary:
FrustumPlanes is a SIMD-optimized helper for frustum culling. It packs UnityEngine.Plane data into a Structure-Of-Arrays (SOA) layout (PlanePacket4) using Unity.Mathematics float4 types, and provides a set of intersection tests against AABBs and spheres. The API is designed for high-performance culling (including usage from unsafe/job contexts) and can produce inclusion/exclusion masks for up to 64 planes (two 32-bit masks packed into a 64-bit ulong) or shorter masks as uints.


Fields

  • public enum IntersectResult
    Enum with results for a coarse intersect test:
  • Out — fully outside
  • In — fully inside
  • Partial — partially overlapping

  • public struct PlanePacket4
    SOA packet holding 4 planes in SIMD-friendly layout:

  • float4 Xs — plane normals' x components
  • float4 Ys — plane normals' y components
  • float4 Zs — plane normals' z components
  • float4 Distances — plane distances (plane.distance)

Properties

  • None (type exposes only nested types and static methods)

Constructors

  • public FrustumPlanes()
    No explicit constructor provided in source. As a struct it has the default parameterless constructor and the type contains only static methods/ nested types — no per-instance state to initialize.

Methods

  • public static int GetPacketCount(int cullingPlaneCount)
    Returns number of PlanePacket4 packets required to store cullingPlaneCount planes. Calculation: (cullingPlaneCount + 3) >> 2.

  • public static void BuildSOAPlanePackets(NativeArray<Plane> cullingPlanes, int cullingPlaneCount, NativeList<PlanePacket4> result)
    Packs planes from a NativeArray into a NativeList (SOA). The result list is resized to packetCount. Any remaining slots (to fill the last packet to 4) are filled with a sentinel plane (normal = (1,0,0), distance = 1e9) to avoid false culling.

  • private static float4 dot4(float4 xs, float4 ys, float4 zs, float4 mx, float4 my, float4 mz)
    Helper performing element-wise dot product for four lanes: xsmx + ysmy + zs*mz. Used internally by the intersection routines.

  • public unsafe static IntersectResult CalculateIntersectResult(PlanePacket4* cullingPlanePackets, int length, float3 center, float3 extents)
    Coarse test (per-packet) against an oriented AABB (center + extents). Returns IntersectResult.Out / Partial / In. length is the number of PlanePacket4 packets. Uses SIMD operations over float4 lanes.

  • public unsafe static void Intersect(PlanePacket4* cullingPlanePackets, int length, float3 center, float3 extents, out ulong inMask, out ulong outMask)
    Computes bitmasks indicating which planes classify the box as fully inside (inMask) or fully outside (outMask). Masks are returned in a 64-bit quantity where lower 32 bits correspond to first up-to-8 packets (packed 4 planes per packet) and upper 32 bits to the subsequent packets — designed to represent up to 64 planes. The function processes the first up-to-8 packets differently to optimize packing.

  • public unsafe static bool Intersect(PlanePacket4* cullingPlanePackets, int length, float3 center, float3 extents)
    Boolean test whether an AABB intersects (not completely outside) the frustum. Returns true if not culled.

  • public unsafe static bool Intersect(PlanePacket4* cullingPlanePackets, int length, float3 center, float radius)
    Boolean sphere-frustum intersection. Returns true if sphere not completely outside.

  • public unsafe static void Intersect(PlanePacket4* cullingPlanePackets, int length, float3 center, float3 extents, out ulong outMask)
    Produces an outMask (ulong) where set bits mark planes that fully exclude the AABB (similar packing as the two-mask variant but only outMask is returned).

  • public unsafe static void Intersect(PlanePacket4* cullingPlanePackets, int length, float3 center, float radius, out ulong outMask)
    Sphere version that produces an outMask (ulong) for exclusion.

  • public unsafe static void Intersect(PlanePacket4* cullingPlanePackets, int length, float3 center, float3 extents, out uint outMask)
    Produces a 32-bit outMask for up to 32 planes (one bit per plane/slot). Useful when total plane count ≤ 32.

  • public unsafe static void Intersect(PlanePacket4* cullingPlanePackets, int length, float3 center, float radius, out uint outMask)
    Sphere version returning 32-bit outMask.

Remarks and implementation details: - The code works on PlanePacket4 packets where each packet holds up to 4 planes. Plane indexes map to bits in masks as packets are processed; the code shifts a 4-bit pattern by 4 each packet to assign the proper bit positions. - BuildSOAPlanePackets fills unused lanes with a sentinel plane (1,0,0, 1e9) to avoid accidental inclusion/exclusion for incomplete final packets. - Methods that take PlanePacket4* are unsafe and expect pinned/contiguous memory (e.g., obtained from NativeList.GetUnsafePtr()). length is the number of packets (use GetPacketCount to compute). - Uses Unity.Mathematics types (float3/float4/int4/uint4) and math functions; ensure Unity.Mathematics is available and compatible with the job/allocator context you call from. - Many overloads exist to support different return mask sizes and shape types (box vs sphere).

Usage Example

// Example: build plane packets from a NativeArray<Plane> and perform an AABB test.
// Note: Requires Unity.Collections and Unity.Mathematics, and unsafe context to get pointer.

using Unity.Collections;
using Unity.Mathematics;
using UnityEngine;
using Game.Rendering;
using System.Runtime.InteropServices;

// Prepare planes (e.g., camera frustum planes)
NativeArray<Plane> planes = new NativeArray<Plane>(/*planeCount*/, Allocator.Temp);
// ... fill planes ...
int planeCount = /* actual plane count */;

// Build SOA packets
var packets = new NativeList<FrustumPlanes.PlanePacket4>(Allocator.Temp);
int packetCount = FrustumPlanes.GetPacketCount(planeCount);
FrustumPlanes.BuildSOAPlanePackets(planes, planeCount, packets);

// AABB to test
float3 center = new float3(0f, 0f, 0f);
float3 extents = new float3(1f, 2f, 1f);

// Perform intersect test (unsafe pointer required)
ulong inMask, outMask;
unsafe
{
    fixed (FrustumPlanes.PlanePacket4* ptr = packets.GetUnsafeReadOnlyPtr())
    {
        FrustumPlanes.Intersect(ptr, packetCount, center, extents, out inMask, out outMask);
    }
}

// inMask/outMask can be inspected to decide per-plane inclusion/exclusion
packets.Dispose();
planes.Dispose();

If you want, I can also provide: - A small helper to convert Camera.CalculateFrustumPlanes(Camera) into a NativeArray and call BuildSOAPlanePackets. - A safe wrapper (no unsafe) that uses NativeList.GetUnsafeReadOnlyPtr() with Unity.Collections.LowLevel.Unsafe functions (requires proper safety handles).