Introduction
In 3D applications, model highlighting plays a crucial role in providing visual feedback, improving user interaction, and enhancing immersion. The code above implements a model highlighting mechanism using Three.js and raycasting to detect and emphasize objects dynamically.
Raycasting for Model Selection
The raycasting technique is used to detect user interaction with 3D objects in the scene. The raycaster object, combined with a normalized pointer, determines which model is under the user’s cursor.
How It Works:
- Capturing Pointer Coordinates
- Converts the mouse position to normalized device coordinates.
- Casting a Ray from the Camera
- Shoots a ray into the scene based on the camera’s perspective.
- Filtering Target Objects
- Only predefined resistor objects are considered.
- Identifying Intersections
- If an object is hit, the function updates the material and panel data.
Code Snippet: Raycasting Logic
function raycastObjects(e) {
pointer.x = (e.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(e.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(pointer, camera);
let filterObjects = [
scene.getObjectByName("Resistor_4Band_001"),
scene.getObjectByName("Resistor_4Band_002"),
scene.getObjectByName("Resistor_4Band_003"),
scene.getObjectByName("Resistor_5Band_001"),
scene.getObjectByName("Resistor_6Band_001"),
].filter((obj) => obj);
let intersects = raycaster.intersectObjects(filterObjects, true);
if (intersects.length > 0) {
let object = intersects[0].object;
if (!object.name) return;
if (["resistor_base", "resistor_base_red", "resistor_base_blue"].includes(object.material.name)) {
highlightModels(object, new THREE.Color(0xffffff));
controlIntensity(object.parent.name);
updateDataPanel(object.parent.name);
}
}
}
Highlighting Mechanism
Once an object is selected, its appearance changes using a temporary highlight effect. The function highlightModels(object, color) replaces the object’s material with a highlighted version and gradually restores it.
How It Works:
- Stores the Original Material
- Before applying any highlight, the object’s original material is stored to ensure it can be restored later.
- Applies a Highlight Material
- A new MeshBasicMaterial is used to make the object visually distinct.
- Uses GSAP for Smooth Transitions
- The color transitions smoothly between the highlight and original colors.
Code Snippet: Highlighting Logic
let modelHighlightStates = new Map();
function highlightModels(model, highlightColor) {
model.traverse((child) => {
if (child.isMesh) {
let originalMaterial = child.material;
if (modelHighlightStates.get(child)) return;
modelHighlightStates.set(child, {
material: originalMaterial,
color: originalMaterial.color.clone(),
});
let highlightMaterial = new THREE.MeshBasicMaterial({
color: originalMaterial.color.clone(),
});
child.material = highlightMaterial;
let highlightDuration = 0.75;
gsap.to(highlightMaterial.color, {
r: highlightColor.r,
g: highlightColor.g,
b: highlightColor.b,
duration: highlightDuration,
onComplete: () => {
gsap.to(highlightMaterial.color, {
r: modelHighlightStates.get(child).color.r,
g: modelHighlightStates.get(child).color.g,
b: modelHighlightStates.get(child).color.b,
duration: highlightDuration,
onComplete: () => {
child.material = modelHighlightStates.get(child).material;
modelHighlightStates.delete(child);
},
});
},
});
}
});
}
Dynamic Light Intensity Adjustment
The highlighting system is enhanced with real-time lighting adjustments to reinforce visual feedback. The controlIntensity(resistor) function modifies RectAreaLight intensity based on the selected resistor.
How It Works:
- Maps Each Resistor to a Specific Light Intensity
- Different resistance values correspond to different intensities.
- Uses GSAP for Smooth Lighting Transitions
- Ensures gradual rather than abrupt intensity changes.
Code Snippet: Adjusting Light Intensity
function controlIntensity(resistor) {
let targetIntensity;
switch (resistor) {
case "Resistor_4Band_001": targetIntensity = 28.5; break;
case "Resistor_4Band_002": targetIntensity = 12.3; break;
case "Resistor_4Band_003": targetIntensity = 2.1; break;
case "Resistor_5Band_001": targetIntensity = 29.5; break;
case "Resistor_6Band_001": targetIntensity = 16.5; break;
default: targetIntensity = 10;
}
[rectLight1, rectLight2, rectLight3, rectLight4, rectLight5].forEach((light) => {
gsap.to(light, {
intensity: targetIntensity,
duration: 2,
ease: "power4.inOut",
});
});
}
Enhancing User Experience
The model highlighting system significantly improves user interaction and engagement in the 3D scene.
Key Benefits:
- Immediate Feedback – Users can quickly identify which object is selected.
- Enhanced Immersion – The scene feels more dynamic and responsive.
- Intuitive Data Representation – Users can easily associate resistor values with corresponding light intensities.