void Update() { if (materials.Count > 0) { AlembicMesh abcmesh = gameObject.GetComponent <AlembicMesh>(); if (abcmesh != null) { int splitIndex = 0; int submeshIndex = 0; if (abcmesh.m_submeshes.Count < materials.Count) { // should have at least materials.Count submeshes Debug.Log("\"" + abcmesh.name + "\": Not enough submeshes for all assigned materials. (" + materials.Count + " material(s) for " + abcmesh.m_submeshes.Count + " submesh(es))"); return; } MeshRenderer renderer = gameObject.GetComponent <MeshRenderer>(); foreach (AlembicMesh.Submesh submesh in abcmesh.m_submeshes) { if (submesh.splitIndex != splitIndex) { submeshIndex = 0; } MeshRenderer splitRenderer = null; Transform split = gameObject.transform.FindChild(gameObject.name + "_split_" + submesh.splitIndex); if (split == null) { if (submesh.splitIndex > 0) { Debug.Log("Invalid split index"); return; } splitRenderer = renderer; } else { if (submesh.splitIndex == 0 && !split.gameObject.activeSelf) { // First split sub object not active means the mesh is hold be the current object splitRenderer = renderer; } else { splitRenderer = split.gameObject.GetComponent <MeshRenderer>(); } } if (splitRenderer == null) { Debug.Log("No renderer on \"" + gameObject.name + "\" to assign materials to"); return; } Material[] assignedMaterials = splitRenderer.sharedMaterials; if (submesh.facesetIndex != -1) { if (submesh.facesetIndex < 0 || submesh.facesetIndex >= materials.Count) { // invalid facesetIndex, do no update material assignments at all Debug.Log("Invalid faceset index"); return; } if (submeshIndex >= assignedMaterials.Length) { Debug.Log("No material for submesh"); return; } if (assignedMaterials[submeshIndex] != materials[submesh.facesetIndex]) { assignedMaterials[submeshIndex] = materials[submesh.facesetIndex]; splitRenderer.sharedMaterials = assignedMaterials; // propagate first split single material assignment to parent renderer if it exists if (submesh.splitIndex == 0 && splitRenderer != renderer && renderer != null && assignedMaterials.Length == 1) { renderer.sharedMaterials = assignedMaterials; } } } else { // should I reset to default material or leave it as it is } splitIndex = submesh.splitIndex; ++submeshIndex; } } materials.Clear(); } }
public static void UpdateAbcMesh(aiObject abc, Transform trans) { const int max_vertices = 65000; AlembicMesh abcmesh = trans.GetComponent <AlembicMesh>(); if (abcmesh == null) { abcmesh = trans.gameObject.AddComponent <AlembicMesh>(); var entry = new AlembicMesh.Entry { host = trans.gameObject, mesh = AddMeshComponents(abc, trans), vertex_cache = new Vector3[0], uv_cache = new Vector2[0], index_cache = new int[0], }; abcmesh.m_meshes.Add(entry); #if UNITY_EDITOR trans.GetComponent <MeshRenderer>().sharedMaterial = GetDefaultMaterial(); #endif } Material material = trans.GetComponent <MeshRenderer>().sharedMaterial; /* * { * AlembicMesh.Entry entry = abcmesh.m_meshes[0]; * Array.Resize(ref entry.index_cache, aiPolyMeshGetIndexCount(ctx)); * Array.Resize(ref entry.vertex_cache, aiPolyMeshGetVertexCount(ctx)); * aiPolyMeshCopyIndices(ctx, Marshal.UnsafeAddrOfPinnedArrayElement(entry.index_cache, 0)); * aiPolyMeshCopyVertices(ctx, Marshal.UnsafeAddrOfPinnedArrayElement(entry.vertex_cache, 0)); * entry.mesh.Clear(); * entry.mesh.vertices = entry.vertex_cache; * if(aiPolyMeshHasNormals(ctx)) * { * aiPolyMeshCopyNormals(ctx, Marshal.UnsafeAddrOfPinnedArrayElement(entry.vertex_cache, 0)); * entry.mesh.normals = entry.vertex_cache; * } * if (aiPolyMeshHasUVs(ctx)) * { * Array.Resize(ref entry.uv_cache, aiPolyMeshGetVertexCount(ctx)); * aiPolyMeshCopyUVs(ctx, Marshal.UnsafeAddrOfPinnedArrayElement(entry.uv_cache, 0)); * entry.mesh.uv = entry.uv_cache; * } * entry.mesh.SetIndices(entry.index_cache, MeshTopology.Triangles, 0); * //entry.mesh.RecalculateNormals(); // * * for (int i = 1; i < abcmesh.m_meshes.Count; ++i) * { * abcmesh.m_meshes[i].host.SetActive(false); * } * } */ aiSplitedMeshInfo smi_prev = default(aiSplitedMeshInfo); aiSplitedMeshInfo smi = default(aiSplitedMeshInfo); int nth_submesh = 0; for (; ;) { smi_prev = smi; smi = default(aiSplitedMeshInfo); bool is_end = aiPolyMeshGetSplitedMeshInfo(abc, ref smi, ref smi_prev, max_vertices); AlembicMesh.Entry entry; if (nth_submesh < abcmesh.m_meshes.Count) { entry = abcmesh.m_meshes[nth_submesh]; entry.host.SetActive(true); } else { string name = "Submesh_" + nth_submesh; GameObject go = new GameObject(); Transform child = go.GetComponent <Transform>(); go.name = name; child.parent = trans; child.localPosition = Vector3.zero; child.localEulerAngles = Vector3.zero; child.localScale = Vector3.one; Mesh mesh = AddMeshComponents(abc, child); mesh.name = name; child.GetComponent <MeshRenderer>().sharedMaterial = material; entry = new AlembicMesh.Entry { host = go, mesh = mesh, vertex_cache = new Vector3[0], uv_cache = new Vector2[0], index_cache = new int[0], }; abcmesh.m_meshes.Add(entry); } bool needs_index_update = entry.mesh.vertexCount == 0 || !aiPolyMeshIsTopologyConstant(abc); if (needs_index_update) { entry.mesh.Clear(); } // update positions { Array.Resize(ref entry.vertex_cache, smi.vertex_count); aiPolyMeshCopySplitedVertices(abc, Marshal.UnsafeAddrOfPinnedArrayElement(entry.vertex_cache, 0), ref smi); entry.mesh.vertices = entry.vertex_cache; } // update normals if (aiPolyMeshHasNormals(abc)) { // normals can reuse entry.vertex_cache aiPolyMeshCopySplitedNormals(abc, Marshal.UnsafeAddrOfPinnedArrayElement(entry.vertex_cache, 0), ref smi); entry.mesh.normals = entry.vertex_cache; } if (needs_index_update) { // update uvs if (aiPolyMeshHasUVs(abc)) { Array.Resize(ref entry.uv_cache, smi.vertex_count); aiPolyMeshCopySplitedUVs(abc, Marshal.UnsafeAddrOfPinnedArrayElement(entry.uv_cache, 0), ref smi); entry.mesh.uv = entry.uv_cache; } // update indices Array.Resize(ref entry.index_cache, smi.triangulated_index_count); aiPolyMeshCopySplitedIndices(abc, Marshal.UnsafeAddrOfPinnedArrayElement(entry.index_cache, 0), ref smi); entry.mesh.SetIndices(entry.index_cache, MeshTopology.Triangles, 0); } // recalculate normals if (!aiPolyMeshHasNormals(abc)) { entry.mesh.RecalculateNormals(); } ++nth_submesh; if (is_end) { break; } } for (int i = nth_submesh + 1; i < abcmesh.m_meshes.Count; ++i) { abcmesh.m_meshes[i].host.SetActive(false); } }