three-bvh-csg

repository·main·Indexed 21 days ago

https://github.com/gkjohnson/three-bvh-csg

A high-performance, memory-compact Constructive Solid Geometry (CSG) implementation for three.js built on top of three-mesh-bvh. It provides an Evaluator for performing boolean operations (such as ADDITION, SUBTRACTION, and INTERSECTION) using Brush instances. The library supports hierarchical CSG trees via Operation and OperationGroup classes, utilizes Bounding Volume Hierarchies (BVH) and half-edge data structures for acceleration, and includes a utility to compute mesh volume.

Tokens
3.9K
Snippets
11
Records
19
Agent score
73%

What's inside three-bvh-csg

  1. Understand the BVH CSG implementation architecture

    main

    The three-bvh-csg library is designed for high-performance Constructive Solid Geometry (CSG) operations using Bounding Volume Hierarchies (BVH) and half-edge data structures.

    Core Design Priorities

    • Compact Memory: Uses typed arrays to keep memory utilization low.
    • Low Garbage Collection (GC) Impact: Employs data pooling (e.g., triangle instances) and modifies existing geometry buffers in place to minimize temporary data creation. Brushes cache data to speed up subsequent operations.
    • High Performance: Uses half-edge structures and BVH to quickly discover and cull triangle intersections.
    • Low Mesh Complexity: The BVH approach minimizes the number of triangles that need to be split, reducing the complexity of the resulting mesh.

    Key Data Structures

    • Half-Edge Structure: Pre-generated per Brush to allow fast traversal of connected triangles.
    • BVH: Pre-generated per Brush to accelerate intersection detection between geometries.
    • Group Indices: A map of group indices to triangles, allowing resulting triangles to be mapped to their appropriate material indices.
  2. Perform hierarchical CSG with Operation and evaluateHierarchy

    main

    For complex, nested CSG trees, use the Operation class and Evaluator.evaluateHierarchy.

    An Operation extends Brush and allows you to define a specific CSGOperation (via the .operation property) that will be applied to its children during a hierarchical evaluation. You can build a tree of operations using OperationGroup (which extends THREE.Group) and then pass the root Operation to evaluator.evaluateHierarchy.

    Key Methods for building trees:

    • .operation: Sets the CSGOperation to perform on the next brush in the processing chain.
    • .insertBefore(brush): Inserts a brush before the operation element in the parent's children list.
    • .insertAfter(brush): Inserts a brush after the operation element in the parent's children list.
    // Conceptual usage of hierarchy
    const root = new Operation( geometry );
    root.operation = ADDITION;
    root.add( childBrush );
    
    const result = evaluator.evaluateHierarchy( root );
  3. How the BVH CSG algorithm works

    main

    The CSG operation follows these primary steps:

    1. Generate Brush Data Structures: The Brush generates its half-edge, BVH, and group indices if they are not already present.
    2. Find All Intersections: BVH intersection tests are performed between the two geometries to identify all intersecting triangle indices.
    3. Handle Whole Triangles:
      • For triangles with no intersections, one triangle is picked and tested via raycasting to determine if it is "inside" or "outside" the other geometry.
      • Based on the operation (e.g., union, subtract), the triangle is either included or excluded.
      • The algorithm then traverses the half-edge structure to include all connected non-intersecting triangles.
    4. Handle Intersecting Triangles:
      • Intersecting triangles are split by all other intersecting triangles.
      • Each resulting sub-triangle is then tested via raycasting to determine inclusion.
  4. Perform basic CSG operations with Evaluator

    main

    To perform Constructive Solid Geometry (CSG) operations, create Brush instances from THREE.BufferGeometry (like SphereGeometry or BoxGeometry), ensure their world matrices are updated, and use an Evaluator to compute the result.

    Important Requirements:

    • All brush geometry must be two-manifold (water-tight with no triangle interpenetration).
    • Once a brush is created, its geometry should not be modified.
    • Call .updateMatrixWorld() on brushes before evaluation to ensure correct positioning.
    import { SUBTRACTION, Brush, Evaluator } from 'three-bvh-csg';
    import { MeshStandardMaterial, Mesh, SphereGeometry, BoxGeometry } from 'three';
    
    const brush1 = new Brush( new SphereGeometry() );
    brush1.updateMatrixWorld();
    
    const brush2 = new Brush( new BoxGeometry() );
    brush2.position.y = 0.5;
    brush2.updateMatrixWorld();
    
    const evaluator = new Evaluator();
    const result = evaluator.evaluate( brush1, brush2, SUBTRACTION );
    
    // render the result!
  5. Troubleshooting CSG export issues

    main

    CSG results use Geometry.drawRange to maintain performance. This can cause standard three.js exporters to fail or produce incorrect results.

    Solution: Before exporting, you must convert the geometry to remove the use of drawRange.

  6. Compute mesh volume

    main

    Use computeMeshVolume(mesh: Mesh | BufferGeometry): Number to calculate the volume of a mesh in world space.

    Note: You must ensure the mesh's world matrix is updated before calling this function.

    const volume = computeMeshVolume( myMesh );
  7. Evaluate CSG operations with Evaluator.evaluate

    main

    The .evaluate() method performs the specified operation(s) on brushes.

    Single Operation Signature: evaluate(brushA: Brush, brushB: Brush, operation: CSGOperation, target?: Brush | Mesh): Brush | Mesh

    • If target is provided, the brush is modified in place.
    • If target is not provided, a new Brush is created.

    Batch Operation Signature: evaluate(brushA: Brush, brushB: Brush, operations: Array<CSGOperation>, targets: Array<Brush | Mesh>): Array<Brush | Mesh>

    • Allows producing multiple results from different operations simultaneously with minimal overhead.
  8. Configure the Evaluator

    main

    The Evaluator class provides several configuration options to control how CSG operations are processed and how the resulting geometry is structured.

    PropertyTypeDefaultDescription
    useCDTClippingBooleanfalseExperimental: uses Constrained Delaunay Triangulation for more robust triangle clipping at a performance cost.
    useGroupsBooleantrueIf true, assigns material arrays and groups to the target Brush. If false, produces a single coherent piece of geometry.
    consolidateGroupsBooleantrueIf true, merges groups that share a common material to reduce draw calls.
    removeUnusedMaterialsBooleantrueIf true, removes materials from the final array that are not used in the result.
  9. Available CSGOperations

    main

    These constants define the type of boolean operation to perform using the Evaluator.

    ADDITION              // A ∪ B
    SUBTRACTION           // A - B
    REVERSE_SUBTRACTION   // B - A
    DIFFERENCE            // A ⊕ B
    INTERSECTION          // A ∩ B
    
    // "Hollow" operations are non-solid and result in simply removing the geometry
    // within Brush B from brush A. For these operations Brush A can be non-manifold
    // but it is still required that Brush B be a water-tight, two-manifold mesh.
    HOLLOW_SUBTRACTION    // A - B
    HOLLOW_INTERSECTION   // A ∩ B
  10. Reference the BVH CSG core file structure

    main

    The following files constitute the core of the implementation:

    FileDescription
    src/core/Brush.jsAn extension of Mesh that caches and updates necessary data structures for CSG.
    src/core/Evaluator.jsUtility for performing CSG operations between Brush instances.
    src/core/operations.jsThe core CSG operation functions.
    src/core/Operations.js & src/core/OperationGroup.jsExtensions of Brush used to build hierarchical operations (similar to Godot or RealTimeCSG).
    src/core/TriangleSplitter.jsUtility for splitting triangles by planes or other triangles.
    src/core/HalfEdgeMap.jsA map encoding triangle edge relationships in a typed array.
    src/core/IntersectionMap.jsStores intersections from one triangle index to another.
    src/core/TypeBackedArray.jsA wrapper for TypedArray that implements an array API and expands automatically.
    src/helpers/*Debug visualization helpers (points, lines, triangles).
    src/workers/*(Unused) Intended for parallelizing data structure generation.
  11. Import core components from three-bvh-csg

    main

    The three-bvh-csg library provides tools for Constructive Solid Geometry (CSG) operations on Three.js meshes using BVH acceleration. The main entrypoint exports the following core modules:

    • Brush: The primary building block for CSG; a mesh wrapper that holds geometry and operation data.
    • Evaluator: The engine that performs the actual CSG operations between brushes.
    • Operation and OperationGroup: Classes used to define how brushes interact (e.g., subtraction, union, intersection).
    • GridMaterial: A specialized material for visualizing grids.
    • TriangleSplitter (via LegacyTriangleSplitter or CDTTriangleSplitter): Utilities for splitting triangles during operations.

    To use the library, you typically import Brush to define your shapes and Evaluator to compute the result.

    import { Brush, Evaluator } from 'three-bvh-csg';
    
    // Example workflow:
    // 1. Create brushes
    // 2. Define operations
    // 3. Evaluate with an Evaluator instance
  12. Use helper objects for mesh debugging

    main

    The library exports several helper classes to inspect and debug mesh structures, specifically useful when working with complex CSG results or half-edge data structures:

    • TriangleSetHelper: For inspecting triangle sets.
    • EdgesHelper: For visualizing mesh edges.
    • PointsHelper: For visualizing mesh vertices/points.
    • HalfEdgeHelper: For visualizing the half-edge data structure used internally for manifold mesh processing.