如何在“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

论文将算法描述为两个部分:初始化和迭代遍历。我可以理解迭代遍历部分,但我无法理解初始化部分中的一些变量是如何计算的。

我需要帮助初始化 tMaxXtMaxYtDeltaXtDeltaY。它们的初始化过程解释如下:

接下来,我们确定光线穿过第一个 垂直体素边界并将其存储在变量 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 中开始新的活动?

在 Avkit 中如何使用这三行代码,以及如何将音乐静音”

如何在 JDBC 中启动事务?

如何在 Fragment 中调用 OnActivityResult 以及它是如何工作的?

如何使用 Firebase 在 Web 上托管 Flutter?它的效果如何?