1

I have a model loaded in from .obj and .mtl I want the user the be able to click on specific parts of the model and, for example, change their colour. i.e click on a door of the car and be able to change the colour of that door mesh.

Here's my model load code, if it's needed.

var mtlLoader = new THREE.MTLLoader();
    mtlLoader.setPath('Models/Aventador/');
    mtlLoader.load('Avent.mtl', function (materials) {
        materials.preload();
        var objLoader = new THREE.OBJLoader();
        objLoader.setMaterials(materials);
        objLoader.setPath('Models/Aventador/');
        objLoader.load('Avent.obj', function (object) {
            object.position.y = 0;          
            scene.add(object);
        }, onProgress, onError);
    });

EDIT: I now have the following code, which gives no errors and prints out 'mouseup' to the console as expected but does not print out any intersections as expected, any ideas what's wrong?

var mouse = new THREE.Vector2();
function onDocumentMouseUp(event) {
    console.log("mouseUp")
    mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
    var raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(mouse, camera);
    var intersects = raycaster.intersectObjects(scene.children);
    for (var i = 0; i < intersects.length; i++) {
        console.log(intersects[i]);
        intersects[i].object.material.color.set(0x0000ff);
    }
}

EDIT 2: helper arrows

Jack
  • 391
  • 5
  • 25
  • I have a feeling that the only way you could do this is if each part of the mesh that is "clickable" (e.g. the door) is a separate mesh loaded into the scene. Do you have the ability to break it up like that? – Hectate Dec 18 '16 at 17:04
  • @Hectate I'm not sure, I don't have much experience with 3D models. I found something that could iterate over the child meshes of the 3DObject and change their properties individually but that had no way to identify which mesh was which – Jack Dec 18 '16 at 17:07
  • Fair enough, I don't either. If it's made up of child meshes that you _can modify_ then what you're looking for an answer is a raycast to detect which component was "touched" and modify the settings of that one. Try: http://stackoverflow.com/questions/9275628/threejs-how-to-add-interactivity/9320071#9320071 – Hectate Dec 18 '16 at 17:12
  • @Hectate in that example what is `objects` in `ray.intersectObjects( objects );`? – Jack Dec 18 '16 at 17:16
  • If I had to guess it would be an array of objects in the scene. Let me provide an answer that should help more. – Hectate Dec 18 '16 at 17:42

1 Answers1

1

So for the clicking part, you'll want to raycast to the model from the mouse's position. The link below should give you enough information to get started:

Raycaster

The raycast should tell you what object you hit, and then you can remember that object for use (changing color properties, for example).

In answer to your other question, the objects is similar to the scene.children seen in the link above. You could also pass just the mesh to it and see if it hits that (instead of say, a light or a flat plane that you have the car sitting on for a surface).

Edit: Because it was an Obj, we figured out in chat that we needed to follow along with this answer and enable recursion on the raycast to get it to detect the portions of the model required.

xxx
  • 1,153
  • 1
  • 11
  • 23
Hectate
  • 210
  • 2
  • 9
  • tried that, doesn't look like its working, or I've got something wrong. See edit – Jack Dec 18 '16 at 18:07
  • It's almost certainly because you're using the mouse coordinates directly. If you look at some of the examples you'll see that they do some math to convert the mouse position to screen space: https://github.com/mrdoob/three.js/blob/master/examples/webgl_interactive_cubes.html – Hectate Dec 18 '16 at 18:13
  • Added that suggested maths. Still getting the same result as before – Jack Dec 18 '16 at 18:21
  • Perhaps draw an ArrowHelper along the ray to see where it's actually going then? If it's still appearing to intersect, then there might be something else going on. Here's a simple code from elsewhere on StackOverflow: `scene.add(new Three.ArrowHelper( raycaster.ray.direction, raycaster.ray.origin, 100, Math.random() * 0xffffff ));` – Hectate Dec 18 '16 at 18:25
  • It's definitely detecting the clicks in the right place and getting the vectors right, see Edit 2 – Jack Dec 18 '16 at 19:07
  • Maybe this is what you need: http://stackoverflow.com/questions/16138088/three-js-raycaster-not-intersecting-custom-mesh – Hectate Dec 18 '16 at 19:14
  • I don't have any geometry object, though? That looks like it's for primitives or objects manually constructed, not loaded .objs – Jack Dec 18 '16 at 19:25
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/130900/discussion-between-hectate-and-jack). – Hectate Dec 18 '16 at 19:53