Camera controls based on object bounding box?

Normal orbit controls from three.js is perfect for round object, but not good for long object (especially when zoom close), I'm looking for a solution to solve that.

It's hard to describe in words, please view this webgl example from Google (zoom in maximum to see): https://www.google.com/o3d/shopping/viewer/360?q=ymMBhK8fu3C&o3ds=use_3d 在这里输入图像描述

This is top view illustration of what I'm looking for: 在这里输入图像描述

I was thinking about use based on default OrbitControls, continuous cast ray from camera to bounding box and keep a constant distance, but the problem is the camera always looking at the center of object, unlike in the above example (cam only rotate when reaching to the corner of object).

Any ideas would be greatly appreciated.


As you pointed out, using the existing THREE.OrbitControls and modifying the target does not work as the camera wouldn't look perpendicularly at the bounding box.

I tried different things, with quite bad results but here's my work.
In every solution I tried, I always had to compute (in any order) :

  • the position of the camera ;
  • the direction of the camera.
  • In any case, the camera must rotate around something. So, all my solutions are more or less based on the THREE.OrbitControls , which acts as, say, "the current state of the rotation" and handles all DOM events stuff for me.


    Looking at the closest point on the AABB

    The idea is the following :

  • The camera rotates ;
  • the closest point on the AABB from the camera is where the camera should look at (direction) ;
  • a certain distance d is used to push the camera away from this point (position).
  • There are 2 cases :

  • The border

  • The corner

  • Tested on this (very tricky) fiddle. Still need to fix top and bottom faces though (rotation singularity).


    Raycasting on a bounding volume

    This is the idea you described in the question :

  • Create a bounding volume the camera should follow ;
  • raycast the camera position on this BV ;
  • the new position of the camera is the intersection point ;
  • the new direction of the camera is the normal of the intersected face.
  • I tried it with a subdivided box geometry with rounded borders and corners so that the camera rotates at angles.

    Considering the smoothness of the surface, the result could have been very convenient. Unfortunately, the camera sharply changes direction when the normal of the intersection changes, causing unpleasant bumps in the motion.

    See this (tricky again) fiddle.

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

    Note that this solution is quite heavy (raycasting a lot of faces) and may requires some pre-processing to create the BV.


    Changing the basis of the classical Orbit Controls

    This is not exactly what you're looking for but it's also suitable for long objects and, honestly, that's the less tricky solution I made.

    The idea is to modify the basis on which the classical THREE.OrbitControls operates so that the position is modified but the direction remains unchanged, like the following :

    I sort of did it with a customized version : THREE.BasisOrbitControls . Take a look at this fiddle.

    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 motion of the camera is described by an ellipsoid .


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

    链接地址: http://www.djcxy.com/p/95346.html

    上一篇: 是否可以修改服务工作者缓存响应头文件?

    下一篇: 基于对象边界框的相机控件?