Three.js - 从UV坐标计算3D坐标

时间:2017-01-15 13:42:39

标签: three.js uv-mapping

当图像被包裹为围绕3D形状的纹理时,我正试图将THREE.js中的对象的位置从平面2D坐标(放置在2D图像上的注释)转换为3D坐标。我们的想法是将一个小的3D物体放置在相同的3D坐标上以表示2D注释。

我可以通过获取与真正整洁的raycaster相交的对象的uv.x和uv.y属性来反过来。

以上是否可以在三个?我需要能够考虑不同的形状几何形状。

1 个答案:

答案 0 :(得分:1)

想出来:

给定您要定位的点的UV坐标:

首先,您需要递归遍历模型中的每个三角形,从每个三角形中传递UV坐标,并使用重心技术与面顶点UV阵列进行比较,以根据UV判断三角形内部是否存在点。 / p>

找到正确的三角形后,您可以找到三角形的相关顶点,并将重心坐标应用于该三角形,以获得局部空间中的坐标。

然后转换为世界空间。

代码如下,有点粗糙,准备好但你明白了:

// Recursively traverse through the model.
var traversePolygonsForGeometries = function (node, uvx, uvy) {
if (node.geometry) {
    // Return a list of triangles that have the point within them.
    // The returned objects will have the x,y,z barycentric coordinates of the point inside the respective triangle
    var baryData = annotationTest(uvx, uvy, node.geometry.faceVertexUvs);
    if (baryData.length) {
        for (var j = 0; j < baryData.length; j++) {
            // In my case I only want to return materials with certain names.
            if (node.geometry.faces[baryData[j][0]].daeMaterial === 
                "frontMaterial" || node.geometry.faces[baryData[j][0]].daeMaterial ===
                "print_area1_0"
                ) {
                // Find the vertices corresponding to the triangle in the model
                var vertexa = node.geometry.vertices[node.geometry.faces[baryData[j][0]].a];
                var vertexb = node.geometry.vertices[node.geometry.faces[baryData[j][0]].b];
                var vertexc = node.geometry.vertices[node.geometry.faces[baryData[j][0]].c];
                // Sum the barycentric coordinates and apply to the vertices to get the coordinate in local space
                var worldX = vertexa.x * baryData[j][1] + vertexb.x * baryData[j][2] + vertexc.x * baryData[j][3];
                var worldY = vertexa.y * baryData[j][1] + vertexb.y * baryData[j][2] + vertexc.y * baryData[j][3];
                var worldZ = vertexa.z * baryData[j][1] + vertexb.z * baryData[j][2] + vertexc.z * baryData[j][3];
                var vector = new THREE.Vector3(worldX, worldY, worldZ);
                // Translate to world space
                var worldVector = vector.applyMatrix4(node.matrixWorld);
                return worldVector;
            }
        }
    }
}
if (node.children) {
    for (var i = 0; i < node.children.length; i++) {
        var worldVectorPoint = traversePolygonsForGeometries(node.children[i], uvx, uvy);
        if (worldVectorPoint) return worldVectorPoint;
    }
}
};

// Loops through each face vertex UV item and tests if it is within the triangle.
function annotationTest(uvX, uvY, faceVertexUvArray) {
    var point = {};
    point.x = uvX;
    point.y = uvY;
    var results = [];
    for (i = 0; i < faceVertexUvArray[0].length; i++) {
        var result = ptInTriangle(point, faceVertexUvArray[0][i][0], faceVertexUvArray[0][i][1], faceVertexUvArray[0][i][2]);
        if (result.length) {
            results.push([i, result[0], result[1], result[2]]);
        }
    }
    return results;
};

// This is a standard barycentric coordinate function.
function ptInTriangle(p, p0, p1, p2) {
    var x0 = p.x;
    var y0 = p.y;
    var x1 = p0.x;
    var y1 = p0.y;
    var x2 = p1.x;
    var y2 = p1.y;
    var x3 = p2.x;
    var y3 = p2.y;

    var b0 = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1)
    var b1 = ((x2 - x0) * (y3 - y0) - (x3 - x0) * (y2 - y0)) / b0
    var b2 = ((x3 - x0) * (y1 - y0) - (x1 - x0) * (y3 - y0)) / b0
    var b3 = ((x1 - x0) * (y2 - y0) - (x2 - x0) * (y1 - y0)) / b0

    if (b1 > 0 && b2 > 0 && b3 > 0) {
        return [b1, b2, b3];
    } else {
        return [];
    }
};