Esempio n. 1
0
            public QuadTreeWalker(Terrain *terrain, Aabb aabb)
            {
                m_Terrain    = terrain;
                m_LevelIndex = 0;
                m_Index      = 0;
                m_ChildIndex = 0;
                Bounds       = new FourTransposedAabbs();

                // Initialize the stack with a single node
                fixed(int *stack = m_Stack)
                {
                    m_Top = stack;

                    // Clamp the query AABB to the terrain bounds
                    int2 min = math.clamp((int2)aabb.Min.xz, 0, terrain->Size - 2); // Size - 1 is number of quads, Size - 2 is the highest valid quad index
                    int2 max = math.clamp((int2)aabb.Max.xz, 0, terrain->Size - 2);

                    // Find the deepest node that fully contains the query AABB, by finding the highest bit in which the AABB min and max differ
                    // We can begin the query from that node instead of the root, and this is much faster than traversing the tree.
                    int  level = 0;
                    int2 diffs = min ^ max;
                    int  diff  = diffs.x | diffs.y;
                    int  bit   = 1 << (terrain->Levels.Length - 1);

                    while ((diff & bit) == 0 && bit > 1)
                    {
                        level++;
                        bit = bit >> 1;
                    }
                    int2 coord = min >> (terrain->Levels.Length - level);

                    // Push the node onto the stack
                    *m_Top = level;
                    *(m_Top + k_StackSize) = coord.x;
                    *(m_Top + k_StackSize + k_StackSize) = coord.y;
                    m_Top++;
                }
            }
Esempio n. 2
0
            // If the stack is not empty, removes the top node and sets the current state from it, then returns true.
            // Otherwise returns false.
            public bool Pop()
            {
                fixed(int *stack = m_Stack)
                {
                    if (m_Top == stack)
                    {
                        return(false); // stack is empty
                    }
                }

                m_Top--;
                m_LevelIndex = *m_Top;
                m_Index      = new int2(*(m_Top + k_StackSize), *(m_Top + k_StackSize + k_StackSize));

                // Get the node
                Level level       = m_Terrain->Levels[m_LevelIndex];
                int   levelOffset = (m_Index.y & ~1) * level.Pitch + ((m_Index.y & 1) << 1) + ((m_Index.x & ~1) << 1) + (m_Index.x & 1); // swizzled, see comment on Nodes
                Node  node        = m_Terrain->Nodes[level.Base + levelOffset];

                // Calculate the AABBs of the node's children
                m_ChildIndex = m_Index + m_Index;
                float3 boundsX = (float3)(m_ChildIndex.x + new int3(0, 1, 2)) * level.Scale;
                float3 boundsZ = (float3)(m_ChildIndex.y + new int3(0, 1, 2)) * level.Scale;

                Bounds = new FourTransposedAabbs
                {
                    Lx = boundsX.xyxy,
                    Hx = boundsX.yzyz,
                    Lz = boundsZ.xxyy,
                    Hz = boundsZ.yyzz,
                    Ly = node.Min4,
                    Hy = node.Max4
                };

                return(true);
            }