UNPKG

three-bvh-csg

Version:

A fast, flexible, dynamic CSG implementation on top of three-mesh-bvh

309 lines (190 loc) 9.37 kB
# three-bvh-csg [![npm version](https://img.shields.io/npm/v/three-bvh-csg.svg?style=flat-square)](https://www.npmjs.com/package/three-bvh-csg) [![build](https://img.shields.io/github/actions/workflow/status/gkjohnson/three-bvh-csg/node.js.yml?style=flat-square&label=build&branch=main)](https://github.com/gkjohnson/three-bvh-csg/actions) [![github](https://flat.badgen.net/badge/icon/github?icon=github&label)](https://github.com/gkjohnson/three-bvh-csg/) [![twitter](https://flat.badgen.net/badge/twitter/@garrettkjohnson/?icon&label)](https://twitter.com/garrettkjohnson) [![sponsors](https://img.shields.io/github/sponsors/gkjohnson?style=flat-square&color=1da1f2)](https://github.com/sponsors/gkjohnson/) ![](./docs/csg-banner.png) An _experimental, in progress_, flexible, memory compact, fast and dynamic CSG implementation on top of [three-mesh-bvh](https://github.com/gkjohnson/three-mesh-bvh). More than 100 times faster than other BSP-based three.js CSG libraries in complex cases. Contributions welcome! > **Note** > All brush geometry must be [two-manifold](https://knowledge.autodesk.com/support/maya-lt/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/MayaLT/files/Polygons-overview-Twomanifold-vs--nonmanifold-polygonal-geometry-htm.html) - or water tight with no triangle interpenetration. > **Warning** > Due to numerical precision and corner cases resulting geometry may not be correctly completely two-manifold. # Roadmap / Help Wanted - Fix triangle splitting / missing triangle issues [#73](https://github.com/gkjohnson/three-bvh-csg/issues/73) [#68](https://github.com/gkjohnson/three-bvh-csg/issues/68) - Polygon splitting & triangulation [#51](https://github.com/gkjohnson/three-bvh-csg/issues/51) - Worker Support [#14](https://github.com/gkjohnson/three-bvh-csg/issues/14) [And more!](https://github.com/gkjohnson/three-bvh-csg/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) # Examples [Simple CSG](https://gkjohnson.github.io/three-bvh-csg/examples/bundle/simple.html) [Complex Model CSG](https://gkjohnson.github.io/three-bvh-csg/examples/bundle/geometry.html) [Multimaterial CSG](https://gkjohnson.github.io/three-bvh-csg/examples/bundle/multimaterial.html) [Hierarchical Operations](https://gkjohnson.github.io/three-bvh-csg/examples/bundle/hierarchy.html) # Use ```js import { SUBTRACTION, Brush, Evaluator } from 'three-bvh-csg'; import { MeshStandardMaterial, Mesh, SphereGeometry, BoxGeometry } from 'three'; const csgEvaluator = new Evaluator(); const brush1 = new Brush( new SphereGeometry() ); const brush2 = new Brush( new BoxGeometry() ); const result = csgEvaluator.evaluate( brush1, brush2, SUBTRACTION ); // render the result! ``` # API ## Constants ### CSGOperations CSG operations enums for use with `Evaluator`. ``` ADDITION SUBTRACTION DIFFERENCE INTERSECTION ``` ## Brush _extends THREE.Mesh_ An object with the same interface as `THREE.Mesh` but used to evaluate CSG operations. Once a brush is created the geometry should not be modified. > **Note** > > It is recommended to remove groups from a geometry before creating a brush if multi-material support is not required. ## Operation _extends Brush_ This is an extension of the `Brush` class. With this class is possible to create a mesh and pass the CSG Operation constant to define which operation computes on the mesh. The result is a Mesh whose effect is defined from the operation selected. You can see how it works in the _hierarchy_ example. ### .operation ```js operation = ADDITION : CSGOperation ``` The operation to perform on the next brush in processing chain when running `Evaluater.evaluateHierarchy`. ### .insertBefore ```js insertBefore( brush : Brush ) ``` Inserts the brush before the operation element that calls the method, in the list of the children of the operation's parent. ### .insertAfter ```js insertAfter( brush : Brush ) ``` Inserts the brush after the operation element that calls the method, in the list of the children of the operation's parent. ## OperationGroup _extends THREE.Group_ A class with the same interface as `THREE.Group` but used to group a list of Operation mesh through the `.add` method inherited from the THREE.Group class. You can create a group starting from single Operation meshes as in the _hierarchy_ example. ## Evaluator ### .useGroups ```js useGroups = true : Boolean ``` Whether to use geometry groups when processing the geometry. If geometry groups are used then a material array and groups will be assigned to the target `Brush` after processing. If groups are disabled then a single coherent piece of geometry with no groups will be produced. ### .evaluate ```js evaluate( brushA : Brush, brushB : Brush, operation : CSGOperation, target = null : Brush | Mesh ) : Brush | Mesh ``` Performs the given `operation` on `brushA` with `brushB`. If no target is provided then a new `Brush` will be created with the new geometry. Otherwise the provided Brush will be _modified in place_ and geometry disposed or marked for update as needed. ### .evaluateHierarchy ```js evaluateHierarchy( root: Opertation, target = new Brush : Brush | Mesh ) : Brush | Mesh ``` The method gets as parameters a root, an Operation mesh and a target if it is provided, otherwise, a new `Brush` will be created. First sets the `updateMatrixWolrd` of the root to true then calls the traverse function with the root parameter to `evaluate` the mesh and its children. ```js evaluate( brush, child, child.operation ); ``` In this case, the arguments passed to `evaluate` is the `root` as `brushA`, the child as `brushB` and the `child.operation` as the operation to apply to the mesh. ## OperationDebugData This class is used in the constructor of the Evaluator class. When the Evaluator is defined the constructor creates a debug property of type OperationDebugData and it is used to set the debug context, that is `addEdge` and `addIntersectionTriangles` to, for example, an EdgesHelper or a TriangleHelper. ### .enabled ```js enabled = false : Boolean ``` Whether to collect the debug data during CSG operations which has a performance a memory cost. ### .intersectionEdges ```js intersectionEdges = [] : Line3 ``` A list of edges formed by intersecting triangles during the CSG process. <!-- ## EvaluatorWorker _extends Evaluator_ ### .evaluate TODO ### .evaluateHierarchy TODO --> ## GridMaterial _extends THREE.MeshPhongMaterial_ A material with the same interface as `THREE.MeshPhongMaterial`. It adds a stylized grid on the mesh for more easily visualizing mesh topology and measurements. ### .enableGrid ```js enableGrid = true : Boolean ``` Sets the visibility of the grid on the mesh. ## HalfEdgeMap TODO ### constructor ```js constructor( geometry : BufferGeometry = null ) ``` ### .getSiblingTriangleIndex ```js getSiblingTriangleIndex( triIndex : Number, edgeIndex : 0 | 1 | 2 ) : Number ``` ### .getSiblingEdgeIndex ```js getSiblingEdgeIndex( triIndex : Number, edgeIndex : 0 | 1 | 2 ) : Number ``` ### .updateFrom ```js updateFrom( geometry : BufferGeometry ) : void ``` ## PointsHelper _extends THREE.InstancedMesh_ Helper class for generating spheres to display. ### .setPoints ```js setPoints( points : Vector3[] ) : void; ``` Sets the points, passed as Vector3, and visualizes them as spheres. ## EdgesHelper _extends THREE.LineSegments_ Helper class for generating a line to display the provided edges. ### .setEdges ```js setEdges( edges : Line3[] ) : void ``` Sets the list of lines to be visualized. ## HalfEdgeMapHelper _extends EdgesHelper_ This is a helper class that takes the `HalfEdgeMap` object and visualizes the connectivity between triangles. ### .setHalfEdges ```js setHalfEdges( geometry : Geometry, halfEdges : HalfEdgeMap ) : void ``` Sets the half edge map to visualize along with the associated geometry. ## TriangleSetHelper _extends THREE.Group_ Helper class for displaying a set of triangles. In the _Simple CSG_ example is possible to enable/disable the visibility of the triangles helper via `displayTriangleIntersections` checkbox. The helper is composed of two meshes, one is a mesh with a MeshPhongMaterial and the other is a mesh with a LineBasicMaterial. ### .setTriangles ```js setTriangles( triangles: Triangle[] ) : void ``` Sets the geometry of the mesh and the line with the position of the triangles passed as a parameter of the method. ## Functions ### computeMeshVolume ```js computeMeshVolume( mesh : Mesh | BufferGeometry ) : Number ``` Computes the volume of the given mesh in world space. The world matrix is expected to be updated before calling this function. # Gotchas - All geometry are expected to have all attributes being used and of the same type. - Geometry on a Brush should be unique and not be modified after being set. - All geometry must be [two-manifold](https://knowledge.autodesk.com/support/maya-lt/learn-explore/caas/CloudHelp/cloudhelp/2015/ENU/MayaLT/files/Polygons-overview-Twomanifold-vs--nonmanifold-polygonal-geometry-htm.html) - or water tight with no triangle interpenetration. # References - [Godot CSG](https://github.com/godotengine/godot/blob/master/modules/csg/csg.cpp) - RealtimeCSG ([Overview](https://www.youtube.com/watch?v=uqaiUMuGlRc), [GDC Presentation](https://www.youtube.com/watch?v=Iqmg4gblreo))