Exemple #1
0
        IEnumerator __RunTexturePackerOnly(CombineTexturesIntoAtlasesCoroutineResult result, MB3_TextureCombinerPipeline.TexturePipelineData data, bool splitAtlasWhenPackingIfTooBig, MB2_EditorMethodsInterface textureEditorMethods, List <AtlasPackingResult> packingResult)
        {
            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("__RunTexturePacker texture properties in shader:" + data.texPropertyNames.Count + " objsToMesh:" + data.allObjsToMesh.Count + " _fixOutOfBoundsUVs:" + data._fixOutOfBoundsUVs);
            }
            List <GameObject> usedObjsToMesh = new List <GameObject>();

            yield return(MB3_TextureCombinerPipeline.__Step1_CollectDistinctMatTexturesAndUsedObjects(null, result, data, this, textureEditorMethods, usedObjsToMesh, LOG_LEVEL));

            if (!result.success)
            {
                yield break;
            }

            data.allTexturesAreNullAndSameColor = new MB3_TextureCombinerPipeline.CreateAtlasForProperty[data.texPropertyNames.Count];
            yield return(MB3_TextureCombinerPipeline.CalculateIdealSizesForTexturesInAtlasAndPadding(null, result, data, this, textureEditorMethods, LOG_LEVEL));

            if (!result.success)
            {
                yield break;
            }

            MB_ITextureCombinerPacker texturePaker = MB3_TextureCombinerPipeline.CreatePacker(data.OnlyOneTextureInAtlasReuseTextures(), data._packingAlgorithm);

            //    run the texture packer only
            AtlasPackingResult[] aprs = MB3_TextureCombinerPipeline.RunTexturePackerOnly(data, splitAtlasWhenPackingIfTooBig, texturePaker, LOG_LEVEL);
            for (int i = 0; i < aprs.Length; i++)
            {
                packingResult.Add(aprs[i]);
            }
        }
        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));
        }
        //texPropertyNames is the list of texture properties in the resultMaterial
        //allowedMaterialsFilter is a list of materials. Objects without any of these materials will be ignored.
        //						 this is used by the multiple materials filter
        //textureEditorMethods encapsulates editor only functionality such as saving assets and tracking texture assets whos format was changed. Is null if using at runtime.
        IEnumerator __CombineTexturesIntoAtlases(ProgressUpdateDelegate progressInfo, CombineTexturesIntoAtlasesCoroutineResult result, MB_AtlasesAndRects resultAtlasesAndRects, MB3_TextureCombinerPipeline.TexturePipelineData data, MB2_EditorMethodsInterface textureEditorMethods)
        {
            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("__CombineTexturesIntoAtlases texture properties in shader:" + data.texPropertyNames.Count + " objsToMesh:" + data.allObjsToMesh.Count + " _fixOutOfBoundsUVs:" + data._fixOutOfBoundsUVs);
            }

            if (progressInfo != null)
            {
                progressInfo("Collecting textures ", .01f);
            }

            MB3_TextureCombinerPipeline pipeline = new MB3_TextureCombinerPipeline();

            /*
             * each atlas (maintex, bump, spec etc...) will have distinctMaterialTextures.Count images in it.
             * each distinctMaterialTextures record is a set of textures, one for each atlas. And a list of materials
             * that use that distinct set of textures.
             */
            List <GameObject> usedObjsToMesh = new List <GameObject>();

            yield return(pipeline.__Step1_CollectDistinctMatTexturesAndUsedObjects(progressInfo, result, data, this, textureEditorMethods, usedObjsToMesh, LOG_LEVEL));

            if (!result.success)
            {
                yield break;
            }

            //Textures in each material (_mainTex, Bump, Spec ect...) must be same size
            //Calculate the best sized to use. Takes into account tiling
            //if only one texture in atlas re-uses original sizes
            yield return(pipeline.CalculateIdealSizesForTexturesInAtlasAndPadding(progressInfo, result, data, this, textureEditorMethods, LOG_LEVEL));

            if (!result.success)
            {
                yield break;
            }

            //buildAndSaveAtlases
            StringBuilder             report       = pipeline.GenerateReport(data);
            MB_ITextureCombinerPacker texturePaker = pipeline.CreatePacker(data.OnlyOneTextureInAtlasReuseTextures(), data._packingAlgorithm);

            if (!texturePaker.Validate(data))
            {
                result.success = false;
                yield break;
            }

            yield return(texturePaker.ConvertTexturesToReadableFormats(progressInfo, result, data, this, textureEditorMethods, LOG_LEVEL));

            if (!result.success)
            {
                yield break;
            }

            AtlasPackingResult[] uvRects = texturePaker.CalculateAtlasRectangles(data, false, LOG_LEVEL);
            Debug.Assert(uvRects.Length == 1, "Error, there should not be more than one packing here.");
            yield return(pipeline.__Step3_BuildAndSaveAtlasesAndStoreResults(result, progressInfo, data, this, texturePaker, uvRects[0], textureEditorMethods, resultAtlasesAndRects, report, LOG_LEVEL));
        }
Exemple #4
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);
        }
Exemple #5
0
        // used by Unity texture packer to handle tiled textures.
        // may create a new texture that has the correct tiling to handle fix out of bounds UVs
        internal static Texture2D GetAdjustedForScaleAndOffset2(string propertyName, MeshBakerMaterialTexture source, Vector2 obUVoffset, Vector2 obUVscale, MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner, MB2_LogLevel LOG_LEVEL)
        {
            Texture2D sourceTex = source.GetTexture2D();

            if (source.matTilingRect.x == 0f && source.matTilingRect.y == 0f && source.matTilingRect.width == 1f && source.matTilingRect.height == 1f)
            {
                if (data._fixOutOfBoundsUVs)
                {
                    if (obUVoffset.x == 0f && obUVoffset.y == 0f && obUVscale.x == 1f && obUVscale.y == 1f)
                    {
                        return(sourceTex); //no adjustment necessary
                    }
                }
                else
                {
                    return(sourceTex); //no adjustment necessary
                }
            }
            Vector2 dim = MB3_TextureCombinerPipeline.GetAdjustedForScaleAndOffset2Dimensions(source, obUVoffset, obUVscale, data, LOG_LEVEL);

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.LogWarning("GetAdjustedForScaleAndOffset2: " + sourceTex + " " + obUVoffset + " " + obUVscale);
            }
            float newWidth  = dim.x;
            float newHeight = dim.y;
            float scx       = (float)source.matTilingRect.width;
            float scy       = (float)source.matTilingRect.height;
            float ox        = (float)source.matTilingRect.x;
            float oy        = (float)source.matTilingRect.y;

            if (data._fixOutOfBoundsUVs)
            {
                scx *= obUVscale.x;
                scy *= obUVscale.y;
                ox   = (float)(source.matTilingRect.x * obUVscale.x + obUVoffset.x);
                oy   = (float)(source.matTilingRect.y * obUVscale.y + obUVoffset.y);
            }
            Texture2D newTex = combiner._createTemporaryTexture(propertyName, (int)newWidth, (int)newHeight, TextureFormat.ARGB32, true);

            for (int i = 0; i < newTex.width; i++)
            {
                for (int j = 0; j < newTex.height; j++)
                {
                    float u = i / newWidth * scx + ox;
                    float v = j / newHeight * scy + oy;
                    newTex.SetPixel(i, j, sourceTex.GetPixelBilinear(u, v));
                }
            }
            newTex.Apply();
            return(newTex);
        }
        internal static void SaveAtlasAndConfigureResultMaterial(MB3_TextureCombinerPipeline.TexturePipelineData data, MB2_EditorMethodsInterface textureEditorMethods, Texture2D atlas, ShaderTextureProperty property, int propIdx)
        {
            bool doAnySrcMatsHaveProperty = MB3_TextureCombinerPipeline._DoAnySrcMatsHaveProperty(propIdx, data.allTexturesAreNullAndSameColor);

            if (data._saveAtlasesAsAssets && textureEditorMethods != null)
            {
                textureEditorMethods.SaveAtlasToAssetDatabase(atlas, property, propIdx, doAnySrcMatsHaveProperty, data.resultMaterial);
            }
            else
            {
                if (doAnySrcMatsHaveProperty)
                {
                    data.resultMaterial.SetTexture(property.name, atlas);
                }
            }

            if (doAnySrcMatsHaveProperty)
            {
                data.resultMaterial.SetTextureOffset(property.name, Vector2.zero);
                data.resultMaterial.SetTextureScale(property.name, Vector2.one);
            }
        }
Exemple #7
0
        //texPropertyNames is the list of texture properties in the resultMaterial
        //allowedMaterialsFilter is a list of materials. Objects without any of these materials will be ignored.
        //						 this is used by the multiple materials filter
        //textureEditorMethods encapsulates editor only functionality such as saving assets and tracking texture assets whos format was changed. Is null if using at runtime.
        IEnumerator __CombineTexturesIntoAtlases(ProgressUpdateDelegate progressInfo, CombineTexturesIntoAtlasesCoroutineResult result, MB_AtlasesAndRects resultAtlasesAndRects, MB3_TextureCombinerPipeline.TexturePipelineData data, bool splitAtlasWhenPackingIfTooBig, MB2_EditorMethodsInterface textureEditorMethods)
        {
            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("__CombineTexturesIntoAtlases texture properties in shader:" + data.texPropertyNames.Count + " objsToMesh:" + data.allObjsToMesh.Count + " _fixOutOfBoundsUVs:" + data._fixOutOfBoundsUVs);
            }

            if (progressInfo != null)
            {
                progressInfo("Collecting textures ", .01f);
            }

            /*
             *          each atlas (maintex, bump, spec etc...) will have distinctMaterialTextures.Count images in it.
             *          each distinctMaterialTextures record is a set of textures, one for each atlas. And a list of materials
             *          that use that distinct set of textures.
             */
            List <GameObject> usedObjsToMesh = new List <GameObject>();

            yield return(MB3_TextureCombinerPipeline.__Step1_CollectDistinctMatTexturesAndUsedObjects(progressInfo, result, data, this, textureEditorMethods, usedObjsToMesh, LOG_LEVEL));

            if (!result.success)
            {
                yield break;
            }

            if (MB3_MeshCombiner.EVAL_VERSION)
            {
                bool usesAllowedShaders = true;
                for (int i = 0; i < data.distinctMaterialTextures.Count; i++)
                {
                    for (int j = 0; j < data.distinctMaterialTextures[i].matsAndGOs.mats.Count; j++)
                    {
                        if (!data.distinctMaterialTextures[i].matsAndGOs.mats[j].mat.shader.name.EndsWith("Diffuse") &&
                            !data.distinctMaterialTextures[i].matsAndGOs.mats[j].mat.shader.name.EndsWith("Bumped Diffuse"))
                        {
                            Debug.LogError("The free version of Mesh Baker only works with Diffuse and Bumped Diffuse Shaders. The full version can be used with any shader. Material " + data.distinctMaterialTextures[i].matsAndGOs.mats[j].mat.name + " uses shader " + data.distinctMaterialTextures[i].matsAndGOs.mats[j].mat.shader.name);
                            usesAllowedShaders = false;
                        }
                    }
                }
                if (!usesAllowedShaders)
                {
                    result.success = false;
                    yield break;
                }
            }

            //Textures in each material (_mainTex, Bump, Spec ect...) must be same size
            //Calculate the best sized to use. Takes into account tiling
            //if only one texture in atlas re-uses original sizes
            yield return(MB3_TextureCombinerPipeline.CalculateIdealSizesForTexturesInAtlasAndPadding(progressInfo, result, data, this, textureEditorMethods, LOG_LEVEL));

            if (!result.success)
            {
                yield break;
            }

            //buildAndSaveAtlases
            StringBuilder             report       = MB3_TextureCombinerPipeline.GenerateReport(data);
            MB_ITextureCombinerPacker texturePaker = MB3_TextureCombinerPipeline.CreatePacker(data.OnlyOneTextureInAtlasReuseTextures(), data._packingAlgorithm);

            yield return(texturePaker.ConvertTexturesToReadableFormats(progressInfo, result, data, this, textureEditorMethods, LOG_LEVEL));

            if (!result.success)
            {
                yield break;
            }

            AtlasPackingResult[] uvRects = texturePaker.CalculateAtlasRectangles(data, splitAtlasWhenPackingIfTooBig, LOG_LEVEL);
            yield return(MB3_TextureCombinerPipeline.__Step3_BuildAndSaveAtlasesAndStoreResults(result, progressInfo, data, this, texturePaker, uvRects[0], textureEditorMethods, resultAtlasesAndRects, report, LOG_LEVEL));
        }
Exemple #8
0
        IEnumerator _CombineTexturesIntoAtlases(ProgressUpdateDelegate progressInfo, CombineTexturesIntoAtlasesCoroutineResult result, MB_AtlasesAndRects resultAtlasesAndRects, Material resultMaterial, List <GameObject> objsToMesh, List <Material> allowedMaterialsFilter, MB2_EditorMethodsInterface textureEditorMethods, List <AtlasPackingResult> atlasPackingResult, bool onlyPackRects, bool splitAtlasWhenPackingIfTooBig)
        {
            System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
            sw.Start();
            try
            {
                _temporaryTextures.Clear();
                MeshBakerMaterialTexture.readyToBuildAtlases = false;

                if (textureEditorMethods != null)
                {
                    textureEditorMethods.Clear();
                    textureEditorMethods.OnPreTextureBake();
                }

                if (objsToMesh == null || objsToMesh.Count == 0)
                {
                    Debug.LogError("No meshes to combine. Please assign some meshes to combine.");
                    result.success = false;
                    yield break;
                }

                if (_atlasPadding < 0)
                {
                    Debug.LogError("Atlas padding must be zero or greater.");
                    result.success = false;
                    yield break;
                }

                if (_maxTilingBakeSize < 2 || _maxTilingBakeSize > 4096)
                {
                    Debug.LogError("Invalid value for max tiling bake size.");
                    result.success = false;
                    yield break;
                }

                for (int i = 0; i < objsToMesh.Count; i++)
                {
                    Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]);
                    for (int j = 0; j < ms.Length; j++)
                    {
                        Material m = ms[j];
                        if (m == null)
                        {
                            Debug.LogError("Game object " + objsToMesh[i] + " has a null material");
                            result.success = false;
                            yield break;
                        }
                    }
                }

                if (progressInfo != null)
                {
                    progressInfo("Collecting textures for " + objsToMesh.Count + " meshes.", .01f);
                }

                MB3_TextureCombinerPipeline.TexturePipelineData data = LoadPipelineData(resultMaterial, new List <ShaderTextureProperty>(), objsToMesh, allowedMaterialsFilter, new List <MB_TexSet>());
                if (!MB3_TextureCombinerPipeline._CollectPropertyNames(data, LOG_LEVEL))
                {
                    result.success = false;
                    yield break;
                }

                if (_fixOutOfBoundsUVs && (_packingAlgorithm == MB2_PackingAlgorithmEnum.MeshBakerTexturePacker_Horizontal ||
                                           _packingAlgorithm == MB2_PackingAlgorithmEnum.MeshBakerTexturePacker_Vertical))
                {
                    if (LOG_LEVEL >= MB2_LogLevel.info)
                    {
                        Debug.LogWarning("'Consider Mesh UVs' is enabled but packing algorithm is MeshBakerTexturePacker_Horizontal or MeshBakerTexturePacker_Vertical. It is recommended to use these packers without using 'Consider Mesh UVs'");
                    }
                }

                data.nonTexturePropertyBlender.LoadTextureBlendersIfNeeded(data.resultMaterial);

                if (onlyPackRects)
                {
                    yield return(__RunTexturePackerOnly(result, data, splitAtlasWhenPackingIfTooBig, textureEditorMethods, atlasPackingResult));
                }
                else
                {
                    yield return(__CombineTexturesIntoAtlases(progressInfo, result, resultAtlasesAndRects, data, splitAtlasWhenPackingIfTooBig, textureEditorMethods));
                }

                /*
                 *      } catch (MissingReferenceException mrex){
                 *              Debug.LogError("Creating atlases failed a MissingReferenceException was thrown. This is normally only happens when trying to create very large atlases and Unity is running out of Memory. Try changing the 'Texture Packer' to a different option, it may work with an alternate packer. This error is sometimes intermittant. Try baking again.");
                 *              Debug.LogError(mrex);
                 *      } catch (Exception ex){
                 *              Debug.LogError(ex);*/
            }
            finally
            {
                _destroyAllTemporaryTextures();
                _restoreProceduralMaterials();
                if (textureEditorMethods != null)
                {
                    textureEditorMethods.RestoreReadFlagsAndFormats(progressInfo);
                    textureEditorMethods.OnPostTextureBake();
                }
                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("===== Done creating atlases for " + resultMaterial + " Total time to create atlases " + sw.Elapsed.ToString());
                }
            }
            //result.success = success;
        }
Exemple #9
0
        public override IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                                  MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                                  AtlasPackingResult packedAtlasRects,
                                                  Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                                  MB2_LogLevel LOG_LEVEL)
        {
            Debug.Assert(!data.OnlyOneTextureInAtlasReuseTextures());
            Rect[] uvRects = packedAtlasRects.rects;

            long estArea    = 0;
            int  atlasSizeX = 1;
            int  atlasSizeY = 1;

            uvRects = null;
            for (int propIdx = 0; propIdx < data.numAtlases; propIdx++)
            {
                //-----------------------
                ShaderTextureProperty prop  = data.texPropertyNames[propIdx];
                Texture2D             atlas = null;
                if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(propIdx, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                {
                    atlas = null;
                }
                else
                {
                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.LogWarning("Beginning loop " + propIdx + " num temporary textures " + combiner._getNumTemporaryTextures());
                    }
                    MB3_TextureCombinerPackerRoot.CreateTemporaryTexturesForAtlas(data.distinctMaterialTextures, combiner, propIdx, data);
                    Texture2D[] texToPack = new Texture2D[data.distinctMaterialTextures.Count];
                    for (int texSetIdx = 0; texSetIdx < data.distinctMaterialTextures.Count; texSetIdx++)
                    {
                        MB_TexSet txs     = data.distinctMaterialTextures[texSetIdx];
                        int       tWidth  = txs.idealWidth;
                        int       tHeight = txs.idealHeight;
                        Texture2D tx      = txs.ts[propIdx].GetTexture2D();
                        if (progressInfo != null)
                        {
                            progressInfo("Adjusting for scale and offset " + tx, .01f);
                        }

                        if (textureEditorMethods != null)
                        {
                            textureEditorMethods.SetReadWriteFlag(tx, true, true);
                        }

                        tx = GetAdjustedForScaleAndOffset2(prop.name, txs.ts[propIdx], txs.obUVoffset, txs.obUVscale, data, combiner, LOG_LEVEL);
                        //create a resized copy if necessary
                        if (tx.width != tWidth || tx.height != tHeight)
                        {
                            if (progressInfo != null)
                            {
                                progressInfo("Resizing texture '" + tx + "'", .01f);
                            }
                            if (LOG_LEVEL >= MB2_LogLevel.debug)
                            {
                                Debug.LogWarning("Copying and resizing texture " + prop.name + " from " + tx.width + "x" + tx.height + " to " + tWidth + "x" + tHeight);
                            }
                            tx = combiner._resizeTexture(prop.name, (Texture2D)tx, tWidth, tHeight);
                        }

                        estArea += tx.width * tx.height;
                        if (data._considerNonTextureProperties)
                        {
                            //combine the tintColor with the texture
                            tx = combiner._createTextureCopy(prop.name, tx);
                            data.nonTexturePropertyBlender.TintTextureWithTextureCombiner(tx, data.distinctMaterialTextures[texSetIdx], prop);
                        }

                        texToPack[texSetIdx] = tx;
                    }

                    if (textureEditorMethods != null)
                    {
                        textureEditorMethods.CheckBuildSettings(estArea);
                    }

                    if (Math.Sqrt(estArea) > 3500f)
                    {
                        if (LOG_LEVEL >= MB2_LogLevel.warn)
                        {
                            Debug.LogWarning("The maximum possible atlas size is 4096. Textures may be shrunk");
                        }
                    }

                    atlas = new Texture2D(1, 1, TextureFormat.ARGB32, true);
                    if (progressInfo != null)
                    {
                        progressInfo("Packing texture atlas " + prop.name, .25f);
                    }
                    if (propIdx == 0)
                    {
                        if (progressInfo != null)
                        {
                            progressInfo("Estimated min size of atlases: " + Math.Sqrt(estArea).ToString("F0"), .1f);
                        }
                        if (LOG_LEVEL >= MB2_LogLevel.info)
                        {
                            Debug.Log("Estimated atlas minimum size:" + Math.Sqrt(estArea).ToString("F0"));
                        }
                        int maxAtlasSize = 4096;
                        uvRects = atlas.PackTextures(texToPack, data._atlasPadding, maxAtlasSize, false);
                        if (LOG_LEVEL >= MB2_LogLevel.info)
                        {
                            Debug.Log("After pack textures atlas size " + atlas.width + " " + atlas.height);
                        }
                        atlasSizeX = atlas.width;
                        atlasSizeY = atlas.height;
                        atlas.Apply();
                    }
                    else
                    {
                        if (progressInfo != null)
                        {
                            progressInfo("Copying Textures Into: " + prop.name, .1f);
                        }
                        atlas = _copyTexturesIntoAtlas(texToPack, data._atlasPadding, uvRects, atlasSizeX, atlasSizeY, combiner);
                    }
                }

                atlases[propIdx] = atlas;
                //----------------------

                if (data._saveAtlasesAsAssets && textureEditorMethods != null)
                {
                    textureEditorMethods.SaveAtlasToAssetDatabase(atlases[propIdx], prop, propIdx, data.resultMaterial);
                }
                data.resultMaterial.SetTextureOffset(prop.name, Vector2.zero);
                data.resultMaterial.SetTextureScale(prop.name, Vector2.one);
                combiner._destroyTemporaryTextures(prop.name);
                GC.Collect();
            }
            packedAtlasRects.rects = uvRects;
            yield break;
        }
        public IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                         MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                         AtlasPackingResult packedAtlasRects,
                                         Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                         MB2_LogLevel LOG_LEVEL)
        {
            Rect[] uvRects = packedAtlasRects.rects;
            if (uvRects.Length == 1)
            {
                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("Only one image per atlas. Will re-use original texture");
                }
                for (int i = 0; i < data.numAtlases; i++)
                {
                    MeshBakerMaterialTexture dmt = data.distinctMaterialTextures[0].ts[i];
                    atlases[i] = dmt.GetTexture2D();
                    data.resultMaterial.SetTexture(data.texPropertyNames[i].name, atlases[i]);
                    data.resultMaterial.SetTextureScale(data.texPropertyNames[i].name, dmt.matTilingRect.size);
                    data.resultMaterial.SetTextureOffset(data.texPropertyNames[i].name, dmt.matTilingRect.min);
                }
            }
            else
            {
                int atlasSizeX = packedAtlasRects.atlasX;
                int atlasSizeY = packedAtlasRects.atlasY;
                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY);
                }
                for (int propIdx = 0; propIdx < data.numAtlases; propIdx++)
                {
                    Texture2D atlas = null;
                    if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(propIdx, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                    {
                        atlas = null;
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("=== Not creating atlas for " + data.texPropertyNames[propIdx].name + " because textures are null and default value parameters are the same.");
                        }
                    }
                    else
                    {
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("=== Creating atlas for " + data.texPropertyNames[propIdx].name);
                        }
                        GC.Collect();

                        //use a jagged array because it is much more efficient in memory
                        Color[][] atlasPixels = new Color[atlasSizeY][];
                        for (int j = 0; j < atlasPixels.Length; j++)
                        {
                            atlasPixels[j] = new Color[atlasSizeX];
                        }
                        bool isNormalMap = false;
                        if (data.texPropertyNames[propIdx].isNormalMap)
                        {
                            isNormalMap = true;
                        }

                        for (int texSetIdx = 0; texSetIdx < data.distinctMaterialTextures.Count; texSetIdx++)
                        {
                            string s = "Creating Atlas '" + data.texPropertyNames[propIdx].name + "' texture " + data.distinctMaterialTextures[texSetIdx];
                            if (progressInfo != null)
                            {
                                progressInfo(s, .01f);
                            }
                            MB_TexSet texSet = data.distinctMaterialTextures[texSetIdx];
                            if (LOG_LEVEL >= MB2_LogLevel.trace)
                            {
                                Debug.Log(string.Format("Adding texture {0} to atlas {1}", texSet.ts[propIdx].GetTexture2D() == null ? "null" : texSet.ts[propIdx].GetTexName(), data.texPropertyNames[propIdx]));
                            }
                            Rect      r  = uvRects[texSetIdx];
                            Texture2D t  = texSet.ts[propIdx].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);
                            if (ww == 0 || hh == 0)
                            {
                                Debug.LogError("Image in atlas has no height or width " + r);
                            }
                            if (progressInfo != null)
                            {
                                progressInfo(s + " set ReadWrite flag", .01f);
                            }
                            if (textureEditorMethods != null)
                            {
                                textureEditorMethods.SetReadWriteFlag(t, true, true);
                            }
                            if (progressInfo != null)
                            {
                                progressInfo(s + "Copying to atlas: '" + texSet.ts[propIdx].GetTexName() + "'", .02f);
                            }
                            DRect samplingRect = texSet.ts[propIdx].encapsulatingSamplingRect;
                            yield return(CopyScaledAndTiledToAtlas(texSet.ts[propIdx], texSet, data.texPropertyNames[propIdx], samplingRect, x, y, ww, hh, packedAtlasRects.padding[texSetIdx], atlasPixels, isNormalMap, data, combiner, progressInfo, LOG_LEVEL));
                            //							Debug.Log("after copyScaledAndTiledAtlas");
                        }
                        yield return(data.numAtlases);

                        if (progressInfo != null)
                        {
                            progressInfo("Applying changes to atlas: '" + data.texPropertyNames[propIdx].name + "'", .03f);
                        }
                        atlas = new Texture2D(atlasSizeX, atlasSizeY, TextureFormat.ARGB32, true);
                        for (int j = 0; j < atlasPixels.Length; j++)
                        {
                            atlas.SetPixels(0, j, atlasSizeX, 1, atlasPixels[j]);
                        }
                        atlas.Apply();
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Saving atlas " + data.texPropertyNames[propIdx].name + " w=" + atlas.width + " h=" + atlas.height);
                        }
                    }
                    atlases[propIdx] = atlas;
                    if (progressInfo != null)
                    {
                        progressInfo("Saving atlas: '" + data.texPropertyNames[propIdx].name + "'", .04f);
                    }
                    System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                    sw.Start();

                    if (data._saveAtlasesAsAssets && textureEditorMethods != null)
                    {
                        textureEditorMethods.SaveAtlasToAssetDatabase(atlases[propIdx], data.texPropertyNames[propIdx], propIdx, data.resultMaterial);
                    }
                    else
                    {
                        data.resultMaterial.SetTexture(data.texPropertyNames[propIdx].name, atlases[propIdx]);
                    }
                    data.resultMaterial.SetTextureOffset(data.texPropertyNames[propIdx].name, Vector2.zero);
                    data.resultMaterial.SetTextureScale(data.texPropertyNames[propIdx].name, Vector2.one);
                    combiner._destroyTemporaryTextures(); // need to save atlases before doing this
                }
            }
            //data.rectsInAtlas = uvRects;
            //			Debug.Log("finished!");
            yield break;
        }
        public IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                         MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                         AtlasPackingResult packedAtlasRects,
                                         Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                         MB2_LogLevel LOG_LEVEL)
        {
            Rect[] uvRects = packedAtlasRects.rects;
            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");
                }
                uvRects    = new Rect[1];
                uvRects[0] = new Rect(0f, 0f, 1f, 1f);
                for (int i = 0; i < data.numAtlases; i++)
                {
                    MeshBakerMaterialTexture dmt = data.distinctMaterialTextures[0].ts[i];
                    atlases[i] = dmt.GetTexture2D();
                    data.resultMaterial.SetTexture(data.texPropertyNames[i].name, atlases[i]);
                    data.resultMaterial.SetTextureScale(data.texPropertyNames[i].name, dmt.matTilingRect.size);
                    data.resultMaterial.SetTextureOffset(data.texPropertyNames[i].name, dmt.matTilingRect.min);
                }
            }
            else
            {
                long estArea    = 0;
                int  atlasSizeX = 1;
                int  atlasSizeY = 1;
                uvRects = null;
                for (int i = 0; i < data.numAtlases; i++)
                { //i is an atlas "MainTex", "BumpMap" etc...
                  //-----------------------
                    Texture2D atlas = null;
                    if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(i, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                    {
                        atlas = null;
                    }
                    else
                    {
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.LogWarning("Beginning loop " + i + " num temporary textures " + combiner._temporaryTextures.Count);
                        }
                        for (int j = 0; j < data.distinctMaterialTextures.Count; j++)
                        { //j is a distinct set of textures one for each of "MainTex", "BumpMap" etc...
                            MB_TexSet txs = data.distinctMaterialTextures[j];

                            int tWidth  = txs.idealWidth;
                            int tHeight = txs.idealHeight;

                            Texture2D tx = txs.ts[i].GetTexture2D();
                            if (tx == null)
                            {
                                tx = txs.ts[i].t = combiner._createTemporaryTexture(tWidth, tHeight, TextureFormat.ARGB32, true);
                                if (data._considerNonTextureProperties && data.nonTexturePropertyBlender != null)
                                {
                                    Color col = data.nonTexturePropertyBlender.GetColorIfNoTexture(txs.matsAndGOs.mats[0].mat, data.texPropertyNames[i]);
                                    if (LOG_LEVEL >= MB2_LogLevel.trace)
                                    {
                                        Debug.Log("Setting texture to solid color " + col);
                                    }
                                    MB_Utility.setSolidColor(tx, col);
                                }
                                else
                                {
                                    Color col = MB3_TextureCombinerNonTextureProperties.GetColorIfNoTexture(data.texPropertyNames[i]);
                                    MB_Utility.setSolidColor(tx, col);
                                }
                            }

                            if (progressInfo != null)
                            {
                                progressInfo("Adjusting for scale and offset " + tx, .01f);
                            }
                            if (textureEditorMethods != null)
                            {
                                textureEditorMethods.SetReadWriteFlag(tx, true, true);
                            }
                            tx = GetAdjustedForScaleAndOffset2(txs.ts[i], txs.obUVoffset, txs.obUVscale, data, combiner, LOG_LEVEL);

                            //create a resized copy if necessary
                            if (tx.width != tWidth || tx.height != tHeight)
                            {
                                if (progressInfo != null)
                                {
                                    progressInfo("Resizing texture '" + tx + "'", .01f);
                                }
                                if (LOG_LEVEL >= MB2_LogLevel.debug)
                                {
                                    Debug.LogWarning("Copying and resizing texture " + data.texPropertyNames[i].name + " from " + tx.width + "x" + tx.height + " to " + tWidth + "x" + tHeight);
                                }
                                tx = combiner._resizeTexture((Texture2D)tx, tWidth, tHeight);
                            }

                            txs.ts[i].t = tx;
                        }

                        Texture2D[] texToPack = new Texture2D[data.distinctMaterialTextures.Count];
                        for (int j = 0; j < data.distinctMaterialTextures.Count; j++)
                        {
                            Texture2D tx = data.distinctMaterialTextures[j].ts[i].GetTexture2D();
                            estArea += tx.width * tx.height;
                            if (data._considerNonTextureProperties)
                            {
                                //combine the tintColor with the texture
                                tx = combiner._createTextureCopy(tx);
                                data.nonTexturePropertyBlender.TintTextureWithTextureCombiner(tx, data.distinctMaterialTextures[j], data.texPropertyNames[i]);
                            }
                            texToPack[j] = tx;
                        }

                        if (textureEditorMethods != null)
                        {
                            textureEditorMethods.CheckBuildSettings(estArea);
                        }

                        if (Math.Sqrt(estArea) > 3500f)
                        {
                            if (LOG_LEVEL >= MB2_LogLevel.warn)
                            {
                                Debug.LogWarning("The maximum possible atlas size is 4096. Textures may be shrunk");
                            }
                        }
                        atlas = new Texture2D(1, 1, TextureFormat.ARGB32, true);
                        if (progressInfo != null)
                        {
                            progressInfo("Packing texture atlas " + data.texPropertyNames[i].name, .25f);
                        }
                        if (i == 0)
                        {
                            if (progressInfo != null)
                            {
                                progressInfo("Estimated min size of atlases: " + Math.Sqrt(estArea).ToString("F0"), .1f);
                            }
                            if (LOG_LEVEL >= MB2_LogLevel.info)
                            {
                                Debug.Log("Estimated atlas minimum size:" + Math.Sqrt(estArea).ToString("F0"));
                            }

                            if (data.distinctMaterialTextures.Count == 1 && data._fixOutOfBoundsUVs == false)
                            { //don't want to force power of 2 so tiling will still work
                                uvRects = new Rect[1] {
                                    new Rect(0f, 0f, 1f, 1f)
                                };
                                atlas = _copyTexturesIntoAtlas(texToPack, data._atlasPadding, uvRects, texToPack[0].width, texToPack[0].height, combiner);
                            }
                            else
                            {
                                int maxAtlasSize = 4096;
                                uvRects = atlas.PackTextures(texToPack, data._atlasPadding, maxAtlasSize, false);
                            }

                            if (LOG_LEVEL >= MB2_LogLevel.info)
                            {
                                Debug.Log("After pack textures atlas size " + atlas.width + " " + atlas.height);
                            }
                            atlasSizeX = atlas.width;
                            atlasSizeY = atlas.height;
                            atlas.Apply();
                        }
                        else
                        {
                            if (progressInfo != null)
                            {
                                progressInfo("Copying Textures Into: " + data.texPropertyNames[i].name, .1f);
                            }
                            atlas = _copyTexturesIntoAtlas(texToPack, data._atlasPadding, uvRects, atlasSizeX, atlasSizeY, combiner);
                        }
                    }
                    atlases[i] = atlas;
                    //----------------------

                    if (data._saveAtlasesAsAssets && textureEditorMethods != null)
                    {
                        textureEditorMethods.SaveAtlasToAssetDatabase(atlases[i], data.texPropertyNames[i], i, data.resultMaterial);
                    }
                    data.resultMaterial.SetTextureOffset(data.texPropertyNames[i].name, Vector2.zero);
                    data.resultMaterial.SetTextureScale(data.texPropertyNames[i].name, Vector2.one);

                    combiner._destroyTemporaryTextures(); // need to save atlases before doing this
                    GC.Collect();
                }
            }
            packedAtlasRects.rects = uvRects;
            yield break;
        }
Exemple #12
0
        public IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                         MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                         AtlasPackingResult packedAtlasRects,
                                         Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                         MB2_LogLevel LOG_LEVEL)
        {
            Debug.Assert(!data.OnlyOneTextureInAtlasReuseTextures());
            Rect[] uvRects = packedAtlasRects.rects;

            int atlasSizeX = packedAtlasRects.atlasX;
            int atlasSizeY = packedAtlasRects.atlasY;

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY);
            }

            int layer = data._layerTexturePackerFastV2;

            Debug.Assert(layer >= 0 && layer <= 32);

            //create a game object
            mesh             = new Mesh();
            renderAtlasesGO  = null;
            cameraGameObject = null;
            try
            {
                System.Diagnostics.Stopwatch db_time_MB3_TextureCombinerPackerMeshBakerFastV2_CreateAtlases = new System.Diagnostics.Stopwatch();
                db_time_MB3_TextureCombinerPackerMeshBakerFastV2_CreateAtlases.Start();
                renderAtlasesGO  = new GameObject("MBrenderAtlasesGO");
                cameraGameObject = new GameObject("MBCameraGameObject");
                MB3_AtlasPackerRenderTextureUsingMesh atlasRenderer = new MB3_AtlasPackerRenderTextureUsingMesh();
                OneTimeSetup(atlasRenderer, renderAtlasesGO, cameraGameObject, atlasSizeX, atlasSizeY, data._atlasPadding, layer, LOG_LEVEL);

                if (data._considerNonTextureProperties && LOG_LEVEL >= MB2_LogLevel.warn)
                {
                    Debug.LogWarning("Blend Non-Texture Properties has limited functionality when used with Mesh Baker Texture Packer Fast.");
                }

                List <Material> mats = new List <Material>();
                for (int propIdx = 0; propIdx < data.numAtlases; propIdx++)
                {
                    Texture2D atlas = null;
                    if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(propIdx, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                    {
                        atlas = null;
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Not creating atlas for " + data.texPropertyNames[propIdx].name + " because textures are null and default value parameters are the same.");
                        }
                    }
                    else
                    {
                        if (progressInfo != null)
                        {
                            progressInfo("Creating Atlas '" + data.texPropertyNames[propIdx].name + "'", .01f);
                        }

                        // configure it
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("About to render " + data.texPropertyNames[propIdx].name + " isNormal=" + data.texPropertyNames[propIdx].isNormalMap);
                        }

                        // Create the mesh
                        mats.Clear();

                        MB3_AtlasPackerRenderTextureUsingMesh.MeshAtlas.BuildAtlas(packedAtlasRects, data.distinctMaterialTextures, propIdx, packedAtlasRects.atlasX, packedAtlasRects.atlasY, mesh, mats, data.texPropertyNames[propIdx], data, combiner, textureEditorMethods, LOG_LEVEL);
                        {
                            MeshFilter mf = renderAtlasesGO.GetComponent <MeshFilter>();
                            mf.sharedMesh = mesh;
                            MeshRenderer mrr = renderAtlasesGO.GetComponent <MeshRenderer>();
                            Material[]   mrs = mats.ToArray();
                            mrr.sharedMaterials = mrs;
                        }

                        // Render
                        atlas = atlasRenderer.DoRenderAtlas(cameraGameObject, packedAtlasRects.atlasX, packedAtlasRects.atlasY, data.texPropertyNames[propIdx].isNormalMap, data.texPropertyNames[propIdx]);

                        {
                            for (int i = 0; i < mats.Count; i++)
                            {
                                MB_Utility.Destroy(mats[i]);
                            }
                            mats.Clear();
                        }

                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Saving atlas " + data.texPropertyNames[propIdx].name + " w=" + atlas.width + " h=" + atlas.height + " id=" + atlas.GetInstanceID());
                        }
                    }
                    atlases[propIdx] = atlas;
                    if (progressInfo != null)
                    {
                        progressInfo("Saving atlas: '" + data.texPropertyNames[propIdx].name + "'", .04f);
                    }
                    if (data.resultType == MB2_TextureBakeResults.ResultType.atlas)
                    {
                        MB3_TextureCombinerPackerRoot.SaveAtlasAndConfigureResultMaterial(data, textureEditorMethods, atlases[propIdx], data.texPropertyNames[propIdx], propIdx);
                    }

                    combiner._destroyTemporaryTextures(data.texPropertyNames[propIdx].name); // need to save atlases before doing this
                }

                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.LogFormat("Timing MB3_TextureCombinerPackerMeshBakerFastV2.CreateAtlases={0}",
                                    db_time_MB3_TextureCombinerPackerMeshBakerFastV2_CreateAtlases.ElapsedMilliseconds * .001f);
                }
            }
            catch (Exception ex)
            {
                Debug.LogError(ex.Message + "\n" + ex.StackTrace.ToString());
            }
            finally
            {
                if (renderAtlasesGO != null)
                {
                    MB_Utility.Destroy(renderAtlasesGO);
                }
                if (cameraGameObject != null)
                {
                    MB_Utility.Destroy(cameraGameObject);
                }
                if (mesh != null)
                {
                    MB_Utility.Destroy(mesh);
                }
            }
            yield break;
        }
        public IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                         MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                         AtlasPackingResult packedAtlasRects,
                                         Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                         MB2_LogLevel LOG_LEVEL)
        {
            Debug.Assert(!data.OnlyOneTextureInAtlasReuseTextures());
            Rect[] uvRects = packedAtlasRects.rects;

            int atlasSizeX = packedAtlasRects.atlasX;
            int atlasSizeY = packedAtlasRects.atlasY;

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY);
            }

            //create a game object
            GameObject renderAtlasesGO = null;

            try
            {
                renderAtlasesGO = new GameObject("MBrenderAtlasesGO");
                MB3_AtlasPackerRenderTexture atlasRenderTexture = renderAtlasesGO.AddComponent <MB3_AtlasPackerRenderTexture>();
                renderAtlasesGO.AddComponent <Camera>();
                if (data._considerNonTextureProperties && LOG_LEVEL >= MB2_LogLevel.warn)
                {
                    Debug.LogError("Blend Non-Texture Properties has limited functionality when used with Mesh Baker Texture Packer Fast. If no texture is pesent, then a small texture matching the non-texture property will be created and used in the atlas. But non-texture properties will not be blended into texture.");
                }

                for (int propIdx = 0; propIdx < data.numAtlases; propIdx++)
                {
                    Texture2D atlas = null;
                    if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(propIdx, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                    {
                        atlas = null;
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Not creating atlas for " + data.texPropertyNames[propIdx].name + " because textures are null and default value parameters are the same.");
                        }
                    }
                    else
                    {
                        GC.Collect();

                        MB3_TextureCombinerPackerRoot.CreateTemporaryTexturesForAtlas(data.distinctMaterialTextures, combiner, propIdx, data);

                        if (progressInfo != null)
                        {
                            progressInfo("Creating Atlas '" + data.texPropertyNames[propIdx].name + "'", .01f);
                        }
                        // ===========
                        // configure it
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("About to render " + data.texPropertyNames[propIdx].name + " isNormal=" + data.texPropertyNames[propIdx].isNormalMap);
                        }
                        atlasRenderTexture.LOG_LEVEL                    = LOG_LEVEL;
                        atlasRenderTexture.width                        = atlasSizeX;
                        atlasRenderTexture.height                       = atlasSizeY;
                        atlasRenderTexture.padding                      = data._atlasPadding;
                        atlasRenderTexture.rects                        = uvRects;
                        atlasRenderTexture.textureSets                  = data.distinctMaterialTextures;
                        atlasRenderTexture.indexOfTexSetToRender        = propIdx;
                        atlasRenderTexture.texPropertyName              = data.texPropertyNames[propIdx];
                        atlasRenderTexture.isNormalMap                  = data.texPropertyNames[propIdx].isNormalMap;
                        atlasRenderTexture.fixOutOfBoundsUVs            = data._fixOutOfBoundsUVs;
                        atlasRenderTexture.considerNonTextureProperties = data._considerNonTextureProperties;
                        atlasRenderTexture.resultMaterialTextureBlender = data.nonTexturePropertyBlender;
                        // call render on it
                        atlas = atlasRenderTexture.OnRenderAtlas(combiner);

                        // destroy it
                        // =============
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Saving atlas " + data.texPropertyNames[propIdx].name + " w=" + atlas.width + " h=" + atlas.height + " id=" + atlas.GetInstanceID());
                        }
                    }
                    atlases[propIdx] = atlas;
                    if (progressInfo != null)
                    {
                        progressInfo("Saving atlas: '" + data.texPropertyNames[propIdx].name + "'", .04f);
                    }
                    if (data.resultType == MB2_TextureBakeResults.ResultType.atlas)
                    {
                        MB3_TextureCombinerPackerRoot.SaveAtlasAndConfigureResultMaterial(data, textureEditorMethods, atlases[propIdx], data.texPropertyNames[propIdx], propIdx);
                    }

                    combiner._destroyTemporaryTextures(data.texPropertyNames[propIdx].name); // need to save atlases before doing this
                }
            }
            catch (Exception ex)
            {
                //Debug.LogError(ex);
                Debug.LogError(ex.Message + "\n" + ex.StackTrace.ToString());
            }
            finally
            {
                if (renderAtlasesGO != null)
                {
                    MB_Utility.Destroy(renderAtlasesGO);
                }
            }
            yield break;
        }
        public IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                         MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                         AtlasPackingResult packedAtlasRects,
                                         Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                         MB2_LogLevel LOG_LEVEL)
        {
            Rect[] uvRects = packedAtlasRects.rects;
            if (uvRects.Length == 1)
            {
                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("Only one image per atlas. Will re-use original texture");
                }
                for (int i = 0; i < data.numAtlases; i++)
                {
                    MeshBakerMaterialTexture dmt = data.distinctMaterialTextures[0].ts[i];
                    atlases[i] = dmt.GetTexture2D();
                    data.resultMaterial.SetTexture(data.texPropertyNames[i].name, atlases[i]);
                    data.resultMaterial.SetTextureScale(data.texPropertyNames[i].name, dmt.matTilingRect.size);
                    data.resultMaterial.SetTextureOffset(data.texPropertyNames[i].name, dmt.matTilingRect.min);
                }
            }
            else
            {
                int atlasSizeX = packedAtlasRects.atlasX;
                int atlasSizeY = packedAtlasRects.atlasY;
                if (LOG_LEVEL >= MB2_LogLevel.debug)
                {
                    Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY);
                }

                //create a game object
                GameObject renderAtlasesGO = null;
                try
                {
                    renderAtlasesGO = new GameObject("MBrenderAtlasesGO");
                    MB3_AtlasPackerRenderTexture atlasRenderTexture = renderAtlasesGO.AddComponent <MB3_AtlasPackerRenderTexture>();
                    renderAtlasesGO.AddComponent <Camera>();
                    if (data._considerNonTextureProperties)
                    {
                        if (LOG_LEVEL >= MB2_LogLevel.warn)
                        {
                            Debug.LogWarning("Blend Non-Texture Properties has limited functionality when used with Mesh Baker Texture Packer Fast.");
                        }
                    }
                    for (int i = 0; i < data.numAtlases; i++)
                    {
                        Texture2D atlas = null;
                        if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(i, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                        {
                            atlas = null;
                            if (LOG_LEVEL >= MB2_LogLevel.debug)
                            {
                                Debug.Log("Not creating atlas for " + data.texPropertyNames[i].name + " because textures are null and default value parameters are the same.");
                            }
                        }
                        else
                        {
                            GC.Collect();
                            if (progressInfo != null)
                            {
                                progressInfo("Creating Atlas '" + data.texPropertyNames[i].name + "'", .01f);
                            }
                            // ===========
                            // configure it
                            if (LOG_LEVEL >= MB2_LogLevel.debug)
                            {
                                Debug.Log("About to render " + data.texPropertyNames[i].name + " isNormal=" + data.texPropertyNames[i].isNormalMap);
                            }
                            atlasRenderTexture.LOG_LEVEL                    = LOG_LEVEL;
                            atlasRenderTexture.width                        = atlasSizeX;
                            atlasRenderTexture.height                       = atlasSizeY;
                            atlasRenderTexture.padding                      = data._atlasPadding;
                            atlasRenderTexture.rects                        = uvRects;
                            atlasRenderTexture.textureSets                  = data.distinctMaterialTextures;
                            atlasRenderTexture.indexOfTexSetToRender        = i;
                            atlasRenderTexture.texPropertyName              = data.texPropertyNames[i];
                            atlasRenderTexture.isNormalMap                  = data.texPropertyNames[i].isNormalMap;
                            atlasRenderTexture.fixOutOfBoundsUVs            = data._fixOutOfBoundsUVs;
                            atlasRenderTexture.considerNonTextureProperties = data._considerNonTextureProperties;
                            atlasRenderTexture.resultMaterialTextureBlender = data.nonTexturePropertyBlender;
                            // call render on it
                            atlas = atlasRenderTexture.OnRenderAtlas(combiner);

                            // destroy it
                            // =============
                            if (LOG_LEVEL >= MB2_LogLevel.debug)
                            {
                                Debug.Log("Saving atlas " + data.texPropertyNames[i].name + " w=" + atlas.width + " h=" + atlas.height + " id=" + atlas.GetInstanceID());
                            }
                        }
                        atlases[i] = atlas;
                        if (progressInfo != null)
                        {
                            progressInfo("Saving atlas: '" + data.texPropertyNames[i].name + "'", .04f);
                        }
                        if (data._saveAtlasesAsAssets && textureEditorMethods != null)
                        {
                            textureEditorMethods.SaveAtlasToAssetDatabase(atlases[i], data.texPropertyNames[i], i, data.resultMaterial);
                        }
                        else
                        {
                            data.resultMaterial.SetTexture(data.texPropertyNames[i].name, atlases[i]);
                        }
                        data.resultMaterial.SetTextureOffset(data.texPropertyNames[i].name, Vector2.zero);
                        data.resultMaterial.SetTextureScale(data.texPropertyNames[i].name, Vector2.one);
                        combiner._destroyTemporaryTextures(); // need to save atlases before doing this
                    }
                }
                catch (Exception ex)
                {
                    //Debug.LogError(ex);
                    Debug.LogException(ex);
                }
                finally
                {
                    if (renderAtlasesGO != null)
                    {
                        MB_Utility.Destroy(renderAtlasesGO);
                    }
                }
            }
            yield break;
        }
Exemple #15
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);
        }
Exemple #16
0
        public static IEnumerator _CreateAtlasesCoroutineSingleResultMaterial(int resMatIdx,
                                                                              MB_TextureArrayResultMaterial bakedMatsAndSlicesResMat,
                                                                              MB_MultiMaterialTexArray resMatConfig,
                                                                              List <GameObject> objsToMesh,
                                                                              MB3_TextureCombiner combiner,
                                                                              MB_TextureArrayFormatSet[] textureArrayOutputFormats,
                                                                              MB_MultiMaterialTexArray[] resultMaterialsTexArray,
                                                                              List <ShaderTextureProperty> customShaderProperties,
                                                                              ProgressUpdateDelegate progressInfo,
                                                                              MB3_TextureCombiner.CreateAtlasesCoroutineResult coroutineResult,
                                                                              bool saveAtlasesAsAssets = false,
                                                                              MB2_EditorMethodsInterface editorMethods = null,
                                                                              float maxTimePerFrame = .01f)
        {
            MB2_LogLevel LOG_LEVEL = combiner.LOG_LEVEL;

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("Baking atlases for result material " + resMatIdx + " num slices:" + resMatConfig.slices.Count);
            }
            // Each result material can be one set of slices per textureProperty. Each slice can be an atlas.
            // Create atlases for each slice.
            List <MB3_TextureCombiner.TemporaryTexture> generatedTemporaryAtlases = new List <MB3_TextureCombiner.TemporaryTexture>();

            {
                combiner.saveAtlasesAsAssets = false; // Don't want generated atlas slices to be assets
                List <MB_TexArraySlice> slicesConfig = resMatConfig.slices;
                for (int sliceIdx = 0; sliceIdx < slicesConfig.Count; sliceIdx++)
                {
                    Material resMatToPass = null;
                    List <MB_TexArraySliceRendererMatPair> srcMatAndObjPairs = slicesConfig[sliceIdx].sourceMaterials;

                    if (LOG_LEVEL >= MB2_LogLevel.trace)
                    {
                        Debug.Log(" Baking atlases for result material:" + resMatIdx + " slice:" + sliceIdx);
                    }
                    resMatToPass = resMatConfig.combinedMaterial;
                    combiner.fixOutOfBoundsUVs = slicesConfig[sliceIdx].considerMeshUVs;
                    MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult coroutineResult2 = new MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult();
                    MB_AtlasesAndRects sliceAtlasesAndRectOutput = bakedMatsAndSlicesResMat.slices[sliceIdx];
                    List <Material>    usedMats = new List <Material>();
                    slicesConfig[sliceIdx].GetAllUsedMaterials(usedMats);

                    yield return(combiner.CombineTexturesIntoAtlasesCoroutine(progressInfo, sliceAtlasesAndRectOutput, resMatToPass, slicesConfig[sliceIdx].GetAllUsedRenderers(objsToMesh), usedMats, editorMethods, coroutineResult2, maxTimePerFrame,
                                                                              onlyPackRects: false, splitAtlasWhenPackingIfTooBig: false));

                    coroutineResult.success = coroutineResult2.success;
                    if (!coroutineResult.success)
                    {
                        coroutineResult.isFinished = true;
                        yield break;
                    }

                    // Track which slices are new generated texture instances. Atlases could be original texture assets (one tex per atlas) or temporary texture instances in memory that will need to be destroyed.
                    {
                        for (int texPropIdx = 0; texPropIdx < sliceAtlasesAndRectOutput.atlases.Length; texPropIdx++)
                        {
                            Texture2D atlas = sliceAtlasesAndRectOutput.atlases[texPropIdx];
                            if (atlas != null)
                            {
                                bool atlasWasASourceTexture = false;
                                for (int srcMatIdx = 0; srcMatIdx < srcMatAndObjPairs.Count; srcMatIdx++)
                                {
                                    Material srcMat = srcMatAndObjPairs[srcMatIdx].sourceMaterial;
                                    if (srcMat.HasProperty(sliceAtlasesAndRectOutput.texPropertyNames[texPropIdx]) &&
                                        srcMat.GetTexture(sliceAtlasesAndRectOutput.texPropertyNames[texPropIdx]) == atlas)
                                    {
                                        atlasWasASourceTexture = true;
                                        break;
                                    }
                                }

                                if (!atlasWasASourceTexture)
                                {
                                    generatedTemporaryAtlases.Add(new MB3_TextureCombiner.TemporaryTexture(sliceAtlasesAndRectOutput.texPropertyNames[texPropIdx], atlas));
                                }
                            }
                        }
                    } // end visit slices

                    Debug.Assert(combiner._getNumTemporaryTextures() == 0, "Combiner should have no temporary textures.");
                }

                combiner.saveAtlasesAsAssets = saveAtlasesAsAssets; // Restore original setting.
            }

            // Generated atlas textures are temporary for texture arrays. They exist only in memory. Need to be cleaned up after we create slices.
            for (int i = 0; i < generatedTemporaryAtlases.Count; i++)
            {
                combiner.AddTemporaryTexture(generatedTemporaryAtlases[i]);
            }

            List <ShaderTextureProperty> texPropertyNames = new List <ShaderTextureProperty>();

            MB3_TextureCombinerPipeline._CollectPropertyNames(texPropertyNames, customShaderProperties, resMatConfig.combinedMaterial, LOG_LEVEL);

            // The slices are built from different source-material-lists. Each slice can have different sets of texture properties missing (nulls).
            // Build a master list of texture properties.
            bool[] hasTexForProperty = MB_TextureArrays.DetermineWhichPropertiesHaveTextures(bakedMatsAndSlicesResMat.slices);

            List <Texture2D> temporaryTextureAssets = new List <Texture2D>();

            try
            {
                MB_MultiMaterialTexArray resMaterial = resMatConfig;
                Dictionary <string, MB_TexArrayForProperty> resTexArraysByProperty = new Dictionary <string, MB_TexArrayForProperty>();
                {
                    // Initialize so I don't need to check if properties exist later.
                    for (int propIdx = 0; propIdx < texPropertyNames.Count; propIdx++)
                    {
                        if (hasTexForProperty[propIdx])
                        {
                            resTexArraysByProperty[texPropertyNames[propIdx].name] =
                                new MB_TexArrayForProperty(texPropertyNames[propIdx].name, new MB_TextureArrayReference[textureArrayOutputFormats.Length]);
                        }
                    }
                }


                MB3_TextureCombinerNonTextureProperties textureBlender = null;
                textureBlender = new MB3_TextureCombinerNonTextureProperties(LOG_LEVEL, combiner.considerNonTextureProperties);
                textureBlender.LoadTextureBlendersIfNeeded(resMatConfig.combinedMaterial);
                textureBlender.AdjustNonTextureProperties(resMatConfig.combinedMaterial, texPropertyNames, editorMethods);

                // Vist each TextureFormatSet
                for (int texFormatSetIdx = 0; texFormatSetIdx < textureArrayOutputFormats.Length; texFormatSetIdx++)
                {
                    MB_TextureArrayFormatSet textureArrayFormatSet = textureArrayOutputFormats[texFormatSetIdx];
                    editorMethods.Clear();

                    MB_TextureArrays.TexturePropertyData texPropertyData = new MB_TextureArrays.TexturePropertyData();
                    MB_TextureArrays.FindBestSizeAndMipCountAndFormatForTextureArrays(texPropertyNames, combiner.maxAtlasSize, textureArrayFormatSet, bakedMatsAndSlicesResMat.slices, texPropertyData);

                    // Create textures we might need to create if they don't exist.
                    {
                        for (int propIdx = 0; propIdx < hasTexForProperty.Length; propIdx++)
                        {
                            if (hasTexForProperty[propIdx])
                            {
                                TextureFormat format       = texPropertyData.formats[propIdx];
                                int           numSlices    = bakedMatsAndSlicesResMat.slices.Length;
                                int           targetWidth  = (int)texPropertyData.sizes[propIdx].x;
                                int           targetHeight = (int)texPropertyData.sizes[propIdx].y;
                                for (int sliceIdx = 0; sliceIdx < numSlices; sliceIdx++)
                                {
                                    if (bakedMatsAndSlicesResMat.slices[sliceIdx].atlases[propIdx] == null)
                                    {
                                        // Can only setSolidColor on truecolor textures. First create a texture in trucolor format
                                        Texture2D sliceTex = new Texture2D(targetWidth, targetHeight, TextureFormat.ARGB32, texPropertyData.doMips[propIdx]);
                                        Color     col      = textureBlender.GetColorForTemporaryTexture(resMatConfig.slices[sliceIdx].sourceMaterials[0].sourceMaterial, texPropertyNames[propIdx]);
                                        MB_Utility.setSolidColor(sliceTex, col);
                                        // Now create a copy of this texture in target format.
                                        bakedMatsAndSlicesResMat.slices[sliceIdx].atlases[propIdx] = editorMethods.CreateTemporaryAssetCopy(texPropertyNames[propIdx], sliceTex, targetWidth, targetHeight, format, LOG_LEVEL);
                                        temporaryTextureAssets.Add(bakedMatsAndSlicesResMat.slices[sliceIdx].atlases[propIdx]);
                                        MB_Utility.Destroy(sliceTex);
                                    }
                                }
                            }
                        }
                    }


                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("Converting source textures to readable formats.");
                    }
                    if (MB_TextureArrays.ConvertTexturesToReadableFormat(texPropertyData, bakedMatsAndSlicesResMat.slices, hasTexForProperty, texPropertyNames, combiner, LOG_LEVEL, temporaryTextureAssets, editorMethods))
                    {
                        // We now have a set of slices (one per textureProperty). Build these into Texture2DArray's.
                        if (LOG_LEVEL >= MB2_LogLevel.debug)
                        {
                            Debug.Log("Creating texture arrays");
                        }
                        if (LOG_LEVEL >= MB2_LogLevel.info)
                        {
                            Debug.Log("THERE MAY BE ERRORS IN THE CONSOLE ABOUT 'Rebuilding mipmaps ... not supported'. THESE ARE PROBABLY FALSE POSITIVES AND CAN BE IGNORED.");
                        }
                        Texture2DArray[] textureArrays = MB_TextureArrays.CreateTextureArraysForResultMaterial(texPropertyData, texPropertyNames, bakedMatsAndSlicesResMat.slices, hasTexForProperty, combiner, LOG_LEVEL);


                        // Now have texture arrays for a result material, for all props. Save it.
                        for (int propIdx = 0; propIdx < textureArrays.Length; propIdx++)
                        {
                            if (hasTexForProperty[propIdx])
                            {
                                MB_TextureArrayReference texRef = new MB_TextureArrayReference(textureArrayFormatSet.name, textureArrays[propIdx]);
                                resTexArraysByProperty[texPropertyNames[propIdx].name].formats[texFormatSetIdx] = texRef;
                                if (saveAtlasesAsAssets)
                                {
                                    editorMethods.SaveTextureArrayToAssetDatabase(textureArrays[propIdx],
                                                                                  textureArrayFormatSet.GetFormatForProperty(texPropertyNames[propIdx].name),
                                                                                  bakedMatsAndSlicesResMat.slices[0].texPropertyNames[propIdx],
                                                                                  propIdx, resMaterial.combinedMaterial);
                                }
                            }
                        }
                    }
                } // end vist format set

                resMaterial.textureProperties = new List <MB_TexArrayForProperty>();
                foreach (MB_TexArrayForProperty val in resTexArraysByProperty.Values)
                {
                    resMaterial.textureProperties.Add(val);
                }
            }
            catch (Exception e)
            {
                Debug.LogError(e.Message + "\n" + e.StackTrace.ToString());
                coroutineResult.isFinished = true;
                coroutineResult.success    = false;
            }
            finally
            {
                editorMethods.RestoreReadFlagsAndFormats(progressInfo);
                combiner._destroyAllTemporaryTextures();
                for (int i = 0; i < temporaryTextureAssets.Count; i++)
                {
                    editorMethods.DestroyAsset(temporaryTextureAssets[i]);
                }
                temporaryTextureAssets.Clear();
            }
        }
Exemple #17
0
        public override IEnumerator CreateAtlases(ProgressUpdateDelegate progressInfo,
                                                  MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner,
                                                  AtlasPackingResult packedAtlasRects,
                                                  Texture2D[] atlases, MB2_EditorMethodsInterface textureEditorMethods,
                                                  MB2_LogLevel LOG_LEVEL)
        {
            Rect[] uvRects = packedAtlasRects.rects;

            int atlasSizeX = packedAtlasRects.atlasX;
            int atlasSizeY = packedAtlasRects.atlasY;

            if (LOG_LEVEL >= MB2_LogLevel.debug)
            {
                Debug.Log("Generated atlas will be " + atlasSizeX + "x" + atlasSizeY);
            }

            for (int propIdx = 0; propIdx < data.numAtlases; propIdx++)
            {
                Texture2D             atlas    = null;
                ShaderTextureProperty property = data.texPropertyNames[propIdx];
                if (!MB3_TextureCombinerPipeline._ShouldWeCreateAtlasForThisProperty(propIdx, data._considerNonTextureProperties, data.allTexturesAreNullAndSameColor))
                {
                    atlas = null;
                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("=== Not creating atlas for " + property.name + " because textures are null and default value parameters are the same.");
                    }
                }
                else
                {
                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("=== Creating atlas for " + property.name);
                    }

                    GC.Collect();

                    CreateTemporaryTexturesForAtlas(data.distinctMaterialTextures, combiner, propIdx, data);

                    //use a jagged array because it is much more efficient in memory
                    Color[][] atlasPixels = new Color[atlasSizeY][];
                    for (int j = 0; j < atlasPixels.Length; j++)
                    {
                        atlasPixels[j] = new Color[atlasSizeX];
                    }

                    bool isNormalMap = false;
                    if (property.isNormalMap)
                    {
                        isNormalMap = true;
                    }

                    for (int texSetIdx = 0; texSetIdx < data.distinctMaterialTextures.Count; texSetIdx++)
                    {
                        MB_TexSet texSet = data.distinctMaterialTextures[texSetIdx];
                        MeshBakerMaterialTexture matTex = texSet.ts[propIdx];
                        string s = "Creating Atlas '" + property.name + "' texture " + matTex.GetTexName();
                        if (progressInfo != null)
                        {
                            progressInfo(s, .01f);
                        }
                        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  = texSet.ts[propIdx].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);
                        if (ww == 0 || hh == 0)
                        {
                            Debug.LogError("Image in atlas has no height or width " + r);
                        }
                        if (progressInfo != null)
                        {
                            progressInfo(s + " set ReadWrite flag", .01f);
                        }
                        if (textureEditorMethods != null)
                        {
                            textureEditorMethods.SetReadWriteFlag(t, true, true);
                        }
                        if (progressInfo != null)
                        {
                            progressInfo(s + "Copying to atlas: '" + matTex.GetTexName() + "'", .02f);
                        }
                        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()));
                        yield return(CopyScaledAndTiledToAtlas(texSet.ts[propIdx], texSet, property, samplingRect, x, y, ww, hh, packedAtlasRects.padding[texSetIdx], atlasPixels, isNormalMap, data, combiner, progressInfo, LOG_LEVEL));
                    }

                    yield return(data.numAtlases);

                    if (progressInfo != null)
                    {
                        progressInfo("Applying changes to atlas: '" + property.name + "'", .03f);
                    }
                    atlas = new Texture2D(atlasSizeX, atlasSizeY, TextureFormat.ARGB32, true);
                    for (int j = 0; j < atlasPixels.Length; j++)
                    {
                        atlas.SetPixels(0, j, atlasSizeX, 1, atlasPixels[j]);
                    }

                    atlas.Apply();
                    if (LOG_LEVEL >= MB2_LogLevel.debug)
                    {
                        Debug.Log("Saving atlas " + property.name + " w=" + atlas.width + " h=" + atlas.height);
                    }
                }

                atlases[propIdx] = atlas;
                if (progressInfo != null)
                {
                    progressInfo("Saving atlas: '" + property.name + "'", .04f);
                }
                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                sw.Start();
                if (data.resultType == MB2_TextureBakeResults.ResultType.atlas)
                {
                    SaveAtlasAndConfigureResultMaterial(data, textureEditorMethods, atlases[propIdx], data.texPropertyNames[propIdx], propIdx);
                }

                combiner._destroyTemporaryTextures(data.texPropertyNames[propIdx].name);
            }

            yield break;
        }
Exemple #18
0
        public void SuggestTreatment(List <GameObject> objsToMesh, Material[] resultMaterials, List <ShaderTextureProperty> _customShaderPropNames)
        {
            this._customShaderPropNames = _customShaderPropNames;
            StringBuilder sb = new StringBuilder();
            Dictionary <int, MB_Utility.MeshAnalysisResult[]> meshAnalysisResultsCache = new Dictionary <int, MB_Utility.MeshAnalysisResult[]>(); //cache results

            for (int i = 0; i < objsToMesh.Count; i++)
            {
                GameObject obj = objsToMesh[i];
                if (obj == null)
                {
                    continue;
                }
                Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]);
                if (ms.Length > 1)
                { // and each material is not mapped to its own layer
                    sb.AppendFormat("\nObject {0} uses {1} materials. Possible treatments:\n", objsToMesh[i].name, ms.Length);
                    sb.AppendFormat("  1) Collapse the submeshes together into one submesh in the combined mesh. Each of the original submesh materials will map to a different UV rectangle in the atlas(es) used by the combined material.\n");
                    sb.AppendFormat("  2) Use the multiple materials feature to map submeshes in the source mesh to submeshes in the combined mesh.\n");
                }
                Mesh m = MB_Utility.GetMesh(obj);

                MB_Utility.MeshAnalysisResult[] mar;
                if (!meshAnalysisResultsCache.TryGetValue(m.GetInstanceID(), out mar))
                {
                    mar = new MB_Utility.MeshAnalysisResult[m.subMeshCount];
                    MB_Utility.doSubmeshesShareVertsOrTris(m, ref mar[0]);
                    for (int j = 0; j < m.subMeshCount; j++)
                    {
                        MB_Utility.hasOutOfBoundsUVs(m, ref mar[j], j);
                        //DRect outOfBoundsUVRect = new DRect(mar[j].uvRect);
                        mar[j].hasOverlappingSubmeshTris  = mar[0].hasOverlappingSubmeshTris;
                        mar[j].hasOverlappingSubmeshVerts = mar[0].hasOverlappingSubmeshVerts;
                    }
                    meshAnalysisResultsCache.Add(m.GetInstanceID(), mar);
                }

                for (int j = 0; j < ms.Length; j++)
                {
                    if (mar[j].hasOutOfBoundsUVs)
                    {
                        DRect r = new DRect(mar[j].uvRect);
                        sb.AppendFormat("\nObject {0} submesh={1} material={2} uses UVs outside the range 0,0 .. 1,1 to create tiling that tiles the box {3},{4} .. {5},{6}. This is a problem because the UVs outside the 0,0 .. 1,1 " +
                                        "rectangle will pick up neighboring textures in the atlas. Possible Treatments:\n", obj, j, ms[j], r.x.ToString("G4"), r.y.ToString("G4"), (r.x + r.width).ToString("G4"), (r.y + r.height).ToString("G4"));
                        sb.AppendFormat("    1) Ignore the problem. The tiling may not affect result significantly.\n");
                        sb.AppendFormat("    2) Use the 'fix out of bounds UVs' feature to bake the tiling and scale the UVs to fit in the 0,0 .. 1,1 rectangle.\n");
                        sb.AppendFormat("    3) Use the Multiple Materials feature to map the material on this submesh to its own submesh in the combined mesh. No other materials should map to this submesh. This will result in only one texture in the atlas(es) and the UVs should tile correctly.\n");
                        sb.AppendFormat("    4) Combine only meshes that use the same (or subset of) the set of materials on this mesh. The original material(s) can be applied to the result\n");
                    }
                }
                if (mar[0].hasOverlappingSubmeshVerts)
                {
                    sb.AppendFormat("\nObject {0} has submeshes that share vertices. This is a problem because each vertex can have only one UV coordinate and may be required to map to different positions in the various atlases that are generated. Possible treatments:\n", objsToMesh[i]);
                    sb.AppendFormat(" 1) Ignore the problem. The vertices may not affect the result.\n");
                    sb.AppendFormat(" 2) Use the Multiple Materials feature to map the submeshs that overlap to their own submeshs in the combined mesh. No other materials should map to this submesh. This will result in only one texture in the atlas(es) and the UVs should tile correctly.\n");
                    sb.AppendFormat(" 3) Combine only meshes that use the same (or subset of) the set of materials on this mesh. The original material(s) can be applied to the result\n");
                }
            }
            Dictionary <Material, List <GameObject> > m2gos = new Dictionary <Material, List <GameObject> >();

            for (int i = 0; i < objsToMesh.Count; i++)
            {
                if (objsToMesh[i] != null)
                {
                    Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]);
                    for (int j = 0; j < ms.Length; j++)
                    {
                        if (ms[j] != null)
                        {
                            List <GameObject> lgo;
                            if (!m2gos.TryGetValue(ms[j], out lgo))
                            {
                                lgo = new List <GameObject>();
                                m2gos.Add(ms[j], lgo);
                            }
                            if (!lgo.Contains(objsToMesh[i]))
                            {
                                lgo.Add(objsToMesh[i]);
                            }
                        }
                    }
                }
            }

            for (int i = 0; i < resultMaterials.Length; i++)
            {
                string resultMatShaderName = resultMaterials[i] != null ? "None" : resultMaterials[i].shader.name;
                MB3_TextureCombinerPipeline.TexturePipelineData data = LoadPipelineData(resultMaterials[i], new List <ShaderTextureProperty>(), objsToMesh, new List <Material>(), new List <MB_TexSet>());
                MB3_TextureCombinerPipeline._CollectPropertyNames(data, LOG_LEVEL);
                foreach (Material m in m2gos.Keys)
                {
                    for (int j = 0; j < data.texPropertyNames.Count; j++)
                    {
                        if (m.HasProperty(data.texPropertyNames[j].name))
                        {
                            Texture txx = MB3_TextureCombinerPipeline.GetTextureConsideringStandardShaderKeywords(resultMatShaderName, m, data.texPropertyNames[j].name);
                            if (txx != null)
                            {
                                Vector2 o = m.GetTextureOffset(data.texPropertyNames[j].name);
                                Vector3 s = m.GetTextureScale(data.texPropertyNames[j].name);
                                if (o.x < 0f || o.x + s.x > 1f ||
                                    o.y < 0f || o.y + s.y > 1f)
                                {
                                    sb.AppendFormat("\nMaterial {0} used by objects {1} uses texture {2} that is tiled (scale={3} offset={4}). If there is more than one texture in the atlas " +
                                                    " then Mesh Baker will bake the tiling into the atlas. If the baked tiling is large then quality can be lost. Possible treatments:\n", m, PrintList(m2gos[m]), txx, s, o);
                                    sb.AppendFormat("  1) Use the baked tiling.\n");
                                    sb.AppendFormat("  2) Use the Multiple Materials feature to map the material on this object/submesh to its own submesh in the combined mesh. No other materials should map to this submesh. The original material can be applied to this submesh.\n");
                                    sb.AppendFormat("  3) Combine only meshes that use the same (or subset of) the set of textures on this mesh. The original material can be applied to the result.\n");
                                }
                            }
                        }
                    }
                }
            }
            string outstr = "";

            if (sb.Length == 0)
            {
                outstr = "====== No problems detected. These meshes should combine well ====\n  If there are problems with the combined meshes please report the problem to digitalOpus.ca so we can improve Mesh Baker.";
            }
            else
            {
                outstr = "====== There are possible problems with these meshes that may prevent them from combining well. TREATMENT SUGGESTIONS (copy and paste to text editor if too big) =====\n" + sb.ToString();
            }
            Debug.Log(outstr);
        }
Exemple #19
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);
        }