Пример #1
0
    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();
        }
    }
Пример #2
0
    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);
        }
    }