Move camera in front of picked face

Hello guys,

I am building a small framework on top of BabylonJS. Now I want to add an example or add the possibility for facing a selected face of any object.

My first step is doing so using the ArcRotationCamera.

An example of the behavior I am looking for can be seen here: https://showroom.littleworkshop.fr/
As soon as you click on an object. The camera is facing the selected object.

I want to be able to face the objects’ picked face.

function facePickedSite(e: BABYLON.ActionEvent) {
    const mesh = e.meshUnderPointer

    if (mesh.isFacetDataEnabled) {
      const vector = mesh.getFacetLocalNormals()[e.additionalData.faceId]
    }
  }

This code seems to give me the normal vector of the selected face. What are the next steps?

Kind regards

EDIT:
I now have this function to animate the movement, but I need to calculate the alpha and beta required to face the clicked face correctly.

function moveCamera() {
        const alphaAnim = new BABYLON.Animation(
          'alphaAnim',
          'alpha',
          60,
          BABYLON.Animation.ANIMATIONTYPE_FLOAT,
          BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT,
        )
        const betaAnim = new BABYLON.Animation(
          'betaAnim',
          'beta',
          60,
          BABYLON.Animation.ANIMATIONTYPE_FLOAT,
          BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT,
        )

        const alphaKeys = [
          { frame: 0, value: camera.alpha },
          { frame: 100, value: 0 },
        ]
        const betaKeys = [
          { frame: 0, value: camera.beta },
          { frame: 100, value: 0 },
        ]

        alphaAnim.setKeys(alphaKeys)
        betaAnim.setKeys(betaKeys)

        camera.animations.push(alphaAnim)
        camera.animations.push(betaAnim)
        camera._scene.beginAnimation(camera, 0, 100, false)
      }

Hey, you don’t actually have to calculate the alpha and beta of the ArcRotateCamera, you can use vectors as well! There is camera.position and camera.target, which can also be animated. I’d suggest you set the target to the origin of your normal and the position to normalOrigin.add(normal.multiplyByFloats(wantedRadius, wantedRadius, wantedRadius));

Thank you for the feedback. The way I understood what you wrote I came up with this snipped

const vector = mesh.getFacetLocalNormals()[e.additionalData.faceId]
const newPosition = vector.add(vector.multiplyByFloats(5, 5, 5))
// newPosition.y = camera.target.y // with this it works for the sides
camera.setPosition(newPosition)

In the case of a simple Box this works for the top and bottom face. For the others I am slightly below where I want to be.

EDIT:
This works so far the best, however clicking on the top or bottom rotates the camera slightly,

const radius = 5
const vector = mesh.getFacetLocalNormals()[e.additionalData.faceId]
const newPosition = e.additionalData.pickedPoint.add(
  vector.multiplyByFloats(radius, radius, radius),
)

Here the whole function code so far

function facePickedSite(e: BABYLON.ActionEvent) {
    try {
      const radius = 5
      const vector = e.meshUnderPointer.getFacetLocalNormals()[e.additionalData.faceId]
      const newPosition = e.additionalData.pickedPoint.add(
        vector.multiplyByFloats(radius, radius, radius),
      )

      const fps = 60
      const totalFrames = 60

      const positionAnim = new BABYLON.Animation(
        'positionAnim',
        'position',
        fps,
        BABYLON.Animation.ANIMATIONTYPE_VECTOR3,
        BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT,
      )

      const positionKeys = [
        { frame: 0, value: camera.position },
        { frame: totalFrames, value: newPosition },
      ]

      positionAnim.setKeys(positionKeys)
      camera.animations.push(positionAnim)
      camera._scene.beginAnimation(camera, 0, totalFrames, false)
    } catch (error) {
      console.error(error)
    }
  }
```
Problems:
- clicking the top or bottom face of a cube results in wrong camera rotation (the visible edges of the cube are not aligned to the screen, the cube itself doesn't have rotation)
- the animation zooms in and out, instead of moving directly or via curve to the new position

Maybe you have some limits on your camera set up that prevent correct movement?

We could much better help if you provided a playground with this code. Seems simple enough.

Haven’t thought about doing one since I am working with a different syntax. But here it is: Babylon.js Playground

Seems like your animation was kind of wrong. I use the helper function and it isn’t behaving off anymore: https://playground.babylonjs.com/#ZSA2P6#1
There is still some issue when the camera wants to look straight up or down, but that seems like a gimbal lock problem to me… someone else should comment on that. Try uncommenting line 10 though, then you don’t have that problem anymore.

2 Likes

This almost works as intended, and so much simpler than I thought.
The only issue that remains is the rotation of the camera as you mentioned.

Thanks a lot so far :smiley:

Hello @Myrmod just checking in, was your question answered? :slight_smile:

Oh yes, everything is fine thanks :slight_smile:

1 Like