我已经在 JavaScript 中并使用 Three.js 实现了拉普拉斯平滑,但它似乎没有按预期工作。每当我在网格上使用悬停和平滑时,面就会断开连接并且变得越来越小。这段代码有什么问题?
平滑后网格的输出图像,白色圆圈为画笔,indices 为包含画笔下所有索引的数组。
indices.forEach( index => {
if (params.brush === 'smooth') {
for (let i = 0; i < 3; i++) {
const currentVector = new THREE.Vector3().fromBufferAttribute(posAttr, index);
const nbI = neighborMap.get(index); // Get the neighbors of the current vertex
if (!nbI || nbI.size === 0) return; // Skip if no neighbors
const nbIAr = Array.from(nbI); // Convert neighbor Set to array
// Initialize average position to zero
const avgPos = new THREE.Vector3();
const neighborCount = nbIAr.length;
// Calculate the average position of the neighboring vertices
nbIAr.forEach(neighborIndex => {
const neighborPos = new THREE.Vector3().fromBufferAttribute(posAttr, neighborIndex);
avgPos.add(neighborPos); // Accumulate neighbor positions
});
avgPos.divideScalar(neighborCount); // Compute the average
// Compute the Laplacian (difference between average and current position)
const laplacian = new THREE.Vector3().subVectors(avgPos, currentVector);
// Update the vertex position by moving it toward the average
const lamdaValue = 0.005
currentVector.addScaledVector(laplacian, lamdaValue); // λ
tempVec.copy(currentVector);
}
}
posAttr.setXYZ(index, tempVec.x, tempVec.y, tempVec.z);
normalAttr.setXYZ(index, 0, 0, 0);
});
我增加了 lamda 的值,它使顶点移得很远,
我在平滑过程中遇到的面断开和缩小的问题与加载 STL 文件时在 Three.js 中使用
BufferGeometryUtils.mergeVertices
有关。 STL 文件不包含索引数据,因此该函数尝试生成索引。但生成的索引数据不适合拉普拉斯平滑算法,导致网格失真。
我通过加载 PLY 文件发现了这个问题,该文件默认包含索引数据。使用 PLY 文件时,拉普拉斯平滑按预期工作。