SimpleRaycaster
🤏 Touching things
In this tutorial, we'll learn to interact with our scene. This will work both for a mouse 🐀 and for the touch screen of a phone 📱 or tablet 🍎. This might sound daunting, but it's actually very easy! Let's see how to do that in 5 minutes.
If you haven't started there, check out that tutorial first!
Next, we will add some objects to pick. Specifically, we will add 3 boxes of different colors using Three.js API. To do that, first we need to create 4 materials: one material per box, and a fourth material to highlight boxes that we pick:
const redMaterial = new THREE.MeshStandardMaterial({ color: 'red' });
const greenMaterial = new THREE.MeshStandardMaterial({ color: 'green' });
const blueMaterial = new THREE.MeshStandardMaterial({ color: 'blue' });
const yellowMaterial = new THREE.MeshBasicMaterial({ color: 'yellow' });
Great! Now, we will add the geometry itself. For that we need 5 meshes that can share the same cube geometry (as all the geometry of the cubes is the same).
const boxGeometry = new THREE.BoxGeometry(3, 3, 3);
const redCube = new THREE.Mesh(boxGeometry, redMaterial);
const greenCube = new THREE.Mesh(boxGeometry, greenMaterial);
const blueCube = new THREE.Mesh(boxGeometry, blueMaterial);
scene.add(redCube, greenCube, blueCube);
const cubes = [redCube, greenCube, blueCube];
Let's give the cubes a different position so that we can see all of them in the scene:
greenCube.position.x = 5;
blueCube.position.x = -5;
🔄 Spinning up the cubes
To spice things up a little, let's create an animation loop that rotates the cubes each frame. You can do this super
easily by creating a function and adding it to the beforeUpdate
event of the RendererComponent inside
Components using the on()
method:
const oneDegree = Math.PI / 180;
function rotateCubes() {
redCube.rotation.x += oneDegree;
redCube.rotation.y += oneDegree;
greenCube.rotation.x += oneDegree;
greenCube.rotation.z += oneDegree;
blueCube.rotation.y += oneDegree;
blueCube.rotation.z += oneDegree;
}
components.renderer.beforeUpdate.on(rotateCubes);
You can turn off animations simply by using the off()
method.
This works for any event
in the library! ⌚
⚡ Casting rays around
Awesome! Now, when we pick a cube, we will substitute the original material by the yellow material. Afterwards, we
will need a way to get back the original material. We can easily achieve this by adding a reference to the material
in the userData
property, which is an object where you can add any data you need:
redCube.userData.originalMaterial = redMaterial;
greenCube.userData.originalMaterial = greenMaterial;
blueCube.userData.originalMaterial = blueMaterial;
Finally, we will use the raycaster. This is very easy using the raycaster component, which solves this for all screen sizes. We will create an event that fires every time that the user moves the mouse. 👇
We will simply reset the material of the previous selection (if it exists), and then apply the yellow material to the found object (if any). This might sound like a lot, but it's actually very little code. 😉
let previousSelection;
window.onmousemove = () => {
const result = components.raycaster.castRay(cubes);
if(previousSelection) {
previousSelection.material = previousSelection.userData.originalMaterial;
}
if(!result) {
return;
}
result.object.material = yellowMaterial;
previousSelection = result.object;
}
Great job! 🎉 Now you know how to pick geometry in your 3D scene using a raycaster component component! 💪 You are now one step closer to build your own BIM software. Let's keep it up and check out another tutorials!