I have been using OrbitControl in my app to allow rotating camera around the world. Recently I am trying to enhance the control to allow the camera to rotate around an arbitrary point, not just the camera lookAt point. I have not had much success yet.
In the code if I remove this: this.object.lookAt( this.target );
it did not work well. Any ideas?
Some pictures to clarify:
I rotated the camera around the center of the object (pivot), but the camera is not looking at the center.
Just update the controls.target property, for example:
controls.target.set(1, 5, 7);
or target a mesh:
controls.target.copy(mesh.position)
OrbitControls were designed for orbiting a scene, with the camera viewport looking directly at the controls rotation target. They are not designed to handle objects rotation separate from camera, they have TransformControls but those don't support damping.
Rotating with Orbit controls, locks your camera viewport to look at the center (the dotted line), and rotates around the center (the red line):
If you move/pan the target, both camera target and rotation center are moving together like this:
What you need is the rotation center and the camera target to be independent, so the camera rotates around the object, whilst looking at a certain point like this:
There seem to be two approaches to creating custom camera/rotation functionality:
1) Modify OrbitControls Change the camera.lookAt to be offset from controls.target
View changes needed to OrbitControls: https://github.com/sciecode/three.js/commit/dccf1578343bb9b7c79bb2eb2004d5ee34a76e6a#diff-ffef32863dd826c87a45cfb28c4ddd83
Demo of custom Orbit Controls: https://jsfiddle.net/kmturley/6qxh3zc9/28/
2) Modify TransformControls Change transform controls to allow damping, free spinning, and hide the gizmo overlays.
Demo of custom Transform Controls https://jsfiddle.net/kmturley/2p1v6bcw/18/
3) Create your own Object rotation controls
import * as THREE from "https://threejs.org/build/three.module.js";
var mesh, renderer, scene, camera, controls;
var radius = 5;
var group;
var targetRotationX = 0;
var targetRotationOnMouseDownX = 0;
var targetRotationY = 0;
var targetRotationOnMouseDownY = 0;
var mouseX = 0;
var mouseXOnMouseDown = 0;
var mouseY = 0;
var mouseYOnMouseDown = 0;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var finalRotationY
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
document.body.appendChild(renderer.domElement);
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera(40, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, radius * 2, radius * 2);
camera.lookAt(0, radius, 0)
// controls
/* controls = new OrbitControls( camera, renderer.domElement ); */
document.addEventListener('mousedown', onDocumentMouseDown, false);
document.addEventListener('touchstart', onDocumentTouchStart, false);
document.addEventListener('touchmove', onDocumentTouchMove, false);
// ambient
scene.add(new THREE.AmbientLight(0x222222));
// light
var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(20, 20, 0);
scene.add(light);
// geometry
var geometry = new THREE.SphereGeometry(radius, 12, 8);
// material
var material = new THREE.MeshPhongMaterial({
color: 0x00ffff,
flatShading: true,
transparent: true,
opacity: 0.7,
});
// mesh
group = new THREE.Object3D();
mesh = new THREE.Mesh(geometry, material);
group.add(mesh);
scene.add(group);
}
function onDocumentMouseDown(event) {
event.preventDefault();
document.addEventListener('mousemove', onDocumentMouseMove, false);
document.addEventListener('mouseup', onDocumentMouseUp, false);
document.addEventListener('mouseout', onDocumentMouseOut, false);
mouseXOnMouseDown = event.clientX - windowHalfX;
targetRotationOnMouseDownX = targetRotationX;
mouseYOnMouseDown = event.clientY - windowHalfY;
targetRotationOnMouseDownY = targetRotationY;
}
function onDocumentMouseMove(event) {
mouseX = event.clientX - windowHalfX;
mouseY = event.clientY - windowHalfY;
targetRotationY = targetRotationOnMouseDownY + (mouseY - mouseYOnMouseDown) * 0.02;
targetRotationX = targetRotationOnMouseDownX + (mouseX - mouseXOnMouseDown) * 0.02;
}
function onDocumentMouseUp(event) {
document.removeEventListener('mousemove', onDocumentMouseMove, false);
document.removeEventListener('mouseup', onDocumentMouseUp, false);
document.removeEventListener('mouseout', onDocumentMouseOut, false);
}
function onDocumentMouseOut(event) {
document.removeEventListener('mousemove', onDocumentMouseMove, false);
document.removeEventListener('mouseup', onDocumentMouseUp, false);
document.removeEventListener('mouseout', onDocumentMouseOut, false);
}
function onDocumentTouchStart(event) {
if (event.touches.length == 1) {
event.preventDefault();
mouseXOnMouseDown = event.touches[0].pageX - windowHalfX;
targetRotationOnMouseDownX = targetRotationX;
mouseYOnMouseDown = event.touches[0].pageY - windowHalfY;
targetRotationOnMouseDownY = targetRotationY;
}
}
function onDocumentTouchMove(event) {
if (event.touches.length == 1) {
event.preventDefault();
mouseX = event.touches[0].pageX - windowHalfX;
targetRotationX = targetRotationOnMouseDownX + (mouseX - mouseXOnMouseDown) * 0.05;
mouseY = event.touches[0].pageY - windowHalfY;
targetRotationY = targetRotationOnMouseDownY + (mouseY - mouseYOnMouseDown) * 0.05;
}
}
function animate() {
requestAnimationFrame(animate);
rotate();
renderer.render(scene, camera);
}
function rotate() {
group.rotation.y += (targetRotationX - group.rotation.y) * 0.1;
finalRotationY = (targetRotationY - group.rotation.x);
if (group.rotation.x <= 1 && group.rotation.x >= -1) {
group.rotation.x += finalRotationY * 0.1;
}
if (group.rotation.x > 1) {
group.rotation.x = 1
}
if (group.rotation.x < -1) {
group.rotation.x = -1
}
}
Demo of custom rotation controls: https://jsfiddle.net/kmturley/6317jd95/11/
Another person's example: http://projects.defmech.com/ThreeJSObjectRotationWithQuaternion/
There is a discussion of these approaches in the three.js github project: https://github.com/mrdoob/three.js/issues/18476
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With