将八叉树转换为数组时如何正确分配索引?

How to properly assign indexes when transforming octree into array?

我正在尝试将一个八叉树展平成一个数组,以便我可以将它传递给 GPU。我想从我的八叉树中获取数据,将其加载到 Voxel 结构的向量中,然后将其发送到 GPU。我在开始时将 2 个体素插入到八叉树中。这些是我的插入函数:

template<typename T>
Octree<T>::Octree(glm::vec3 position, float octreeSize, int depth) : root(position, 1.0f), depth(depth), octreeSize(octreeSize), transform(1.0f)
{
    insert(glm::vec3(0.5, 0.1, 0.7f), true);
    insert(glm::vec3(-0.5, -0.1, -0.7f), true);
    transform = glm::translate(transform, glm::vec3(0, 0, 5));
}

template<typename T>
void Octree<T>::insert(glm::vec3 pos, T data)
{
    root.subdivide(pos, data, depth, 1.0f);
}

template<typename T>
int Octree<T>::Node::getIndexOfPosition(glm::vec3 lookupPosition, glm::vec3 nodePosition) const
{
    int index = 0;
    index |= lookupPosition.y > nodePosition.y ? 4 : 0;
    index |= lookupPosition.x > nodePosition.x ? 2 : 0;
    index |= lookupPosition.z > nodePosition.z ? 1 : 0;

    return index;
}


template<typename T>
void Octree<T>::Node:: subdivide(glm::vec3 targetPos, T value, int divDepth, float parentSize)
{
    int subdivIndex = getIndexOfPosition(targetPos, position);
    if(children.empty())
    {
        for(int i = 0; i < 8; i++)
        {
            glm::vec3 newPos = position;
            float sizeModifier = parentSize * 0.5f;
            if ((i & 4) == 4)
                newPos.y += sizeModifier;
            else
                newPos.y -= sizeModifier;

            if ((i & 2) == 2)
                newPos.x += sizeModifier;
            else
                newPos.x -= sizeModifier;

            if ((i & 1) == 1)
                newPos.z += sizeModifier;
            else
                newPos.z -= sizeModifier;
            Node newNode(newPos, sizeModifier);
            children.push_back(newNode);
        }
    }

    if (divDepth > 0)
    {
        //std::cout << "Subdividing" << std::endl;
        children[subdivIndex].subdivide(targetPos, value, divDepth - 1, parentSize*0.5f);
    }
    else
    {
        children[subdivIndex].data = value;
    }
}

我的体素结构:

struct Voxel
{
    Voxel(): pIndex(-1), index(-1), pos(90000.f), col(0.f) { for (int & i : cIdx) i = -1; }
    int cIdx[8]; // The indexes of the child nodes in the vector
    int index;   // The current index of this voxel within the vector
    int pIndex;
    glm::vec4 pos;
    glm::vec4 col;
};

目前我正在按预定顺序遍历我的八叉树,我递归地遍历每个子节点(如果有的话),将当前体素子索引设置为当前索引,然后对所有子节点执行相同操作.最后,一旦我们位于树的底部或者我们没有子节点,将该节点推送到 GPU 并将子节点的父索引设置为当前索引。这是我的功能:

template<typename T>
int
Octree<T>::Node::fillShaderVector(std::vector<Voxel> &voxelData, glm::mat4 octTransform, float octSize, int index) const
{
    Voxel voxel;
    if (isInternal())
    {
        int i = 0;
        for (auto child: children)
        {
            // I think this is where we have issues
            voxel.cIdx[i] = index;
            index = child.fillShaderVector(voxelData, octTransform, octSize, index);
            i++;
        }
    }

    voxel.pos = glm::vec4(position, 1.0);
    // Store size as the 4th element in the vector
    voxel.pos.w = voxelSize;
    voxel.col = glm::vec4(1.0);
    voxel.index = index;

    voxelData.push_back(voxel);
    index++;

    if (isInternal())
    {
        for(int i : voxel.cIdx)
            voxelData[i].pIndex = voxel.index;
    }

    return index;
}

template<typename T>
bool Octree<T>::Node::isInternal() const
{
    return !children.empty();
}

这正确地遍历了节点,我能够为每个体素获得正确的索引,但是我似乎无法正确设置父索引。

示例输出(为了简洁起见,我删掉了很多,它从 0..56 开始 Parent: -1 意味着没有父节点,即应该只是根节点,而 child: -1 , 表示它是叶节点):

Index: 0
Parent: 56
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 1
Parent: 24
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 2
Parent: 24
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 3
Parent: 24
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 4
Parent: 24
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 5
Parent: 20
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 6
Parent: 20
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 7
Parent: 20
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 8
Parent: 20
Children: -1 -1 -1 -1 -1 -1 -1 -1
...
Index: 16
Parent: 19
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 17
Parent: 19
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 18
Parent: 19
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 19
Parent: -1
Children: 11 12 13 14 15 16 17 18
Index: 20
Parent: -1
Children: 4 5 6 7 8 9 10 11
...
Index: 47
Parent: 48
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 48
Parent: -1
Children: 32 33 34 43 44 45 46 47
Index: 49
Parent: 55
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 50
Parent: 55
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 51
Parent: 55
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 52
Parent: 55
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 53
Parent: 55
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 54
Parent: 55
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 55
Parent: -1
Children: 31 32 49 50 51 52 53 54
Index: 56
Parent: -1
Children: 0 25 26 27 28 29 30 31

我的 fillShaderVector 函数有什么问题导致我无法准确填写父索引?

我解决了这个问题,在预订时我将体素推到矢量上,然后我使用它的索引直接修改矢量并成功更新父数据和子数据。

新插入代码

template<typename T>
int
Octree<T>::Node::fillShaderVector(std::vector<Voxel> &voxelData, glm::mat4 octTransform, float octSize, int index) const
{
    Voxel voxel;

    voxel.pos = glm::vec4(position, 1.0);
    // Store size as the 4th element in the vector
    voxel.pos.w = voxelSize;
    voxel.col = glm::vec4(1.0);
    voxel.index = index;

    voxelData.push_back(voxel);
    index++;
    if (isInternal())
    {
        int i = 0;
        for (auto child: children)
        {
            voxelData[voxel.index].cIdx[i] = index;
            index = child.fillShaderVector(voxelData, octTransform, octSize, index);
            i++;
        }
    }
    if (isInternal())
    {
        for(auto c: voxelData[voxel.index].cIdx)
            if(c != -1) voxelData[c].pIndex = voxel.index;
    }

    return index;
}

这导致正确的索引和层次结构

Index: 0
Parent: -1
Children: 1 26 27 28 29 30 31 32
Index: 1
Parent: 0
Children: 2 3 4 5 6 23 24 25
Index: 2
Parent: 1
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 3
Parent: 1
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 4
Parent: 1
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 5
Parent: 1
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 6
Parent: 1
Children: 7 8 9 10 11 12 13 14
Index: 7
Parent: 6
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 8
Parent: 6
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 9
Parent: 6
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 10
Parent: 6
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 11
Parent: 6
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 12
Parent: 6
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 13
Parent: 6
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 14
Parent: 6
Children: 15 16 17 18 19 20 21 22
Index: 15
Parent: 14
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 16
Parent: 14
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 17
Parent: 14
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 18
Parent: 14
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 19
Parent: 14
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 20
Parent: 14
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 21
Parent: 14
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 22
Parent: 14
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 23
Parent: 1
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 24
Parent: 1
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 25
Parent: 1
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 26
Parent: 0
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 27
Parent: 0
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 28
Parent: 0
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 29
Parent: 0
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 30
Parent: 0
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 31
Parent: 0
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 32
Parent: 0
Children: 33 34 51 52 53 54 55 56
Index: 33
Parent: 32
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 34
Parent: 32
Children: 35 36 37 46 47 48 49 50
Index: 35
Parent: 34
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 36
Parent: 34
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 37
Parent: 34
Children: 38 39 40 41 42 43 44 45
Index: 38
Parent: 37
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 39
Parent: 37
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 40
Parent: 37
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 41
Parent: 37
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 42
Parent: 37
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 43
Parent: 37
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 44
Parent: 37
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 45
Parent: 37
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 46
Parent: 34
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 47
Parent: 34
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 48
Parent: 34
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 49
Parent: 34
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 50
Parent: 34
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 51
Parent: 32
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 52
Parent: 32
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 53
Parent: 32
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 54
Parent: 32
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 55
Parent: 32
Children: -1 -1 -1 -1 -1 -1 -1 -1
Index: 56
Parent: 32
Children: -1 -1 -1 -1 -1 -1 -1 -1