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查看更多。

【Three.js】如何选中外部模型的更多相关文章

  1. Three.js如何选中外部模型

    1.问题 three.js中模型选中使用的是射线法,根据摄像机角度,鼠标点击位置和模型选中的distance参数判断来选中模型.对于原生的矢量模型完全没有问题,但是当遇到导入的外部模型,如obj.st ...

  2. WebGL three.js学习笔记 加载外部模型以及Tween.js动画

    WebGL three.js学习笔记 加载外部模型以及Tween.js动画 本文的程序实现了加载外部stl格式的模型,以及学习了如何把加载的模型变为一个粒子系统,并使用Tween.js对该粒子系统进行 ...

  3. 原始js调用 选中事件

    curRadio.get(0).checked=true;//原始js调用 选中事件,curRadio是radio单个对象

  4. js获取选中日期的当周的周一和周日

    js获取选中日期的当周的周一和周日 第一种方法(推荐): function getWeekStr(str) { // 将字符串转为标准时间格式 str2 = Date.parse(str); let ...

  5. js中的盒子模型

    说到盒子模型,你第一时间会想到css盒子模型,css中的盒子模型包括(内容区+内边距+边框).那在js中怎么去获取这些属性值呢?下面一起来学习js中的盒子模型. css样式 body { margin ...

  6. 【黑金原创教程】【TimeQuest】【第五章】网表质量与外部模型

    声明:本文为黑金动力社区(http://www.heijin.org)原创教程,如需转载请注明出处,谢谢! 黑金动力社区2013年原创教程连载计划: http://www.cnblogs.com/al ...

  7. 【黑金原创教程】【TimeQuest】【第六章】物理时钟与外部模型

    声明:本文为黑金动力社区(http://www.heijin.org)原创教程,如需转载请注明出处,谢谢! 黑金动力社区2013年原创教程连载计划: http://www.cnblogs.com/al ...

  8. js、css外部文件的相对路径问题

    如果js.css外部文件有使用到相对路径时,需要注意其相对路径的基准是不一样的. 比如说,在index.html中引用到了外部的js和css文件,这两个文件都通过相对路径引用了某一张图片:这些文件所在 ...

  9. 【带着canvas去流浪(14)】Three.js中凹浮雕模型的生成方式

    目录 一. 方案1:ThreeBSP.js或ThreeCSG.js扩展库 二. 方案2:平面镂空模型拉伸 三. 方案3:Cinema 4D建模后输出模型文件 示例代码托管在:http://www.gi ...

随机推荐

  1. DataStage 六、安装和部署集群环境

    DataStage序列文章 DataStage 一.安装 DataStage 二.InfoSphere Information Server进程的启动和停止 DataStage 三.配置ODBC Da ...

  2. Python打开文件open()的注意事项

    刚刚用open(fileName)来打开txt格式的文件,总是出现错误,总是找不到文件读取的内容,后来才发现是open()在使用过程中自动关闭了.这里介绍另种方法解决这个问题. 第一种方法. with ...

  3. CI框架入门教程

    1. URL常用的相关函数 url相关函数在辅助类url中第一,要使用它们必须先加载$this->load->helper('url')或者自动装载    site_url('控制器/方法 ...

  4. Linux的系统引导

    启动引导: 1.主机加电自检,加载BIOS信息 2.读取MBR的引导文件[grub lilo] 3.引导linux内核 4.运行第一个进程init pid=1 5.进入相应的运行级别[0-6] 6.运 ...

  5. Oracle物化视图的一般使用

    普通视图和物化视图根本就不是一个东西,说区别都是硬拼到一起的,首先明白基本概念,普通视图是不存储任何数据的,他只有定义,在查询中是转换为对应的定义SQL去查询,而物化视图是将数据转换为一个表,实际存储 ...

  6. ImageUploader卸载教程-Xproer.ImageUploader

    1.1. 手动卸载控件-Windows XP 主要步骤如下: 1.关闭所有IE 2.打开cmd 3.进入C:\Windows\System32 4.输入命令regsvr32 -u ImageUploa ...

  7. PHP(一)基础语法和数据类型

  8. Duplicate Symbol链接错误的原因总结和解决方法[转]

    from:http://www.cocoachina.com/bbs/read.php?tid=177492 duplicate symbol是一种常见的链接错误,不像编译错误那样可以直接定位到问题的 ...

  9. swift 动画

    // //  ViewController.swift //  Anamation // //  Created by su on 15/12/9. //  Copyright © 2015年 tia ...

  10. 20169205实验三 敏捷开发与XP实践

    20169205实验三 敏捷开发与XP实践 实验内容及步骤 (一)敏捷开发与XP基本知识 敏捷开发(Agile Development)是一种以人为核心.迭代.循序渐进的开发方法. 一项实践在XP环境 ...