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