public static bool hasOutOfBoundsUVs(Mesh m, ref MeshAnalysisResult putResultHere, int submeshIndex = -1, int uvChannel = 0) { if (m == null) { putResultHere.hasOutOfBoundsUVs = false; return(putResultHere.hasOutOfBoundsUVs); } Vector2[] uvs; if (uvChannel == 0) { uvs = m.uv; } else if (uvChannel == 1) { uvs = m.uv2; } else if (uvChannel == 2) { uvs = m.uv3; } else { uvs = m.uv4; } return(hasOutOfBoundsUVs(uvs, m, ref putResultHere, submeshIndex)); }
public static int doSubmeshesShareVertsOrTris(Mesh m, ref MeshAnalysisResult mar) { MB_Triangle consider = new MB_Triangle(); MB_Triangle other = new MB_Triangle(); //cache all triangles int[][] tris = new int[m.subMeshCount][]; for (int i = 0; i < m.subMeshCount; i++) { tris[i] = m.GetTriangles(i); } bool sharesVerts = false; bool sharesTris = false; for (int i = 0; i < m.subMeshCount; i++) { int[] smA = tris[i]; for (int j = i + 1; j < m.subMeshCount; j++) { int[] smB = tris[j]; for (int k = 0; k < smA.Length; k += 3) { consider.Initialize(smA, k, i); for (int l = 0; l < smB.Length; l += 3) { other.Initialize(smB, l, j); if (consider.isSame(other)) { sharesTris = true; break; } if (consider.sharesVerts(other)) { sharesVerts = true; break; } } } } } if (sharesTris) { mar.hasOverlappingSubmeshVerts = true; mar.hasOverlappingSubmeshTris = true; return(2); } else if (sharesVerts) { mar.hasOverlappingSubmeshVerts = true; mar.hasOverlappingSubmeshTris = false; return(1); } else { mar.hasOverlappingSubmeshTris = false; mar.hasOverlappingSubmeshVerts = false; return(0); } }
public static bool hasOutOfBoundsUVs(Mesh m, ref Rect uvBounds) { MeshAnalysisResult mar = new MeshAnalysisResult(); bool outVal = hasOutOfBoundsUVs(m, ref mar); uvBounds = mar.uvRect; return(outVal); }
public static bool hasOutOfBoundsUVs(Mesh m, ref MeshAnalysisResult putResultHere, int submeshIndex = -1) { if (m == null) { putResultHere.hasOutOfBoundsUVs = false; return(putResultHere.hasOutOfBoundsUVs); } Vector2[] uvs = m.uv; return(hasOutOfBoundsUVs(uvs, m, ref putResultHere, submeshIndex)); }
public static bool hasOutOfBoundsUVs(Vector2[] uvs, Mesh m, ref MeshAnalysisResult putResultHere, int submeshIndex = -1) { putResultHere.hasUVs = true; if (uvs.Length == 0) { putResultHere.hasUVs = false; putResultHere.hasOutOfBoundsUVs = false; putResultHere.uvRect = new Rect(); return(putResultHere.hasOutOfBoundsUVs); } float minx, miny, maxx, maxy; if (submeshIndex >= m.subMeshCount) { putResultHere.hasOutOfBoundsUVs = false; putResultHere.uvRect = new Rect(); return(putResultHere.hasOutOfBoundsUVs); } else if (submeshIndex >= 0) { //checking specific submesh int[] tris = m.GetTriangles(submeshIndex); if (tris.Length == 0) { putResultHere.hasOutOfBoundsUVs = false; putResultHere.uvRect = new Rect(); return(putResultHere.hasOutOfBoundsUVs); } minx = maxx = uvs[tris[0]].x; miny = maxy = uvs[tris[0]].y; for (int idx = 0; idx < tris.Length; idx++) { int i = tris[idx]; if (uvs[i].x < minx) { minx = uvs[i].x; } if (uvs[i].x > maxx) { maxx = uvs[i].x; } if (uvs[i].y < miny) { miny = uvs[i].y; } if (uvs[i].y > maxy) { maxy = uvs[i].y; } } } else { //checking all UVs minx = maxx = uvs[0].x; miny = maxy = uvs[0].y; for (int i = 0; i < uvs.Length; i++) { if (uvs[i].x < minx) { minx = uvs[i].x; } if (uvs[i].x > maxx) { maxx = uvs[i].x; } if (uvs[i].y < miny) { miny = uvs[i].y; } if (uvs[i].y > maxy) { maxy = uvs[i].y; } } } Rect uvBounds = new Rect(); uvBounds.x = minx; uvBounds.y = miny; uvBounds.width = maxx - minx; uvBounds.height = maxy - miny; if (maxx > 1f || minx < 0f || maxy > 1f || miny < 0f) { putResultHere.hasOutOfBoundsUVs = true; } else { putResultHere.hasOutOfBoundsUVs = false; } putResultHere.uvRect = uvBounds; return(putResultHere.hasOutOfBoundsUVs); }
//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); }
public static bool hasOutOfBoundsUVs(Mesh m, ref Rect uvBounds, ref MeshAnalysisResult putResultHere, int submeshIndex = -1) { if (m == null) { putResultHere.hasOutOfBoundsUVs = false; return(putResultHere.hasOutOfBoundsUVs); } Vector2[] uvs = m.uv; if (uvs.Length == 0) { putResultHere.hasOutOfBoundsUVs = false; putResultHere.uvRect = uvBounds; return(putResultHere.hasOutOfBoundsUVs); } float minx, miny, maxx, maxy; if (submeshIndex >= m.subMeshCount) { putResultHere.hasOutOfBoundsUVs = false; putResultHere.uvRect = uvBounds; return(putResultHere.hasOutOfBoundsUVs); } else if (submeshIndex >= 0) { //checking specific submesh int[] tris = m.GetTriangles(submeshIndex); if (tris.Length == 0) { putResultHere.hasOutOfBoundsUVs = false; putResultHere.uvRect = uvBounds; return(putResultHere.hasOutOfBoundsUVs); } minx = maxx = uvs[tris[0]].x; miny = maxy = uvs[tris[0]].y; for (int idx = 0; idx < tris.Length; idx++) { int i = tris[idx]; if (uvs[i].x < minx) { minx = uvs[i].x; } if (uvs[i].x > maxx) { maxx = uvs[i].x; } if (uvs[i].y < miny) { miny = uvs[i].y; } if (uvs[i].y > maxy) { maxy = uvs[i].y; } } } else { //checking all UVs minx = maxx = uvs[0].x; miny = maxy = uvs[0].y; for (int i = 0; i < uvs.Length; i++) { if (uvs[i].x < minx) { minx = uvs[i].x; } if (uvs[i].x > maxx) { maxx = uvs[i].x; } if (uvs[i].y < miny) { miny = uvs[i].y; } if (uvs[i].y > maxy) { maxy = uvs[i].y; } } } uvBounds.x = minx; uvBounds.y = miny; uvBounds.width = maxx - minx; uvBounds.height = maxy - miny; if (maxx > 1f || minx < 0f || maxy > 1f || miny < 0f) { putResultHere.hasOutOfBoundsUVs = true; putResultHere.uvRect = uvBounds; return(putResultHere.hasOutOfBoundsUVs); } //all well behaved objs use the same rect so TexSets compare properly uvBounds.x = uvBounds.y = 0f; uvBounds.width = uvBounds.height = 1f; putResultHere.uvRect = uvBounds; putResultHere.hasOutOfBoundsUVs = false; return(putResultHere.hasOutOfBoundsUVs); }
public static bool hasOutOfBoundsUVs(Mesh m, ref Rect uvBounds) { MeshAnalysisResult mar = new MeshAnalysisResult(); return(hasOutOfBoundsUVs(m, ref uvBounds, ref mar)); }
public static int doSubmeshesShareVertsOrTris(Mesh m, ref MeshAnalysisResult mar){ MB_Triangle consider = new MB_Triangle(); MB_Triangle other = new MB_Triangle(); //cache all triangles int[][] tris = new int[m.subMeshCount][]; for (int i = 0; i < m.subMeshCount; i++){ tris[i] = m.GetTriangles(i); } bool sharesVerts = false; bool sharesTris = false; for (int i = 0; i < m.subMeshCount; i++){ int[] smA = tris[i]; for (int j = i+1; j < m.subMeshCount; j++){ int[] smB = tris[j]; for (int k = 0; k < smA.Length; k+=3){ consider.Initialize(smA,k,i); for (int l = 0; l < smB.Length; l+=3){ other.Initialize(smB,l,j); if (consider.isSame(other)){ sharesTris = true; break; } if (consider.sharesVerts(other)){ sharesVerts = true; break; } } } } } if (sharesTris){ mar.hasOverlappingSubmeshVerts = true; mar.hasOverlappingSubmeshTris = true; return 2; } else if (sharesVerts){ mar.hasOverlappingSubmeshVerts = true; mar.hasOverlappingSubmeshTris = false; return 1; } else { mar.hasOverlappingSubmeshTris = false; mar.hasOverlappingSubmeshVerts = false; return 0; } }
public static bool hasOutOfBoundsUVs(Mesh m, ref Rect uvBounds, ref MeshAnalysisResult putResultHere, int submeshIndex = -1){ if (m == null){ putResultHere.hasOutOfBoundsUVs = false; return putResultHere.hasOutOfBoundsUVs; } Vector2[] uvs = m.uv; if (uvs.Length == 0){ putResultHere.hasOutOfBoundsUVs = false; putResultHere.uvRect = uvBounds; return putResultHere.hasOutOfBoundsUVs; } float minx,miny,maxx,maxy; if (submeshIndex >= m.subMeshCount){ putResultHere.hasOutOfBoundsUVs = false; putResultHere.uvRect = uvBounds; return putResultHere.hasOutOfBoundsUVs; } else if (submeshIndex >= 0){ //checking specific submesh int[] tris = m.GetTriangles(submeshIndex); if (tris.Length == 0) { putResultHere.hasOutOfBoundsUVs = false; putResultHere.uvRect = uvBounds; return putResultHere.hasOutOfBoundsUVs; } minx = maxx = uvs[tris[0]].x; miny = maxy = uvs[tris[0]].y; for (int idx = 0; idx < tris.Length; idx++){ int i = tris[idx]; if (uvs[i].x < minx) minx = uvs[i].x; if (uvs[i].x > maxx) maxx = uvs[i].x; if (uvs[i].y < miny) miny = uvs[i].y; if (uvs[i].y > maxy) maxy = uvs[i].y; } } else { //checking all UVs minx = maxx = uvs[0].x; miny = maxy = uvs[0].y; for (int i = 0; i < uvs.Length; i++){ if (uvs[i].x < minx) minx = uvs[i].x; if (uvs[i].x > maxx) maxx = uvs[i].x; if (uvs[i].y < miny) miny = uvs[i].y; if (uvs[i].y > maxy) maxy = uvs[i].y; } } uvBounds.x = minx; uvBounds.y = miny; uvBounds.width = maxx - minx; uvBounds.height = maxy - miny; if (maxx > 1f || minx < 0f || maxy > 1f || miny < 0f){ putResultHere.hasOutOfBoundsUVs = true; putResultHere.uvRect = uvBounds; return putResultHere.hasOutOfBoundsUVs; } //all well behaved objs use the same rect so TexSets compare properly uvBounds.x = uvBounds.y = 0f; uvBounds.width = uvBounds.height = 1f; putResultHere.uvRect = uvBounds; putResultHere.hasOutOfBoundsUVs = false; return putResultHere.hasOutOfBoundsUVs; }
public static bool hasOutOfBoundsUVs(Mesh m, ref Rect uvBounds){ MeshAnalysisResult mar = new MeshAnalysisResult(); return hasOutOfBoundsUVs(m,ref uvBounds, ref mar); }
/// <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); }