用Three.js将纹理应用于非立方体多面体

时间:2013-10-03 21:35:26

标签: javascript three.js textures

我使用Three.js生成一个多面体,每个面上都有不同的颜色和文字,由canvas元素生成。现在,我坚持使用多面体,其中Three.js包含原生类,但在某些时候,我想分支出更不规则的形状。

在线提供了许多示例(包括StackOverflow帖子,如Three.js cube with different texture on each face),这些示例解释了如何使用多维数据集执行此操作。我没有成功找到任何显示应用于非立方体的相同技术的样本,但在大多数情况下,适用于CubeGeometry的相同过程也适用于TetrahedronGeometry等。

这是我用来生成多面体的代码的简化版本:

switch (shape) {
    case "ICOSAHEDRON" :

        // Step 1: Create the appropriate geometry.
        geometry = new THREE.IcosahedronGeometry(PolyHeatMap.GEOMETRY_CIRCUMRADIUS);

        // Step 2: Create one material for each face, and combine them into one big
        // MeshFaceMaterial.
        material = new THREE.MeshFaceMaterial(createMaterials(20, textArray));

        // Step 3: Pair each face with one of the materials.
        for (x = 0; face = geometry.faces[x]; x++)
        {
            face.materialIndex = x;
        }
        break;

     // And so on, for other shapes.
}

function createTexture (title, color) {
    var canvas = document.createElement("canvas");

    // Magical canvas generation happens here.

    var texture = new THREE.Texture(canvas);
    texture.needsUpdate = true;

    return new THREE.MeshLambertMaterial({ map : texture });
}

function createMaterials (numFacets, textArray)
{
    var materialsArray = [],
        material;

    for (var x = 0, xl = numFacets; x < xl; x++)
    {
        material = createTexture(textArray[x], generateColor(textArray[x]));
        material.side = THREE.DoubleSide;
        materials.push(oMaterial); 
    }

    return materials;
}

使用此技术可以完美渲染多维数据集,但对于其他多面体,纹理的行为不符合预期:

Icosahedron Example

很难准确解释这里发生的事情。基本上,每个面都显示正确的纹理,但纹理本身已被拉伸和移动,就像覆盖整个多面体一样。换句话说 - 看着形状死亡 - 左上角仅显示其纹理的左上部分,右上角仅显示右上部分,依此类推。

多面体另一侧的面根本没有显示纹理细节;只有颜色。

在尝试使用Three.js之前我没有使用3D渲染的经验,所以我想有一些我缺少的步骤是由CubeGeometry自动处理但不是它的姐妹类。我将参考已发布的其他示例,但大多数示例都是渲染立方体,而那些不使用纯色的示例。

要对非立方体形状上的纹理进行缩放和正确居中需要做些什么?

1 个答案:

答案 0 :(得分:1)

您需要设置新的UV。

我举了一个简单的例子,怎么做,不知道它是不是最好的方法。

jsFiddle example

更新

  geometry.faceVertexUvs[0] = [];

   for(var i = 0; i < geometry.faces.length; i++){                              

        // set new coordinates, all faces will have same mapping.            
        geometry.faceVertexUvs[0].push([
        new THREE.Vector2( 0,0 ),
        new THREE.Vector2( 0,1 ),
        new THREE.Vector2( 1,1),

        ]);
    }