Kd 算法从创建一个 BSP 根节点开始,通过对一组基元(三角形、球体等)进行分区,以便创建两个新数组(左基元和右基元),用于创建其两个子树。
通过将给定的图元数组划分为两个数组来计算左右图元。通过取每个三角形的区间(投影到给定轴(x、y 或 z)上)的中点的中值来计算分割平面位置。
例如,具有 x 坐标:1、2、3 的三角形具有中点 1=(3-1)/2(沿 x 轴)具有 x 坐标:2、3、8 的三角形具有中点 3= (8-2)/2 (沿 x 轴) x 坐标为 4, 3, 8 的三角形有一个中点 2.5=(8-3)/2 (沿 x 轴) 包含这些的原始数组三个三角形由一个平面划分,通过 x=2.5(中值)平行于 yz 平面。生成的左图元数组包含三个三角形,生成的右图元数组包含三个三角形。
具有左右基元的两个结果数组用于构造 Kd 节点的左右子树(基元仅存储在叶节点处)。
对于左子树:
If (the left primitives are empty) then the left subtree points to NULL
else if (the number of left primitives is smaller than the minimal number || the depth == 1) then the left subtree is a leaf node
else the left subtree is another tree.
create the left subtree with the left primitives along the axis (++axis % 3) with --depth as depth and the same minimal number.
类似于右子树。
实现的算法有效,但速度很慢,因为树的分区不是很好。当对 5500 个三角形的兔子进行光线追踪时,1 个三角形的叶节点很多,而最后一个叶节点仍然包含 762 个三角形。
是否有更好的分区算法(因为我的只是将单点转换为曲面的 Kd 树的实现)来平衡树?
更新:我搜索了一种算法或启发式方法,可以根据切割点将区间数组 [t0,t1] 划分为两个区间数组。左侧数组包含切割点左侧的间隔和包含切割点的间隔。类似于正确的阵列。两个数组必须具有大致相同的间隔数,并且重复间隔的数量必须尽可能少。该算法的复杂度可能不是 O(n^2)。