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); }
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); }
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); } } }
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); }