1
votes

Essentially in my scene I have an entity with laser controls and a raycaster in the following structure:

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

My objective is to summon the inventory at the current x,y position of the laser line, I already have access to the point corresponding to the end of the laser line. I don't want the inventory to move from that position again. If I set the inventory to be the child of the raycaster it always moves with the line. If I set the inventory to be the child of the scene whilst setting it's position to the world coordinates of the point where it's supposed to be, it just does not work.

Approaches I've tried and failed:

  • Starting the inventory as raycaster child and changing parent to the scene and applying the world matrix of the raycaster
  • Keeping inventory as raycaster child, capturing it's initial world matrix and setting that same world matrix on every tick

And finally, my current approach (with code) that still fails

1.Convering the local coordinates of the line end to world coordinates

2.Appending inventory to scene

3.Converting the world coordinates from line end into local coordinates of the scene

4.Applying the position in 3 to the inventory

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: How do I set an entity to the position of the raycaster line end at the point in time I add it to the scene and have it remain in that position forever

1

1 Answers

1
votes

Ended up finding a solution. This is running on the event listener for a controller click event (point being it doesn't need to run on every tick, it's run only once)

  1. Created a dummy node that is a child of the raycaster and set it's position to the x,y coordinates of the line end and whatever z coordinate I want
  2. Appended the proper inventory node to the scene
  3. Set the position of the inventory from the world matrix of the dummy node with the setFromMatrixPosition() method

    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
    

The same thought process could be applied if one wanted to spawn some entity where the user is looking by having the dummy node be a child of the camera instead of the raycaster