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

11

我正在尝试使用Three.js加载一些STL文件。模型已经成功加载,但是有太多的三角形需要合并/平滑。

我之前在其他3D格式中成功地应用了平滑加载地形,但是我无法在使用STLLoader加载STL文件后对BufferGeometry进行操作。

enter image description here _

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不是函数 如果我注释掉“mergeVertices()”行,我得到不同的错误:Uncaught TypeError:无法读取未定义的属性'length'SubdivisionsModifier,第156行。 看起来我尝试的示例代码已经过时了(由于Three.JS库的巨大变化,最近经常发生这种情况)。或者我忘记了什么。事实上,顶点似乎为空..?
提前致谢!
4个回答

9
看来我一直在错误的方向上寻找解决方法:平滑三角形与SubdivisionsModifier没有任何关系...我需要做的比这更简单,只需在应用材料之前计算顶点,这样它就可以使用SmoothShading而不是FlatShading(我理解得对吗?)。
问题在于STLLoader返回的BufferGeometry没有计算顶点/vertex,所以我必须手动计算。在此之后,应用mergeVertices(),然后再进行computeVertexNormals(),完成!三角形消失了,一切都很平滑。
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 );
});

enter image description here


请有人纠正我,如果我想要简单地使网格平滑视觉上,我需要在应用材质之前执行mergeVertices() + computeVertexNormals()(性能更好)。另一方面,SubdivisionsModifiers允许修改网格本身,使越来越多的三角形物理平滑(对于大型模型性能较低)。这个概念正确吗? - spacorum
我认为你需要将 "object." 替换为 "object.geometry" (4个位置都要替换)。通过这种编辑,你的解决方案解决了我尝试从OBJ源文件获取平滑着色的问题,非常感谢 :-)。 - steveOw

4

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

1
我在加载obj文件时遇到了这个问题。如果您有像3dsmax这样的3D软件:
  1. 打开obj文件,
  2. 进入多边形选择模式并选择所有多边形。
  3. 在表面属性面板下,点击“自动平滑”按钮。
  4. 将模型导出回obj格式。
现在,您无需调用geometry.mergeVertices()和geometry.computeVertexNormals()函数。只需加载obj并添加到场景中,网格就会变得平滑。 编辑: 我的obj文件默认使用meshphongmaterial,将着色属性更改为值2后,网格变得平滑了。
child.material.shading = 2

0

STL不支持顶点索引。 这就是它有所有三角形的重复顶点的原因。 每个顶点都有其三角形法线作为其法线。 因此,在同一位置(多个非常接近的顶点),存在多个法线值。 这会导致在使用法线进行光照计算时几何表面不平滑。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接