I am currently developing a .stl viewer using Three.js with the objective of selecting and calculating specific areas within the model. To achieve this area calculation, I need the capability to select faces (e.g. change color).
Although I came across something similar, my research indicates that it only works with pre-made meshes (like the cube in the example).
I aim to incorporate this example into my own code.
While there are existing solutions, I am struggling to implement a functional method in my code:
My current code includes a fully operational .stl loader and viewer. The raycaster exists, but it's not functioning correctly, so I have temporarily disabled it. Credits to Mugen87 for the fix!
You can access my code and an example .stl file on GitHub. It only requires a Live Server environment, which can easily be set up using VSCode (refer to the readme).
Here's a snippet of my current code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3d viewer tjalle</title>
<link rel="stylesheet" type="text/css" href="../style/render.css">
</head>
<body>
<script src="https://rawcdn.githack.com/mrdoob/three.js/r117/build/three.min.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/r117/examples/js/loaders/STLLoader.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/r117/examples/js/controls/OrbitControls.js"></script>
<script>
function init() {
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
document.addEventListener( 'mousemove', onMouseMove, false );
function onMouseMove(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}
// Basic setup
scene = new THREE.Scene();
scene.background = new THREE.Color(0xdddddd);
// Camera setup
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 5000);
// Renderer setup
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// Camera Positioning
camera.rotation.y = 45 / 180 * Math.PI;
camera.position.x = 800;
camera.position.y = 100;
camera.position.z = 1000;
// Orbit control for camera
let controls = new THREE.OrbitControls(camera, renderer.domElement);
// Ambient lighting
hlight = new THREE.AmbientLight(0xffffff, 5.3);
scene.add(hlight);
// Point lights
light = new THREE.PointLight(0xffffff, 1, 10000);
light.position.set(0, 300, 500);
scene.add(light);
controls.update();
// Animation
function animate() {
raycaster.setFromCamera(mouse, camera);
scene.children[2].material.color.set(0x1313)
var intersects = raycaster.intersectObjects(scene.children);
for (var i = 0; i < intersects.length; i++) {
intersects[i].object.material.color.set(0xff0000);
}
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
// STLLoader setup
let loader = new THREE.STLLoader();
loader.load('../converter/output/output.stl', function (geometry) {
var material = new THREE.MeshLambertMaterial({
color: 0x1313,
wireframe: false
});
var mesh = new THREE.Mesh(geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.position.set(0, 0, 0);
scene.add(mesh);
renderer.render(scene, camera)
animate();
console.log("SCene: ", )
});
}
// Initialize method
init();
</script>
</body>
</html>