2012-09-11 36 views
16

我試圖實現該算法對本文所解釋的,用於遍歷網格單元,以便下面的一條直線上,其是用於光線跟蹤有用:如何在「光線追蹤的快速體素遍歷算法」中初始化t變量?

http://www.cse.yorku.ca/~amana/research/grid.pdf

本文介紹的算法作爲兩個部分:初始化和迭代遍歷。我可以低估迭代遍歷的部分,但是我很難理解如何計算初始化部分中的一些變量。

我需要初始化幫助tMaxX,tMaxY,tDeltaX & tDeltaY。其初始化過程解釋如下:

接下來,我們確定噸的在其中光線穿過第一個 垂直體素邊界並將其存儲在變量tMaxX值。我們在y中執行類似的計算 並將結果存儲在tMaxY中。 這兩個值的最小值表示我們可以沿着光線行進多少,並仍然保留在當前體素中。

最後,我們計算tDeltaX和tDeltaY。 TDeltaX指示沿着我們必須移動的光線(以t爲單位)多遠,這樣的移動的水平分量等於體素的寬度。類似地, 在tDeltaY中存儲沿垂直分量等於體素高度的射線的移動量。

我無法從上面給出的英文描述中推斷出我需要的代碼。有人可以將它翻譯成數學/僞代碼表達式嗎?

回答

10

初始化爲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

+0

什麼是x1和x2? – subb

+0

@subb起點和終點的座標 – MBo

+0

必須注意的是,與某些標準庫中實現的不同,此Frac()函數必須爲負數返回一個* positive *分數(對於負數返回負數部分)。 – josch

2

正面和負面方向(在CUDA C中)爲3D工作的人:

#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 

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,但您可以根據需要輕鬆修改它。