zoukankan      html  css  js  c++  java
  • 【Three.js】如何选中外部模型

    1.问题

        three.js中模型选中使用的是射线法,根据摄像机角度,鼠标点击位置和模型选中的distance参数判断来选中模型。对于原生的矢量模型完全没有问题,但是当遇到导入的外部模型,如obj、stl等的时候,就发现完全选中不了,本文就如果解决选中外部模型和原生模型问题进行解决。

        先说说射线法,参考文章:https://blog.csdn.net/qq_30100043/article/details/79054862

    (图片偷自:https://segmentfault.com/a/1190000010490845 )    


    2.选中原生矢量模型

        直接上代码:

    function click(e){
      // 声明 raycaster 和 mouse 变量
        var raycaster = new THREE.Raycaster();
        var mouse = new THREE.Vector2();
    
        // 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    
        //通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
        raycaster.setFromCamera(mouse, camera);
    
        // 获取与射线相交的对象数组,其中的元素按照距离排序,越近的越靠前
        var intersects = raycaster.intersectObjects(scene.children);
    
        var objs=[];
        for (var i = 0; i < intersects.length; i++) {
            var intersect = intersects[i];
            if (intersect.object instanceof THREE.Mesh) {
                var obj = intersect.object;
                //把距离加到模型用户数据里面,方便后面排序
                obj.userData.distance = intersect.distance;
                objs.push(obj);
            }
        }
    
        //按照距离排序
        objs = objs.sort(function (a, b) {
        return a.userData.distance - b.userData.distance;
        });
    
        //objs就是按照距离由近到远排列的选中模型数组集合
        //todo:后面操作渲染展示等等...
        //....
    }


    3.选中外部模型

        内容2中的方法可以实现完美选中立方体、圆柱等矢量三维模型,但是当场景中有obj等3d max导入的外部模型时却无法选中,为什么呢?原因参考文章:https://segmentfault.com/a/1190000004382956

         

    (图片来源:https://segmentfault.com/a/1190000004382956

        核心原因如上图,外部模型本质是一个group,里面包含了多个mesh,而内容2里面的方法其实只查询了scene下第一层的mesh模型,见下图。

        由此可以看出,要想选中外部模型,需要将遍历对象修改为外部模型的children就可以了。代码如下:

    function click(e){
      //声明 raycaster 和 mouse 变量
      var raycaster = new THREE.Raycaster();
      var mouse = new THREE.Vector2();
    
      // 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1
      mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
      mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    
      //通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线位置
      raycaster.setFromCamera(mouse, camera);
    
      //找到场景中所有外部模型
        var scensObjs = [];
        main.scene.children.forEach(child => {
        for (var i = 0; i < child.children.length; i++) {
          var obj=child.children[i];
          scensObjs.push(obj);
          }
        });
    
        //返回选中的外部模型对象
        var intersects = raycaster.intersectObjects(scensObjs);
    
        var objs = [];
        for (var i = 0; i < intersects.length; i++) {
            var intersect = intersects[i];
            if (intersect.object instanceof THREE.Mesh) {
                var obj = intersect.object.parent;
                //把距离加到模型用户数据里面,方便后面排序
                obj.userData.distance = intersect.distance;
                objs.push(obj);
            }
        }
    
      //按照距离排序
      objs = objs.sort(function (a, b) {
          return a.userData.distance - b.userData.distance;
      });
    
      //objs就是按照距离由近到远排列的选中模型数组集合
      //todo:后面操作渲染展示等等...
      //....
    }
    
        用上面的方法就可以选中外部模型,不过会遇到一个问题,就是选中的外部模型不是整个模型,而是模型中的一部分,这个与模型有关系,上面就说过一个外部模型其实是一个group,里面有很多个mesh组成,射线法选中的模型只是一个mesh,也就是group的children的某一个。如果想返回整个模型,很简单,取mesh的parent就可以了。代码如下:
    //假设selectedMesh是选中的外部模型中的一部分
    var selectedMesh=...;
    //obj就是整个模型
    var obj=selectedMesh.parent;
     


    4.如何同时选中外部模型和原生模型

        现在来整合一下内容2和内容3的方法,如果能一次同时选中外部模型和矢量模型。具体实现代码,请移步我的博客查看:http://www.88gis.cn/web/pages/blog/blogInfo.html?id=2bfbc05f-db14-4051-a64c-14579ebb7b25

      

    更多前端、GIS相关博客,请访问我的个人博客88gis.cn查看更多。   




  • 相关阅读:
    N的阶乘:高精度
    蓝桥杯历届试题 连号区间数:枚举(含样例解释)
    最大公共子串:DP
    IncDec序列:差分+贪心
    [ACM] hdu 1465 不容易系列之一(错排复习)
    写给现在,写给未来
    [ACM] hdu 2082 找单词 (母函数)
    [ACM] poj 1146 ID Codes(字符串的下一个排列)
    [ACM] hdu 2149 Public Sale (巴什博奕)
    [ACM] hdu 1846 Brave Game (巴什博奕)
  • 原文地址:https://www.cnblogs.com/tracyjfly/p/9999675.html
Copyright © 2011-2022 走看看