Three.js投影机和雷对象 [英] Three.js Projector and Ray objects

查看:301
本文介绍了Three.js投影机和雷对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在试图与投影机和雷班工作,以做一些碰撞检测演示。我开始只是想用鼠标选择对象,或将它们拖动。我已经看过了使用对象的例子,但没有人似乎有意见解释究竟是什么的一些投影机和雷的方法在做什么。我有几个问题,我希望会很容易为别人解答。

究竟是什么发生,什么是Projector.projectVector()和Projector.unprojectVector()?之间的区别,我注意到,它似乎在所有的例子中使用投影机和射线对象unproject方法光线被创建之前调用。 当你使用projectVector?

我使用下面的code本 演示 以旋多维数据集时,用鼠标拖再拖。 有人可以用简单的术语解释究竟发生时,我unproject与mouse3D和摄像头,然后创建光芒。是否光线取决于调用unprojectVector()

  / **时触发的事件了鼠标按键时pressed下来* /
功能onDocumentMouseDown(事件){
    。事件preventDefault();
    MOUSEDOWN = TRUE;
    mouse3D.x = mouse2D.x = mouseDown2D.x =(event.clientX / window.innerWidth)* 2  -  1;
    mouse3D.y = mouse2D.y = mouseDown2D.y =  - (event.clientY / window.innerHeight)* 2 + 1;
    mouse3D.z = 0.5;

    / **通过鼠标项目从摄像头,并创建一个光线* /
    projector.unprojectVector(mouse3D,摄像头);
    VAR光=新THREE.Ray(camera.position,mouse3D.subSelf(camera.position).normalize());
    VAR相交= ray.intersectObject(crateMesh); //店相交的对象

    如果(intersects.length大于0){
        SELECTED =相交[0] .object;
        VAR相交= ray.intersectObject(平面);
    }

}

/ **此事件处理只鼠标按下事件后触发,
    鼠标向上事件之前,只有当鼠标移动* /
功能onDocumentMouseMove(事件){
    。事件preventDefault();

    mouse3D.x = mouse2D.x =(event.clientX / window.innerWidth)* 2  -  1;
    mouse3D.y = mouse2D.y =  - (event.clientY / window.innerHeight)* 2 + 1;
    mouse3D.z = 0.5;
    projector.unprojectVector(mouse3D,摄像头);

    VAR光=新THREE.Ray(camera.position,mouse3D.subSelf(camera.position).normalize());

    如果(选择){
        VAR相交= ray.intersectObject(平面);
        dragVector.sub(mouse2D,mouseDown2D);
        返回;
    }

    VAR相交= ray.intersectObject(crateMesh);

    如果(intersects.length大于0){
        如果(相交!=相交[0] .object){
            相交的相交= [0] .object;
        }
    }
    其他 {
        相交= NULL;
    }
}

/ **删除时,让鼠标按钮事件监听器去* /
功能onDocumentMouseUp(事件){
    。事件preventDefault();

    / **更新鼠标的位置* /
    mouse3D.x = mouse2D.x =(event.clientX / window.innerWidth)* 2  -  1;
    mouse3D.y = mouse2D.y =  - (event.clientY / window.innerHeight)* 2 + 1;
    mouse3D.z = 0.5;

    如果(相交的){
        SELECTED = NULL;
    }

    MOUSEDOWN = FALSE;
    dragVector.set(0,0);
}

/ **删除事件侦听器,当鼠标逃跑的渲染器* /
功能onDocumentMouseOut(事件){
    。事件preventDefault();

    如果(相交的){
        plane.position.copy(INTERSECTED.position);
        SELECTED = NULL;
    }
    MOUSEDOWN = FALSE;
    dragVector.set(0,0);
}
 

解决方案

基本上,你需要从3D世界空间和2D屏幕空间项目。

渲染器使用 projectVector 的转换3D点到2D画面。 unprojectVector 基本上是在做反,unprojecting 2D点进入3D世界。对于这两种方法,你传递你通过查看现场摄像头。

所以,在这种code您创建在二维空间中的归一化向量。说实话,我从来没有太肯定的 Z = 0.5 逻辑。

  mouse3D.x =(event.clientX / window.innerWidth)* 2  -  1;
mouse3D.y =  - (event.clientY / window.innerHeight)* 2 + 1;
mouse3D.z = 0.5;
 

然后,code使用相机的投影矩阵,其转换为我们的3D世界空间。

  projector.unprojectVector(mouse3D,摄像头);
 

随着mouse3D点转换成3D空间,现在我们可以用它来获得方向,然后使用相机的位置抛出的曙光。

  VAR光=新THREE.Ray(camera.position,mouse3D.subSelf(camera.position).normalize());
VAR相交= ray.intersectObject(平面);
 

I have been trying to work with the Projector and Ray classes in order to do some collision detection demos. I have started just trying to use the mouse to select objects or to drag them. I have looked at examples that use the objects, but none of them seem to have comments explaining what exactly some of the methods of Projector and Ray are doing. I have a couple questions that I am hoping will be easy for someone to answer.

What exactly is happening and what is the difference between Projector.projectVector() and Projector.unprojectVector()? I notice that it seems in all the examples using both projector and ray objects the unproject method is called before the ray is created. When would you use projectVector?

I am using the following code in this demo to spin the cube when dragged on with the mouse. Can someone explain in simple terms what exactly is happening when I unproject with the mouse3D and camera and then create the Ray. Does the ray depend on the call to unprojectVector()

/** Event fired when the mouse button is pressed down */
function onDocumentMouseDown(event) {
    event.preventDefault();
    mouseDown = true;
    mouse3D.x = mouse2D.x = mouseDown2D.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse3D.y = mouse2D.y = mouseDown2D.y = -(event.clientY / window.innerHeight) * 2 + 1;
    mouse3D.z = 0.5;

    /** Project from camera through the mouse and create a ray */
    projector.unprojectVector(mouse3D, camera);
    var ray = new THREE.Ray(camera.position, mouse3D.subSelf(camera.position).normalize());
    var intersects = ray.intersectObject(crateMesh); // store intersecting objects

    if (intersects.length > 0) {
        SELECTED = intersects[0].object;
        var intersects = ray.intersectObject(plane);
    }

}

/** This event handler is only fired after the mouse down event and
    before the mouse up event and only when the mouse moves */
function onDocumentMouseMove(event) {
    event.preventDefault();

    mouse3D.x = mouse2D.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse3D.y = mouse2D.y = -(event.clientY / window.innerHeight) * 2 + 1;
    mouse3D.z = 0.5;
    projector.unprojectVector(mouse3D, camera);

    var ray = new THREE.Ray(camera.position, mouse3D.subSelf(camera.position).normalize());

    if (SELECTED) {
        var intersects = ray.intersectObject(plane);
        dragVector.sub(mouse2D, mouseDown2D);
        return;
    }

    var intersects = ray.intersectObject(crateMesh);

    if (intersects.length > 0) {
        if (INTERSECTED != intersects[0].object) {
            INTERSECTED = intersects[0].object;
        }
    }
    else {
        INTERSECTED = null;
    }
}

/** Removes event listeners when the mouse button is let go */
function onDocumentMouseUp(event) {
    event.preventDefault();

    /** Update mouse position */
    mouse3D.x = mouse2D.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse3D.y = mouse2D.y = -(event.clientY / window.innerHeight) * 2 + 1;
    mouse3D.z = 0.5;

    if (INTERSECTED) {
        SELECTED = null;
    }

    mouseDown = false;
    dragVector.set(0, 0);
}

/** Removes event listeners if the mouse runs off the renderer */
function onDocumentMouseOut(event) {
    event.preventDefault();

    if (INTERSECTED) {
        plane.position.copy(INTERSECTED.position);
        SELECTED = null;
    }
    mouseDown = false;
    dragVector.set(0, 0);
}

解决方案

Basically, you need to project from the 3D world space and the 2D screen space.

Renderers use projectVector for translating 3D points to the 2D screen. unprojectVector is basically for doing the inverse, unprojecting 2D points into the 3D world. For both methods you pass the camera you're viewing the scene through.

So, in this code you're creating a normalised vector in 2D space. To be honest, I was never too sure about the z = 0.5 logic.

mouse3D.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse3D.y = -(event.clientY / window.innerHeight) * 2 + 1;
mouse3D.z = 0.5;

Then, this code uses the camera projection matrix to transform it to our 3D world space.

projector.unprojectVector(mouse3D, camera);

With the mouse3D point converted into the 3D space, we can now use it for getting the direction and then use the camera position to throw a ray from.

var ray = new THREE.Ray(camera.position, mouse3D.subSelf(camera.position).normalize());
var intersects = ray.intersectObject(plane);

这篇关于Three.js投影机和雷对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆