Three.js如何選中外部模型


1.問題

    three.js中模型選中使用的是射線法,根據攝像機角度,鼠標點擊位置和模型選中的distance參數判斷來選中模型。對於原生的矢量模型完全沒有問題,但是當遇到導入的外部模型,如obj、stl等的時候,就發現完全選中不了,本文就如果解決選中外部模型和原生模型問題進行解決。

    先說說射線法,參考文章:https://blog.csdn.net/qq_30100043/article/details/79054862

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;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM