void PackBins() { MaxRects maxRects = new MaxRects((int)_container.width, (int)_container.height, false); _bins = new List <Rect> (); if (_tryToFillContainer) { List <Rect> inputs = new List <Rect> (_items); while (inputs.Count > 0) { Rect input = inputs [UnityEngine.Random.Range(0, inputs.Count)]; Rect output = maxRects.Insert((int)input.width, (int)input.height, MaxRects.FreeRectChoiceHeuristic.RectContactPointRule); if (IsDegenerate(output)) { inputs.Remove(input); } else { _bins.Add(new Rect(output.x + _container.x, output.y + _container.y, output.width, output.height)); } } } else { foreach (Rect input in _items) { Rect output = maxRects.Insert((int)input.width, (int)input.height, MaxRects.FreeRectChoiceHeuristic.RectContactPointRule); _bins.Add(new Rect(output.x + _container.x, output.y + _container.y, output.width, output.height)); } } }
public static Dictionary <Texture2D, Rect> PackTextures(HashSet <Texture2D> textures, out int size, int minAtlasSize, int maxAtlasSize) { MaxRects maxRects; size = minAtlasSize; Dictionary <Texture2D, Rect> atlasRectsPerTexture = new Dictionary <Texture2D, Rect> (); while (true) { maxRects = new MaxRects(size, size, false); bool fit = true; atlasRectsPerTexture.Clear(); foreach (Texture2D texture in textures) { Rect atlasRect = maxRects.Insert(texture.width, texture.height, MaxRects.FreeRectChoiceHeuristic.RectBestAreaFit); if (atlasRect.width == 0 || atlasRect.height == 0) { size *= 2; if (size > maxAtlasSize) { throw new Exception("texture atlas bigger than " + maxAtlasSize + "x" + maxAtlasSize); } fit = false; break; } atlasRectsPerTexture.Add(texture, atlasRect); } if (fit) { break; } } return(atlasRectsPerTexture); }
public static Dictionary <string, Rect> RepackRects(Dictionary <string, Rect> atlasRects1, out int size, int minAtlasSize, int maxAtlasSize) { MaxRects maxRects; size = minAtlasSize; Dictionary <string, Rect> atlasRects2 = new Dictionary <string, Rect> (); while (true) { maxRects = new MaxRects(size, size, false); bool fit = true; atlasRects2.Clear(); foreach (KeyValuePair <string, Rect> atlasRect1 in atlasRects1) { Rect atlasRect2 = maxRects.Insert((int)atlasRect1.Value.width, (int)atlasRect1.Value.height, MaxRects.FreeRectChoiceHeuristic.RectBestAreaFit); if (atlasRect2.width == 0 || atlasRect2.height == 0) { size *= 2; if (size > maxAtlasSize) { throw new Exception("texture atlas bigger than " + maxAtlasSize + "x" + maxAtlasSize); } fit = false; break; } atlasRects2.Add(atlasRect1.Key, atlasRect2); } if (fit) { break; } } return(atlasRects2); }
public override void Execute(BaseGrid grid, ArchitectureStyle[] allArchitectureStyles, int[] architectureStylesMap, List <Block> blocks) { _allotments = new List <Allotment> (); foreach (Block block in blocks) { List <Rect> allPossibleAreas = new List <Rect> (); foreach (ArchitectureStyle possibleArchitectureStyle in block.architectureStyles) { int tileWidth = possibleArchitectureStyle.tileWidth; Rect[] possibleAreas = Combinatorics.PossibleAreas(possibleArchitectureStyle.minWidth + possibleArchitectureStyle.spacing, possibleArchitectureStyle.maxWidth + possibleArchitectureStyle.spacing, possibleArchitectureStyle.minDepth + possibleArchitectureStyle.spacing, possibleArchitectureStyle.maxDepth + possibleArchitectureStyle.spacing); foreach (Rect possibleArea in possibleAreas) { Rect area = new Rect(0, 0, possibleArea.width * tileWidth, possibleArea.height * tileWidth); if (!allPossibleAreas.Contains(area)) { allPossibleAreas.Add(area); } } } List <Rect> allotmentAreas = new List <Rect> (); MaxRects maxRects = new MaxRects(block.width, block.depth); if (_tryToFitSmallerAllotmentsFirst) { // sort possible allotment areas by rectangle area allPossibleAreas.Sort(delegate(Rect r1, Rect r2) { float a1 = (r1.width * r1.height); float a2 = (r2.width * r2.height); return(a1.CompareTo(a2)); }); } while (allPossibleAreas.Count > 0) { Rect possibleArea; if (_tryToFitSmallerAllotmentsFirst) { possibleArea = allPossibleAreas [0]; } else { possibleArea = allPossibleAreas [UnityEngine.Random.Range(0, allPossibleAreas.Count)]; } Rect allotmentArea = maxRects.Insert((int)possibleArea.width, (int)possibleArea.height, _allotmentFittingHeuristics); if (allotmentArea.width == 0 || allotmentArea.height == 0) { allPossibleAreas.Remove(possibleArea); continue; } allotmentAreas.Add(new Rect(allotmentArea.x, allotmentArea.y, allotmentArea.width, allotmentArea.height)); } if (maxRects.Occupancy() < _minOccupancyRate) { string message = "block occupancy is less than minimum: " + maxRects.Occupancy(); if (_abortInError) { throw new Exception(message); } else { Debug.LogWarning(message); } } int blockXStart = (int)block.center.x - block.width / 2; int blockZStart = (int)block.center.y - block.depth / 2; foreach (Rect allotmentArea in allotmentAreas) { ArchitectureStyle architectureStyle = FindSuitableArchitectureStyle(allotmentArea, block.architectureStyles); bool hasLeftNeighbour = false; bool hasRightNeighbour = false; bool hasUpperNeighbour = false; bool hasLowerNeighbour = false; foreach (Rect neighbourAllotmentArea in allotmentAreas) { if (neighbourAllotmentArea == allotmentArea) { continue; } if (neighbourAllotmentArea.xMax <= allotmentArea.xMin && ((neighbourAllotmentArea.yMin >= allotmentArea.yMin && neighbourAllotmentArea.yMin <= allotmentArea.yMax) || (neighbourAllotmentArea.yMax >= allotmentArea.yMin && neighbourAllotmentArea.yMax <= allotmentArea.yMax) || (allotmentArea.yMin >= neighbourAllotmentArea.yMin && allotmentArea.yMin <= neighbourAllotmentArea.yMax) || (allotmentArea.yMax >= neighbourAllotmentArea.yMin && allotmentArea.yMax <= neighbourAllotmentArea.yMax))) { hasLeftNeighbour = true; } else if (neighbourAllotmentArea.xMin >= allotmentArea.xMax && ((neighbourAllotmentArea.yMin >= allotmentArea.yMin && neighbourAllotmentArea.yMin <= allotmentArea.yMax) || (neighbourAllotmentArea.yMax >= allotmentArea.yMin && neighbourAllotmentArea.yMax <= allotmentArea.yMax) || (allotmentArea.yMin >= neighbourAllotmentArea.yMin && allotmentArea.yMin <= neighbourAllotmentArea.yMax) || (allotmentArea.yMax >= neighbourAllotmentArea.yMin && allotmentArea.yMax <= neighbourAllotmentArea.yMax))) { hasRightNeighbour = true; } else if (neighbourAllotmentArea.yMin >= allotmentArea.yMax && ((neighbourAllotmentArea.xMin >= allotmentArea.xMin && neighbourAllotmentArea.xMin <= allotmentArea.xMax) || (neighbourAllotmentArea.xMax >= allotmentArea.xMin && neighbourAllotmentArea.xMax <= allotmentArea.xMax) || (allotmentArea.xMin >= neighbourAllotmentArea.xMin && allotmentArea.xMin <= neighbourAllotmentArea.xMax) || (allotmentArea.xMax >= neighbourAllotmentArea.xMin && allotmentArea.xMax <= neighbourAllotmentArea.xMax))) { hasUpperNeighbour = true; } else if (neighbourAllotmentArea.yMax <= allotmentArea.yMin && ((neighbourAllotmentArea.xMin >= allotmentArea.xMin && neighbourAllotmentArea.xMin <= allotmentArea.xMax) || (neighbourAllotmentArea.xMax >= allotmentArea.xMin && neighbourAllotmentArea.xMax <= allotmentArea.xMax) || (allotmentArea.xMin >= neighbourAllotmentArea.xMin && allotmentArea.xMin <= neighbourAllotmentArea.xMax) || (allotmentArea.xMax >= neighbourAllotmentArea.xMin && allotmentArea.xMax <= neighbourAllotmentArea.xMax))) { hasLowerNeighbour = true; } } if (hasLeftNeighbour && hasRightNeighbour && hasUpperNeighbour && hasLowerNeighbour) { continue; } List <Direction> freeFaces = new List <Direction> (); if (!hasLowerNeighbour) { freeFaces.Add(Direction.FRONT); } if (!hasUpperNeighbour) { freeFaces.Add(Direction.BACK); } if (!hasLeftNeighbour) { freeFaces.Add(Direction.LEFT); } if (!hasRightNeighbour) { freeFaces.Add(Direction.RIGHT); } int widthInTiles = (int)allotmentArea.width / architectureStyle.tileWidth; int depthInTiles = (int)allotmentArea.height / architectureStyle.tileWidth; int spacing = architectureStyle.spacing * (architectureStyle.tileWidth / 2); _allotments.Add(new Allotment(blockXStart + (int)allotmentArea.x + spacing, blockZStart + (int)allotmentArea.y + spacing, (int)allotmentArea.width, (int)allotmentArea.height, widthInTiles, depthInTiles, freeFaces.ToArray(), architectureStyle)); } } }