public void SetTilingTreatmentAndAdjustEncapsulatingSamplingRect(MB_TextureTilingTreatment newTilingTreatment) { Debug.Assert(texSet.allTexturesUseSameMatTiling == false); if (texSet.tilingTreatment == MB_TextureTilingTreatment.edgeToEdgeX) { foreach (MeshBakerMaterialTexture t in texSet.ts) { DRect r = t.GetEncapsulatingSamplingRect(); r.width = 1; t.SetEncapsulatingSamplingRect(texSet, r); } } else if (texSet.tilingTreatment == MB_TextureTilingTreatment.edgeToEdgeY) { foreach (MeshBakerMaterialTexture t in texSet.ts) { DRect r = t.GetEncapsulatingSamplingRect(); r.height = 1; t.SetEncapsulatingSamplingRect(texSet, r); } } else if (texSet.tilingTreatment == MB_TextureTilingTreatment.edgeToEdgeXY) { foreach (MeshBakerMaterialTexture t in texSet.ts) { DRect r = t.GetEncapsulatingSamplingRect(); r.height = 1; r.width = 1; t.SetEncapsulatingSamplingRect(texSet, r); } } }
/// <param name="mat">The Material</param> /// <param name="destRect">The rect in the atlas this material maps to</param> /// <param name="allPropsUseSameTiling">If true then use sourceMaterialTiling and samplingEncapsulatingRect. /// if false then use srcUVsamplingRect. None used values should be 0,0,0,0.</param> /// <param name="sourceMaterialTiling">allPropsUseSameTiling_sourceMaterialTiling</param> /// <param name="samplingEncapsulatingRect">allPropsUseSameTiling_samplingEncapsulatinRect</param> /// <param name="srcUVsamplingRect">propsUseDifferntTiling_srcUVsamplingRect</param> public MB_MaterialAndUVRect(Material mat, Rect destRect, bool allPropsUseSameTiling, Rect sourceMaterialTiling, Rect samplingEncapsulatingRect, Rect srcUVsamplingRect, MB_TextureTilingTreatment treatment, string objName) { if (allPropsUseSameTiling) { Debug.Assert(srcUVsamplingRect == new Rect(0, 0, 0, 0)); } if (!allPropsUseSameTiling) { Debug.Assert(samplingEncapsulatingRect == new Rect(0, 0, 0, 0)); Debug.Assert(sourceMaterialTiling == new Rect(0, 0, 0, 0)); } material = mat; atlasRect = destRect; tilingTreatment = treatment; this.allPropsUseSameTiling = allPropsUseSameTiling; allPropsUseSameTiling_sourceMaterialTiling = sourceMaterialTiling; allPropsUseSameTiling_samplingEncapsulatinRect = samplingEncapsulatingRect; propsUseDifferntTiling_srcUVsamplingRect = srcUVsamplingRect; srcObjName = objName; }
public static bool IsMeshAndMaterialRectEnclosedByAtlasRect(MB_TextureTilingTreatment tilingTreatment, Rect uvR, Rect sourceMaterialTiling, Rect samplingEncapsulatinRect, MB2_LogLevel logLevel) { Rect potentialRect = new Rect(); Rect matR = sourceMaterialTiling; // test to see if this would fit in what was baked in the atlas Rect rr = samplingEncapsulatinRect; potentialRect = MB3_UVTransformUtility.CombineTransforms(ref uvR, ref matR); if (logLevel >= MB2_LogLevel.trace) { if (logLevel >= MB2_LogLevel.trace) { Debug.Log("uvR=" + uvR.ToString("f5") + " matR=" + matR.ToString("f5") + "Potential Rect " + potentialRect.ToString("f5") + " encapsulating=" + rr.ToString("f5")); } } if (logLevel >= MB2_LogLevel.trace) { if (logLevel >= MB2_LogLevel.trace) { Debug.Log("Potential Rect Cannonical " + potentialRect.ToString("f5") + " encapsulating=" + rr.ToString("f5")); } } if (tilingTreatment == MB_TextureTilingTreatment.edgeToEdgeX) { if (MB3_UVTransformUtility.LineSegmentContainsShifted(rr.y, rr.height, potentialRect.y, potentialRect.height)) { return(true); } } else if (tilingTreatment == MB_TextureTilingTreatment.edgeToEdgeY) { if (MB3_UVTransformUtility.LineSegmentContainsShifted(rr.x, rr.width, potentialRect.x, potentialRect.width)) { return(true); } } else if (tilingTreatment == MB_TextureTilingTreatment.edgeToEdgeXY) { //only one rect in atlas and is edge to edge in both X and Y directions. return(true); } else { if (MB3_UVTransformUtility.RectContainsShifted(ref rr, ref potentialRect)) { return(true); } } return(false); }
public MB_TexSet(MeshBakerMaterialTexture[] tss, Vector2 uvOffset, Vector2 uvScale, MB_TextureTilingTreatment treatment) { ts = tss; tilingTreatment = treatment; obUVoffset = uvOffset; obUVscale = uvScale; allTexturesUseSameMatTiling = false; thisIsOnlyTexSetInAtlas = false; matsAndGOs = new MatsAndGOs(); matsAndGOs.mats = new List<MatAndTransformToMerged>(); matsAndGOs.gos = new List<GameObject>(); pipelineVariation = new PipelineVariationSomeTexturesUseDifferentMatTiling(this); }
/// <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, ref String errorMsg, MB2_LogLevel logLevel) { if (tbr.version < VERSION) { UpgradeToCurrentVersion(tbr); } tilingTreatment = MB_TextureTilingTreatment.unknown; if (tbr.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(); return(false); } if (mat == null) { rectInAtlas = new Rect(); encapsulatingRectOut = 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(); encapsulatingRectOut = 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(); encapsulatingRectOut = new Rect(); sourceMaterialTilingOut = new Rect(); errorMsg = String.Format("Material {0} could not be found in the Texture Bake Result", mat.name); return(false); } if (!tbr.resultMaterials[idxInResultMats].considerMeshUVs) { if (numTimesMatAppearsInAtlas[idx] != 1) { Debug.LogError("There is a problem with this TextureBakeResults. FixOutOfBoundsUVs is false and a material appears more than once."); } MB_MaterialAndUVRect mr = matsAndSrcUVRect[idx]; rectInAtlas = mr.atlasRect; tilingTreatment = mr.tilingTreatment; encapsulatingRectOut = mr.GetEncapsulatingRect(); sourceMaterialTilingOut = mr.GetMaterialTilingRect(); 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 (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(); return(true); } else { rectInAtlas = new Rect(); encapsulatingRectOut = 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} for material {1}", m.name, mat); return(false); } } }
public void SetTilingTreatmentAndAdjustEncapsulatingSamplingRect(MB_TextureTilingTreatment newTilingTreatment) { tilingTreatment = newTilingTreatment; pipelineVariation.SetTilingTreatmentAndAdjustEncapsulatingSamplingRect(newTilingTreatment); }
public bool MapSharedMaterialsToAtlasRects(Material[] sharedMaterials, bool checkTargetSubmeshIdxsFromPreviousBake, Mesh m, MeshChannelsCache meshChannelsCache, Dictionary <int, MB_Utility.MeshAnalysisResult[]> meshAnalysisResultsCache, OrderedDictionary sourceMats2submeshIdx_map, GameObject go, MB_DynamicGameObject dgoOut) { MB_TextureTilingTreatment[] tilingTreatment = new MB_TextureTilingTreatment[sharedMaterials.Length]; Rect[] uvRectsInAtlas = new Rect[sharedMaterials.Length]; Rect[] encapsulatingRect = new Rect[sharedMaterials.Length]; Rect[] sourceMaterialTiling = new Rect[sharedMaterials.Length]; int[] sliceIdx = new int[sharedMaterials.Length]; String errorMsg = ""; for (int srcSubmeshIdx = 0; srcSubmeshIdx < sharedMaterials.Length; srcSubmeshIdx++) { System.Object subIdx = sourceMats2submeshIdx_map[sharedMaterials[srcSubmeshIdx]]; int resMatIdx; if (subIdx == null) { Debug.LogError("Source object " + go.name + " used a material " + sharedMaterials[srcSubmeshIdx] + " that was not in the baked materials."); return(false); } else { resMatIdx = (int)subIdx; if (checkTargetSubmeshIdxsFromPreviousBake) { /* * Possibilities: * Consider a mesh with three submeshes with materials A, B, C that map to * different submeshes in the combined mesh, AA,BB,CC. The user is updating the UVs on a * MeshRenderer so that object 'one' now uses material C => CC instead of A => AA. This will mean that the * triangle buffers will need to be resized. This is not allowed in UpdateGameObjects. * Must map to the same submesh that the old one mapped to. */ if (resMatIdx != dgoOut.targetSubmeshIdxs[srcSubmeshIdx]) { Debug.LogError(String.Format("Update failed for object {0}. Material {1} is mapped to a different submesh in the combined mesh than the previous material. This is not supported. Try using AddDelete.", go.name, sharedMaterials[srcSubmeshIdx])); return(false); } } } if (!TryMapMaterialToUVRect(sharedMaterials[srcSubmeshIdx], m, srcSubmeshIdx, resMatIdx, meshChannelsCache, meshAnalysisResultsCache, out tilingTreatment[srcSubmeshIdx], out uvRectsInAtlas[srcSubmeshIdx], out encapsulatingRect[srcSubmeshIdx], out sourceMaterialTiling[srcSubmeshIdx], out sliceIdx[srcSubmeshIdx], ref errorMsg, LOG_LEVEL)) { Debug.LogError(errorMsg); return(false); } } dgoOut.uvRects = uvRectsInAtlas; dgoOut.encapsulatingRect = encapsulatingRect; dgoOut.sourceMaterialTiling = sourceMaterialTiling; dgoOut.textureArraySliceIdx = sliceIdx; return(true); }