Выбор объектов с 3 ортогональными камерами и 3 окнами просмотра - three.js

У меня есть приложение WebGl/ThreeJS, в котором у меня есть 3 средства визуализации WebGL, 1 сцена и 1 холст для каждого средства визуализации. Первые 2 холста в порядке, они работают нормально.

Другой холст разделен на 3 окна просмотра одинакового размера, и в каждом окне просмотра я добавил ортогональную камеру в другом положении.

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

Я создаю свои орфографические камеры, как приведенный выше код, дающий 3 разных положения для каждой камеры (12, 0,0) (0, 12,0) (0,0, 12) и задающий ширину, высоту окна просмотра (не холст) :

    var viewSize = 50 ;
    var aspectRatio = width/height;
    var camera = new THREE.OrthographicCamera( viewSize*aspectRatio / - 2, viewSize*aspectRatio / 2, viewSize / 2, viewSize / - 2, 0, 100);
    camera.position.set(x,y,z);
    camera.lookAt(new THREE.Vector3(0,0,0) );

После настройки камер/портов просмотра и на основе этого очень полезного поста: post, я создал и вызвал 1 раз для каждого окна просмотра/камеры эту функцию:

{ 
  var raycaster = new THREE.Raycaster();
  var mouse = new THREE.Vector2();

  function MouseEvents( spheres, func, _camera, domElement ) {
    this.plane = {'object3d' : undefined} ;
    this.camera = _camera;
    this.container = domElement; 
    this.objects = spheres;

    var _this =this;

    this.offset = new THREE.Vector3();
    this.INTERSECTED;
    this.SELECTED;

    if(func === 'dragNdrop'){

      this.plane.object3d = new THREE.Mesh(
        new THREE.PlaneBufferGeometry( 10000, 10000, 2, 2 ),
        new THREE.MeshBasicMaterial( { color: "#"+((1<<24)*Math.random()|0).toString(16)  } )
      );
      this.plane.object3d.visible = true;
      if(this.container === 'motifPosX' ) this.plane.object3d.position.z = -100;
      if(this.container === 'motifPosY' ) this.plane.object3d.position.x = -100;
      if(this.container === 'motifPosZ' ) this.plane.object3d.position.y = -100;

      this.plane.object3d.lookAt(this.camera.position);
      MotifExplorer.add(this.plane);

    }
    var mMoove = this.onDocumentMouseMove.bind(this) ;
    var mDown = this.onDocumentMouseDown.bind(this) ;
    var mUp = this.onDocumentMouseUp.bind(this) ;

    document.getElementById(this.container).addEventListener("mousemove", mMoove, false);
    document.getElementById(this.container).addEventListener("mousedown", mDown, false);
    document.getElementById(this.container).addEventListener("mouseup",   mUp, false);

  }; 

  MouseEvents.prototype.onDocumentMouseMove = function(event){ 
    var _this = this;

    event.preventDefault();

    _this.plane.object3d.lookAt( _this.camera.position );
    mouse.x = ( event.clientX / $('#'+_this.container).width() ) * 2 - 1;
    mouse.y = - ( event.clientY / $('#'+_this.container).height() )* 2 + 1;

    //

    raycaster.setFromCamera( mouse, _this.camera );

    if ( _this.SELECTED ) {

      var intersects = raycaster.intersectObject( _this.plane.object3d );
      _this.SELECTED.position.copy( intersects[ 0 ].point.sub( _this.offset ) );
      return;

    }

    var intersects = raycaster.intersectObjects( _this.getAtoms() );

    if ( intersects.length > 0 &&  intersects[0].object.parent.name ==='atom') {

      if ( _this.INTERSECTED != intersects[0].object.parent ) {

        _this.INTERSECTED = intersects[0].object.parent;

        _this.plane.object3d.position.copy( _this.INTERSECTED.position );

      }

      document.getElementById(_this.container).style.cursor = 'pointer';

    } 
    else {

      _this.INTERSECTED = null;

      document.getElementById(_this.container).style.cursor = 'auto';

    }

  }
  MouseEvents.prototype.onDocumentMouseDown = function(event){  
    var _this =this;

    event.preventDefault();

    raycaster.setFromCamera( mouse, _this.camera );

    var intersects = raycaster.intersectObjects( _this.getAtoms() );

    if ( intersects.length > 0 &&  intersects[0].object.parent.name ==='atom') {

      _this.SELECTED = intersects[0].object.parent;

      var intersects = raycaster.intersectObject( _this.plane.object3d );

      _this.offset.copy( intersects[ 0 ].point ).sub( _this.plane.object3d.position );

      document.getElementById(_this.container).style.cursor = 'move';

    }

  }
  MouseEvents.prototype.onDocumentMouseUp  = function(event){  
    var _this =this;
    event.preventDefault();

    if ( _this.INTERSECTED ) {

      _this.plane.object3d.position.copy( _this.INTERSECTED.position );

      _this.SELECTED = null;

    }

    document.getElementById(_this.container).style.cursor = 'auto';

  };

  MouseEvents.prototype.getAtoms = function() {  
    var _this = this;
    var objects = []; 
    MotifExplorer.getInstance().object3d.traverse (function (object) {
      if (object.name === 'atom') { 
        for (var i = 0; i < object.children.length; i++) { 
          _this.objects.push(object.children[i]);
        };
      }
    });
    return _this.objects;
  };

  return MouseEvents;

});

Итак, в консоли все работает без ошибок, но сферы не обнаруживаются при наведении или клике. Я думаю, что что-то не так с моими настройками, координатами мыши и размерами холста.

Я хочу отметить, что у меня также есть orbitControls, настроенные для каждого окна просмотра независимо, но я отключил все функции, кроме масштабирования прокрутки.

Кроме того, когда я добавляю сферу, она фактически обнаруживается функцией, если я увеличиваю масштаб настолько, что сфера занимает всю область просмотра.

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

Забыл сказать, что для одного модуля визуализации/камеры/холста, занимающего весь экран, я смог создать перетаскиваемую сферу. Моя проблема заключается в том, что мне нужно изменить, чтобы иметь эту функциональность на холсте с определенными размерами и для его 3 видовых экранов/камер.


person Community    schedule 20.02.2015    source источник
comment
Вам нужно учитывать параметры области просмотра и настроить значения mouse.x и mouse.y так, чтобы они всегда оставались в интервале [ - 1, + 1 ].   -  person WestLangley    schedule 20.02.2015
comment
@WestLangley: я только что исправил это. Незадолго до того, как я увидел ваш ответ, в котором была описана именно моя проблема! Когда я исправил координаты мыши, обнаружение сработало отлично. Еще раз большое спасибо, хотя я нашел ответ самостоятельно :)   -  person    schedule 20.02.2015
comment
Я столкнулся с той же проблемой. Я не могу определить местоположение мыши. Что исправить?   -  person Shashidhara    schedule 25.11.2019