Как инициализировать t-переменные в "Алгоритм обхода ускоренного Voxel для трассировки лучей"? - программирование
Подтвердить что ты не робот

Как инициализировать t-переменные в "Алгоритм обхода ускоренного Voxel для трассировки лучей"?

Я пытаюсь реализовать алгоритм, описанный в этой статье, используемый для пересечения сетчатых ячеек по следующей прямой, что полезно для трассировки лучей:

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

В статье описывается алгоритм как две части: инициализация и итеративный обход. Я могу игнорировать итеративную часть обхода, но мне трудно понять, как вычисляются некоторые из переменных в части инициализации.

Мне нужна помощь, инициализирующая tMaxX, tMaxY, tDeltaX и tDeltaY. Их процедура инициализации объясняется следующим образом:

Далее, мы определяем значение t, при котором луч пересекает первый вертикальной границы вокселя и сохранить его в переменной tMaxX. Мы выполняем аналогичное вычисление по y и сохранение результата в tMaxY. Минимум эти два значения будут указывать, сколько мы можем перемещаться вдоль луча и все еще остаются в текущем вокселе.

Наконец, мы вычисляем tDeltaX и tDeltaY. TDeltaX показывает, насколько далеко вдоль луча мы должны двигаться (в единицах t) для горизонтальной компонент такого движения, равный ширине воксела. По аналогии, хранить в tDeltaY количество движения вдоль луча, которое имеет вертикальная составляющая, равная высоте воксела.

Я не могу вывести код, который мне нужен, из приведенного выше английского описания. Может ли кто-нибудь перевести его на выражение математики/псевдокода для меня?

4b9b3361

Ответ 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

Ответ 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   

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, но вы можете легко изменить ее для своих нужд.