Подтвердить что ты не робот

Преобразование координат мира в координаты экрана в файле Three.js с использованием Projection

Есть несколько замечательных вопросов о стеке (1, 2) о непроектировании в Three.js, то есть как преобразовать (x, y) координаты мыши в браузере в координаты (x, y, z) в пространстве холста Three.js. В основном они следуют этой схеме:

    var elem = renderer.domElement, 
        boundingRect = elem.getBoundingClientRect(),
        x = (event.clientX - boundingRect.left) * (elem.width / boundingRect.width),
        y = (event.clientY - boundingRect.top) * (elem.height / boundingRect.height);

    var vector = new THREE.Vector3( 
        ( x / WIDTH ) * 2 - 1, 
        - ( y / HEIGHT ) * 2 + 1, 
        0.5 
    );

    projector.unprojectVector( vector, camera );
    var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );
    var intersects = ray.intersectObjects( scene.children );

Я пытаюсь сделать обратное - вместо перехода от "экрана к миру", чтобы перейти от "мира к экрану". Если я знаю положение объекта в Three.js, как определить его положение на экране?

Кажется, что не было опубликованного решения этой проблемы. Еще один вопрос об этом только что появился в Stack, но автор утверждает, что решил проблему с функцией, которая не работает для меня. Их решение не использует прогнозируемый Ray, и я уверен, что, поскольку 2D-3D использует unprojectVector(), для решения 3D-2D потребуется projectVector().

Существует также эта проблема открыта в Github.

Любая помощь приветствуется.

4b9b3361

Ответ 1

Попробуйте следующее:

var width = 640, height = 480;
var widthHalf = width / 2, heightHalf = height / 2;

var vector = new THREE.Vector3();
var projector = new THREE.Projector();
projector.projectVector( vector.setFromMatrixPosition( object.matrixWorld ), camera );

vector.x = ( vector.x * widthHalf ) + widthHalf;
vector.y = - ( vector.y * heightHalf ) + heightHalf;

Ответ 2

Для современных Three.js(r75) вектор можно проецировать на экран с помощью:

var width = window.innerWidth, height = window.innerHeight;
var widthHalf = width / 2, heightHalf = height / 2;

var pos = object.position.clone();
pos.project(camera);
pos.x = ( pos.x * widthHalf ) + widthHalf;
pos.y = - ( pos.y * heightHalf ) + heightHalf;

Ответ 3

Для всех, получающих журналы deprecated или warnings, принятый ответ для старых версий Three.js. Теперь это еще проще:

let pos = new THREE.Vector3();
pos = pos.setFromMatrixPosition(object.matrixWorld);
pos.project(camera);

let widthHalf = canvasWidth / 2;
let heightHalf = canvasHeight / 2;

pos.x = (pos.x * widthHalf) + widthHalf;
pos.y = - (pos.y * heightHalf) + heightHalf;
pos.z = 0;

console.log(pos);

Ответ 4

Вы не можете преобразовать координаты (x, y) в координаты (x, y, z), потому что вы теряете информацию. Вы процитировали, как найти все точки на всех объектах в сцене, которые пересекают луч, порожденный (x, y).

Переход от "мира к экрану" по вашему запросу - это то, о чем идет речь, и эквивалентно рендерингу одной точки (x, y, z). Что вы делаете, так это применить матрицу проекции к вашей точке (x, y, z). Вероятно, это функция Projector.projectVector(vector, camera) на http://mrdoob.github.com/three.js/docs/49/#Projector, но из-за того, что она выводит 3D-вектор, я могу только предположить, что один размеров 0, и вы можете игнорировать его.