public static AtlasPackingResult[] CalculateAtlasRectanglesStatic(MB3_TextureCombinerPipeline.TexturePipelineData data, bool doMultiAtlas, MB2_LogLevel LOG_LEVEL)
        {
            List <Vector2> imageSizes = new List <Vector2>();

            for (int i = 0; i < data.distinctMaterialTextures.Count; i++)
            {
                imageSizes.Add(new Vector2(data.distinctMaterialTextures[i].idealWidth, data.distinctMaterialTextures[i].idealHeight));
            }

            MB2_TexturePacker tp = MB3_TextureCombinerPipeline.CreateTexturePacker(data._packingAlgorithm);

            tp.atlasMustBePowerOfTwo = data._meshBakerTexturePackerForcePowerOfTwo;
            List <AtlasPadding> paddings = new List <AtlasPadding>();

            for (int i = 0; i < imageSizes.Count; i++)
            {
                AtlasPadding padding = new AtlasPadding();
                padding.topBottom = data._atlasPadding;
                padding.leftRight = data._atlasPadding;
                if (data._packingAlgorithm == MB2_PackingAlgorithmEnum.MeshBakerTexturePacker_Horizontal)
                {
                    padding.leftRight = 0;
                }
                if (data._packingAlgorithm == MB2_PackingAlgorithmEnum.MeshBakerTexturePacker_Vertical)
                {
                    padding.topBottom = 0;
                }
                paddings.Add(padding);
            }

            return(tp.GetRects(imageSizes, paddings, data._maxAtlasWidth, data._maxAtlasHeight, doMultiAtlas));
        }
        public AtlasPackingResult[] CalculateAtlasRectangles(MB3_TextureCombinerPipeline.TexturePipelineData data, bool doMultiAtlas, MB2_LogLevel LOG_LEVEL)
        {
            Debug.Assert(data.OnlyOneTextureInAtlasReuseTextures());
            if (LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("Only one image per atlas. Will re-use original texture");
            AtlasPackingResult[] packerRects = new AtlasPackingResult[1];
            AtlasPadding[] paddings = new AtlasPadding[] { new AtlasPadding(data._atlasPadding) };
            packerRects[0] = new AtlasPackingResult(paddings);
            packerRects[0].rects = new Rect[1];
            packerRects[0].srcImgIdxs = new int[] { 0 };
            packerRects[0].rects[0] = new Rect(0f, 0f, 1f, 1f);

            MeshBakerMaterialTexture dmt = null;
            if (data.distinctMaterialTextures[0].ts.Length > 0)
            {
                dmt = data.distinctMaterialTextures[0].ts[0];

            }
            if (dmt == null || dmt.isNull)
            {
                packerRects[0].atlasX = 16;
                packerRects[0].atlasY = 16;
                packerRects[0].usedW = 16;
                packerRects[0].usedH = 16;
            }
            else
            {
                packerRects[0].atlasX = dmt.width;
                packerRects[0].atlasY = dmt.height;
                packerRects[0].usedW = dmt.width;
                packerRects[0].usedH = dmt.height;
            }
            return packerRects;
        }
Ejemplo n.º 3
0
 //normalize atlases so that that rects are 0 to 1
 public void normalizeRects(AtlasPackingResult rr, AtlasPadding padding)
 {
     for (int i = 0; i < rr.rects.Length; i++)
     {
         rr.rects[i].x      = (rr.rects[i].x + padding.leftRight) / rr.atlasX;
         rr.rects[i].y      = (rr.rects[i].y + padding.topBottom) / rr.atlasY;
         rr.rects[i].width  = (rr.rects[i].width - padding.leftRight * 2) / rr.atlasX;
         rr.rects[i].height = (rr.rects[i].height - padding.topBottom * 2) / rr.atlasY;
     }
 }
        public override AtlasPackingResult[] GetRects(List <Vector2> imgWidthHeights, int maxDimensionX, int maxDimensionY, int atPadding)
        {
            List <AtlasPadding> padding = new List <AtlasPadding>();

            for (int i = 0; i < imgWidthHeights.Count; i++)
            {
                AtlasPadding p = new AtlasPadding();
                p.leftRight = p.topBottom = atPadding;
                padding.Add(p);
            }
            return(GetRects(imgWidthHeights, padding, maxDimensionX, maxDimensionY, false));
        }
Ejemplo n.º 5
0
        public AtlasPackingResult CalculateAtlasRectangles(MB3_TextureCombinerPipeline.TexturePipelineData data, MB2_LogLevel LOG_LEVEL)
        {
            if (data._packingAlgorithm == MB2_PackingAlgorithmEnum.UnitysPackTextures)
            {
                //with Unity texture packer we don't find the rectangles, Unity does. When packer is run
                return(new AtlasPackingResult(new AtlasPadding[0]));
            }
            AtlasPackingResult uvRects;

            if (data.distinctMaterialTextures.Count == 1 && data._fixOutOfBoundsUVs == false)
            {
                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("Only one image per atlas. Will re-use original texture");
                }
                AtlasPadding[] paddings = new AtlasPadding[] { new AtlasPadding(data._atlasPadding) };
                uvRects          = new AtlasPackingResult(paddings);
                uvRects.rects    = new Rect[1];
                uvRects.rects[0] = new Rect(0f, 0f, 1f, 1f);
                uvRects.atlasX   = data.distinctMaterialTextures[0].idealWidth;
                uvRects.atlasY   = data.distinctMaterialTextures[0].idealHeight;
            }
            else
            {
                List <Vector2> imageSizes = new List <Vector2>();
                for (int i = 0; i < data.distinctMaterialTextures.Count; i++)
                {
                    imageSizes.Add(new Vector2(data.distinctMaterialTextures[i].idealWidth, data.distinctMaterialTextures[i].idealHeight));
                }
                MB2_TexturePacker tp = MB3_TextureCombinerPipeline.CreateTexturePacker(data._packingAlgorithm);
                tp.atlasMustBePowerOfTwo = data._meshBakerTexturePackerForcePowerOfTwo;
                int atlasMaxDimension        = data._maxAtlasSize;
                List <AtlasPadding> paddings = new List <AtlasPadding>();
                for (int i = 0; i < imageSizes.Count; i++)
                {
                    AtlasPadding padding = new AtlasPadding();
                    padding.topBottom = data._atlasPadding;
                    padding.leftRight = data._atlasPadding;
                    if (data._packingAlgorithm == MB2_PackingAlgorithmEnum.MeshBakerTexturePacker_Horizontal)
                    {
                        padding.leftRight = 0;
                    }
                    if (data._packingAlgorithm == MB2_PackingAlgorithmEnum.MeshBakerTexturePacker_Vertical)
                    {
                        padding.topBottom = 0;
                    }
                    paddings.Add(padding);
                }
                AtlasPackingResult[] packerRects = tp.GetRects(imageSizes, paddings, atlasMaxDimension, atlasMaxDimension, false);
                uvRects = packerRects[0];
            }
            return(uvRects);
        }
Ejemplo n.º 6
0
        public override AtlasPackingResult[] GetRects(List <Vector2> imgWidthHeights, int maxDimensionX, int maxDimensionY, int padding)
        {
            List <AtlasPadding> paddings = new List <AtlasPadding>();

            for (int i = 0; i < imgWidthHeights.Count; i++)
            {
                AtlasPadding p = new AtlasPadding();
                if (packingOrientation == TexturePackingOrientation.horizontal)
                {
                    p.leftRight = 0;
                    p.topBottom = 8;
                }
                else
                {
                    p.leftRight = 8;
                    p.topBottom = 0;
                }
                paddings.Add(p);
            }
            return(GetRects(imgWidthHeights, paddings, maxDimensionX, maxDimensionY, false));
        }
        /*
         * Packed rects may exceed atlas size and require scaling
         * When scaling want pixel perfect fit in atlas. Corners of rects should exactly align with pixel grid
         * Padding should be subtracted from pixel perfect rect to create pixel perfect square
         * TODO this doesn't handle each rectangle having different padding
         */
        internal bool ScaleAtlasToFitMaxDim(Vector2 rootWH, List <Image> images, int maxDimensionX, int maxDimensionY, AtlasPadding padding, int minImageSizeX, int minImageSizeY, int masterImageSizeX, int masterImageSizeY,
                                            ref int outW, ref int outH, out float padX, out float padY, out int newMinSizeX, out int newMinSizeY)
        {
            newMinSizeX = minImageSizeX;
            newMinSizeY = minImageSizeY;
            bool redoPacking = false;

            // the atlas may be packed larger than the maxDimension. If so then the atlas needs to be scaled down to fit
            padX = (float)padding.leftRight / (float)outW; //padding needs to be pixel perfect in size
            if (rootWH.x > maxDimensionX)
            {
                padX = (float)padding.leftRight / (float)maxDimensionX;
                float scaleFactor = (float)maxDimensionX / (float)rootWH.x;
                if (LOG_LEVEL >= MB2_LogLevel.warn)
                {
                    Debug.LogWarning("Packing exceeded atlas width shrinking to " + scaleFactor);
                }
                for (int i = 0; i < images.Count; i++)
                {
                    Image im = images[i];
                    if (im.w * scaleFactor < masterImageSizeX)
                    { //check if small images will be rounded too small. If so need to redo packing forcing a larger min size
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Small images are being scaled to zero. Will need to redo packing with larger minTexSizeX.");
                        }
                        redoPacking = true;
                        newMinSizeX = Mathf.CeilToInt(minImageSizeX / scaleFactor);
                    }
                    int right = (int)((im.x + im.w) * scaleFactor);
                    im.x = (int)(scaleFactor * im.x);
                    im.w = right - im.x;
                }
                outW = maxDimensionX;
            }

            padY = (float)padding.topBottom / (float)outH;
            if (rootWH.y > maxDimensionY)
            {
                //float minSizeY = ((float)minImageSizeY + 1) / maxDimension;
                padY = (float)padding.topBottom / (float)maxDimensionY;
                float scaleFactor = (float)maxDimensionY / (float)rootWH.y;
                if (LOG_LEVEL >= MB2_LogLevel.warn)
                {
                    Debug.LogWarning("Packing exceeded atlas height shrinking to " + scaleFactor);
                }
                for (int i = 0; i < images.Count; i++)
                {
                    Image im = images[i];
                    if (im.h * scaleFactor < masterImageSizeY)
                    { //check if small images will be rounded too small. If so need to redo packing forcing a larger min size
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Small images are being scaled to zero. Will need to redo packing with larger minTexSizeY.");
                        }
                        redoPacking = true;
                        newMinSizeY = Mathf.CeilToInt(minImageSizeY / scaleFactor);
                    }
                    int bottom = (int)((im.y + im.h) * scaleFactor);
                    im.y = (int)(scaleFactor * im.y);
                    im.h = bottom - im.y;
                }
                outH = maxDimensionY;
            }
            return(redoPacking);
        }
 public Image(int id, int tw, int th, AtlasPadding padding, int minImageSizeX, int minImageSizeY)
 {
     imgId = id;
     w     = Mathf.Max(tw + padding.leftRight * 2, minImageSizeX);
     h     = Mathf.Max(th + padding.topBottom * 2, minImageSizeY);
 }
        internal static IEnumerator CopyScaledAndTiledToAtlas(MeshBakerMaterialTexture source, MB_TexSet sourceMaterial,
                                                              ShaderTextureProperty shaderPropertyName, DRect srcSamplingRect, int targX, int targY, int targW, int targH,
                                                              AtlasPadding padding,
                                                              Color[][] atlasPixels, bool isNormalMap,
                                                              MB3_TextureCombinerPipeline.TexturePipelineData data,
                                                              MB3_TextureCombiner combiner,
                                                              ProgressUpdateDelegate progressInfo = null,
                                                              MB2_LogLevel LOG_LEVEL = MB2_LogLevel.info)
        {
            //HasFinished = false;
            Texture2D t = source.GetTexture2D();

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("CopyScaledAndTiledToAtlas: " + t + " inAtlasX=" + targX + " inAtlasY=" + targY + " inAtlasW=" + targW + " inAtlasH=" + targH);
            }
            float newWidth  = targW;
            float newHeight = targH;
            float scx       = (float)srcSamplingRect.width;
            float scy       = (float)srcSamplingRect.height;
            float ox        = (float)srcSamplingRect.x;
            float oy        = (float)srcSamplingRect.y;
            int   w         = (int)newWidth;
            int   h         = (int)newHeight;

            if (t == null)
            {
                if (LOG_LEVEL >= MB2_LogLevel.trace)
                {
                    Debug.Log("No source texture creating a 16x16 texture.");
                }
                t   = combiner._createTemporaryTexture(16, 16, TextureFormat.ARGB32, true);
                scx = 1;
                scy = 1;
                if (data._considerNonTextureProperties && data.nonTexturePropertyBlender != null)
                {
                    Color col = data.nonTexturePropertyBlender.GetColorIfNoTexture(sourceMaterial.matsAndGOs.mats[0].mat, shaderPropertyName);
                    if (LOG_LEVEL >= MB2_LogLevel.trace)
                    {
                        Debug.Log("Setting texture to solid color " + col);
                    }
                    MB_Utility.setSolidColor(t, col);
                }
                else
                {
                    Color col = MB3_TextureCombinerNonTextureProperties.GetColorIfNoTexture(shaderPropertyName);
                    MB_Utility.setSolidColor(t, col);
                }
            }
            if (data._considerNonTextureProperties && data.nonTexturePropertyBlender != null)
            {
                t = combiner._createTextureCopy(t);
                t = data.nonTexturePropertyBlender.TintTextureWithTextureCombiner(t, sourceMaterial, shaderPropertyName);
            }
            for (int i = 0; i < w; i++)
            {
                if (progressInfo != null && w > 0)
                {
                    progressInfo("CopyScaledAndTiledToAtlas " + (((float)i / (float)w) * 100f).ToString("F0"), .2f);
                }
                for (int j = 0; j < h; j++)
                {
                    float u = i / newWidth * scx + ox;
                    float v = j / newHeight * scy + oy;
                    atlasPixels[targY + j][targX + i] = t.GetPixelBilinear(u, v);
                }
            }
            //bleed the border colors into the padding
            for (int i = 0; i < w; i++)
            {
                for (int j = 1; j <= padding.topBottom; j++)
                {
                    //top margin
                    atlasPixels[(targY - j)][targX + i] = atlasPixels[(targY)][targX + i];
                    //bottom margin
                    atlasPixels[(targY + h - 1 + j)][targX + i] = atlasPixels[(targY + h - 1)][targX + i];
                }
            }
            for (int j = 0; j < h; j++)
            {
                for (int i = 1; i <= padding.leftRight; i++)
                {
                    //left margin
                    atlasPixels[(targY + j)][targX - i] = atlasPixels[(targY + j)][targX];
                    //right margin
                    atlasPixels[(targY + j)][targX + w + i - 1] = atlasPixels[(targY + j)][targX + w - 1];
                }
            }
            //corners
            for (int i = 1; i <= padding.leftRight; i++)
            {
                for (int j = 1; j <= padding.topBottom; j++)
                {
                    atlasPixels[(targY - j)][targX - i]                 = atlasPixels[targY][targX];
                    atlasPixels[(targY + h - 1 + j)][targX - i]         = atlasPixels[(targY + h - 1)][targX];
                    atlasPixels[(targY + h - 1 + j)][targX + w + i - 1] = atlasPixels[(targY + h - 1)][targX + w - 1];
                    atlasPixels[(targY - j)][targX + w + i - 1]         = atlasPixels[targY][targX + w - 1];
                    yield return(null);
                }
                yield return(null);
            }
            //			Debug.Log("copyandscaledatlas finished too!");
            //HasFinished = true;
            yield break;
        }
Ejemplo n.º 10
0
        public override AtlasPackingResult[] CalculateAtlasRectangles(MB3_TextureCombinerPipeline.TexturePipelineData data, bool doMultiAtlas, MB2_LogLevel LOG_LEVEL)
        {
            Debug.Assert(!data.OnlyOneTextureInAtlasReuseTextures());

            //TODO parameter
            int maxAtlasWidth = 512;

            Debug.Assert(data._packingAlgorithm != MB2_PackingAlgorithmEnum.UnitysPackTextures, "Unity texture packer cannot be used");

            //split the list of distinctMaterialTextures into two bins
            List <MB_TexSet> horizontalVerticalDistinctMaterialTextures = new List <MB_TexSet>();
            List <MB_TexSet> regularTextures = new List <MB_TexSet>();

            for (int i = 0; i < data.distinctMaterialTextures.Count; i++)
            {
                MB_TexSet texSet = data.distinctMaterialTextures[i];
                if (texSet.idealWidth >= maxAtlasWidth &&
                    texSet.ts[0].GetEncapsulatingSamplingRect().width > 1f)
                {
                    horizontalVerticalDistinctMaterialTextures.Add(texSet);
                }
                else
                {
                    regularTextures.Add(texSet);
                }
            }
            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log(String.Format("Splitting list of distinctMaterialTextures numHorizontalVertical={0} numRegular={1}", horizontalVerticalDistinctMaterialTextures.Count, regularTextures.Count));
            }

            //pack one with the horizontal texture packer
            MB2_TexturePacker        tp;
            MB2_PackingAlgorithmEnum packingAlgorithm;
            int atlasMaxDimension = data._maxAtlasSize;

            AtlasPackingResult[] packerRectsHorizontalVertical;
            if (horizontalVerticalDistinctMaterialTextures.Count > 0)
            {
                packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker_Horizontal;
                List <Vector2> imageSizesHorizontalVertical = new List <Vector2>();
                for (int i = 0; i < horizontalVerticalDistinctMaterialTextures.Count; i++)
                {
                    horizontalVerticalDistinctMaterialTextures[i].SetTilingTreatmentAndAdjustEncapsulatingSamplingRect(MB_TextureTilingTreatment.edgeToEdgeX);
                    imageSizesHorizontalVertical.Add(new Vector2(horizontalVerticalDistinctMaterialTextures[i].idealWidth, horizontalVerticalDistinctMaterialTextures[i].idealHeight));
                }
                tp = MB3_TextureCombinerPipeline.CreateTexturePacker(packingAlgorithm);
                tp.atlasMustBePowerOfTwo = false;
                List <AtlasPadding> paddingsHorizontalVertical = new List <AtlasPadding>();
                for (int i = 0; i < imageSizesHorizontalVertical.Count; i++)
                {
                    AtlasPadding padding = new AtlasPadding();
                    padding.topBottom = data._atlasPadding;
                    padding.leftRight = data._atlasPadding;
                    if (packingAlgorithm == MB2_PackingAlgorithmEnum.MeshBakerTexturePacker_Horizontal)
                    {
                        padding.leftRight = 0;
                    }
                    if (packingAlgorithm == MB2_PackingAlgorithmEnum.MeshBakerTexturePacker_Vertical)
                    {
                        padding.topBottom = 0;
                    }
                    paddingsHorizontalVertical.Add(padding);
                }
                tp.LOG_LEVEL = MB2_LogLevel.trace;
                packerRectsHorizontalVertical = tp.GetRects(imageSizesHorizontalVertical, paddingsHorizontalVertical, maxAtlasWidth, atlasMaxDimension, false);
            }
            else
            {
                packerRectsHorizontalVertical = new AtlasPackingResult[0];
            }
            AtlasPackingResult[] packerRectsRegular;
            if (regularTextures.Count > 0)
            {
                //pack other with regular texture packer
                packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker;
                List <Vector2> imageSizesRegular = new List <Vector2>();
                for (int i = 0; i < regularTextures.Count; i++)
                {
                    imageSizesRegular.Add(new Vector2(regularTextures[i].idealWidth, regularTextures[i].idealHeight));
                }
                tp = MB3_TextureCombinerPipeline.CreateTexturePacker(MB2_PackingAlgorithmEnum.MeshBakerTexturePacker);
                tp.atlasMustBePowerOfTwo = false;
                List <AtlasPadding> paddingsRegular = new List <AtlasPadding>();
                for (int i = 0; i < imageSizesRegular.Count; i++)
                {
                    AtlasPadding padding = new AtlasPadding();
                    padding.topBottom = data._atlasPadding;
                    padding.leftRight = data._atlasPadding;
                    paddingsRegular.Add(padding);
                }
                tp.LOG_LEVEL       = MB2_LogLevel.trace;
                packerRectsRegular = tp.GetRects(imageSizesRegular, paddingsRegular, maxAtlasWidth, atlasMaxDimension, false);
            }
            else
            {
                packerRectsRegular = new AtlasPackingResult[0];
            }

            AtlasPackingResult result = null;

            if (packerRectsHorizontalVertical.Length == 0 && packerRectsRegular.Length == 0)
            {
                Debug.Assert(false, "Should never have reached this.");
                return(null);
            }
            else if (packerRectsHorizontalVertical.Length > 0 && packerRectsRegular.Length > 0)
            {
                result = MergeAtlasPackingResultStackBonA(packerRectsHorizontalVertical[0], packerRectsRegular[0], atlasMaxDimension, maxAtlasWidth, true);
            }
            else if (packerRectsHorizontalVertical.Length > 0)
            {
                Debug.LogError("TODO handle this");
                result = packerRectsHorizontalVertical[0];
            }
            else if (packerRectsRegular.Length > 0)
            {
                Debug.LogError("TODO handle this.");
                result = packerRectsRegular[0];
            }

            Debug.Assert(data.distinctMaterialTextures.Count == result.rects.Length);
            //We re-ordered the distinctMaterial textures so replace the list with the new reordered one
            horizontalVerticalDistinctMaterialTextures.AddRange(regularTextures);
            data.distinctMaterialTextures = horizontalVerticalDistinctMaterialTextures;
            AtlasPackingResult[] results;
            if (result != null)
            {
                results = new AtlasPackingResult[] { result }
            }
            ;
            else
            {
                results = new AtlasPackingResult[0];
            }
            return(results);
        }
Ejemplo n.º 11
0
        public static AtlasPackingResult MergeAtlasPackingResultStackBonA(AtlasPackingResult a,
                                                                          AtlasPackingResult b, int maxHeightDim, int maxWidthDim, bool stretchBToAtlasWidth)
        {
            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);

            Rect AatlasToFinal;
            Rect BatlasToFinal;

            // first calc height scale and offset
            float finalH = a.usedH + b.usedH;
            float scaleYa, scaleYb;

            if (finalH > maxHeightDim)
            {
                scaleYa = maxHeightDim / finalH;                                              //0,1
                float offsetBy = ((float)Mathf.FloorToInt(a.usedH * scaleYa)) / maxHeightDim; //0,1
                scaleYa       = offsetBy;
                scaleYb       = (1f - offsetBy);
                AatlasToFinal = new Rect(0, 0, 1, scaleYa);
                BatlasToFinal = new Rect(0, offsetBy, 1, scaleYb);
            }
            else
            {
                float offsetBy = a.usedH / finalH;
                AatlasToFinal = new Rect(0, 0, 1, offsetBy);
                BatlasToFinal = new Rect(0, offsetBy, 1, b.usedH / finalH);
            }

            //next calc width scale and offset
            if (a.atlasX > b.atlasX)
            {
                if (!stretchBToAtlasWidth)
                {
                    // b rects will be placed in a larger atlas which will make them smaller
                    BatlasToFinal.width = ((float)b.atlasX) / a.atlasX;
                }
            }
            else if (b.atlasX > a.atlasX)
            {
                // a rects will be placed in a larger atlas which will make them smaller
                AatlasToFinal.width = ((float)a.atlasX) / b.atlasX;
            }

            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);
            int   atlasX = Mathf.Max(a.usedW, b.usedW);
            int   atlasY = a.usedH + b.usedH;
            float maxx   = 0f;
            float maxy   = 0f;

            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;
                maxx          = Mathf.Max(maxx, r.xMax);
                maxy          = Mathf.Max(maxy, r.yMax);
                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;
                maxx      = Mathf.Max(maxx, r.xMax);
                maxy      = Mathf.Max(maxy, r.yMax);
                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);
        }
Ejemplo n.º 12
0
 public void InitializeAtlasPadding(ref AtlasPadding padding, int paddingValue)
 {
     padding.topBottom = 0;
     padding.leftRight = paddingValue;
 }
Ejemplo n.º 13
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);
        }
Ejemplo n.º 14
0
        public override AtlasPackingResult[] CalculateAtlasRectangles(MB3_TextureCombinerPipeline.TexturePipelineData data, bool doMultiAtlas, MB2_LogLevel LOG_LEVEL)
        {
            Debug.Assert(!data.OnlyOneTextureInAtlasReuseTextures());
            Debug.Assert(data._packingAlgorithm != MB2_PackingAlgorithmEnum.UnitysPackTextures, "Unity texture packer cannot be used");

            IPipeline pipeline;

            if (_atlasDirection == AtlasDirection.horizontal)
            {
                pipeline = new HorizontalPipeline();
            }
            else
            {
                pipeline = new VerticalPipeline();
            }

            //int maxAtlasWidth = data._maxAtlasWidth;
            //int maxAtlasHeight = data._maxAtlasHeight;
            if (_atlasDirection == AtlasDirection.horizontal)
            {
                if (!data._useMaxAtlasWidthOverride)
                {
                    // need to get the width of the atlas without mesh uvs considered
                    int maxWidth = 2;
                    for (int i = 0; i < data.distinctMaterialTextures.Count; i++)
                    {
                        MB_TexSet ts = data.distinctMaterialTextures[i];
                        int       w;
                        if (data._fixOutOfBoundsUVs)
                        {
                            Vector2 rawHeightWidth = ts.GetMaxRawTextureHeightWidth();
                            w = (int)rawHeightWidth.x;
                        }
                        else
                        {
                            w = ts.idealWidth;
                        }
                        if (ts.idealWidth > maxWidth)
                        {
                            maxWidth = w;
                        }
                    }
                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("Calculated max atlas width: " + maxWidth);
                    }
                    data._maxAtlasWidth = maxWidth;
                }
            }
            else
            {
                if (!data._useMaxAtlasHeightOverride)
                {
                    int maxHeight = 2;
                    for (int i = 0; i < data.distinctMaterialTextures.Count; i++)
                    {
                        MB_TexSet ts = data.distinctMaterialTextures[i];
                        int       h;
                        if (data._fixOutOfBoundsUVs)
                        {
                            Vector2 rawHeightWidth = ts.GetMaxRawTextureHeightWidth();
                            h = (int)rawHeightWidth.y;
                        }
                        else
                        {
                            h = ts.idealHeight;
                        }
                        if (ts.idealHeight > maxHeight)
                        {
                            maxHeight = h;
                        }
                    }
                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("Calculated max atlas height: " + maxHeight);
                    }
                    data._maxAtlasHeight = maxHeight;
                }
            }

            //split the list of distinctMaterialTextures into two bins
            List <MB_TexSet> horizontalVerticalDistinctMaterialTextures = new List <MB_TexSet>();
            List <MB_TexSet> regularTextures = new List <MB_TexSet>();

            for (int i = 0; i < data.distinctMaterialTextures.Count; i++)
            {
                pipeline.SortTexSetIntoBins(data.distinctMaterialTextures[i], horizontalVerticalDistinctMaterialTextures, regularTextures, data._maxAtlasWidth, data._maxAtlasHeight);
            }

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log(String.Format("Splitting list of distinctMaterialTextures numHorizontalVertical={0} numRegular={1} maxAtlasWidth={2} maxAtlasHeight={3}", horizontalVerticalDistinctMaterialTextures.Count, regularTextures.Count, data._maxAtlasWidth, data._maxAtlasHeight));
            }

            //pack one bin with the horizontal vertical texture packer.
            MB2_TexturePacker        tp;
            MB2_PackingAlgorithmEnum packingAlgorithm;

            AtlasPackingResult[] packerRectsHorizontalVertical;
            if (horizontalVerticalDistinctMaterialTextures.Count > 0)
            {
                packingAlgorithm = pipeline.GetPackingAlg();
                List <Vector2> imageSizesHorizontalVertical = new List <Vector2>();
                for (int i = 0; i < horizontalVerticalDistinctMaterialTextures.Count; i++)
                {
                    horizontalVerticalDistinctMaterialTextures[i].SetTilingTreatmentAndAdjustEncapsulatingSamplingRect(pipeline.GetEdge2EdgeTreatment());
                    imageSizesHorizontalVertical.Add(new Vector2(horizontalVerticalDistinctMaterialTextures[i].idealWidth, horizontalVerticalDistinctMaterialTextures[i].idealHeight));
                }

                tp = MB3_TextureCombinerPipeline.CreateTexturePacker(packingAlgorithm);
                tp.atlasMustBePowerOfTwo = false;
                List <AtlasPadding> paddingsHorizontalVertical = new List <AtlasPadding>();
                for (int i = 0; i < imageSizesHorizontalVertical.Count; i++)
                {
                    AtlasPadding padding = new AtlasPadding();
                    pipeline.InitializeAtlasPadding(ref padding, data._atlasPadding);
                    paddingsHorizontalVertical.Add(padding);
                }

                tp.LOG_LEVEL = MB2_LogLevel.trace;
                packerRectsHorizontalVertical = tp.GetRects(imageSizesHorizontalVertical, paddingsHorizontalVertical, data._maxAtlasWidth, data._maxAtlasHeight, false);
                if (LOG_LEVEL >= MB2_LogLevel.trace)
                {
                    Debug.Log(String.Format("Packed {0} textures with edgeToEdge tiling into an atlas of size {1} by {2} usedW {3} usedH {4}", horizontalVerticalDistinctMaterialTextures.Count, packerRectsHorizontalVertical[0].atlasX, packerRectsHorizontalVertical[0].atlasY, packerRectsHorizontalVertical[0].usedW, packerRectsHorizontalVertical[0].usedH));
                }
            }
            else
            {
                packerRectsHorizontalVertical = new AtlasPackingResult[0];
            }

            //pack other bin with regular texture packer
            AtlasPackingResult[] packerRectsRegular;
            if (regularTextures.Count > 0)
            {
                packingAlgorithm = MB2_PackingAlgorithmEnum.MeshBakerTexturePacker;
                List <Vector2> imageSizesRegular = new List <Vector2>();
                for (int i = 0; i < regularTextures.Count; i++)
                {
                    imageSizesRegular.Add(new Vector2(regularTextures[i].idealWidth, regularTextures[i].idealHeight));
                }

                tp = MB3_TextureCombinerPipeline.CreateTexturePacker(MB2_PackingAlgorithmEnum.MeshBakerTexturePacker);
                tp.atlasMustBePowerOfTwo = false;
                List <AtlasPadding> paddingsRegular = new List <AtlasPadding>();
                for (int i = 0; i < imageSizesRegular.Count; i++)
                {
                    AtlasPadding padding = new AtlasPadding();
                    padding.topBottom = data._atlasPadding;
                    padding.leftRight = data._atlasPadding;
                    paddingsRegular.Add(padding);
                }

                int atlasRegularMaxWidth, atlasRegularMaxHeight;
                int usedHorizontalVertWidth = 0, usedHorizontalVertHeight = 0;
                if (packerRectsHorizontalVertical.Length > 0)
                {
                    usedHorizontalVertHeight = packerRectsHorizontalVertical[0].atlasY;
                    usedHorizontalVertWidth  = packerRectsHorizontalVertical[0].atlasX;
                }
                pipeline.GetExtraRoomForRegularAtlas(usedHorizontalVertWidth, usedHorizontalVertHeight, data._maxAtlasWidth, data._maxAtlasHeight, out atlasRegularMaxWidth, out atlasRegularMaxHeight);
                packerRectsRegular = tp.GetRects(imageSizesRegular, paddingsRegular, atlasRegularMaxWidth, atlasRegularMaxHeight, false);
                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log(String.Format("Packed {0} textures without edgeToEdge tiling into an atlas of size {1} by {2} usedW {3} usedH {4}", regularTextures.Count, packerRectsRegular[0].atlasX, packerRectsRegular[0].atlasY, packerRectsRegular[0].usedW, packerRectsRegular[0].usedH));
                }
            }
            else
            {
                packerRectsRegular = new AtlasPackingResult[0];
            }


            AtlasPackingResult result = null;

            if (packerRectsHorizontalVertical.Length == 0 && packerRectsRegular.Length == 0)
            {
                Debug.Assert(false, "Should never have reached this.");
                return(null);
            }
            else if (packerRectsHorizontalVertical.Length > 0 && packerRectsRegular.Length > 0)
            {
                result = MergeAtlasPackingResultStackBonA(packerRectsHorizontalVertical[0], packerRectsRegular[0], data._maxAtlasWidth, data._maxAtlasHeight, true, pipeline);
            }
            else if (packerRectsHorizontalVertical.Length > 0)
            {
                result = packerRectsHorizontalVertical[0];
            }
            else if (packerRectsRegular.Length > 0)
            {
                result = packerRectsRegular[0];
            }

            Debug.Assert(data.distinctMaterialTextures.Count == result.rects.Length);

            //We re-ordered the distinctMaterial textures so replace the list with the new reordered one
            horizontalVerticalDistinctMaterialTextures.AddRange(regularTextures);
            data.distinctMaterialTextures = horizontalVerticalDistinctMaterialTextures;
            AtlasPackingResult[] results;
            if (result != null)
            {
                results = new AtlasPackingResult[] { result }
            }
            ;
            else
            {
                results = new AtlasPackingResult[0];
            }
            return(results);
        }
        internal static IEnumerator CopyScaledAndTiledToAtlas(MeshBakerMaterialTexture source, MB_TexSet sourceMaterial,
                                                              ShaderTextureProperty shaderPropertyName, DRect srcSamplingRect, int targX, int targY, int targW, int targH,
                                                              AtlasPadding padding,
                                                              Color[][] atlasPixels, bool isNormalMap,
                                                              MB3_TextureCombinerPipeline.TexturePipelineData data,
                                                              MB3_TextureCombiner combiner,
                                                              ProgressUpdateDelegate progressInfo = null,
                                                              MB2_LogLevel LOG_LEVEL = MB2_LogLevel.info)
        {
            //HasFinished = false;
            Texture2D t = source.GetTexture2D();

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log(String.Format("CopyScaledAndTiledToAtlas: {0} inAtlasX={1} inAtlasY={2} inAtlasW={3} inAtlasH={4} paddX={5} paddY={6} srcSamplingRect={7}",
                                        t, targX, targY, targW, targH, padding.leftRight, padding.topBottom, srcSamplingRect));
            }
            float newWidth  = targW;
            float newHeight = targH;
            float scx       = (float)srcSamplingRect.width;
            float scy       = (float)srcSamplingRect.height;
            float ox        = (float)srcSamplingRect.x;
            float oy        = (float)srcSamplingRect.y;
            int   w         = (int)newWidth;
            int   h         = (int)newHeight;

            if (data._considerNonTextureProperties)
            {
                t = combiner._createTextureCopy(shaderPropertyName.name, t);
                t = data.nonTexturePropertyBlender.TintTextureWithTextureCombiner(t, sourceMaterial, shaderPropertyName);
            }
            for (int i = 0; i < w; i++)
            {
                if (progressInfo != null && w > 0)
                {
                    progressInfo("CopyScaledAndTiledToAtlas " + (((float)i / (float)w) * 100f).ToString("F0"), .2f);
                }
                for (int j = 0; j < h; j++)
                {
                    float u = i / newWidth * scx + ox;
                    float v = j / newHeight * scy + oy;
                    atlasPixels[targY + j][targX + i] = t.GetPixelBilinear(u, v);
                }
            }

            //bleed the border colors into the padding
            for (int i = 0; i < w; i++)
            {
                for (int j = 1; j <= padding.topBottom; j++)
                {
                    //top margin
                    atlasPixels[(targY - j)][targX + i] = atlasPixels[(targY)][targX + i];
                    //bottom margin
                    atlasPixels[(targY + h - 1 + j)][targX + i] = atlasPixels[(targY + h - 1)][targX + i];
                }
            }
            for (int j = 0; j < h; j++)
            {
                for (int i = 1; i <= padding.leftRight; i++)
                {
                    //left margin
                    atlasPixels[(targY + j)][targX - i] = atlasPixels[(targY + j)][targX];
                    //right margin
                    atlasPixels[(targY + j)][targX + w + i - 1] = atlasPixels[(targY + j)][targX + w - 1];
                }
            }
            //corners
            for (int i = 1; i <= padding.leftRight; i++)
            {
                for (int j = 1; j <= padding.topBottom; j++)
                {
                    atlasPixels[(targY - j)][targX - i]                 = atlasPixels[targY][targX];
                    atlasPixels[(targY + h - 1 + j)][targX - i]         = atlasPixels[(targY + h - 1)][targX];
                    atlasPixels[(targY + h - 1 + j)][targX + w + i - 1] = atlasPixels[(targY + h - 1)][targX + w - 1];
                    atlasPixels[(targY - j)][targX + w + i - 1]         = atlasPixels[targY][targX + w - 1];
                    yield return(null);
                }
                yield return(null);
            }
            //			Debug.Log("copyandscaledatlas finished too!");
            //HasFinished = true;
            yield break;
        }
Ejemplo n.º 16
0
            internal static void BuildAtlas(
                AtlasPackingResult packedAtlasRects,
                List <MB_TexSet> distinctMaterialTextures,
                int propIdx,
                int atlasSizeX, int atlasSizeY,
                Mesh m,
                List <Material> generatedMats,
                ShaderTextureProperty property,
                MB3_TextureCombinerPipeline.TexturePipelineData data,
                MB3_TextureCombiner combiner,
                MB2_EditorMethodsInterface textureEditorMethods,
                MB2_LogLevel LOG_LEVEL)
            {
                // Collect vertices and quads for mesh that we will use for the atlas.
                Debug.Assert(generatedMats.Count == 0, "Previous mats should have been destroyed");
                generatedMats.Clear();
                List <Vector3> vs  = new List <Vector3>();
                List <Vector2> uvs = new List <Vector2>();

                // One submesh and material per texture that we are packing
                List <int>[] ts = new List <int> [distinctMaterialTextures.Count];
                for (int i = 0; i < ts.Length; i++)
                {
                    ts[i] = new List <int>();
                }

                MeshBakerMaterialTexture.readyToBuildAtlases = true;
                GC.Collect();
                MB3_TextureCombinerPackerRoot.CreateTemporaryTexturesForAtlas(data.distinctMaterialTextures, combiner, propIdx, data);

                Rect[] uvRects = packedAtlasRects.rects;
                for (int texSetIdx = 0; texSetIdx < distinctMaterialTextures.Count; texSetIdx++)
                {
                    MB_TexSet texSet = distinctMaterialTextures[texSetIdx];
                    MeshBakerMaterialTexture matTex = texSet.ts[propIdx];

                    if (LOG_LEVEL >= MB2_LogLevel.trace)
                    {
                        Debug.Log(string.Format("Adding texture {0} to atlas {1} for texSet {2} srcMat {3}", matTex.GetTexName(), property.name, texSetIdx, texSet.matsAndGOs.mats[0].GetMaterialName()));
                    }
                    Rect      r  = uvRects[texSetIdx];
                    Texture2D t  = matTex.GetTexture2D();
                    int       x  = Mathf.RoundToInt(r.x * atlasSizeX);
                    int       y  = Mathf.RoundToInt(r.y * atlasSizeY);
                    int       ww = Mathf.RoundToInt(r.width * atlasSizeX);
                    int       hh = Mathf.RoundToInt(r.height * atlasSizeY);
                    r = new Rect(x, y, ww, hh);
                    if (ww == 0 || hh == 0)
                    {
                        Debug.LogError("Image in atlas has no height or width " + r);
                    }
                    DRect samplingRect = texSet.ts[propIdx].GetEncapsulatingSamplingRect();
                    Debug.Assert(!texSet.ts[propIdx].isNull, string.Format("Adding texture {0} to atlas {1} for texSet {2} srcMat {3}", matTex.GetTexName(), property.name, texSetIdx, texSet.matsAndGOs.mats[0].GetMaterialName()));

                    AtlasPadding padding = packedAtlasRects.padding[texSetIdx];
                    AddNineSlicedRect(r, padding.leftRight, padding.topBottom, samplingRect.GetRect(), vs, uvs, ts[texSetIdx], t.width, t.height, t.name);

                    Material mt = new Material(Shader.Find("MeshBaker/Unlit/UnlitWithAlpha"));

                    bool isSavingAsANormalMapAssetThatWillBeImported = property.isNormalMap && data._saveAtlasesAsAssets;
                    MBVersion.PipelineType pipelineType = MBVersion.DetectPipeline();
                    if (pipelineType == MBVersion.PipelineType.URP)
                    {
                        ConfigureMaterial_DefaultPipeline(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL);
                        //ConfigureMaterial_URP(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL);
                    }
                    else if (pipelineType == MBVersion.PipelineType.HDRP)
                    {
                        ConfigureMaterial_DefaultPipeline(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL);
                    }
                    else
                    {
                        ConfigureMaterial_DefaultPipeline(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL);
                    }

                    generatedMats.Add(mt);
                }

                // Apply to the mesh
                m.Clear();
                m.vertices     = vs.ToArray();
                m.uv           = uvs.ToArray();
                m.subMeshCount = ts.Length;
                for (int i = 0; i < m.subMeshCount; i++)
                {
                    m.SetIndices(ts[i].ToArray(), MeshTopology.Triangles, i);
                }
                MeshBakerMaterialTexture.readyToBuildAtlases = false;
            }