如何在“A Fast Voxel Traversal Algorithm for Ray Tracing”中初始化 t 变量?
Posted
技术标签:
【中文标题】如何在“A Fast Voxel Traversal Algorithm for Ray Tracing”中初始化 t 变量?【英文标题】:How do I initialize the t-variables in "A Fast Voxel Traversal Algorithm for Ray Tracing"? 【发布时间】:2012-09-04 05:27:50 【问题描述】:我正在尝试实现本文中解释的算法,用于沿直线遍历网格单元,这对于光线追踪很有用:
http://www.cse.yorku.ca/~amana/research/grid.pdf
论文将算法描述为两个部分:初始化和迭代遍历。我可以理解迭代遍历部分,但我无法理解初始化部分中的一些变量是如何计算的。
我需要帮助初始化 tMaxX
、tMaxY
、tDeltaX
和 tDeltaY
。它们的初始化过程解释如下:
接下来,我们确定光线穿过第一个 垂直体素边界并将其存储在变量 tMaxX 中。我们执行一个 在 y 中进行类似的计算并将结果存储在 tMaxY 中。最小的 这两个值将指示我们可以沿着射线行进多少 并且仍然保留在当前体素中。
最后,我们计算 tDeltaX 和 tDeltaY。 TDeltaX 表示多远 我们必须沿着射线移动(以 t 为单位) 这种运动的分量等于体素的宽度。相似地, 在 tDeltaY 中存储沿具有 a 的射线的移动量 垂直分量等于体素的高度。
我无法从上面给出的英文描述中推断出我需要的代码。有人可以帮我把它翻译成数学/伪代码表达式吗?
【问题讨论】:
【参考方案1】:X坐标变量的初始化(Y同理)
DX = X2 - X1
tDeltaX = GridCellWidth / DX
tMaxX = tDeltaX * (1.0 - Frac(X1 / GridCellWidth))
//Frac if fractional part of float, for example, Frac(1.3) = 0.3, Frac(-1.7)=0.3
例子:
GridCellWidth, Height = 20
X1 = 5, X2 = 105
Y1 = 5, Y2 = 55
DX = 100, DY = 50
tDeltaX = 0.2, tDeltaY = 0.4
tMaxX = 0.2 * (1.0 - 0.25) = 0.15 //ray will meet first vertical line at this param
tMaxY = 0.4 * (1.0 - 0.25) = 0.3 //ray will meet first horizontal line at this param
我们可以看到第一个单元格边界将在参数 t = 0.15 处遇到
【讨论】:
必须注意,这个 Frac() 函数必须为负数返回一个 positive 分数,这与在某些标准库中实现的(返回一个负分数)相反负数)。 负值对我不起作用,例如:x1 = 0, x2 = 0; x1 = 1,x2 = -1;宽度 = 1 高度 = 1 dx = 1; dy = -1 tDeltaX = 1; tDeltaY = -1; tMaxX = 1 * (1 - 0) = 1 tMaxY = -1 * (1 - 0) = -1;在这种情况下,tMaxY 总是小于 tMaxX,加上 tDeltaY 不会有太大变化 @SnowyCoder 将方向(使用镜像)变换到坐标平面的第一象限。【参考方案2】:在 3D 中为我工作的正向和负向(在 CUDA C 中):
#define SIGN(x) (x > 0 ? 1 : (x < 0 ? -1 : 0))
#define FRAC0(x) (x - floorf(x))
#define FRAC1(x) (1 - x + floorf(x))
float tMaxX, tMaxY, tMaxZ, tDeltaX, tDeltaY, tDeltaZ;
int3 voxel;
float x1, y1, z1; // start point
float x2, y2, z2; // end point
int dx = SIGN(x2 - x1);
if (dx != 0) tDeltaX = fmin(dx / (x2 - x1), 10000000.0f); else tDeltaX = 10000000.0f;
if (dx > 0) tMaxX = tDeltaX * FRAC1(x1); else tMaxX = tDeltaX * FRAC0(x1);
voxel.x = (int) x1;
int dy = SIGN(y2 - y1);
if (dy != 0) tDeltaY = fmin(dy / (y2 - y1), 10000000.0f); else tDeltaY = 10000000.0f;
if (dy > 0) tMaxY = tDeltaY * FRAC1(y1); else tMaxY = tDeltaY * FRAC0(y1);
voxel.y = (int) y1;
int dz = SIGN(z2 - z1);
if (dz != 0) tDeltaZ = fmin(dz / (z2 - z1), 10000000.0f); else tDeltaZ = 10000000.0f;
if (dz > 0) tMaxZ = tDeltaZ * FRAC1(z1); else tMaxZ = tDeltaZ * FRAC0(z1);
voxel.z = (int) z1;
while (true)
if (tMaxX < tMaxY)
if (tMaxX < tMaxZ)
voxel.x += dx;
tMaxX += tDeltaX;
else
voxel.z += dz;
tMaxZ += tDeltaZ;
else
if (tMaxY < tMaxZ)
voxel.y += dy;
tMaxY += tDeltaY;
else
voxel.z += dz;
tMaxZ += tDeltaZ;
if (tMaxX > 1 && tMaxY > 1 && tMaxZ > 1) break;
// process voxel here
注意,在我的例子中,网格单元格的宽度/高度/深度都等于 1,但您可以根据需要轻松修改它。
【讨论】:
以上是关于如何在“A Fast Voxel Traversal Algorithm for Ray Tracing”中初始化 t 变量?的主要内容,如果未能解决你的问题,请参考以下文章
如何在异步任务中调用意图?或者如何在 onPostExecute 中开始新的活动?