public void DoIntegrityCheckMergedEncapsulatingSamplingRects(List <MB_TexSet> distinctMaterialTextures) { if (MB3_MeshBakerRoot.DO_INTEGRITY_CHECKS) { for (int i = 0; i < distinctMaterialTextures.Count; i++) { MB_TexSet tx1 = distinctMaterialTextures[i]; if (!tx1.allTexturesUseSameMatTiling) { continue; } for (int matIdx = 0; matIdx < tx1.matsAndGOs.mats.Count; matIdx++) { MatAndTransformToMerged mat = tx1.matsAndGOs.mats[matIdx]; DRect uvR = mat.obUVRectIfTilingSame; DRect matR = mat.materialTiling; if (!MB2_TextureBakeResults.IsMeshAndMaterialRectEnclosedByAtlasRect(tx1.tilingTreatment, uvR.GetRect(), matR.GetRect(), tx1.ts[0].GetEncapsulatingSamplingRect().GetRect(), MB2_LogLevel.info)) { Debug.LogErrorFormat("mesh " + tx1.matsAndGOs.mats[matIdx].objName + "\n" + " uv=" + uvR + "\n" + " mat=" + matR.GetRect().ToString("f5") + "\n" + " samplingRect=" + tx1.matsAndGOs.mats[matIdx].samplingRectMatAndUVTiling.GetRect().ToString("f4") + "\n" + " encapsulatingRect " + tx1.ts[0].GetEncapsulatingSamplingRect().GetRect().ToString("f4") + "\n"); Debug.LogErrorFormat(string.Format("Integrity check failed. " + tx1.matsAndGOs.mats[matIdx].objName + " Encapsulating sampling rect failed to contain potentialRect\n")); MB2_TextureBakeResults.IsMeshAndMaterialRectEnclosedByAtlasRect(tx1.tilingTreatment, uvR.GetRect(), matR.GetRect(), tx1.ts[0].GetEncapsulatingSamplingRect().GetRect(), MB2_LogLevel.trace); Debug.Assert(false); } } } } }
/// <summary> /// A material can appear more than once in an atlas if using fixOutOfBoundsUVs. /// in this case you need to use the UV rect of the mesh to find the correct rectangle. /// If the all properties on the mat use the same tiling then /// encapsulatingRect can be larger and will include baked UV and material tiling /// If mat uses different tiling for different maps then encapsulatingRect is the uvs of /// source mesh used to bake atlas and sourceMaterialTilingOut is 0,0,1,1. This works because /// material tiling was baked into the atlas. /// </summary> public bool TryMapMaterialToUVRect(Material mat, Mesh m, int submeshIdx, int idxInResultMats, MB3_MeshCombinerSingle.MeshChannelsCache meshChannelCache, Dictionary <int, MB_Utility.MeshAnalysisResult[]> meshAnalysisCache, out MB_TextureTilingTreatment tilingTreatment, out Rect rectInAtlas, out Rect encapsulatingRectOut, out Rect sourceMaterialTilingOut, out int sliceIdx, ref String errorMsg, MB2_LogLevel logLevel) { if (textureBakeResults.version < MB2_TextureBakeResults.VERSION) { textureBakeResults.UpgradeToCurrentVersion(textureBakeResults); } tilingTreatment = MB_TextureTilingTreatment.unknown; if (textureBakeResults.materialsAndUVRects.Length == 0) { errorMsg = "The 'Texture 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(); encapsulatingRectOut = new Rect(); sourceMaterialTilingOut = new Rect(); sliceIdx = -1; return(false); } if (mat == null) { rectInAtlas = new Rect(); encapsulatingRectOut = new Rect(); sourceMaterialTilingOut = new Rect(); sliceIdx = -1; 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(); encapsulatingRectOut = new Rect(); sourceMaterialTilingOut = new Rect(); sliceIdx = -1; 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(); encapsulatingRectOut = new Rect(); sourceMaterialTilingOut = new Rect(); sliceIdx = -1; errorMsg = String.Format("Material {0} could not be found in the Texture Bake Result", mat.name); return(false); } bool considerUVs = textureBakeResults.GetConsiderMeshUVs(idxInResultMats, mat); if (!considerUVs) { if (numTimesMatAppearsInAtlas[idx] != 1) { Debug.LogError("There is a problem with this TextureBakeResults. FixOutOfBoundsUVs is false and a material appears more than once: " + matsAndSrcUVRect[idx].material + " appears: " + numTimesMatAppearsInAtlas[idx]); } MB_MaterialAndUVRect mr = matsAndSrcUVRect[idx]; rectInAtlas = mr.atlasRect; tilingTreatment = mr.tilingTreatment; encapsulatingRectOut = mr.GetEncapsulatingRect(); sourceMaterialTilingOut = mr.GetMaterialTilingRect(); sliceIdx = mr.textureArraySliceIdx; return(true); } else { //todo what if no UVs //Find UV rect in source mesh MB_Utility.MeshAnalysisResult[] mar; if (!meshAnalysisCache.TryGetValue(m.GetInstanceID(), out mar)) { mar = new MB_Utility.MeshAnalysisResult[m.subMeshCount]; for (int j = 0; j < m.subMeshCount; j++) { Vector2[] uvss = meshChannelCache.GetUv0Raw(m); MB_Utility.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; Rect encapsulatingRect = new Rect(0, 0, 0, 0); Rect sourceMaterialTiling = new Rect(0, 0, 0, 0); if (logLevel >= MB2_LogLevel.trace) { Debug.Log(String.Format("Trying to find a rectangle in atlas capable of holding tiled sampling rect for mesh {0} using material {1} meshUVrect={2}", m, mat, mar[submeshIdx].uvRect.ToString("f5"))); } for (int i = idx; i < matsAndSrcUVRect.Length; i++) { MB_MaterialAndUVRect matAndUVrect = matsAndSrcUVRect[i]; if (matAndUVrect.material == mat) { if (matAndUVrect.allPropsUseSameTiling) { encapsulatingRect = matAndUVrect.allPropsUseSameTiling_samplingEncapsulatinRect; sourceMaterialTiling = matAndUVrect.allPropsUseSameTiling_sourceMaterialTiling; } else { encapsulatingRect = matAndUVrect.propsUseDifferntTiling_srcUVsamplingRect; sourceMaterialTiling = new Rect(0, 0, 1, 1); } if (MB2_TextureBakeResults.IsMeshAndMaterialRectEnclosedByAtlasRect( matAndUVrect.tilingTreatment, mar[submeshIdx].uvRect, sourceMaterialTiling, encapsulatingRect, logLevel)) { if (logLevel >= MB2_LogLevel.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) { MB_MaterialAndUVRect mr = matsAndSrcUVRect[idx]; rectInAtlas = mr.atlasRect; tilingTreatment = mr.tilingTreatment; encapsulatingRectOut = mr.GetEncapsulatingRect(); sourceMaterialTilingOut = mr.GetMaterialTilingRect(); sliceIdx = mr.textureArraySliceIdx; return(true); } else { rectInAtlas = new Rect(); encapsulatingRectOut = new Rect(); sourceMaterialTilingOut = new Rect(); sliceIdx = -1; errorMsg = String.Format("Could not find a tiled rectangle in the atlas capable of containing the uv and material tiling on mesh {0} for material {1}. Was this mesh included when atlases were baked?", m.name, mat); return(false); } } }