如何在 STL 加载的 BufferGeometry 中平滑网格三角形
Posted
技术标签:
【中文标题】如何在 STL 加载的 BufferGeometry 中平滑网格三角形【英文标题】:How to smooth mesh triangles in STL loaded 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 库中的巨大变化,最近经常发生这种情况)。或者,也许我忘记了什么。事实是顶点似乎为空..?
提前致谢!
【问题讨论】:
【参考方案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 文件时发生了这个问题。如果你有 3dsmax 之类的 3d 软件:
-
打开 obj 文件,
进入多边形选择模式并选择所有多边形。
在“曲面属性”面板下,单击“自动平滑”按钮。
将模型导出回 obj 格式
现在您不必调用函数 geometry.mergeVertices() 和 geometry.computeVertexNormals();。只需加载 obj 并添加到场景中,网格就会变得平滑。
编辑: 我的 obj 文件默认具有 meshphongmaterial,将着色属性更改为值 2 后,网格变得平滑。
child.material.shading = 2
【讨论】:
【参考方案4】:STL 不支持顶点索引。 这就是它复制了所有三角形的顶点的原因。 每个顶点的法线为三角形法线。 结果,在同一位置(多个非常闭合的顶点),有多个法线值。 当使用法线进行光照计算时,这会导致几何体表面不光滑。
【讨论】:
以上是关于如何在 STL 加载的 BufferGeometry 中平滑网格三角形的主要内容,如果未能解决你的问题,请参考以下文章
使用 Vue-cli 和 Three.js 加载 STL 文件
three.js加载stl模型文件,怎么能让模型大小一致并居中
使用 C++ Boost 或 STL 和 Mysql 存储和检索图像
Amazon Redshift:当找到的表 id 不匹配时,如何将 `stl_load_errors` 行与正确的表名相关联?