Code Monkey home page Code Monkey logo

octreecsg's Introduction

OctreeCSG

Constructive Solid Geometry (CSG) library for use with three.js
The OctreeCSG library is using the Octree data structure to store the geometry data for the CSG operations

All the code examples below can be tested live in 3dd.dev

Table of Contents

Usage

OctreeCSG comes as a Javascript Module and can be imported with the following command:

import OctreeCSG from './OctreeCSG/OctreeCSG.js';

Basic Operations

OctreeCSG provides basic boolean operations (union, subtract and intersect) for ease of use. The basic operations expects the same type of parameters:

Parameter Description
mesh1 First mesh
mesh2 Second mesh
targetMaterial (Optional) The material to use for the final mesh, can be a single material or an array of two materials. Default: A clone of the material of the first mesh

Mesh Union (OctreeCSG.meshUnion)

const geometry = new THREE.BoxGeometry(10, 10, 10);
const material1 = new THREE.MeshStandardMaterial({ color: 0xff0000 });
const material2 = new THREE.MeshStandardMaterial({ color: 0x0000ff });
const mesh1 = new THREE.Mesh(geometry, material1);
const mesh2 = new THREE.Mesh(geometry.clone(), material2);
mesh2.position.set(5, -5, 5);

const resultMesh = OctreeCSG.meshUnion(mesh1, mesh2);
scene.add(resultMesh);

Mesh Subtract (OctreeCSG.meshSubtract)

const geometry = new THREE.BoxGeometry(10, 10, 10);
const material1 = new THREE.MeshStandardMaterial({ color: 0xff0000 });
const material2 = new THREE.MeshStandardMaterial({ color: 0x0000ff });
const mesh1 = new THREE.Mesh(geometry, material1);
const mesh2 = new THREE.Mesh(geometry.clone(), material2);
mesh2.position.set(5, -5, 5);

const resultMesh = OctreeCSG.meshSubtract(mesh1, mesh2);
scene.add(resultMesh);

Mesh Intersect (OctreeCSG.meshIntersect)

const geometry = new THREE.BoxGeometry(10, 10, 10);
const material1 = new THREE.MeshStandardMaterial({ color: 0xff0000 });
const material2 = new THREE.MeshStandardMaterial({ color: 0x0000ff });
const mesh1 = new THREE.Mesh(geometry, material1);
const mesh2 = new THREE.Mesh(geometry.clone(), material2);
mesh2.position.set(5, -5, 5);

const resultMesh = OctreeCSG.meshIntersect(mesh1, mesh2);
scene.add(resultMesh);



Advanced Operations

OctreeCSG.fromMesh

Converts a three.js mesh to an Octree

Parameter Description
obj three.js mesh
objectIndex (Optional) Used for specifying the geometry group index in the result mesh. Default: Input mesh's groups if there are any
octree (Optional) Target octree to use. Default: new Octree
buildTargetOctree (Optional) Specifies if to build the target Octree tree or return a flat Octree (true / flase). Default: true

OctreeCSG.toMesh

Converts an Octree to a three.js mesh

Parameter Description
octree Octree object
material Material object or an array of materials to use for the new three.js mesh

OctreeCSG.union:

Merges two Octrees (octreeA and octreeB) to one Octree

Parameter Description
octreeA First octree object
octreeB Second octree object
buildTargetOctree (Optional) Specifies if to build the target Octree tree or return a flat Octree (true / flase). Default: true
const geometry = new THREE.BoxGeometry(10, 10, 10);
const material1 = new THREE.MeshStandardMaterial({ color: 0xff0000 });
const material2 = new THREE.MeshStandardMaterial({ color: 0x0000ff });
const mesh1 = new THREE.Mesh(geometry, material1);
const mesh2 = new THREE.Mesh(geometry.clone(), material2);
mesh2.position.set(5, -5, 5);
const octreeA = OctreeCSG.fromMesh(mesh1);
const octreeB = OctreeCSG.fromMesh(mesh2);

const resultOctree = OctreeCSG.union(octreeA, octreeB);

const resultMesh = OctreeCSG.toMesh(resultOctree, mesh1.material.clone());
scene.add(resultMesh);

OctreeCSG.subtract:

Subtracts octreeB from octreeA and returns the result Octree

Parameter Description
octreeA First octree object
octreeB Second octree object
buildTargetOctree (Optional) Specifies if to build the target Octree tree or return a flat Octree (true / flase). Default: true
const geometry = new THREE.BoxGeometry(10, 10, 10);
const material1 = new THREE.MeshStandardMaterial({ color: 0xff0000 });
const material2 = new THREE.MeshStandardMaterial({ color: 0x0000ff });
const mesh1 = new THREE.Mesh(geometry, material1);
const mesh2 = new THREE.Mesh(geometry.clone(), material2);
mesh2.position.set(5, -5, 5);
const octreeA = OctreeCSG.fromMesh(mesh1);
const octreeB = OctreeCSG.fromMesh(mesh2);

const resultOctree = OctreeCSG.subtract(octreeA, octreeB);

const resultMesh = OctreeCSG.toMesh(resultOctree, mesh1.material.clone());
scene.add(resultMesh);

OctreeCSG.intersect:

Returns the intersection of octreeA and octreeB

Parameter Description
octreeA First octree object
octreeB Second octree object
buildTargetOctree (Optional) Specifies if to build the target Octree tree or return a flat Octree (true / flase). Default: true
const geometry = new THREE.BoxGeometry(10, 10, 10);
const material1 = new THREE.MeshStandardMaterial({ color: 0xff0000 });
const material2 = new THREE.MeshStandardMaterial({ color: 0x0000ff });
const mesh1 = new THREE.Mesh(geometry, material1);
const mesh2 = new THREE.Mesh(geometry.clone(), material2);
mesh2.position.set(5, -5, 5);
const octreeA = OctreeCSG.fromMesh(mesh1);
const octreeB = OctreeCSG.fromMesh(mesh2);

const resultOctree = OctreeCSG.intersect(octreeA, octreeB);

const resultMesh = OctreeCSG.toMesh(resultOctree, mesh1.material.clone());
scene.add(resultMesh);

OctreeCSG.operation

CSG Hierarchy of Operations (syntax may change), provides a simple method to combine several CSG operations into one

Parameter Description
obj Input object with the CSG hierarchy
returnOctrees (Optional) Specifies whether to return the Octrees as part of the result or not (true / false). Default: false

Input object structure:

Key Expected Value
op Type of operation to perform as string, options: union, subtract and intersect
material (Optional) Used only in the root level of the object, if a material is provided the returned object will be a three.js mesh instead of an Octree. Value can be a single material or an array of materials
objA First object, can be a three.js mesh, Octree or a sub-structure of the CSG operation
objB Second object, can be a three.js mesh, Octree or a sub-structure of the CSG operation
let baseMaterial = new THREE.MeshBasicMaterial({ color: 0x0000ff });
let cubeGeometry = new THREE.BoxGeometry(10, 10, 10);
let sphereGeometry = new THREE.SphereGeometry(6.5, 64, 32);
let baseCylinderGeometry = new THREE.CylinderGeometry(3, 3, 20, 64);

let cubeMesh = new THREE.Mesh(cubeGeometry, baseMaterial.clone());
let sphereMesh = new THREE.Mesh(sphereGeometry, baseMaterial.clone());
let cylinderMesh1 = new THREE.Mesh(baseCylinderGeometry.clone(), baseMaterial.clone());
let cylinderMesh2 = new THREE.Mesh(baseCylinderGeometry.clone(), baseMaterial.clone());
let cylinderMesh3 = new THREE.Mesh(baseCylinderGeometry.clone(), baseMaterial.clone());

cubeMesh.material.color.set(0xff0000);
sphereMesh.material.color.set(0x0000ff);
cylinderMesh1.material.color.set(0x00ff00);
cylinderMesh2.material.color.set(0x00ff00);
cylinderMesh3.material.color.set(0x00ff00);
cylinderMesh2.rotation.set(0, 0, THREE.MathUtils.degToRad(90));
cylinderMesh3.rotation.set(THREE.MathUtils.degToRad(90), 0, 0);

let result = OctreeCSG.operation({
    op: "subtract",
    material: [cubeMesh.material, sphereMesh.material, cylinderMesh1.material, cylinderMesh2.material, cylinderMesh3.material],
    objA: {
        op: "intersect",
        objA: cubeMesh,
        objB: sphereMesh
    },
    objB: {
        op: "union",
        objA: {
            op: "union",
            objA: cylinderMesh1,
            objB: cylinderMesh2,
        },
        objB: cylinderMesh3
    }
});
scene.add(result);

Array Operations

OctreeCSG provides 3 methods to perform CSG operations on an array of meshes / octrees

Parameter Description
objArr An array of meshes or octrees to perform the CSG operation on
materialIndexMax (Optional) Can be used to specify the maximum number of groups in the result Octree. Default: Infinity

List of Methods:

  • OctreeCSG.unionArray - Union operation on an array of meshes
  • OctreeCSG.subtractArray - Subtract operation on an array of meshes
  • OctreeCSG.intersectArray - Intersect operation on an array of meshes

Asynchronous Operations

OctreeCSG provides asynchronous CSG methods for all the advanced CSG operations.

List of Methods:

  • OctreeCSG.async.union
  • OctreeCSG.async.subtract
  • OctreeCSG.async.intersect
  • OctreeCSG.async.operation
  • OctreeCSG.async.unionArray
  • OctreeCSG.async.subtractArray
  • OctreeCSG.async.intersectArray

OctreeCSG Flags

The following flags and variables control how OctreeCSG operates.

Flag / Variable Default Value Description
OctreeCSG.useOctreeRay true Determines if to use OctreeCSG's ray intersection logic or use three.js's intersection logic (Raycaster.intersectObject). Options: true, false
OctreeCSG.rayIntersectTriangleType MollerTrumbore Determines which ray-triangle intersection algorithm to use. three.js's ray-triangle intersection algorithm proved to be not accurate enough for CSG operations during testing so the Möller–Trumbore ray-triangle intersection algorithm was implemented. Options: MollerTrumbore, regular (uses three.js's Ray.intersectTriangle)
OctreeCSG.useWindingNumber false Determines if to use the ray-triangle intersection algorithm or the Winding number algorithm. The Winding number alogirthm can be more accurate than the ray-triangle algorithm on some occasions at the cost of performance. Options: true, false
OctreeCSG.maxLevel 16 Maximum number of sub-Octree levels in the tree
OctreeCSG.polygonsPerTree 100 Minimum number of polygons (triangles) in a sub-Octree before a split is needed

Examples

More examples coming soon.

Resources

  • The Polygon, Vertex and Plane classes were adapted from THREE-CSGMesh
  • The Winding number algorithm is based on this code
  • The Möller–Trumbore ray-triangle intersection algorithm is based on this code
  • The triangle-triangle intersection logic and algorithm is based on this code

octreecsg's People

Contributors

giladdarshan avatar manthrax avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.