Three.js — получение координат X, Y и Z щелчка мыши

Я использую версию 68 файла three.js.

Я хотел бы щелкнуть где-нибудь и получить координаты X, Y и Z. Я выполнил шаги здесь, но они дают мне значение Z, равное 0: Мышь/холст X, Y в Three.js World X, Y, Z

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

Это возможно? Вот jsfiddle: http://jsfiddle.net/j9ydgyL3/

В этом jsfiddle, если бы мне удалось щелкнуть в центре этого квадрата, я надеюсь вычислить 10, 10, 10 для значений X, Y и Z соответственно, потому что это координаты положения квадрата. Вот две функции беспокойства:

function getMousePosition(clientX, clientY) {
    var mouse2D = new THREE.Vector3();
    var mouse3D = new THREE.Vector3();
    mouse2D.x = (clientX / window.innerWidth) * 2 - 1;
    mouse2D.y = -(clientY / window.innerHeight) * 2 + 1;
    mouse2D.z = 0.5;
    mouse3D = projector.unprojectVector(mouse2D.clone(), camera);
    return mouse3D;
    //var vector = new THREE.Vector3(
    //( clientX / window.innerWidth ) * 2 - 1,
    //- ( clientY / window.innerHeight ) * 2 + 1,
    //0.5 );

    //projector.unprojectVector( vector, camera );
    //var dir = vector.sub( camera.position ).normalize();
    //var distance = - camera.position.z / dir.z;
    //var pos = camera.position.clone().add( dir.multiplyScalar( distance ) );
    //return pos;
}

function onDocumentMouseUp(event) {
    event.preventDefault();

    var mouse3D = getMousePosition(event.clientX, event.clientY);
    console.log(mouse3D.x + ' ' + mouse3D.y + ' ' + mouse3D.z);
}

Я оставил часть другого кода, который пробовал, закомментировать. Обратите внимание, что этот закомментированный код не работал на веб-сайте jsfiddle, возможно, потому, что они все еще используют версию three.js 54. Он отлично работает на моей машине с версией 68.

Редактировать: Чтобы уточнить, я хотел бы иметь возможность получать координаты независимо от того, где находится мышь. Я просто использовал сетку в этом примере, потому что легко проверить, работает ли она, посмотрев, совпадают ли вычисленные координаты с координатами сетки. Чего бы я действительно хотел, так это чтобы он работал без использования рейкастинга на сетке. Например, мы могли бы всегда выводить вычисленные координаты на консоль при каждом движении мыши, независимо от того, что находится на сцене.


person Programmer_D    schedule 08.10.2014    source источник
comment
Как вы собираетесь найти координату Z без чего-то вроде сетки, по которой можно щелкнуть? Это может быть любое значение от -Inf до +Inf. Вам действительно нужно что-то там, что предоставляет координаты для проверки, и, согласно ответу, вы должны использовать raycaster, чтобы проверить это.   -  person Leeft    schedule 08.10.2014
comment
@Left Я не уверен, поэтому и спросил, возможно ли это. если это действительно невозможно, то не стесняйтесь опубликовать это как ответ, и я приму его =)   -  person Programmer_D    schedule 09.10.2014


Ответы (1)


Для этого следует использовать THREE.Raycaster. Когда вы зададите список intersectObjects, вы сможете получить массив объектов, пересекающихся с лучом. Таким образом, вы можете получить позицию из «щелкнутого» объекта из возвращаемого списка. Проверьте обновленную скрипту здесь. Я также изменил ваш Three.js на версию R68.

Для более продвинутого использования THREE.RayCaster просмотрите примеры на Threejs.org/examples, например этот пример с интерактивными кубами.

Соответствующий код из обновленной скрипты:

function getMousePosition(clientX, clientY) {
    var mouse2D = new THREE.Vector3();
    var mouse3D = new THREE.Vector3();
    mouse2D.x = (clientX / window.innerWidth) * 2 - 1;
    mouse2D.y = -(clientY / window.innerHeight) * 2 + 1;
    mouse2D.z = 0.5;
    mouse3D = projector.unprojectVector(mouse2D.clone(), camera);
    return mouse3D;
    var vector = new THREE.Vector3(
    (clientX / window.innerWidth) * 2 - 1, -(clientY / window.innerHeight) * 2 + 1,
    0.5);

    projector.unprojectVector(vector, camera);
    var dir = vector.sub(camera.position).normalize();
    var distance = -camera.position.z / dir.z;
    var pos = camera.position.clone().add(dir.multiplyScalar(distance));
    return pos;
}

function onDocumentMouseUp(event) {
    event.preventDefault();

    var mouse3D = getMousePosition(event.clientX, event.clientY);
    console.log(mouse3D.x + ' ' + mouse3D.y + ' ' + mouse3D.z);

var vector = new THREE.Vector3( mouse3D.x, mouse3D.y, 1 );    
    raycaster.set( camera.position, vector.sub( camera.position ).normalize() );

    var intersects = raycaster.intersectObjects(scene.children );
    if(intersects.length > 0){
        console.log(intersects[0].object.position);
    }
}

function animate() {
    requestAnimationFrame(animate);
    render();
}

function render() {
    renderer.render(scene, camera);
}
person Wilt    schedule 08.10.2014