Управление несколькими камерами с одинаковыми элементами управления

У меня есть две разные сцены из трех сцен, каждая из которых имеет свою собственную камеру. Я могу управлять каждой камерой индивидуально с помощью соответствующего экземпляра TrackballControls.

Есть ли надежный способ "блокировать" или "связывать" эти элементы управления вместе, так что манипулирование ими приводит к тому, что одна и та же камера перемещается в другую? Мой текущий подход состоит в том, чтобы добавить слушателей change к элементам управления и обновить обе камеры, чтобы либо сменить, но это не очень аккуратно, так как, как один, оба элемента управления могут меняться сразу (из-за увлажнения).

Ответ 1

Я считаю, что он должен работать, если вы установите матрицы второй камеры в значения первых и отключите автоматическую матрицу-обновления обеих камер:

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

Но теперь вам нужно обновить матрицу вручную в своем рендере:

camera1.updateMatrix();

Этот вызов будет принимать значения для position, rotation и scale (которые были обновлены элементами управления) и скомпоновать их в camera1.matrix, которые для каждого присваивания ранее также используются в качестве матрицы для вторая камера.

Тем не менее, это немного взломанно и может привести к разным проблемам. Я лично предпочел бы более явный подход, который вы уже реализовали.

Вопрос: почему вы даже используете два экземпляра камеры и управления? Пока камера не добавляется в сцену, вы можете просто отображать обе сцены с использованием одной и той же камеры.

Ответ 2

Можно ли использовать шаблоны проектирования Observer или Publisher для управления этими объектами?

Кажется, что вы управляете камерами с помощью элемента управления. Вы можете создать объект с одним и тем же интерфейсом управления, но когда вы передаете команду объекту, он повторяет ту же самую команду для каждой из подписанных или зарегистрированных камер.

/* код psuedo: 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 );

Эта привязка создается самостоятельно, а не использует собственные функции three.js, но ее легко реализовать и быстро заставить вас функционировать.

Примечание. Я написал свой psuedocode в es6, потому что он проще и удобнее в общении. Вы можете записать его в es5 или старше, но вы должны изменить определение класса на ряд определений функциональных объектов, которые создают главный объект и его функциональные возможности.