STUDIO: LookAt Rotation from a child object

I have a child object, which I would like to LookAt() at the camera object which does not have a parent. The two objects are not related in the hierarchy.

e.g.

Parent
- Child1
 - Child2 (eye)
Camera (target)

The problem I am running into is if any parents have any position or rotation values, then everything is thrown off.

I’ve noticed that ecs.Position.get() returns the local position, and not the world position - I can’t seem to find a WorldPosition function. If one exists please send it my way :pray: .

In the meantime I’ve attempted to make a quick and dirty one myself, but there is still some issues that maybe someone else can spot and remedy.

Functions:

function GetWorldPosition(world, eid) {
  if (eid) {
    const calculatedPosition = ecs.math.vec3.from(ecs.Position.get(world, eid))
    let objectParent = world.getParent(eid)

    while (objectParent) {
      const parentPosition = ecs.math.vec3.from(ecs.Position.get(world, objectParent))
      calculatedPosition.setPlus(parentPosition)
      objectParent = world.getParent(objectParent)
    }

    return calculatedPosition
  }
}

function GetWorldRotation(world, eid) {
  if (eid) {
    const calculatedRotation = ecs.math.quat.zero()
    let objectParent = world.getParent(eid)

    while (objectParent) {
      const parentRotation = ecs.math.quat.from(ecs.Quaternion.get(world, objectParent))
      calculatedRotation.setPlus(parentRotation)
      objectParent = world.getParent(objectParent)
    }

    return calculatedRotation
  }
}

Tick:

tick: (world, component) => {
    // Runs every frame.
    const {eid} = component
    const {rotateYOnly} = component.schema

    // Look at the camera.

    const cameraPosition = vec3.from(ecs.Position.get(world, world.camera.getActiveEid()))
    const objectWorldPosition = GetWorldPosition(world, eid)
   
    const lookAtQuaternion = quat.lookAt(objectWorldPosition, cameraPosition, vec3.up())
    
    // Undo the parents rotation
    lookAtQuaternion.setPlus(GetWorldRotation(world, eid))

    ecs.Quaternion.set(world, eid, lookAtQuaternion)
  }

I think I’ve found a very rough ‘solution’. I’ve ensured the parent only rotates on the Y axis and also ‘fixed’ my quat math by converting it to Euler, doing the subtract, then back to quat. I realize I could run into Gimbal Lock here but it doesn’t seem an issue so far.