예제 #1
0
        private static AtlasPackingResult MergeAtlasPackingResultStackBonA(AtlasPackingResult a,
                                                                           AtlasPackingResult b, int maxWidthDim, int maxHeightDim, bool stretchBToAtlasWidth, IPipeline pipeline)
        {
            Debug.Assert(a.usedW == a.atlasX);
            Debug.Assert(a.usedH == a.atlasY);
            Debug.Assert(b.usedW == b.atlasX);
            Debug.Assert(b.usedH == b.atlasY);
            Debug.Assert(a.usedW <= maxWidthDim, a.usedW + " " + maxWidthDim);
            Debug.Assert(a.usedH <= maxHeightDim, a.usedH + " " + maxHeightDim);
            Debug.Assert(b.usedH <= maxHeightDim);
            Debug.Assert(b.usedW <= maxWidthDim, b.usedW + " " + maxWidthDim);

            Rect AatlasToFinal;
            Rect BatlasToFinal;

            // first calc height scale and offset
            int atlasX;
            int atlasY;

            pipeline.MergeAtlasPackingResultStackBonAInternal(a, b, out AatlasToFinal, out BatlasToFinal, stretchBToAtlasWidth, maxWidthDim, maxHeightDim, out atlasX, out atlasY);

            Rect[]         newRects   = new Rect[a.rects.Length + b.rects.Length];
            AtlasPadding[] paddings   = new AtlasPadding[a.rects.Length + b.rects.Length];
            int[]          srcImgIdxs = new int[a.rects.Length + b.rects.Length];
            Array.Copy(a.padding, paddings, a.padding.Length);
            Array.Copy(b.padding, 0, paddings, a.padding.Length, b.padding.Length);
            Array.Copy(a.srcImgIdxs, srcImgIdxs, a.srcImgIdxs.Length);
            Array.Copy(b.srcImgIdxs, 0, srcImgIdxs, a.srcImgIdxs.Length, b.srcImgIdxs.Length);
            Array.Copy(a.rects, newRects, a.rects.Length);
            for (int i = 0; i < a.rects.Length; i++)
            {
                Rect r = a.rects[i];
                r.x       = AatlasToFinal.x + r.x * AatlasToFinal.width;
                r.y       = AatlasToFinal.y + r.y * AatlasToFinal.height;
                r.width  *= AatlasToFinal.width;
                r.height *= AatlasToFinal.height;
                Debug.Assert(r.max.x <= 1f);
                Debug.Assert(r.max.y <= 1f);
                Debug.Assert(r.min.x >= 0f);
                Debug.Assert(r.min.y >= 0f);
                newRects[i]   = r;
                srcImgIdxs[i] = a.srcImgIdxs[i];
            }

            for (int i = 0; i < b.rects.Length; i++)
            {
                Rect r = b.rects[i];
                r.x       = BatlasToFinal.x + r.x * BatlasToFinal.width;
                r.y       = BatlasToFinal.y + r.y * BatlasToFinal.height;
                r.width  *= BatlasToFinal.width;
                r.height *= BatlasToFinal.height;
                Debug.Assert(r.max.x <= 1f);
                Debug.Assert(r.max.y <= 1f);
                Debug.Assert(r.min.x >= 0f);
                Debug.Assert(r.min.y >= 0f);
                newRects[a.rects.Length + i]   = r;
                srcImgIdxs[a.rects.Length + i] = b.srcImgIdxs[i];
            }

            AtlasPackingResult res = new AtlasPackingResult(paddings);

            res.atlasX     = atlasX;
            res.atlasY     = atlasY;
            res.padding    = paddings;
            res.rects      = newRects;
            res.srcImgIdxs = srcImgIdxs;
            res.CalcUsedWidthAndHeight();
            return(res);
        }
예제 #2
0
        //----------------- Algorithm for fitting everything into multiple Atlases
        //
        // for images being added calc area, maxW, maxH. A perfectly packed atlas will match area exactly. atlas must be at least maxH and maxW in size.
        // Sort images from big to small using either height, width or area comparer
        //
        // If an image is bigger than maxDim, then shrink it to max size on the largest dimension
        // distribute images using the new algorithm, should never have to expand the atlas instead create new atlases as needed
        // should not need to scale atlases
        //
        AtlasPackingResult[] _GetRectsMultiAtlas(List <Vector2> imgWidthHeights, List <AtlasPadding> paddings, int maxDimensionPassedX, int maxDimensionPassedY, int minImageSizeX, int minImageSizeY, int masterImageSizeX, int masterImageSizeY)
        {
            Debug.Log(String.Format("_GetRects numImages={0}, maxDimensionX={1}, maxDimensionY={2} minImageSizeX={3}, minImageSizeY={4}, masterImageSizeX={5}, masterImageSizeY={6}",
                                    imgWidthHeights.Count, maxDimensionPassedX, maxDimensionPassedY, minImageSizeX, minImageSizeY, masterImageSizeX, masterImageSizeY));
            float area = 0;
            int   maxW = 0;
            int   maxH = 0;

            ImageAreaInAtlas[] imgsToAdd = new ImageAreaInAtlas[imgWidthHeights.Count];
            int maxDimensionX            = maxDimensionPassedX;
            int maxDimensionY            = maxDimensionPassedY;

            if (atlasMustBePowerOfTwo)
            {
                maxDimensionX = RoundToNearestPositivePowerOfTwo(maxDimensionX);
                maxDimensionY = RoundToNearestPositivePowerOfTwo(maxDimensionY);
            }
            for (int i = 0; i < imgsToAdd.Length; i++)
            {
                int iw = (int)imgWidthHeights[i].x;
                int ih = (int)imgWidthHeights[i].y;

                //shrink the image so that it fits in maxDimenion if it is larger than maxDimension if atlas exceeds maxDim x maxDim then new alas will be created
                iw = Mathf.Min(iw, maxDimensionX - paddings[i].leftRight * 2);
                ih = Mathf.Min(ih, maxDimensionY - paddings[i].topBottom * 2);

                ImageAreaInAtlas im = imgsToAdd[i] = new ImageAreaInAtlas(i, iw, ih, paddings[i], minImageSizeX, minImageSizeY);
                area += im.w * im.h;
                maxW  = Mathf.Max(maxW, im.w);
                maxH  = Mathf.Max(maxH, im.h);
            }

            //explore the space to find a resonably efficient packing
            //int sqrtArea = (int)Mathf.Sqrt(area);
            int idealAtlasW;
            int idealAtlasH;

            if (atlasMustBePowerOfTwo)
            {
                idealAtlasH = RoundToNearestPositivePowerOfTwo(maxDimensionY);
                idealAtlasW = RoundToNearestPositivePowerOfTwo(maxDimensionX);
            }
            else
            {
                idealAtlasH = maxDimensionY;
                idealAtlasW = maxDimensionX;
            }

            if (idealAtlasW == 0)
            {
                idealAtlasW = 4;
            }
            if (idealAtlasH == 0)
            {
                idealAtlasH = 4;
            }

            ProbeResult pr = new ProbeResult();

            Array.Sort(imgsToAdd, new ImageHeightComparer());
            if (ProbeMultiAtlas(imgsToAdd, idealAtlasW, idealAtlasH, area, maxDimensionX, maxDimensionY, pr))
            {
                bestRoot = pr;
            }
            Array.Sort(imgsToAdd, new ImageWidthComparer());
            if (ProbeMultiAtlas(imgsToAdd, idealAtlasW, idealAtlasH, area, maxDimensionX, maxDimensionY, pr))
            {
                if (pr.totalAtlasArea < bestRoot.totalAtlasArea)
                {
                    bestRoot = pr;
                }
            }
            Array.Sort(imgsToAdd, new ImageAreaComparer());
            if (ProbeMultiAtlas(imgsToAdd, idealAtlasW, idealAtlasH, area, maxDimensionX, maxDimensionY, pr))
            {
                if (pr.totalAtlasArea < bestRoot.totalAtlasArea)
                {
                    bestRoot = pr;
                }
            }

            if (bestRoot == null)
            {
                return(null);
            }
            Debug.Log("Best fit found: w=" + bestRoot.w + " h=" + bestRoot.h + " efficiency=" + bestRoot.efficiency + " squareness=" + bestRoot.squareness + " fits in max dimension=" + bestRoot.largerOrEqualToMaxDim);

            //the atlas can be larger than the max dimension scale it if this is the case
            //int newMinSizeX = minImageSizeX;
            //int newMinSizeY = minImageSizeY;
            List <AtlasPackingResult> rs = new List <AtlasPackingResult>();

            // find all Nodes that are an individual atlas
            List <AtalsAreaNode>  atlasNodes = new List <AtalsAreaNode>();
            Stack <AtalsAreaNode> stack      = new Stack <AtalsAreaNode>();
            AtalsAreaNode         node       = bestRoot.root;

            while (node != null)
            {
                stack.Push(node);
                node = node.child[0];
            }

            // traverse the tree collecting atlasNodes
            while (stack.Count > 0)
            {
                node = stack.Pop();
                if (node.isFullAtlas == NodeType.maxDim)
                {
                    atlasNodes.Add(node);
                }
                if (node.child[1] != null)
                {
                    node = node.child[1];
                    while (node != null)
                    {
                        stack.Push(node);
                        node = node.child[0];
                    }
                }
            }

            //pack atlases so they all fit
            for (int i = 0; i < atlasNodes.Count; i++)
            {
                List <ImageAreaInAtlas> images = new List <ImageAreaInAtlas>();
                flattenTree(atlasNodes[i], images);
                Rect[] rss       = new Rect[images.Count];
                int[]  srcImgIdx = new int[images.Count];
                for (int j = 0; j < images.Count; j++)
                {
                    rss[j]       = (new Rect(images[j].x - atlasNodes[i].nodeAreaRect.x, images[j].y, images[j].w, images[j].h));
                    srcImgIdx[j] = images[j].imgId;
                }
                AtlasPackingResult res = new AtlasPackingResult(paddings.ToArray());
                GetExtent(atlasNodes[i], ref res.usedW, ref res.usedH);
                res.usedW -= atlasNodes[i].nodeAreaRect.x;
                int outW = atlasNodes[i].nodeAreaRect.w;
                int outH = atlasNodes[i].nodeAreaRect.h;
                if (atlasMustBePowerOfTwo)
                {
                    outW = Mathf.Min(CeilToNearestPowerOfTwo(res.usedW), atlasNodes[i].nodeAreaRect.w);
                    outH = Mathf.Min(CeilToNearestPowerOfTwo(res.usedH), atlasNodes[i].nodeAreaRect.h);
                    if (outH < outW / 2)
                    {
                        outH = outW / 2;                  //smaller dim can't be less than half larger
                    }
                    if (outW < outH / 2)
                    {
                        outW = outH / 2;
                    }
                }
                else
                {
                    outW = res.usedW;
                    outH = res.usedH;
                }

                res.atlasY = outH;
                res.atlasX = outW;

                res.rects      = rss;
                res.srcImgIdxs = srcImgIdx;
                res.CalcUsedWidthAndHeight();
                rs.Add(res);
                normalizeRects(res, paddings[i]);
                Debug.Log(String.Format("Done GetRects "));
            }

            return(rs.ToArray());
        }
예제 #3
0
        AtlasPackingResult _GetRectsSingleAtlas(List <Vector2> imgWidthHeights, List <AtlasPadding> paddings, int maxDimensionX, int maxDimensionY, int minImageSizeX, int minImageSizeY, int masterImageSizeX, int masterImageSizeY, int recursionDepth)
        {
            AtlasPackingResult res = new AtlasPackingResult(paddings.ToArray());

            List <Rect>             rects  = new List <Rect>();
            int                     extent = 0;
            int                     maxh   = 0;
            int                     maxw   = 0;
            List <ImageAreaInAtlas> images = new List <ImageAreaInAtlas>();

            Debug.Log("Packing rects for: " + imgWidthHeights.Count);
            for (int i = 0; i < imgWidthHeights.Count; i++)
            {
                ImageAreaInAtlas im = new ImageAreaInAtlas(i, (int)imgWidthHeights[i].x, (int)imgWidthHeights[i].y, paddings[i], minImageSizeX, minImageSizeY);

                // if images are stacked horizontally then there is no padding at the top or bottom
                if (packingOrientation == TexturePackingOrientation.vertical)
                {
                    im.h -= paddings[i].topBottom * 2;
                    im.x  = extent;
                    im.y  = 0;
                    rects.Add(new Rect(im.w, im.h, extent, 0));
                    extent += im.w;
                    maxh    = Mathf.Max(maxh, im.h);
                }
                else
                {
                    im.w -= paddings[i].leftRight * 2;
                    im.y  = extent;
                    im.x  = 0;
                    rects.Add(new Rect(im.w, im.h, 0, extent));
                    extent += im.h;
                    maxw    = Mathf.Max(maxw, im.w);
                }
                images.Add(im);
            }
            //scale atlas to fit maxDimension
            Vector2 rootWH;

            if (packingOrientation == TexturePackingOrientation.vertical)
            {
                rootWH = new Vector2(extent, maxh);
            }
            else
            {
                rootWH = new Vector2(maxw, extent);
            }
            int outW = (int)rootWH.x;
            int outH = (int)rootWH.y;

            if (packingOrientation == TexturePackingOrientation.vertical)
            {
                if (atlasMustBePowerOfTwo)
                {
                    outW = Mathf.Min(CeilToNearestPowerOfTwo(outW), maxDimensionX);
                }
                else
                {
                    outW = Mathf.Min(outW, maxDimensionX);
                }
            }
            else
            {
                if (atlasMustBePowerOfTwo)
                {
                    outH = Mathf.Min(CeilToNearestPowerOfTwo(outH), maxDimensionY);
                }
                else
                {
                    outH = Mathf.Min(outH, maxDimensionY);
                }
            }

            float padX, padY;
            int   newMinSizeX, newMinSizeY;

            if (!ScaleAtlasToFitMaxDim(rootWH, images, maxDimensionX, maxDimensionY, paddings[0], minImageSizeX, minImageSizeY, masterImageSizeX, masterImageSizeY,
                                       ref outW, ref outH, out padX, out padY, out newMinSizeX, out newMinSizeY))
            {
                res            = new AtlasPackingResult(paddings.ToArray());
                res.rects      = new Rect[images.Count];
                res.srcImgIdxs = new int[images.Count];
                res.atlasX     = outW;
                res.atlasY     = outH;
                for (int i = 0; i < images.Count; i++)
                {
                    ImageAreaInAtlas im = images[i];
                    Rect             r;
                    if (packingOrientation == TexturePackingOrientation.vertical)
                    {
                        r = res.rects[i] = new Rect((float)im.x / (float)outW + padX,
                                                    (float)im.y / (float)outH,
                                                    (float)im.w / (float)outW - padX * 2f,
                                                    stretchImagesToEdges ? 1f : (float)im.h / (float)outH);          // all images are stretched to fill the height
                    }
                    else
                    {
                        r = res.rects[i] = new Rect((float)im.x / (float)outW,
                                                    (float)im.y / (float)outH + padY,
                                                    (stretchImagesToEdges ? 1f : ((float)im.w / (float)outW)),
                                                    (float)im.h / (float)outH - padY * 2f);          // all images are stretched to fill the height
                    }
                    res.srcImgIdxs[i] = im.imgId;
                    Debug.Log("Image: " + i + " imgID=" + im.imgId + " x=" + r.x * outW +
                              " y=" + r.y * outH + " w=" + r.width * outW +
                              " h=" + r.height * outH + " padding=" + paddings[i] + " outW=" + outW + " outH=" + outH);
                }
                res.CalcUsedWidthAndHeight();
                return(res);
            }
            Debug.Log("Packing failed returning null atlas result");
            return(null);
        }
예제 #4
0
        //------------------ Algorithm for fitting everything into one atlas and scaling down
        //
        // for images being added calc area, maxW, maxH. A perfectly packed atlas will match area exactly. atlas must be at least maxH and maxW in size.
        // Sort images from big to small using either height, width or area comparer
        // Explore space to find a resonably efficient packing. Grow the atlas gradually until a fit is found
        // Scale atlas to fit
        //
        AtlasPackingResult _GetRectsSingleAtlas(List <Vector2> imgWidthHeights,
                                                List <AtlasPadding> paddings,
                                                int maxDimensionX,
                                                int maxDimensionY,
                                                int minImageSizeX,
                                                int minImageSizeY,
                                                int masterImageSizeX,
                                                int masterImageSizeY,
                                                int recursionDepth)
        {
            Debug.Log(string.Format("_GetRects 图片数量 ={0}, 最大尺寸X ={1}, 最小尺寸 X={2}, 最小尺寸 Y ={3}, masterImageSizeX={4}, masterImageSizeY={5}, 递归深度 = {6}",
                                    imgWidthHeights.Count, maxDimensionX, minImageSizeX, minImageSizeY, masterImageSizeX, masterImageSizeY, recursionDepth));
            if (recursionDepth > 10)
            {
                //最大递归深度设定为 10
                Debug.LogError("Maximum recursion depth reached. Couldn't find packing for these textures.");
                return(null);
            }
            float allImageTotalArea = 0;
            int   maxW = 0;
            int   maxH = 0;

            ImageAreaInAtlas[] imgsToAdd = new ImageAreaInAtlas[imgWidthHeights.Count];
            for (int i = 0; i < imgsToAdd.Length; i++)
            {
                int iw = (int)imgWidthHeights[i].x;
                int ih = (int)imgWidthHeights[i].y;

                ImageAreaInAtlas im = imgsToAdd[i] = new ImageAreaInAtlas(i, iw, ih, paddings[i], minImageSizeX, minImageSizeY);
                allImageTotalArea += im.w * im.h;
                maxW = Mathf.Max(maxW, im.w);
                maxH = Mathf.Max(maxH, im.h);
            }

            if ((float)maxH / (float)maxW > 2)
            {
                Array.Sort(imgsToAdd, new ImageHeightComparer());
            }
            else if ((float)maxH / (float)maxW < .5)
            {
                Array.Sort(imgsToAdd, new ImageWidthComparer());
            }
            else
            {
                Array.Sort(imgsToAdd, new ImageAreaComparer());
            }

            //explore the space to find a resonably efficient packing
            //探索图片空间以找到合理有效的包装
            int sqrtArea = (int)Mathf.Sqrt(allImageTotalArea);
            int idealAtlasW;
            int idealAtlasH;

            if (atlasMustBePowerOfTwo)
            {
                idealAtlasW = idealAtlasH = RoundToNearestPositivePowerOfTwo(sqrtArea);
                if (maxW > idealAtlasW)
                {
                    idealAtlasW = CeilToNearestPowerOfTwo(idealAtlasW);
                }
                if (maxH > idealAtlasH)
                {
                    idealAtlasH = CeilToNearestPowerOfTwo(idealAtlasH);
                }
            }
            else
            {
                idealAtlasW = sqrtArea;
                idealAtlasH = sqrtArea;
                if (maxW > sqrtArea)
                {
                    idealAtlasW = maxW;
                    idealAtlasH = Mathf.Max(Mathf.CeilToInt(allImageTotalArea / maxW), maxH);
                }
                if (maxH > sqrtArea)
                {
                    idealAtlasW = Mathf.Max(Mathf.CeilToInt(allImageTotalArea / maxH), maxW);
                    idealAtlasH = maxH;
                }
            }

            if (idealAtlasW == 0)
            {
                idealAtlasW = 4;
            }
            if (idealAtlasH == 0)
            {
                idealAtlasH = 4;
            }
            int stepW = (int)(idealAtlasW * .15f);
            int stepH = (int)(idealAtlasH * .15f);

            if (stepW == 0)
            {
                stepW = 1;
            }
            if (stepH == 0)
            {
                stepH = 1;
            }
            int numWIterations = 2;
            int steppedWidth   = idealAtlasW;
            int steppedHeight  = idealAtlasH;

            while (numWIterations >= 1 && steppedHeight < sqrtArea * 1000)
            {
                bool successW = false;
                numWIterations = 0;
                steppedWidth   = idealAtlasW;
                while (!successW && steppedWidth < sqrtArea * 1000)
                {
                    ProbeResult pr = new ProbeResult();
                    Debug.Log("Probing h=" + steppedHeight + " w=" + steppedWidth);

                    if (ProbeSingleAtlas(imgsToAdd, steppedWidth, steppedHeight, allImageTotalArea, maxDimensionX, maxDimensionY, pr))
                    {
                        successW = true;
                        if (bestRoot == null)
                        {
                            bestRoot = pr;
                        }
                        else if (pr.GetScore(atlasMustBePowerOfTwo) > bestRoot.GetScore(atlasMustBePowerOfTwo))
                        {
                            bestRoot = pr;
                        }
                    }
                    else
                    {
                        numWIterations++;
                        steppedWidth = SetStepWidthHeight(steppedWidth, stepW, maxDimensionX);
                        Debug.Log("增加 Width h=" + steppedHeight + " w=" + steppedWidth);
                    }
                }
                steppedHeight = SetStepWidthHeight(steppedHeight, stepH, maxDimensionY);
                Debug.Log("增加 Height h=" + steppedHeight + " w=" + steppedWidth);
            }
            if (bestRoot == null)
            {
                return(null);
            }

            int outW = 0;
            int outH = 0;

            if (atlasMustBePowerOfTwo)
            {
                outW = Mathf.Min(CeilToNearestPowerOfTwo(bestRoot.w), maxDimensionX);
                outH = Mathf.Min(CeilToNearestPowerOfTwo(bestRoot.h), maxDimensionY);
                if (outH < outW / 2)
                {
                    outH = outW / 2;                  //smaller dim can't be less than half larger
                }
                if (outW < outH / 2)
                {
                    outW = outH / 2;
                }
            }
            else
            {
                outW = Mathf.Min(bestRoot.w, maxDimensionX);
                outH = Mathf.Min(bestRoot.h, maxDimensionY);
            }

            bestRoot.outW = outW;
            bestRoot.outH = outH;
            Debug.Log("Best fit found: atlasW=" + outW +
                      " atlasH" + outH +
                      " w=" + bestRoot.w +
                      " h=" + bestRoot.h +
                      " efficiency=" + bestRoot.efficiency +
                      " squareness=" + bestRoot.squareness +
                      " fits in max dimension=" + bestRoot.largerOrEqualToMaxDim);

            //Debug.Assert(images.Count != imgsToAdd.Length, "Result images not the same lentgh as source"));

            //the atlas can be larger than the max dimension scale it if this is the case
            //int newMinSizeX = minImageSizeX;
            //int	newMinSizeY = minImageSizeY;


            List <ImageAreaInAtlas> images = new List <ImageAreaInAtlas>();

            flattenTree(bestRoot.root, images);
            images.Sort(new ImgIDComparer());
            // the atlas may be packed larger than the maxDimension. If so then the atlas needs to be scaled down to fit
            Vector2 rootWH = new Vector2(bestRoot.w, bestRoot.h);
            float   padX, padY;
            int     newMinSizeX, newMinSizeY;

            if (!ScaleAtlasToFitMaxDim(rootWH, images, maxDimensionX, maxDimensionY, paddings[0], minImageSizeX, minImageSizeY, masterImageSizeX, masterImageSizeY,
                                       ref outW, ref outH, out padX, out padY, out newMinSizeX, out newMinSizeY))
            {
                AtlasPackingResult res = new AtlasPackingResult(paddings.ToArray());
                res.rects      = new Rect[images.Count];
                res.srcImgIdxs = new int[images.Count];
                res.atlasX     = outW;
                res.atlasY     = outH;
                res.usedW      = -1;
                res.usedH      = -1;
                for (int i = 0; i < images.Count; i++)
                {
                    ImageAreaInAtlas im = images[i];
                    Rect             r  = res.rects[i] = new Rect((float)im.x / (float)outW + padX,
                                                                  (float)im.y / (float)outH + padY,
                                                                  (float)im.w / (float)outW - padX * 2f,
                                                                  (float)im.h / (float)outH - padY * 2f);
                    res.srcImgIdxs[i] = im.imgId;
                    Debug.Log("Image: " + i + " imgID=" + im.imgId + " x=" + r.x * outW +
                              " y=" + r.y * outH + " w=" + r.width * outW +
                              " h=" + r.height * outH + " padding=" + paddings[i]);
                }
                res.CalcUsedWidthAndHeight();
                return(res);
            }
            else
            {
                Debug.Log("==================== REDOING PACKING ================");
                //root = null;
                return(_GetRectsSingleAtlas(imgWidthHeights, paddings, maxDimensionX, maxDimensionY, newMinSizeX, newMinSizeY, masterImageSizeX, masterImageSizeY, recursionDepth + 1));
            }


            //Debug.Log(String.Format("Done GetRects atlasW={0} atlasH={1}", bestRoot.w, bestRoot.h));

            //return res;
        }
예제 #5
0
        AtlasPackingResult[] _GetRectsMultiAtlasVertical(List <Vector2> imgWidthHeights, List <AtlasPadding> paddings, int maxDimensionPassedX, int maxDimensionPassedY, int minImageSizeX, int minImageSizeY, int masterImageSizeX, int masterImageSizeY)
        {
            List <AtlasPackingResult> rs = new List <AtlasPackingResult>();
            int extent = 0;
            int maxh   = 0;
            int maxw   = 0;

            Debug.Log("Packing rects for: " + imgWidthHeights.Count);

            List <ImageAreaInAtlas> allImages = new List <ImageAreaInAtlas>();

            for (int i = 0; i < imgWidthHeights.Count; i++)
            {
                ImageAreaInAtlas im = new ImageAreaInAtlas(i, (int)imgWidthHeights[i].x, (int)imgWidthHeights[i].y, paddings[i], minImageSizeX, minImageSizeY);
                im.h -= paddings[i].topBottom * 2;
                allImages.Add(im);
            }
            allImages.Sort(new ImageWidthComparer());
            List <ImageAreaInAtlas> images = new List <ImageAreaInAtlas>();
            List <Rect>             rects  = new List <Rect>();
            int spaceRemaining             = maxDimensionPassedX;

            while (allImages.Count > 0 || images.Count > 0)
            {
                ImageAreaInAtlas im = PopLargestThatFits(allImages, spaceRemaining, maxDimensionPassedX, images.Count == 0);
                if (im == null)
                {
                    Debug.Log("Atlas filled creating a new atlas ");
                    AtlasPackingResult apr = new AtlasPackingResult(paddings.ToArray());
                    apr.atlasX = maxw;
                    apr.atlasY = maxh;
                    Rect[] rss       = new Rect[images.Count];
                    int[]  srcImgIdx = new int[images.Count];
                    for (int j = 0; j < images.Count; j++)
                    {
                        Rect r = new Rect(images[j].x, images[j].y,
                                          images[j].w,
                                          stretchImagesToEdges ? maxh : images[j].h);
                        rss[j]       = r;
                        srcImgIdx[j] = images[j].imgId;
                    }
                    apr.rects      = rss;
                    apr.srcImgIdxs = srcImgIdx;
                    apr.CalcUsedWidthAndHeight();
                    images.Clear();
                    rects.Clear();
                    extent = 0;
                    maxh   = 0;
                    rs.Add(apr);
                    spaceRemaining = maxDimensionPassedX;
                }
                else
                {
                    im.x = extent;
                    im.y = 0;
                    images.Add(im);
                    rects.Add(new Rect(extent, 0, im.w, im.h));
                    extent        += im.w;
                    maxh           = Mathf.Max(maxh, im.h);
                    maxw           = extent;
                    spaceRemaining = maxDimensionPassedX - extent;
                }
            }

            for (int i = 0; i < rs.Count; i++)
            {
                int outW = rs[i].atlasX;
                int outH = Mathf.Min(rs[i].atlasY, maxDimensionPassedY);
                if (atlasMustBePowerOfTwo)
                {
                    outW = Mathf.Min(CeilToNearestPowerOfTwo(outW), maxDimensionPassedX);
                }
                else
                {
                    outW = Mathf.Min(outW, maxDimensionPassedX);
                }
                rs[i].atlasX = outW;
                //-------------------------------
                //scale atlas to fit maxDimension
                float padX, padY;
                int   newMinSizeX, newMinSizeY;
                ScaleAtlasToFitMaxDim(new Vector2(rs[i].atlasX, rs[i].atlasY), images, maxDimensionPassedX, maxDimensionPassedY, paddings[0], minImageSizeX, minImageSizeY, masterImageSizeX, masterImageSizeY,
                                      ref outW, ref outH, out padX, out padY, out newMinSizeX, out newMinSizeY);
            }



            //normalize atlases so that that rects are 0 to 1
            for (int i = 0; i < rs.Count; i++)
            {
                normalizeRects(rs[i], paddings[i]);
                rs[i].CalcUsedWidthAndHeight();
            }
            //-----------------------------
            return(rs.ToArray());
        }