three.js - 指针事件未在 react-three-fiber 中触发
问题描述
我正在尝试将指针事件添加到使用 GLTFJSX 加载到 react-three-fiber 中的 GLTF 文件中。但是,指针事件不会触发,我不知道为什么。
我已经尝试将相同的事件添加到其他类似的代码沙箱中,并且它可以工作 - 那么如果我在做基本相同的事情,为什么它不能在这个示例中工作?
https://codesandbox.io/s/hopeful-brook-h8rhs?file=/src/App.js
- 预期行为:当您将鼠标悬停在模型上或单击它时,它应该被记录到控制台。
- 实际行为:只有
onPointerMissed
事件会触发。
有时,onPointerOver
andonPointerOut
事件确实有效。这似乎是随机起作用的——有时它起作用,但大多数时候它只是不起作用。
我错过了一些明显的东西吗?
编辑
当更改为mesh
时,指针事件起作用。skinnedMesh
所以这个问题与不检测指针事件直接相关。
解决方案
问题在于SkinnedMesh
修改了图形卡(GPU)中的顶点位置,因此 JavaScript 端在执行命中测试(也称为 Raycasting)时不知道顶点已被移动。看看下面的截图:
网:
当您使用Mesh
时,顶点显示在geometry.attributes.position
指示的位置。形状小而远,但您的鼠标事件按预期工作。
蒙皮网格:
使用SkinnedMesh
时,顶点在 GPU 中被平移得更近,但光线投射计算仍使用原始geometry.attributes.position
坐标进行命中测试。这就是为什么您只能在红框内的一个非常小的区域内获得预期的鼠标事件。
解决方案:
解决方案因您的用例而异,但您可以执行以下任何操作:
- 使用
Mesh
,并更新mesh.position
属性以将其移近相机。 - 如果需要
SkinnedMesh
,请尽量保持骨架位移足够小,以使其蒙皮位置不会偏离其原始位置太远。 - 您可以创建一个不可见的“hitbox”,然后将鼠标事件添加到其中。这是大多数游戏开发人员使用的方法,因为它可以更快地针对非常简单的几何体计算命中测试:
var hitGeom = new THREE.BoxBufferGeometry(1, 1, 1);
var hitMat = new THREE.MeshBasicMaterial({visible: false});
// ...
<mesh geometry={hitGeom} material={hitMat}>
推荐阅读
- c - 对 C 中的数组使用 scanf()
- javascript - 重定向组件被渲染但不会改变历史对象
- java - 如何将图像贴纸放在方框中?
- pascal - 嵌套 IF 错误“;” 预期但发现“标识符 GANJIL”
- python - 如何将 str.startswith 用于多列?
- c# - 无法将 MvvmCross 升级到 6.2.0
- node.js - 从 child_process.spawn() 向标准输入发送两个输入
- c# - 如何比较两个DatagridView的两列
- youtube - Youtube direct lite 给出错误:uploads.gdata.youtube.com's server IP address could not be found
- php - 如何从 URL PHP 中删除 GET 变量?