ThreeJS中选中物体,并显示相关信息

博文参考

选中物体的原理

1、如果一个点A在被另一个物体B里面。
2、则从点A到空间另一点(C)的射线一定与物体B的边缘相交。
3、通过以物体B中心为起点,向物体的各个顶点发出射线,检测射线是否与其他点(A)相交,若相交则 检查最近的一个交点与射线起点的距离,如果这个距离比物体中心到物体顶点的距离都要小,则点A在 物体B里面 点A就是鼠标点击到世界坐标系中的坐标 物体B就是选中的物体 而点C就是相机的位置。

点A就是鼠标点击到世界坐标系中的坐标
物体B就是选中的物体
而点C就是相机的位置。

Raycaster基础概念

坐标系

我们的手机屏幕是二维的,但是我们展示物体的世界是三维的,当我们在构建一个物体的时候我们 是以一个三维世界既是世界坐标来构建,而转化为屏幕坐标展示在我们眼前,则需要经历多道矩阵 变化,中间webGL替我们操作了许多事情。

世界坐标系:在webGL中,世界坐标系是以屏幕中心为原点(0, 0, 0),且是始终不变的。你面对屏
幕,你的右边是x正轴,上面是y正轴,屏幕指向你的为z正轴。长度单位这样来定:窗口范围按此
单位恰好是(-1,-1)到(1,1),即屏幕左下角坐标为(-1,-1),右上角坐标为(1,1)。 

屏幕坐标系:webGL的重要功能之一就是将三维的世界坐标经过变换、投影等计算,最终算出它在显示设备上对应的位置,这个位置就称为设备坐标。在屏幕、打印机等设备上的坐标是二维坐标。

Raycaster

光线投射Raycaster

这个类设计用于鼠标去获取在3D世界被鼠标选中的一些物体

Raycaster( origin, direction, near, far )
origin — 射线的起点向量。
direction — 射线的方向向量,应该归一标准化。
near — 所有返回的结果应该比 near 远。Near不能为负,默认值为0。
far — 所有返回的结果应该比 far 近。Far 不能小于 near,默认值为无穷大。

代码实现

//将鼠标点击位置的屏幕坐标转成threejs中的标准坐标,具体解释见代码释义
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);
//射线和模型求交,选中一系列直线
var intersects = raycaster.intersectObjects(objects);
console.log('imtersrcts=' + intersects)
if (intersects.length > 0) {
//选中第一个射线相交的物体
SELECTED = intersects[0].object;
var intersected = intersects[0].object;
console.log(intersects[0].object)
}
}

代码释义

//得到
mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(e.clientY / window.innerHeight) * 2 + 1;
推导过程:
设A点为点击点(x1,y1),x1=e.clintX, y1=e.clientY
设A点在世界坐标中的坐标值为B(x2,y2);
由于A点的坐标值的原点是以屏幕左上角为(0,0);
我们可以计算可得以屏幕中心为原点的B'值
x2' = x1 - innerWidth/2
y2' = innerHeight/2 - y1
又由于在世界坐标的范围是[-1,1],要得到正确的B值我们必须要将坐标标准化
x2 = (x1 -innerWidth/2)/(innerwidth/2) = (x1/innerWidth)*2-1
同理得 y2 = -(y1/innerHeight)*2 +1

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Three.js,我们可以使用Css2DRenderer来实现在选中模型时显示对应的文字标签。Css2DRenderer允许我们在3D场景渲染2D元素,比如文字或者标签。 以下是实现的步骤: 1. 首先,创建一个新的Css2DRenderer对象,并将其与渲染器关联起来: ```javascript const css2dRenderer = new THREE.CSS2DRenderer(); css2dRenderer.setSize(window.innerWidth, window.innerHeight); css2dRenderer.domElement.style.position = 'absolute'; css2dRenderer.domElement.style.top = 0; document.body.appendChild(css2dRenderer.domElement); ``` 2. 创建一个CSS2DObject对象来表示文字标签。可以使用HTML元素来创建这个对象。例如,使用一个div元素来创建一个包含文字的标签: ```javascript const label = document.createElement('div'); label.className = 'label'; label.textContent = 'Hello, World!'; ``` 3. 创建一个CSS2DObject对象,并将其位置设置为所选模型的位置: ```javascript const cssObject = new THREE.CSS2DObject(label); cssObject.position.set(model.position.x, model.position.y, model.position.z); ``` 4. 将CSS2DObject添加到场景,并将其渲染到屏幕上: ```javascript scene.add(cssObject); css2dRenderer.render(scene, camera); ``` 5. 最后,为选中模型添加交互事件,以便在选中模型时显示标签。可以使用Raycaster来检测鼠标与模型的交互: ```javascript const raycaster = new THREE.Raycaster(); const mouse = new THREE.Vector2(); function onMouseMove(event) { // 计算鼠标的归一化设备坐标 mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = -(event.clientY / window.innerHeight) * 2 + 1; // 更新射线的位置和方向 raycaster.setFromCamera(mouse, camera); // 计算射线与模型的交互 const intersects = raycaster.intersectObjects(scene.children); if (intersects.length > 0) { // 选中模型时显示标签 const selectedModel = intersects[0].object; const cssObject = selectedModel.userData.label; cssObject.visible = true; } else { // 没有选中模型时隐藏所有标签 scene.traverse((child) => { if (child.userData.label) { child.userData.label.visible = false; } }); } // 渲染场景和标签 css2dRenderer.render(scene, camera); } window.addEventListener('mousemove', onMouseMove, false); ``` 记得在CSS文件定义.label类的样式,以控制标签的外观: ```css .label { position: absolute; background-color: rgba(0, 0, 0, 0.8); color: white; padding: 4px; } ``` 这样就可以在选中模型时显示对应的文字标签了。希望对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值