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; } //Integrity check that sampling rects fit into enapsulating rects //DRect encapsulatingRectCannonical = tx1.ts[0].encapsulatingSamplingRect; //MB3_UVTransformUtility.Canonicalize(ref encapsulatingRectCannonical, 0, 0); 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(uvR.GetRect(), matR.GetRect(), tx1.ts[0].encapsulatingSamplingRect.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].encapsulatingSamplingRect.GetRect().ToString("f4") + "\n"); //" encapsulatingRectCannonical=" + rr.ToString("f4") + "\n\n"); Debug.LogErrorFormat(string.Format("Integrity check failed. " + tx1.matsAndGOs.mats[matIdx].objName + " Encapsulating sampling rect failed to contain potentialRect\n")); MB2_TextureBakeResults.IsMeshAndMaterialRectEnclosedByAtlasRect(uvR.GetRect(), matR.GetRect(), tx1.ts[0].encapsulatingSamplingRect.GetRect(), MB2_LogLevel.trace); Debug.Assert(false); } } } } }
/* * public class SamplingRectEnclosesComparer : IComparer<MatAndTransformToMerged> * { * public int Compare(MatAndTransformToMerged x, MatAndTransformToMerged y) * { * if (x.samplingRectMatAndUVTiling.Equals(y.samplingRectMatAndUVTiling)) * { * return 0; * } * else if (x.samplingRectMatAndUVTiling.Encloses(y.samplingRectMatAndUVTiling)) * { * return -1; * } * else * { * return 1; * } * } * } */ public static Rect BuildTransformMeshUV2AtlasRectB(bool considerMeshUVs, Rect _atlasRect, //this is uvRect in combined Atlas Rect _obUVRect, Rect _sourceMaterialTiling, Rect _encapsulatingRect) { DRect atlasRect = new DRect(_atlasRect); DRect obUVRect; if (considerMeshUVs) { obUVRect = new DRect(_obUVRect); //this is the uvRect in src mesh } else { obUVRect = new DRect(0.0, 0.0, 1.0, 1.0); } DRect sourceMaterialTiling = new DRect(_sourceMaterialTiling); DRect encapsulatingRectMatAndUVTiling = new DRect(_encapsulatingRect); DRect encapsulatingRectMatAndUVTilingInverse = MB3_UVTransformUtility.InverseTransform(ref encapsulatingRectMatAndUVTiling); DRect toNormalizedUVs = MB3_UVTransformUtility.InverseTransform(ref obUVRect); DRect meshFullSamplingRect = MB3_UVTransformUtility.CombineTransforms(ref obUVRect, ref sourceMaterialTiling); DRect shiftToFitInEncapsulating = MB3_UVTransformUtility.GetShiftTransformToFitBinA(ref encapsulatingRectMatAndUVTiling, ref meshFullSamplingRect); meshFullSamplingRect = MB3_UVTransformUtility.CombineTransforms(ref meshFullSamplingRect, ref shiftToFitInEncapsulating); //transform between full sample rect and encapsulating rect DRect relativeTrans = MB3_UVTransformUtility.CombineTransforms(ref meshFullSamplingRect, ref encapsulatingRectMatAndUVTilingInverse); // [transform] = [toNormalizedUVs][relativeTrans][uvSubRectInAtlas] DRect trans = MB3_UVTransformUtility.CombineTransforms(ref toNormalizedUVs, ref relativeTrans); trans = MB3_UVTransformUtility.CombineTransforms(ref trans, ref atlasRect); Rect rr = trans.GetRect(); return(rr); /* * Debug.Log("toNormalizedUVs " + toNormalizedUVs); * Debug.Log("relativeTrans " + relativeTrans); * Debug.Log("atlasRect " + atlasRect); * Debug.Log("trans " + trans); * Debug.Log("srcMatTiling " + sourceMaterialTiling); * Debug.Log("obUVRect" + obUVRect); * Debug.Log("samplingRectMatAndUVTiling" + encapsulatingRectMatAndUVTiling); */ }
internal static void BuildAtlas( AtlasPackingResult packedAtlasRects, List <MB_TexSet> distinctMaterialTextures, int propIdx, int atlasSizeX, int atlasSizeY, Mesh m, List <Material> generatedMats, ShaderTextureProperty property, MB3_TextureCombinerPipeline.TexturePipelineData data, MB3_TextureCombiner combiner, MB2_EditorMethodsInterface textureEditorMethods, MB2_LogLevel LOG_LEVEL) { // Collect vertices and quads for mesh that we will use for the atlas. Debug.Assert(generatedMats.Count == 0, "Previous mats should have been destroyed"); generatedMats.Clear(); List <Vector3> vs = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); // One submesh and material per texture that we are packing List <int>[] ts = new List <int> [distinctMaterialTextures.Count]; for (int i = 0; i < ts.Length; i++) { ts[i] = new List <int>(); } MeshBakerMaterialTexture.readyToBuildAtlases = true; GC.Collect(); MB3_TextureCombinerPackerRoot.CreateTemporaryTexturesForAtlas(data.distinctMaterialTextures, combiner, propIdx, data); Rect[] uvRects = packedAtlasRects.rects; for (int texSetIdx = 0; texSetIdx < distinctMaterialTextures.Count; texSetIdx++) { MB_TexSet texSet = distinctMaterialTextures[texSetIdx]; MeshBakerMaterialTexture matTex = texSet.ts[propIdx]; if (LOG_LEVEL >= MB2_LogLevel.trace) { Debug.Log(string.Format("Adding texture {0} to atlas {1} for texSet {2} srcMat {3}", matTex.GetTexName(), property.name, texSetIdx, texSet.matsAndGOs.mats[0].GetMaterialName())); } Rect r = uvRects[texSetIdx]; Texture2D t = matTex.GetTexture2D(); int x = Mathf.RoundToInt(r.x * atlasSizeX); int y = Mathf.RoundToInt(r.y * atlasSizeY); int ww = Mathf.RoundToInt(r.width * atlasSizeX); int hh = Mathf.RoundToInt(r.height * atlasSizeY); r = new Rect(x, y, ww, hh); if (ww == 0 || hh == 0) { Debug.LogError("Image in atlas has no height or width " + r); } DRect samplingRect = texSet.ts[propIdx].GetEncapsulatingSamplingRect(); Debug.Assert(!texSet.ts[propIdx].isNull, string.Format("Adding texture {0} to atlas {1} for texSet {2} srcMat {3}", matTex.GetTexName(), property.name, texSetIdx, texSet.matsAndGOs.mats[0].GetMaterialName())); AtlasPadding padding = packedAtlasRects.padding[texSetIdx]; AddNineSlicedRect(r, padding.leftRight, padding.topBottom, samplingRect.GetRect(), vs, uvs, ts[texSetIdx], t.width, t.height, t.name); Material mt = new Material(Shader.Find("MeshBaker/Unlit/UnlitWithAlpha")); bool isSavingAsANormalMapAssetThatWillBeImported = property.isNormalMap && data._saveAtlasesAsAssets; MBVersion.PipelineType pipelineType = MBVersion.DetectPipeline(); if (pipelineType == MBVersion.PipelineType.URP) { ConfigureMaterial_DefaultPipeline(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL); //ConfigureMaterial_URP(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL); } else if (pipelineType == MBVersion.PipelineType.HDRP) { ConfigureMaterial_DefaultPipeline(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL); } else { ConfigureMaterial_DefaultPipeline(mt, t, isSavingAsANormalMapAssetThatWillBeImported, LOG_LEVEL); } generatedMats.Add(mt); } // Apply to the mesh m.Clear(); m.vertices = vs.ToArray(); m.uv = uvs.ToArray(); m.subMeshCount = ts.Length; for (int i = 0; i < m.subMeshCount; i++) { m.SetIndices(ts[i].ToArray(), MeshTopology.Triangles, i); } MeshBakerMaterialTexture.readyToBuildAtlases = false; }