2

I am having the following function to get the selected object, so my function is here

function onMouseDown(event) {
    console.log(event);
    event.preventDefault();

    mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
    // find intersections

    var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
    projector.unprojectVector( vector, camera );


    var pLocal = new THREE.Vector3(0, 0, -1);
    var pWorld = pLocal.applyMatrix4(camera.matrixWorld);
    var ray = new THREE.Raycaster(pWorld, vector.sub(pWorld).normalize());




    ray.set( camera.position, vector.sub( camera.position ).normalize() );
    var intersects = ray.intersectObjects( scene.children );
    //console.log(intersects);
    console.log(scene.children);
    if ( intersects.length > 0 ) {

    var clickedObject = intersects[0].object;

    console.log('objects '+intersects[ 0 ].object);
    console.log('objects id'+intersects[ 0 ].object.id);
    console.log('objects name'+intersects[ 0 ].object.name);

    if ( INTERSECTED != intersects[ 0 ].object ) {

    if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );

    INTERSECTED = intersects[ 0 ].object;
    console.log('INTERSECTED '+INTERSECTED);
    INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
    INTERSECTED.material.emissive.setHex( 0xff0000 );

    }

    } else {

    if ( INTERSECTED ) INTERSECTED.material.emissive.setHex( INTERSECTED.currentHex );

    INTERSECTED = null;

    }
}

but am getting empty array on intersects , i tried my level best but i can't find any solution here, if i console the scene.children i can see all the attached objects of the scene on before this am adding the object into scene as like here

var   loader = new THREE.JSONLoader();      
loader.load("uploads/accessories/3d/code/3dfile_"+file+".js",
      function(geometry, object_material) 
      {

          var object = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(object_material));
          model = new THREE.Object3D();
          model.id="Myid"+file;
          model.name="Myname"+file;
          model.userData ={ URL: "http://myurl.com" };
          model.add(object);    
          model.position.set(x,y,z);        
          model.scale.set(obj_width,obj_height,obj_rotation);   
          model.opacity =2;
          model.rotation.y = 600; 
          model.duration = 12000;
          model.mirroredLoop = true;
          model.castShadow = true;
          model.receiveShadow = true;

          console.log(model);   
          var smodel=model;
          scene.add(smodel);                            
      }
  );

now i want to get the added model by new THREE.Object3D(); in onMouseDown but i can't, any one have the same issue ?

Jothi Kannan
  • 3,320
  • 6
  • 40
  • 77

4 Answers4

6

You need to pass in the recursive flag to Raycaster.intersectObjects().

intersects = ray.intersectObjects( scene.children, true );

Also, do not overwrite Object3D.id. Set Object3D.userData.id instead.

three.js r.68

WestLangley
  • 102,557
  • 10
  • 276
  • 276
  • Hi, i did it. still i can't select the intersected object. – Jothi Kannan Oct 07 '14 at 04:16
  • Jothi, this is not that difficult. I bet you can find your own mistake. – WestLangley Oct 07 '14 at 04:45
  • i can't find any issue from my side, so am getting frustrating about these things, am doing what all you are do to get the intersected objects, but i failed – Jothi Kannan Oct 07 '14 at 04:50
  • Is it possibly to do with `.load()`'s callback being called asynchronously? ie the callback does not run in the same event turn as `.load()` itself, therefore the scene does not receive the new model until some indeterminate time in the future - probably only a few seconds but certainly in a future javascript event turn. – Roamer-1888 Oct 07 '14 at 09:56
1

You are using a MeshFaceMaterial which doesn't have a hex to grab. You have to get the 'materials array' from the 'material' like so:

for(var p =0; p < INTERSECTED.material.materials.length; p++){
    INTERSECTED.currentHex = INTERSECTED.material.materials[p].emissive.getHex();
}

This way you are not selecting the MeshFaceMaterial but the MeshLambertMaterial or MeshBasicMaterial that you are using for each face. If you are using images as your textures I would suggest checking out Three.js material texture and color for a quick answer to that question.

Hope this was helpful!

Community
  • 1
  • 1
Endorox
  • 99
  • 9
1

Raycaster is little bit tricky I have added explanation

A typical setup need to be done for raycaster to work as follows:

first initialize a variable to hold mouse position from which we need to emit a ray

var mouse = {
  x: 0,
  y: 0
};

 //object intersected 
var INTERSECTED;

// pool of objects which can be selected
var objects = [];

// ray caster initialization
var  raycaster = new THREE.Raycaster();

We need to create a Object3D parent to hold all child meshes

let mainGroup = new THREE.Object3D();
// add into object pool
objects.push(mainGroup);
scene.add(mainGroup);


// add mesh to be select by ray caster in Object3D parent
mainGroup.add(meshToSelect);

Add an event listener to get mouse X,Y position

document.addEventListener("mousemove", this.onDocumentMouseMove, false);


  onDocumentMouseMove = event => {
    event.preventDefault();

    if (event && typeof event !== undefined) {
      mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
      mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    }
  };

Now use raycaster like this:

  renderScene = () => {

    // Emit ray
    raycaster.setFromCamera(mouse, this.camera);

    // all intersects 
    var intersects = raycaster.intersectObjects(objects, true);

    if (intersects.length > 0) {
      if (INTERSECTED != intersects[0].object) {
         //if new item selected swap color of new item 
         //& revert color of previous item
        if (INTERSECTED)
          INTERSECTED.material.color.setHex(INTERSECTED.currentHex);
        INTERSECTED = intersects[0].object;
        INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
        INTERSECTED.material.color.setHex(0xff0000);

      }
    } else {
       // None selected then revert color of previous item
      if (INTERSECTED)
        INTERSECTED.material.color.setHex(INTERSECTED.currentHex);
      INTERSECTED = null;
    }

    if (this.renderer) this.renderer.render(scene, this.camera);
  };
Hitesh Sahu
  • 41,955
  • 17
  • 205
  • 154
-2

Try to make through this example. Look at messages in the console.

<script src="js/controls/EventsControls.js"></script>

EventsControls = new EventsControls( camera, renderer.domElement );
EventsControls.draggable = false;

EventsControls.onclick = function() {

   console.log( this.focused.name );

}

var jsonLoader = new THREE.JSONLoader();
jsonLoader.load( "models/Tux.js", addModelToScene ); 


function addModelToScene( geometry, materials ) {

   var material = new THREE.MeshFaceMaterial( materials );
   model = new THREE.Mesh( geometry, material );
   model.scale.set( 10, 10, 10 ); model.name = 'Tux';
   model.rotation.x = -Math.PI/2; 
   model.position.set( 175, 45, 125 );
   scene.add( model ); 
   EventsControls.attach( model );

}
gevaraweb
  • 912
  • 7
  • 19
  • 1
    i can't find any `Raycaster` related terms on your given example ? – Jothi Kannan Oct 11 '14 at 06:01
  • Raycaster sits in a DisplaceControl. It for those who doesn't want to know that such a Raycaster =). If any additional opportunities are necessary, modify a DisplaceControl.js code. – gevaraweb Oct 11 '14 at 06:26
  • I renamed DisplaceControl to ObjectControls, and found and corrected a bug, and changed the link. If it is still actual, change too pleas. – gevaraweb Oct 14 '14 at 17:52