my goal is to split the shape e.g. like a torus but it could be a circle triangle etc. I want to split the shape by using a custom plane. Once the torus is split-into two parts both parts need to be draggable separately.
So far I am able to split the torus but
- both parts torusAbove and torusBelow are displayed in black dott. It is not taking colour or texture. What is the problem here?
- Another issue is if I would like to highlight the intersection of tours and planes with some colour e.g. green, how can I achieve it?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Three.js Plane and Torus Split Example</title>
<style>
body {
margin: 0;
}
canvas {
display: block;
}
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/r128/examples/js/controls/DragControls.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/r128/examples/js/controls/OrbitControls.js"></script>
<script>
// 1. Set up the scene, camera, and renderer
const scene = new THREE.Scene();
// Set the camera's perspective
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
// Set up the WebGL renderer
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// Append the renderer's canvas element to the document body
document.body.appendChild(renderer.domElement);
// Set the clear color for the renderer (background color)
renderer.setClearColor(0x00ffff); // Black background
// 2. Create the plane geometry and material
const planeGeometry = new THREE.PlaneGeometry(5, 5); // 5x5 units plane
const planeMaterial = new THREE.MeshStandardMaterial({
color: 0x00ff00
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
scene.add(plane);
// Position the plane
plane.rotation.x = -Math.PI / 2; // Rotate the plane to be horizontal
// 3. Create the torus geometry and material
const torusGeometry = new THREE.TorusGeometry(1, 0.4, 100, 100); // Increased radialSegments to 32
const torusMaterial = new THREE.MeshStandardMaterial({
color: 0xffff00,
roughness: 0.5,
metalness: 0.5
}); // Red color, with some roughness and metalness
let torus = new THREE.Mesh(torusGeometry, torusMaterial);
scene.add(torus);
// Position the torus
torus.position.set(0, 1, 0); // Position the torus above the plane
// 4. Add a light source
const ambientLight = new THREE.AmbientLight(0x404040); // Soft white light
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1);
pointLight.position.set(5, 5, 5);
scene.add(pointLight);
// Position the camera
camera.position.set(0, 5, 5); // Place the camera at (0, 5, 5)
camera.lookAt(0, 0, 0); // Make the camera look at the origin
// 5. Enable OrbitControls for better navigation
const orbitControls = new THREE.OrbitControls(camera, renderer.domElement);
// 6. Function to split the torus
function splitTorus() {
const planeHeight = plane.position.y;
const posAttr = torus.geometry.attributes.position;
const verticesAbove = [];
const verticesBelow = [];
for (let i = 0; i < posAttr.count; i++) {
const vertex = new THREE.Vector3().fromBufferAttribute(posAttr, i);
vertex.applyMatrix4(torus.matrixWorld);
if (vertex.y >= planeHeight) {
verticesAbove.push(vertex);
} else {
verticesBelow.push(vertex);
}
}
const geometryAbove = new THREE.BufferGeometry().setFromPoints(verticesAbove);
const geometryBelow = new THREE.BufferGeometry().setFromPoints(verticesBelow);
const materialAbove = new THREE.MeshStandardMaterial({
color: 0x0000ff,
roughness: 0.5,
metalness: 0.5
}); // Blue color, with some roughness and metalness
const materialBelow = new THREE.MeshStandardMaterial({
color: 0xffff00,
roughness: 0.5,
metalness: 0.5
}); // Yellow color, with some roughness and metalness
const torusAbove = new THREE.Mesh(geometryAbove, materialAbove);
const torusBelow = new THREE.Mesh(geometryBelow, materialBelow);
scene.remove(torus);
scene.remove(plane);
scene.add(torusAbove);
scene.add(torusBelow);
torusAbove.name = 'torusAbove';
torusBelow.name = 'torusBelow';
return [torusAbove, torusBelow];
}
let [torusAbove, torusBelow] = splitTorus();
// 7. Enable DragControls for both parts
const dragControlsAbove = new THREE.DragControls([torusAbove], camera, renderer.domElement);
const dragControlsBelow = new THREE.DragControls([torusBelow], camera, renderer.domElement);
// Highlight dragged objects
dragControlsAbove.addEventListener('dragstart', function(event) {
event.object.material.emissive.set(0xaaaaaa);
});
dragControlsAbove.addEventListener('dragend', function(event) {
event.object.material.emissive.set(0xff00ff);
});
dragControlsBelow.addEventListener('dragstart', function(event) {
event.object.material.emissive.set(0xaaaaff);
});
dragControlsBelow.addEventListener('dragend', function(event) {
event.object.material.emissive.set(0x0000ff);
});
// 8. Render the scene
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
// Handle window resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
</script>
</body>
</html>