【问题标题】:three.js can't select the objects with Raycasterthree.js 无法用 Raycaster 选择对象
【发布时间】:2014-11-30 20:15:18
【问题描述】:

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

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 中获得添加的模型,但我不能,有人有同样的问题吗?

【问题讨论】:

    标签: javascript jquery three.js


    【解决方案1】:

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

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

    另外,不要覆盖Object3D.id。改为设置Object3D.userData.id

    three.js r.68

    【讨论】:

    • 嗨,我做到了。我仍然无法选择相交的对象。
    • Jothi,这并不难。我打赌你会发现自己的错误。
    • 我找不到任何问题,所以我对这些事情感到沮丧,正在尽你所能得到相交的对象,但我失败了
    • 这可能与异步调用.load() 的回调有关吗?即回调不会在与.load() 本身相同的事件轮次中运行,因此场景直到未来某个不确定的时间才会收到新模型 - 可能只有几秒钟,但肯定会在未来的 javascript 事件轮次中。跨度>
    【解决方案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 );
    
    }
    

    【讨论】:

    • 我在您给定的示例中找不到任何Raycaster 相关术语?
    • Raycaster 位于 DisplaceControl 中。它适用于那些不想知道这样的 Raycaster =) 的人。如果需要任何其他机会,请修改 DisplaceControl.js 代码。
    • 我将 DisplaceControl 重命名为 ObjectControls,发现并纠正了一个错误,并更改了链接。如果它仍然是实际的,请更改。
    【解决方案3】:

    您正在使用没有要抓取的十六进制的 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 以快速回答该问题。

    希望这对您有所帮助!

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 2015-02-21
        • 1970-01-01
        • 2020-07-28
        • 2021-11-16
        • 2015-08-07
        • 1970-01-01
        • 2015-12-25
        • 2020-04-11
        • 1970-01-01
        相关资源
        最近更新 更多