using System.Collections.Generic; using UnityEngine; using System.IO; using System.Linq; #if UNITY_EDITOR using UnityEditor; #endif namespace UniGLTF { public static class StaticMeshIntegrator { const string ASSET_SUFFIX = ".mesh.asset"; class Integrator { List m_positions = new List(); List m_normals = new List(); List m_uv = new List(); /* List m_uv2 = new List(); // ToDo List m_uv3 = new List(); // ToDo List m_uv4 = new List(); // ToDo List m_colors = new List(); // ToDo */ List m_subMeshes = new List(); List m_materials = new List(); public List Materials { get { return m_materials; } } public void Push(Matrix4x4 localToRoot, Mesh mesh, Material[] materials) { var offset = m_positions.Count; var hasNormal = m_normals.Count == m_positions.Count; var hasUv = m_uv.Count == m_positions.Count; // attributes m_positions.AddRange(mesh.vertices.Select(x => localToRoot.MultiplyPoint(x))); if(mesh.normals!=null && mesh.normals.Length == mesh.vertexCount) { if (!hasNormal) for (int i = m_normals.Count; i < m_positions.Count; ++i) m_normals.Add(Vector3.zero); m_normals.AddRange(mesh.normals.Select(x => localToRoot.MultiplyVector(x))); } if (mesh.uv != null && mesh.uv.Length == mesh.vertexCount) { if (!hasUv) for (int i = m_uv.Count; i < m_positions.Count; ++i) m_uv.Add(Vector2.zero); m_uv.AddRange(mesh.uv); } // indices for (int i = 0; i < mesh.subMeshCount; ++i) { m_subMeshes.Add(mesh.GetIndices(i).Select(x => offset + x).ToArray()); } // materials m_materials.AddRange(materials); } public Mesh ToMesh() { var mesh = new Mesh(); mesh.name = "integrated"; mesh.vertices = m_positions.ToArray(); if (m_normals.Count > 0) { if (m_normals.Count < m_positions.Count) for (int i = m_normals.Count; i < m_positions.Count; ++i) m_normals.Add(Vector3.zero); mesh.normals = m_normals.ToArray(); } if (m_uv.Count > 0) { if (m_uv.Count < m_positions.Count) for (int i = m_uv.Count; i < m_positions.Count; ++i) m_uv.Add(Vector2.zero); mesh.uv = m_uv.ToArray(); } mesh.subMeshCount = m_subMeshes.Count; for(int i=0; i(); var filter = t.GetComponent(); if (renderer != null && filter != null && filter.sharedMesh != null && renderer.sharedMaterials!=null && renderer.sharedMaterials.Length == filter.sharedMesh.subMeshCount) { integrator.Push(root.worldToLocalMatrix * t.localToWorldMatrix, filter.sharedMesh, renderer.sharedMaterials); } } return new MeshWithMaterials { Mesh = integrator.ToMesh(), Materials = integrator.Materials.ToArray(), }; } #if UNITY_EDITOR [MenuItem(UniGLTFVersion.MENU + "/Integrate static mesh", validate = true)] public static bool CanIntegrateSelected() { return Selection.activeObject != null && Selection.activeObject is GameObject; } [MenuItem(UniGLTFVersion.MENU + "/Integrate static mesh")] public static void IntegrateSelected() { var go = Selection.activeObject as GameObject; var meshWithMaterials = Integrate(go.transform); // save as asset var assetPath = ""; #if UNITY_2018_2_OR_NEWER var prefab = PrefabUtility.GetCorrespondingObjectFromSource(go); #else var prefab = PrefabUtility.GetPrefabParent(go); #endif if (prefab != null) { var prefabPath = AssetDatabase.GetAssetPath(prefab); assetPath = string.Format("{0}/{1}_{2}{3}", Path.GetDirectoryName(prefabPath), Path.GetFileNameWithoutExtension(prefabPath), go.name, ASSET_SUFFIX ); } else { var path = EditorUtility.SaveFilePanel( "Save mesh", "Assets", go.name+".asset", "asset"); if (string.IsNullOrEmpty(path)) { return; } assetPath = UnityPath.FromFullpath(path).Value; } assetPath = AssetDatabase.GenerateUniqueAssetPath(assetPath); Debug.LogFormat("CreateAsset: {0}", assetPath); AssetDatabase.CreateAsset(meshWithMaterials.Mesh, assetPath); // add component var meshObject = new GameObject(go.name + ".integrated"); if (go.transform.parent != null) { meshObject.transform.SetParent(go.transform.parent, false); } meshObject.transform.localPosition = go.transform.localPosition; meshObject.transform.localRotation = go.transform.localRotation; meshObject.transform.localScale = go.transform.localScale; var filter = meshObject.AddComponent(); filter.sharedMesh = meshWithMaterials.Mesh; var renderer = meshObject.AddComponent(); renderer.sharedMaterials = meshWithMaterials.Materials; } #endif } }