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

时间:2016-02-01 17:09:02

标签: stl three.js geometry mesh smooth

我正在尝试使用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 );
});

这是我试过的,它会抛出一个错误:未捕获TypeError:smooth.mergeVertices不是函数

如果我评论“mergeVertices()”行,我得到的是一个不同的错误:未捕获的TypeError:无法读取SubdivisionsModifier第156行中未定义的属性'length'。

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

提前致谢!

4 个答案:

答案 0 :(得分:5)

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

这里的问题是STLLoader返回的BufferGeometry没有计算顶点/顶点,所以我必须手动完成。之后,在computeVertexNormals()和voilà之前应用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 );
});

enter image description here

答案 1 :(得分: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 )

答案 2 :(得分:1)

加载obj文件时发生了这个问题。如果您有像3dsmax这样的3d软件:

  1. 打开obj文件,
  2. 转到多边形选择模式并选择所有多边形。
  3. 在“曲面属性”面板下,单击“自动平滑”按钮。
  4. 将模型导回obj格式
  5. 现在您不必调用函数geometry.mergeVertices()和geometry.computeVertexNormals();.只需加载obj并添加到场景中,网格就会很流畅。

    编辑: 我的obj文件默认使用meshphongmaterial,并且在将着色属性更改为值2时,网格变得平滑。

    child.material.shading = 2
    

答案 3 :(得分:0)

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