Camera Collision Detection

Hello all,

I am currently working on a project where you can view an object in a room.
The room is represented by a BoxGeometry.
The default position of the camera with OrbitControls is inside the room. I would like to make sure that the camera cannot leave the room.
Unfortunately I can use properties like polarAngle and azimuthAngle only conditionally, because a complete rotation of the camera within the room should be possible.

My idea was to determine in the update of the OrbitControl or the camera now whether the room is left, and thus prevent the update.

But before that I would like to know if there are better solutions for this problem, maybe even supported by threejs.

I am glad about every answer! Thanks a lot!

Kind regards
VForsmann

1 Like

you can use a raycaster between the orbit controls target and camera position. And adjust the camera position to any intersection.
Demo here : Raycaster Collision Detection - Three.js Tutorials (sbcode.net)
Source code here : https://sbcode.net/view_source/raycaster2.html
See the lines after
controls.addEventListener('change', function () { ...

2 Likes

This looks awesome!
Thank you very much :slight_smile:

A note regarding this - just raycasting will work in most collision situations, but sometimes you will still be able to see backfaces of the walls / through of the walls - that’s due to camera field of view reaching further than just the centre of the viewport (try slowly moving the camera along the ground plane in @seanwasere example, at some point you’ll also be able to through the floor.) As an example:

  1. You detect collisions on the way to target and move the camera to the last collision point:

  1. Camera is moved forward and centre of the screen does reach beyond the wall:

But the edges of the viewport will still be cutting through the walls.

To take that into account, you can either detect collisions using a sphere (with centre at the camera position, with radius adjusting to camera fov), or add fov-based padding after reaching the collision point (which will kinda be equivalent to sphere, just fewer math :sweat_smile: )

2 Likes

i recently bumped into this project: GitHub - yomotsu/camera-controls: A camera control for three.js, similar to THREE.OrbitControls yet supports smooth transitions and more features.

this has natural support for collisions and entrapment. search for boundary, there’s a demo for this, too.

3 Likes

Thank you very much guys!
With your solutions i could build what i wanted!
Could also adept it to the camera target not leaving the room and use some small maths to early detect the collision and have no problems with the camera fov!

1 Like

I am using Camera Control in this project, using forward and truck to move the camera, how to block the camera moving through the wall?

You can send a ray in the direction of the camera and if there is an intersection with the object or you can calculate the distance to that object, you can block to camera from moving in this direction.

Just looking for some additional advice here. I have written a player follow camera without using orbitcontrols. Used spherical coordinate formulae to update the mouse position on mouse drag. I raycast to the expected position of the camera, and if intersection found, i update the camera’s position to the intersection position of the raycast.
Some code:

if (intersects.length) {
      const offsetVector = directionVector.multiplyScalar(-0.25);
      this.camera.position.copy(
        intersects[0].point.clone().add(offsetVector.clone())
      );
    }

However, this solution isn’t perfect. @mjurczyk if you do see this, would love to know where I can learn more about the fov based padding approach. I tried sphere collisions like you mentioned, but i suspect it performs well in closed spaces (small room glb files). When the mouse is moved fast, the backfaces of the intersected meshes still show.
Would love to learn more from you guys!

@VForsmann what solution worked best for you? @seanwasere any inputs that you might have?