public SubmeshBuilder GetSubmeshBuilder(int submeshIndex, GeometryType geomType)
        {
            SubmeshBuilder builder;

            if (!m_submeshesBySubmeshIndex.TryGetValue(submeshIndex, out builder))
            {
                builder = new SubmeshBuilder(new SubmeshBuilder.AddVertexDelegate((fv) => {
                    if (Mode == GenerateMode.CollisionMesh)
                    {
                        // Collision meshes ignore UV, Normals, and Color data
                        fv.ClearUV1();
                        fv.ClearUV2();
                        fv.ClearUV3();
                        fv.ClearNormal();
                        fv.SetColor(new Vector4(1.0f, 1.0f, 1.0f, 1.0f));
                    }

                    UInt64 vertHash = fv.CalculateHash();

                    Dictionary <UInt64, int> submesh_verthash_to_index;
                    if (!m_vert_hash_by_submesh_to_index.TryGetValue(submeshIndex, out submesh_verthash_to_index))
                    {
                        submesh_verthash_to_index = new Dictionary <UInt64, int>();
                        m_vert_hash_by_submesh_to_index.Add(submeshIndex, submesh_verthash_to_index);
                    }

                    // For combined mesh
                    int combined_index;
                    if (!m_combined_vert_hash_to_index.TryGetValue(vertHash, out combined_index))
                    {
                        combined_index = m_combined_verts.Count;
                        m_combined_vert_hash_to_index.Add(vertHash, combined_index);
                        m_combined_verts.Add(fv);
                    }

                    // For individual submesh
                    int submesh_index;
                    if (!submesh_verthash_to_index.TryGetValue(vertHash, out submesh_index))
                    {
                        List <FaceVertex> submesh_vert_list;
                        if (!m_verts_by_submesh.TryGetValue(submeshIndex, out submesh_vert_list))
                        {
                            submesh_vert_list = new List <FaceVertex>();
                            m_verts_by_submesh.Add(submeshIndex, submesh_vert_list);
                        }

                        submesh_index = submesh_vert_list.Count;
                        submesh_verthash_to_index.Add(vertHash, submesh_index);
                        submesh_vert_list.Add(fv);
                    }

                    return(new SubmeshBuilder.AddVertexResult()
                    {
                        CombinedVertexIndex = combined_index, SubmeshVertexIndex = submesh_index
                    });
                }), geomType);
                m_submeshesBySubmeshIndex.Add(submeshIndex, builder);
            }
            return(builder);
        }
        public void GenerateMeshObject(GenerateMode generateMode, float smoothingAngleSameMaterial, float smoothingAngleDiffMaterial, List <Mesh> output_mesh_list, List <int> output_submesh_index_list)
        {
            if (generateMode == GenerateMode.RenderMesh)
            {
                //
                // Building a render mesh -- materials matter
                //
                foreach (var kvp in m_submeshesBySubmeshIndex)
                {
                    int            submesh_index   = kvp.Key;
                    SubmeshBuilder submesh_builder = kvp.Value;

                    // Sometimes we may create a submesh builder but not add any verts
                    // to it. This could be for no-render decal face flags.
                    List <FaceVertex> faceVerts;
                    if (!m_verts_by_submesh.TryGetValue(submesh_index, out faceVerts))
                    {
                        continue;
                    }

                    BuildMeshWorkerResult submesh_mesh_data = new BuildMeshWorkerResult();
                    submesh_mesh_data.Build(faceVerts);

                    Mesh m = new Mesh();
                    m.vertices = submesh_mesh_data.m_vertices;

                    // Needs UVs and colors
                    m.uv = submesh_mesh_data.m_uv1s;
                    if (submesh_mesh_data.m_has_uv2)
                    {
                        m.uv2 = submesh_mesh_data.m_uv2s;
                    }
                    if (submesh_mesh_data.m_has_uv3)
                    {
                        m.uv3 = submesh_mesh_data.m_uv3s;
                    }
                    if (submesh_mesh_data.m_has_translucent)
                    {
                        // Only take colors if there was a non-white color
                        m.colors = submesh_mesh_data.m_colors;
                    }

                    // As an optimization - each material gets its own mesh (instead of using submeshes within the mesh)
                    m.subMeshCount = 1;
                    m.SetTriangles(submesh_builder.SubmeshTriangleList, 0);

                    m.RecalculateNormals(smoothingAngleSameMaterial, smoothingAngleDiffMaterial, submesh_mesh_data.m_normal_lock, submesh_mesh_data.m_normals);
                    // Recalculate tangents (AFTER normals, as RecalculateNormals will destroy tangents)
                    m.RecalculateTangents();
                    m.RecalculateBounds();

                    output_mesh_list.Add(m);
                    output_submesh_index_list.Add(submesh_index);
                }
            }
            else
            {
                //
                // Building a collision mesh -- combine the verts
                //
                BuildMeshWorkerResult combined_mesh_data = new BuildMeshWorkerResult();
                combined_mesh_data.Build(m_combined_verts);

                Mesh m = new Mesh();
                m.vertices = combined_mesh_data.m_vertices;

                // Collision mesh is one submesh
                m.subMeshCount = 1;

                var all_combined_triangles = new List <int>();
                foreach (var kvp in m_submeshesBySubmeshIndex)
                {
                    int submeshIndex = kvp.Key;
                    if (submeshIndex < 0)
                    {
                        continue;
                    }
                    var submeshBuilder = kvp.Value;
                    if (submeshBuilder.GeomType == GeometryType.Portal)
                    {
                        // don't include the debug portal geometry into the collision data
                        continue;
                    }
                    all_combined_triangles.AddRange(submeshBuilder.CombinedTriangleList);
                }
                m.SetTriangles(all_combined_triangles.ToArray(), 0);

                m.RecalculateNormals(smoothingAngleSameMaterial, smoothingAngleDiffMaterial, combined_mesh_data.m_normal_lock, combined_mesh_data.m_normals);
                m.RecalculateBounds();
                ;
                output_mesh_list.Add(m);
                output_submesh_index_list.Add(0);
            }
        }