A 帧:无法成功设置场景子对象的世界位置
A-Frame: Cannot set world position of scene child object successfully
基本上在我的场景中,我有一个具有激光控制的实体和一个采用以下结构的光线投射器:
<a-scene>
<a-entity laser-controls raycaster ...>
<!--<a-entity id="inventory" ...> Could be inserted here-->
</a-entity>
<!--<a-entity id="inventory" ...> Could be inserted here-->
</a-scene>
我的objective是在激光线当前x,y位置召唤库存,我已经可以访问到激光线末端对应的点了。我不希望库存再次从那个位置移动。如果我将库存设置为光线投射器的子级,它总是随线移动。如果我将库存设置为场景的子项,同时将其位置设置为它应该位于的点的世界坐标,它就不起作用。
我尝试过但失败的方法:
- 以 raycaster 子级启动清单并将父级更改为场景并应用 raycaster 的世界矩阵
- 作为 raycaster child 保持库存,捕获它的初始世界矩阵并在每个 tick 上设置相同的世界矩阵
最后,我目前的方法(使用代码)仍然失败
1.Convering线端的局部坐标到世界坐标
2.Appending盘点到场景
3.Converting线端到场景局部坐标的世界坐标
4.Applying位置3到库存
let v = this.emptyVec
v.copy(this.raycaster.components.line.data.end)
this.raycaster.object3D.localToWorld(v);
this.el.appendChild(inventoryNode) //this.el is the scene
this.el.object3D.worldToLocal(v);
const {x,y} = v
inventoryNode.object3D.position.set(x,y,inventoryZDistance)
TLDR:如何在我将实体添加到场景时将实体设置到 raycaster 线末端的位置并使其永远保持在该位置
最终找到了解决方案。这是控制器点击事件的事件侦听器上的 运行ning(重点是它不需要在每个滴答上 运行,它只需要 运行 一次)
- 创建了一个作为 raycaster 子节点的虚拟节点,并将其位置设置为线端的 x、y 坐标以及我想要的任何 z 坐标
- 将正确的库存节点附加到场景
使用 setFromMatrixPosition() 方法从虚拟节点的世界矩阵设置库存位置
let dummyNode = document.createElement("a-entity")
dummyNode.setAttribute("id", "dummyinventory")
dummyNode.setAttribute("visible", false) //maybe unnecessary
const {x,y} = this.raycaster.components.line.data.end
dummyNode.object3D.position.set(x,y,inventoryZDistance)
this.raycaster.appendChild(dummyNode)
inventoryNode.setAttribute('look-at', "[camera]") //if you want inventory to face the camera
this.el.appendChild(inventoryNode)
setTimeout(()=>{
let newMatrix = dummyNode.object3D.matrixWorld
inventoryNode.object3D.position.setFromMatrixPosition(newMatrix)
},50) //give the world matrix of dummyNode some time to update, with no timeout sometimes fails
如果想要通过让虚拟节点成为相机的子节点而不是光线投射器来在用户正在查看的位置生成某个实体,则可以应用相同的思考过程
基本上在我的场景中,我有一个具有激光控制的实体和一个采用以下结构的光线投射器:
<a-scene>
<a-entity laser-controls raycaster ...>
<!--<a-entity id="inventory" ...> Could be inserted here-->
</a-entity>
<!--<a-entity id="inventory" ...> Could be inserted here-->
</a-scene>
我的objective是在激光线当前x,y位置召唤库存,我已经可以访问到激光线末端对应的点了。我不希望库存再次从那个位置移动。如果我将库存设置为光线投射器的子级,它总是随线移动。如果我将库存设置为场景的子项,同时将其位置设置为它应该位于的点的世界坐标,它就不起作用。
我尝试过但失败的方法:
- 以 raycaster 子级启动清单并将父级更改为场景并应用 raycaster 的世界矩阵
- 作为 raycaster child 保持库存,捕获它的初始世界矩阵并在每个 tick 上设置相同的世界矩阵
最后,我目前的方法(使用代码)仍然失败
1.Convering线端的局部坐标到世界坐标
2.Appending盘点到场景
3.Converting线端到场景局部坐标的世界坐标
4.Applying位置3到库存
let v = this.emptyVec
v.copy(this.raycaster.components.line.data.end)
this.raycaster.object3D.localToWorld(v);
this.el.appendChild(inventoryNode) //this.el is the scene
this.el.object3D.worldToLocal(v);
const {x,y} = v
inventoryNode.object3D.position.set(x,y,inventoryZDistance)
TLDR:如何在我将实体添加到场景时将实体设置到 raycaster 线末端的位置并使其永远保持在该位置
最终找到了解决方案。这是控制器点击事件的事件侦听器上的 运行ning(重点是它不需要在每个滴答上 运行,它只需要 运行 一次)
- 创建了一个作为 raycaster 子节点的虚拟节点,并将其位置设置为线端的 x、y 坐标以及我想要的任何 z 坐标
- 将正确的库存节点附加到场景
使用 setFromMatrixPosition() 方法从虚拟节点的世界矩阵设置库存位置
let dummyNode = document.createElement("a-entity") dummyNode.setAttribute("id", "dummyinventory") dummyNode.setAttribute("visible", false) //maybe unnecessary const {x,y} = this.raycaster.components.line.data.end dummyNode.object3D.position.set(x,y,inventoryZDistance) this.raycaster.appendChild(dummyNode) inventoryNode.setAttribute('look-at', "[camera]") //if you want inventory to face the camera this.el.appendChild(inventoryNode) setTimeout(()=>{ let newMatrix = dummyNode.object3D.matrixWorld inventoryNode.object3D.position.setFromMatrixPosition(newMatrix) },50) //give the world matrix of dummyNode some time to update, with no timeout sometimes fails
如果想要通过让虚拟节点成为相机的子节点而不是光线投射器来在用户正在查看的位置生成某个实体,则可以应用相同的思考过程