A框架:无法成功设置场景子对象的世界位置

时间:2019-04-10 23:34:55

标签: three.js aframe coordinate-transformation webvr

基本上,在我的场景中,我有一个带有激光控件的实体和一个以下结构的光线投射器:

   <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>

我的目标是在激光线的当前x,y位置召集库存,我已经可以访问与激光线末端相对应的点。我不希望广告资源再次从该位置移动。如果将清单设置为raycaster的子级,它将始终随行移动。如果将清单设置为场景的子项,同时将其位置设置为应该位于该点的世界坐标,则它将不起作用。

我尝试过并失败的方法:

  • 以raycaster的子级开始清单,并将父级更改为场景并应用raycaster的世界矩阵
  • 将清单保留为raycaster子级,捕获其初始世界矩阵,并在每个刻度上设置相同的世界矩阵

最后,我目前的方法(带有代码)仍然失败

1。将线端的局部坐标转换为世界坐标

2。将广告资源追加到场景

3。将世界坐标从线端转换为场景的局部坐标

4。将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线末端的位置

1 个答案:

答案 0 :(得分:0)

最终找到了解决方案。这是在控制器单击事件的事件侦听器上运行的(需要注意的是,它不必在每个刻度上都运行,它只运行一次)

  1. 创建了一个虚拟节点,该节点是raycaster的子节点,并将其位置设置为行尾的x,y坐标以及我想要的任何z坐标
  2. 将适当的清单节点添加到场景中
  3. 使用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
    

如果希望通过使虚拟节点是照相机的子代而不是光线投射器的子代来生成用户正在查看的某个实体,则可以应用相同的思维过程