コード例 #1
0
        IEnumerator __RunTexturePackerOnly(CombineTexturesIntoAtlasesCoroutineResult result, MB_AtlasesAndRects resultAtlasesAndRects, MB3_TextureCombinerPipeline.TexturePipelineData data, bool splitAtlasWhenPackingIfTooBig, MB2_EditorMethodsInterface textureEditorMethods, List <AtlasPackingResult> packingResult)
        {
            MB3_TextureCombinerPipeline pipeline = new MB3_TextureCombinerPipeline();

            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(pipeline.__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(pipeline.CalculateIdealSizesForTexturesInAtlasAndPadding(null, result, data, this, textureEditorMethods, LOG_LEVEL));

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

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

            //    run the texture packer only
            AtlasPackingResult[] aprs = pipeline.RunTexturePackerOnly(data, splitAtlasWhenPackingIfTooBig, resultAtlasesAndRects, texturePaker, LOG_LEVEL);
            for (int i = 0; i < aprs.Length; i++)
            {
                packingResult.Add(aprs[i]);
            }
        }
        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());
            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();
                if (data.resultType == MB2_TextureBakeResults.ResultType.atlas)
                {
                    data.resultMaterial.SetTexture(data.texPropertyNames[i].name, atlases[i]);
                    data.resultMaterial.SetTextureScale(data.texPropertyNames[i].name, Vector2.one);
                    data.resultMaterial.SetTextureOffset(data.texPropertyNames[i].name, Vector2.zero);
                }
            }

            yield break;
        }
コード例 #3
0
 public virtual IEnumerator ConvertTexturesToReadableFormats(ProgressUpdateDelegate progressInfo,
                                                             MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult result,
                                                             MB3_TextureCombinerPipeline.TexturePipelineData data,
                                                             MB3_TextureCombiner combiner,
                                                             MB2_EditorMethodsInterface textureEditorMethods,
                                                             MB2_LogLevel LOG_LEVEL)
 {
     Debug.Assert(!data.OnlyOneTextureInAtlasReuseTextures());
     //MakeProceduralTexturesReadable(progressInfo, result, data, combiner, textureEditorMethods, LOG_LEVEL);
     for (int i = 0; i < data.distinctMaterialTextures.Count; i++)
     {
         for (int j = 0; j < data.texPropertyNames.Count; j++)
         {
             MeshBakerMaterialTexture ts = data.distinctMaterialTextures[i].ts[j];
             if (!ts.isNull)
             {
                 if (textureEditorMethods != null)
                 {
                     Texture       tx     = ts.GetTexture2D();
                     TextureFormat format = TextureFormat.ARGB32;
                     if (progressInfo != null)
                     {
                         progressInfo(String.Format("Convert texture {0} to readable format ", tx), .5f);
                     }
                     textureEditorMethods.AddTextureFormat((Texture2D)tx, format, data.texPropertyNames[j].isNormalMap);
                 }
             }
         }
     }
     yield break;
 }
        public AtlasPackingResult[] CalculateAtlasRectangles(MB3_TextureCombinerPipeline.TexturePipelineData data, bool doMultiAtlas, MB2_LogLevel LOG_LEVEL)
        {
            Debug.Assert(data.OnlyOneTextureInAtlasReuseTextures());
            if (LOG_LEVEL >= MB2_LogLevel.debug) Debug.Log("Only one image per atlas. Will re-use original texture");
            AtlasPackingResult[] packerRects = new AtlasPackingResult[1];
            AtlasPadding[] paddings = new AtlasPadding[] { new AtlasPadding(data._atlasPadding) };
            packerRects[0] = new AtlasPackingResult(paddings);
            packerRects[0].rects = new Rect[1];
            packerRects[0].srcImgIdxs = new int[] { 0 };
            packerRects[0].rects[0] = new Rect(0f, 0f, 1f, 1f);

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

            }
            if (dmt == null || dmt.isNull)
            {
                packerRects[0].atlasX = 16;
                packerRects[0].atlasY = 16;
                packerRects[0].usedW = 16;
                packerRects[0].usedH = 16;
            }
            else
            {
                packerRects[0].atlasX = dmt.width;
                packerRects[0].atlasY = dmt.height;
                packerRects[0].usedW = dmt.width;
                packerRects[0].usedH = dmt.height;
            }
            return packerRects;
        }
コード例 #5
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, 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));
        }
        public virtual bool Validate(MB3_TextureCombinerPipeline.TexturePipelineData data)
        {
            if (!data.OnlyOneTextureInAtlasReuseTextures())
            {
                Debug.LogError("There must be only one texture in the atlas to use MB3_TextureCombinerPackerOneTextureInAtlas");
                return(false);
            }

            return(true);
        }
 public IEnumerator ConvertTexturesToReadableFormats(ProgressUpdateDelegate progressInfo,
                                                     MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult result,
                                                     MB3_TextureCombinerPipeline.TexturePipelineData data,
                                                     MB3_TextureCombiner combiner,
                                                     MB2_EditorMethodsInterface textureEditorMethods,
                                                     MB2_LogLevel LOG_LEVEL)
 {
     Debug.Assert(data.OnlyOneTextureInAtlasReuseTextures());
     yield break;
 }
コード例 #8
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));
        }
コード例 #9
0
 public override AtlasPackingResult[] CalculateAtlasRectangles(MB3_TextureCombinerPipeline.TexturePipelineData data, bool doMultiAtlas, MB2_LogLevel LOG_LEVEL)
 {
     Debug.Assert(!data.OnlyOneTextureInAtlasReuseTextures());
     //with Unity texture packer we don't find the rectangles, Unity does. When packer is run
     return(new AtlasPackingResult[] { new AtlasPackingResult(new AtlasPadding[0]) });
 }
コード例 #10
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;
        }
コード例 #11
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);
        }
コード例 #12
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);
        }
        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 virtual AtlasPackingResult[] CalculateAtlasRectangles(MB3_TextureCombinerPipeline.TexturePipelineData data, bool doMultiAtlas, MB2_LogLevel LOG_LEVEL)
 {
     Debug.Assert(!data.OnlyOneTextureInAtlasReuseTextures());
     return(MB3_TextureCombinerPackerRoot.CalculateAtlasRectanglesStatic(data, doMultiAtlas, LOG_LEVEL));
 }
コード例 #15
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;
        }