Controlling a camera based on a bounding object?

The normal orbit controls from three.js are ideal for a round object, but not suitable for a long object (especially when zoom is approaching), I'm looking for a solution to solve this issue.

Difficult to describe in words, please review this webgl example from Google (increase the maximum number to see): https://www.google.com/o3d/shopping/viewer/360?q=ymMBhK8fu3C&o3ds=use_3d enter image description here

This is the illustration above that I am looking for: enter image description here

I thought about using a continuous cast beam from the camera to the bounding box based on the standard OrbitControls and kept a constant distance, but the problem is that the camera always looks at the center of the object, in contrast to the above example (cam only rotates when the angle of the object is reached) .

We will be very grateful for any ideas.

+7
javascript 3d
source share
1 answer

As you pointed out, using the existing THREE.OrbitControls and changing the target does not work, since the camera will not look perpendicular in the bounding box.

I tried different things, with pretty bad results, but here is my job.
In every solution I tried, I always had to calculate (in any order):

  • camera position
  • camera direction .

In any case, the camera should revolve around something. So, all my decisions are more or less based on THREE.OrbitControls , which acts like, say, the "current state of rotation" and processes all the DOM event events for me.


Looking for the nearest point on AABB

The idea is this:

  • The camera rotates
  • the nearest point on the AABB from the camera is the place where the camera should look (direction);
  • a certain distance d is used to push the camera out of this point (position).

There are 2 cases:

  • The border
    nearest point on border

  • angle
    nearest corner point

Tested on this (very complex) violin . It is still necessary to fix the upper and lower surfaces, though (feature rotation).


Limited Ratings

This is the idea you described in the question:

  • Create the bounding volume that the camera should follow;
  • raycast camera position on this BV;
  • the new camera position is the intersection point ;
  • The new direction of the camera is the normal intersected surface.

I tried it with the geometry of a split block with rounded borders and corners so that the camera rotates at angles.

Raycasting on bv

Given the smoothness of the surface, the result could be very convenient. Unfortunately, the camera abruptly changes direction when the normal of intersection changes, causing unpleasant bumps in motion.

See this (complicated again) violin .

To fix this, we can linearly interpolate the normal along the triangle, but this requires that the normals be calculated in such a way that each normal of the vertex is the average of the normals of the faces to which this vertex belongs.

Normals interpolated along a face

Please note that this solution is quite heavy (raycasting a lot of faces) and may require some pre-processing to create a BV.


Changing the basics of classic orbit controls

This is not exactly what you are looking for, but it is also suitable for long objects and, frankly, the less complicated decision I made.

The idea is to modify the basis on which the classic THREE.OrbitControls , so that the position changes, but the direction remains the same, for example:

A new basis for orbital control

I did this with a special version: THREE.BasisOrbitControls . Take a look at this script .

 var basis = new THREE.Matrix4(); basis.makeScale(2.0, 3.0, 4.0); // my object is very long and a bit tall var controls = new THREE.BasisOrbitControl(camera, basis, renderer.domElement); 

Note that the resulting camera movement is described by an ellipsoid .


Hope this helps, I'm really interested in a clean solution.

+4
source share

All Articles