void OnDrawGizmos()
    {
        bool           success  = false;
        List <Vector3> testLine = test.Line.ToList();

        if (mathTest == MathTest.Collides)
        {
            success = ProcGenHelpers.CollidesWith(testLine[0], testLine[1], reference.Line.ToList(), true, out reference.markIndex);
        }
        else if (mathTest == MathTest.Ray)
        {
            reference.markIndex = -1;
            Vector3 pt = Vector3.one;
            success = ProcGenHelpers.RayInterceptsSegment(testLine[0], testLine[1] - testLine[0], reference.Line.ToList(), out pt);
            if (success)
            {
                Gizmos.color = Color.green;
                Gizmos.DrawSphere(pt, gizmosSize);
            }
        }
        else if (mathTest == MathTest.IsKnown)
        {
            success = ProcGenHelpers.IsKnownSegment(testLine[0], testLine[1], true, reference.Line.ToList());
        }


        test.lineColor = success ? Color.green : Color.gray;
    }
    public Dictionary <int, List <Vector3> > GetInterceptTris(Vector3[] intercepts, float proximityToPlaneThreshold = 0.001f)
    {
        Dictionary <int, List <Vector3> > interceptTris = new Dictionary <int, List <Vector3> >();

        for (int idIntercept = 0; idIntercept < intercepts.Length; idIntercept++)
        {
            Vector3 pt = intercepts[idIntercept];

            for (int idTri = 0, idVert = 0; idTri < myTrisCount; idTri++, idVert += 3)
            {
                Plane p = new Plane(myTriNormals[idTri], myTriCenters[idTri]);
                if (Mathf.Abs(p.GetDistanceToPoint(pt)) < proximityToPlaneThreshold)
                {
                    Vector3 vertA = myVerts[myTris[idVert]];
                    Vector3 vertB = myVerts[myTris[idVert + 1]];
                    Vector3 vertC = myVerts[myTris[idVert + 2]];

                    if (ProcGenHelpers.PointInTriangle(vertA, vertB, vertC, pt))
                    {
                        if (!interceptTris.Keys.Contains(idTri))
                        {
                            interceptTris[idTri] = new List <Vector3>();
                        }
                        interceptTris[idTri].Add(pt);
                        break;
                    }
                }
            }
        }

        return(interceptTris);
    }
    public List <Vector3> GetLineCutIntercepts(Vector3 a, Vector3 b, Vector3 n)
    {
        List <Vector3> cuts = new List <Vector3>();

        Vector3 intercept = Vector3.zero;

        for (int i = 0, v = 0; i < myTrisCount; i++, v += 3)
        {
            Vector3 vertA = myVerts[myTris[v]];
            Vector3 vertB = myVerts[myTris[v + 1]];
            Vector3 vertC = myVerts[myTris[v + 2]];

            //Debug.Log(string.Format("{0} - {1}, tri {2}", a, b, i));
            if (ProcGenHelpers.LineSegmentInterceptPlane(vertA, vertB, vertC, a, b, out intercept))
            {
                //Debug.Log("In plane");
                //cuts.Add(intercept);

                if (ProcGenHelpers.PointInTriangle(vertA, vertB, vertC, intercept))
                {
                    cuts.Add(intercept);
                }
            }
        }

        return(cuts);
    }
Esempio n. 4
0
    void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        if (drawing)
        {
            List <Vector3> allIntercepts = new List <Vector3>();

            //TODO: Much should be in cutter in future
            cutter.RecalculateMeshlike();

            Vector3[] l           = line.Line.ToArray();
            Vector3   normal      = Vector3.Cross(l[1] - l[0], l[2] - l[0]).normalized;
            int[]     outTriangle = new int[3] {
                0, 1, 2
            };

            Dictionary <int, List <Vector3> > cuts = cutter.GetCuts(l, outTriangle, 0, normal);
            foreach (List <Vector3> cutz in cuts.Values)
            {
                allIntercepts.AddRange(cutz);
            }

            foreach (Vector3 intercept in allIntercepts)
            {
                Gizmos.DrawSphere(intercept, gizmoSize);
            }
            subPaths = cutter.GetSubPaths(l, outTriangle, 0, normal, cuts, allIntercepts);

            //Debug.Log(subPaths.Count() + " paths");
            Gizmos.color = Color.red;
            for (int subP = 0; subP < subPaths.Count(); subP++)
            {
                List <int> tris = ProcGenHelpers.PolyToTriangles(subPaths[subP], normal, 0);
                //Debug.Log(tris.Count() + " triangle points");
                for (int idT = 0, lT = tris.Count(); idT < lT; idT += 3)
                {
                    Gizmos.DrawLine(subPaths[subP][tris[idT]], subPaths[subP][tris[idT + 1]]);
                    Gizmos.DrawLine(subPaths[subP][tris[idT + 1]], subPaths[subP][tris[idT + 2]]);
                    Gizmos.DrawLine(subPaths[subP][tris[idT + 2]], subPaths[subP][tris[idT]]);
                    Vector3 center = (subPaths[subP][tris[idT]] + subPaths[subP][tris[idT + 1]] + subPaths[subP][tris[idT + 2]]) / 3;
                    Gizmos.DrawWireCube(center, gizmoSize * Vector3.one);
                    Gizmos.DrawLine(center, center + Vector3.Cross(subPaths[subP][tris[idT + 1]] - subPaths[subP][tris[idT]], subPaths[subP][tris[idT + 2]] - subPaths[subP][tris[idT]]));
                }
            }
        }
    }
    float WallCWOrthoOffset(List <Vector3> innerWall, int wallSegment)
    {
        int l       = perimeter.Count;
        int idPerim = perimeter.IndexOf(innerWall[wallSegment]);

        if (idPerim >= 0)
        {
            Vector3 pt  = perimeter[idPerim];
            Vector3 rhs = pt - perimeter[(l + idPerim - 1) % l];
            Vector3 lhs = perimeter[(idPerim + 1) % l] - pt;
            if (ProcGenHelpers.XZRotation(lhs, rhs) == -1)
            {
                if (ProcGenHelpers.XZRotation(rhs, innerWall[wallSegment + 1] - innerWall[wallSegment]) == 0)
                {
                    return(0);
                }
                else
                {
                    return(1);
                }
            }
        }
        else if (wallSegment == l - 2)
        {
            idPerim = perimeter.IndexOf(innerWall[wallSegment]);
            if (idPerim >= 0)
            {
                Vector3 pt  = perimeter[idPerim];
                Vector3 rhs = pt - perimeter[(l + idPerim - 1) % l];
                Vector3 lhs = perimeter[(idPerim + 1) % l] - pt;
                if (ProcGenHelpers.XZRotation(lhs, rhs) == -1)
                {
                    if (ProcGenHelpers.XZRotation(rhs, innerWall[wallSegment - 1] - innerWall[wallSegment]) == 0)
                    {
                        return(1);
                    }
                    else
                    {
                        return(0);
                    }
                }
            }
        }
        return(0.5f);
    }
    void PlaceSelf()
    {
        List<List<Vector3>> floorParts = floor.GetPartialFloorRects(false).ToList();
        List<Vector3> outerWall = floor.GetCircumferance(false).ToList();
        int outerWallsLength = outerWall.Count;

        bool validated = false;

        while (!validated)
        {
            List<Vector3> compartment = floorParts[Random.Range(0, floorParts.Count)];

            Vector3 v1 = compartment[1] - compartment[0];
            Vector3 v2 = compartment[2] - compartment[1];

            //Vector3 c = compartment.Aggregate(Vector3.zero, (sum, e) => sum + e) / compartment.Count;

            Vector3 pt = compartment[0] + Random.value * v1 + Random.value * v2;
            
            validated = true;
            
            for (int i=0; i<outerWallsLength; i++)
            {
                float d = ProcGenHelpers.GetMinDist(pt, outerWall[i], outerWall[(i + 1) % outerWallsLength]);                
                if (d < proximityThreshold)
                {
                    Debug.Log("Invalid");
                    validated = false;
                    break;
                }
            }

            if (validated)
            {
                transform.position = pt;
            }
            
        }

        GetComponentInParent<RotateMe>().rotating = false;
        PlayerController.Instance.Spawn(transform);

    }
Esempio n. 7
0
    private void Player_OnModRayActivation(RaycastHit hit)
    {
        if (doorLayers != (doorLayers | (1 << hit.transform.gameObject.layer)))
        {
            return;
        }

        Vector3 localPos = transform.InverseTransformPoint(hit.point);

        localPos.y = doorSpawnY;

        for (int i = 0, l = transform.childCount; i < l; i++)
        {
            if (Vector3.SqrMagnitude(transform.GetChild(i).localPosition - localPos) < minSqDistanceBetweenDoors)
            {
                return;
            }
        }

        GameObject door = (GameObject)Instantiate(doorPrefab, transform);

        door.tag   = gameObject.tag;
        door.layer = gameObject.layer;
        door.transform.rotation = Quaternion.LookRotation(ProcGenHelpers.Get90CCW(hit.normal), Vector3.up);

        door.transform.localPosition = localPos;

        door.GetComponentInChildren <CookieCutter>().Cut();

        for (int i = 0, l = door.transform.childCount; i < l; i++)
        {
            if (!door.transform.GetChild(i).gameObject.activeInHierarchy)
            {
                door.transform.GetChild(i).gameObject.SetActive(true);
            }
        }
    }
Esempio n. 8
0
    void OnDrawGizmos()
    {
        if (!showing)
        {
            return;
        }

        Vector3[] points = line.Line.ToArray();
        if (points.Length == 3)
        {
            bool isIn = ProcGenHelpers.PointInTriangle(points[0], points[1], points[2], point.position);

            Gizmos.color = Color.red;

            if (isIn)
            {
                Gizmos.DrawCube(point.position, Vector3.one * gizmoSize);
            }
            else
            {
                Gizmos.DrawSphere(point.position, gizmoSize / 2f);
            }
        }
    }
    bool MapCornerStraightWall()
    {
        bool    room = false;
        Vector3 a    = convex[Random.Range(0, convex.Count)];
        //Debug.Log("Building from corner " + a);
        int            idA        = perimeter.IndexOf(a);
        List <Vector3> directions = new List <Vector3>();

        if (idA >= 0)
        {
            directions.Add((a - perimeter[(perimeter.Count + (idA - 1)) % perimeter.Count]).normalized);
            directions.Add((a - perimeter[(idA + 1) % perimeter.Count]).normalized);
            directions.Add((perimeter[(idA + 1) % perimeter.Count] - a).normalized);
            directions.Add((perimeter[(perimeter.Count + (idA - 1)) % perimeter.Count] - a).normalized);

            //AddGizmoWall(a, a + directions[0]);
            //AddGizmoWall(a, a + directions[1]);
        }

        else
        {
            foreach (List <Vector3> iWall in wallLines)
            {
                if (iWall.Contains(a))
                {
                    idA = iWall.IndexOf(a);
                    directions.Add((a - iWall[idA - 1]).normalized);
                    directions.Add((a - iWall[idA + 1]).normalized);
                    directions.Add((iWall[idA - 1] - a).normalized);
                    directions.Add((iWall[idA + 1] - a).normalized);

                    //AddGizmoWall(a, a + directions[0]);
                    //AddGizmoWall(a, a + directions[1]);

                    break;
                }
            }
        }

        Vector3 pt = Vector3.zero;

        for (int i = 0; i < directions.Count; i++)
        {
            if (ProcGenHelpers.RayInterceptsSegment(a, directions[i], perimeter, out pt))
            {
                int     wallsHit;
                Vector3 pt2;
                if (ProcGenHelpers.RayInterceptsSegment(a, directions[i], wallLines, out pt2, out wallsHit))
                {
                    if (!ProcGenHelpers.TooClose(pt, wallLines[wallsHit], shortestWall) && !ProcGenHelpers.IsKnownSegment(a, pt2, wallLines) && !ProcGenHelpers.IsKnownSegment(a, pt2, true, perimeter))
                    {
                        pt = pt2;
                        Debug.Log("Corner to inner wall");
                        room = true;
                        break;
                    }
                }
                else if (!ProcGenHelpers.TooClose(pt, perimeter, shortestWall) && !ProcGenHelpers.IsKnownSegment(a, pt, true, perimeter) && !ProcGenHelpers.IsKnownSegment(a, pt, wallLines))
                {
                    Debug.Log("Corner to outer wall");
                    room = true;
                    break;
                }
            }
        }

        if (room)
        {
            Debug.LogWarning(string.Format("Added simple wall {0} {1}", a, pt));
            nonConcave.Add(pt);
            wallLines.Add(new List <Vector3>()
            {
                a, pt
            });
            if (!nonConcave.Contains(pt))
            {
                nonConcave.Add(pt);
            }
        }

        return(room);
    }
    bool MapCornerToCornerWall()
    {
        bool    room  = false;
        int     indx  = Random.Range(0, convex.Count);
        Vector3 a1    = convex[indx];
        int     indx2 = (indx + Random.Range(1, convex.Count - 1)) % convex.Count;
        Vector3 a2    = convex[indx2];
        //Debug.Log(string.Format("Using indices {0} {1} ({2})", indx, indx2, convex.Count));
        List <List <Vector3> > testPaths = new List <List <Vector3> >();

        if (a1.x == a2.x || a1.z == a2.z)
        {
            testPaths.Add(new List <Vector3>()
            {
                a1, a2
            });
            //Debug.Log(string.Format("Test simple wall {0} {1}", a1, a2));
        }
        else
        {
            Vector3[] c = new Vector3[2] {
                new Vector3(a1.x, 0, a2.z), new Vector3(a2.x, 0, a1.z)
            };
            for (int i = 0; i < 2; i++)
            {
                testPaths.Add(new List <Vector3>()
                {
                    a1, c[i], a2
                });
            }
        }

        for (int i = 0, l = testPaths.Count; i < l; i++)
        {
            List <Vector3> newWall = testPaths[i];
            int            testIndex;
            int            pathIndex;

            bool isKnown = false;
            for (int idW = 0, wL = newWall.Count; idW < wL - 1; idW++)
            {
                if (ProcGenHelpers.IsKnownSegment(newWall[idW], newWall[idW + 1], true, perimeter) ||
                    ProcGenHelpers.IsKnownSegment(newWall[idW], newWall[idW + 1], wallLines))
                {
                    isKnown = true;
                    break;
                }
            }

            if (isKnown)
            {
                //Debug.Log("Inner wall collided with previously known wall");
            }
            else if (ProcGenHelpers.CollidesWith(newWall, perimeter, true, out testIndex, out pathIndex))
            {
                Debug.Log(string.Format("Inner wall {0} {1} collides at ({2} | {3})", newWall[testIndex], newWall[testIndex + 1], testIndex, pathIndex));
            }
            else
            {
                int pathsIndex;
                if (ProcGenHelpers.CollidesWith(newWall, wallLines, out testIndex, out pathIndex, out pathsIndex))
                {
                    Debug.Log("Collides with inner wall");
                }
                else
                {
                    //Debug.Log(string.Format("Added curved wall {0} {1} {2}", newWall.Count, newWall[0], newWall[newWall.Count -1]));
                    wallLines.Add(newWall);
                    room = true;
                    if (newWall.Count == 3)
                    {
                        convex.Add(newWall[1]);
                    }

                    break;
                }
            }
        }

        return(room);
    }
    bool MapWallToWall()
    {
        bool room = false;
        //Min length to divide
        float        longest = Mathf.Pow(shortestWall * 2, 2);
        List <float> lens    = new List <float>();

        for (int i = 0, l = perimeter.Count; i < l; i++)
        {
            int nextI = (i + 1) % l;
            lens.Add((perimeter[nextI] - perimeter[i]).sqrMagnitude);
        }
        int c = lens.Where(e => e > longest).Count();

        if (c > 0)
        {
            int v = Random.Range(0, c) + 1;

            //TODO: need to use also inner walls I thinks

            List <int> sums = new List <int>();
            lens.Aggregate(0, (sum, e) => { sum += e > longest ? 1 : 0; sums.Add(sum); return(sum); });
            int idLong = sums.IndexOf(v);

            longest = Mathf.Sqrt(lens[idLong]);
            float flexPos = longest - 2 * shortestWall;
            int   nextI   = (idLong + 1) % perimeter.Count;
            float t       = (Random.value * flexPos + shortestWall) / longest;
            //Debug.Log(t);
            Vector3 pt = Vector3.Lerp(perimeter[idLong], perimeter[nextI], t);

            Vector3 d = ProcGenHelpers.Get90CW(pt - perimeter[idLong]).normalized;
            AddGizmoWall(pt, pt + d);
            Vector3 ptB;
            //Debug.Log(string.Format("{0} - {1}, {2}, d {3}", perimeter[idLong], perimeter[nextI], pt, d));

            if (ProcGenHelpers.RayInterceptsSegment(pt, d, perimeter, out ptB))
            {
                bool    perim2Perim = true;
                Vector3 ptC;
                bool    allowWall = true;
                int     idLine;
                if (ProcGenHelpers.RayInterceptsSegment(pt, d, wallLines, out ptC, out idLine))
                {
                    if (ProcGenHelpers.TooClose(pt, wallLines[idLine], shortestWall) || ProcGenHelpers.IsKnownSegment(pt, ptC, wallLines) || ProcGenHelpers.IsKnownSegment(pt, ptC, true, perimeter))
                    {
                        allowWall = false;
                    }
                    else
                    {
                        //Debug.Log("Wall construction intercept inner wall");
                        nonConcave.Add(ptB);
                        if ((ptC - pt).sqrMagnitude < (ptB - pt).sqrMagnitude)
                        {
                            ptB         = ptC;
                            perim2Perim = false;
                        }
                    }
                }
                else if (ProcGenHelpers.IsKnownSegment(pt, ptB, true, perimeter))
                {
                    allowWall = false;
                }

                if (allowWall && (ptB - pt).magnitude > shortestWall && !ProcGenHelpers.TooClose(pt, perimeter, shortestWall))
                {
                    wallLines.Add(new List <Vector3>()
                    {
                        pt, ptB
                    });
                    if (!nonConcave.Contains(pt))
                    {
                        nonConcave.Add(pt);
                    }
                    if (!nonConcave.Contains(ptB))
                    {
                        nonConcave.Add(ptB);
                    }
                    room = true;
                    perimeter.Insert(idLong + 1, pt);

                    if (perim2Perim)
                    {
                        for (int i = 0, l = perimeter.Count; i < l; i++)
                        {
                            int j = (i + 1) % l;
                            if (ProcGenHelpers.PointOnSegmentXZ(perimeter[i], perimeter[j], ptB))
                            {
                                perimeter.Insert(i + 1, ptB);
                                Debug.Log("Inserted perim to perim");
                                break;
                            }
                        }
                    }

                    Debug.Log("Inserted free wall");
                }
            }
        }

        return(room);
    }
    IEnumerator <WaitForSeconds> _Build()
    {
        //TODO: Best way to remove convex points
        //TODO: Instert point in next wall behind current rather than far wall
        //TODO: Have points of interest (non concave) and use for corners too?
        //TODO: Linear points to wall building.
        //TODO: Allow inner wall free building.

        gizmoWalls.Clear();
        int rooms = Mathf.Clamp(Random.Range(1, 3) + Random.Range(1, 4) + Random.Range(2, 4), 4, 7);

        perimeter.Clear();
        perimeter.AddRange(ProcGenHelpers.Simplify(floor.GetCircumferance(false).Select(v => transform.InverseTransformPoint(v)).ToList()));

        yield return(new WaitForSeconds(0.05f));

        for (int i = 0, l = perimeter.Count; i < l; i++)
        {
            Vector3 pt       = perimeter[i];
            Vector3 rhs      = pt - perimeter[(l + i - 1) % l];
            Vector3 lhs      = perimeter[(i + 1) % l] - pt;
            int     rotation = ProcGenHelpers.XZRotation(lhs, rhs);
            if (rotation == -1)
            {
                //Debug.Log(string.Format("{0}: convex", i));
                convex.Add(pt);
            }
            else if (rotation == 1)
            {
                //Debug.Log(string.Format("{0}: concave", i));
                nonConcave.Add(pt);
            }
        }


        yield return(new WaitForSeconds(0.01f));

        int attempts = 0;

        while (rooms > 0 && attempts < 300)
        {
            bool          addedRoom = false;
            RoomBuildType nextRoom  = NextRoomType;
            if (nextRoom == RoomBuildType.ConvexCornerToStraightToWall)
            {
                if (MapCornerStraightWall())
                {
                    rooms--;
                    addedRoom = true;
                }
            }
            else if (nextRoom == RoomBuildType.ConvexCornerToConvexCorner)
            {
                if (MapCornerToCornerWall())
                {
                    rooms--;
                    addedRoom = true;
                }
            }
            else if (nextRoom == RoomBuildType.WallStraightToWall)
            {
                if (MapWallToWall())
                {
                    rooms--;
                    addedRoom = true;
                }
            }

            attempts++;
            yield return(new WaitForSeconds(addedRoom ? 0.05f : 0.01f));
        }

        Debug.LogWarning(string.Format("Ended with remaining {0} rooms after {1} attempts", rooms, attempts));

        foreach (List <Vector3> innerWall in wallLines)
        {
            ConstructInnerWall(innerWall);
            yield return(new WaitForSeconds(0.05f));

            innerWall.Reverse();
            ConstructInnerWall(innerWall);
            yield return(new WaitForSeconds(0.05f));
        }


        mCol.sharedMesh = null;
        mCol.sharedMesh = mesh;

        generated  = true;
        generating = false;
    }
    public void CutDough(Mesh dough, MeshFilter mFilt)
    {
        Debug.Log("Cutting " + mFilt.gameObject);
        Transform doughTransform = mFilt.transform;

        List <Vector3> allIntercepts = new List <Vector3>();

        Vector3[]      verts    = dough.vertices.Select(v => doughTransform.TransformPoint(v)).ToArray();
        int[]          tris     = dough.triangles;
        Vector2[]      uvs      = dough.uv;
        List <Vector3> newVerts = new List <Vector3>();
        List <Vector2> newUVs   = new List <Vector2>();
        List <int>     newTris  = new List <int>();

        for (int triStart = 0, nTris = tris.Length; triStart < nTris; triStart += 3)
        {
            Vector3[] triCorners = new Vector3[3] {
                verts[tris[triStart]], verts[tris[triStart + 1]], verts[tris[triStart + 2]]
            };
            if (triCorners.All(v => PointInMesh(v)))
            {
                Debug.Log(string.Format("Remove tri {0} {1} {2} because entirely inside cutter", tris[triStart], tris[triStart + 1], tris[triStart + 2]));
                continue;
            }

            Vector2[] triUVs = new Vector2[3] {
                uvs[tris[triStart]], uvs[tris[triStart + 1]], uvs[tris[triStart + 2]]
            };
            Vector3 normal = Vector3.Cross(triCorners[1] - triCorners[0], triCorners[2] - triCorners[0]).normalized;
            Debug.Log(string.Format("Tri {0} {1} {2}, Normal {3}", triCorners[0], triCorners[1], triCorners[2], normal));
            int[] outTriangle = new int[3] {
                0, 1, 2
            };

            Dictionary <int, List <Vector3> > cuts = GetCuts(triCorners, outTriangle, 0, normal);
            foreach (List <Vector3> cutz in cuts.Values)
            {
                allIntercepts.AddRange(cutz);
            }

            //TODO: add stuff here to fix entirely inside

            if (allIntercepts.Count() > 0)
            {
                List <List <Vector3> > subPaths = GetSubPaths(triCorners, outTriangle, 0, normal, cuts, allIntercepts);

                for (int subP = 0; subP < subPaths.Count(); subP++)
                {
                    Debug.Log(string.Format("Creating tris on {0} for poly {1} (length {3}) of original tri {2} +1 +2", mFilt.gameObject, subP, triStart, subPaths[subP].Count()));
                    newTris.AddRange(ProcGenHelpers.PolyToTriangles(subPaths[subP], normal, newVerts.Count()));
                    newVerts.AddRange(subPaths[subP]);
                    newUVs.AddRange(ProcGenHelpers.GetProjectedUVs(triCorners, triUVs, subPaths[subP]));
                }
            }
            else
            {
                //Triangle outside cutter entirely
                int nVerts = newVerts.Count();
                newVerts.AddRange(triCorners);
                newUVs.AddRange(triUVs);
                for (int i = 0; i < 3; i++)
                {
                    newTris.Add(nVerts + i);
                }
            }
        }

        Mesh cutDough = new Mesh();

        cutDough.name = dough.name + ".CCut";
        cutDough.Clear();
        cutDough.SetVertices(newVerts.Select(v => doughTransform.InverseTransformPoint(v)).ToList());
        cutDough.SetUVs(0, newUVs);
        cutDough.SetTriangles(newTris, 0);
        cutDough.RecalculateBounds();
        cutDough.RecalculateNormals();

        mFilt.sharedMesh = cutDough;

        MeshCollider mCol = mFilt.GetComponent <MeshCollider>();

        if (mCol && mCol.sharedMesh == dough)
        {
            mCol.sharedMesh = cutDough;
        }
    }
    public List <List <Vector3> > GetSubPaths(Vector3[] verts, int[] tris, int start, Vector3 normal, Dictionary <int, List <Vector3> > cuts, List <Vector3> allIntercepts, int len = 3)
    {
        List <List <Vector3> > subPaths = new List <List <Vector3> >();

        if (allIntercepts.Count() == 1)
        {
            Debug.Log("Not safe distance to original tri vert to make cut");
            return(subPaths);
        }

        int curSubPath = 0;
        Dictionary <int, List <Vector3> > interceptTris = GetInterceptTris(allIntercepts.ToArray());
        List <KeyValuePair <int, int> >   triCorners    = new List <KeyValuePair <int, int> >();
        List <Vector3> triVerts = new List <Vector3>();

        for (int i = start, end = start + len, j = 0; i < end; i++, j++)
        {
            triVerts.Add(verts[tris[i]]);
            triCorners.Add(new KeyValuePair <int, int>(j, tris[i]));
        }

        List <int> cornersInCurSubPath = new List <int>();
        int        curCorner           = triCorners[0].Value;
        int        triCurCornerIndex   = triCorners[0].Key;
        bool       keepTrying          = true;

        while (triCorners.Count() > 0 || keepTrying)
        {
            bool walkingSubPath = false;
            //Debug.Log(string.Format("Current sub path {0}, {1} known", curSubPath, subPaths.Count()));
            if (PointInMesh(verts[curCorner]) || curSubPath >= subPaths.Count())
            {
                if (triCorners.Count() > 0)
                {
                    //Debug.Log(corners.Count() + " corners remaining");
                    if (subPaths.Count() == 0 || subPaths[subPaths.Count() - 1].Count() > 0)
                    {
                        subPaths.Add(new List <Vector3>());
                    }
                    curCorner         = triCorners[0].Value;
                    triCurCornerIndex = triCorners[0].Key;
                    triCorners.RemoveAt(0);
                    cornersInCurSubPath.Clear();
                }
                else
                {
                    //Debug.Log("Out of corners");
                    keepTrying = false;
                }
                continue;
            }

            //Debug.Log(string.Format("Adding corner {0} to path {1}", curCorner, curSubPath));
            cornersInCurSubPath.Add(curCorner);
            subPaths[curSubPath].Add(verts[curCorner]);

            if (cuts[curCorner].Count() > 0)
            {
                Vector3    intercept = cuts[curCorner][0]; //First cut is going into cutter always
                List <int> iTris     = interceptTris.Where(kvp => kvp.Value.Contains(intercept)).Select(kvp => kvp.Key).ToList();
                if (iTris.Count() == 1)
                {
                    int            tri       = iTris[0];
                    Vector3        thirdVert = triVerts[(triCurCornerIndex + 2) % 3];
                    List <Vector3> cutLine   = TraceSurface(tri, thirdVert, intercept, normal, interceptTris, out rayTrain);
                    if (cutLine.Count() > 0)
                    {
                        if (cutLine.Where((v, idV) => idV < cutLine.Count() - 1).All(v => ProcGenHelpers.PointInTriangle(triVerts[0], triVerts[1], triVerts[2], v)))
                        {
                            cutLine.Insert(0, intercept);

                            subPaths[curSubPath].AddRange(cutLine);

                            walkingSubPath = true;

                            int nextEdge = ProcGenHelpers.GetClosestSegment(triVerts, cutLine.Last());
                            if (nextEdge < 0)
                            {
                                walkingSubPath = false;
                                Debug.LogError("Lost track of where we are, now everything is possible. Unfortunately.");
                            }
                            else
                            {
                                nextEdge = (nextEdge + 1) % triVerts.Count();
                                //Debug.Log(nextEdge);
                                if (cornersInCurSubPath.Contains(nextEdge))
                                {
                                    //Debug.Log(string.Format("Closing {0} SubPath with corner {1}", curSubPath, curCorner));
                                    curSubPath++;
                                }
                                else
                                {
                                    triCurCornerIndex = triCorners.Where(e => e.Value == nextEdge).First().Key;
                                    if (!triCorners.Remove(triCorners.Where(e => e.Value == nextEdge).First()))
                                    {
                                        Debug.LogWarning(string.Format("Seems like we are revisting corner #{0}, this should not have happened.", nextEdge));
                                    }
                                    else
                                    {
                                        //Debug.Log(string.Format("Next edge {0} is not current corner {1} for sub-path {2}", nextEdge, curCorner, curSubPath));
                                    }
                                    curCorner = nextEdge;
                                }
                            }
                        }
                        else
                        {
                            Debug.LogWarning("Cutting the triangle outside triangle is bad idea.");
                        }
                    }
                    else
                    {
                        Debug.LogWarning("Empty cut");
                    }
                }
                else
                {
                    Debug.LogWarning("Intercept is duplicated");
                }
            }

            if (!walkingSubPath)
            {
                if (triCorners.Count() > 0)
                {
                    curCorner         = triCorners[0].Value;
                    triCurCornerIndex = triCorners[0].Key;
                    triCorners.RemoveAt(0);
                }
                else
                {
                    keepTrying = false;
                }
            }
        }

        return(subPaths.Where(p => p.Count() > 0).ToList());
    }
    //List<Vector3> outsideTriFail = new List<Vector3>();

    public List <Vector3> TraceSurface(int tri, Vector3 thirdVert, Vector3 intercept, Vector3 normal, Dictionary <int, List <Vector3> > allIntercepts, out List <Ray> rayTrain, float proximityOfInterceptThreshold = 0.01f, int searchDepth = 20)
    {
        List <Vector3> traceLine        = new List <Vector3>();
        Vector3        orginalIntercept = intercept;

        //Vector3 originalNorm = myTriNormals[tri];
        rayTrain = new List <Ray>();
        Ray r;

        if (ProcGenHelpers.InterceptionRay(normal, intercept, myTriNormals[tri], out r))
        {
            r.direction = Mathf.Sign(Vector3.Dot(thirdVert - intercept, r.direction)) * r.direction;

            while (tri >= 0)
            {
                rayTrain.Add(new Ray(r.origin, r.direction));
                int     v     = tri * 3;
                Vector3 vertA = myVerts[myTris[v]];
                Vector3 vertB = myVerts[myTris[v + 1]];
                Vector3 vertC = myVerts[myTris[v + 2]];

                int hitEdge;

                //TODO: Sensitive as edge condition in some rotations
                Vector3 rayHit = ProcGenHelpers.RayHitEdge(vertA, vertB, vertC, r, out hitEdge);

                if (hitEdge == -1)
                {
                    /*
                     * outsideTriFail.Clear();
                     * outsideTriFail.Add(vertA);
                     * outsideTriFail.Add(vertB);
                     * outsideTriFail.Add(vertC);
                     * Debug.LogError(string.Format("Intercept {0} was not in the reported triangle {2} (trace length = {1}, normal = {3})!", intercept, traceLine.Count(), tri, normal));
                     * Debug.Log(string.Format("{0} {1} {2} ray {3} -> ({4}, {5}, {6}) missed", vertA, vertB, vertC, r.origin, r.direction.x, r.direction.y, r.direction.z));
                     * Debug.Log(string.Format("Norm calc {0} Norm pre calc {1}, Other Norm {2}, Ray direction {3}",
                     *  Vector3.Cross(vertB - vertA, vertC - vertA), originalNorm, normal, Vector3.Cross(originalNorm, normal)));
                     * outsideTriFail.Clear();
                     * outsideTriFail.Add(vertA);
                     * outsideTriFail.Add(vertB);
                     * outsideTriFail.Add(vertC);
                     */

                    traceLine.Clear();
                    tri = -1;
                    Debug.LogError(string.Format("Intercept {0} was not in the reported triangle {2} (trace length = {1}, normal = {3})!", intercept, traceLine.Count(), tri, normal));
                    float t1;
                    float t2;
                    bool  val = ProcGenHelpers.LineSegmentInterceptIn3D(vertB, vertC, r, 0.01f, out t1, out t2);
                    Debug.LogError(string.Format("t1 {0} t2 {1} dist {2} {3}, {4}", t1, t2, Vector3.Distance(vertB + (vertC - vertB).normalized * t1, r.GetPoint(t2)), val, (vertC - vertB).magnitude));
                }
                else
                {
                    if (allIntercepts.Keys.Contains(tri))
                    {
                        List <Vector3> hitIntercepts = allIntercepts[tri]
                                                       .Where(v1 => Vector3.SqrMagnitude(v1 - orginalIntercept) > proximityOfInterceptThreshold)
                                                       .Select(v2 => new {
                            vert = v2,
                            dist = ProcGenHelpers.GetMinDist(v2, intercept, rayHit)
                        })
                                                       .Where(e => e.dist < proximityOfInterceptThreshold)
                                                       //TODO: Potentially order by proximity to intercept
                                                       .Select(e => e.vert).ToList();

                        if (hitIntercepts.Count > 0)
                        {
                            //Debug.Log(string.Format("Found path connecting intercepts {0} - {1}", orginalIntercept, hitIntercepts[0]));
                            traceLine.Add(hitIntercepts[0]);
                            return(traceLine);
                        }
                        else
                        {
                            /*
                             * Debug.Log(string.Format("No close intercept on {0} ({1} - {2}), closest: {3}",
                             *  tri,
                             *  intercept, rayHit,
                             *  allIntercepts[tri]
                             *      //.Where(v1 => Vector3.SqrMagnitude(v1 - orginalIntercept) > proximityOfInterceptThreshold)
                             *      .Select(v2 => new {
                             *          vert = v2,
                             *          dist = ProcGenHelpers.GetMinDist(v2, intercept, rayHit)
                             *      })
                             *      .OrderBy(e => e.dist)
                             *      //TODO: Potentially order by proximity to intercept
                             *      .Select(e => e.vert).FirstOrDefault().magnitude
                             *  ));
                             */
                        }
                    }
                    else
                    {
                        //Debug.Log("No intercept in tri " + tri);
                    }

                    if (traceLine.Contains(rayHit))
                    {
                        Debug.LogError("Going back over myself");
                        return(traceLine);
                    }
                    else
                    {
                        //Debug.Log("Hit tri edge at " + rayHit);
                        traceLine.Add(rayHit);
                    }

                    int nextTri = GetNeighbourTri(myTris[v + hitEdge], myTris[v + (hitEdge + 1) % 3], tri);
                    if (nextTri != -1)
                    {
                        intercept = rayHit;

                        if (ProcGenHelpers.InterceptionRay(normal, intercept, myTriNormals[nextTri], out r))
                        {
                            int     idThirdVert = GetMissingVert(nextTri, myTris[v + hitEdge], myTris[v + (hitEdge + 1) % 3]);
                            Vector3 d3          = myVerts[idThirdVert] - intercept;
                            float   sign        = Mathf.Sign(Vector3.Dot(d3, r.direction));

                            /*Debug.Log(string.Format("{3} ({9}) -> {4} ({10}): {0} - {1}, {2} ({5}, {6}) [{7} {8}]",
                             *  myTris[v + hitEdge], myTris[v + (hitEdge + 1) % 3], idThirdVert,
                             *  tri, nextTri,
                             *  r.direction, sign,
                             *  myVerts[idThirdVert], intercept,
                             *  myTriNormals[tri], myTriNormals[nextTri]
                             *  ));*/
                            r.direction = sign * r.direction;
                            tri         = nextTri;
                            //Debug.Log("Found next tri");
                        }
                        else
                        {
                            Debug.LogError("The identified next tri didn't intercept cutting Tri");
                            tri = -1;
                        }
                    }
                    else
                    {
                        Debug.LogError("No neighbour");
                    }
                }

                if (traceLine.Count() >= searchDepth)
                {
                    Debug.LogWarning("Aborted trace because reached search depth");
                    traceLine.Clear();
                    return(traceLine);
                }
            }
        }

        traceLine.Clear();
        Debug.Log("Found strange line that started in " + orginalIntercept);
        return(traceLine);
    }