【问题标题】:How to smooth mesh triangles in STL loaded BufferGeometry如何在 STL 加载的 BufferGeometry 中平滑网格三角形
【发布时间】:2016-05-10 05:50:46
【问题描述】:

我正在尝试使用 Three.js 加载一些 STL 文件。模型已正确加载,但我想合并/平滑的三角形太多。

我已经成功地应用了其他 3D 格式的平滑加载地形,但我无法使用通过 STLLoader 加载 STL 文件产生的 BufferGeometry 来实现。

_

var material = new THREE.MeshLambertMaterial( { ... } );
var path = "./models/budah.stl";
var loader = new THREE.STLLoader();
loader.load( path, function ( object ) {
                object.computeBoundingBox();
                object.computeBoundingSphere();
                object.computeFaceNormals();
                object.computeVertexNormals();
                object.normalizeNormals();
                object.center();

                // Apply smooth
                var modifier = new THREE.SubdivisionModifier( 1);
                var smooth = smooth = object.clone();
                smooth.mergeVertices();
                smooth.computeFaceNormals();
                smooth.computeVertexNormals();
                modifier.modify( smooth );
                scene.add( smooth );
});

这是我试过的,它抛出一个错误:Uncaught TypeError: smooth.mergeVertices is not a function

如果我评论“mergeVertices()”行,我得到的是一个不同的错误:Uncaught TypeError: Cannot read property 'length' of undefined in SubdivisionsModifier,第 156 行。

我正在尝试的示例代码似乎已经过时(由于 Three.JS 库中的巨大变化,最近经常发生这种情况)。或者,也许我忘记了什么。事实是顶点似乎为空..?

提前致谢!

【问题讨论】:

    标签: stl three.js geometry mesh smooth


    【解决方案1】:

    看来我看错了方向:平滑三角形与 SubdivisionsModifier 无关...我需要的比这更容易,只需在应用材质之前计算顶点,因此它可以使用 SmoothShading 而不是FlatShading(我猜对了吗?)。

    这里的问题是 STLLoader 返回的 BufferGeometry 没有计算顶点/顶点,所以我不得不手动进行。之后,在 computeVertexNormals() 之前应用 mergeVertices() ,瞧!三角形消失,一切顺利:

    var material = new THREE.MeshLambertMaterial( { ... } );
    var path = "./models/budah.stl";
    var loader = new THREE.STLLoader();
    loader.load( path, function ( object ) {                
                    object.computeBoundingBox();
                    object.computeVertexNormals();
                    object.center();
                    ///////////////////////////////////////////////////////////////
    
                    var attrib = object.getAttribute('position');
                    if(attrib === undefined) {
                        throw new Error('a given BufferGeometry object must have a position attribute.');
                    }
                    var positions = attrib.array;
                    var vertices = [];
                    for(var i = 0, n = positions.length; i < n; i += 3) {
                        var x = positions[i];
                        var y = positions[i + 1];
                        var z = positions[i + 2];
                        vertices.push(new THREE.Vector3(x, y, z));
                    }
                    var faces = [];
                    for(var i = 0, n = vertices.length; i < n; i += 3) {
                        faces.push(new THREE.Face3(i, i + 1, i + 2));
                    }
    
                    var geometry = new THREE.Geometry();
                    geometry.vertices = vertices;
                    geometry.faces = faces;
                    geometry.computeFaceNormals();              
                    geometry.mergeVertices()
                    geometry.computeVertexNormals();
    
                    ///////////////////////////////////////////////////////////////
                    var mesh = new THREE.Mesh(geometry, material);
    
                    scene.add( mesh );
    });
    

    【讨论】:

    • 请有人纠正我:所以如果我只想让网格在视觉上变得平滑,我需要在应用材质之前合并Vertices() + computeVertexNormals()(更好的性能)。另一方面,SubdivisionsModifiers 允许修改网格本身,使越来越多的三角形在物理上平滑(大型模型的性能低下)。这个概念对吗?
    • 我认为您需要替换“对象”。通过“object.geometry”(乘以 4 个位置)。 (通过该编辑)您的解决方案解决了我尝试从 OBJ 源文件中获得平滑阴影的问题,非常感谢:-)。
    【解决方案2】:

    然后,您可以将其转换回 BufferGeometry,因为对于更复杂的模型,它的 GPU/CPU 效率更高:

    var geometry = new THREE.Geometry();
    geometry.vertices = vertices;
    geometry.faces = faces;
    geometry.computeFaceNormals();
    geometry.mergeVertices();
    geometry.computeVertexNormals();
    var buffer_g = new THREE.BufferGeometry();
    buffer_g.fromGeometry(geometry);
    var mesh = new THREE.Mesh(buffer_g, material);
    scene.add( mesh )
    

    【讨论】:

      【解决方案3】:

      我在加载 obj 文件时发生了这个问题。如果你有 3ds​​max 之类的 3d 软件:

      1. 打开 obj 文件,
      2. 进入多边形选择模式并选择所有多边形。
      3. 在“曲面属性”面板下,单击“自动平滑”按钮。
      4. 将模型导出回 obj 格式

      现在您不必调用函数 geometry.mergeVertices() 和 geometry.computeVertexNormals();。只需加载 obj 并添加到场景中,网格就会变得平滑。

      编辑: 我的 obj 文件默认具有 meshphongmaterial,将着色属性更改为值 2 后,网格变得平滑。

      child.material.shading = 2
      

      【讨论】:

        【解决方案4】:

        STL 不支持顶点索引。 这就是它复制了所有三角形的顶点的原因。 每个顶点的法线为三角形法线。 结果,在同一位置(多个非常闭合的顶点),有多个法线值。 当使用法线进行光照计算时,这会导致几何体表面不光滑。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-06-11
          • 1970-01-01
          • 1970-01-01
          • 2011-11-15
          • 1970-01-01
          • 2019-11-01
          • 1970-01-01
          相关资源
          最近更新 更多