Friday, February 10, 2017

Control multiple cameras with the same controls

Leave a Comment

I have two different threejs scenes and each has its own camera. I can control each camera individually with a corresponding TrackballControls instance.

Is there a reliable way to 'lock' or 'bind' these controls together, so that manipulating one causes the same camera repositioning in the other? My current approach is to add change listeners to the controls and update both cameras to either's change, but this isn't very neat as, for one, both controls can be changing at once (due to dampening).

2 Answers

Answers 1

I believe it should work if you set the matrices of the second camera to the values of the first and disable automatic matrix-updates of both cameras:

camera2.matrix = camera1.matrix; camera2.projectionMatrix = camera1.projectionMatrix; camera1.matrixAutoUpdate = false; camera2.matrixAutoUpdate = false; 

But now you need to update the matrix manually in your renderloop:

camera1.updateMatrix(); 

That call will take the values for position, rotation and scale (that have been updated by the controls) and compose them into camera1.matrix, which per assignment before is also used as the matrix for the second camera.

However, this feels a bit hacky and can lead to all sorts of weird problems. I personally would probably prefer the more explicit approach you have already implemented.

Question is why are you even using two camera- and controls-instances? As long as the camera isn't added to the scene you can just render both scenes using the same camera.

Answers 2

Is it possible to use the Observer or Publisher design patterns to control these objects?

It seems that you are manipulating the cameras with a control. You might create an object that has the same control interface, but when you pass a command to the object, it repeats that same command to each of the subscribed or registered cameras.

/* psuedo code : es6 */

class MasterControl {     constructor(){         this.camera_bindings = [];     }     control_action1(){         for( var camera of this.camera_bindings ){              camera.control_action1();         }     }     control_action2( arg1, arg2 ){         for( var camera of this.camera_bindings ){              camera.control_action2( arg1, arg2 );         }     }      bindCamera( camera ){        if( this.camera_bindings.indexOf( camera ) === -1 ){            this.camera_bindings.push( camera );        }     } }  var master = new MasterControl(); master.bindCamera( camera1 ); master.bindCamera( camera2 ); master.bindCamera( camera3 );  let STEP_X = -5; let STEP_Y = 10; //the following command will send the command to all three cameras master.control_action2( STEP_X, STEP_Y ); 

This binding is self created rather than using native three.js features, but it is easy to implement and can get you functional quickly.

Note: I wrote my psuedocode in es6, because it is simpler and easy to communicate. You can write it in es5 or older, but you must change the class definition into a series of functional object definitions that create the master object and its functionality.

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment