/// <summary> /// 合并游戏物体列表,空物体,重复物体,空材质,网格验证 /// </summary> /// <param name="gameObjectsToMesh"></param> /// <returns></returns> private static bool ValidateCombineGameObject(List <GameObject> gameObjectsToMesh) { //网格分析结果缓存 Dictionary <int, MeshAnalysisResult> meshAnalysisResultCache = new Dictionary <int, MeshAnalysisResult>();; //获取将合并网格的游戏物体 List <GameObject> objsToMesh = gameObjectsToMesh; for (int i = 0; i < objsToMesh.Count; i++) { GameObject go = objsToMesh[i]; if (go == null) { Debug.LogError("合并网格游戏物体列表中包含 null 物体,在位置" + i); return(false); } for (int j = i + 1; j < objsToMesh.Count; j++) { if (objsToMesh[i] == objsToMesh[j]) { Debug.LogError("合并网格游戏物体列表中包含重复游戏物体 " + i + " 和 " + j); return(false); } } if (MeshBakerUtility.GetGOMaterials(go).Length == 0) { Debug.LogError("游戏物体 " + go + " 没有材质"); return(false); } Mesh m = MeshBakerUtility.GetMesh(go); if (m == null) { Debug.LogError("合并网格游戏物体列表中, " + go + " 没有网格 "); return(false); } if (m != null) { //This check can be very expensive and it only warns so only do this if we are in the editor. if (!Application.isEditor && Application.isPlaying && combineData.DoMultiMaterial) { MeshAnalysisResult mar; if (!meshAnalysisResultCache.TryGetValue(m.GetInstanceID(), out mar)) { MeshBakerUtility.doSubmeshesShareVertsOrTris(m, ref mar); meshAnalysisResultCache.Add(m.GetInstanceID(), mar); } //检查重叠的子网格顶点 if (mar.hasOverlappingSubmeshVerts) { Debug.LogWarning("游戏物体 " + objsToMesh[i] + " has overlapping submeshes (submeshes share vertices)." + "If the UVs associated with the shared vertices are important then this bake may not work. " + "If you are using multiple materials then this object can only be combined with objects that use the exact same set of textures " + "(each atlas contains one texture). There may be other undesirable side affects as well. Mesh Master, " + "available in the asset store can fix overlapping submeshes."); } } } } return(true); }
/* 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); }
public static bool DoCombinedValidate(MeshBakerRoot mom, MB_ObjsToCombineTypes objToCombineType, MBValidationLevel validationLevel) { if (mom.textureBakeResults == null) { Debug.LogError("Need to set Material Bake Result on " + mom); return(false); } if (mom is MeshBakerCommon) { MeshBakerCommon momMB = (MeshBakerCommon)mom; TextureBaker tb = momMB.GetTextureBaker(); if (tb != null && tb.textureBakeResults != mom.textureBakeResults) { Debug.LogWarning("Material Bake Result on this component is not the same as the Material Bake Result on the MB3_TextureBaker."); } } Dictionary <int, MeshBakerUtility.MeshAnalysisResult> meshAnalysisResultCache = null; if (validationLevel == MBValidationLevel.robust) { meshAnalysisResultCache = new Dictionary <int, MeshBakerUtility.MeshAnalysisResult>(); } List <GameObject> objsToMesh = mom.GetObjectsToCombine(); for (int i = 0; i < objsToMesh.Count; i++) { GameObject go = objsToMesh[i]; if (go == null) { Debug.LogError("The list of objects to combine contains a null at position." + i + " Select and use [shift] delete to remove"); return(false); } for (int j = i + 1; j < objsToMesh.Count; j++) { if (objsToMesh[i] == objsToMesh[j]) { Debug.LogError("The list of objects to combine contains duplicates at " + i + " and " + j); return(false); } } if (MeshBakerUtility.GetGOMaterials(go) == null) { Debug.LogError("Object " + go + " in the list of objects to be combined does not have a material"); return(false); } Mesh m = MeshBakerUtility.GetMesh(go); if (m == null) { Debug.LogError("Object " + go + " in the list of objects to be combined does not have a mesh"); return(false); } if (m != null) //This check can be very expensive and it only warns so only do this if we are in the editor. { if (!Application.isEditor && Application.isPlaying && mom.textureBakeResults.doMultiMaterial && validationLevel >= MBValidationLevel.robust) { MeshBakerUtility.MeshAnalysisResult mar; if (!meshAnalysisResultCache.TryGetValue(m.GetInstanceID(), out mar)) { MeshBakerUtility.doSubmeshesShareVertsOrTris(m, ref mar); meshAnalysisResultCache.Add(m.GetInstanceID(), mar); } if (mar.hasOverlappingSubmeshVerts) { Debug.LogWarning("Object " + objsToMesh[i] + " in the list of objects to combine has overlapping submeshes (submeshes share vertices). If the UVs associated with the shared vertices are important then this bake may not work. If you are using multiple materials then this object can only be combined with objects that use the exact same set of textures (each atlas contains one texture). There may be other undesirable side affects as well. Mesh Master, available in the asset store can fix overlapping submeshes."); } } } } List <GameObject> objs = objsToMesh; if (mom is MeshBaker) { objs = mom.GetObjectsToCombine(); //if (((MB3_MeshBaker)mom).useObjsToMeshFromTexBaker && tb != null) objs = tb.GetObjectsToCombine(); if (objs == null || objs.Count == 0) { Debug.LogError("No meshes to combine. Please assign some meshes to combine."); return(false); } } return(true); }