Esempio n. 1
0
 // return point that minimizes quadric error for edge [ea,eb]
 Vector3d OptimalPoint(QuadricError q, int ea, int eb)
 {
     if (MinimizeQuadricPositionError == false)
     {
         return((mesh.GetVertex(ea) + mesh.GetVertex(eb)) * 0.5);
     }
     else
     {
         try {
             return(q.OptimalPoint());
         } catch {
             // degenerate matrix, evaluate quadric at edge end and midpoints
             // (could do line search here...)
             Vector3d va = mesh.GetVertex(ea);
             Vector3d vb = mesh.GetVertex(eb);
             Vector3d c  = (va + vb) * 0.5;
             double   fa = q.Evaluate(va);
             double   fb = q.Evaluate(vb);
             double   fc = q.Evaluate(c);
             double   m  = MathUtil.Min(fa, fb, fc);
             if (m == fa)
             {
                 return(va);
             }
             else if (m == fb)
             {
                 return(vb);
             }
             return(c);
         }
     }
 }
Esempio n. 2
0
        // return point that minimizes quadric error for edge [ea,eb]
        protected Vector3d OptimalPoint(int eid, ref QuadricError q, int ea, int eb)
        {
            // if we would like to preserve boundary, we need to know that here
            // so that we properly score these edges
            if (HaveBoundary && PreserveBoundaryShape)
            {
                if (mesh.IsBoundaryEdge(eid))
                {
                    return((mesh.GetVertex(ea) + mesh.GetVertex(eb)) * 0.5);
                }
                else
                {
                    if (IsBoundaryV(ea))
                    {
                        return(mesh.GetVertex(ea));
                    }
                    else if (IsBoundaryV(eb))
                    {
                        return(mesh.GetVertex(eb));
                    }
                }
            }

            // [TODO] if we have constraints, we should apply them here, for same reason as bdry above...

            if (MinimizeQuadricPositionError == false)
            {
                return(project((mesh.GetVertex(ea) + mesh.GetVertex(eb)) * 0.5));
            }
            else
            {
                Vector3d result = Vector3d.Zero;
                if (q.OptimalPoint(ref result))
                {
                    return(project(result));
                }

                // degenerate matrix, evaluate quadric at edge end and midpoints
                // (could do line search here...)
                Vector3d va = mesh.GetVertex(ea);
                Vector3d vb = mesh.GetVertex(eb);
                Vector3d c  = project((va + vb) * 0.5);
                double   fa = q.Evaluate(ref va);
                double   fb = q.Evaluate(ref vb);
                double   fc = q.Evaluate(ref c);
                double   m  = MathUtil.Min(fa, fb, fc);
                if (m == fa)
                {
                    return(va);
                }
                else if (m == fb)
                {
                    return(vb);
                }

                return(c);
            }
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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);
             */
        }
Esempio n. 5
0
 // 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);
         }
     }
 }
Esempio n. 6
0
 // 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);
         }
     }
 }