Я работаю над реализацией воксельного октодерева Raycaster, и единственное, что осталось, - это переупорядочить данные для заполнения конечного уровня октодерева, чтобы затем данные можно было усреднить для построения нижних уровней дерева.
Я изначально думаю в 2D (квадродерево) для удобства. У меня данные упорядочены, как показано слева на чертеже, и в настоящее время я могу переставить их, как справа. Пример - 8x8
.
Однако я понял, что мне нужно упорядочить данные в порядке узлов, как на рисунке ниже:
Другими словами, я хочу перейти от массива, где данные соответствуют таким индексам:
[0 1 2 3 4 5 6 7 8 9 ... 63]
в массив, который будет иметь данные в следующем порядке:
[0 1 4 5 16 17 20 21 2 3 ... 63]
для примера 8x8
квадродерева.
Я не могу понять, как это сделать. Моя основная проблема связана с произвольным размером дерева. Я, вероятно, мог бы жестко закодировать набор вложенных циклов, если бы заранее знал размер, но это явно не лучшее или элегантное решение. Я думаю, что есть рекурсивный способ добиться этого.
Это мой быстрый и грязный набросок для сортировки данных способом, описанным на рисунке 1. Он в основном работает, отслеживая четыре позиции в исходных данных, а затем продвигая их вперед по мере заполнения нового массива. Насколько я могу судить, это работает нормально, но не подходит для моих нужд:
int w = 8;
int[] before = new int[w*w*w];
int[] after = new int[w*w*w];
for (int i=0; i<w*w*w; i++) {
before[i] = i;
}
int toFill = 0;
int front = 0;
int back = w;
int frontZ = w*w;
int backZ = w*w + w;
do {
for (int i=0; i<w/2; i++) {
for (int j=0; j<w/2; j++) {
after[toFill++] = front++;
after[toFill++] = front++;
after[toFill++] = back++;
after[toFill++] = back++;
after[toFill++] = frontZ++;
after[toFill++] = frontZ++;
after[toFill++] = backZ++;
after[toFill++] = backZ++;
}
front += w;
back += w;
frontZ += w;
backZ += w;
}
front += w*w;
back += w*w;
frontZ += w*w;
backZ += w*w;
} while (toFill < w*w*w);
for (int i=0; i<w*w*w; i++) {
println("after " + i + " " + after[i]);
}