/// <summary> /// Virtually expands the atlas from its initial size to its maximum size. /// </summary> /// <remarks> /// The areas are built by doubling horizontally and vertically, over and over. Consider the following example, /// where the initial atlas size is 64x64 and the maximum size is 256x256. The resulting 5 areas would be: /// 1: First area determined by the initial atlas size /// 2: Area generated by horizontal expansion /// 3: Area generated by vertical expansion /// 4: Area generated by horizontal expansion /// 5: Area generated by vertical expansion - final expansion /// _______________________ /// | | /// | | /// | 5 | /// | | /// | | /// |_______________________| /// | | | /// | 3 | | /// |___________| 4 | /// | | | | /// | 1 | 2 | | /// |_____|_____|___________| /// /// Because of the exponential nature of this process, we don't need to worry about very large textures. For /// example, from 64x64 to 4096x4096, only 12 iterations are required, leading to 13 areas. /// </remarks> private void BuildAreas() { AreaNode current = m_FirstUnpartitionedArea; while (virtualWidth < maxAtlasSize || virtualHeight < maxAtlasSize) { RectInt newArea; if (virtualWidth > virtualHeight) { // Double Vertically. newArea = new RectInt(0, virtualHeight, virtualWidth, virtualHeight); virtualHeight *= 2; } else { // Double Horizontally. newArea = new RectInt(virtualWidth, 0, virtualWidth, virtualHeight); virtualWidth *= 2; } var newAreaNode = AreaNode.Acquire(newArea); newAreaNode.AddAfter(current); current = newAreaNode; } }
/// <param name="initialAtlasSize">Initial size of the atlas (POT).</param> /// <param name="maxAtlasSize">Maximum size of the atlas (POT).</param> public UIRAtlasAllocator(int initialAtlasSize, int maxAtlasSize, int sidePadding = 1) { // Validate Size Coherence. Assert.IsTrue(initialAtlasSize > 0 && initialAtlasSize <= maxAtlasSize); // Validate POT Assert.IsTrue(initialAtlasSize == Mathf.NextPowerOfTwo(initialAtlasSize)); Assert.IsTrue(maxAtlasSize == Mathf.NextPowerOfTwo(maxAtlasSize)); m_1SidePadding = sidePadding; m_2SidePadding = sidePadding << 1; this.maxAtlasSize = maxAtlasSize; maxImageWidth = maxAtlasSize; maxImageHeight = (initialAtlasSize == maxAtlasSize) ? maxAtlasSize / 2 + m_2SidePadding : maxAtlasSize / 4 + m_2SidePadding; virtualWidth = initialAtlasSize; virtualHeight = initialAtlasSize; int maxOpenRows = GetLog2OfNextPower(maxAtlasSize) + 1; m_OpenRows = new Row[maxOpenRows]; var area = new RectInt(0, 0, initialAtlasSize, initialAtlasSize); m_FirstUnpartitionedArea = AreaNode.Acquire(area); BuildAreas(); }