//posibilities // using fixOutOfBoundsUVs or not // /// <summary> /// 根据合并列表物体配置多材质 /// </summary> /// <param name="mom"></param> /// <param name="resultMaterials"></param> /// <param name="textureBaker"></param> public static void ConfigureMutiMaterialsFromObjsToCombine(TextureCombineEntrance mom, SerializedProperty resultMaterials, SerializedObject textureBaker) { if (mom.GetObjectsToCombine().Count == 0) { Debug.LogError("合并列表为空"); return; } if (resultMaterials.arraySize > 0) { Debug.LogError("多材质映射已配置,在进行当前操作前需清除旧配置"); return; } if (mom.textureBakeResults == null) { Debug.LogError("Texture Bake Result 为空"); return; } //validate that the objects to be combined are valid //验证合并列表内物体有效性 for (int i = 0; i < mom.GetObjectsToCombine().Count; i++) { GameObject go = mom.GetObjectsToCombine()[i]; if (go == null) { Debug.LogError("合并列表中有空物体于 " + i); return; } Renderer r = go.GetComponent <Renderer>(); if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer))) { Debug.LogError("合并列表中第 " + i + " 个游戏物体没有 renderer 组件"); return; } if (r.sharedMaterial == null) { Debug.LogError("合并列表中第 " + i + " 个游戏物体没有材质"); return; } } Dictionary <Material, Mesh> obUVobjectToMesh_map = new Dictionary <Material, Mesh>(); //first pass put any meshes with obUVs on their own submesh if not fixing OB uvs //1.将所有带有obUV的网格置于单独的材质中,(如果不固定OB UV) if (mom.doMultiMaterialSplitAtlasesIfOBUVs) { for (int i = 0; i < mom.GetObjectsToCombine().Count; i++) { GameObject go = mom.GetObjectsToCombine()[i]; Mesh m = MeshBakerUtility.GetMesh(go); MeshAnalysisResult dummyMar = new MeshAnalysisResult(); Renderer r = go.GetComponent <Renderer>(); for (int j = 0; j < r.sharedMaterials.Length; j++) { if (MeshBakerUtility.hasOutOfBoundsUVs(m, ref dummyMar, j)) { if (!obUVobjectToMesh_map.ContainsKey(r.sharedMaterials[j])) { Debug.LogWarning("Object " + go + " submesh " + j + " uses UVs outside the range 0,0..1,1 to generate tiling. " + "This object has been mapped to its own submesh in the combined mesh. " + "It can share a submesh with other objects that use different materials " + "if you use the fix out of bounds UVs feature which will bake the tiling"); obUVobjectToMesh_map.Add(r.sharedMaterials[j], m); } } } } } Dictionary <MultiMatSubmeshInfo, List <List <Material> > > shaderToMaterial_map = new Dictionary <MultiMatSubmeshInfo, List <List <Material> > >(); //2.没有 OB uvs 的材质按 shader 添加到 shader2Material_map 中 for (int i = 0; i < mom.GetObjectsToCombine().Count; i++) { Renderer r = mom.GetObjectsToCombine()[i].GetComponent <Renderer>(); for (int j = 0; j < r.sharedMaterials.Length; j++) { if (!obUVobjectToMesh_map.ContainsKey(r.sharedMaterials[j])) { //if not already added if (r.sharedMaterials[j] == null) { continue; } List <List <Material> > binsOfMatsThatUseShader = null; MultiMatSubmeshInfo newKey = new MultiMatSubmeshInfo(r.sharedMaterials[j].shader, r.sharedMaterials[j]); if (!shaderToMaterial_map.TryGetValue(newKey, out binsOfMatsThatUseShader)) { binsOfMatsThatUseShader = new List <List <Material> >(); binsOfMatsThatUseShader.Add(new List <Material>()); shaderToMaterial_map.Add(newKey, binsOfMatsThatUseShader); } if (!binsOfMatsThatUseShader[0].Contains(r.sharedMaterials[j])) { binsOfMatsThatUseShader[0].Add(r.sharedMaterials[j]); } } } } int ResultMatsCount = shaderToMaterial_map.Count; //third pass for each shader grouping check how big the atlas would be and group into bins that would fit in an atlas // 3.检查每个 Shader-Mat 组的最终打包的 atlas 大小,过大则分到另一个图集中 if (mom.doMultiMaterialSplitAtlasesIfTooBig) { if (mom.packingAlgorithm == PackingAlgorithmEnum.UnitysPackTextures) { Debug.LogWarning("Unity texture packer does not support splitting atlases if too big. Atlases will not be split."); } else { ResultMatsCount = 0; foreach (MultiMatSubmeshInfo sh in shaderToMaterial_map.Keys) { List <List <Material> > binsOfMatsThatUseShader = shaderToMaterial_map[sh]; List <Material> allMatsThatUserShader = binsOfMatsThatUseShader[0];//at this point everything is in the same list binsOfMatsThatUseShader.RemoveAt(0); TextureCombineHandler combiner = mom.CreateAndConfigureTextureCombiner(); combiner.saveAtlasesAsAssets = false; if (allMatsThatUserShader.Count > 1) { combiner.fixOutOfBoundsUVs = mom.fixOutOfBoundsUVs; } else { combiner.fixOutOfBoundsUVs = false; } // Do the texture pack List <AtlasPackingResult> packingResults = new List <AtlasPackingResult>(); Material tempMat = new Material(sh.shader); combiner.CombineTexturesIntoAtlases(null, null, tempMat, mom.GetObjectsToCombine(), allMatsThatUserShader, null, packingResults, true, true); for (int i = 0; i < packingResults.Count; i++) { List <MatsAndGOs> matsData = (List <MatsAndGOs>)packingResults[i].data; List <Material> mats = new List <Material>(); for (int j = 0; j < matsData.Count; j++) { for (int kk = 0; kk < matsData[j].mats.Count; kk++) { if (!mats.Contains(matsData[j].mats[kk].mat)) { mats.Add(matsData[j].mats[kk].mat); } } } binsOfMatsThatUseShader.Add(mats); } ResultMatsCount += binsOfMatsThatUseShader.Count; } } } //build the result materials if (shaderToMaterial_map.Count == 0 && obUVobjectToMesh_map.Count == 0) { Debug.LogError("合并列表中没有材质"); } mom.resultMaterials = new MultiMaterial[ResultMatsCount + obUVobjectToMesh_map.Count]; string pth = AssetDatabase.GetAssetPath(mom.textureBakeResults); string baseName = Path.GetFileNameWithoutExtension(pth); string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6); int k = 0; foreach (MultiMatSubmeshInfo sh in shaderToMaterial_map.Keys) { foreach (List <Material> sourseMatsThatUseSameShader in shaderToMaterial_map[sh]) { MultiMaterial mm = mom.resultMaterials[k] = new MultiMaterial(); mm.sourceMaterials = sourseMatsThatUseSameShader; if (mm.sourceMaterials.Count == 1) { mm.considerMeshUVs = false; } else { mm.considerMeshUVs = mom.fixOutOfBoundsUVs; } string matName = folderPath + baseName + "-mat" + k + ".mat"; Material newMat = new Material(Shader.Find("Diffuse")); if (sourseMatsThatUseSameShader.Count > 0 && sourseMatsThatUseSameShader[0] != null) { //复制参数值 TextureCombineEntrance.ConfigureNewMaterialToMatchOld(newMat, sourseMatsThatUseSameShader[0]); } AssetDatabase.CreateAsset(newMat, matName); //合并材质初始值为源材质列表第一个的值 mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material)); k++; } } foreach (Material m in obUVobjectToMesh_map.Keys) { MultiMaterial mm = mom.resultMaterials[k] = new MultiMaterial(); mm.sourceMaterials = new List <Material>(); mm.sourceMaterials.Add(m); mm.considerMeshUVs = false; string matName = folderPath + baseName + "-mat" + k + ".mat"; Material newMat = new Material(Shader.Find("Diffuse")); TextureCombineEntrance.ConfigureNewMaterialToMatchOld(newMat, m); AssetDatabase.CreateAsset(newMat, matName); mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material)); k++; } SceneBakerUtilityInEditor.UpdateIfDirtyOrScript(textureBaker); }
/// <summary> /// 第一步: /// 写入 TexturePipelineData 的 MaterialPropTexturesSet 列表,和 usedObjsToMesh 列表 /// 每个TexSet在 Atlas 中都是一个矩形。 /// 如果 allowedMaterialsFilter (过滤器)为空,则将收集 allObjsToMesh 上的所有材质,usedObjsToMesh 将与allObjsToMesh相同 /// 否则,将仅包括 allowedMaterialsFilter 中的材质,usedObjsToMesh将是使用这些材料的objs。 /// </summary> internal static void Step1_CollectDistinctMatTexturesAndUsedObjects(TextureCombinePipelineData data, EditorMethodsInterface textureEditorMethods, List <GameObject> usedObjsToMesh) { // 收集UsedObjects上不同的材质纹理 bool outOfBoundsUVs = false; Dictionary <int, MeshAnalysisResult[]> meshAnalysisResultsCache = new Dictionary <int, MeshAnalysisResult[]>(); //cache results for (int i = 0; i < data.allObjsToMesh.Count; i++) { GameObject obj = data.allObjsToMesh[i]; if (obj == null) { Debug.LogError("合并游戏物体列表中包含空物体"); return; } Mesh sharedMesh = MeshBakerUtility.GetMesh(obj); if (sharedMesh == null) { Debug.LogError("游戏物体 " + obj.name + " 网格为空"); return; } Material[] sharedMaterials = MeshBakerUtility.GetGOMaterials(obj); if (sharedMaterials.Length == 0) { Debug.LogError("游戏物体 " + obj.name + " 材质为空."); return; } //analyze mesh or grab cached result of previous analysis, stores one result for each submesh //处理网格数据 MeshAnalysisResult[] meshAnalysisResults; //每个游戏物体的主网格子网格数据数组 if (!meshAnalysisResultsCache.TryGetValue(sharedMesh.GetInstanceID(), out meshAnalysisResults)) { //获取参与合并物体的网格分析数据 meshAnalysisResults = new MeshAnalysisResult[sharedMesh.subMeshCount]; for (int j = 0; j < sharedMesh.subMeshCount; j++) { MeshBakerUtility.hasOutOfBoundsUVs(sharedMesh, ref meshAnalysisResults[j], j); if (data.normalizeTexelDensity) { meshAnalysisResults[j].submeshArea = GetSubmeshArea(sharedMesh, j); } if (data.fixOutOfBoundsUVs && !meshAnalysisResults[j].hasUVs) { meshAnalysisResults[j].uvRect = new Rect(0, 0, 1, 1); Debug.LogWarning("Mesh for object " + obj + " has no UV channel but 'consider UVs' is enabled." + " Assuming UVs will be generated filling 0,0,1,1 rectangle."); } } meshAnalysisResultsCache.Add(sharedMesh.GetInstanceID(), meshAnalysisResults); } //处理材质数据 for (int matIdx = 0; matIdx < sharedMaterials.Length; matIdx++) { Material mat = sharedMaterials[matIdx]; // 材质过滤器 if (data.allowedMaterialsFilter != null && !data.allowedMaterialsFilter.Contains(mat)) { continue; } outOfBoundsUVs = outOfBoundsUVs || meshAnalysisResults[matIdx].hasOutOfBoundsUVs; if (mat.name.Contains("(Instance)")) { Debug.LogError("The sharedMaterial on object " + obj.name + " has been 'Instanced'." + " This was probably caused by a script accessing the meshRender.material property in the editor. " + " The material to UV Rectangle mapping will be incorrect. " + "To fix this recreate the object from its prefab or re-assign its material from the correct asset."); return; } if (data.fixOutOfBoundsUVs) { if (!MeshBakerUtility.AreAllSharedMaterialsDistinct(sharedMaterials)) { Debug.LogWarning("游戏物体 " + obj.name + " 使用相同的材质在多个子网格. " + "可能生成奇怪的 resultAtlasesAndRects,尤其是与 _fixOutOfBoundsUVs 为 true 时"); } } //材质属性 Texutre 信息 MaterialPropTexture[] mts = new MaterialPropTexture[data.texPropertyNames.Count]; for (int propIdx = 0; propIdx < data.texPropertyNames.Count; propIdx++) { Texture tx = null; Vector2 scale = Vector2.one; Vector2 offset = Vector2.zero; float texelDensity = 0f; if (mat.HasProperty(data.texPropertyNames[propIdx].name)) { Texture txx = GetTextureConsideringStandardShaderKeywords(data.ResultMaterial.shader.name, mat, data.texPropertyNames[propIdx].name); if (txx != null) { if (txx is Texture2D) { //TextureFormat 验证 tx = txx; TextureFormat f = ((Texture2D)tx).format; bool isNormalMap = false; if (!Application.isPlaying && textureEditorMethods != null) { isNormalMap = textureEditorMethods.IsNormalMap((Texture2D)tx); } if ((f == TextureFormat.ARGB32 || f == TextureFormat.RGBA32 || f == TextureFormat.BGRA32 || f == TextureFormat.RGB24 || f == TextureFormat.Alpha8) && !isNormalMap) //DXT5 does not work { //可使用 } else { //TRIED to copy texture using tex2.SetPixels(tex1.GetPixels()) but bug in 3.5 means DTX1 and 5 compressed textures come out skewe //尝试使用tex2.SetPixels(tex1.GetPixels())复制纹理,但是3.5中的bug意味着DTX1和5压缩纹理出现扭曲 if (Application.isPlaying && data.packingAlgorithm != PackingAlgorithmEnum.MeshBakerTexturePacker_Fast) { Debug.LogWarning("合并列表中,游戏物体 " + obj.name + " 所使用的 Texture " + tx.name + " 使用的格式 " + f + "不是: ARGB32, RGBA32, BGRA32, RGB24, Alpha8 或 DXT. " + "无法在运行时重新设置尺寸" + "If format says 'compressed' try changing it to 'truecolor'"); return; } else { tx = (Texture2D)mat.GetTexture(data.texPropertyNames[propIdx].name); } } } else { Debug.LogError("合并列表中,游戏物体 " + obj.name + " 渲染网格使用的 Texture 不是 Texture2D. "); return; } } //像素密度 if (tx != null && data.normalizeTexelDensity) { //不考虑平铺和UV采样超出范围 if (meshAnalysisResults[propIdx].submeshArea == 0) { texelDensity = 0f; } else { texelDensity = (tx.width * tx.height) / (meshAnalysisResults[propIdx].submeshArea); } } //规格,偏移 GetMaterialScaleAndOffset(mat, data.texPropertyNames[propIdx].name, out offset, out scale); } mts[propIdx] = new MaterialPropTexture(tx, offset, scale, texelDensity); } // 收集材质参数值的平均值 data.nonTexturePropertyBlender.CollectAverageValuesOfNonTextureProperties(data.ResultMaterial, mat); Vector2 obUVscale = new Vector2(meshAnalysisResults[matIdx].uvRect.width, meshAnalysisResults[matIdx].uvRect.height); Vector2 obUVoffset = new Vector2(meshAnalysisResults[matIdx].uvRect.x, meshAnalysisResults[matIdx].uvRect.y); //Add to distinct set of textures if not already there TextureTilingTreatment tilingTreatment = TextureTilingTreatment.none; if (data.fixOutOfBoundsUVs) { tilingTreatment = TextureTilingTreatment.considerUVs; } //合并信息 distinctMaterialTextures 数据设置 //材质各参数 Texture,及 UV 偏移数据映射 MaterialPropTexturesSet setOfTexs = new MaterialPropTexturesSet(mts, obUVoffset, obUVscale, tilingTreatment); //one of these per submesh //材质及各变化参数Rect 数据 MatAndTransformToMerged matt = new MatAndTransformToMerged(new DRect(obUVoffset, obUVscale), data.fixOutOfBoundsUVs, mat); setOfTexs.matsAndGOs.mats.Add(matt); MaterialPropTexturesSet setOfTexs2 = data.distinctMaterialTextures.Find(x => x.IsEqual(setOfTexs, data.fixOutOfBoundsUVs, data.nonTexturePropertyBlender)); if (setOfTexs2 != null) { setOfTexs = setOfTexs2; } else { data.distinctMaterialTextures.Add(setOfTexs); } if (!setOfTexs.matsAndGOs.mats.Contains(matt)) { setOfTexs.matsAndGOs.mats.Add(matt); } if (!setOfTexs.matsAndGOs.gos.Contains(obj)) { setOfTexs.matsAndGOs.gos.Add(obj); //已使用 游戏物体 if (!usedObjsToMesh.Contains(obj)) { usedObjsToMesh.Add(obj); } } } } Debug.Log(string.Format("第一阶段完成;" + "参与合并的游戏物体的不同材质,各自包含与shader属性对应的不同的纹理,收集到 {0} 组 textures,即 {0} 个不同的材质," + "fixOutOfBoundsUV:{1} " + "considerNonTextureProperties:{2}", data.distinctMaterialTextures.Count, data.fixOutOfBoundsUVs, data.considerNonTextureProperties)); if (data.distinctMaterialTextures.Count == 0) { Debug.LogError("None of the source object materials matched any of the allowed materials for submesh with result material: " + data.ResultMaterial); return; } TextureCombinerMerging merger = new TextureCombinerMerging(data.considerNonTextureProperties, data.nonTexturePropertyBlender, data.fixOutOfBoundsUVs); merger.MergeOverlappingDistinctMaterialTexturesAndCalcMaterialSubrects(data.distinctMaterialTextures); }
/* tried to see if the MultiMaterialConfig could be done using the GroupBy filters. Saddly it didn't work -_- */ public static void ConfigureMutiMaterialsFromObjsToCombine2(TextureCombineEntrance mom, SerializedProperty resultMaterials, SerializedObject textureBaker) { if (mom.GetObjectsToCombine().Count == 0) { Debug.LogError("You need to add some objects to combine before building the multi material list."); return; } if (resultMaterials.arraySize > 0) { Debug.LogError("You already have some source to combined material mappings configured. You must remove these before doing this operation."); return; } if (mom.textureBakeResults == null) { Debug.LogError("Texture Bake Result asset must be set before using this operation."); return; } //validate that the objects to be combined are valid for (int i = 0; i < mom.GetObjectsToCombine().Count; i++) { GameObject go = mom.GetObjectsToCombine()[i]; if (go == null) { Debug.LogError("Null object in list of objects to combine at position " + i); return; } Renderer r = go.GetComponent <Renderer>(); if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer))) { Debug.LogError("GameObject at position " + i + " in list of objects to combine did not have a renderer"); return; } if (r.sharedMaterial == null) { Debug.LogError("GameObject at position " + i + " in list of objects to combine has a null material"); return; } } IGroupByFilter[] filters = new IGroupByFilter[3]; filters[0] = new GroupByOutOfBoundsUVs(); filters[1] = new GroupByShader(); filters[2] = new MB3_GroupByStandardShaderType(); List <GameObjectFilterInfo> gameObjects = new List <GameObjectFilterInfo>(); HashSet <GameObject> objectsAlreadyIncludedInBakers = new HashSet <GameObject>(); for (int i = 0; i < mom.GetObjectsToCombine().Count; i++) { GameObjectFilterInfo goaw = new GameObjectFilterInfo(mom.GetObjectsToCombine()[i], objectsAlreadyIncludedInBakers, filters); if (goaw.materials.Length > 0) //don't consider renderers with no materials { gameObjects.Add(goaw); } } //analyse meshes Dictionary <int, MeshAnalysisResult> meshAnalysisResultCache = new Dictionary <int, MeshAnalysisResult>(); int totalVerts = 0; for (int i = 0; i < gameObjects.Count; i++) { //string rpt = String.Format("Processing {0} [{1} of {2}]", gameObjects[i].go.name, i, gameObjects.Count); //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " A", .6f); Mesh mm = MeshBakerUtility.GetMesh(gameObjects[i].go); int nVerts = 0; if (mm != null) { nVerts += mm.vertexCount; MeshAnalysisResult mar; if (!meshAnalysisResultCache.TryGetValue(mm.GetInstanceID(), out mar)) { //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Check Out Of Bounds UVs", .6f); MeshBakerUtility.hasOutOfBoundsUVs(mm, ref mar); //Rect dummy = mar.uvRect; MeshBakerUtility.doSubmeshesShareVertsOrTris(mm, ref mar); meshAnalysisResultCache.Add(mm.GetInstanceID(), mar); } if (mar.hasOutOfBoundsUVs) { int w = (int)mar.uvRect.width; int h = (int)mar.uvRect.height; gameObjects[i].outOfBoundsUVs = true; gameObjects[i].warning += " [WARNING: has uvs outside the range (0,1) tex is tiled " + w + "x" + h + " times]"; } if (mar.hasOverlappingSubmeshVerts) { gameObjects[i].submeshesOverlap = true; gameObjects[i].warning += " [WARNING: Submeshes share verts or triangles. 'Multiple Combined Materials' feature may not work.]"; } } totalVerts += nVerts; //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Validate OBuvs Multi Material", .6f); Renderer mr = gameObjects[i].go.GetComponent <Renderer>(); if (!MeshBakerUtility.AreAllSharedMaterialsDistinct(mr.sharedMaterials)) { gameObjects[i].warning += " [WARNING: Object uses same material on multiple submeshes. This may produce poor results when used with multiple materials or fix out of bounds uvs.]"; } } List <GameObjectFilterInfo> objsNotAddedToBaker = new List <GameObjectFilterInfo>(); Dictionary <GameObjectFilterInfo, List <List <GameObjectFilterInfo> > > gs2bakeGroupMap = null;//MB3_MeshBakerEditorWindow.sortIntoBakeGroups3(gameObjects, objsNotAddedToBaker, filters, false, mom.maxAtlasSize); mom.resultMaterials = new MultiMaterial[gs2bakeGroupMap.Keys.Count]; string pth = AssetDatabase.GetAssetPath(mom.textureBakeResults); string baseName = Path.GetFileNameWithoutExtension(pth); string folderPath = pth.Substring(0, pth.Length - baseName.Length - 6); int k = 0; foreach (GameObjectFilterInfo m in gs2bakeGroupMap.Keys) { MultiMaterial mm = mom.resultMaterials[k] = new MultiMaterial(); mm.sourceMaterials = new List <Material>(); mm.sourceMaterials.Add(m.materials[0]); string matName = folderPath + baseName + "-mat" + k + ".mat"; Material newMat = new Material(Shader.Find("Diffuse")); TextureCombineEntrance.ConfigureNewMaterialToMatchOld(newMat, m.materials[0]); AssetDatabase.CreateAsset(newMat, matName); mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material)); k++; } SceneBakerUtilityInEditor.UpdateIfDirtyOrScript(textureBaker); }
//a material can appear more than once in an atlas if using fixOutOfBoundsUVs. //in this case need to use the UV rect of the mesh to find the correct rectangle. public bool TryMapMaterialToUVRect(Material mat, Mesh m, int submeshIdx, MeshCombinerSingle.MeshChannelsCache meshChannelCache, Dictionary <int, MeshBakerUtility.MeshAnalysisResult[]> meshAnalysisCache, out Rect rectInAtlas, //out Rect subrectInAtlasMatTiling, out Rect encapsulatingRect, out Rect sourceMaterialTilingOut, ref String errorMsg, MBLogLevel logLevel) { if (tbr.materialsAndUVRects.Length == 0 && tbr.materials.Length > 0) { errorMsg = "The 'Material Bake Result' needs to be re-baked to be compatible with this version of Mesh Baker. Please re-bake using the MB3_TextureBaker."; rectInAtlas = new Rect(); //subrectInAtlasMatTiling = new Rect(); encapsulatingRect = new Rect(); sourceMaterialTilingOut = new Rect(); return(false); } if (mat == null) { rectInAtlas = new Rect(); //subrectInAtlasMatTiling = new Rect(); encapsulatingRect = new Rect(); sourceMaterialTilingOut = new Rect(); errorMsg = String.Format("Mesh {0} Had no material on submesh {1} cannot map to a material in the atlas", m.name, submeshIdx); return(false); } if (submeshIdx >= m.subMeshCount) { errorMsg = "Submesh index is greater than the number of submeshes"; rectInAtlas = new Rect(); //subrectInAtlasMatTiling = new Rect(); encapsulatingRect = new Rect(); sourceMaterialTilingOut = new Rect(); return(false); } //find the first index of this material int idx = -1; for (int i = 0; i < matsAndSrcUVRect.Length; i++) { if (mat == matsAndSrcUVRect[i].material) { idx = i; break; } } // if couldn't find material if (idx == -1) { rectInAtlas = new Rect(); //subrectInAtlasMatTiling = new Rect(); encapsulatingRect = new Rect(); sourceMaterialTilingOut = new Rect(); errorMsg = String.Format("Material {0} could not be found in the Material Bake Result", mat.name); return(false); } if (!tbr.fixOutOfBoundsUVs) { if (numTimesMatAppearsInAtlas[idx] != 1) { Debug.LogError("There is a problem with this TextureBakeResults. FixOutOfBoundsUVs is false and a material appears more than once."); } rectInAtlas = matsAndSrcUVRect[idx].atlasRect; //subrectInAtlasMatTiling = matsAndSrcUVRect[idx].atlasSubrectMaterialOnly; encapsulatingRect = matsAndSrcUVRect[idx].samplingEncapsulatinRect; sourceMaterialTilingOut = matsAndSrcUVRect[idx].sourceMaterialTiling; return(true); } else { //todo what if no UVs //Find UV rect in source mesh MeshBakerUtility.MeshAnalysisResult[] mar; if (!meshAnalysisCache.TryGetValue(m.GetInstanceID(), out mar)) { mar = new MeshBakerUtility.MeshAnalysisResult[m.subMeshCount]; for (int j = 0; j < m.subMeshCount; j++) { Vector2[] uvss = meshChannelCache.GetUv0Raw(m); MeshBakerUtility.hasOutOfBoundsUVs(uvss, m, ref mar[j], j); } meshAnalysisCache.Add(m.GetInstanceID(), mar); } //this could be a mesh that was not used in the texture baking that has huge UV tiling too big for the rect that was baked //find a record that has an atlas uvRect capable of containing this bool found = false; if (logLevel >= MBLogLevel.trace) { Debug.LogWarning(String.Format("Trying to find a rectangle in atlas capable of holding tiled sampling rect for mesh {0} using material {1}", m, mat)); } for (int i = idx; i < matsAndSrcUVRect.Length; i++) { if (matsAndSrcUVRect[i].material == mat) { //calculate what the UV rect in the atlas would be if we combined the material tiling of this rect with the UV tiling of this submesh Rect potentialRect = new Rect(); Rect uvR = mar[submeshIdx].uvRect; Rect matR = matsAndSrcUVRect[i].sourceMaterialTiling; // test to see if this would fit in what was baked in the atlas Rect rr = matsAndSrcUVRect[i].samplingEncapsulatinRect; UVTransformUtility.Canonicalize(ref rr, 0, 0); potentialRect = UVTransformUtility.CombineTransforms(ref uvR, ref matR); if (logLevel >= MBLogLevel.trace) { Debug.Log("uvR=" + uvR.ToString("f5") + " matR=" + matR.ToString("f5") + "Potential Rect " + potentialRect.ToString("f5") + " encapsulating=" + rr.ToString("f5")); } UVTransformUtility.Canonicalize(ref potentialRect, rr.x, rr.y); if (logLevel >= MBLogLevel.trace) { Debug.Log("Potential Rect Cannonical " + potentialRect.ToString("f5") + " encapsulating=" + rr.ToString("f5")); } if (UVTransformUtility.RectContains(ref rr, ref potentialRect)) { if (logLevel >= MBLogLevel.trace) { Debug.Log("Found rect in atlas capable of containing tiled sampling rect for mesh " + m + " at idx=" + i); } idx = i; found = true; break; } } } if (found) { rectInAtlas = matsAndSrcUVRect[idx].atlasRect; //subrectInAtlasMatTiling = matsAndSrcUVRect[idx].atlasSubrectMaterialOnly; encapsulatingRect = matsAndSrcUVRect[idx].samplingEncapsulatinRect; sourceMaterialTilingOut = matsAndSrcUVRect[idx].sourceMaterialTiling; return(true); } else { rectInAtlas = new Rect(); //subrectInAtlasMatTiling = new Rect(); encapsulatingRect = new Rect(); sourceMaterialTilingOut = new Rect(); errorMsg = String.Format("Could not find a tiled rectangle in the atlas capable of containing the uv and material tiling on mesh {0}", m.name); return(false); } } }