Для разреженного воксельного рендерера октри, основанного на октреях, я хочу иметь возможность вращать и зеркально отображать отдельные узлы октодерева. Хотя на самом деле это не октри, из-за того, что узлы используются совместно и им разрешено содержать себя как поддерево. В противном случае я мог бы просто применить преобразование к самому октревому дереву.
Без ограничения общности предположим, что куб является единичным кубом с одним углом в начале координат, т. Е. (0,0,0), и противоположным углом. в (1,1,1). Я закодировал углы куба как 3-битное целое число. Таким образом, 0 (= 0b000) представляет угол в начале координат, 1 (= 0b001) представляет угол в (0,0,1) и 7 (= 0b111) представляет угол в (1,1,1). Единственные разрешенные повороты и отражения находятся вокруг центра куба (½, ½, ½) и такие, что углы заканчиваются в целочисленных координатах. Это означает, что есть только 48 различных возможных преобразований. (Первый угол может быть отображен на 8 возможных позиций, следующий угол на 3, третий на 2, и это фиксирует положение остальных углов.)
Я еще не решил, как кодировать преобразование, хотя должна быть возможность закодировать его как одно 32-разрядное целое число (или даже 6-разрядное целое число, поскольку существует только 48 возможных преобразований). Затем преобразование можно применить как функцию, которая отображает каждый угол куба на его местоположение после преобразования. Т.е.
int transform(int corner, int transformation) {
// magic happens here
return result;
}
Кроме того, у меня также должна быть функция combine
, которая объединяет преобразования, так что transform(corner, combine(a,b))
равно transform(transform(corner, b), a)
.
Поскольку эти функции будут вызываться около миллиарда раз во-вторых, они должны быть быстрыми. Хотя transform будет вызываться примерно в 4 раза чаще, чем комбинат. Алгоритм является рекурсивным, поэтому, если кодировка преобразования использует более одного 32-разрядного целого числа, это потребует дополнительных затрат времени выполнения для помещения его в стек.
До сих пор я выяснил, что проблема может быть разложенным на переворачивание битов, которое может быть сделано с одной операцией xor, и перестановкой битов (которую я пока не знаю, как сделать эффективно). Тем не менее, операция, которая выполняет оба одновременно, может быть более эффективной.
Я намерен использовать это в коде C ++, который уже использует встроенные функции SSE4.1. Хотя решение, которое не использует встроенные функции или требует только SSE3, является предпочтительным. И, в конце концов, скорость важнее всего. Я попытаюсь использовать http://quick-bench.com/ для сравнения решений.
(Примечание. Я использовал тег affinetransform, поскольку тег orthogonaltransform отсутствует, и я не хотел его создавать).