yomotsu / camera-controls

A camera control for three.js, similar to THREE.OrbitControls yet supports smooth transitions and more features.

Home Page:https://yomotsu.github.io/camera-controls/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Trackball control like rotation

madsendennis opened this issue · comments

Is your feature request related to a problem? Please describe.

I would like to use the controller with a "trackball" like control mechanism - like the one from the threejs examples.

This would allow for continuous rotation around an object without the viewing angle being locked - and a more natural rotation for inspecting objects from different sides where there is no obvious up vector.

Is this already possible with the controller through configuration? Or what would need to be updated to include this?

Thanks a lot for this great package.

Describe the solution you'd like

No response

Describe alternatives you've considered

No response

Additional context

No response

Thanks for your feature request.
However, unfortunately, camera-controls can't do that.
The vertical rotation must be between 0 and Math.PI (which is 180degs) inclusive.

If you need Trackball control, please use TrackballControls in three.js.

Hi @yomotsu , thanks for getting back to me.

I still prefer all the functionality that comes with camera controls. So I would need some mixture of the two. One way to "fix" it is to update the camera.up after each interaction in the camera-controls lib. This is also done in this repo: https://github.com/JaneliaSciComp/three-orbit-unlimited-controls
But I do not get the expected behaviour. Maybe you can easily spot the problem?

let camera = new THREE.OrthographicCamera(...)
camera.up.set(0.0, 0.0, 1.0);

let controls = new CameraControls(camera, container);

controls.addEventListener('sleep', () => {
  fixUp();
});

const fixUp = () => {
  const target = controls.getTarget();
  const view = new THREE.Vector3()
    .subVectors(target, camera.position)
    .normalize();
  // So first find the vector off to the side, orthogonal to both this.object.up and
  // the "view" vector.
  const side = new THREE.Vector3()
    .crossVectors(view, camera.up)
    .normalize();
  // Then find the vector orthogonal to both this "side" vector and the "view" vector.
  // This vector will be the new "up" vector.
  const up = new THREE.Vector3().crossVectors(side, view).normalize();
  camera.up.copy(up);
  controls.updateCameraUp();
};

I don't know if it is the updateCameraUp that is not able to handle a different 'up' vector, since it referes to _AXIS_Y?

try this:

const fixUp = () => {
  const target = controls.getTarget();
  const view = new THREE.Vector3()
    .subVectors(target, camera.position)
    .normalize();
  // So first find the vector off to the side, orthogonal to both this.object.up and
  // the "view" vector.
  const side = new THREE.Vector3()
    .crossVectors(view, camera.up)
    .normalize();
  // Then find the vector orthogonal to both this "side" vector and the "view" vector.
  // This vector will be the new "up" vector.
  const up = new THREE.Vector3().crossVectors(side, view).normalize();
  camera.up.copy(up);
  
  const position = this.getPosition( new THREE.Vector3() );
  controls.updateCameraUp();
  this.setPosition( position.x, position.y, position.z );
};

Screen.Recording.2023-03-17.at.1.55.56.mp4

We also could add this as cameraControls.applyCameraUp().

Thanks. It works. I think that would be very handy. I don't know if there is a more intuitive way to automatically apply applyCameraUp than I do now:

controls.addEventListener('controlend', () => {
      controls.addEventListener('sleep', this.updateUpVector);
    });

If so, maybe there could even be an automaticUp flag that would automatically call the applyCameraUp(). Then the interaction is very close to a trackball controller I think.

Good to hear that, but I think this disables (or breaks) some features of the camera control, such as reset( true ).

Perhaps automaticUp is better handled in userland as it causes confusions, because camera-controls is not a TrackballControls.