【发布时间】:2014-02-11 21:56:15
【问题描述】:
对于固定大小的体素数据,计算梯度的最有效方法是什么,例如下面的源代码。请注意,我需要空间中任何点的渐变。梯度将用于估计行进立方体实现中的法线。
#import <array>
struct VoxelData {
VoxelData(float* data, unsigned int xDim, unsigned int yDim, unsigned int zDim)
:data(data), xDim(xDim), yDim(yDim), zDim(zDim)
{}
std::array<float,3> get_gradient(float x, float y, float z){
std::array<float,3> res;
// compute gradient efficiently
return res;
}
float get_density(int x, int y, int z){
if (x<0 || y<0 || z<0 || x >= xDim || y >= yDim || z >= zDim){
return 0;
}
return data[get_element_index(x, y, z)];
}
int get_element_index(int x, int y, int z){
return x * zDim * yDim + y*zDim + z;
}
const float* const data;
const unsigned int xDim;
const unsigned int yDim;
const unsigned int zDim;
};
更新 1 可以在此处找到该问题的演示项目:
https://github.com/mortennobel/OpenGLVoxelizer
目前输出如下图(基于 MooseBoys 代码):
更新 2 我正在寻找的解决方案必须提供相当准确的渐变,因为它们在可视化中用作法线,并且必须避免像下面这样的视觉伪影。
更新 2 用户示例的解决方案是:
【问题讨论】:
-
我很感兴趣为什么你需要任何点的梯度。看来这将是任何容易优化的机会。此外,点的规则间距(与三角形大小变化的典型阴影相反)可能比逐点 get_gradient 提供更好的方法。您是否考虑过这种可能性?
-
有一个潜在的性能优化,因为我只需要渐变立方体生成的每个顶点,这些顶点总是有两个位于整数的轴(换句话说,这可以简化计算到两个线性插值和一个三线性插值)。
-
如果每个网格点都有梯度(向量 [x,y,z]),那么(梯度的)三线性插值将变为沿一个轴的线性插值(非积分一)。另一方面,您可以将梯度计算为插值密度场的导数。我不知道它有什么优点/缺点,但它会更慢。你打算用哪种方式?
-
您从哪里获取数据?通过使用生成体素的原始数据源而不是体素本身,我得到了惊人的平滑结果。前提是数据采用可以区分的形式,例如平滑字段的总和,这会产生漂亮的结果。
-
@AndyNewman:我处理的体素数据是基于 FEM(有限元方法)的计算(更具体地说是 3D 中的多网格拓扑优化)的结果。 AFAIK 梯度,必须使用插值模式基于体素计算结果。我主要关心的是如何使用合理的快速方法获得最佳的视觉效果(我实际上不认为性能会是一个大问题)。
标签: c++ raytracing voxel marching-cubes