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
// ...
}
// 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
// ...
}
1条答案
按热度按时间deyfvvtc1#
假设SDF在半整数坐标i处采样。例如,
f[0][0][0]
是单元格中间的值,该单元格跨越(0,0,0)和(1,1,1)之间的3D空间。如果要使用类似minecraft的立方体网格对其进行体素化,则可以沿着以下方式执行操作:(Note:我省略了处理
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.然后运行与上面相同的代码,但不是EmitVertex(vec3(x,y,z))
,它将在整数位置发出顶点,而是使用扰动位置:EmitVertex(p[z][y][x])
: