开始以为是鼠标移动事件频繁触发3D选中事件引起的,导入lodash的节流尝试后无效。
经过查询,是由于3D模型的点较多,使用raycaster.intersectObject会产生大量计算。
参考了这篇文章:
Three-mesh-bvh: A plugin for fast geometry raycasting and spatial queries! - Resources - three.js forum
采用MeshBVH插件进行碰撞检测。
初始化代码
// Import via ES6 modules
import * as THREE from 'three';
import { computeBoundsTree, disposeBoundsTree, acceleratedRaycast } from 'three-mesh-bvh';
// Or UMD
const { computeBoundsTree, disposeBoundsTree, acceleratedRaycast } = window.MeshBVHLib;
// Add the extension functions
THREE.BufferGeometry.prototype.computeBoundsTree = computeBoundsTree;
THREE.BufferGeometry.prototype.disposeBoundsTree = disposeBoundsTree;
THREE.Mesh.prototype.raycast = acceleratedRaycast;
导入glft模型
gltfLoader.load("./model/fan.glb", gltf => {
gltf.scene.traverse(child => {
if (child instanceof THREE.Mesh) {
(child as THREE.Mesh).geometry.computeBoundsTree();
绑定鼠标移动事件计算物体碰撞
this.mouseMoveToAllFjEvent = event => {
this.mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
this.mouse.y = -((event.clientY / window.innerHeight) * 2 - 1);
this.raycaster.setFromCamera(this.mouse, cameraModule.activeCamera);
const intersects = this.raycaster.intersectObject(this.fjDetailGroup);
if (intersects.length > 0) {
this.outLinePass!.selectedObjects = [this.fjDetailGroup];
} else {
this.outLinePass!.selectedObjects = [];
`Raycasting`是一种计算机图形学技术,用于确定从一个点(通常是观察者的位置或屏幕上的某一点)发射出的光线与场景中物体的交点。在`3D`应用中,这一技术常用于模拟光照效果、碰撞检测以及用户交互。简单来说,当你在屏幕上点击或触摸时,`Three.js`会从该点向场景发射一条虚拟的射线,然后检查这条射线与场景中哪些对象相交,从而判断用户点击了哪个对象。
模型一般都比普通的前端项目要大,普通的模型要在1MB,大一点的就上不封顶了。模型越大,电脑加载的时间就越长。为了避免用户判断为bug,或者随便点击导致产生其他bug。我们需要增加进度条来提示用户。
// Import via ES6 modules
import * as THREE from 'three' ;
import { computeBoundsTree , disposeBoundsTree , acceleratedRaycast } from 'three-mesh-bvh' ;
// Or UMD
const { computeBoundsTree , disposeBoundsTree , acceleratedRaycast } = window . MeshBVHLib ;
// Add the extension functions
THREE . BufferGeometry .
用鼠标在屏幕中拾取/选取对象1.demo效果2.知识要点2.1 光线投射对象Raycaster2.1.1 创建光线投射对象2.1.2获取射线交叉对象3.实现要点3.1 添加鼠标点击和悬浮监听事件3.2 屏幕坐标系转换为three.js 坐标系3.3 创建光线投射对象获取选取对象3.4 选中对象处理4.demo代码
1.demo效果
如上图,该demo实现鼠标可以在屏幕中选取球体、圆柱或方块,点击时改变其透明度。若勾选showRay属性。鼠标滑过对象时出现模拟投射射线的红色线条
2.知识要点
2.1 光线投
1.创建 Raycaster 实例
2.为窗口绑定事件 pointermove 想使用点击事件 click 的可以自行修改
3.定义窗口触发 pointermove 事件所执行的回调函数 onPointerMove
4.通过摄像机和鼠标位置更新射线
自己动手写一个方法比分析他人的写的方法困难很多,由此而来的对程序的进一步理解也是分析别人的代码很难得到的。
一、先来几张效果图:
1、场景中有两个半径为1的球体,蓝色线段从球心出发指向球体的“正向”
2、物体被选中后改变纹理图片和透明度,可以使用“w、s、a、d、空格、ctrl”控制物体相对于物体的正向“前、后、左、右、上、下”移动,按住按键时间越长移动速度越快,绿色线段由球心指向物体运...
学习资料:
上一篇:光追渲染器开发记录:基础渲染架构/线程池/泛型单例_This is MX的博客-CSDN博客https://blog.csdn.net/m0_56399931/article/det
包围层次盒BVH是一种场景管理技术,广泛应用于碰撞检测、射线相交测试之类的应用场合中。
bvTree有两种节点(Node)类型:Interior Node 和 Leaf Node。
LeafNode 是最终存放tile的地方
划分策略可以选择比较高端的表面积启发式算法(SurfaceArea Heuristic)
SAH基于的思想:如果某物的表面积越大,那么它被射线击中的...
本节介绍, three.js (webgl) 中 进行碰撞检测,其实,网上有方法介绍,使用射线,或者也可以使用官方的方法 ammo.js,这里由于自己使用的一些情况特殊,所以并没有使用官方的方法和射线方法,而是使用包围盒 + 位置判断的方法,来简单判断是否发生碰撞;2、然后根据移动物体与其他物体的位置差,同移动物体与其他物体包围盒对应的长宽高之和的一半,如果位置差的xyz 都小于移动物体与某个物体包围盒长宽高之和的一半,则可判断碰撞。2、在上面的基础上,添加一个 html ,用来实现案例效果,引入相关包。