Пример #1
0
        static void Swap(ref MeshUtils.Vertex a, ref MeshUtils.Vertex b)
        {
            var tmp = a;

            a = b;
            b = tmp;
        }
Пример #2
0
        public void Check()
        {
            MeshUtils.Edge e;

            MeshUtils.Face fPrev = _fHead, f;
            for (fPrev = _fHead; (f = fPrev._next) != _fHead; fPrev = f)
            {
                e = f._anEdge;
                do
                {
                    Debug.Assert(e._Sym != e);
                    Debug.Assert(e._Sym._Sym == e);
                    Debug.Assert(e._Lnext._Onext._Sym == e);
                    Debug.Assert(e._Onext._Sym._Lnext == e);
                    Debug.Assert(e._Lface == f);
                    e = e._Lnext;
                } while (e != f._anEdge);
            }
            Debug.Assert(f._prev == fPrev && f._anEdge == null);

            MeshUtils.Vertex vPrev = _vHead, v;
            for (vPrev = _vHead; (v = vPrev._next) != _vHead; vPrev = v)
            {
                Debug.Assert(v._prev == vPrev);
                e = v._anEdge;
                do
                {
                    Debug.Assert(e._Sym != e);
                    Debug.Assert(e._Sym._Sym == e);
                    Debug.Assert(e._Lnext._Onext._Sym == e);
                    Debug.Assert(e._Onext._Sym._Lnext == e);
                    Debug.Assert(e._Org == v);
                    e = e._Onext;
                } while (e != v._anEdge);
            }
            Debug.Assert(v._prev == vPrev && v._anEdge == null);

            MeshUtils.Edge ePrev = _eHead;
            for (ePrev = _eHead; (e = ePrev._next) != _eHead; ePrev = e)
            {
                Debug.Assert(e._Sym._next == ePrev._Sym);
                Debug.Assert(e._Sym != e);
                Debug.Assert(e._Sym._Sym == e);
                Debug.Assert(e._Org != null);
                Debug.Assert(e._Dst != null);
                Debug.Assert(e._Lnext._Onext._Sym == e);
                Debug.Assert(e._Onext._Sym._Lnext == e);
            }
            Debug.Assert(e._Sym._next == ePrev._Sym &&
                         e._Sym == _eHeadSym &&
                         e._Sym._Sym == e &&
                         e._Org == null && e._Dst == null &&
                         e._Lface == null && e._Rface == null);
        }
Пример #3
0
        public static Real TransSign(MeshUtils.Vertex u, MeshUtils.Vertex v, MeshUtils.Vertex w)
        {
            Debug.Assert(TransLeq(u, v) && TransLeq(v, w));

            var gapL = v._t - u._t;
            var gapR = w._t - v._t;

            if (gapL + gapR > 0.0f)
            {
                return((v._s - w._s) * gapL + (v._s - u._s) * gapR);
            }
            /* vertical line */
            return(0);
        }
Пример #4
0
        /// <summary>
        /// Returns a number whose sign matches EdgeEval(u,v,w) but which
        /// is cheaper to evaluate. Returns > 0, == 0 , or < 0
        /// as v is above, on, or below the edge uw.
        /// </summary>
        public static Real EdgeSign(MeshUtils.Vertex u, MeshUtils.Vertex v, MeshUtils.Vertex w)
        {
            Debug.Assert(VertLeq(u, v) && VertLeq(v, w));

            var gapL = v._s - u._s;
            var gapR = w._s - v._s;

            if (gapL + gapR > 0.0f)
            {
                return((v._t - w._t) * gapL + (v._t - u._t) * gapR);
            }
            /* vertical line */
            return(0);
        }
Пример #5
0
        /// <summary>
        /// Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w),
        /// evaluates the t-coord of the edge uw at the s-coord of the vertex v.
        /// Returns v->t - (uw)(v->s), ie. the signed distance from uw to v.
        /// If uw is vertical (and thus passes thru v), the result is zero.
        ///
        /// The calculation is extremely accurate and stable, even when v
        /// is very close to u or w.  In particular if we set v->t = 0 and
        /// let r be the negated result (this evaluates (uw)(v->s)), then
        /// r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t).
        /// </summary>
        public static Real EdgeEval(MeshUtils.Vertex u, MeshUtils.Vertex v, MeshUtils.Vertex w)
        {
            Debug.Assert(VertLeq(u, v) && VertLeq(v, w));

            var gapL = v._s - u._s;
            var gapR = w._s - v._s;

            if (gapL + gapR > 0.0f)
            {
                if (gapL < gapR)
                {
                    return((v._t - u._t) + (u._t - w._t) * (gapL / (gapL + gapR)));
                }
                else
                {
                    return((v._t - w._t) + (w._t - u._t) * (gapR / (gapL + gapR)));
                }
            }
            /* vertical line */
            return(0);
        }
Пример #6
0
        public void Reset(IPool pool)
        {
            for (MeshUtils.Face f = _fHead, fNext = _fHead; f._next != null; f = fNext)
            {
                fNext = f._next;
                pool.Return(f);
            }
            for (MeshUtils.Vertex v = _vHead, vNext = _vHead; v._next != null; v = vNext)
            {
                vNext = v._next;
                pool.Return(v);
            }
            for (MeshUtils.Edge e = _eHead, eNext = _eHead; e._next != null; e = eNext)
            {
                eNext = e._next;
                pool.Return(e._Sym);
                pool.Return(e);
            }

            _vHead = null;
            _fHead = null;
            _eHead = _eHeadSym = null;
        }
Пример #7
0
        public void Init(IPool pool)
        {
            var v = _vHead = pool.Get <MeshUtils.Vertex>();
            var f = _fHead = pool.Get <MeshUtils.Face>();

            var pair = MeshUtils.EdgePair.Create(pool);
            var e    = _eHead = pair._e;
            var eSym = _eHeadSym = pair._eSym;

            v._next   = v._prev = v;
            v._anEdge = null;

            f._next   = f._prev = f;
            f._anEdge = null;
            f._trail  = null;
            f._marked = false;
            f._inside = false;

            e._next         = e;
            e._Sym          = eSym;
            e._Onext        = null;
            e._Lnext        = null;
            e._Org          = null;
            e._Lface        = null;
            e._winding      = 0;
            e._activeRegion = null;

            eSym._next         = eSym;
            eSym._Sym          = e;
            eSym._Onext        = null;
            eSym._Lnext        = null;
            eSym._Org          = null;
            eSym._Lface        = null;
            eSym._winding      = 0;
            eSym._activeRegion = null;
        }
Пример #8
0
 public static bool VertLeq(MeshUtils.Vertex lhs, MeshUtils.Vertex rhs)
 {
     return((lhs._s < rhs._s) || (lhs._s == rhs._s && lhs._t <= rhs._t));
 }
Пример #9
0
 public static bool VertEq(MeshUtils.Vertex lhs, MeshUtils.Vertex rhs)
 {
     return(lhs._s == rhs._s && lhs._t == rhs._t);
 }
Пример #10
0
 public static bool VertCCW(MeshUtils.Vertex u, MeshUtils.Vertex v, MeshUtils.Vertex w)
 {
     return((u._s * (v._t - w._t) + v._s * (w._t - u._t) + w._s * (u._t - v._t)) >= 0.0f);
 }
Пример #11
0
        /// <summary>
        /// Given edges (o1,d1) and (o2,d2), compute their point of intersection.
        /// The computed point is guaranteed to lie in the intersection of the
        /// bounding rectangles defined by each edge.
        /// </summary>
        public static void EdgeIntersect(MeshUtils.Vertex o1, MeshUtils.Vertex d1, MeshUtils.Vertex o2, MeshUtils.Vertex d2, MeshUtils.Vertex v)
        {
            // This is certainly not the most efficient way to find the intersection
            // of two line segments, but it is very numerically stable.
            //
            // Strategy: find the two middle vertices in the VertLeq ordering,
            // and interpolate the intersection s-value from these.  Then repeat
            // using the TransLeq ordering to find the intersection t-value.

            if (!VertLeq(o1, d1))
            {
                Swap(ref o1, ref d1);
            }
            if (!VertLeq(o2, d2))
            {
                Swap(ref o2, ref d2);
            }
            if (!VertLeq(o1, o2))
            {
                Swap(ref o1, ref o2); Swap(ref d1, ref d2);
            }

            if (!VertLeq(o2, d1))
            {
                // Technically, no intersection -- do our best
                v._s = (o2._s + d1._s) / 2.0f;
            }
            else if (VertLeq(d1, d2))
            {
                // Interpolate between o2 and d1
                var z1 = EdgeEval(o1, o2, d1);
                var z2 = EdgeEval(o2, d1, d2);
                if (z1 + z2 < 0.0f)
                {
                    z1 = -z1;
                    z2 = -z2;
                }
                v._s = Interpolate(z1, o2._s, z2, d1._s);
            }
            else
            {
                // Interpolate between o2 and d2
                var z1 = EdgeSign(o1, o2, d1);
                var z2 = -EdgeSign(o1, d2, d1);
                if (z1 + z2 < 0.0f)
                {
                    z1 = -z1;
                    z2 = -z2;
                }
                v._s = Interpolate(z1, o2._s, z2, d2._s);
            }

            // Now repeat the process for t

            if (!TransLeq(o1, d1))
            {
                Swap(ref o1, ref d1);
            }
            if (!TransLeq(o2, d2))
            {
                Swap(ref o2, ref d2);
            }
            if (!TransLeq(o1, o2))
            {
                Swap(ref o1, ref o2); Swap(ref d1, ref d2);
            }

            if (!TransLeq(o2, d1))
            {
                // Technically, no intersection -- do our best
                v._t = (o2._t + d1._t) / 2.0f;
            }
            else if (TransLeq(d1, d2))
            {
                // Interpolate between o2 and d1
                var z1 = TransEval(o1, o2, d1);
                var z2 = TransEval(o2, d1, d2);
                if (z1 + z2 < 0.0f)
                {
                    z1 = -z1;
                    z2 = -z2;
                }
                v._t = Interpolate(z1, o2._t, z2, d1._t);
            }
            else
            {
                // Interpolate between o2 and d2
                var z1 = TransSign(o1, o2, d1);
                var z2 = -TransSign(o1, d2, d1);
                if (z1 + z2 < 0.0f)
                {
                    z1 = -z1;
                    z2 = -z2;
                }
                v._t = Interpolate(z1, o2._t, z2, d2._t);
            }
        }
Пример #12
0
 public static Real VertL1dist(MeshUtils.Vertex u, MeshUtils.Vertex v)
 {
     return(Math.Abs(u._s - v._s) + Math.Abs(u._t - v._t));
 }
Пример #13
0
 public static bool TransLeq(MeshUtils.Vertex lhs, MeshUtils.Vertex rhs)
 {
     return((lhs._t < rhs._t) || (lhs._t == rhs._t && lhs._s <= rhs._s));
 }
Пример #14
0
        private void ComputeNormal(ref Vec3 norm)
        {
            var v = _mesh._vHead._next;

            var minVal = new Real[3] {
                v._coords.X, v._coords.Y, v._coords.Z
            };
            var minVert = new MeshUtils.Vertex[3] {
                v, v, v
            };
            var maxVal = new Real[3] {
                v._coords.X, v._coords.Y, v._coords.Z
            };
            var maxVert = new MeshUtils.Vertex[3] {
                v, v, v
            };

            for (; v != _mesh._vHead; v = v._next)
            {
                if (v._coords.X < minVal[0])
                {
                    minVal[0] = v._coords.X; minVert[0] = v;
                }
                if (v._coords.Y < minVal[1])
                {
                    minVal[1] = v._coords.Y; minVert[1] = v;
                }
                if (v._coords.Z < minVal[2])
                {
                    minVal[2] = v._coords.Z; minVert[2] = v;
                }
                if (v._coords.X > maxVal[0])
                {
                    maxVal[0] = v._coords.X; maxVert[0] = v;
                }
                if (v._coords.Y > maxVal[1])
                {
                    maxVal[1] = v._coords.Y; maxVert[1] = v;
                }
                if (v._coords.Z > maxVal[2])
                {
                    maxVal[2] = v._coords.Z; maxVert[2] = v;
                }
            }

            // Find two vertices separated by at least 1/sqrt(3) of the maximum
            // distance between any two vertices
            int i = 0;

            if (maxVal[1] - minVal[1] > maxVal[0] - minVal[0])
            {
                i = 1;
            }
            if (maxVal[2] - minVal[2] > maxVal[i] - minVal[i])
            {
                i = 2;
            }
            if (minVal[i] >= maxVal[i])
            {
                // All vertices are the same -- normal doesn't matter
                norm = new Vec3 {
                    X = 0, Y = 0, Z = 1
                };
                return;
            }

            // Look for a third vertex which forms the triangle with maximum area
            // (Length of normal == twice the triangle area)
            Real maxLen2 = 0, tLen2;
            var  v1 = minVert[i];
            var  v2 = maxVert[i];
            Vec3 d1, d2, tNorm;

            Vec3.Sub(ref v1._coords, ref v2._coords, out d1);
            for (v = _mesh._vHead._next; v != _mesh._vHead; v = v._next)
            {
                Vec3.Sub(ref v._coords, ref v2._coords, out d2);
                tNorm.X = d1.Y * d2.Z - d1.Z * d2.Y;
                tNorm.Y = d1.Z * d2.X - d1.X * d2.Z;
                tNorm.Z = d1.X * d2.Y - d1.Y * d2.X;
                tLen2   = tNorm.X * tNorm.X + tNorm.Y * tNorm.Y + tNorm.Z * tNorm.Z;
                if (tLen2 > maxLen2)
                {
                    maxLen2 = tLen2;
                    norm    = tNorm;
                }
            }

            if (maxLen2 <= 0.0f)
            {
                // All points lie on a single line -- any decent normal will do
                norm    = Vec3.Zero;
                i       = Vec3.LongAxis(ref d1);
                norm[i] = 1;
            }
        }