Marching Cubes算法如何结合无符号距离场(UDF)实现网格生成?
无符号距离场(UDF)下Marching Cubes的运行机制解释
首先明确核心前提:原生Marching Cubes的本质是提取三维标量场的指定等值面,算法本身只要求能区分体素顶点处于等值面的「高于阈值侧」和「低于阈值侧」,并不绑定有符号距离场(SDF)的内外语义,只要能给UDF构造出两类状态的区分逻辑,就能直接复用现有MC实现。
目前工业界和学术界主流的UDF适配方案有两种,都可以直接对接你在用的skimage.measure.marching_cubes_lewiner接口:
方案1:伪符号构造法(DUDE论文采用方案)
这是最轻量化、不需要修改现有MC代码的方案,实现逻辑如下:
- 首先根据你的场景分辨率选定一个极小的距离阈值
τ,通常取体素边长的1/2,常见取值范围为1e-3~1e-2 - 对所有空间点的UDF值做线性转换:
fake_sdf = udf(x) - τ - 将转换后的
fake_sdf作为输入标量场传入MC接口,提取level=0的等值面即可 - 逻辑说明:转换后的
fake_sdf小于0的区域,对应所有距离真实表面小于τ的空间点,大于0的区域对应距离表面大于τ的点,相当于把「距离表面厚度为τ的薄层」定义为伪SDF的「内部」,这样就构造出了MC需要的正负二分类状态,提取出的网格和真实表面几乎重合,当τ足够小时误差可以忽略。
方案2:梯度引导符号赋值法
如果需要提取严格的0等值面、不想引入τ带来的薄壁误差,可以采用这种方案:
- 首先对每个体素顶点计算UDF的梯度
g = ∇udf(x),UDF的梯度方向天然指向最近的表面点 - 预先选定一个已知处于场景外部的参考点
p_out,计算顶点x到参考点的方向向量v = x - p_out - 计算点积
v·g:如果结果大于0,说明顶点在表面外侧,赋值s = +udf(x);如果结果小于0,说明顶点在表面内侧,赋值s = -udf(x) - 将得到的带符号标量场
s输入MC接口,提取level=0的等值面即可 - 逻辑说明:利用UDF梯度的方向特性反向推导点的内外属性,生成和原生SDF完全一致的标量场,不需要引入阈值误差,输出结果和SDF场景下的MC输出无差异。
现有接口适配说明
你当前使用的skimage.measure.marching_cubes_lewiner接口本身没有强制要求输入标量场为SDF,只要是三维浮点数组即可,按照上述两种方案处理UDF后直接传入接口,指定对应的level参数就能正常生成网格。
内容的提问来源于stack exchange,提问作者Saipy
相关产品推荐
相关产品推荐

