将3D拾取转换为纹理投影?

时间:2016-06-08 23:43:06

标签: three.js

我正在尝试在WebGL中编写一个非常小的工具,它允许我绘制到UV'网格中。到目前为止,其中一个挑战是试图找到一种方法将鼠标拾取位置转换为我应该在加载的纹理中绘制的位置。有没有人有任何例子或可以推荐一些这方面的文献?

1 个答案:

答案 0 :(得分:2)

"技巧"你正在寻找的可能是 THREE.Raycaster.setFromCamera()Here's a jsfiddle这是我认为您尝试做的简单版本。它在一个画布中呈现包含纹理球体的简单场景,并将应用于球体的纹理副本放在另一个画布中。单击球体将在第二个画布上的纹理上的相应点上绘制一个红点。

有趣的是:

init()中,我们定义了一个用于渲染画布的点击处理程序,名为 clickCanvas 。它将click事件的x和y坐标传递给 getClickPosition()

function getClickPosition(n, x, y) {
        var rect;

        rect = n.getBoundingClientRect();
        return([
                (x - rect.left) / n.clientWidth,
                (y - rect.top) / n.clientHeight
        ]);
}

这会将x和y坐标转换为0到1之间的UV-ish有序值对。这些值传递给 projectLocation()

function projectLocation(x, y) {
        var c, i, v, p;

        // Bounds check our coords
        if(x < 0) x = 0;
        if(x > 1) x = 1;
        if(y < 0) y = 0;
        if(y > 1) y = 1;

        // Convert our values from the range [0, 1] to the range [-1, 1]
        v = new THREE.Vector2();
        v.x = x * 2 - 1;
        v.y = (-y * 2) + 1;

        raycaster.setFromCamera(v, camera);
        i = raycaster.intersectObjects(scene.children, true);
        if(i.length > 0) {
                getLocation(i[0]);
        }
}

这将获取UV-ish坐标并将它们转换为介于-1和1之间的值,这是THREE.Raycaster()想要的(在此示例中,使 getClickPosition()自动执行此操作,但在实际代码中,您可能需要在DOM元素中单击的相对位置。 raycaster会发现是否有任何东西与从点击发生的位置(在#34;相机镜头&#34;)投射到场景中的光线相交。从那里,交叉点对象(如果有的话)被传递给 getLocation()

function getLocation(intersect) {
        var uv;

        uv = intersect.uv;
        x = Math.round(uv.x * texture.image.width);
        y = Math.round((1 - uv.y) * texture.image.height);

        canvasCtx.lineWidth = 1;
        canvasCtx.fillStyle = 'red';
        canvasCtx.fillRect(x - 1, y - 1, 2, 2);
        canvasCtx.fill();
}

交点对象包含交点的UV坐标。 getLocation()将这些转换为纹理中的XY坐标。