我正在尝试实现天真的表面网络算法(在c++,opengl中),如here所述。 。我知道我需要对穿过表面的边的端点进行插值,然后我需要找到这些插值结果的质心。我不明白的是:我现在每个重要单元都有一个顶点,如何将这些顶点排列成形成网格的三角形?
最佳答案
假设您的 SDF 在半整数坐标处采样,即 f[0][0][0]
是单元格中间跨越 (0,0,0) 和 (1,1,1) 之间 3d 空间的值。如果您要使用类似《我的世界》的立方网格体对其进行体素化,您将按照以下方式进行操作:
for each integer x,y,z {
// X-major
if(f[z][y][x-1]*f[z][y][x] < 0) {
v0 = EmitVertex(vec3(x,y,z));
v1 = EmitVertex(vec3(x,y+1,z));
v2 = EmitVertex(vec3(x,y,z+1));
v3 = EmitVertex(vec3(x,y+1,z+1));
if(f[z][y][x] < 0) {
// flip order so normal points along negative X
swap(v0, v3);
}
EmitTriangle(v0, v1, v2);
EmitTriangle(v2, v1, v3);
}
// do the same for Y and Z directions
// ...
}
(注意:我省略了处理 f[z][y][x] == 0
的复杂性。)
对于表面网络,代码本质上保持不变。您使用单元中心的值(例如 f[-1/0][-1/0][-1/0]
)来计算扰动位置 p[0][0][0]
位于这些单元格之间的顶点。平均p[0][0][0] == vec3(0,0,0)
,但它可以是 (-0.5,-0.5,-0.5) 和 (0.5,0.5,0.5) 之间的任意值。然后运行与上面相同的代码,但不是 EmitVertex(vec3(x,y,z))
,这会在整数位置发出顶点,您使用扰动位置: EmitVertex(p[z][y][x])
:
// precompute vertex locations
for each integer x,y,z {
p[z][y][x] = vec3(x,y,z) + deviation(
f[z-1][y-1][x-1], f[z-1][y-1][x], f[z-1][y][x-1], f[z-1][y][x],
f[z][y-1][x-1], f[z][y-1][x], f[z][y][x-1], f[z][y][x]
);
}
// generate mesh
for each integer x,y,z {
// X-major
if(f[z][y][x-1]*f[z][y][x] < 0) {
v0 = EmitVertex(p[z][y][x]);
v1 = EmitVertex(p[z][y+1][x]);
v2 = EmitVertex(p[z+1][y][x]);
v3 = EmitVertex(p[z+1][y+1][x]);
// same as before ...
}
// do the same for Y and Z directions
// ...
}
关于c++ - 朴素表面网络算法 : how to connect vertices to form triangles?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76113537/