CSG subtraction from mesh

Aim:

I’m trying to use CSG to make the angled red box in my picture act as a mask on the blue cylinder. However, the resultant shape (pink cylinder) should look like a cylinder sliced diagonally in half. However, as you can see, the subtraction isn’t working.

Current result:

Code:

import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { CSG } from 'three-csg-ts';

// Setup scene, camera, renderer
const scene = new THREE.Scene();
scene.background = new THREE.Color( 0xFFFFFF );
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.z = 60;
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

// Controls
const controls = new OrbitControls(camera, renderer.domElement);

// Create cylinder mesh
const geometry = new THREE.CylinderGeometry( 2.5, 2.5, 20, 32 );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const cylinder = new THREE.Mesh( geometry, material );
cylinder.position.set(0, 0, 0);

// Create topEndMesh = topEndCylinder - topEndCube{rotated}
// Create topEndCylinder
const topEndCylinderGeometry = new THREE.CylinderGeometry( 2.5, 2.5, 5, 32 );
const topEndCylinderMaterial = new THREE.MeshBasicMaterial( { color: 0x0000FF } );
const topEndCylinder = new THREE.Mesh( topEndCylinderGeometry, topEndCylinderMaterial );
topEndCylinder.position.set(0, 12.5, 0); // topEndCylinder height is 5, so position must be half height plus height of body
scene.add(topEndCylinder);

// Create topEndCube
const topEndCubeGeometry = new THREE.BoxGeometry(Math.sqrt(50), Math.sqrt(50), Math.sqrt(50));
const topEndCubeMaterial = new THREE.MeshBasicMaterial( { color: 0xFF0000 } );
const topEndCube = new THREE.Mesh( topEndCubeGeometry, topEndCubeMaterial );
topEndCube.position.set(2.5, 15, 0); // position on top right of cylinder
topEndCube.rotation.z = (2 * Math.PI) - (Math.PI / 4); // rotate cube -45 degrees
topEndCube.updateMatrix(); // store the rotation
scene.add(topEndCube);

// Perform subtraction
const topEndCylinderCSG = CSG.fromMesh(topEndCylinder, 0);
const topEndCubeCSG = CSG.fromMesh(topEndCube, 1);
const topEndMeshCSG = topEndCylinderCSG.subtract(topEndCubeCSG);
const topEndMesh = CSG.toMesh(topEndMeshCSG, new THREE.Matrix4(), new THREE.MeshBasicMaterial( { color: 0xFFC0CB } ));
scene.add(topEndMesh);

topEndMesh.position.set(10, 5, 0);

const axesHelper = new THREE.AxesHelper( 50 ); 
scene.add(axesHelper, cylinder);

function animate() {
    requestAnimationFrame(animate);
    controls.update();
    renderer.render(scene, camera);
}
animate();

What I’ve tried:

I tried doing topEndCylinderCSG.intersect(topEndCubeCSG) to return an intersection. This would help ensure the two shapes were actually overlapping. But this returned nothing, leading me to suspect that was the cause.

However, I’ve set the positions of both shapes to top_cylinder(0, 12.5, 0) and cube(2.5, 15, 0). Given their sizes, they should intersect.

I receive no error messages.

Blue cylinder masked by red cube:

After the masking it should look like this:

Perhaps this will help.

Note how I translate the box geometry to be higher and rotated.

2 Likes

thank you!