Is there any way to get around this?
Short answer is "Yes, but it's not using a standard version OrbitControls.js".
Read on for my detailed reasoning....
I have just spent some time looking at the source code of OrbitControls.js
(r87) considering the idea of implementing an enhancement that would allow you to provide an optional 2nd point that it would use as the camera target.
However after exploring the code I think this would be a bad feature to add to the standard public version. There are many features of OrbitControls such as the ability to limit viewing angle, min and max rotation and dolly distance that assume camera and orbit center are the same. If there was an option 2nd camera tagret these would all need to be modified to use either the center of orbit or the camera target or to have a configurable parameter that switches which one it uses. That would add hundreds of extra lines of code, making it harder to understand and all for a very niche feature.
So... The solution:
Because you are building a technical tool, I suspect you don't care about limited viewing angle, distance or rotation so if I were you I would copy OrbitControls.js
into your project, rename it to OrbitControls_customised.js
and make the changes you need:
Add 2 new parameters below this.target
called this.cameraTarget
and this.coupleCenters
// "target" sets the location of focus, where the object orbits around
this.target = new THREE.Vector3();
// "cameraTarget" is where the camera is looking (by default the same as target
this.cameraTarget = new THREE.Vector3();
// Whether the camera should be locked to the orbit center
this.coupleCenters = true;
And on the line where it instructs the camera to look at the center...
scope.object.lookAt( scope.target );
...change it so it only updates the camera when coupleCenters is true...
if( scope.coupleCenters ){
scope.cameraTarget = scope.target;
}
scope.object.lookAt( scope.cameraTarget );
Now, with those changes made, you can put an onMouseDown
event that uses RayCasting to find the point on your object, sets controls.decoupleCenters
to false
and sets controls.target
to the intersecting/crossing point of the raycast. Then an onMouseUp
event that sets the controls.target
back to the controls.cameraTarget
to allow it to behave as normal.
I hope that answers your question and gives you some rough road-map to work towards.