public void ReleaseAndMerge(AtlasNodePool pool) { Int16 n = m_Self; do { pool.m_Nodes[n].ReleaseChildren(pool); pool.m_Nodes[n].ClearIsOccupied(); n = pool.m_Nodes[n].m_Parent; }while (n >= 0 && pool.m_Nodes[n].IsMergeNeeded(pool)); }
public void ReleaseChildren(AtlasNodePool pool) { if (IsLeafNode()) { return; } pool.m_Nodes[m_LeftChild].ReleaseChildren(pool); pool.m_Nodes[m_RightChild].ReleaseChildren(pool); pool.AtlasNodeFree(m_LeftChild); pool.AtlasNodeFree(m_RightChild); m_LeftChild = -1; m_RightChild = -1; }
public AtlasAllocatorDynamic(int width, int height, int capacityAllocations) { // In an evenly split binary tree, the nodeCount == leafNodeCount * 2 int capacityNodes = capacityAllocations * 2; Debug.Assert(capacityNodes < (1 << 16), "Error: AtlasAllocatorDynamic: Attempted to allocate a capacity of " + capacityNodes + ", which is greater than our 16-bit indices can support. Please request a capacity <=" + (1 << 16)); m_Pool = new AtlasNodePool((Int16)capacityNodes); m_NodeFromID = new Dictionary <int, Int16>(capacityAllocations); Int16 rootParent = -1; m_Root = m_Pool.AtlasNodeCreate(rootParent); m_Pool.m_Nodes[m_Root].m_Rect.Set(width, height, 0, 0); m_Width = width; m_Height = height; // string debug = ""; // DebugStringFromNode(ref debug, m_Root); // Debug.Log("Allocating atlas = " + debug); }
public bool IsMergeNeeded(AtlasNodePool pool) { return(pool.m_Nodes[m_LeftChild].IsLeafNode() && (!pool.m_Nodes[m_LeftChild].IsOccupied()) && pool.m_Nodes[m_RightChild].IsLeafNode() && (!pool.m_Nodes[m_RightChild].IsOccupied())); }
public Int16 Allocate(AtlasNodePool pool, int width, int height) { if (Mathf.Min(width, height) < 1) { // Degenerate allocation requested. Debug.Assert(false, "Error: Texture2DAtlasDynamic: Attempted to allocate a degenerate region. Please ensure width and height are >= 1"); return(-1); } // not a leaf node, try children // TODO: Rather than always going left, then right, we might want to always attempt to allocate in the smaller child, then larger. if (!IsLeafNode()) { Int16 node = pool.m_Nodes[m_LeftChild].Allocate(pool, width, height); if (node == -1) { node = pool.m_Nodes[m_RightChild].Allocate(pool, width, height); } return(node); } // leaf node, check for fit if (IsOccupied()) { return(-1); } if (width > m_Rect.x || height > m_Rect.y) { return(-1); } // perform the split Debug.Assert(m_LeftChild == -1); Debug.Assert(m_RightChild == -1); m_LeftChild = pool.AtlasNodeCreate(m_Self); m_RightChild = pool.AtlasNodeCreate(m_Self); // Debug.Log("m_LeftChild = " + m_LeftChild); // Debug.Log("m_RightChild = " + m_RightChild); Debug.Assert(m_LeftChild >= 0 && m_LeftChild < pool.m_Nodes.Length); Debug.Assert(m_RightChild >= 0 && m_RightChild < pool.m_Nodes.Length); // Debug.Log("Rect = {" + m_Rect.x + ", " + m_Rect.y + ", " + m_Rect.z + ", " + m_Rect.w + "}"); float deltaX = m_Rect.x - width; float deltaY = m_Rect.y - height; // Debug.Log("deltaX = " + deltaX); // Debug.Log("deltaY = " + deltaY); if (deltaX >= deltaY) { // Debug.Log("Split horizontally"); // +--------+------+ // | | | // | | | // | | | // | | | // +--------+------+ pool.m_Nodes[m_LeftChild].m_Rect.x = width; pool.m_Nodes[m_LeftChild].m_Rect.y = m_Rect.y; pool.m_Nodes[m_LeftChild].m_Rect.z = m_Rect.z; pool.m_Nodes[m_LeftChild].m_Rect.w = m_Rect.w; pool.m_Nodes[m_RightChild].m_Rect.x = deltaX; pool.m_Nodes[m_RightChild].m_Rect.y = m_Rect.y; pool.m_Nodes[m_RightChild].m_Rect.z = m_Rect.z + width; pool.m_Nodes[m_RightChild].m_Rect.w = m_Rect.w; if (deltaY < 1) { pool.m_Nodes[m_LeftChild].SetIsOccupied(); return(m_LeftChild); } else { Int16 node = pool.m_Nodes[m_LeftChild].Allocate(pool, width, height); if (node >= 0) { pool.m_Nodes[node].SetIsOccupied(); } return(node); } } else { // Debug.Log("Split vertically."); // +---------------+ // | | // |---------------| // | | // | | // +---------------+ pool.m_Nodes[m_LeftChild].m_Rect.x = m_Rect.x; pool.m_Nodes[m_LeftChild].m_Rect.y = height; pool.m_Nodes[m_LeftChild].m_Rect.z = m_Rect.z; pool.m_Nodes[m_LeftChild].m_Rect.w = m_Rect.w; pool.m_Nodes[m_RightChild].m_Rect.x = m_Rect.x; pool.m_Nodes[m_RightChild].m_Rect.y = deltaY; pool.m_Nodes[m_RightChild].m_Rect.z = m_Rect.z; pool.m_Nodes[m_RightChild].m_Rect.w = m_Rect.w + height; if (deltaX < 1) { pool.m_Nodes[m_LeftChild].SetIsOccupied(); return(m_LeftChild); } else { Int16 node = pool.m_Nodes[m_LeftChild].Allocate(pool, width, height); if (node >= 0) { pool.m_Nodes[node].SetIsOccupied(); } return(node); } } }