public Mesh ExtractMesh(IEnumerable <int> geom_ids) { /* Returns a single Mesh containing all geometry from the geom_ids (except the UV * coordinates). The mesh consists of two submeshes: the triangles, and the stems. * We fill them with dummies if they are empty, to simplify the callers. */ CallRegularUpdate(); lock (geometries_lock) { var extractor = new MeshExtractor(); extractor.vertices = new Vector3[mgos.Count][]; extractor.normals = new Vector3[mgos.Count][]; foreach (var geom_id in geom_ids) { Geom geom = geometries[geom_id]; uint gmask = geom.gindex & GINDEX_MASK; if (gmask != GINDEX_FREE) { int renderer_index = (int)(geom.gindex >> GINDEX_SHIFT); var mgo = mgos[renderer_index]; if (mgo != null) { mgo._ExtractMeshGeometry(extractor, geom, renderer_index); } } } if (extractor.out_vertices.Count == 0) { extractor.out_vertices.Add(Vector3.zero); extractor.out_normals.Add(Vector3.zero); } if (extractor.out_triangles.Count == 0) { extractor.out_triangles.Add(0); extractor.out_triangles.Add(0); extractor.out_triangles.Add(0); } if (extractor.out_stems.Count == 0) { extractor.out_stems.Add(0); extractor.out_stems.Add(0); } var mesh = new Mesh(); if (extractor.out_vertices.Count >= 0xFFE0) { mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; } mesh.SetVertices(extractor.out_vertices); mesh.SetNormals(extractor.out_normals); mesh.subMeshCount = 2; mesh.SetTriangles(extractor.out_triangles, 0, calculateBounds: false); mesh.SetIndices(extractor.out_stems.ToArray(), MeshTopology.Lines, 1, calculateBounds: false); mesh.RecalculateBounds(); return(mesh); } }
internal void _ExtractMeshGeometry(MeshExtractor extractor, Geom geom, int renderer_index) { var vertices = extractor.vertices[renderer_index]; if (vertices == null) { vertices = extractor.vertices[renderer_index] = mesh.vertices; } var normals = extractor.normals[renderer_index]; if (normals == null) { normals = extractor.normals[renderer_index] = mesh.normals; } int tstart, tstop; tstart = geom.triangle_start * 3; tstop = geom.triangle_stop * 3; if (tstop == 0xFFFF * 3) { tstop = all_triangles.Length; } int sstart, sstop; sstart = geom.stem_start * 2; sstop = geom.stem_stop * 2; if (sstop == 0xFFFF * 2) { sstop = all_stems.Length; } /* xxx this assumes that each independent geom_id was built from its * own set of new vertices, without reusing any of the previous vertices; * otherwise, we're going to get large ranges in min,max and a lot of * duplication if we're extracting a mesh with many geom_ids */ int min = 0x7fffffff, max = -1; for (int j = tstart; j < tstop; j++) { if (all_triangles[j] < min) { min = all_triangles[j]; } if (all_triangles[j] > max) { max = all_triangles[j]; } } for (int j = sstart; j < sstop; j++) { if (all_stems[j] < min) { min = all_stems[j]; } if (all_stems[j] > max) { max = all_stems[j]; } } int diff = extractor.out_vertices.Count - min; for (int i = min; i <= max; i++) { extractor.out_vertices.Add(vertices[i]); extractor.out_normals.Add(i < normals.Length ? normals[i] : Vector3.zero); } for (int j = tstart; j < tstop; j++) { extractor.out_triangles.Add(all_triangles[j] + diff); } for (int j = sstart; j < sstop; j++) { extractor.out_stems.Add(all_stems[j] + diff); } }