protected virtual void InitializeQueue() { int NE = mesh.EdgeCount; Nodes = new QEdge[2 * NE]; // [RMS] do we need this many? NodePool = new MemoryPool <QEdge>(NE); EdgeQueue = new g3ext.FastPriorityQueue <QEdge>(NE); int cur_eid = start_edges(); bool done = false; do { if (mesh.IsEdge(cur_eid)) { Index2i ev = mesh.GetEdgeV(cur_eid); QuadricError Q = new QuadricError(ref vertQuadrics[ev.a], ref vertQuadrics[ev.b]); Vector3d opt = OptimalPoint(Q, ev.a, ev.b); double err = Q.Evaluate(opt); QEdge ee = NodePool.Allocate(); ee.Initialize(cur_eid, Q, opt); Nodes[cur_eid] = ee; EdgeQueue.Enqueue(ee, (float)err); } cur_eid = next_edge(cur_eid, out done); } while (done == false); }
protected virtual void InitializeQueue() { int NE = mesh.EdgeCount; int MaxEID = mesh.MaxEdgeID; EdgeQuadrics = new QEdge[MaxEID]; EdgeQueue = new IndexPriorityQueue(MaxEID); float[] edgeErrors = new float[MaxEID]; // vertex quadrics can be computed in parallel gParallel.BlockStartEnd(0, MaxEID - 1, (start_eid, end_eid) => { for (int eid = start_eid; eid <= end_eid; eid++) { if (mesh.IsEdge(eid)) { Index2i ev = mesh.GetEdgeV(eid); QuadricError Q = new QuadricError(ref vertQuadrics[ev.a], ref vertQuadrics[ev.b]); Vector3d opt = OptimalPoint(eid, ref Q, ev.a, ev.b); edgeErrors[eid] = (float)Q.Evaluate(ref opt); EdgeQuadrics[eid] = new QEdge(eid, ref Q, ref opt); } } }); // sorted pq insert is faster, so sort edge errors array and index map int[] indices = new int[MaxEID]; for (int i = 0; i < MaxEID; ++i) { indices[i] = i; } Array.Sort(edgeErrors, indices); // now do inserts for (int i = 0; i < edgeErrors.Length; ++i) { int eid = indices[i]; if (mesh.IsEdge(eid)) { QEdge edge = EdgeQuadrics[eid]; EdgeQueue.Insert(edge.eid, edgeErrors[i]); } } /* * // previous code that does unsorted insert. This is marginally slower, but * // might get even slower on larger meshes? have only tried up to about 350k. * // (still, this function is not the bottleneck...) * int cur_eid = start_edges(); * bool done = false; * do { * if (mesh.IsEdge(cur_eid)) { * QEdge edge = EdgeQuadrics[cur_eid]; * double err = errList[cur_eid]; * EdgeQueue.Enqueue(cur_eid, (float)err); * } * cur_eid = next_edge(cur_eid, out done); * } while (done == false); */ }
public virtual void DoReduce() { if (mesh.TriangleCount == 0) // badness if we don't catch this... { return; } begin_pass(); begin_setup(); InitializeVertexQuadrics(); InitializeQueue(); end_setup(); begin_ops(); begin_collapse(); while (EdgeQueue.Count > 0 && mesh.TriangleCount > TargetTriangleCount) { COUNT_ITERATIONS++; QEdge cur = EdgeQueue.Dequeue(); Nodes[cur.eid] = null; NodePool.Return(cur); if (!mesh.IsEdge(cur.eid)) { continue; } Index2i ev = mesh.GetEdgeV(cur.eid); int vKept; ProcessResult result = CollapseEdge(cur.eid, cur.collapse_pt, out vKept); if (result == ProcessResult.Ok_Collapsed) { vertQuadrics[vKept] = cur.q; UpdateNeighbours(vKept); } } end_collapse(); end_ops(); Reproject(); end_pass(); }
// update queue weight for each edge in vertex one-ring protected virtual void UpdateNeighbours(int vid) { foreach (int eid in mesh.VtxEdgesItr(vid)) { Index2i nev = mesh.GetEdgeV(eid); QuadricError Q = new QuadricError(ref vertQuadrics[nev.a], ref vertQuadrics[nev.b]); Vector3d opt = OptimalPoint(eid, ref Q, nev.a, nev.b); double err = Q.Evaluate(ref opt); EdgeQuadrics[eid] = new QEdge(eid, ref Q, ref opt); if (EdgeQueue.Contains(eid)) { EdgeQueue.Update(eid, (float)err); } else { EdgeQueue.Insert(eid, (float)err); } } }
// update queue weight for each edge in vertex one-ring protected virtual void UpdateNeighbours(int vid) { foreach (int eid in mesh.VtxEdgesItr(vid)) { Index2i nev = mesh.GetEdgeV(eid); QuadricError Q = new QuadricError(ref vertQuadrics[nev.a], ref vertQuadrics[nev.b]); Vector3d opt = OptimalPoint(Q, nev.a, nev.b); double err = Q.Evaluate(opt); QEdge eid_node = Nodes[eid]; if (eid_node != null) { eid_node.q = Q; eid_node.collapse_pt = opt; EdgeQueue.UpdatePriority(eid_node, (float)err); } else { QEdge ee = NodePool.Allocate(); ee.Initialize(eid, Q, opt); Nodes[eid] = ee; EdgeQueue.Enqueue(ee, (float)err); } } }