Esempio n. 1
0
        // ---------------------------
        // Intersection point of edge
        // ---------------------------
        public Vector3 Intersection(Vector3 p0, Vector3 p1)
        {
            // to avoid rounding errors, always make sure float calculations are done in this order
            if (IsAbove(p0))
            {
                Vector3 tmp = p0;
                p0 = p1;
                p1 = tmp;
            }
            else if (!IsAbove(p1))
            {
                Debug.LogException(MeshUtilsException.Internal("both below"));
            }

            if (IsAbove(p0))
            {
                Debug.LogException(MeshUtilsException.Internal("both above"));
            }

            float dist0 = Distance(p0);
            float dist1 = Distance(p1);

            float factor = dist0 / (dist0 + dist1);

            return(p0 + (p1 - p0) * factor);
        }
Esempio n. 2
0
        public static void GenIntersection(
            CuttingPlane plane,
            Vector3 a, Vector3 b, Vector3 c,
            RingGenerator rings
            )
        {
            // find intersection vertices
            Vector3 e = plane.Intersection(a, c, Vector2.zero, Vector2.zero, 0).Item1,
                    d = plane.Intersection(b, c, Vector2.zero, Vector2.zero, 0).Item1;

            // if e == d, the three vertices lie in a line,
            //   and thus do not make up a triangle
            if (e == d)
            {
                return;

                // not sure if this is nescessary
                throw MeshUtilsException.ZeroAreaTriangle();
            }

            // find proper direction for ring
            Vector3 tri_nor = Vector3.Cross(c - a, c - b);
            bool    dir     = Vector3.Dot(e - d, Vector3.Cross(plane.normal, tri_nor)) > 0;

            // add connected pair in ring generator
            rings.AddConnected(dir?e:d, dir?d:e);
        }
Esempio n. 3
0
 // ------------------------------------------------------
 // Create a unit vector perpendicular to a given vector
 // Exact direction is obviously unknown
 // ------------------------------------------------------
 public static Vector3 UnitPerpendicular(Vector3 v)
 {
     if (v == Vector3.zero)
     {
         throw MeshUtilsException.ZeroNormal();
     }
     return(new Vector3(v.y - v.z, v.z - v.x, v.x - v.y).normalized);
 }
Esempio n. 4
0
        public Vector3 DirectionalProject(Vector3 v, Vector3 dir)
        {
            float t = -(Vector3.Dot(v, normal) + d) / Vector3.Dot(dir, normal);

            if (float.IsInfinity(t) || float.IsNaN(t))
            {
                throw MeshUtilsException.Internal("Directional projection failed: t=" + t + " v=" + v + " n=" + normal + " d=" + d + " dir=" + dir);
            }
            return(v + dir * t);
        }
Esempio n. 5
0
 public MUPlane(Vector3 normal, Vector3 pointInPlane)
 {
     if (normal == Vector3.zero)
     {
         throw MeshUtilsException.Internal("Zero normal");
     }
     this.pointInPlane = pointInPlane;
     this.normal       = normal.normalized;
     this.d            = -Vector3.Dot(pointInPlane, this.normal);
 }
Esempio n. 6
0
 private void AssertMatchingCounts()
 {
     if (uvs.Count > 0 && uvs.Count != vertices.Count)
     {
         throw MeshUtilsException.Internal("UV/vertex count mismatch (" + uvs.Count + " uvs, " + vertices.Count + " verts)");
     }
     if (normals.Count > 0 && normals.Count != vertices.Count)
     {
         throw MeshUtilsException.Internal("Normal/vertex count mismatch (" + normals.Count + " normals, " + vertices.Count + " verts)");
     }
 }
Esempio n. 7
0
        public List <Ring> GetRings(bool selfConnectPartials, bool ignorePartials)
        {
            List <Ring> res = this.complete.ConvertAll(r => new Ring(r));

            if (selfConnectPartials)
            {
                foreach (List <Vector3> p in partials)
                {
                    if (p.Count < 3)
                    {
                        continue;
                    }
                    res.Add(new Ring(p));
                }
            }
            if (!ignorePartials && !selfConnectPartials && this.partials.Count > 0)
            {
                throw MeshUtilsException.MalformedMesh("Incomplete intersections found");
            }
            return(res);
        }
Esempio n. 8
0
            // ------------------------
            // Connect rings in strip
            // ------------------------
            public void TemplateJoin(CuttingTemplate template, SortedDictionary <float, Vector3> map)
            {
                if (map.Count == 0)
                {
                    return;
                }
                if (map.Count % 2 == 1)
                {
                    throw MeshUtilsException.Internal("Odd strip entry/exit count");
                }
                bool    first_is_entry = false;
                Vector3 first_vec      = map.First().Value;

                foreach (List <Vector3> part in partials)
                {
                    if (part[0] != first_vec)
                    {
                        continue;
                    }
                    first_is_entry = true;
                    break;
                }
                var x = map.Values.GetEnumerator();

                for (int i = 0; i < map.Count; i += 2)
                {
                    if (!x.MoveNext())
                    {
                        throw MeshUtilsException.Internal("Enumerator exhausted");
                    }
                    Vector3 a = x.Current;
                    if (!x.MoveNext())
                    {
                        throw MeshUtilsException.Internal("Enumerator exhausted");
                    }
                    Vector3 b = x.Current;
                    AddConnected(first_is_entry?b:a, first_is_entry?a:b);
                }
            }
Esempio n. 9
0
        private static bool ProcessTriangle(
            CuttingTemplate template,
            Vector3 a, Vector3 b, Vector3 c,
            Dictionary <Vector3, Tuple <SortedDictionary <float, Vector3>, RingGen> > point_data,
            MeshPart pos, MeshPart neg,
            RingGenerator intersection_ring,
            IvSaver ivSaver,
            bool addNormals
            )
        {
            List <Vector3> points    = template.points;
            Vector3        normal    = template.normal;
            RingGenerator  tri_rings = new RingGenerator();
            Vector3        tri_nor   = -Vector3.Cross(c - a, c - b).normalized;

            if (tri_nor == Vector3.zero)
            {
                // Debug.LogWarning("zero area tri");
                return(true);
            }
            bool    partToUse = Vector3.Dot(tri_nor, normal) > 0;
            bool    ring_dir  = partToUse;
            MUPlane tri_plane = new MUPlane(tri_nor, a);
            Vector3 ab_nor    = Vector3.Cross(tri_nor, (b - a).normalized), // vector perpendicular to edge and pointing away from triangle
                    bc_nor    = Vector3.Cross(tri_nor, (c - b).normalized),
                    ca_nor    = Vector3.Cross(tri_nor, (a - c).normalized);

        #if EPSILON_TEST
            if (Math.Abs(Vector3.Dot(tri_nor, normal)) < 0.01f)
            {
                Debug.LogWarning("epsilon ignore");
                return(false);
            }
        #endif
            // Debug.Log("tri verts: "+a+" "+b+" "+c);
            // Debug.Log((b-a).magnitude+" "+(c-b).magnitude+" "+(a-c).magnitude);
            // Debug.Log("edge norms: "+ab_nor+" "+bc_nor+" "+ca_nor);
            Dictionary <float, Vector3> map_ab = new Dictionary <float, Vector3>(), // distance (from first vertex in edge) -> vertex in edge
                                        map_bc = new Dictionary <float, Vector3>(), // used for sorting... TODO: change to SortedDictionary
                                        map_ca = new Dictionary <float, Vector3>();
            HashSet <Vector3> exiting_ivs      = new HashSet <Vector3>();
            MUPlane           ab = new MUPlane(ab_nor, a), // planes passing through edges, perpendicular to triangle
                              bc = new MUPlane(bc_nor, b),
                              ca = new MUPlane(ca_nor, c);
            // Debug.Log("tri: "+tri_plane+" "+normal);
            //Debugging.DebugRing(points);
            Vector3 opi, old_point;
            bool    oaab, oabc, oaca;
            SortedDictionary <float, Vector3> dist_map_old;
            RingGen strip_rings;
            if (template.isClosed)
            {
                opi          = tri_plane.DirectionalProject(points.Last(), normal);
                old_point    = points.Last();
                oaab         = ab.IsAbove(opi);
                oabc         = bc.IsAbove(opi);
                oaca         = ca.IsAbove(opi);
                dist_map_old = point_data[points.Last()].Item1;
                strip_rings  = point_data[points.Last()].Item2;
            }
            else
            {
                opi          = tri_plane.DirectionalProject(points.First(), normal);
                old_point    = points.First();
                oaab         = ab.IsAbove(opi);
                oabc         = bc.IsAbove(opi);
                oaca         = ca.IsAbove(opi);
                dist_map_old = point_data[points.First()].Item1;
                strip_rings  = point_data[points.First()].Item2;
            }
            bool oldInside = !(oaab || oabc || oaca);
            for (int i = template.isClosed ? 0 : 1; i < points.Count; i++)
            {
                Vector3 cur_point = points[i];
                SortedDictionary <float, Vector3> dist_map = point_data[cur_point].Item1;
                Vector3 pi = tri_plane.DirectionalProject(cur_point, normal);
                // Debug.Log(opi+" => "+pi);
                bool aab    = ab.IsAbove(pi), // above means outside edge
                     abc    = bc.IsAbove(pi),
                     aca    = ca.IsAbove(pi);
                bool inside = !(aab || abc || aca);
                // Debug.Log(aab+" "+abc+" "+aca+" | "+oaab+" "+oabc+" "+oaca);
                if (inside != oldInside)
                {
                    // Debug.Log("EDGE PAIR: "+a+" "+b+" "+c+" pi-opi: "+pi+" "+opi+" hc: "+pi.GetHashCode()+" "+opi.GetHashCode());
                    // add edge pair
                    MUPlane edge_plane;
                    Dictionary <float, Vector3> map;
                    Vector3 ep1, ep2, iv;
                    if (inside)
                    {
                        if (oaab)
                        {
                            edge_plane = ab; map = map_ab; ep1 = a; ep2 = b;
                            iv         = ivSaver.Intersect(edge_plane, ep1, ep2, opi, pi, old_point, cur_point);
                            if (Vector3.Dot(ep1 - iv, ep2 - iv) < 0)
                            {
                                goto connect;
                            }
                        }
                        if (oabc)
                        {
                            edge_plane = bc; map = map_bc; ep1 = b; ep2 = c;
                            iv         = ivSaver.Intersect(edge_plane, ep1, ep2, opi, pi, old_point, cur_point);
                            if (Vector3.Dot(ep1 - iv, ep2 - iv) < 0)
                            {
                                goto connect;
                            }
                        }
                        if (oaca)
                        {
                            edge_plane = ca; map = map_ca; ep1 = c; ep2 = a;
                            iv         = ivSaver.Intersect(edge_plane, ep1, ep2, opi, pi, old_point, cur_point);
                            if (Vector3.Dot(ep1 - iv, ep2 - iv) < 0)
                            {
                                goto connect;
                            }
                        }
                        throw MeshUtilsException.Internal("Point on neither side of triangle");
connect:
                        // Debug.Log("EDGE PAIR: "+iv+" "+pi+" hc: "+iv.GetHashCode()+" "+pi.GetHashCode());
                        float dist_key = template.plane.SignedDistance(pi);
                        if (!dist_map.ContainsKey(dist_key))
                        {
                            dist_map.Add(dist_key, pi);
                        }
                        map.Add((ep1 - iv).magnitude, iv);
                        strip_rings.AddConnected(ring_dir?iv:pi, ring_dir?pi:iv);
                        intersection_ring.AddConnected(ring_dir?iv:pi, ring_dir?pi:iv);
                        tri_rings.AddConnected(iv, pi);
                    }
                    else
                    {
                        // Debug.Log(a+" "+b+" "+c+" "+template_plane);
                        // Debug.Log(pa+" "+pb+" "+pc+" "+points[i-1]+" "+points[i]);
                        if (aab)
                        {
                            edge_plane = ab; map = map_ab; ep1 = a; ep2 = b;
                            iv         = ivSaver.Intersect(edge_plane, ep1, ep2, opi, pi, old_point, cur_point);
                            if (Vector3.Dot(ep1 - iv, ep2 - iv) < 0)
                            {
                                goto connect;
                            }
                        }
                        if (abc)
                        {
                            edge_plane = bc; map = map_bc; ep1 = b; ep2 = c;
                            iv         = ivSaver.Intersect(edge_plane, ep1, ep2, opi, pi, old_point, cur_point);
                            if (Vector3.Dot(ep1 - iv, ep2 - iv) < 0)
                            {
                                goto connect;
                            }
                        }
                        if (aca)
                        {
                            edge_plane = ca; map = map_ca; ep1 = c; ep2 = a;
                            iv         = ivSaver.Intersect(edge_plane, ep1, ep2, opi, pi, old_point, cur_point);
                            if (Vector3.Dot(ep1 - iv, ep2 - iv) < 0)
                            {
                                goto connect;
                            }
                        }
                        throw MeshUtilsException.Internal("Point on neither side of triangle");
connect:
                        // Debug.Log("EDGE PAIR: "+iv+" "+opi+" hc: "+iv.GetHashCode()+" "+opi.GetHashCode());
                        float dist_key = template.plane.SignedDistance(opi);
                        if (!dist_map_old.ContainsKey(dist_key))
                        {
                            dist_map_old.Add(dist_key, opi);
                        }
                        map.Add((ep1 - iv).magnitude, iv);
                        strip_rings.AddConnected(ring_dir?opi:iv, ring_dir?iv:opi);
                        intersection_ring.AddConnected(ring_dir?opi:iv, ring_dir?iv:opi);
                        tri_rings.AddConnected(opi, iv);
                        exiting_ivs.Add(iv);
                    }
                }
                else if (inside)
                {
                    // add inner pair
                    // Debug.Log("INNER PAIR: "+a+" "+b+" "+c+" pi-opi: "+pi+" "+opi+" hc: "+pi.GetHashCode()+" "+opi.GetHashCode());
                    // Debug.Log("INNER PAIR: "+pi+" "+opi+" hc: "+pi.GetHashCode()+" "+opi.GetHashCode());
                    strip_rings.AddConnected(ring_dir?opi:pi, ring_dir?pi:opi);
                    intersection_ring.AddConnected(ring_dir?opi:pi, ring_dir?pi:opi);
                    tri_rings.AddConnected(opi, pi);
                    float dist_key = template.plane.SignedDistance(pi);
                    if (!dist_map.ContainsKey(dist_key))
                    {
                        dist_map.Add(dist_key, pi);
                    }
                    dist_key = template.plane.SignedDistance(opi);
                    if (!dist_map_old.ContainsKey(dist_key))
                    {
                        dist_map_old.Add(dist_key, opi);
                    }
                }
                else
                {
                    // add outer pair
                    if ( // test to check if edge does not cross triangle
                        (aab && oaab) ||
                        (abc && oabc) ||
                        (aca && oaca)
                        )
                    {
                        goto continue_for;
                    }
                    // crosses triangle
                    if (!aab && !oaab)   // not ab
                    {
                        Vector3 iv0 = ivSaver.Intersect(bc, b, c, opi, pi, old_point, cur_point),
                                iv1 = ivSaver.Intersect(ca, c, a, opi, pi, old_point, cur_point);
                        if (
                            Vector3.Dot(b - iv0, c - iv0) > 0 ||
                            Vector3.Dot(c - iv1, a - iv1) > 0
                            )
                        {
                            goto continue_for;
                        }
                        // Debug.Log("OUTER PAIR: "+iv0+" "+iv1+" hc: "+iv0.GetHashCode()+" "+iv1.GetHashCode());
                        map_bc.Add((b - iv0).magnitude, iv0);
                        map_ca.Add((c - iv1).magnitude, iv1);
                        bool iv0_first = (iv0 - opi).magnitude < (iv1 - opi).magnitude;
                        exiting_ivs.Add(iv0_first?iv1:iv0);
                        tri_rings.AddConnected(iv0_first?iv0:iv1, iv0_first?iv1:iv0);
                        strip_rings.AddConnected((!ring_dir ^ iv0_first)?iv0:iv1, (!ring_dir ^ iv0_first)?iv1:iv0);
                        intersection_ring.AddConnected((!ring_dir ^ iv0_first)?iv0:iv1, (!ring_dir ^ iv0_first)?iv1:iv0);
                    }
                    else if (!abc && !oabc)     // not bc
                    {
                        Vector3 iv0 = ivSaver.Intersect(ca, c, a, opi, pi, old_point, cur_point),
                                iv1 = ivSaver.Intersect(ab, a, b, opi, pi, old_point, cur_point);
                        if (
                            Vector3.Dot(c - iv0, a - iv0) > 0 ||
                            Vector3.Dot(a - iv1, b - iv1) > 0
                            )
                        {
                            goto continue_for;
                        }
                        // Debug.Log("OUTER PAIR: "+iv0+" "+iv1+" hc: "+iv0.GetHashCode()+" "+iv1.GetHashCode());
                        map_ca.Add((c - iv0).magnitude, iv0);
                        map_ab.Add((a - iv1).magnitude, iv1);
                        bool iv0_first = (iv0 - opi).magnitude < (iv1 - opi).magnitude;
                        exiting_ivs.Add(iv0_first?iv1:iv0);
                        tri_rings.AddConnected(iv0_first?iv0:iv1, iv0_first?iv1:iv0);
                        strip_rings.AddConnected((!ring_dir ^ iv0_first)?iv0:iv1, (!ring_dir ^ iv0_first)?iv1:iv0);
                        intersection_ring.AddConnected((!ring_dir ^ iv0_first)?iv0:iv1, (!ring_dir ^ iv0_first)?iv1:iv0);
                    }
                    else if (!aca && !oaca)     // not ca
                    {
                        Vector3 iv0 = ivSaver.Intersect(ab, a, b, opi, pi, old_point, cur_point),
                                iv1 = ivSaver.Intersect(bc, b, c, opi, pi, old_point, cur_point);
                        if (
                            Vector3.Dot(a - iv0, b - iv0) > 0 ||
                            Vector3.Dot(b - iv1, c - iv1) > 0
                            )
                        {
                            goto continue_for;
                        }
                        // Debug.Log("OUTER PAIR: "+iv0+" "+iv1+" hc: "+iv0.GetHashCode()+" "+iv1.GetHashCode());
                        map_ab.Add((a - iv0).magnitude, iv0);
                        map_bc.Add((b - iv1).magnitude, iv1);
                        bool iv0_first = (iv0 - opi).magnitude < (iv1 - opi).magnitude;
                        exiting_ivs.Add(iv0_first?iv1:iv0);
                        tri_rings.AddConnected(iv0_first?iv0:iv1, iv0_first?iv1:iv0);
                        strip_rings.AddConnected((!ring_dir ^ iv0_first)?iv0:iv1, (!ring_dir ^ iv0_first)?iv1:iv0);
                        intersection_ring.AddConnected((!ring_dir ^ iv0_first)?iv0:iv1, (!ring_dir ^ iv0_first)?iv1:iv0);
                    }
                    else     // opposite sides
                    {
                        MUPlane edge_plane, edge_plane1;
                        Dictionary <float, Vector3> map, map1;
                        Vector3 iv, iv1; // iv is entry, must be one side; iv1 is exit, can be either two other sides
                        float   iv_mag, iv1_mag;
                        bool    swap_ring_dir = false;

                        if (aab && !abc && !aca || oaab && !oabc && !oaca)
                        {
                            // Debug.Log("1 swap "+oaab);
                            if (oaab)
                            {
                                swap_ring_dir = true;
                            }
                            edge_plane = ab;
                            map        = map_ab;
                            iv         = ivSaver.Intersect(ab, a, b, opi, pi, old_point, cur_point);
                            iv_mag     = (a - iv).magnitude;
                            if (Vector3.Dot(a - iv, b - iv) > 0)
                            {
                                goto continue_for;
                            }
                            iv1 = ivSaver.Intersect(bc, b, c, opi, pi, old_point, cur_point);
                            if (Vector3.Dot(b - iv1, c - iv1) > 0)
                            {
                                iv1         = ivSaver.Intersect(ca, c, a, opi, pi, old_point, cur_point);
                                iv1_mag     = (c - iv1).magnitude;
                                edge_plane1 = ca;
                                map1        = map_ca;
                            }
                            else
                            {
                                iv1_mag     = (b - iv1).magnitude;
                                edge_plane1 = bc;
                                map1        = map_bc;
                            }
                            goto connect_opposite;
                        }
                        else if (!aab && abc && !aca || !oaab && oabc && !oaca)
                        {
                            // Debug.Log("2 swap "+oabc);
                            if (oabc)
                            {
                                swap_ring_dir = true;
                            }
                            edge_plane = bc;
                            map        = map_bc;
                            iv         = ivSaver.Intersect(bc, b, c, opi, pi, old_point, cur_point);
                            iv_mag     = (b - iv).magnitude;
                            if (Vector3.Dot(b - iv, c - iv) > 0)
                            {
                                goto continue_for;
                            }
                            iv1 = ivSaver.Intersect(ca, c, a, opi, pi, old_point, cur_point);
                            if (Vector3.Dot(c - iv1, a - iv1) > 0)
                            {
                                iv1         = ivSaver.Intersect(ab, a, b, opi, pi, old_point, cur_point);
                                iv1_mag     = (a - iv1).magnitude;
                                edge_plane1 = ab;
                                map1        = map_ab;
                            }
                            else
                            {
                                iv1_mag     = (c - iv1).magnitude;
                                edge_plane1 = ca;
                                map1        = map_ca;
                            }
                            goto connect_opposite;
                        }
                        else if (!aab && !abc && aca || !oaab && !oabc && oaca)
                        {
                            // Debug.Log("3 swap "+oaca);
                            if (oaca)
                            {
                                swap_ring_dir = true;
                            }
                            edge_plane = ca;
                            map        = map_ca;
                            iv         = ivSaver.Intersect(ca, c, a, opi, pi, old_point, cur_point);
                            iv_mag     = (c - iv).magnitude;
                            if (Vector3.Dot(c - iv, a - iv) > 0)
                            {
                                goto continue_for;
                            }
                            iv1 = ivSaver.Intersect(ab, a, b, opi, pi, old_point, cur_point);
                            if (Vector3.Dot(a - iv1, b - iv1) > 0)
                            {
                                iv1         = ivSaver.Intersect(bc, b, c, opi, pi, old_point, cur_point);
                                iv1_mag     = (b - iv1).magnitude;
                                edge_plane1 = bc;
                                map1        = map_bc;
                            }
                            else
                            {
                                iv1_mag     = (a - iv1).magnitude;
                                edge_plane1 = ab;
                                map1        = map_ab;
                            }
                            goto connect_opposite;
                        }

                        throw MeshUtilsException.Internal("Case exhaustion failed");
connect_opposite:
                        // Debug.Log("CROSS PAIR: "+iv+" "+iv1+" hc: "+iv.GetHashCode()+" "+iv1.GetHashCode());
                        // Debug.Log("yay "+opi+" "+pi+" "+a+" "+b+" "+c+" "+aab+" "+abc+" "+aca+" "+oaab+" "+oabc+" "+oaca);
                        map.Add(iv_mag, iv);
                        map1.Add(iv1_mag, iv1);
                        exiting_ivs.Add(swap_ring_dir?iv1:iv);
                        // Debug.Log("exiting is "+(swap_ring_dir?iv1:iv));
                        strip_rings.AddConnected((!ring_dir ^ swap_ring_dir)?iv:iv1, (!ring_dir ^ swap_ring_dir)?iv1:iv);
                        intersection_ring.AddConnected((!ring_dir ^ swap_ring_dir)?iv:iv1, (!ring_dir ^ swap_ring_dir)?iv1:iv);
                        tri_rings.AddConnected(swap_ring_dir?iv:iv1, swap_ring_dir?iv1:iv);
                    }
                }
continue_for:
                old_point    = cur_point;
                oldInside    = inside;
                oaab         = aab;
                oabc         = abc;
                oaca         = aca;
                opi          = pi;
                dist_map_old = dist_map;
                strip_rings  = point_data[points[i]].Item2;
            }
            if (tri_rings.HasComplete())
            {
            #if !HANDLE_CLOSED
                throw MeshUtilsException.Internal("Template closed and within triangle not handled");
            #else
                // Debug.Log("inside");
                if (tri_rings.HasPartials())
                {
                    throw MeshUtilsException.Internal("Unexpected condition");
                }
                List <Ring> ring = tri_rings.GetRings(false, false);
                if (ring.Count != 1)
                {
                    throw MeshUtilsException.Internal("Multiple rings in single triangle");
                }
                Debugging.DebugRing(ring[0].verts);
                GenerateRingMesh(ring[0].verts, partToUse?neg:pos, tri_nor, true, null, addNormals);

                var r0 = new Ring(new List <Vector3>()
                {
                    a, b, c
                });
                var r1 = ring[0];

                r1.verts.Reverse();

                // join indices
                int i0 = 0, i1 = 0;
                r0.RingDist(r1, ref i0, ref i1);

                // the inner ring should have the opposite direction
                // join by inserting r1 at i0 in r0
                List <Vector3> res = new List <Vector3>();
                res.AddRange(r0.verts.GetRange(0, i0 + 1));               // r0 from start to split
                res.AddRange(r1.verts.GetRange(i1, r1.verts.Count - i1)); // r1 from split to end
                res.AddRange(r1.verts.GetRange(0, i1 + 1));               // r1 from start to split
                res.AddRange(r0.verts.GetRange(i0, r0.verts.Count - i0)); // r0 from split to end

                // Debugging.DebugRing(res);

                GenerateRingMesh(res, partToUse?pos:neg, tri_nor, true, null, addNormals);
                return(true);
            #endif
            }
            if (!tri_rings.HasPartials())
            {
                return(false);
            }
            // Debugging.DebugRing(points.ConvertAll(p=>tri_plane.DirectionalProject(p,normal)));
            // Debug.Log("tri verts:"+a+" "+b+" "+c);
            // tri_rings.MyDebugLog();
            // Debug.Log("connecting ivs...");
            RingGenerator inv_tri_rings = tri_rings.Duplicate();                                // seperate rings needed for other MeshPart
            ConnectIVs(exiting_ivs, a, b, c, map_ab, map_ca, map_bc, tri_rings, inv_tri_rings); // connect edges around in triangle rings
            ConnectIVs(exiting_ivs, b, c, a, map_bc, map_ab, map_ca, tri_rings, inv_tri_rings); // one call per edge
            ConnectIVs(exiting_ivs, c, a, b, map_ca, map_bc, map_ab, tri_rings, inv_tri_rings);
            // Debug.Log("gen:");
            //tri_rings.MyDebugLog();
            foreach (var ring in tri_rings.GetRings(false, false))
            {
                // Debugging.DebugRing(ring.verts);
                GenerateRingMesh(ring.verts, partToUse?neg:pos, tri_nor, true, null, addNormals);
            }
            // Debug.Log("gen inv:");
            //inv_tri_rings.MyDebugLog();
            foreach (var ring in inv_tri_rings.GetRings(false, false))
            {
                //Debugging.DebugRing(ring.verts);
                ring.verts.Reverse();
                GenerateRingMesh(ring.verts, partToUse?pos:neg, tri_nor, true, null, addNormals);
            }
            //Debug.Log("--------------- END PROCESS TRIANGLE");
            return(true);
        }
Esempio n. 10
0
        public static void GenerateRingMesh(
            List <Vector3> ring, MeshPart part, Vector3 normal, bool side, Vector2?innerUV, bool addNormals = false
            )
        {
            bool addUVs = innerUV != null;

            // List<List<Vector3>> reduceHist = new List<List<Vector3>>();
            // reduceHist.Add(ring);

            int indStart = part.vertices.Count;

            part.vertices.AddRange(ring);
            if (addUVs || addNormals)
            {
                foreach (var _ in ring)
                {
                    if (addUVs)
                    {
                        part.uvs.Add(innerUV.Value);
                    }
                    if (addNormals)
                    {
                        part.normals.Add(side ? -normal : normal);
                    }
                }
            }

            List <Tuple <Vector3, int> > set = ring.ConvertAll(v => new Tuple <Vector3, int>(v, indStart++));

            int  i = -1, lsc = set.Count;
            bool didInf = false;

            while (set.Count > 1)
            {
                i++;
                if (i >= set.Count)
                {
                    if (lsc == set.Count)
                    {
                        if (didInf)
                        {
                            // Debug.LogError("ear clipping failed");
                            // DebugRings(reduceHist);
                            // Debug.Log("normal "+(normal*1000));
                            // DebugRing(set.ConvertAll(s=>s.Item1));
                            throw MeshUtilsException.Internal("Ear clipping failed");
                        }
                        didInf = true;
                    }
                    else
                    {
                        didInf = false;
                    }
                    lsc = set.Count;
                }
                i %= set.Count;

                Tuple <Vector3, int> vi0 = set[i],
                                     vi1 = set[(i + 1) % set.Count],
                                     vi2 = set[(i + 2) % set.Count];
                Vector3 d1 = vi1.Item1 - vi0.Item1; // i0 -> i1
                Vector3 d2 = vi2.Item1 - vi0.Item1; // i0 -> i2

                // we assume points do not lie in a line (see SimplifyRing)
                // if they do however, it's just a waste of vertices

                // check convex ear
                float conv = Vector3.Dot(Vector3.Cross(d1.normalized, d2.normalized), normal);
                if (conv > 0)
                {
                    continue;
                }

                // check that there are no other vertices inside this triangle
                if (set.Exists(v => {
                    // note: we must compare the vectors, otherwise coinciding vectors do not
                    // register as being the same
                    if (v.Item1 == vi0.Item1 || v.Item1 == vi1.Item1 || v.Item1 == vi2.Item1)
                    {
                        return(false);
                    }
                    return(VectorUtil.CheckIsInside(d1, d2, v.Item1 - vi0.Item1));
                }))
                {
                    continue;
                }

                // generate indices
                if (side)
                {
                    part.indices.Add(vi0.Item2);
                    part.indices.Add(vi1.Item2);
                    part.indices.Add(vi2.Item2);
                }
                else
                {
                    part.indices.Add(vi0.Item2);
                    part.indices.Add(vi2.Item2);
                    part.indices.Add(vi1.Item2);
                }

                // eliminate vertex
                set.RemoveAt((++i) % set.Count);
                i++;

                // reduceHist.Add(set.ConvertAll(s=>s.Item1));
            }
        }
Esempio n. 11
0
        public static void GenPartialTriangles(
            CuttingPlane plane,
            MeshPart part,
            Vector3 a, Vector3 b, Vector3 c,
            Vector2 txa, Vector2 txb, Vector2 txc,
            int i_a, int i_b, int i_c,
            HashSet <Vector3> allow_cut,
            bool addUVs
            )
        {
            // find intersection vertices / uvs
            var es = plane.Intersection(a, c, txa, txc, 0);
            var ds = plane.Intersection(b, c, txb, txc, 0);

            Vector3 e = es.Item1, d = ds.Item1;
            Vector2 txe = es.Item2, txd = ds.Item2;

            // if e == d, the three vertices lie in a line,
            //   and thus do not make up a triangle
            if (e == d)
            {
                return;

                // not sure if this is nescessary
                throw MeshUtilsException.ZeroAreaTriangle();
            }

            if (
                !allow_cut.Contains(e) &&
                !allow_cut.Contains(d)
                )
            {
                // triangle must not be cut
                part.indices.Add(part.indexMap[i_a]);
                part.indices.Add(part.indexMap[i_b]);
                part.indices.Add(part.indexMap[i_c]);
                return;
            }

            // new indices
            int i0 = part.vertices.Count, i1 = part.vertices.Count + 2;

            // add new vertices and uvs
            part.vertices.Add(d);
            part.vertices.Add(e);
            part.vertices.Add(d);
            part.vertices.Add(e);
            if (addUVs)
            {
                part.uvs.Add(txd);
                part.uvs.Add(txe);
                part.uvs.Add(txd);
                part.uvs.Add(txe);
            }

            // generate triangles ...

            // add a,d,e
            part.indices.Add(part.indexMap[i_a]);
            part.indices.Add(i0);
            part.indices.Add(i0 + 1);
            // add a,b,d
            part.indices.Add(part.indexMap[i_a]);
            part.indices.Add(part.indexMap[i_b]);
            part.indices.Add(i0);
            // add e,d,c
            part.indices.Add(i1 + 1);
            part.indices.Add(i1);
            part.indices.Add(part.indexMap[i_c]);
        }
Esempio n. 12
0
        // ------------------------------------------------------------
        // Generate single triangle for an intersecting triangle a,b,c
        // It is assumed that a is on the positive half plane
        // ------------------------------------------------------------
        public static void GenTriangle(
            CuttingPlane plane,
            MeshPart pos,
            Vector3 a, Vector3 b, Vector3 c,
            Vector2 txa, Vector2 txb, Vector2 txc,
            Vector3 na, Vector3 nb, Vector3 nc,
            int i_a, int i_b, int i_c,
            RingGenerator rings,
            bool addUVs,
            bool addNormals,
            float shift
            )
        {
            // find intersection vertices / uvs
            var es = plane.Intersection(c, a, txa, txc, nc, na, shift);
            var ds = plane.Intersection(b, a, txb, txc, nb, na, shift);

            Vector3 e = es.Item1, d = ds.Item1;
            Vector2 txe = es.Item2, txd = ds.Item2;
            Vector3 ne = es.Item3, nd = ds.Item3;

            // if e == d, the three vertices lie in a line,
            //   and thus do not make up a triangle
            if (e == d)
            {
                return;

                // not sure if this is nescessary
                throw MeshUtilsException.ZeroAreaTriangle();
            }

            // new indices
            int i0 = pos.vertices.Count;

            // add connected pair in ring generator

            // find proper direction for ring
            Vector3 tri_nor = Vector3.Cross(c - a, c - b);
            bool    dir     = Vector3.Dot(e - d, Vector3.Cross(plane.normal, tri_nor)) > 0;

            rings.AddConnected(dir?e:d, dir?d:e);

            // add new vertices and uvs
            pos.vertices.Add(d);
            pos.vertices.Add(e);
            if (addUVs)
            {
                pos.uvs.Add(txd);
                pos.uvs.Add(txe);
            }
            if (addNormals)
            {
                pos.normals.Add(nd);
                pos.normals.Add(ne);
            }

            // add a,d,e to positive indicies
            pos.indices.Add(pos.indexMap[i_a]);
            pos.indices.Add(i0);
            pos.indices.Add(i0 + 1);
        }