八叉树展平为GPU可用数组时的索引分配问题:父索引无法正确设置的排查
问题分析与修复方案
你的fillShaderVector函数核心问题出在节点索引的记录逻辑和遍历顺序的索引映射上,导致父节点无法正确关联到它的直接子节点,反而错误地关联到了子节点的后代节点。
具体问题拆解
错误记录子节点索引
你当前的代码中,voxel.cIdx[i] = index是将处理子节点的起始索引存入了父节点的子节点索引数组,但这个起始索引指向的是子节点的第一个后代(比如叶子节点),而非子节点自身。因为你的遍历是后序遍历:先递归处理所有子节点的后代,再将子节点本身加入vector,所以子节点自身的索引是递归返回后的index - 1(递归返回的index是处理完子节点及其后代后的下一个可用索引)。错误更新父索引
由于voxel.cIdx里存的是子节点后代的起始索引,后续voxelData[i].pIndex = voxel.index修改的是子节点后代的父索引,而非子节点自身的父索引,这就导致大量中间节点的pIndex始终是默认的-1。子节点遍历的不必要拷贝
for (auto child: children)使用值拷贝遍历子节点,不仅效率低下,还可能引发对象拷贝带来的意外问题。
修复后的代码实现
template<typename T> int Octree<T>::Node::fillShaderVector(std::vector<Voxel> &voxelData, glm::mat4 octTransform, float octSize, int index) const { Voxel voxel; std::vector<int> childIndices; // 临时存储每个直接子节点的索引 if (isInternal()) { // 递归处理所有子节点,记录每个子节点自身的索引 for (const auto &child : children) { // 使用const引用避免拷贝 int prevIndex = index; index = child.fillShaderVector(voxelData, octTransform, octSize, index); // 子节点是后序插入的,所以它的索引是返回index的前一位 int childNodeIdx = index - 1; childIndices.push_back(childNodeIdx); } // 将子节点索引复制到cIdx数组 for (int i = 0; i < childIndices.size(); ++i) { voxel.cIdx[i] = childIndices[i]; } } else { // 叶子节点显式设置所有子节点索引为-1(构造函数已初始化,这里显式更清晰) std::fill(std::begin(voxel.cIdx), std::end(voxel.cIdx), -1); } // 设置当前节点的属性 voxel.pos = glm::vec4(position, 1.0); voxel.pos.w = voxelSize; voxel.col = glm::vec4(1.0); voxel.index = index; voxel.pIndex = -1; // 默认无父节点,后续由父节点修改 voxelData.push_back(voxel); int currentNodeIdx = index; // 当前节点在vector中的索引 index++; // 现在可以正确设置所有直接子节点的父索引 if (isInternal()) { for (int childIdx : childIndices) { voxelData[childIdx].pIndex = currentNodeIdx; } } return index; }
修复逻辑说明
- 记录子节点自身索引:递归处理子节点后,通过
index - 1获取子节点自身在vector中的索引(因为后序遍历中,子节点是最后被插入的),并存储到临时数组childIndices中。 - 正确关联父索引:当前节点被加入vector后,再遍历
childIndices,将每个子节点的pIndex设置为当前节点的索引,确保直接父子关系正确。 - 优化遍历方式:使用
const auto &child遍历子节点,避免不必要的对象拷贝,提升效率。
验证预期
修复后,你会看到:
- 根节点的
pIndex为-1,其余所有节点的pIndex都指向它们的直接父节点。 - 每个内部节点的
cIdx数组存储的是它的8个直接子节点的索引,而非子节点的后代索引。 - 叶子节点的
cIdx全部为-1,符合预期。
内容的提问来源于stack exchange,提问作者0x003
相关产品推荐
相关产品推荐

