Преобразование координат мира в координаты экрана в файле 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.
Любая помощь приветствуется.
Ответы
Ответ 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, и вы можете игнорировать его.