예제 #1
0
        protected virtual void InitializeVertexQuadrics()
        {
            int NT = mesh.MaxTriangleID;

            QuadricError[] triQuadrics = new QuadricError[NT];
            double[]       triAreas    = new double[NT];
            gParallel.ForEach(mesh.TriangleIndices(), (tid) => {
                Vector3d c, n;
                mesh.GetTriInfo(tid, out n, out triAreas[tid], out c);
                triQuadrics[tid] = new QuadricError(n, c);
            });


            int NV = mesh.MaxVertexID;

            vertQuadrics = new QuadricError[NV];
            gParallel.ForEach(mesh.VertexIndices(), (vid) => {
                vertQuadrics[vid] = QuadricError.Zero;
                foreach (int tid in mesh.VtxTrianglesItr(vid))
                {
                    vertQuadrics[vid].Add(triAreas[tid], ref triQuadrics[tid]);
                }
                //Util.gDevAssert(MathUtil.EpsilonEqual(0, vertQuadrics[i].Evaluate(mesh.GetVertex(i)), MathUtil.Epsilon * 10));
            });
        }
예제 #2
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);
         }
     }
 }
예제 #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);
        }
예제 #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);
             */
        }
예제 #5
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);
            }
        }
예제 #6
0
 public void Add(double w, ref QuadricError b)
 {
     Axx += w * b.Axx;
     Axy += w * b.Axy;
     Axz += w * b.Axz;
     Ayy += w * b.Ayy;
     Ayz += w * b.Ayz;
     Azz += w * b.Azz;
     bx  += w * b.bx;
     by  += w * b.by;
     bz  += w * b.bz;
     c   += w * b.c;
 }
예제 #7
0
 public QuadricError(ref QuadricError a, ref QuadricError b)
 {
     Axx = a.Axx + b.Axx;
     Axy = a.Axy + b.Axy;
     Axz = a.Axz + b.Axz;
     Ayy = a.Ayy + b.Ayy;
     Ayz = a.Ayz + b.Ayz;
     Azz = a.Azz + b.Azz;
     bx  = a.bx + b.bx;
     by  = a.by + b.by;
     bz  = a.bz + b.bz;
     c   = a.c + b.c;
 }
예제 #8
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);
         }
     }
 }
예제 #9
0
        protected virtual void InitializeVertexQuadrics()
        {
            int NT          = mesh.MaxTriangleID;
            var triQuadrics = new QuadricError[NT];

            double[] triAreas = new double[NT];
            gParallel.BlockStartEnd(0, mesh.MaxTriangleID - 1, (start_tid, end_tid) =>
            {
                Vector3d c, n;
                for (int tid = start_tid; tid <= end_tid; tid++)
                {
                    if (mesh.IsTriangle(tid))
                    {
                        mesh.GetTriInfo(tid, out n, out triAreas[tid], out c);
                        triQuadrics[tid] = new QuadricError(ref n, ref c);
                    }
                }
            });


            int NV = mesh.MaxVertexID;

            vertQuadrics = new QuadricError[NV];
            gParallel.BlockStartEnd(0, mesh.MaxVertexID - 1, (start_vid, end_vid) =>
            {
                for (int vid = start_vid; vid <= end_vid; vid++)
                {
                    vertQuadrics[vid] = QuadricError.Zero;
                    if (mesh.IsVertex(vid))
                    {
                        foreach (int tid in mesh.VtxTrianglesItr(vid))
                        {
                            vertQuadrics[vid].Add(triAreas[tid], ref triQuadrics[tid]);
                        }
                        //Util.gDevAssert(MathUtil.EpsilonEqual(0, vertQuadrics[i].Evaluate(mesh.GetVertex(i)), MathUtil.Epsilon * 10));
                    }
                }
            });
        }
예제 #10
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);
         }
     }
 }
예제 #11
0
 public QEdge(int edge_id, ref QuadricError qin, ref Vector3d pt)
 {
     eid         = edge_id;
     q           = qin;
     collapse_pt = pt;
 }
예제 #12
0
 public void Initialize(int edge_id, QuadricError qin, Vector3d pt)
 {
     eid         = edge_id;
     q           = qin;
     collapse_pt = pt;
 }
예제 #13
0
 public QEdge(int edge_id, QuadricError qin, Vector3d pt)
 {
     Initialize(edge_id, qin, pt);
 }