<h5 dir="auto">Description of the problem</h5>
<ol dir="auto">
<li>The camera has a parent.</li>
<li>The parent sets the position.</li>
</ol>
<ul dir="auto">
<li><a href="https://stackblitz.com/edit/three-example" rel="nofollow">OrbitControls-example</a> (latest release branch)</li>
</ul>
<h5 dir="auto">Three.js version</h5>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Dev</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> r114</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> ...</li>
</ul>
<h5 dir="auto">Browser</h5>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> All of them</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Chrome</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Firefox</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Internet Explorer</li>
</ul>
<h5 dir="auto">OS</h5>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> All of them</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Windows</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> macOS</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Linux</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Android</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> iOS</li>
</ul>
<h5 dir="auto">Hardware Requirements (graphics card, VR Device, ...)</h5>
<h5 dir="auto">Description of the problem</h5>
<p dir="auto"><code class="notranslate">OrbitControls</code> (and <code class="notranslate">TrackballControls</code>) break if the camera's parent is moving.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content=" movingObject.add(camera);
 controls = new THREE.OrbitControls(camera);"><pre class="notranslate"><code class="notranslate"> movingObject.add(camera);
 controls = new THREE.OrbitControls(camera);
</code></pre></div>
<p dir="auto">The expected behaviour: <a href="http://jsfiddle.net/lguminski/24ahxn5w/show" rel="nofollow">jsfiddle</a><br>
The actual behaviour: <a href="https://jsfiddle.net/lguminski/Lvt5y2m9/show" rel="nofollow">jsfiddle</a></p>
<p dir="auto">The problem is that <code class="notranslate">OrbitControls</code> operates in world's space (due to <code class="notranslate">Object3D.lookAt()</code> 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.</p>
<p dir="auto">The problem can be solved by introducing an additional camera (<a href="https://stackoverflow.com/a/53298655/1314907" rel="nofollow">Forcing OrbitControls to navigate around a moving object (stackoverflow)</a> ), but this is merely a workaround.</p>
<p dir="auto">I believe that the real root cause of the problem a little design flaw in the <code class="notranslate">Object3D.lookAt()</code> method used by <code class="notranslate">OrbitControls</code>. The method is a low-level function that takes a point (<code class="notranslate">x</code>, <code class="notranslate">y,</code>, <code class="notranslate">z</code>) 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 <code class="notranslate">OrbitControls</code> case).</p>
<p dir="auto">Saying simply, I believe that the low-level method tries to be too smart.</p>
<p dir="auto">Suggested solution:</p>
<ol dir="auto">
<li>Making <code class="notranslate">Object3D.lookAt( x, y, z )</code> really simple by using parent's coordinates (<code class="notranslate">this.matrix</code>) instead of world coordinates (<code class="notranslate">this.matrixWorld</code>).
<ul dir="auto">
<li>after the modification<code class="notranslate">OrbitControls</code> starts respecting <code class="notranslate">camera.parent</code>.</li>
<li>this change is backwards compatible (except for r98 - more about it later), because for objects in world space <code class="notranslate">this.matrix</code> equals <code class="notranslate">this.matrixWorld</code>. 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).")</li>
</ul>
</li>
<li>Introducing a new high-level method <code class="notranslate">Object3D.lookAtObject3D( object )</code>, which would have all information on target's coordinate system provided, because its argument is <code class="notranslate">THREE.Object3D</code>. Thus this method can deal with all complexities caused by parents' translations and rotations.</li>
</ol>
<p dir="auto">The code would look like this</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="	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 );
		};
	}(),"><pre class="notranslate">	<span class="pl-s1">lookAt</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
		<span class="pl-c">// This method operates relatively to object's parent</span>
		<span class="pl-k">var</span> <span class="pl-s1">q1</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Quaternion</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
		<span class="pl-k">var</span> <span class="pl-s1">m1</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Matrix4</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
		<span class="pl-k">var</span> <span class="pl-s1">target</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Vector3</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
		<span class="pl-k">var</span> <span class="pl-s1">position</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Vector3</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
		<span class="pl-k">return</span> <span class="pl-k">function</span> <span class="pl-en">lookAt</span><span class="pl-kos">(</span> <span class="pl-s1">x</span><span class="pl-kos">,</span> <span class="pl-s1">y</span><span class="pl-kos">,</span> <span class="pl-s1">z</span> <span class="pl-kos">)</span> <span class="pl-kos">{</span>
			<span class="pl-k">if</span> <span class="pl-kos">(</span> <span class="pl-s1">x</span><span class="pl-kos">.</span><span class="pl-c1">isVector3</span> <span class="pl-kos">)</span> <span class="pl-kos">{</span>
				<span class="pl-s1">target</span><span class="pl-kos">.</span><span class="pl-en">copy</span><span class="pl-kos">(</span> <span class="pl-s1">x</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
			<span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
				<span class="pl-s1">target</span><span class="pl-kos">.</span><span class="pl-en">set</span><span class="pl-kos">(</span> <span class="pl-s1">x</span><span class="pl-kos">,</span> <span class="pl-s1">y</span><span class="pl-kos">,</span> <span class="pl-s1">z</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
			<span class="pl-kos">}</span>
			<span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">updateMatrix</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
			<span class="pl-s1">position</span><span class="pl-kos">.</span><span class="pl-en">setFromMatrixPosition</span><span class="pl-kos">(</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">matrix</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
			<span class="pl-k">if</span> <span class="pl-kos">(</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">isCamera</span> <span class="pl-kos">)</span> <span class="pl-kos">{</span>
				<span class="pl-s1">m1</span><span class="pl-kos">.</span><span class="pl-en">lookAt</span><span class="pl-kos">(</span> <span class="pl-s1">position</span><span class="pl-kos">,</span> <span class="pl-s1">target</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">up</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
			<span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
				<span class="pl-s1">m1</span><span class="pl-kos">.</span><span class="pl-en">lookAt</span><span class="pl-kos">(</span> <span class="pl-s1">target</span><span class="pl-kos">,</span> <span class="pl-s1">position</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">up</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
			<span class="pl-kos">}</span>
			<span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">quaternion</span><span class="pl-kos">.</span><span class="pl-en">setFromRotationMatrix</span><span class="pl-kos">(</span> <span class="pl-s1">m1</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
		<span class="pl-kos">}</span><span class="pl-kos">;</span>
	<span class="pl-kos">}</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
	<span class="pl-s1">lookAtObject3D</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
		<span class="pl-k">var</span> <span class="pl-s1">m1</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Matrix4</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
		<span class="pl-k">var</span> <span class="pl-s1">position</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Vector3</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
		<span class="pl-k">var</span> <span class="pl-s1">parentMatrix</span><span class="pl-kos">;</span>
		<span class="pl-k">return</span> <span class="pl-k">function</span> <span class="pl-en">lookAtObject3D</span><span class="pl-kos">(</span> <span class="pl-s1">object</span> <span class="pl-kos">)</span> <span class="pl-kos">{</span>
			<span class="pl-s1">object</span><span class="pl-kos">.</span><span class="pl-en">updateWorldMatrix</span><span class="pl-kos">(</span> <span class="pl-c1">true</span><span class="pl-kos">,</span> <span class="pl-c1">false</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
			<span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">parent</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
				<span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">parent</span><span class="pl-kos">.</span><span class="pl-en">updateWorldMatrix</span><span class="pl-kos">(</span> <span class="pl-c1">true</span><span class="pl-kos">,</span> <span class="pl-c1">false</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
				<span class="pl-s1">parentMatrix</span> <span class="pl-c1">=</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">parent</span><span class="pl-kos">.</span><span class="pl-c1">matrixWorld</span><span class="pl-kos">;</span>
			<span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-kos">{</span>
				<span class="pl-s1">parentMatrix</span> <span class="pl-c1">=</span> <span class="pl-s1">m1</span><span class="pl-kos">.</span><span class="pl-en">identity</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
			<span class="pl-kos">}</span>
			<span class="pl-s1">m1</span>
				<span class="pl-kos">.</span><span class="pl-en">getInverse</span><span class="pl-kos">(</span> <span class="pl-s1">parentMatrix</span> <span class="pl-kos">)</span>
				<span class="pl-kos">.</span><span class="pl-en">multiply</span><span class="pl-kos">(</span> <span class="pl-s1">object</span><span class="pl-kos">.</span><span class="pl-c1">matrixWorld</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
			<span class="pl-s1">position</span><span class="pl-kos">.</span><span class="pl-en">setFromMatrixPosition</span><span class="pl-kos">(</span> <span class="pl-s1">m1</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
			<span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">lookAt</span><span class="pl-kos">(</span> <span class="pl-s1">position</span> <span class="pl-kos">)</span><span class="pl-kos">;</span>
		<span class="pl-kos">}</span><span class="pl-kos">;</span>
	<span class="pl-kos">}</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">,</span></pre></div>
<p dir="auto">The only problem I can see is that the latest version (<code class="notranslate">r98</code>) started supporting rotated parents. But I don't think people started using it (perhaps except for <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/greggman/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/greggman">@greggman</a> ), and the advantage of <code class="notranslate">Object3D.lookAtObject3D( object )</code> over <code class="notranslate">r98</code>'s <code class="notranslate">lookAt()</code> is that it supports any coordinate system (no matter how object's parents are rotated).</p>
<p dir="auto">Here are 2 examples showing how it would work:</p>
<ul dir="auto">
<li><a href="http://jsfiddle.net/lguminski/6fzkjndo/show" rel="nofollow">solar system (jsfiddle)</a> showing <code class="notranslate">OrbitControls</code> working with a moving object, and also using the new <code class="notranslate">Object3D.lookAtObject3D( object )</code> method</li>
<li><a href="https://jsfiddle.net/lguminski/7Lo43ctz/" rel="nofollow">a targetting tank (jsfiddle)</a> - this is the original example by <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/greggman/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/greggman">@greggman</a> from <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="342275284" data-permission-text="Title is private" data-url="https://github.com/mrdoob/three.js/issues/14496" data-hovercard-type="issue" data-hovercard-url="/mrdoob/three.js/issues/14496/hovercard" href="https://github.com/mrdoob/three.js/issues/14496">#14496</a> after my modification</li>
</ul>
<p dir="auto">An initial PR follows.</p>
<h5 dir="auto">Three.js version</h5>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> r98</li>
</ul>
<h5 dir="auto">Browser</h5>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> All of them</li>
</ul>
<h5 dir="auto">OS</h5>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> All of them</li>
</ul>
<h5 dir="auto">Hardware Requirements (graphics card, VR Device, ...)</h5>
<p dir="auto"><strong>EDIT:</strong> code reformatted and added support for parentless objects (detached camera)</p>