three.js无法使用Raycaster选择对象

时间:2014-10-06 14:29:08

标签: javascript jquery three.js

我有以下函数来获取所选对象,所以我的函数在这里

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;

    }
}

但我在intersects上获得了空数组,我尝试了我的最佳水平,但我无法找到任何解决方案,如果我控制scene.children我可以看到所有附加的对象现场 在此之前将对象添加到场景中就像这里一样

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);                            
      }
  );

现在我希望在new THREE.Object3D();中通过onMouseDown获取添加的模型,但我不能,任何人都有相同的问题?

4 个答案:

答案 0 :(得分:4)

您需要将recursive标记传递给Raycaster.intersectObjects()

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

另外,请勿覆盖Object3D.id。改为设置Object3D.userData.id

three.js r.68

答案 1 :(得分:0)

您正在使用没有十六进制抓取的MeshFaceMaterial。您必须从'材料'中获取'材料数组',如下所示:

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

这样您就不会选择MeshFaceMaterial,而是选择每个面使用的MeshLambertMaterial或MeshBasicMaterial。如果您使用图像作为纹理,我建议您查看Three.js material texture and color以快速回答该问题。

希望这有用!

答案 2 :(得分:0)

Raycaster有点棘手,我已经添加了解释

为使raycaster正常工作,需要完成以下典型设置:

首先初始化一个变量,以保存需要从中发出光线的鼠标位置

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();

我们需要创建一个Object3D父对象来容纳所有子网格物体

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);

添加事件侦听器以获取鼠标X,Y位置

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;
    }
  };

现在像这样使用raycaster:

  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);
  };

答案 3 :(得分:-2)

尝试完成此example。查看控制台中的消息。

<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 );

}