【问题标题】:Texture shown plain one color on mesh with custom geometry in Three.js在 Three.js 中使用自定义几何图形在网格上显示纯一种颜色的纹理
【发布时间】:2016-11-16 18:34:12
【问题描述】:

我为我的三角形几何图形添加了纹理。但一切都是基于最轻值的一种纯色。然后我知道我应该分配 UV。但同样的问题,但我的纹理颜色最深(见图)。

代码如下:

var material = new THREE.MeshBasicMaterial( { map: new THREE.TextureLoader().load(texture), overdraw: true } );
var geometry = new THREE.Geometry();
// 1re marche de 3 (30 degrées)
geometry.vertices.push(new THREE.Vector3(0.0, 0.0, 0.0));
geometry.vertices.push(new THREE.Vector3(longueurTotalFacteur, largeur, 0.0));
geometry.vertices.push(new THREE.Vector3(0.0, largeur, 0.0));
geometry.vertices.push(new THREE.Vector3(0.0, 0.0, -epaisseur));
geometry.vertices.push(new THREE.Vector3(longueurTotalFacteur, largeur, -epaisseur));
geometry.vertices.push(new THREE.Vector3(0.0, largeur, -epaisseur));
geometry.faces.push(new THREE.Face3(0, 1, 2)); // Dessus
geometry.faces.push(new THREE.Face3(5, 4, 3)); // Dessous
geometry.faces.push(new THREE.Face3(3, 1, 0)); // Côté long
geometry.faces.push(new THREE.Face3(4, 1, 3)); // Côté long
geometry.faces.push(new THREE.Face3(4, 2, 1)); // Côté court
geometry.faces.push(new THREE.Face3(5, 2, 4)); // Côté court
geometry.faces.push(new THREE.Face3(5, 0, 2)); // Côté moyen
geometry.faces.push(new THREE.Face3(3, 0, 5)); // Côté moyen

assignUVs(geometry);
... (snipped)...
function assignUVs(geometry) {
    geometry.faceVertexUvs[0] = [];
    geometry.faces.forEach(function(face) {
        var components = ['x', 'y', 'z'].sort(function(a, b) {
            return Math.abs(face.normal[a]) > Math.abs(face.normal[b]);
        });

        var v1 = geometry.vertices[face.a];
        var v2 = geometry.vertices[face.b];
        var v3 = geometry.vertices[face.c];

        geometry.faceVertexUvs[0].push([
            new THREE.Vector2(v1[components[0]], v1[components[1]]),
            new THREE.Vector2(v2[components[0]], v2[components[1]]),
            new THREE.Vector2(v3[components[0]], v3[components[1]])
        ]);
    });
    geometry.uvsNeedUpdate = true;
}

这是我得到的:

【问题讨论】:

    标签: javascript three.js geometry mesh


    【解决方案1】:

    你不能这样做:

    var material = new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(texture), overdraw: true });

    纹理加载是一个异步过程。您需要在onLoad 回调中应用纹理。请参考the documents for THREE.TextureLoader here。

    你的例子:

    var material = new THREE.MeshBasicMaterial( { overdraw: true } );
    var url = //your texture path...
    var onLoad = function(texture){
        material.map = texture;
        material.needsUpdate = true;
    }
    var loader = new THREE.TextureLoader();
    loader.load(url, onLoad);
    

    更新

    当您计算 UV 时,您需要对偏移量和范围做一些事情。检查来自this example fiddle 的computeUVs;你可能需要为你的楼梯几何形状稍微改变一下......

    function computeUVs(geometry) {
    
      geometry.computeBoundingBox();
    
      var max = geometry.boundingBox.max,
          min = geometry.boundingBox.min;
      var offset = new THREE.Vector2(0 - min.x, 0 - min.y);
      var range = new THREE.Vector2(max.x - min.x, max.y - min.y);
      var faces = geometry.faces;
      var vertices = geometry.vertices;
    
      geometry.faceVertexUvs[0] = [];
    
      for (var i = 0, il = faces.length; i < il; i++) {
    
        var v1 = vertices[faces[i].a],
            v2 = vertices[faces[i].b],
            v3 = vertices[faces[i].c];
    
        geometry.faceVertexUvs[0].push([
          new THREE.Vector2((v1.x + offset.x) / range.x, (v1.y + offset.y) / range.y),
          new THREE.Vector2((v2.x + offset.x) / range.x, (v2.y + offset.y) / range.y),
          new THREE.Vector2((v3.x + offset.x) / range.x, (v3.y + offset.y) / range.y)
        ]);
      }
      geometry.uvsNeedUpdate = true;
    }
    

    此代码基于this stackoverflow answer。

    【讨论】:

    • 我用你的答案更新了我的代码,但没有任何改变。 var material1 = new THREE.MeshBasicMaterial(); var geometry = new THREE.Geometry(); // 这里的几何设置向量去掉了assignUVs(geometry); var onLoad = function(_texture) { material1.map = _texture; material1.needsUpdate = true; };几何.userData = 模型; // 保留以备后用。网格[no] = new THREE.Mesh(几何,material1); groupe.add(mesh[no]); var loader = new THREE.TextureLoader; loader.load(texture, onLoad);
    • @Wilt TextureLoader.load 函数返回一个纹理对象。异步部分位于 THREE.ImageLoader 中的 TextureLoader.load 函数中,该函数会更新纹理。您发布并说的代码不起作用,实际上确实有效。
    • 不过,我不确定这样做的含义
    • @MartinPineault 我更新了我的答案......我只是引用了不起作用的内容。您应该仔细read the docs 并查看一些示例。加载纹理并不复杂,只要您遵循文档...
    • @2pha 我发布了 '你不能这样做' :D 我现在格式化为引用 ;) 并添加了一个示例...
    猜你喜欢
    • 1970-01-01
    • 2017-03-28
    • 2019-08-23
    • 2011-11-02
    • 2016-03-08
    • 2020-12-12
    • 2015-03-16
    • 1970-01-01
    • 2021-08-01
    相关资源
    最近更新 更多