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; }
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; }
//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; }
//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)); }
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]) }); }
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 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); }
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)); }
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; }