Как получить объект в 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};
}