【发布时间】:2020-05-22 20:49:44
【问题描述】:
对于基于八叉树的稀疏体素八叉树渲染器,我希望能够旋转和镜像八叉树的各个节点。虽然它不是真正的八叉树,但由于节点被共享并被允许将自己包含为子树。否则我可以简单地将转换应用于八叉树本身。
不失一般性,假设立方体是一个单位立方体,一个角在原点,即 (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 的调用频率大约是 combine 的 4 倍。该算法是递归的,因此如果转换编码使用多个 32 位整数,则将其放入堆栈会产生额外的运行时成本。
到目前为止,我已经发现问题可以分解为位翻转,这可以通过单个异或操作和位排列(我还不知道如何有效地完成)来完成。不过,同时执行这两种操作的操作可能会更有效。
我打算在已经使用 SSE4.1 内在函数的 C++ 代码中使用它。尽管首选不使用内在函数或仅需要 SSE3 的解决方案。最后,速度是最重要的。我会尝试使用http://quick-bench.com/ 来比较解决方案。
(注意:我使用了仿射变换标签,因为没有正交变换标签,我不想创建它)。
【问题讨论】:
-
你可以只连接 8 个新角并得到一个 24 位整数。
-
然后我可以用一个简单的位移+掩码实现变换,这真的很快。虽然我将如何实现组合功能?
-
如果你有两个转换
a和b这样a_i是i-th 的图像(i只是由二进制表示表示的自然数角)角,你可以通过设置c_i = b_{|a_i|}来计算它们的组合c,其中|a_i|是二进制字符串a_i表示的自然数。 -
有一个很好的 6 位编码:首先将对称性分解为它在坐标平面 (x,y,z) 上的作用(六种可能性)加上它发送角的位置 (1,1, 1)。根据移位的索引是否以正确的循环顺序出现,将 (x,y,z) 的排列分解为符号位,然后用两位来描述 x 的去向。 (类似的技巧非常适合正方形的对称性......我不确定如何有效地处理三个元素的排列 - 也许只是使用表格查找?)
标签: c++ sse affinetransform isomorphism