如何在 STL 加载的 BufferGeometry 中平滑网格三角形

How to smooth mesh triangles in STL loaded BufferGeometry

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

我已经成功应用了其他 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 属性 'length' of undefined 在 SubdivisionsModifier 中,第 156 行。

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

提前致谢!

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

这里的问题是STLLoader返回的BufferGeometry没有计算出来vertices/vertex,所以我不得不手动计算。之后,在 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 );
});

然后,您可以将其转换回 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 )

我在加载 obj 文件时遇到了这个问题。如果你有像 3dsmax 这样的 3d 软件:

  1. 打开obj文件,
  2. 转到多边形 selection 模式和 select 所有多边形。
  3. 在表面属性面板下,单击 'Auto Smooth' 按钮。
  4. 将模型导出回 obj 格式

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

编辑: 默认情况下,我的 obj 文件具有 meshphongmaterial,并且在将阴影 属性 更改为值 2 时,网格变得平滑。

child.material.shading = 2

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