Class ScyllaBVH
Managed Bounding Volume Hierarchy (BVH) wrapper providing convenient, validated access to spatial queries.
Inherited Members
Namespace: Scylla.Core.Structures
Assembly: ScyllaCore.dll
Syntax
public sealed class ScyllaBVH : IScyllaCollection, IDisposable
Remarks
This is the recommended high-level interface for using the BVH system in most scenarios. It wraps ScyllaBVHCore and provides additional safety and convenience features.
Key Differences from Core:
- Automatic parameter validation with descriptive exceptions
- Built-in query scratch stack (no need to provide your own)
- Dispose safety checks to prevent use-after-dispose
- Implements IScyllaCollection for framework integration
- Sealed class (not a struct) for managed ownership semantics
When to Use:
- ScyllaBVH (this class): General-purpose usage, game code, managed contexts
- ScyllaBVHCore: Burst jobs, DOTS systems, performance-critical paths with pre-allocated buffers
Usage Pattern:
- Create with appropriate allocator (typically Allocator.Persistent)
- Build from arrays or add items incrementally
- Perform queries (QueryOverlap, QueryRay, QuerySphere)
- Update item bounds as objects move
- Dispose when done
Performance Considerations:
- The built-in query stack is convenient but may reallocate during large queries
- For Burst-compiled jobs, access the Core property directly
- Pre-reserve capacity with Reserve() to minimize allocations
Thread Safety:
This class is NOT thread-safe by default (matches Scylla collection patterns). Use external synchronization if accessing concurrently from multiple threads. The SyncRoot property returns null (no built-in synchronization).
// Direct construction
var bvh = new ScyllaBVH(Allocator.Persistent, initialItemCapacity: 128, fatteningMargin: 0.15f);
// Using fluent builder for complex configuration,
var bvh = ScyllaBVH.CreateBuilder()
.WithAllocator(Allocator.Persistent)
.WithItemCapacity(128)
.WithNodeCapacity(256)
.WithQueryStackCapacity(512)
.WithFatteningMargin(0.15f)
.Build();
Constructors
ScyllaBVH(Allocator, int, int, float, int)
Creates a new BVH instance with specified capacity and configuration parameters.
Declaration
public ScyllaBVH(Allocator allocator, int initialItemCapacity = 64, int initialNodeCapacity = 128, float fatteningMargin = 0.1, int initialQueryStackCapacity = 256)
Parameters
| Type | Name | Description |
|---|---|---|
| Allocator | allocator | Memory allocator for native containers (Persistent, TempJob, or Temp) |
| int | initialItemCapacity | Initial capacity for item storage (default: 64) |
| int | initialNodeCapacity | Initial capacity for node storage (default: 128) |
| float | fatteningMargin | Margin to expand leaf AABBs (default: 0.1) |
| int | initialQueryStackCapacity | Initial capacity for query traversal stack (default: 256) |
Remarks
Allocator Selection:
- Allocator.Persistent: Long-lived BVH (recommended for most game scenarios)
- Allocator.TempJob: BVH used within a single frame across jobs
- Allocator.Temp: Short-lived BVH used within a single frame (avoid for BVH due to size)
Capacity Guidelines:
Initial capacities are hints to reduce early allocations. The BVH will grow automatically.
- itemCapacity: Number of items you expect to store
- nodeCapacity: Should be approximately 2 * itemCapacity - 1 for a complete binary tree
- queryStackCapacity: Depends on tree depth; 256 is suitable for most cases
Fattening Margin:
Leaf AABBs are expanded by this margin to reduce update frequency for moving objects.
- Larger values: Fewer updates but more false positives in queries
- Smaller values: More updates but tighter query results
- Typical range: 0.05 to 0.2 (5% to 20% expansion)
Properties
Capabilities
Capability flags supported by this collection instance.
Declaration
public ScyllaCollectionCapabilities Capabilities { get; }
Property Value
| Type | Description |
|---|---|
| ScyllaCollectionCapabilities |
Core
Exposes the underlying Burst-friendly BVH core for direct use in jobs and performance-critical code.
Declaration
public ScyllaBVHCore Core { get; }
Property Value
| Type | Description |
|---|---|
| ScyllaBVHCore |
Remarks
Use this property to access the low-level ScyllaBVHCore when:
- Running BVH operations inside Burst-compiled jobs
- You need to provide your own scratch buffers (instead of using the built-in _queryStack)
- Maximum performance is required and validation overhead is unwanted
Important:
The core is a struct, so modifying the returned value won't affect the wrapper's internal state. If you need to modify the core (e.g., calling Build(), Add(), Remove()), you must work with the wrapper's methods or carefully manage the core instance yourself. The wrapper's _queryStack is NOT accessible through the core, so query methods on the core require you to provide your own NativeList<int> traversal stack.
Exceptions
| Type | Condition |
|---|---|
| ObjectDisposedException | Thrown if the BVH has been disposed |
Count
Number of items currently stored.
Declaration
public int Count { get; }
Property Value
| Type | Description |
|---|---|
| int |
IsEmpty
Convenience property indicating whether the BVH contains no items.
Declaration
public bool IsEmpty { get; }
Property Value
| Type | Description |
|---|---|
| bool |
SyncRoot
Synchronization root for externally coordinating operations with this collection. For unsynchronized collections this is null.
Declaration
public object SyncRoot { get; }
Property Value
| Type | Description |
|---|---|
| object |
ThreadSafety
Declares the thread-safety guarantees provided by this collection instance.
Declaration
public ScyllaCollectionThreadSafety ThreadSafety { get; }
Property Value
| Type | Description |
|---|---|
| ScyllaCollectionThreadSafety |
Methods
Add(int, ScyllaAABB3)
Adds a new item to the BVH dynamically.
Declaration
public void Add(int itemID, ScyllaAABB3 bounds)
Parameters
| Type | Name | Description |
|---|---|---|
| int | itemID | Unique identifier for the item |
| ScyllaAABB3 | bounds | Axis-aligned bounding box for the item |
Remarks
This is a convenience wrapper around ScyllaBVHCore.Add() with validation. Performs incremental insertion using the Surface Area Heuristic to find the best insertion point. Throws InvalidOperationException if the item ID already exists in the BVH. Throws ArgumentException if the bounds are invalid. For bulk initialization, prefer using Build() for better performance.
Exceptions
| Type | Condition |
|---|---|
| ArgumentException | Thrown when bounds are invalid |
| InvalidOperationException | Thrown when item ID already exists |
Build(NativeArray<int>, NativeArray<ScyllaAABB3>)
Constructs a complete BVH from arrays of item IDs and corresponding axis-aligned bounding boxes.
Declaration
public void Build(NativeArray<int> itemIDs, NativeArray<ScyllaAABB3> bounds)
Parameters
| Type | Name | Description |
|---|---|---|
| NativeArray<int> | itemIDs | Array of unique item identifiers |
| NativeArray<ScyllaAABB3> | bounds | Array of axis-aligned bounding boxes corresponding to each item ID |
Remarks
This is a convenience wrapper around ScyllaBVHCore.Build() with validation. Performs a top-down bulk build using the Surface Area Heuristic for efficient query performance. This method is significantly more efficient than adding items one-by-one for bulk initialization. Throws ArgumentException if the array lengths don't match.
Exceptions
| Type | Condition |
|---|---|
| ArgumentException | Thrown when itemIDs and bounds arrays have different lengths |
Clear()
Removes all items from the BVH and resets the tree structure.
Declaration
public void Clear()
Remarks
This is a convenience wrapper around ScyllaBVHCore.Clear(). Clears all items and nodes while preserving internal container capacities. After clearing, the BVH is empty and ready for new items.
Contains(int)
Returns true if an item with the specified ID is currently stored in the BVH.
Declaration
public bool Contains(int itemID)
Parameters
| Type | Name | Description |
|---|---|---|
| int | itemID | The unique identifier of the item to check |
Returns
| Type | Description |
|---|---|
| bool | True if the item exists in the BVH, false otherwise |
Remarks
This is a convenience wrapper around ScyllaBVHCore.Contains(). This is an O(1) hash map lookup operation.
CreateBuilder()
Creates a new fluent builder for configuring and constructing a ScyllaBVH instance. The builder provides a discoverable API for setting allocator, capacities, and fattening margin.
Declaration
public static ScyllaBVH.Builder CreateBuilder()
Returns
| Type | Description |
|---|---|
| ScyllaBVH.Builder | A new builder instance for configuring ScyllaBVH construction |
Remarks
var bvh = ScyllaBVH.CreateBuilder()
.WithAllocator(Allocator.Persistent)
.WithItemCapacity(128)
.WithFatteningMargin(0.15f)
.Build();
Dispose()
Disposes the BVH and releases all unmanaged memory.
Declaration
public void Dispose()
Remarks
Disposes the internal query stack and core BVH structure. After calling Dispose(), the BVH is no longer usable. It is safe to call Dispose() multiple times (subsequent calls are no-ops). Always call Dispose() when done to prevent memory leaks.
QueryOverlap(ScyllaAABB3, NativeList<int>)
Performs an AABB overlap query and appends all intersecting item IDs to the results list.
Declaration
public void QueryOverlap(ScyllaAABB3 query, NativeList<int> results)
Parameters
| Type | Name | Description |
|---|---|---|
| ScyllaAABB3 | query | Query axis-aligned bounding box |
| NativeList<int> | results | Result list to append matching item IDs (not cleared by this method) |
Remarks
This is a convenience wrapper around ScyllaBVHCore.QueryOverlap() that uses an internal scratch stack for traversal. For custom traversal control or to avoid internal allocations, access the Core property and call QueryOverlap directly. Uses iterative depth-first traversal to efficiently cull the BVH hierarchy. Results are appended to the list (not cleared), allowing multiple queries to accumulate.
QueryRay(ScyllaRay3, float, NativeList<int>)
Performs a ray intersection query and appends all intersecting item IDs to the results list.
Declaration
public void QueryRay(ScyllaRay3 ray, float maxDistance, NativeList<int> results)
Parameters
| Type | Name | Description |
|---|---|---|
| ScyllaRay3 | ray | Ray with origin, direction, and precomputed inverse direction |
| float | maxDistance | Maximum ray distance to test (forms segment [0, maxDistance]) |
| NativeList<int> | results | Result list to append matching item IDs (not cleared by this method) |
Remarks
This is a convenience wrapper around ScyllaBVHCore.QueryRay() that uses an internal scratch stack for traversal. For custom traversal control or to avoid internal allocations, access the Core property and call QueryRay directly. Uses iterative depth-first traversal with ray-AABB intersection tests (slab method). The ScyllaRay3 struct contains cached inverse direction for efficient slab-method testing. Results are appended to the list (not cleared), allowing multiple queries to accumulate.
QuerySphere(float3, float, NativeList<int>)
Performs a sphere intersection query and appends all intersecting item IDs to the results list.
Declaration
public void QuerySphere(float3 center, float radius, NativeList<int> results)
Parameters
| Type | Name | Description |
|---|---|---|
| float3 | center | Sphere center point |
| float | radius | Sphere radius (must be non-negative) |
| NativeList<int> | results | Result list to append matching item IDs (not cleared by this method) |
Remarks
This is a convenience wrapper around ScyllaBVHCore.QuerySphere() that uses an internal scratch stack for traversal. For custom traversal control or to avoid internal allocations, access the Core property and call QuerySphere directly. Uses iterative depth-first traversal with sphere-AABB distance tests. Distance calculations use squared distance to avoid expensive square root operations. Results are appended to the list (not cleared), allowing multiple queries to accumulate.
Remove(int)
Removes an item from the BVH by its unique identifier.
Declaration
public bool Remove(int itemID)
Parameters
| Type | Name | Description |
|---|---|---|
| int | itemID | Unique identifier of the item to remove |
Returns
| Type | Description |
|---|---|
| bool | True if the item existed and was removed, false if the item was not found |
Remarks
This is a convenience wrapper around ScyllaBVHCore.Remove(). Detaches the item's leaf node from the tree, promotes its sibling, and refits ancestor bounds. Uses swap-back removal internally for efficient memory management.
Reserve(int, int, int)
Reserves internal capacities for items, nodes, and scratch buffers.
Declaration
public void Reserve(int itemCapacity, int nodeCapacity, int scratchCapacity)
Parameters
| Type | Name | Description |
|---|---|---|
| int | itemCapacity | Minimum capacity for item storage (IDs and bounds) |
| int | nodeCapacity | Minimum capacity for BVH node storage |
| int | scratchCapacity | Minimum capacity for build and query scratch buffers |
Remarks
This is a convenience wrapper around ScyllaBVHCore.Reserve(). Pre-allocating capacity ensures that subsequent operations don't trigger allocations during Burst-compiled job execution.
Update(int, ScyllaAABB3)
Updates an existing item's bounds using a refit-or-reinsert strategy.
Declaration
public bool Update(int itemID, ScyllaAABB3 newBounds)
Parameters
| Type | Name | Description |
|---|---|---|
| int | itemID | Unique identifier of the item to update |
| ScyllaAABB3 | newBounds | New axis-aligned bounding box for the item |
Returns
| Type | Description |
|---|---|
| bool | True if the item existed and was updated, false if the item was not found |
Remarks
This is a convenience wrapper around ScyllaBVHCore.Update() with validation. If the new bounds fit within the existing fattened leaf bounds, performs a quick refit. Otherwise, detaches and reinserts the leaf with newly fattened bounds. Throws ArgumentException if the bounds are invalid.
Exceptions
| Type | Condition |
|---|---|
| ArgumentException | Thrown when bounds are invalid |