2016-03-08 5 views
1

Я установил raycaster, чтобы выполнить выбор объекта с моего холста.TrijS raycaster выключен с камерой и объектом с координатой более 1000000

Он хорошо подходит для небольших значений camera.position.x и object.position.x, но моя проблема в том, что он не работает хорошо, когда camera.postion.x - большое количество, в моем случае 10 000 000!

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

   var raycaster = new THREE.Raycaster(); 
       var vector = new THREE.Vector2(); 

       camera.position.x = 11000000; 
       object.position.x = 11000000; 

       function onMouseMove(event) { 

        vector.x = ((event.clientX - renderer.domElement.offsetLeft)/renderer.domElement.clientWidth) * 2 - 1; 
        vector.y = - ((event.clientY - renderer.domElement.offsetTop)/renderer.domElement.clientHeight) * 2 + 1; 

        raycaster.setFromCamera(vector, camera); 

        var intersects = raycaster.intersectObjects(scene.children, true); 

        if(intersects.length>0){ 
         alert("INTERSECTION " + intersects[0].object.userData.name); 
         } 

       }canvas.addEventListener('mousemove', onMouseMove, false); 

Я пропустил добавление объекта к сцене и некоторые другие вещи, чтобы сообщение не было слишком длинным. Это срабатывает, когда, например, для параметра camera.position.x и object.position.x установлено значение менее 1 000 000, хотя некоторые искажения присутствуют и тогда.

EDIT 1

   var scene = new THREE.Scene(); 

       var canvas = document.getElementById('canvas'); 

       var height = canvas.clientHeight; 
       var width = canvas.clientWidth; 

       var camera = new THREE.PerspectiveCamera(70, width/height, 1, 1000); 

       var renderer = new THREE.WebGLRenderer(); 
       renderer.setSize(width, height); 
       canvas.appendChild(renderer.domElement); 

Кроме того, здесь является частью моей HTML, где 'холст' ДИВ расположен, я также попытался canvas.offsetLef вместо renderer.domElement.offsetLeft и т.д ..

РЕДАКТИРОВАТЬ 2

<div id="content" ng-controller="ShippingCtrl"> 

     <div id="left_panel"> 

     </div> 

     <div id="canvas" style="width:900px; height:600px; border:1px solid white"> 

     </div> 

     <div id="right_pannel"> 

     </div></div> 
+0

Я хотел бы быть уверенным, что DOMElement и холст происхождения координаты в HTML/CSS являются одинаковыми и без полей, масштаб браузера или смещения перемещают луч с вашего намерения. Тогда также верно, что ваш renderer setSize также верен. Я никогда не видел пропусков лучей из-за неточности плавания. – Radio

+0

Я бы сказал, что у вас что-то не так в вашей настройке. Возможно, скрипка с полным кодом поможет другим указать на проблему. – Wilt

+0

У меня такая же проблема. Но raycaster находит пересекающиеся объекты, если я вращаюсь и панорамирую мою сцену с помощью orbitControls. Вы нашли решение? –

ответ

1

Подозрюющ с плавающей точкой ошибки округления я Walke d через непрозрачность в Matlab, чтобы понять, как с ним справится другая реализация. Я начал с матрицами камеры в codepen примере

проекции камеры

4.951969385147095e-01       0       0       0 
        0  1.428148031234741e+00       0       0 
        0       0 -1.001000523567200e+00 -1.000000000000000e+00 
        0       0 -2.001000404357910e+00       0 

камеры Мир

 1   0   0   0 
     0   1   0   0 
     0   0   1   0 
4000000  2000000  1000800   1 

Инверсия матрицы проекции камеры, рассчитанные с помощью JavaScript через threejs

обратного матрица проекции камеры

2.0193986892700195       0       0      0 
        0   0.700207531452179       0      0 
        0       0       0  -0.499750018119812 
        0       0       -1  0.5002500414848328 

Инверсия матрицы проекции камеры, рассчитанные с помощью Matlab

2.019398591193624e+00       0       0       0 
        0  7.002075262012054e-01       0       0 
        0       0       0 -4.997500239490878e-01 
        0       0 -1.000000000000000e+00  5.002500356257574e-01 

Умножение матрицы вместе (обратная проекция камеры матрица * камера мир матрица)

в threejs

2.0193986892700195       0       0      0 
        0   0.700207531452179       0      0 
      -1999000.125    -999500.0625    -500149.8125  -0.499750018119812 
      2001000.125    1000500.0625     500649.25  0.5002500414848328 

Тот же расчет в Matlab

c amProjectionInv * camWorld

2.019398591193624e+00       0       0       0 
        0  7.002075262012054e-01       0       0 
-1.999000095796351e+06 -9.995000478981755e+05 -5.001498239682470e+05 -4.997500239490878e-01 
2.001000142503030e+06  1.000500071251515e+06  5.006492356542581e+05  5.002500356257574e-01 

Используя точку в центре экрана для простоты [0,0,0.5,1.0] и умножения через и деления на ш

от threejs

 3599999.783405974,  1799999.891702987,  900796.0640709081 

из Matlab

4.000000000000000e+06  2.000000000000000e+06  1.000796005991391e+06  1.000000000000000e+00 

происходит накопление ошибок округления. Я не совсем понимаю, как отличаются C++ (Matlab) и JavaScript (три js) в обработке 64-разрядных чисел с плавающей запятой IEEE Standard 754.

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

center(): THREE.Vector3 { 
    let datacenter = this.dataCenter(); 
    let center = datacenter.add(this.sceneLocation); 
    return center; 
} 

worldBBox(): THREE.Box3 { 
    return new THREE.Box3().setFromObject(this.pathsGroup); 
} 

protected updateScenePosition(): void { 
    this.sceneLocation = this.dataCenter().negate(); 
    this.scene.position.set(this.sceneLocation.x, this.sceneLocation.y, this.sceneLocation.z); 
    this.scene.matrixWorldNeedsUpdate=true; 
    this.scene.updateMatrixWorld(true); 
} 

protected dataCenter(): THREE.Vector3 { 
    let dataBBox = this.dataBoundingBox(); 
    let center = dataBBox.max.clone(); 
    center.sub(dataBBox.min); 
    center.divideScalar(2.0); 
    center.add(dataBBox.min); 
    return center; 
} 

protected dataBoundingBox(): THREE.Box3 { 
    let bbox = new THREE.Box3().setFromObject(this.pathsGroup); 
    this.pathsGroup.worldToLocal(bbox.min); 
    this.pathsGroup.worldToLocal(bbox.max); 

    return bbox; 
} 

Когда объект добавляется к сцене, я называю updateScenePosition, хотя это, вероятно, не является строго необходимым, так как новые объекты, скорее всего, в примерно той же местности и видимый ошибка, вероятно, уже компенсируется исходными объектами.

Обновление камеры затем

CENTERVIEW(): пустота {

this.look = this.bigscene.center().clone(); 

    this.camera.position.set(this.look.x, this.look.y, this.look.z+3600); 

    this.camera.lookAt(this.look); 
    this.controls.target.set(this.look.x, this.look.y, this.look.z); 

    this.light.position.copy(this.camera.position); //headlight 
}