bool _validateTextureBakeResults() { if (_textureBakeResults == null) { Debug.LogError("Texture Bake Results is null. Can't combine meshes."); return(false); } if ((_textureBakeResults.materialsAndUVRects == null || _textureBakeResults.materialsAndUVRects.Length == 0)) { Debug.LogError("Texture Bake Results has no materials in material to sourceUVRect map. Try baking materials. Can't combine meshes."); return(false); } if (_textureBakeResults.resultMaterials == null || _textureBakeResults.resultMaterials.Length == 0) { if (_textureBakeResults.materialsAndUVRects != null && _textureBakeResults.materialsAndUVRects.Length > 0 && _textureBakeResults.doMultiMaterial == false && _textureBakeResults.resultMaterial != null) { //backward compatibility MB_MultiMaterial[] mm = _textureBakeResults.resultMaterials = new MB_MultiMaterial[1]; mm[0] = new MB_MultiMaterial(); mm[0].combinedMaterial = _textureBakeResults.resultMaterial; mm[0].considerMeshUVs = _textureBakeResults.fixOutOfBoundsUVs; List <Material> mats = mm[0].sourceMaterials = new List <Material>(); for (int i = 0; i < _textureBakeResults.materialsAndUVRects.Length; i++) { if (!mats.Contains(_textureBakeResults.materialsAndUVRects[i].material)) { mats.Add(_textureBakeResults.materialsAndUVRects[i].material); } } } else { Debug.LogError("Texture Bake Results has no result materials. Try baking materials. Can't combine meshes."); return(false); } } return(true); }
bool _ValidateResultMaterials() { HashSet <Material> allMatsOnObjs = new HashSet <Material>(); for (int i = 0; i < objsToMesh.Count; i++) { if (objsToMesh[i] != null) { Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]); for (int j = 0; j < ms.Length; j++) { if (ms[j] != null) { allMatsOnObjs.Add(ms[j]); } } } } HashSet <Material> allMatsInMapping = new HashSet <Material>(); for (int i = 0; i < resultMaterials.Length; i++) { MB_MultiMaterial mm = resultMaterials[i]; if (mm.combinedMaterial == null) { Debug.LogError("Combined Material is null please create and assign a result material."); return(false); } Shader targShader = mm.combinedMaterial.shader; for (int j = 0; j < mm.sourceMaterials.Count; j++) { if (mm.sourceMaterials[j] == null) { Debug.LogError("There are null entries in the list of Source Materials"); return(false); } if (targShader != mm.sourceMaterials[j].shader) { Debug.LogWarning("Source material " + mm.sourceMaterials[j] + " does not use shader " + targShader + " it may not have the required textures. If not empty textures will be generated."); } if (allMatsInMapping.Contains(mm.sourceMaterials[j])) { Debug.LogError("A Material " + mm.sourceMaterials[j] + " appears more than once in the list of source materials in the source material to combined mapping. Each source material must be unique."); return(false); } allMatsInMapping.Add(mm.sourceMaterials[j]); } } if (allMatsOnObjs.IsProperSubsetOf(allMatsInMapping)) { allMatsInMapping.ExceptWith(allMatsOnObjs); Debug.LogWarning("There are materials in the mapping that are not used on your source objects: " + PrintSet(allMatsInMapping)); } if (resultMaterials != null && resultMaterials.Length > 0 && allMatsInMapping.IsProperSubsetOf(allMatsOnObjs)) { allMatsOnObjs.ExceptWith(allMatsInMapping); Debug.LogError("There are materials on the objects to combine that are not in the mapping: " + PrintSet(allMatsOnObjs)); return(false); } return(true); }
public IEnumerator CreateAtlasesCoroutine(ProgressUpdateDelegate progressInfo, CreateAtlasesCoroutineResult coroutineResult, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null, float maxTimePerFrame = .01f) { MBVersionConcrete mbv = new MBVersionConcrete(); if (!MB3_TextureCombiner._RunCorutineWithoutPauseIsRunning && (mbv.GetMajorVersion() < 5 || (mbv.GetMajorVersion() == 5 && mbv.GetMinorVersion() < 3))) { Debug.LogError("Running the texture combiner as a coroutine only works in Unity 5.3 and higher"); coroutineResult.success = false; yield break; } this.OnCombinedTexturesCoroutineAtlasesAndRects = null; if (maxTimePerFrame <= 0f) { Debug.LogError("maxTimePerFrame must be a value greater than zero"); coroutineResult.isFinished = true; yield break; } MB2_ValidationLevel vl = Application.isPlaying ? MB2_ValidationLevel.quick : MB2_ValidationLevel.robust; if (!DoCombinedValidate(this, MB_ObjsToCombineTypes.dontCare, null, vl)) { coroutineResult.isFinished = true; yield break; } if (_doMultiMaterial && !_ValidateResultMaterials()) { coroutineResult.isFinished = true; yield break; } else if (!_doMultiMaterial) { if (_resultMaterial == null) { Debug.LogError("Combined Material is null please create and assign a result material."); coroutineResult.isFinished = true; yield break; } Shader targShader = _resultMaterial.shader; for (int i = 0; i < objsToMesh.Count; i++) { Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]); for (int j = 0; j < ms.Length; j++) { Material m = ms[j]; if (m != null && m.shader != targShader) { Debug.LogWarning("Game object " + objsToMesh[i] + " does not use shader " + targShader + " it may not have the required textures. If not small solid color textures will be generated."); } } } } MB3_TextureCombiner combiner = CreateAndConfigureTextureCombiner(); combiner.saveAtlasesAsAssets = saveAtlasesAsAssets; //initialize structure to store results int numResults = 1; if (_doMultiMaterial) { numResults = resultMaterials.Length; } OnCombinedTexturesCoroutineAtlasesAndRects = new MB_AtlasesAndRects[numResults]; for (int i = 0; i < OnCombinedTexturesCoroutineAtlasesAndRects.Length; i++) { OnCombinedTexturesCoroutineAtlasesAndRects[i] = new MB_AtlasesAndRects(); } //Do the material combining. for (int i = 0; i < OnCombinedTexturesCoroutineAtlasesAndRects.Length; i++) { Material resMatToPass = null; List <Material> sourceMats = null; if (_doMultiMaterial) { sourceMats = resultMaterials[i].sourceMaterials; resMatToPass = resultMaterials[i].combinedMaterial; combiner.fixOutOfBoundsUVs = resultMaterials[i].considerMeshUVs; } else { resMatToPass = _resultMaterial; } MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult coroutineResult2 = new MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult(); yield return(combiner.CombineTexturesIntoAtlasesCoroutine(progressInfo, OnCombinedTexturesCoroutineAtlasesAndRects[i], resMatToPass, objsToMesh, sourceMats, editorMethods, coroutineResult2, maxTimePerFrame)); coroutineResult.success = coroutineResult2.success; if (!coroutineResult.success) { coroutineResult.isFinished = true; yield break; } } unpackMat2RectMap(textureBakeResults); //Save the results textureBakeResults.doMultiMaterial = _doMultiMaterial; //textureBakeResults.resultMaterial = _resultMaterial; if (_doMultiMaterial) { textureBakeResults.resultMaterials = resultMaterials; } else { MB_MultiMaterial[] resMats = new MB_MultiMaterial[1]; resMats[0] = new MB_MultiMaterial(); resMats[0].combinedMaterial = _resultMaterial; resMats[0].considerMeshUVs = _fixOutOfBoundsUVs; resMats[0].sourceMaterials = new List <Material>(); for (int i = 0; i < textureBakeResults.materialsAndUVRects.Length; i++) { resMats[0].sourceMaterials.Add(textureBakeResults.materialsAndUVRects[i].material); } textureBakeResults.resultMaterials = resMats; } //textureBakeResults.fixOutOfBoundsUVs = combiner.fixOutOfBoundsUVs; //set the texture bake resultAtlasesAndRects on the Mesh Baker component if it exists MB3_MeshBakerCommon[] mb = GetComponentsInChildren <MB3_MeshBakerCommon>(); for (int i = 0; i < mb.Length; i++) { mb[i].textureBakeResults = textureBakeResults; } if (LOG_LEVEL >= MB2_LogLevel.info) { Debug.Log("Created Atlases"); } coroutineResult.isFinished = true; if (coroutineResult.success && onBuiltAtlasesSuccess != null) { onBuiltAtlasesSuccess(); } if (!coroutineResult.success && onBuiltAtlasesFail != null) { onBuiltAtlasesFail(); } }
//posibilities // using fixOutOfBoundsUVs or not // public static void ConfigureMutiMaterialsFromObjsToCombine(MB3_TextureBaker 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; } Dictionary <MultiMatSubmeshInfo, List <List <Material> > > shader2Material_map = new Dictionary <MultiMatSubmeshInfo, List <List <Material> > >(); Dictionary <Material, Mesh> obUVobject2mesh_map = new Dictionary <Material, Mesh>(); //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; } } //first pass put any meshes with obUVs on their own submesh if not fixing OB uvs if (mom.doMultiMaterialSplitAtlasesIfOBUVs) { for (int i = 0; i < mom.GetObjectsToCombine().Count; i++) { GameObject go = mom.GetObjectsToCombine()[i]; Mesh m = MB_Utility.GetMesh(go); MB_Utility.MeshAnalysisResult dummyMar = new MB_Utility.MeshAnalysisResult(); Renderer r = go.GetComponent <Renderer>(); for (int j = 0; j < r.sharedMaterials.Length; j++) { if (MB_Utility.hasOutOfBoundsUVs(m, ref dummyMar, j)) { if (!obUVobject2mesh_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"); obUVobject2mesh_map.Add(r.sharedMaterials[j], m); } } } } } //second pass put other materials without OB uvs in a shader to material 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 (!obUVobject2mesh_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 (!shader2Material_map.TryGetValue(newKey, out binsOfMatsThatUseShader)) { binsOfMatsThatUseShader = new List <List <Material> >(); binsOfMatsThatUseShader.Add(new List <Material>()); shader2Material_map.Add(newKey, binsOfMatsThatUseShader); } if (!binsOfMatsThatUseShader[0].Contains(r.sharedMaterials[j])) { binsOfMatsThatUseShader[0].Add(r.sharedMaterials[j]); } } } } int numResMats = shader2Material_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 if (mom.doMultiMaterialSplitAtlasesIfTooBig) { if (mom.packingAlgorithm == MB2_PackingAlgorithmEnum.UnitysPackTextures) { Debug.LogWarning("Unity texture packer does not support splitting atlases if too big. Atlases will not be split."); } else { numResMats = 0; foreach (MultiMatSubmeshInfo sh in shader2Material_map.Keys) { List <List <Material> > binsOfMatsThatUseShader = shader2Material_map[sh]; List <Material> allMatsThatUserShader = binsOfMatsThatUseShader[0];//at this point everything is in the same list binsOfMatsThatUseShader.RemoveAt(0); MB3_TextureCombiner 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); 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); } numResMats += binsOfMatsThatUseShader.Count; } } } //build the result materials if (shader2Material_map.Count == 0 && obUVobject2mesh_map.Count == 0) { Debug.LogError("Found no materials in list of objects to combine"); } mom.resultMaterials = new MB_MultiMaterial[numResMats + obUVobject2mesh_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 shader2Material_map.Keys) { foreach (List <Material> matsThatUse in shader2Material_map[sh]) { MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial(); mm.sourceMaterials = matsThatUse; 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 (matsThatUse.Count > 0 && matsThatUse[0] != null) { MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, matsThatUse[0]); } AssetDatabase.CreateAsset(newMat, matName); mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material)); k++; } } foreach (Material m in obUVobject2mesh_map.Keys) { MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_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")); MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, m); AssetDatabase.CreateAsset(newMat, matName); mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material)); k++; } MBVersionEditor.UpdateIfDirtyOrScript(textureBaker); }
/* tried to see if the MultiMaterialConfig could be done using the GroupBy filters. Saddly it didn't work */ public static void ConfigureMutiMaterialsFromObjsToCombine2(MB3_TextureBaker 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, MB_Utility.MeshAnalysisResult> meshAnalysisResultCache = new Dictionary <int, MB_Utility.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 = MB_Utility.GetMesh(gameObjects[i].go); int nVerts = 0; if (mm != null) { nVerts += mm.vertexCount; MB_Utility.MeshAnalysisResult mar; if (!meshAnalysisResultCache.TryGetValue(mm.GetInstanceID(), out mar)) { //EditorUtility.DisplayProgressBar("Analysing Scene", rpt + " Check Out Of Bounds UVs", .6f); MB_Utility.hasOutOfBoundsUVs(mm, ref mar); //Rect dummy = mar.uvRect; MB_Utility.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 (!MB_Utility.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 = MB3_MeshBakerEditorWindow.sortIntoBakeGroups3(gameObjects, objsNotAddedToBaker, filters, false, mom.maxAtlasSize); mom.resultMaterials = new MB_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) { MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_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")); MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, m.materials[0]); AssetDatabase.CreateAsset(newMat, matName); mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material)); k++; } MBVersionEditor.UpdateIfDirtyOrScript(textureBaker); }
private IEnumerator _CreateAtlasesCoroutineAtlases(MB3_TextureCombiner combiner, ProgressUpdateDelegate progressInfo, MB3_TextureCombiner.CreateAtlasesCoroutineResult coroutineResult, bool saveAtlasesAsAssets = false, MB2_EditorMethodsInterface editorMethods = null, float maxTimePerFrame = .01f) { int numResults = 1; if (_doMultiMaterial) { numResults = resultMaterials.Length; } OnCombinedTexturesCoroutineAtlasesAndRects = new MB_AtlasesAndRects[numResults]; for (int i = 0; i < OnCombinedTexturesCoroutineAtlasesAndRects.Length; i++) { OnCombinedTexturesCoroutineAtlasesAndRects[i] = new MB_AtlasesAndRects(); } //Do the material combining. for (int i = 0; i < OnCombinedTexturesCoroutineAtlasesAndRects.Length; i++) { Material resMatToPass = null; List <Material> sourceMats = null; if (_doMultiMaterial) { sourceMats = resultMaterials[i].sourceMaterials; resMatToPass = resultMaterials[i].combinedMaterial; combiner.fixOutOfBoundsUVs = resultMaterials[i].considerMeshUVs; } else { resMatToPass = _resultMaterial; } MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult coroutineResult2 = new MB3_TextureCombiner.CombineTexturesIntoAtlasesCoroutineResult(); yield return(combiner.CombineTexturesIntoAtlasesCoroutine(progressInfo, OnCombinedTexturesCoroutineAtlasesAndRects[i], resMatToPass, objsToMesh, sourceMats, editorMethods, coroutineResult2, maxTimePerFrame, onlyPackRects: false, splitAtlasWhenPackingIfTooBig: false)); coroutineResult.success = coroutineResult2.success; if (!coroutineResult.success) { coroutineResult.isFinished = true; yield break; } } unpackMat2RectMap(OnCombinedTexturesCoroutineAtlasesAndRects); if (coroutineResult.success && editorMethods != null) { editorMethods.GetMaterialPrimaryKeysIfAddressables(textureBakeResults); } //Save the results textureBakeResults.resultType = MB2_TextureBakeResults.ResultType.atlas; textureBakeResults.resultMaterialsTexArray = new MB_MultiMaterialTexArray[0]; textureBakeResults.doMultiMaterial = _doMultiMaterial; if (_doMultiMaterial) { textureBakeResults.resultMaterials = resultMaterials; } else { MB_MultiMaterial[] resMats = new MB_MultiMaterial[1]; resMats[0] = new MB_MultiMaterial(); resMats[0].combinedMaterial = _resultMaterial; resMats[0].considerMeshUVs = _fixOutOfBoundsUVs; resMats[0].sourceMaterials = new List <Material>(); for (int i = 0; i < textureBakeResults.materialsAndUVRects.Length; i++) { resMats[0].sourceMaterials.Add(textureBakeResults.materialsAndUVRects[i].material); } textureBakeResults.resultMaterials = resMats; } if (LOG_LEVEL >= MB2_LogLevel.info) { Debug.Log("Created Atlases"); } }
public void ConfigureMutiMaterialsFromObjsToCombine(MB3_TextureBaker mom) { if (mom.objsToMesh.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("Material Bake Result asset must be set before using this operation."); return; } Dictionary <Shader, List <Material> > shader2Material_map = new Dictionary <Shader, List <Material> >(); Dictionary <Material, Mesh> obUVobject2material_map = new Dictionary <Material, Mesh>(); //validate that the objects to be combined are valid for (int i = 0; i < mom.objsToMesh.Count; i++) { GameObject go = mom.objsToMesh[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; } } //first pass put any meshes with obUVs on their own submesh if not fixing OB uvs if (!mom.fixOutOfBoundsUVs) { for (int i = 0; i < mom.objsToMesh.Count; i++) { GameObject go = mom.objsToMesh[i]; Mesh m = MB_Utility.GetMesh(go); Rect dummy = new Rect(); Renderer r = go.GetComponent <Renderer>(); for (int j = 0; j < r.sharedMaterials.Length; j++) { if (MB_Utility.hasOutOfBoundsUVs(m, ref dummy, j)) { if (!obUVobject2material_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"); obUVobject2material_map.Add(r.sharedMaterials[j], m); } } } } } //second pass put other materials without OB uvs in a shader to material map for (int i = 0; i < mom.objsToMesh.Count; i++) { Renderer r = mom.objsToMesh[i].GetComponent <Renderer>(); for (int j = 0; j < r.sharedMaterials.Length; j++) { if (!obUVobject2material_map.ContainsKey(r.sharedMaterials[j])) { if (r.sharedMaterials[j] == null) { continue; } List <Material> matsThatUseShader = null; if (!shader2Material_map.TryGetValue(r.sharedMaterials[j].shader, out matsThatUseShader)) { matsThatUseShader = new List <Material>(); shader2Material_map.Add(r.sharedMaterials[j].shader, matsThatUseShader); } if (!matsThatUseShader.Contains(r.sharedMaterials[j])) { matsThatUseShader.Add(r.sharedMaterials[j]); } } } } if (shader2Material_map.Count == 0 && obUVobject2material_map.Count == 0) { Debug.LogError("Found no materials in list of objects to combine"); } mom.resultMaterials = new MB_MultiMaterial[shader2Material_map.Count + obUVobject2material_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 (Shader sh in shader2Material_map.Keys) { List <Material> matsThatUse = shader2Material_map[sh]; MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial(); mm.sourceMaterials = matsThatUse; string matName = folderPath + baseName + "-mat" + k + ".mat"; Material newMat = new Material(Shader.Find("Diffuse")); if (matsThatUse.Count > 0 && matsThatUse[0] != null) { MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, matsThatUse[0]); } AssetDatabase.CreateAsset(newMat, matName); mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material)); k++; } foreach (Material m in obUVobject2material_map.Keys) { MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial(); mm.sourceMaterials = new List <Material>(); mm.sourceMaterials.Add(m); string matName = folderPath + baseName + "-mat" + k + ".mat"; Material newMat = new Material(Shader.Find("Diffuse")); MB3_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, m); AssetDatabase.CreateAsset(newMat, matName); mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material)); k++; } textureBaker.UpdateIfDirtyOrScript(); }
public MB_AtlasesAndRects[] CreateAtlases(ProgressUpdateDelegate progressInfo, bool saveAtlasesAsAssets = false, MB_TextureCombiner.FileSaveFunction fileSaveFunction = null) { if (doMultiMaterial) { for (int i = 0; i < resultMaterials.Length; i++) { MB_MultiMaterial mm = resultMaterials[i]; if (mm.combinedMaterial == null) { Debug.LogError("Combined Material is null please create and assign a result material."); return(null); } UnityEngine.Shader targShader = mm.combinedMaterial.shader; for (int j = 0; j < mm.sourceMaterials.Count; j++) { if (mm.sourceMaterials[j] == null) { Debug.LogError("There are null entries in the list of Source Materials"); return(null); } if (targShader != mm.sourceMaterials[j].shader) { Debug.LogWarning("Source material " + mm.sourceMaterials[j] + " does not use shader " + targShader + " it may not have the required textures. If not empty textures will be generated."); } } } } else { if (resultMaterial == null) { Debug.LogError("Combined Material is null please create and assign a result material."); return(null); } UnityEngine.Shader targShader = resultMaterial.shader; for (int i = 0; i < objsToMesh.Count; i++) { Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]); for (int j = 0; j < ms.Length; j++) { Material m = ms[j]; if (m == null) { Debug.LogError("Game object " + objsToMesh[i] + " has a null material. Can't build atlases"); return(null); } if (m.shader != targShader) { Debug.LogWarning("Game object " + objsToMesh[i] + " does not use shader " + targShader + " it may not have the required textures. If not empty textures will be generated."); } } } } int numResults = 1; if (doMultiMaterial) { numResults = resultMaterials.Length; } MB_AtlasesAndRects[] results = new MB_AtlasesAndRects[numResults]; for (int i = 0; i < results.Length; i++) { results[i] = new MB_AtlasesAndRects(); } MB_TextureCombiner tc = new MB_TextureCombiner(); Material resMatToPass = null; List <Material> sourceMats = null; for (int i = 0; i < results.Length; i++) { if (doMultiMaterial) { sourceMats = resultMaterials[i].sourceMaterials; resMatToPass = resultMaterials[i].combinedMaterial; } else { resMatToPass = resultMaterial; } Debug.Log("Creating atlases for result material " + resMatToPass); if (!tc.combineTexturesIntoAtlases(progressInfo, results[i], resMatToPass, objsToMesh, sourceMats, atlasPadding, customShaderPropNames, resizePowerOfTwoTextures, fixOutOfBoundsUVs, maxTilingBakeSize, saveAtlasesAsAssets, texturePackingAlgorithm, fileSaveFunction)) { return(null); } } if (results != null) { textureBakeResults.combinedMaterialInfo = results; textureBakeResults.doMultiMaterial = doMultiMaterial; textureBakeResults.resultMaterial = resultMaterial; textureBakeResults.resultMaterials = resultMaterials; textureBakeResults.fixOutOfBoundsUVs = fixOutOfBoundsUVs; unpackMat2RectMap(textureBakeResults); if (UnityEngine.Application.isPlaying) { if (doMultiMaterial) { for (int j = 0; j < resultMaterials.Length; j++) { Material resMat = resultMaterials[j].combinedMaterial; //resultMaterials[j].combinedMaterial; Texture2D[] atlases = results[j].atlases; for (int i = 0; i < atlases.Length; i++) { resMat.SetTexture(results[j].texPropertyNames[i], atlases[i]); // _setMaterialTextureProperty(resMat, newMesh.texPropertyNames[i], relativePath); } } } else { Material resMat = resultMaterial; //resultMaterials[j].combinedMaterial; Texture2D[] atlases = results[0].atlases; for (int i = 0; i < atlases.Length; i++) { resMat.SetTexture(results[0].texPropertyNames[i], atlases[i]); // _setMaterialTextureProperty(resMat, newMesh.texPropertyNames[i], relativePath); } } } } if (VERBOSE) { Debug.Log("Created Atlases"); } return(results); }
private bool _ValidateResultMaterials() { HashSet <Material> hashSet = new HashSet <Material>(); for (int i = 0; i < this.objsToMesh.Count; i++) { if (this.objsToMesh[i] != null) { Material[] gomaterials = MB_Utility.GetGOMaterials(this.objsToMesh[i]); for (int j = 0; j < gomaterials.Length; j++) { if (gomaterials[j] != null) { hashSet.Add(gomaterials[j]); } } } } HashSet <Material> hashSet2 = new HashSet <Material>(); for (int k = 0; k < this.resultMaterials.Length; k++) { MB_MultiMaterial mb_MultiMaterial = this.resultMaterials[k]; if (mb_MultiMaterial.combinedMaterial == null) { Debug.LogError("Combined Material is null please create and assign a result material."); return(false); } Shader shader = mb_MultiMaterial.combinedMaterial.shader; for (int l = 0; l < mb_MultiMaterial.sourceMaterials.Count; l++) { if (mb_MultiMaterial.sourceMaterials[l] == null) { Debug.LogError("There are null entries in the list of Source Materials"); return(false); } if (shader != mb_MultiMaterial.sourceMaterials[l].shader) { Debug.LogWarning(string.Concat(new object[] { "Source material ", mb_MultiMaterial.sourceMaterials[l], " does not use shader ", shader, " it may not have the required textures. If not empty textures will be generated." })); } if (hashSet2.Contains(mb_MultiMaterial.sourceMaterials[l])) { Debug.LogError("A Material " + mb_MultiMaterial.sourceMaterials[l] + " appears more than once in the list of source materials in the source material to combined mapping. Each source material must be unique."); return(false); } hashSet2.Add(mb_MultiMaterial.sourceMaterials[l]); } } if (hashSet.IsProperSubsetOf(hashSet2)) { hashSet2.ExceptWith(hashSet); Debug.LogWarning("There are materials in the mapping that are not used on your source objects: " + this.PrintSet(hashSet2)); } if (hashSet2.IsProperSubsetOf(hashSet)) { hashSet.ExceptWith(hashSet2); Debug.LogError("There are materials on the objects to combine that are not in the mapping: " + this.PrintSet(hashSet)); return(false); } return(true); }
bool _addToCombined(GameObject[] goToAdd, GameObject[] goToDelete, bool disableRendererInSource) { if (goToAdd == null) { goToAdd = empty; } if (goToDelete == null) { goToDelete = empty; } if (_mesh == null) { _mesh = new Mesh(); } if (mat2rect_map.Keys.Count == 0) { _initialize(); } int numResultMats = 1; if (doMultiMaterial) { numResultMats = resultMaterials.Length; } if (VERBOSE) { Debug.Log("_addToCombined objs adding:" + goToAdd.Length + " objs deleting:" + goToDelete.Length + " fixOutOfBounds:" + fixOutOfBoundsUVs + " doMultiMaterial:" + doMultiMaterial); } OrderedDictionary sourceMats2submeshIdx_map = null; if (doMultiMaterial) { //build the sourceMats to submesh index map sourceMats2submeshIdx_map = new OrderedDictionary(); for (int i = 0; i < numResultMats; i++) { MB_MultiMaterial mm = resultMaterials[i]; for (int j = 0; j < mm.sourceMaterials.Count; j++) { if (mm.sourceMaterials[j] == null) { Debug.LogError("Found null material in source materials for combined mesh materials " + i); return(false); } if (!sourceMats2submeshIdx_map.Contains(mm.sourceMaterials[j])) { sourceMats2submeshIdx_map.Add(mm.sourceMaterials[j], i); } } } } if (submeshTris.Length == 0) { submeshTris = new int[numResultMats][]; for (int i = 0; i < submeshTris.Length; i++) { submeshTris[i] = new int[0]; } } //calculate num to delete int totalDeleteVerts = 0; // int totalDeleteTris = 0; int[] totalDeleteSubmeshTris = new int[numResultMats]; for (int i = 0; i < goToDelete.Length; i++) { MB_DynamicGameObject dgo; if (instance2combined_map.TryGetValue(goToDelete[i], out dgo)) { totalDeleteVerts += dgo.numVerts; // totalDeleteTris += dgo.numTris; for (int j = 0; j < dgo.submeshNumTris.Length; j++) { totalDeleteSubmeshTris[j] += dgo.submeshNumTris[j]; } } else { Debug.LogWarning("Trying to delete an object that is not in combined mesh"); } } //now add List <MB_DynamicGameObject> toAddDGOs = new List <MB_DynamicGameObject>(); int totalAddVerts = 0; // int totalAddTris = 0; int[] totalAddSubmeshTris = new int[numResultMats]; for (int i = 0; i < goToAdd.Length; i++) { if (!instance2combined_map.ContainsKey(goToAdd[i])) { MB_DynamicGameObject dgo = new MB_DynamicGameObject(); GameObject go = goToAdd[i]; Material[] sharedMaterials = MB_Utility.GetGOMaterials(go); if (sharedMaterials == null) { Debug.LogError("Object " + go.name + " does not have a Renderer"); goToAdd[i] = null; continue; } Mesh m = MB_Utility.GetMesh(go); if (m == null) { Debug.LogError("Object " + go.name + " MeshFilter or SkinedMeshRenderer had no mesh"); goToAdd[i] = null; } Rect[] uvRects = new Rect[sharedMaterials.Length]; for (int j = 0; j < sharedMaterials.Length; j++) { if (!mat2rect_map.TryGetValue(sharedMaterials[j], out uvRects[j])) { Debug.LogError("Object " + go.name + " has an unknown material " + sharedMaterials[j] + ". Try baking textures"); goToAdd[i] = null; } } if (goToAdd[i] != null) { dgo.go = goToAdd[i]; dgo.uvRects = uvRects; dgo.sharedMesh = m; dgo.numVerts = m.vertexCount; if (!_collectMaterialTriangles(m, dgo, sharedMaterials, sourceMats2submeshIdx_map)) { return(false); } dgo.submeshNumTris = new int[numResultMats]; dgo.submeshTriIdxs = new int[numResultMats]; if (fixOutOfBoundsUVs) { if (!_collectOutOfBoundsUVRects(m, dgo, sharedMaterials, sourceMats2submeshIdx_map)) { return(false); } } toAddDGOs.Add(dgo); totalAddVerts += dgo.numVerts; // totalAddTris += dgo.numTris; for (int j = 0; j < dgo._submeshTris.Length; j++) { totalAddSubmeshTris[dgo.targetSubmeshIdxs[j]] += dgo._submeshTris[j].Count; } } } else { Debug.LogWarning("Object " + goToAdd[i].name + " has already been added to " + name); goToAdd[i] = null; } } for (int i = 0; i < goToAdd.Length; i++) { if (goToAdd[i] != null && disableRendererInSource) { MB_Utility.DisableRendererInSource(goToAdd[i]); } } int newVertSize = verts.Length + totalAddVerts - totalDeleteVerts; // int newTrisSize = tris.Length + totalAddTris - totalDeleteTris; int[] newSubmeshTrisSize = new int[numResultMats]; if (VERBOSE) { Debug.Log("Verts adding:" + totalAddVerts + " deleting:" + totalDeleteVerts); } if (VERBOSE) { Debug.Log("Submeshes:" + newSubmeshTrisSize.Length); } for (int i = 0; i < newSubmeshTrisSize.Length; i++) { newSubmeshTrisSize[i] = submeshTris[i].Length + totalAddSubmeshTris[i] - totalDeleteSubmeshTris[i]; if (VERBOSE) { Debug.Log(" submesh :" + i + " already contains:" + submeshTris[i].Length + " trisAdded:" + totalAddSubmeshTris[i] + " trisDeleted:" + totalDeleteSubmeshTris[i]); } } if (newVertSize > 65534) { Debug.LogError("Cannot add objects. Resulting mesh will have more than 64k vertices ."); return(false); } Vector3[] nverts = new Vector3[newVertSize]; Vector3[] nnormals = new Vector3[newVertSize]; Vector4[] ntangents = new Vector4[newVertSize]; Vector2[] nuvs = new Vector2[newVertSize]; Vector2[] nuv1s = new Vector2[newVertSize]; Vector2[] nuv2s = new Vector2[newVertSize]; Color[] ncolors = new Color[newVertSize]; // int[] ntris = new int[newTrisSize]; int[][] nsubmeshTris = null; nsubmeshTris = new int[numResultMats][]; for (int i = 0; i < nsubmeshTris.Length; i++) { nsubmeshTris[i] = new int[newSubmeshTrisSize[i]]; } for (int i = 0; i < goToDelete.Length; i++) { MB_DynamicGameObject dgo; if (instance2combined_map.TryGetValue(goToDelete[i], out dgo)) { dgo._beingDeleted = true; } } objectsInCombinedMesh.Sort(); //copy existing arrays to narrays gameobj by gameobj omitting deleted ones int targVidx = 0; int[] targSubmeshTidx = new int[numResultMats]; int triangleIdxAdjustment = 0; for (int i = 0; i < objectsInCombinedMesh.Count; i++) { MB_DynamicGameObject dgo = objectsInCombinedMesh[i]; if (!dgo._beingDeleted) { if (VERBOSE) { Debug.Log("Copying obj in combined arrays idx:" + i); } Array.Copy(verts, dgo.vertIdx, nverts, targVidx, dgo.numVerts); Array.Copy(normals, dgo.vertIdx, nnormals, targVidx, dgo.numVerts); Array.Copy(tangents, dgo.vertIdx, ntangents, targVidx, dgo.numVerts); Array.Copy(uvs, dgo.vertIdx, nuvs, targVidx, dgo.numVerts); Array.Copy(uv1s, dgo.vertIdx, nuv1s, targVidx, dgo.numVerts); Array.Copy(uv2s, dgo.vertIdx, nuv2s, targVidx, dgo.numVerts); Array.Copy(colors, dgo.vertIdx, ncolors, targVidx, dgo.numVerts); //adjust triangles, then copy them over for (int subIdx = 0; subIdx < numResultMats; subIdx++) { int[] sTris = submeshTris[subIdx]; int sTriIdx = dgo.submeshTriIdxs[subIdx]; int sNumTris = dgo.submeshNumTris[subIdx]; if (VERBOSE) { Debug.Log(" Adjusting submesh triangles submesh:" + subIdx + " startIdx:" + sTriIdx + " num:" + sNumTris); } for (int j = sTriIdx; j < sTriIdx + sNumTris; j++) { sTris[j] = sTris[j] - triangleIdxAdjustment; } Array.Copy(sTris, sTriIdx, nsubmeshTris[subIdx], targSubmeshTidx[subIdx], sNumTris); } // dgo.triIdx = targTidx; dgo.vertIdx = targVidx; // targTidx += dgo.numTris; for (int j = 0; j < targSubmeshTidx.Length; j++) { dgo.submeshTriIdxs[j] = targSubmeshTidx[j]; targSubmeshTidx[j] += dgo.submeshNumTris[j]; } targVidx += dgo.numVerts; } else { if (VERBOSE) { Debug.Log("Not copying obj: " + i); } triangleIdxAdjustment += dgo.numVerts; } } for (int i = objectsInCombinedMesh.Count - 1; i >= 0; i--) { if (objectsInCombinedMesh[i]._beingDeleted) { instance2combined_map.Remove(objectsInCombinedMesh[i].go); objectsInCombinedMesh.RemoveAt(i); } } verts = nverts; normals = nnormals; tangents = ntangents; uvs = nuvs; uv1s = nuv1s; uv2s = nuv2s; colors = ncolors; // tris = ntris; submeshTris = nsubmeshTris; //add new for (int i = 0; i < toAddDGOs.Count; i++) { MB_DynamicGameObject dgo = toAddDGOs[i]; GameObject go = dgo.go; int vertsIdx = targVidx; // int trisIdx = targTidx; Mesh mesh = dgo.sharedMesh; Matrix4x4 l2wMat = go.transform.localToWorldMatrix; Quaternion l2wQ = go.transform.rotation; nverts = mesh.vertices; Vector3[] nnorms = mesh.normals; Vector4[] ntangs = mesh.tangents; for (int j = 0; j < nverts.Length; j++) { nverts[j] = l2wMat.MultiplyPoint(nverts[j]); nnorms[j] = l2wQ * nnorms[j]; float w = ntangs[j].w; //need to preserve the w value ntangs[j] = l2wQ * ntangs[j]; ntangs[j].w = w; } int numTriSets = mesh.subMeshCount; if (dgo.uvRects.Length < numTriSets) { Debug.LogWarning("Mesh " + dgo.go.name + " has more submeshes than materials"); numTriSets = dgo.uvRects.Length; } else if (dgo.uvRects.Length > numTriSets) { Debug.LogWarning("Mesh " + dgo.go.name + " has fewer submeshes than materials"); } nuvs = mesh.uv; int[] done = new int[nuvs.Length]; //use this to track uvs that have already been adjusted don't adjust twice for (int l = 0; l < done.Length; l++) { done[l] = -1; } bool triangleArraysOverlap = false; Rect obUVRect = new Rect(); for (int k = 0; k < dgo._submeshTris.Length; k++) { List <int> subTris = dgo._submeshTris[k]; Rect uvRect = dgo.uvRects[k]; if (fixOutOfBoundsUVs) { obUVRect = dgo.obUVRects[dgo.targetSubmeshIdxs[k]]; } for (int l = 0; l < subTris.Count; l++) { int vidx = subTris[l]; if (done[vidx] == -1) { done[vidx] = k; //prevents a uv from being adjusted twice if (fixOutOfBoundsUVs) { nuvs[vidx].x = nuvs[vidx].x / obUVRect.width - obUVRect.x / obUVRect.width; nuvs[vidx].y = nuvs[vidx].y / obUVRect.height - obUVRect.y / obUVRect.height; } nuvs[vidx].x = uvRect.x + nuvs[vidx].x * uvRect.width; nuvs[vidx].y = uvRect.y + nuvs[vidx].y * uvRect.height; } if (done[vidx] != k) { triangleArraysOverlap = true; } } } if (triangleArraysOverlap) { Debug.LogWarning(dgo.go.name + "has submeshes which share verticies. Adjusted uvs may not map correctly in combined atlas."); } nverts.CopyTo(verts, vertsIdx); nnorms.CopyTo(normals, vertsIdx); ntangs.CopyTo(tangents, vertsIdx); nuvs.CopyTo(uvs, vertsIdx); mesh.uv1.CopyTo(uv1s, vertsIdx); mesh.uv2.CopyTo(uv2s, vertsIdx); mesh.colors.CopyTo(colors, vertsIdx); // ntris = mesh.triangles; // for (int j = 0; j < ntris.Length; j++){ // ntris[j] = ntris[j] + vertsIdx; // } for (int combinedMeshIdx = 0; combinedMeshIdx < targSubmeshTidx.Length; combinedMeshIdx++) { dgo.submeshTriIdxs[combinedMeshIdx] = targSubmeshTidx[combinedMeshIdx]; } for (int j = 0; j < dgo._submeshTris.Length; j++) { List <int> sts = dgo._submeshTris[j]; for (int k = 0; k < sts.Count; k++) { sts[k] = sts[k] + vertsIdx; } int combinedMeshIdx = dgo.targetSubmeshIdxs[j]; sts.CopyTo(submeshTris[combinedMeshIdx], targSubmeshTidx[combinedMeshIdx]); dgo.submeshNumTris[combinedMeshIdx] += sts.Count; targSubmeshTidx[combinedMeshIdx] += sts.Count; } dgo.vertIdx = targVidx; instance2combined_map.Add(go, dgo); objectsInCombinedMesh.Add(dgo); targVidx += nverts.Length; for (int j = 0; j < dgo._submeshTris.Length; j++) { dgo._submeshTris[j].Clear(); } dgo._submeshTris = null; if (VERBOSE) { Debug.Log("Added to combined:" + dgo.go.name + " verts:" + nverts.Length); } } return(true); }
public MB_AtlasesAndRects[] CreateAtlases(ProgressUpdateDelegate progressInfo) { if (doMultiMaterial) { for (int i = 0; i < resultMaterials.Length; i++) { MB_MultiMaterial mm = resultMaterials[i]; Shader targShader = mm.combinedMaterial.shader; for (int j = 0; j < mm.sourceMaterials.Count; j++) { if (targShader != mm.sourceMaterials[j].shader) { Debug.LogWarning("Source material " + mm.sourceMaterials[j] + " does not use shader " + targShader + " it may not have the required textures. If not empty textures will be generated."); } } } } else { Shader targShader = resultMaterial.shader; for (int i = 0; i < objsToMesh.Count; i++) { Material[] ms = MB_Utility.GetGOMaterials(objsToMesh[i]); for (int j = 0; j < ms.Length; j++) { Material m = ms[j]; if (m == null) { Debug.LogError("Game object " + objsToMesh[i] + " has a null material. Can't build atlases"); return(null); } if (m.shader != targShader) { Debug.LogWarning("Game object " + objsToMesh[i] + " does not use shader " + targShader + " it may not have the required textures. If not empty textures will be generated."); } } } } int numResults = 1; if (doMultiMaterial) { numResults = resultMaterials.Length; } MB_AtlasesAndRects[] results = new MB_AtlasesAndRects[numResults]; for (int i = 0; i < results.Length; i++) { results[i] = new MB_AtlasesAndRects(); } MB_TextureCombiner tc = new MB_TextureCombiner(); Material[] resMatsToPass = new Material[1]; List <Material> sourceMats = null; for (int i = 0; i < results.Length; i++) { if (doMultiMaterial) { sourceMats = resultMaterials[i].sourceMaterials; resMatsToPass[0] = resultMaterials[i].combinedMaterial; } else { resMatsToPass[0] = resultMaterial; } Debug.Log("Creating atlases for result material " + resMatsToPass[0]); if (!tc.combineTexturesIntoAtlases(progressInfo, results[i], resMatsToPass, objsToMesh, sourceMats, atlasPadding, customShaderPropNames, resizePowerOfTwoTextures, fixOutOfBoundsUVs, 1024)) { return(null); } } updateMaterialToRectMapping(results); return(results); }
public void ConfigureMutiMaterialsFromObjsToCombine(MB2_TextureBaker mom) { if (mom.objsToMesh.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("Material Bake Result asset must be set before using this operation."); return; } Dictionary <UnityEngine.Shader, List <Material> > shader2Material_map = new Dictionary <UnityEngine.Shader, List <Material> >(); bool hasOutOfBoundsUVs = false; for (int i = 0; i < mom.objsToMesh.Count; i++) { UnityEngine.GameObject go = mom.objsToMesh[i]; if (go == null) { Debug.LogError("Null object in list of objects to combine at position " + i); return; } UnityEngine.Renderer r = go.GetComponent <UnityEngine.Renderer>(); if (r == null || (!(r is MeshRenderer) && !(r is SkinnedMeshRenderer))) { Debug.LogError("UnityEngine.GameObject at position " + i + " in list of objects to combine did not have a renderer"); return; } Mesh m = MB_Utility.GetMesh(go); Rect dummy = new Rect(); if (MB_Utility.hasOutOfBoundsUVs(m, ref dummy, -1)) { hasOutOfBoundsUVs = true; } for (int j = 0; j < r.sharedMaterials.Length; j++) { if (r.sharedMaterials[j] == null) { continue; } List <Material> matsThatUseShader = null;; if (!shader2Material_map.TryGetValue(r.sharedMaterials[j].shader, out matsThatUseShader)) { matsThatUseShader = new List <Material>(); shader2Material_map.Add(r.sharedMaterials[j].shader, matsThatUseShader); } if (!matsThatUseShader.Contains(r.sharedMaterials[j])) { matsThatUseShader.Add(r.sharedMaterials[j]); } } } if (hasOutOfBoundsUVs) { mom.fixOutOfBoundsUVs = true; Debug.LogWarning("Some game objects have out-of-bounds UVs. Setting the fix-out-of-bounds UVs flag"); } if (shader2Material_map.Count == 0) { Debug.LogError("Found no materials in list of objects to combine"); } mom.resultMaterials = new MB_MultiMaterial[shader2Material_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 (UnityEngine.Shader sh in shader2Material_map.Keys) { List <Material> matsThatUse = shader2Material_map[sh]; MB_MultiMaterial mm = mom.resultMaterials[k] = new MB_MultiMaterial(); mm.sourceMaterials = matsThatUse; string matName = folderPath + baseName + "-mat" + k + ".mat"; Material newMat = new Material(UnityEngine.Shader.Find("Diffuse")); if (matsThatUse.Count > 0 && matsThatUse[0] != null) { MB2_TextureBaker.ConfigureNewMaterialToMatchOld(newMat, matsThatUse[0]); } AssetDatabase.CreateAsset(newMat, matName); mm.combinedMaterial = (Material)AssetDatabase.LoadAssetAtPath(matName, typeof(Material)); k++; } textureBaker.UpdateIfDirtyOrScript(); }