Implementing Camera Zoom on Collision

Hello everyone,

I’m looking to implement a feature where the camera zooms in on a locked target mesh when it collides with another mesh. As shown in the attached video, the camera manages to zoom in during a collision. I’m eager to learn how to recreate this behavior.

Thanks!

I managed before doing this automatically by following this documentation guide:

I’ve applied the principles discussed on the page, but I require something slightly different. When an object appears between the camera and its locked target, the camera should zoom in. As it stands, when the camera collides with the terrain, it remains immobile.

What should happen instead is that the camera performs a raycast from its current position to the locked target. If it detects any objects in this path, it should zoom in to the position of the detected object.

You can see this behavior in the attached video - even when the camera is quite far away, it zooms in on the locked target as soon as it detects an object in between.

how about this action?
https://playground.babylonjs.com/#F6EH15

1 Like

This makes sense! It at least covers the scenario where the camera zooms in upon colliding with an object. However, it doesn’t address the second scenario (check my second video) where the camera is far away, not colliding with an object, but an object moves between the camera and the locked target

It’s a bit of a cheat.
https://playground.babylonjs.com/#F6EH15#1

3 Likes

@11128 That looks cool! Thank you! Can we also get the position of box.isOccluded?

1 Like

Can you tell me what the position of the box you are talking about means (what you need)?
Think of isoccluded as literally working when the box is not visible to other meshes, etc.

Camera => Sphere back => Sphere front => target (box), can we get the position of Sphere front so we can set camera’s position to it.

First of all, the late reply means that at the time, i have already left work and just taking a break.

anyway. I tried to implement a collision-based implementation without rays
But I think this is too expensive and dirty. even I can’t get the desired value

https://playground.babylonjs.com/#F6EH15#6
https://playground.babylonjs.com/#F6EH15#7

For example, you want to get the value of the front position of a sphere.
I tried to save the position value until the end of the hit and copy it to camera, but something wasn’t right.

so. I used ray and
Its hits tell me the meshes when they are occluded and also tell me the hit points.
https://playground.babylonjs.com/#F6EH15#10

1 Like

Thank you so much for all your effort! This helps tremendously!

Sorry for my vague reply . . :woozy_face:

I didin’t test yet and didn’t find my old code so, check out this code I modified from an AI:

// Title:
// Ray collision camera

// Brief:
// Adjusts position of ArcRotateCamera when any objects are in between target and camera

// Description:
// In this code, we create a scene with an ArcRotateCamera, a target object, and an obstruction object. 
// The adjustCameraPosition function is called in the render loop and checks if there is any obstruction between the camera's target and its position. 
// If an obstruction is detected, the camera's position is adjusted to move it away from the obstruction along the camera's ray direction.
// You may need to adjust the code based on your specific setup and requirements.

// Author:
// Generated by an AI and modified by SkyHops

// Import BABYLON
import * as BABYLON from 'babylonjs';

// Get canvas
const canvas = document.getElementById('renderCanvas');
// Create engine
const engine = new BABYLON.Engine(canvas, true);
// Create scene
const scene = new BABYLON.Scene(engine);

// Create arc rotate camera
const camera = new BABYLON.ArcRotateCamera('camera', 0, 0, 10, new BABYLON.Vector3(0, 0, 0), scene);
camera.setPosition(new BABYLON.Vector3(0, 0, -10));
camera.attachControl(canvas, false);

// Create target object
const target = BABYLON.MeshBuilder.CreateSphere('target', { diameter: 1 }, scene);
target.position = new BABYLON.Vector3(0, 0, 0);

// Create obstruction object
const obstruction = BABYLON.MeshBuilder.CreateBox('obstruction', { size: 2 }, scene);
obstruction.position = new BABYLON.Vector3(0, 0, -5);

// Function to adjust camera position when obstruction is in between
function adjustCameraPosition() {
  const ray = new BABYLON.Ray(camera.position, camera.target.subtract(camera.position));
  const pickInfo = scene.pickWithRay(ray);
  
  if (pickInfo.hit && pickInfo.pickedMesh !== target) {
    let distance = pickInfo.distance - 0.5; // Adjust the distance to leave some space between the obstruction and the camera
    const newPosition = camera.position.add(ray.direction.multiplyByFloats(distance, distance, distance));
    camera.setPosition(newPosition);
  }
}

// Render loop
engine.runRenderLoop(function () {
  // Adjust camera position
  adjustCameraPosition();
  
  // Render scene
  scene.render();
});

// Window resize event
window.addEventListener('resize', function () {
  engine.resize();
});

:robot:

This is the PG of quoting
https://playground.babylonjs.com/#F6EH15#11

The differences are as follows

  1. always ray check (It’s better if it only works when camera move.)
  2. ray check when occlusded

but I’m sure both will work.

1 Like