public void ReleaseAndMerge(Atlas3DNodePool 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(Atlas3DNodePool pool) { if (IsLeafNode()) { return; } pool.m_Nodes[m_LeftChild].ReleaseChildren(pool); pool.m_Nodes[m_RightChild].ReleaseChildren(pool); pool.Atlas3DNodeFree(m_LeftChild); pool.Atlas3DNodeFree(m_RightChild); m_LeftChild = -1; m_RightChild = -1; }
public Atlas3DAllocatorDynamic(int width, int height, int depth, int capacityAllocations) { // In an evenly split binary tree, the nodeCount == leafNodeCount * 2 int capacityNodes = capacityAllocations * 2; Debug.Assert(capacityNodes < (1 << 16), "Error: Atlas3DAllocatorDynamic: 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 Atlas3DNodePool((Int16)capacityNodes); m_NodeFromID = new Dictionary <int, Int16>(capacityAllocations); Int16 rootParent = -1; m_Root = m_Pool.Atlas3DNodeCreate(rootParent); m_Pool.m_Nodes[m_Root].m_RectSize = new Vector3(width, height, depth); m_Pool.m_Nodes[m_Root].m_RectOffset = Vector3.zero; m_Width = width; m_Height = height; m_Depth = depth; // string debug = ""; // DebugStringFromNode(ref debug, m_Root); // Debug.Log("Allocating atlas = " + debug); }
public bool IsMergeNeeded(Atlas3DNodePool 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(Atlas3DNodePool pool, int width, int height, int depth) { if (Mathf.Min(Mathf.Min(width, height), depth) < 1) { // Degenerate allocation requested. Debug.Assert(false, "Error: Texture3DAtlasDynamic: 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, depth); if (node == -1) { node = pool.m_Nodes[m_RightChild].Allocate(pool, width, height, depth); } return(node); } // leaf node, check for fit if (IsOccupied()) { return(-1); } if (width > m_RectSize.x || height > m_RectSize.y || depth > m_RectSize.z) { return(-1); } // perform the split Debug.Assert(m_LeftChild == -1); Debug.Assert(m_RightChild == -1); m_LeftChild = pool.Atlas3DNodeCreate(m_Self); m_RightChild = pool.Atlas3DNodeCreate(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_RectSize.x + ", " + m_RectSize.y + ", " + m_RectSize.z + ", " + m_RectOffset.x + ", " + m_RectOffset.y + "," + m_RectOffset.z + "}"); float deltaX = m_RectSize.x - width; float deltaY = m_RectSize.y - height; float deltaZ = m_RectSize.z - depth; // Debug.Log("deltaX = " + deltaX); // Debug.Log("deltaY = " + deltaY); // Debug.Log("deltaZ = " + deltaZ); if (deltaX >= deltaY && deltaX >= deltaZ) { // Debug.Log("Split X"); // // +--------+------+ // / / /| // / / / | // +--------+------+ | // | | | | // | | | + // | | | / // | | |/ // +--------+------+ // pool.m_Nodes[m_LeftChild].m_RectSize = new Vector3(width, m_RectSize.y, m_RectSize.z); pool.m_Nodes[m_LeftChild].m_RectOffset = m_RectOffset; pool.m_Nodes[m_RightChild].m_RectSize = new Vector3(deltaX, m_RectSize.y, m_RectSize.z); pool.m_Nodes[m_RightChild].m_RectOffset = new Vector3(m_RectOffset.x + width, m_RectOffset.y, m_RectOffset.z); if (Mathf.Max(deltaY, deltaZ) < 1) { pool.m_Nodes[m_LeftChild].SetIsOccupied(); return(m_LeftChild); } else { Int16 node = pool.m_Nodes[m_LeftChild].Allocate(pool, width, height, depth); if (node >= 0) { pool.m_Nodes[node].SetIsOccupied(); } return(node); } } else if (deltaY >= deltaX && deltaY >= deltaZ) { // Debug.Log("Split Y."); // // +---------------+ // / /| // / / + // +---------------+ /| // | |/ | // +---------------+ + // | | / // | |/ // +---------------+ // pool.m_Nodes[m_LeftChild].m_RectSize = new Vector3(m_RectSize.x, height, m_RectSize.z); pool.m_Nodes[m_LeftChild].m_RectOffset = m_RectOffset; pool.m_Nodes[m_RightChild].m_RectSize = new Vector3(m_RectSize.x, deltaY, m_RectSize.z); pool.m_Nodes[m_RightChild].m_RectOffset = new Vector3(m_RectOffset.x, m_RectOffset.y + height, m_RectOffset.z); if (Math.Max(deltaX, deltaZ) < 1) { pool.m_Nodes[m_LeftChild].SetIsOccupied(); return(m_LeftChild); } else { Int16 node = pool.m_Nodes[m_LeftChild].Allocate(pool, width, height, depth); if (node >= 0) { pool.m_Nodes[node].SetIsOccupied(); } return(node); } } else // deltaZ >= deltaX && deltaZ >= deltaY { // Debug.Log("Split Z."); // // +---------------+ // +---------------+| // / /|| // +---------------+ || // | | || // | | |+ // | | + // | |/ // +---------------+ // pool.m_Nodes[m_LeftChild].m_RectSize = new Vector3(m_RectSize.x, m_RectSize.y, depth); pool.m_Nodes[m_LeftChild].m_RectOffset = m_RectOffset; pool.m_Nodes[m_RightChild].m_RectSize = new Vector3(m_RectSize.x, m_RectSize.y, deltaZ); pool.m_Nodes[m_RightChild].m_RectOffset = new Vector3(m_RectOffset.x, m_RectOffset.y, m_RectOffset.z + depth); if (Math.Max(deltaX, deltaY) < 1) { pool.m_Nodes[m_LeftChild].SetIsOccupied(); return(m_LeftChild); } else { Int16 node = pool.m_Nodes[m_LeftChild].Allocate(pool, width, height, depth); if (node >= 0) { pool.m_Nodes[node].SetIsOccupied(); } return(node); } } }