GameObject combineMesh(bool exportAssets) { GameObject returnObject = new GameObject(m_parentObject.name); returnObject.transform.position = m_parentObject.transform.position; returnObject.transform.rotation = m_parentObject.transform.rotation; MeshFilter[] filters = m_parentObject.GetComponentsInChildren <MeshFilter>(); Matrix4x4 myTransform = m_parentObject.transform.worldToLocalMatrix; Dictionary <string, Dictionary <Material, List <MeshCombineUtility.MeshInstance> > > allMeshesAndMaterials = new Dictionary <string, Dictionary <Material, List <MeshCombineUtility.MeshInstance> > >(); for (int i = 0; i < filters.Length; i++) { Renderer curRenderer = filters[i].renderer; MeshCombineUtility.MeshInstance instance = new MeshCombineUtility.MeshInstance(); instance.mesh = filters[i].sharedMesh; if (curRenderer != null && curRenderer.enabled && instance.mesh != null) { instance.transform = myTransform * filters[i].transform.localToWorldMatrix; Material[] materials = curRenderer.sharedMaterials; for (int m = 0; m < materials.Length; m++) { instance.subMeshIndex = System.Math.Min(m, instance.mesh.subMeshCount - 1); if (!allMeshesAndMaterials.ContainsKey(materials[m].shader.ToString())) { allMeshesAndMaterials.Add(materials[m].shader.ToString(), new Dictionary <Material, List <MeshCombineUtility.MeshInstance> >()); } if (!allMeshesAndMaterials[materials[m].shader.ToString()].ContainsKey(materials[m])) { allMeshesAndMaterials[materials[m].shader.ToString()].Add(materials[m], new List <MeshCombineUtility.MeshInstance>()); } allMeshesAndMaterials[materials[m].shader.ToString()][materials[m]].Add(instance); } } } foreach (KeyValuePair <string, Dictionary <Material, List <MeshCombineUtility.MeshInstance> > > firstPass in allMeshesAndMaterials) { Material[] allMaterialTextures = new Material[firstPass.Value.Keys.Count]; int index = 0; foreach (KeyValuePair <Material, List <MeshCombineUtility.MeshInstance> > kv in firstPass.Value) { allMaterialTextures[index] = kv.Key; index++; } TextureCombineUtility.TexturePosition[] textureUVPositions; Material combined = TextureCombineUtility.combine(allMaterialTextures, out textureUVPositions, m_textureAtlasInfo); List <MeshCombineUtility.MeshInstance> meshes = new List <MeshCombineUtility.MeshInstance>(); foreach (KeyValuePair <Material, List <MeshCombineUtility.MeshInstance> > kv in firstPass.Value) { List <MeshCombineUtility.MeshInstance> meshIntermediates = new List <MeshCombineUtility.MeshInstance>(); Mesh[] firstCombineStep = MeshCombineUtility.Combine(kv.Value.ToArray()); for (int i = 0; i < firstCombineStep.Length; i++) { MeshCombineUtility.MeshInstance instance = new MeshCombineUtility.MeshInstance(); instance.mesh = firstCombineStep[i]; instance.subMeshIndex = 0; instance.transform = Matrix4x4.identity; meshIntermediates.Add(instance); } TextureCombineUtility.TexturePosition refTexture = textureUVPositions[0]; for (int j = 0; j < textureUVPositions.Length; j++) { if (kv.Key.mainTexture.name == textureUVPositions[j].textures[0].name) { refTexture = textureUVPositions[j]; break; } } for (int j = 0; j < meshIntermediates.Count; j++) { Vector2[] uvCopy = meshIntermediates[j].mesh.uv; for (int k = 0; k < uvCopy.Length; k++) { uvCopy[k].x = refTexture.position.x + uvCopy[k].x * refTexture.position.width; uvCopy[k].y = refTexture.position.y + uvCopy[k].y * refTexture.position.height; } meshIntermediates[j].mesh.uv = uvCopy; uvCopy = meshIntermediates[j].mesh.uv1; for (int k = 0; k < uvCopy.Length; k++) { uvCopy[k].x = refTexture.position.x + uvCopy[k].x * refTexture.position.width; uvCopy[k].y = refTexture.position.y + uvCopy[k].y * refTexture.position.height; } meshIntermediates[j].mesh.uv1 = uvCopy; uvCopy = meshIntermediates[j].mesh.uv2; for (int k = 0; k < uvCopy.Length; k++) { uvCopy[k].x = refTexture.position.x + uvCopy[k].x * refTexture.position.width; uvCopy[k].y = refTexture.position.y + uvCopy[k].y * refTexture.position.height; } meshIntermediates[j].mesh.uv2 = uvCopy; meshes.Add(meshIntermediates[j]); } } Material mat = combined; Mesh[] combinedMeshes = MeshCombineUtility.Combine(meshes.ToArray()); GameObject parent = new GameObject("Combined " + m_parentObject.name + " " + firstPass.Key + " Mesh Parent"); parent.transform.position = m_parentObject.transform.position; parent.transform.rotation = m_parentObject.transform.rotation; parent.transform.parent = returnObject.transform; for (int i = 0; i < combinedMeshes.Length; i++) { GameObject go = new GameObject("Combined " + m_parentObject.name + " Mesh"); go.transform.parent = parent.transform; go.tag = m_parentObject.tag; go.layer = m_parentObject.layer; go.transform.localScale = Vector3.one; go.transform.localRotation = Quaternion.identity; go.transform.localPosition = Vector3.zero; MeshFilter filter = go.AddComponent <MeshFilter>(); go.AddComponent <MeshRenderer>(); go.renderer.sharedMaterial = mat; filter.mesh = combinedMeshes[i]; if (exportAssets == true) { checkAndCreateFolder(); //(go.GetComponent<MeshRenderer>().material.mainTexture as Texture2D).format = TextureFormat.RGBA32; Debug.Log((go.GetComponent <MeshRenderer>().sharedMaterial.mainTexture as Texture2D).format); if ((go.GetComponent <MeshRenderer>().sharedMaterial.mainTexture as Texture2D).format != TextureFormat.ARGB32 && (go.GetComponent <MeshRenderer>().sharedMaterial.mainTexture as Texture2D).format != TextureFormat.RGB24 && (go.GetComponent <MeshRenderer>().sharedMaterial.mainTexture as Texture2D).format != TextureFormat.RGBA32) { Debug.LogError("Textures assigned to objects must be either RGBA32 or RGB 24 to be exported"); return(null); } byte[] texture = (go.GetComponent <MeshRenderer>().material.mainTexture as Texture2D).EncodeToPNG(); System.IO.File.WriteAllBytes(m_pathToAssets + mat.shader.ToString().Remove(mat.shader.ToString().IndexOf("(")) + i + ".png", texture); exportMesh(combinedMeshes[i], mat.shader.ToString().Remove(mat.shader.ToString().IndexOf("(")) + i); } } } //if(developmentBake == true) //{ foreach (Renderer r in m_parentObject.GetComponentsInChildren <Renderer>()) { r.enabled = false; } //} return(returnObject); }
public TextureAtlasInfo textureAtlasProperties; // = new TextureCombineUtility.TextureAtlasInfo(); /// This option has a far longer preprocessing time at startup but leads to better runtime performance. void Start() { MeshFilter[] filters = GetComponentsInChildren <MeshFilter>(); Matrix4x4 myTransform = transform.worldToLocalMatrix; Dictionary <string, Dictionary <Material, List <MeshCombineUtility.MeshInstance> > > allMeshesAndMaterials = new Dictionary <string, Dictionary <Material, List <MeshCombineUtility.MeshInstance> > >(); for (int i = 0; i < filters.Length; i++) { Renderer curRenderer = filters[i].GetComponent <Renderer>(); MeshCombineUtility.MeshInstance instance = new MeshCombineUtility.MeshInstance(); instance.mesh = filters[i].mesh; if (curRenderer != null && curRenderer.enabled && instance.mesh != null) { instance.transform = myTransform * filters[i].transform.localToWorldMatrix; Material[] materials = curRenderer.sharedMaterials; for (int m = 0; m < materials.Length; m++) { instance.subMeshIndex = System.Math.Min(m, instance.mesh.subMeshCount - 1); if (!allMeshesAndMaterials.ContainsKey(materials[m].shader.ToString())) { allMeshesAndMaterials.Add(materials[m].shader.ToString(), new Dictionary <Material, List <MeshCombineUtility.MeshInstance> >()); } if (!allMeshesAndMaterials[materials[m].shader.ToString()].ContainsKey(materials[m])) { allMeshesAndMaterials[materials[m].shader.ToString()].Add(materials[m], new List <MeshCombineUtility.MeshInstance>()); } allMeshesAndMaterials[materials[m].shader.ToString()][materials[m]].Add(instance); } } } foreach (KeyValuePair <string, Dictionary <Material, List <MeshCombineUtility.MeshInstance> > > firstPass in allMeshesAndMaterials) { Material[] allMaterialTextures = new Material[firstPass.Value.Keys.Count]; int index = 0; foreach (KeyValuePair <Material, List <MeshCombineUtility.MeshInstance> > kv in firstPass.Value) { allMaterialTextures[index] = kv.Key; index++; } TextureCombineUtility.TexturePosition[] textureUVPositions; Material combined = TextureCombineUtility.combine(allMaterialTextures, out textureUVPositions, textureAtlasProperties); if (textureUVPositions != null) { List <MeshCombineUtility.MeshInstance> meshIntermediates = new List <MeshCombineUtility.MeshInstance>(); foreach (KeyValuePair <Material, List <MeshCombineUtility.MeshInstance> > kv in firstPass.Value) { TextureCombineUtility.TexturePosition refTexture = textureUVPositions[0]; for (int i = 0; i < textureUVPositions.Length; i++) { if (kv.Key.mainTexture.name == textureUVPositions[i].textures[0].name) { refTexture = textureUVPositions[i]; break; } } for (int i = 0; i < kv.Value.Count; i++) { Vector2[] uvCopy = kv.Value[i].mesh.uv; for (int j = 0; j < uvCopy.Length; j++) { uvCopy[j].x = refTexture.position.x + uvCopy[j].x * refTexture.position.width; uvCopy[j].y = refTexture.position.y + uvCopy[j].y * refTexture.position.height; } kv.Value[i].mesh.uv = uvCopy; uvCopy = kv.Value[i].mesh.uv2; for (int j = 0; j < uvCopy.Length; j++) { uvCopy[j].x = refTexture.position.x + uvCopy[j].x * refTexture.position.width; uvCopy[j].y = refTexture.position.y + uvCopy[j].y * refTexture.position.height; } kv.Value[i].mesh.uv2 = uvCopy; uvCopy = kv.Value[i].mesh.uv2; for (int j = 0; j < uvCopy.Length; j++) { uvCopy[j].x = refTexture.position.x + uvCopy[j].x * refTexture.position.width; uvCopy[j].y = refTexture.position.y + uvCopy[j].y * refTexture.position.height; } kv.Value[i].mesh.uv2 = uvCopy; meshIntermediates.Add(kv.Value[i]); } } Material mat = combined; Mesh[] combinedMeshes = MeshCombineUtility.Combine(meshIntermediates.ToArray()); GameObject parent = new GameObject("Combined " + gameObject.name + " " + firstPass.Key + " Mesh Parent"); parent.transform.position = transform.position; parent.transform.rotation = transform.rotation; for (int i = 0; i < combinedMeshes.Length; i++) { GameObject go = new GameObject("Combined " + gameObject.name + " Mesh"); go.transform.parent = parent.transform; go.tag = gameObject.tag; go.layer = gameObject.layer; go.transform.localScale = Vector3.one; go.transform.localRotation = Quaternion.identity; go.transform.localPosition = Vector3.zero; MeshFilter filter = go.AddComponent <MeshFilter>(); go.AddComponent <MeshRenderer>(); go.GetComponent <Renderer>().sharedMaterial = mat; filter.mesh = combinedMeshes[i]; } } } Destroy(gameObject); }
GameObject combineMesh(bool exportAssets, bool genCollider = true, bool doSetParent = true, bool doSetLayer = true, bool doSetTag = true) { // GameObject returnObject = new GameObject(m_parentObject.name); // returnObject.transform.position = m_parentObject.transform.position; // returnObject.transform.rotation = m_parentObject.transform.rotation; MeshFilter[] filters = m_parentObject.GetComponentsInChildren <MeshFilter>(); Matrix4x4 myTransform = m_parentObject.transform.worldToLocalMatrix; this.checkAndCreateFolder(); Dictionary <string, Dictionary <Material, List <MeshCombineUtility.MeshInstance> > > allMeshesAndMaterials = new Dictionary <string, Dictionary <Material, List <MeshCombineUtility.MeshInstance> > >(); for (int i = 0; i < filters.Length; i++) { Renderer curRenderer = filters[i].GetComponent <Renderer>(); MeshCombineUtility.MeshInstance instance = new MeshCombineUtility.MeshInstance(); instance.mesh = filters[i].sharedMesh; if (curRenderer != null && curRenderer.enabled && instance.mesh != null) { instance.transform = myTransform * filters[i].transform.localToWorldMatrix; Material[] materials = curRenderer.sharedMaterials; for (int m = 0; m < materials.Length; m++) { instance.subMeshIndex = System.Math.Min(m, instance.mesh.subMeshCount - 1); if (!allMeshesAndMaterials.ContainsKey(materials[m].shader.ToString())) { allMeshesAndMaterials.Add(materials[m].shader.ToString(), new Dictionary <Material, List <MeshCombineUtility.MeshInstance> >()); } if (!allMeshesAndMaterials[materials[m].shader.ToString()].ContainsKey(materials[m])) { allMeshesAndMaterials[materials[m].shader.ToString()].Add(materials[m], new List <MeshCombineUtility.MeshInstance>()); } allMeshesAndMaterials[materials[m].shader.ToString()][materials[m]].Add(instance); } } } foreach (KeyValuePair <string, Dictionary <Material, List <MeshCombineUtility.MeshInstance> > > firstPass in allMeshesAndMaterials) { Material[] allMaterialTextures = new Material[firstPass.Value.Keys.Count]; int index = 0; foreach (KeyValuePair <Material, List <MeshCombineUtility.MeshInstance> > kv in firstPass.Value) { allMaterialTextures[index] = kv.Key; index++; } TextureCombineUtility.TexturePosition[] textureUVPositions; Material combined = TextureCombineUtility.combine(allMaterialTextures, out textureUVPositions, m_textureAtlasInfo); List <MeshCombineUtility.MeshInstance> meshes = new List <MeshCombineUtility.MeshInstance>(); foreach (KeyValuePair <Material, List <MeshCombineUtility.MeshInstance> > kv in firstPass.Value) { List <MeshCombineUtility.MeshInstance> meshIntermediates = new List <MeshCombineUtility.MeshInstance>(); Mesh[] firstCombineStep = MeshCombineUtility.Combine(kv.Value.ToArray()); for (int i = 0; i < firstCombineStep.Length; i++) { MeshCombineUtility.MeshInstance instance = new MeshCombineUtility.MeshInstance(); instance.mesh = firstCombineStep[i]; instance.subMeshIndex = 0; instance.transform = Matrix4x4.identity; meshIntermediates.Add(instance); } if (textureUVPositions != null) { TextureCombineUtility.TexturePosition refTexture = textureUVPositions[0]; for (int j = 0; j < textureUVPositions.Length; j++) { if (kv.Key.mainTexture.name == textureUVPositions[j].textures[0].name) { refTexture = textureUVPositions[j]; break; } } for (int j = 0; j < meshIntermediates.Count; j++) { Vector2[] uvCopy = meshIntermediates[j].mesh.uv; for (int k = 0; k < uvCopy.Length; k++) { uvCopy[k].x = refTexture.position.x + uvCopy[k].x * refTexture.position.width; uvCopy[k].y = refTexture.position.y + uvCopy[k].y * refTexture.position.height; } meshIntermediates[j].mesh.uv = uvCopy; uvCopy = meshIntermediates[j].mesh.uv2; for (int k = 0; k < uvCopy.Length; k++) { uvCopy[k].x = refTexture.position.x + uvCopy[k].x * refTexture.position.width; uvCopy[k].y = refTexture.position.y + uvCopy[k].y * refTexture.position.height; } meshIntermediates[j].mesh.uv2 = uvCopy; uvCopy = meshIntermediates[j].mesh.uv2; for (int k = 0; k < uvCopy.Length; k++) { uvCopy[k].x = refTexture.position.x + uvCopy[k].x * refTexture.position.width; uvCopy[k].y = refTexture.position.y + uvCopy[k].y * refTexture.position.height; } meshIntermediates[j].mesh.uv2 = uvCopy; meshes.Add(meshIntermediates[j]); } } } Material mat = combined; if (exportAssets) //combined exportMaterial and combined Textures { checkAndCreateFolder(); Debug.Log((mat.mainTexture as Texture2D).format); if ((mat.mainTexture as Texture2D).format != TextureFormat.ARGB32 && (mat.mainTexture as Texture2D).format != TextureFormat.RGB24 && (mat.mainTexture as Texture2D).format != TextureFormat.RGBA32) { Debug.LogError("Textures assigned to objects must be either RGBA32 or RGB 24 to be exported"); return(null); } byte[] textureByte = (mat.mainTexture as Texture2D).EncodeToPNG(); string texturefolder = m_pathToAssets.Substring(m_pathToAssets.LastIndexOf("Assets/")) + "Textures/"; checkAndCreateFolder(texturefolder); System.IO.File.WriteAllBytes(texturefolder + m_parentObject.name + ".png", textureByte); Material outMat = new Material(mat); string materialfolder = m_pathToAssets.Substring(m_pathToAssets.LastIndexOf("Assets/")) + "Materials/"; checkAndCreateFolder(materialfolder); string assetPathFile = materialfolder + m_parentObject.name + ".mat"; AssetDatabase.CreateAsset(outMat, assetPathFile); outMat.CopyPropertiesFromMaterial(mat); outMat.mainTexture = AssetDatabase.LoadAssetAtPath(texturefolder + m_parentObject.name + ".png", typeof(Texture)) as Texture; AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); mat = outMat; } Mesh[] combinedMeshes = MeshCombineUtility.Combine(meshes.ToArray()); GameObject parent = new GameObject(m_parentObject.name + "_Combined " + firstPass.Key + " Mesh Parent"); parent.transform.position = m_parentObject.transform.position; parent.transform.rotation = m_parentObject.transform.rotation; parent.transform.parent = m_parentObject.transform; if (doSetLayer) { parent.layer = m_parentObject.layer; } if (doSetTag) { parent.tag = m_parentObject.tag; } if (doSetParent) { parent.transform.parent = m_parentObject.transform.parent; } parent.isStatic = m_parentObject.isStatic; for (int i = 0; i < combinedMeshes.Length; i++) { GameObject go = new GameObject(m_parentObject.name + "_Combined_Meshs"); go.transform.parent = parent.transform; go.tag = m_parentObject.tag; go.layer = m_parentObject.layer; go.transform.localScale = Vector3.one; go.transform.localRotation = Quaternion.identity; go.transform.localPosition = Vector3.zero; MeshFilter filter = go.AddComponent <MeshFilter>(); go.AddComponent <MeshRenderer>(); go.GetComponent <Renderer>().sharedMaterial = mat; filter.mesh = combinedMeshes[i]; if (exportAssets == true) { exportMeshFilter(filter, m_parentObject.name + i); // exportMesh(combinedMeshes[i], m_parentObject.name + i,mat); } if (genCollider) { if (go.GetComponent <MeshCollider>() == null) { go.gameObject.AddComponent <MeshCollider>(); } } if (doSetLayer) { go.layer = m_parentObject.layer; } if (doSetTag) { go.tag = m_parentObject.tag; } go.isStatic = m_parentObject.isStatic; } } //if(developmentBake == true) //{ foreach (Renderer r in m_parentObject.GetComponentsInChildren <Renderer>()) { r.enabled = false; } //} return(m_parentObject); }