Как получить объект в 3DG пространстве WebGL с координаты щелчка мыши
Я собираю настольную игру в WebGL. Плата может поворачиваться/масштабироваться. Мне нужен способ перевести щелчок на элемент холста (x, y) в соответствующую точку в 3D-пространстве (x, y, z). Конечным результатом является то, что я хочу знать координату (x, y, z), которая содержит точку, которая касается самого близкого к пользователю объекта. Например, пользователь нажимает кусок, и вы представляете себе, как луч проходит через трехмерное пространство, проходящее через кусок и игровое поле, но я хочу, чтобы координата (x, y, z) была в том месте, где она была прикосновение.
Я чувствую, что это должна быть очень распространенная проблема, но я не могу найти решение в своих googles. Должен быть какой-то способ проецировать текущий вид 3D-пространства в 2D, чтобы вы могли сопоставить каждую точку в 2D-пространстве с соответствующей точкой в 3D-пространстве. Я хочу, чтобы пользователь мог наводить курсор мыши на пространство на доске и иметь цвет смены места.
Ответы
Ответ 1
Вы ищете функцию unproject, которая преобразует координаты экрана в луч, отлитый от положения камеры в 3D-мире. Затем вы должны выполнить тесты пересечения лучей/треугольников, чтобы найти ближайший треугольник к камере, который также пересекает луч.
У меня есть пример unprojecting, доступный на jax/camera.js # L568 - но вам все равно нужно реализовать пересечение лучей/треугольников. У меня есть реализация этого в jax/triangle.js # L113.
Существует более простая и (обычно) более быстрая альтернатива, однако, называется "сбор". Используйте это, если вы хотите выбрать весь объект (например, шахматный кусок), и если вам не важно, куда на самом деле щелкнула мышь. Способ WebGL для этого состоит в том, чтобы отобразить всю сцену в разных оттенках синего (синий - это ключ, а красный и зеленый - для уникальных идентификаторов объектов в сцене) к текстуре, а затем считывает пиксель из это текстура. Декодирование RGB в ID объекта даст вам объект, который был нажат. Опять же, я реализовал это, и он доступен в jax/world.js # L82. (См. Также строки 146, 162, 175.)
Оба подхода имеют плюсы и минусы (обсуждаются здесь и в некоторых комментариях после), и вам нужно будет выяснить, какой подход наилучшим образом отвечает вашим потребностям. Выбор медленнее с огромными сценами, но непрозрачность в чистом JS чрезвычайно медленная (поскольку сама JS не так уж быстро), поэтому моя лучшая рекомендация - экспериментировать с обоими.
FYI, вы также можете посмотреть проект GLU и код непроекта, на который я основал свой код свободно: http://www.opengl.org/wiki/GluProject_and_gluUnProject_code
Ответ 2
Это рабочая демонстрация
function onMouseUp(event) {
event.preventDefault();
x_pos = (event.clientX / window.innerWidth) * 2 - 1;
y_pos = -(event.clientY / window.innerHeight) * 2 + 1;
z_pos = 0.5;
var vector = new THREE.Vector3( x_pos , y_pos , z_pos );
var projector = new THREE.Projector();
projector.unprojectVector(vector, camera);
var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
var intersects = raycaster.intersectObjects(intersectObjects);
if (intersects.length > 0) {
xp = intersects[0].point.x.toFixed(2);
yp = intersects[0].point.y.toFixed(2);
zp = intersects[0].point.z.toFixed(2);
destination = new THREE.Vector3( xp , yp , zp );
radians = Math.atan2( ( driller.position.x - xp) , (driller.position.z - zp));
radians += 90 * (Math.PI / 180);
console.log(radians);
var tween = new TWEEN.Tween(driller.rotation).to({ y : radians },200).easing(TWEEN.Easing.Linear.None).start();
}
weissner-doors.de/drone/
Ответ 3
Я работаю над этой проблемой на данный момент - подход, который я принимаю, - это
- Рендеринг объектов для выбора буфера с уникальным цветом
- Чтение пикселя буфера, возврат к выбранному объекту
- Render выбрал объект для буферизации с каждым цветом пикселя функцией Z-depth
- Прочитать буферный пиксель, вернуться к глубине Z
- Мы выбрали объект и приблизили Z для кодов выбора
Ответ 4
культивируется из одного из потоков.
не уверен в (x, y, z), но вы можете получить canvas(x,y)
с помощью
getBoundingClientRect()
function getCanvasCoord(){
var mx = event.clientX;
var my = event.clientY;
var canvas = document.getElementById('canvasId');
var rect = canvas.getBoundingClientRect();// check if your browser supports this
mx = mx - rect.left;
my = my - rect.top;
return {x: mx , y: my};
}