Issue 1:
Description of the problem

The camera has a parent.

The parent sets the position.

OrbitControls-example (latest release branch)

Three.js version

Dev

r114

...

Browser

All of them

Chrome

Firefox

Internet Explorer

OS

All of them

Windows

macOS

Linux

Android

iOS

Hardware Requirements (graphics card, VR Device, ...)

Issue 2:
Description of the problem

OrbitControls (and TrackballControls) break if the camera's parent is moving.

movingObject.add(camera);
controls = new THREE.OrbitControls(camera);

The expected behaviour: jsfiddle

The actual behaviour: jsfiddle

The problem is that OrbitControls operates in world's space (due to Object3D.lookAt() bound to world's space), but the camera is bound to its moving parent. As a result their is a conflict between camera world position set by mouse movements, and by camera's parent movement.

The problem can be solved by introducing an additional camera (Forcing OrbitControls to navigate around a moving object (stackoverflow) ), but this is merely a workaround.

I believe that the real root cause of the problem a little design flaw in the Object3D.lookAt() method used by OrbitControls. The method is a low-level function that takes a point (x, y,, z) argument without any information in the point's reference system. So it makes an assumption that the point is in world's coordinates, and the assumption is sometimes right, sometimes wrong (the OrbitControls case).

Saying simply, I believe that the low-level method tries to be too smart.

Suggested solution:

Making Object3D.lookAt( x, y, z ) really simple by using parent's coordinates (this.matrix) instead of world coordinates (this.matrixWorld).

after the modificationOrbitControls starts respecting camera.parent.

this change is backwards compatible (except for r98 - more about it later), because for objects in world space this.matrix equals this.matrixWorld. Object's having a parent were not really supported anyway, and that was explicitly stated ("This method does not support objects with rotated and/or translated parent(s).")

Introducing a new high-level method Object3D.lookAtObject3D( object ), which would have all information on target's coordinate system provided, because its argument is THREE.Object3D. Thus this method can deal with all complexities caused by parents' translations and rotations.

The code would look like this

lookAt: function () {
// This method operates relatively to object's parent
var q1 = new Quaternion();
var m1 = new Matrix4();
var target = new Vector3();
var position = new Vector3();
return function lookAt( x, y, z ) {
if ( x.isVector3 ) {
target.copy( x );
} else {
target.set( x, y, z );
}
this.updateMatrix();
position.setFromMatrixPosition( this.matrix );
if ( this.isCamera ) {
m1.lookAt( position, target, this.up );
} else {
m1.lookAt( target, position, this.up );
}
this.quaternion.setFromRotationMatrix( m1 );
};
}(),
lookAtObject3D: function () {
var m1 = new Matrix4();
var position = new Vector3();
var parentMatrix;
return function lookAtObject3D( object ) {
object.updateWorldMatrix( true, false );
if (this.parent) {
this.parent.updateWorldMatrix( true, false );
parentMatrix = this.parent.matrixWorld;
} else {
parentMatrix = m1.identity();
}
m1
.getInverse( parentMatrix )
.multiply( object.matrixWorld );
position.setFromMatrixPosition( m1 );
this.lookAt( position );
};
}(),

The only problem I can see is that the latest version (r98) started supporting rotated parents. But I don't think people started using it (perhaps except for @greggman ), and the advantage of Object3D.lookAtObject3D( object ) over r98's lookAt() is that it supports any coordinate system (no matter how object's parents are rotated).

Here are 2 examples showing how it would work:

solar system (jsfiddle) showing OrbitControls working with a moving object, and also using the new Object3D.lookAtObject3D( object ) method

a targetting tank (jsfiddle) - this is the original example by @greggman from #14496 after my modification

An initial PR follows.

Three.js version

r98

Browser

All of them

OS

All of them

Hardware Requirements (graphics card, VR Device, ...)

EDIT: code reformatted and added support for parentless objects (detached camera)