public void InitializeFromApply(DMesh3 mesh, IEnumerable <int> triangles) { initialize_buffers(mesh); bool has_groups = mesh.HasTriangleGroups; foreach (int tid in triangles) { if (!mesh.IsTriangle(tid)) { continue; } Index3i tv = mesh.GetTriangle(tid); bool va = save_vertex(mesh, tv.a); bool vb = save_vertex(mesh, tv.b); bool vc = save_vertex(mesh, tv.c); Index4i tri = new Index4i(tv.a, tv.b, tv.c, has_groups ? mesh.GetTriangleGroup(tid) : DMesh3.InvalidID); RemovedT.Add(tid); Triangles.Add(tri); MeshResult result = mesh.RemoveTriangle(tid, true, false); if (result != MeshResult.Ok) { throw new Exception("RemoveTrianglesMeshChange.Initialize: exception in RemoveTriangle(" + tid.ToString() + "): " + result.ToString()); } Util.gDevAssert(mesh.IsVertex(tv.a) == va && mesh.IsVertex(tv.b) == vb && mesh.IsVertex(tv.c) == vc); } }
public int AppendTriangle(int i, int j, int k, int g = -1) { int ti = Triangles.Length / 3; if (HasTriangleGroups) { FaceGroups.Add((g == -1) ? 0 : g); } Triangles.Add(i); Triangles.Add(j); Triangles.Add(k); return(ti); }
public int AppendQuad(int i, int j, int k, int l, int g = -1) { int qi = Quads.Length / 4; if (HasFaceGroups) { FaceGroups.Add((g == -1) ? 0 : g); } Quads.Add(i); Quads.Add(j); Quads.Add(k); Quads.Add(l); return(qi); }
public void InitializeFromExisting(DMesh3 mesh, IEnumerable <int> added_v, IEnumerable <int> added_t) { initialize_buffers(mesh); bool has_groups = mesh.HasTriangleGroups; if (added_v != null) { foreach (int vid in added_v) { Util.gDevAssert(mesh.IsVertex(vid)); append_vertex(mesh, vid); } } foreach (int tid in added_t) { Util.gDevAssert(mesh.IsTriangle(tid)); Index3i tv = mesh.GetTriangle(tid); Index4i tri = new Index4i(tv.a, tv.b, tv.c, has_groups ? mesh.GetTriangleGroup(tid) : DMesh3.InvalidID); AddedT.Add(tid); Triangles.Add(tri); } }
bool save_vertex(DMesh3 mesh, int vid, bool force = false) { if (force || mesh.VerticesRefCounts.refCount(vid) == 2) { RemovedV.Add(vid); Positions.Add(mesh.GetVertex(vid)); if (Normals != null) { Normals.Add(mesh.GetVertexNormal(vid)); } if (Colors != null) { Colors.Add(mesh.GetVertexColor(vid)); } if (UVs != null) { UVs.Add(mesh.GetVertexUV(vid)); } return(false); } return(true); }
public int AppendUV(Vector2f uv) { int id = UVs.Length; UVs.Add(uv); return(id); }
public IOReadResult Read(BinaryReader reader, ReadOptions options, IMeshBuilder builder) { if (options.CustomFlags != null) { ParseArguments(options.CustomFlags); } /*byte[] header = */ reader.ReadBytes(80); int totalTris = reader.ReadInt32(); Objects = new List <STLSolid>(); Objects.Add(new STLSolid()); int tri_size = 50; // bytes IntPtr bufptr = Marshal.AllocHGlobal(tri_size); var tmp = new stl_triangle(); Type tri_type = tmp.GetType(); var tri_attribs = new DVector <short>(); try { for (int i = 0; i < totalTris; ++i) { byte[] tri_bytes = reader.ReadBytes(50); if (tri_bytes.Length < 50) { break; } Marshal.Copy(tri_bytes, 0, bufptr, tri_size); var tri = (stl_triangle)Marshal.PtrToStructure(bufptr, tri_type); append_vertex(tri.ax, tri.ay, tri.az); append_vertex(tri.bx, tri.by, tri.bz); append_vertex(tri.cx, tri.cy, tri.cz); tri_attribs.Add(tri.attrib); } } catch (Exception e) { return(new IOReadResult(IOCode.GenericReaderError, "exception: " + e.Message)); } Marshal.FreeHGlobal(bufptr); if (Objects.Count == 1) { Objects[0].TriAttribs = tri_attribs; } foreach (STLSolid solid in Objects) { BuildMesh(solid, builder); } return(new IOReadResult(IOCode.Ok, "")); }
public PackedSparseMatrix Square() { if (Rows.Length != Columns) { throw new Exception("PackedSparseMatrix.Square: matrix is not square!"); } int N = Columns; var entries = new DVector <matrix_entry>(); var entries_lock = new SpinLock(); gParallel.BlockStartEnd(0, N - 1, (r_start, r_end) => { for (int r1i = r_start; r1i <= r_end; r1i++) { // determine which entries of squared matrix might be nonzeros var nbrs = new HashSet <int>(); nbrs.Add(r1i); PackedSparseMatrix.nonzero[] row = Rows[r1i]; for (int k = 0; k < row.Length; ++k) { if (row[k].j > r1i) { nbrs.Add(row[k].j); } PackedSparseMatrix.nonzero[] row2 = Rows[row[k].j]; for (int j = 0; j < row2.Length; ++j) { if (row2[j].j > r1i) // only compute lower-triangular entries { nbrs.Add(row2[j].j); } } } // compute them! foreach (int c2i in nbrs) { double v = DotRowColumn(r1i, c2i, this); if (Math.Abs(v) > MathUtil.ZeroTolerance) { bool taken = false; entries_lock.Enter(ref taken); entries.Add(new matrix_entry() { r = r1i, c = c2i, value = v }); entries_lock.Exit(); } } } }); var R = new PackedSparseMatrix(entries, N, N, true); return(R); }
/// <summary> /// insert val into list at list_index. /// </summary> public void Insert(int list_index, int val) { int block_ptr = list_heads[list_index]; if (block_ptr == Null) { block_ptr = allocate_block(); block_store[block_ptr] = 0; list_heads[list_index] = block_ptr; } int N = block_store[block_ptr]; if (N < BLOCKSIZE) { block_store[block_ptr + N + 1] = val; } else { // spill to linked list int cur_head = block_store[block_ptr + BLOCK_LIST_OFFSET]; if (free_head_ptr == Null) { // allocate new linkedlist node int new_ptr = linked_store.size; linked_store.Add(val); linked_store.Add(cur_head); block_store[block_ptr + BLOCK_LIST_OFFSET] = new_ptr; } else { // pull from free list int free_ptr = free_head_ptr; free_head_ptr = linked_store[free_ptr + 1]; linked_store[free_ptr] = val; linked_store[free_ptr + 1] = cur_head; block_store[block_ptr + BLOCK_LIST_OFFSET] = free_ptr; } } // count new element block_store[block_ptr] += 1; }
/* * Construction */ public int AppendVertex(double x, double y, double z) { int i = Vertices.Length / 3; if (HasVertexNormals) { Normals.Add(0); Normals.Add(1); Normals.Add(0); } if (HasVertexColors) { Colors.Add(1); Colors.Add(1); Colors.Add(1); } if (HasVertexUVs) { UVs.Add(0); UVs.Add(0); } Vertices.Add(x); Vertices.Add(y); Vertices.Add(z); return(i); }
public T Allocate() { if (Free.size > 0) { T allocated = Free[Free.size - 1]; Free.pop_back(); return(allocated); } else { T newval = new T(); Allocated.Add(newval); return(newval); } }
// Appends a box that contains free triangles in one-ring of vertex vid. // If tri count is < spill threshold, push onto spill list instead. // Returns # of free tris found. int add_one_ring_box(int vid, byte[] used_triangles, int[] temp_tris, ref int iBoxCur, ref int iIndicesCur, DVector <int> spill, int nSpillThresh) { // collect free triangles int num_free = 0; foreach (int tid in mesh.VtxTrianglesItr(vid)) { if (used_triangles[tid] == 0) { temp_tris[num_free++] = tid; } } // none free, get out if (num_free == 0) { return(0); } // if we only had a couple free triangles, wait and see if // they get picked up by another vert if (num_free < nSpillThresh) { spill.Add(vid); return(num_free); } // append new box AxisAlignedBox3f box = AxisAlignedBox3f.Empty; int iBox = iBoxCur++; box_to_index.insert(iIndicesCur, iBox); index_list.insert(num_free, iIndicesCur++); for (int i = 0; i < num_free; ++i) { index_list.insert(temp_tris[i], iIndicesCur++); used_triangles[temp_tris[i]]++; // incrementing for sanity check below, just need to set to 1 box.Contain(mesh.GetTriBounds(temp_tris[i])); } box_centers.insert(box.Center, iBox); box_extents.insert(box.Extents, iBox); return(num_free); }
void append_vertex(DMesh3 mesh, int vid) { AddedV.Add(vid); Positions.Add(mesh.GetVertex(vid)); if (Normals != null) { Normals.Add(mesh.GetVertexNormal(vid)); } if (Colors != null) { Colors.Add(mesh.GetVertexColor(vid)); } if (UVs != null) { UVs.Add(mesh.GetVertexUV(vid)); } }
// todo: // remove // clear public void rebuild_free_list() { free_indices = new DVector <int>(); used_count = 0; int N = ref_counts.Length; for (int i = 0; i < N; ++i) { if (ref_counts[i] > 0) { used_count++; } else { free_indices.Add(i); } } }
public static PackedSparseMatrix FromDense(DenseMatrix m, bool bSymmetric) { var nonzeros = new DVector <matrix_entry>(); for (int r = 0; r < m.Rows; ++r) { int nStop = (bSymmetric) ? r + 1 : m.Columns; for (int c = 0; c < nStop; ++c) { if (m[r, c] != 0) { nonzeros.Add(new matrix_entry() { r = r, c = c, value = m[r, c] }); } } } return(new PackedSparseMatrix(nonzeros, m.Rows, m.Columns, bSymmetric)); }
public int AppendNewVertex(DMesh3 mesh, int vid) { int idx = ModifiedV.Length; ModifiedV.Add(vid); OldPositions.Add(mesh.GetVertex(vid)); NewPositions.Add(OldPositions[idx]); if (NewNormals != null) { OldNormals.Add(mesh.GetVertexNormal(vid)); NewNormals.Add(OldNormals[idx]); } if (NewColors != null) { OldColors.Add(mesh.GetVertexColor(vid)); NewColors.Add(OldColors[idx]); } if (NewUVs != null) { OldUVs.Add(mesh.GetVertexUV(vid)); NewUVs.Add(OldUVs[idx]); } return(idx); }
// strategy here is: // 1) partition triangles by vertex one-rings into leaf boxes // 1a) first pass where we skip one-rings that have < 3 free tris // 1b) second pass where we handle any missed tris // 2) sequentially combine N leaf boxes into (N/2 + N%2) layer 2 boxes // 3) repeat until layer K has only 1 box, which is root of tree void build_by_one_rings(ClusterPolicy ePolicy) { box_to_index = new DVector <int>(); box_centers = new DVector <Vector3f>(); box_extents = new DVector <Vector3f>(); int iBoxCur = 0; index_list = new DVector <int>(); int iIndicesCur = 0; // replace w/ BitArray ? byte[] used_triangles = new byte[mesh.MaxTriangleID]; Array.Clear(used_triangles, 0, used_triangles.Length); // temporary buffer int nMaxEdgeCount = mesh.GetMaxVtxEdgeCount(); int[] temp_tris = new int[2 * nMaxEdgeCount]; // first pass: cluster by one-ring, but if # of free tris // in a ring is small (< 3), push onto spill list to try again, // because those tris might be picked up by a bigger cluster DVector <int> spill = new DVector <int>(); foreach (int vid in mesh.VertexIndices()) { int tCount = add_one_ring_box(vid, used_triangles, temp_tris, ref iBoxCur, ref iIndicesCur, spill, 3); if (tCount < 3) { spill.Add(vid); } } // second pass: check any spill vertices. Most are probably gone // now, but a few stray triangles might still exist int N = spill.Length; for (int si = 0; si < N; ++si) { int vid = spill[si]; add_one_ring_box(vid, used_triangles, temp_tris, ref iBoxCur, ref iIndicesCur, null, 0); } // [RMS] test code to make sure each triangle is in exactly one list //foreach ( int tid in mesh.TriangleIndices() ) { // int n = used_triangles[tid]; // if (n != 1) // Util.gBreakToDebugger(); //} // keep track of where triangle lists end triangles_end = iIndicesCur; // this defines ClusterPolicy.Default //ClusterFunctionType clusterF = cluster_boxes; //ClusterFunctionType clusterF = cluster_boxes_matrix; ClusterFunctionType clusterF = cluster_boxes_nearsearch; if (ePolicy == ClusterPolicy.Fastest) { clusterF = cluster_boxes; } else if (ePolicy == ClusterPolicy.MinimalVolume) { clusterF = cluster_boxes_matrix; } else if (ePolicy == ClusterPolicy.FastVolumeMetric) { clusterF = cluster_boxes_nearsearch; } // ok, now repeatedly cluster current layer of N boxes into N/2 + N%2 boxes, // until we hit a 1-box layer, which is root of the tree int nPrevEnd = iBoxCur; int nLayerSize = clusterF(0, iBoxCur, ref iBoxCur, ref iIndicesCur); int iStart = nPrevEnd; int iCount = iBoxCur - nPrevEnd; while (nLayerSize > 1) { nPrevEnd = iBoxCur; nLayerSize = clusterF(iStart, iCount, ref iBoxCur, ref iIndicesCur); iStart = nPrevEnd; iCount = iBoxCur - nPrevEnd; } root_index = iBoxCur - 1; }
private void append_face(string[] tokens, OBJMaterial activeMaterial, int nActiveGroup) { int nMode = 0; if (tokens[1].IndexOf("//") != -1) { nMode = 1; } else if (tokens[1].IndexOf('/') != -1) { nMode = 2; } var t = new Triangle(); t.clear(); for (int ti = 0; ti < tokens.Length - 1; ++ti) { int j = (ti < 3) ? ti : 2; if (ti >= 3) { t.move_vertex(2, 1); } // parse next vertex if (nMode == 0) { // "f v1 v2 v3" t.set_vertex(j, parse_v(tokens[ti + 1])); } else if (nMode == 1) { // "f v1//vn1 v2//vn2 v3//vn3" string[] parts = tokens[ti + 1].Split(this.splitDoubleSlash, StringSplitOptions.RemoveEmptyEntries); t.set_vertex(j, parse_v(parts[0]), parse_n(parts[1])); } else if (nMode == 2) { string[] parts = tokens[ti + 1].Split(this.splitSlash, StringSplitOptions.RemoveEmptyEntries); if (parts.Length == 2) { // "f v1/vt1 v2/vt2 v3/vt3" t.set_vertex(j, parse_v(parts[0]), -1, parse_u(parts[1])); } else if (parts.Length == 3) { // "f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3" t.set_vertex(j, parse_v(parts[0]), parse_n(parts[2]), parse_u(parts[1])); } else { emit_warning("parse_triangle unexpected face component " + tokens[j]); } } // do append if (ti >= 2) { if (activeMaterial != null) { t.nMaterialID = activeMaterial.id; UsedMaterials[activeMaterial.id] = activeMaterial.name; } t.nGroupID = nActiveGroup; vTriangles.Add(t); if (t.is_complex()) { HasComplexVertices = true; } } } }
public void Return(T obj) { Free.Add(obj); }
public IOReadResult ParseInput(TextReader reader, ReadOptions options) { vPositions = new DVector <double>(); vNormals = new DVector <float>(); vUVs = new DVector <float>(); vColors = new DVector <float>(); vTriangles = new DVector <Triangle>(); bool bVerticesHaveColors = false; int nMaxUVLength = 0; OBJMaterial activeMaterial = null; var GroupNames = new Dictionary <string, int>(); int nGroupCounter = 0; int nActiveGroup = Triangle.InvalidGroupID; int nLines = 0; while (reader.Peek() >= 0) { string line = reader.ReadLine(); nLines++; string[] tokens = line.Split((char[])null, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length == 0) { continue; } // [RMS] this will hang VS on large models... //if (nWarningLevel >= 2) // emit_warning("Parsing line " + line); try { if (tokens[0][0] == 'v') { if (tokens[0].Length == 1) { if (tokens.Length == 7) { vPositions.Add(Double.Parse(tokens[1])); vPositions.Add(Double.Parse(tokens[2])); vPositions.Add(Double.Parse(tokens[3])); vColors.Add(float.Parse(tokens[4])); vColors.Add(float.Parse(tokens[5])); vColors.Add(float.Parse(tokens[6])); bVerticesHaveColors = true; } else if (tokens.Length >= 4) { vPositions.Add(Double.Parse(tokens[1])); vPositions.Add(Double.Parse(tokens[2])); vPositions.Add(Double.Parse(tokens[3])); } if (tokens.Length != 4 && tokens.Length != 7) { emit_warning("[OBJReader] vertex has unknown format: " + line); } } else if (tokens[0][1] == 'n') { if (tokens.Length >= 4) { vNormals.Add(float.Parse(tokens[1])); vNormals.Add(float.Parse(tokens[2])); vNormals.Add(float.Parse(tokens[3])); } if (tokens.Length != 4) { emit_warning("[OBJReader] normal has more than 3 coordinates: " + line); } } else if (tokens[0][1] == 't') { if (tokens.Length >= 3) { vUVs.Add(float.Parse(tokens[1])); vUVs.Add(float.Parse(tokens[2])); nMaxUVLength = Math.Max(nMaxUVLength, tokens.Length); } if (tokens.Length != 3) { emit_warning("[OBJReader] UV has unknown format: " + line); } } } else if (tokens[0][0] == 'f') { if (tokens.Length < 4) { emit_warning("[OBJReader] degenerate face specified : " + line); } else if (tokens.Length == 4) { var tri = new Triangle(); parse_triangle(tokens, ref tri); tri.nGroupID = nActiveGroup; if (activeMaterial != null) { tri.nMaterialID = activeMaterial.id; UsedMaterials[activeMaterial.id] = activeMaterial.name; } vTriangles.Add(tri); if (tri.is_complex()) { HasComplexVertices = true; } } else { append_face(tokens, activeMaterial, nActiveGroup); } } else if (tokens[0][0] == 'g') { string sGroupName = (tokens.Length == 2) ? tokens[1] : line.Substring(line.IndexOf(tokens[1])); if (GroupNames.ContainsKey(sGroupName)) { nActiveGroup = GroupNames[sGroupName]; } else { nActiveGroup = nGroupCounter; GroupNames[sGroupName] = nGroupCounter++; } } else if (tokens[0][0] == 'o') { // TODO multi-object support } else if (tokens[0] == "mtllib" && options.ReadMaterials) { if (MTLFileSearchPaths.Count == 0) { emit_warning("Materials requested but Material Search Paths not initialized!"); } string sMTLPathString = (tokens.Length == 2) ? tokens[1] : line.Substring(line.IndexOf(tokens[1])); string sFile = FindMTLFile(sMTLPathString); if (sFile != null) { IOReadResult result = ReadMaterials(sFile); if (result.code != IOCode.Ok) { emit_warning("error parsing " + sFile + " : " + result.message); } } else { emit_warning("material file " + sMTLPathString + " could not be found in material search paths"); } } else if (tokens[0] == "usemtl" && options.ReadMaterials) { activeMaterial = find_material(tokens[1]); } } catch (Exception e) { emit_warning("error parsing line " + nLines.ToString() + ": " + line + ", exception " + e.Message); } } m_bOBJHasPerVertexColors = bVerticesHaveColors; m_bOBJHasTriangleGroups = (nActiveGroup != Triangle.InvalidGroupID); m_nSetInvalidGroupsTo = nGroupCounter++; m_nUVComponents = nMaxUVLength; return(new IOReadResult(IOCode.Ok, "")); }