WSA
WSA

Reputation: 43

AFRAME: Coordinates of the fixed point in front of the camera

I want to get the coordinates in space of the point in front of the camera, regardless of its angle of rotation. I need this point to draw a line from it to the object behind the camera, and I want the line itself to be visible, I want to put it in front of the camera at 1 meter.

Every scene tick:

  1. That is, when I rotate the camera (with the mouse or with the orientation of the smartphone), every tick I want to find the coordinates of a point that is perpendicular to the viewpoint at a distance of 1 meter. Camera rotated with look-controls component.

  2. Draw line to coordinate of target object from coordinate of 1m above camera point.

tick:

let posTarget = getEntityCenterPoint(entity);
if (!!posTarget) {

    let posCamera = this._currentCamera.getAttribute("position");
    let posViewer = new THREE.Vector3(posCamera.x, posCamera.y, posCamera.z  + 1);

    //create a blue LineBasicMaterial
    const material = new THREE.LineBasicMaterial( { color: 0x0000ff } );

    const points = [];
    points.push( posViewer, posTarget);
    const geometry = new THREE.BufferGeometry().setFromPoints( points );
    const line = new THREE.Line( geometry, material );
    this.el.setObject3D("mesh", line );
}

The problem is that posCamera does not update when I rotate the camera through look-controls. Please help me to find the coordinates of the point 1 meter in front of the camera(posViewer) every tick depending on the rotation.

I tried every tick to take the coordinates in front of the camera, but for some reason they are executed only once, and further turns of the camera are not updated and the line stays in place.

Upvotes: 0

Views: 163

Answers (1)

Piotr Adam Milewski
Piotr Adam Milewski

Reputation: 14645

Your calculation of (posCamera.x, posCamera.y, posCamera.z + 1) is the equivalent of 1 meter north of the camera. It doesn't take into accout where the camera is looking.

Two ways of getting the position in front of any object would be:

With a direction vector

Get a normalized direction vector, and add it to the add the position

<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<script>
  AFRAME.registerComponent("place-in-front-of-camera", {
    tick: function() {
      if (!this.el.sceneEl.renderStarted) return  // wait till ready

      // the reference to our position
      const position = this.el.object3D.position  
      // the reference to the THREE.Camera
      const camera = this.el.sceneEl.camera       
      // the aframe entity which moves with the camera
      const aframe_cam_wrapper = camera.el.object3D;  
      
      this.el.sceneEl.camera.getWorldDirection(position)  // "the direction i'm looking at"
      position.add(aframe_cam_wrapper.position) // plus the camera position
    }
  })

</script>
<a-scene>
  <a-sphere color="green" radius="0.05" place-in-front-of-camera></a-sphere>
  <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
  <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
  <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
  <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
  <a-sky color="#ECECEC"></a-sky>
</a-scene>

With local -> world transforms

If you want (0, 0, 1) in regard to the camera, you need to get those coords from the cameras frame of reference (being its local space), converted to the global frame of reference (being the world space):

<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<script>
  AFRAME.registerComponent("place-in-front-of-camera", {
    tick: function() {
      if (!this.el.sceneEl.renderStarted) return // wait till ready

      const position = this.el.object3D.position // the reference to our position
      const camera = this.el.sceneEl.camera // the reference to the THREE.Camera
      const front = new THREE.Vector3(0, 0, -1);
      camera.localToWorld(front);
      position.copy(front) // use it as the position
    }
  })
</script>
<a-scene>
  <a-sphere color="green" radius="0.05" place-in-front-of-camera></a-sphere>
  <a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
  <a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
  <a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
  <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
  <a-sky color="#ECECEC"></a-sky>
</a-scene>

Upvotes: 1

Related Questions