void CalculateMeshContour() { if (mesh == null) { return; } edges.Clear(); pointers.Clear(); Vector3[] verts = mesh.vertices; int[] tris = mesh.triangles; for (int i = 0; i < tris.Length; i += 3) { // Make sure it is clockwise if (Polygon.IsClockwise(verts[tris[i + 0]], verts[tris[i + 1]], verts[tris[i + 2]])) { int tmp = tris[i + 0]; tris[i + 0] = tris[i + 2]; tris[i + 2] = tmp; } edges[new Int2(tris[i + 0], tris[i + 1])] = i; edges[new Int2(tris[i + 1], tris[i + 2])] = i; edges[new Int2(tris[i + 2], tris[i + 0])] = i; } // Construct a list of pointers along all edges for (int i = 0; i < tris.Length; i += 3) { for (int j = 0; j < 3; j++) { if (!edges.ContainsKey(new Int2(tris[i + ((j + 1) % 3)], tris[i + ((j + 0) % 3)]))) { pointers[tris[i + ((j + 0) % 3)]] = tris[i + ((j + 1) % 3)]; } } } var contourBuffer = new List <Vector3[]>(); List <Vector3> buffer = Pathfinding.Util.ListPool <Vector3> .Claim(); // Follow edge pointers to generate the contours for (int i = 0; i < verts.Length; i++) { if (pointers.ContainsKey(i)) { buffer.Clear(); int s = i; do { int tmp = pointers[s]; //This path has been taken before if (tmp == -1) { break; } pointers[s] = -1; buffer.Add(verts[s]); s = tmp; if (s == -1) { Debug.LogError("Invalid Mesh '" + mesh.name + " in " + gameObject.name); break; } } while (s != i); if (buffer.Count > 0) { contourBuffer.Add(buffer.ToArray()); } } } // Return lists to the pool Pathfinding.Util.ListPool <Vector3> .Release(buffer); contours = contourBuffer.ToArray(); }
private void GenerateNodes(Vector3[] vectorVertices, int[] triangles, out Vector3[] originalVertices, out VInt3[] vertices) { if ((vectorVertices.Length == 0) || (triangles.Length == 0)) { originalVertices = vectorVertices; vertices = new VInt3[0]; this.nodes = new TriangleMeshNode[0]; } else { vertices = new VInt3[vectorVertices.Length]; int index = 0; for (int i = 0; i < vertices.Length; i++) { vertices[i] = (VInt3)this.matrix.MultiplyPoint3x4(vectorVertices[i]); } Dictionary <VInt3, int> dictionary = new Dictionary <VInt3, int>(); int[] numArray = new int[vertices.Length]; for (int j = 0; j < vertices.Length; j++) { if (!dictionary.ContainsKey(vertices[j])) { numArray[index] = j; dictionary.Add(vertices[j], index); index++; } } for (int k = 0; k < triangles.Length; k++) { VInt3 num5 = vertices[triangles[k]]; triangles[k] = dictionary[num5]; } VInt3[] numArray2 = vertices; vertices = new VInt3[index]; originalVertices = new Vector3[index]; for (int m = 0; m < index; m++) { vertices[m] = numArray2[numArray[m]]; originalVertices[m] = vectorVertices[numArray[m]]; } this.nodes = new TriangleMeshNode[triangles.Length / 3]; int graphIndex = base.active.astarData.GetGraphIndex(this); for (int n = 0; n < this.nodes.Length; n++) { this.nodes[n] = new TriangleMeshNode(base.active); TriangleMeshNode node = this.nodes[n]; node.GraphIndex = (uint)graphIndex; node.Penalty = base.initialPenalty; node.Walkable = true; node.v0 = triangles[n * 3]; node.v1 = triangles[(n * 3) + 1]; node.v2 = triangles[(n * 3) + 2]; if (!Polygon.IsClockwise(vertices[node.v0], vertices[node.v1], vertices[node.v2])) { int num9 = node.v0; node.v0 = node.v2; node.v2 = num9; } if (Polygon.IsColinear(vertices[node.v0], vertices[node.v1], vertices[node.v2])) { Debug.DrawLine((Vector3)vertices[node.v0], (Vector3)vertices[node.v1], Color.red); Debug.DrawLine((Vector3)vertices[node.v1], (Vector3)vertices[node.v2], Color.red); Debug.DrawLine((Vector3)vertices[node.v2], (Vector3)vertices[node.v0], Color.red); } node.UpdatePositionFromVertices(); } DictionaryView <VInt2, TriangleMeshNode> view = new DictionaryView <VInt2, TriangleMeshNode>(); int num10 = 0; int num11 = 0; while (num10 < triangles.Length) { view[new VInt2(triangles[num10], triangles[num10 + 1])] = this.nodes[num11]; view[new VInt2(triangles[num10 + 1], triangles[num10 + 2])] = this.nodes[num11]; view[new VInt2(triangles[num10 + 2], triangles[num10])] = this.nodes[num11]; num11++; num10 += 3; } ListLinqView <MeshNode> view2 = new ListLinqView <MeshNode>(); List <uint> list = new List <uint>(); int num12 = 0; int num13 = 0; int num14 = 0; while (num13 < triangles.Length) { view2.Clear(); list.Clear(); TriangleMeshNode node2 = this.nodes[num14]; for (int num15 = 0; num15 < 3; num15++) { TriangleMeshNode node3; if (view.TryGetValue(new VInt2(triangles[num13 + ((num15 + 1) % 3)], triangles[num13 + num15]), out node3)) { view2.Add(node3); VInt3 num16 = node2.position - node3.position; list.Add((uint)num16.costMagnitude); } } node2.connections = view2.ToArray(); node2.connectionCosts = list.ToArray(); num14++; num13 += 3; } if (num12 > 0) { Debug.LogError("One or more triangles are identical to other triangles, this is not a good thing to have in a navmesh\nIncreasing the scale of the mesh might help\nNumber of triangles with error: " + num12 + "\n"); } RebuildBBTree(this); } }
// Token: 0x06002248 RID: 8776 RVA: 0x0018DCF8 File Offset: 0x0018BEF8 public void RecalcConvex() { this.convexPoints = (this.convex ? Polygon.ConvexHullXZ(this.points) : null); }
public List <Vector3> SmoothSimple(List <Vector3> path) { if (path.Count < 2) { return(path); } List <Vector3> subdivided; if (uniformLength) { // Clamp to a small value to avoid the path being divided into a huge number of segments maxSegmentLength = Mathf.Max(maxSegmentLength, 0.005f); float pathLength = 0; for (int i = 0; i < path.Count - 1; i++) { pathLength += Vector3.Distance(path[i], path[i + 1]); } int estimatedNumberOfSegments = Mathf.FloorToInt(pathLength / maxSegmentLength); // Get a list with an initial capacity high enough so that we can add all points subdivided = ListPool <Vector3> .Claim(estimatedNumberOfSegments + 2); float distanceAlong = 0; // Sample points every [maxSegmentLength] world units along the path for (int i = 0; i < path.Count - 1; i++) { var start = path[i]; var end = path[i + 1]; float length = Vector3.Distance(start, end); while (distanceAlong < length) { subdivided.Add(Vector3.Lerp(start, end, distanceAlong / length)); distanceAlong += maxSegmentLength; } distanceAlong -= length; } // Make sure we get the exact position of the last point subdivided.Add(path[path.Count - 1]); } else { subdivisions = Mathf.Max(subdivisions, 0); if (subdivisions > 10) { Debug.LogWarning("Very large number of subdivisions. Cowardly refusing to subdivide every segment into more than " + (1 << subdivisions) + " subsegments"); subdivisions = 10; } int steps = 1 << subdivisions; subdivided = ListPool <Vector3> .Claim((path.Count - 1) *steps + 1); Polygon.Subdivide(path, subdivided, steps); } if (strength > 0) { for (int it = 0; it < iterations; it++) { Vector3 prev = subdivided[0]; for (int i = 1; i < subdivided.Count - 1; i++) { Vector3 tmp = subdivided[i]; // prev is at this point set to the value that subdivided[i-1] had before this loop started // Move the point closer to the average of the adjacent points subdivided[i] = Vector3.Lerp(tmp, (prev + subdivided[i + 1]) / 2F, strength); prev = tmp; } } } return(subdivided); }
/** Recalculate convex points. * Will not do anything if not #convex is enabled */ public void RecalcConvex() { convexPoints = convex ? Polygon.ConvexHull(points) : null; }
public bool FindNextCorners(Vector3 origin, int startIndex, List <Vector3> funnelPath, int numCorners, out bool lastCorner) { lastCorner = false; if (this.left == null) { throw new Exception("left list is null"); } if (this.right == null) { throw new Exception("right list is null"); } if (funnelPath == null) { throw new ArgumentNullException("funnelPath"); } if (this.left.Count != this.right.Count) { throw new ArgumentException("left and right lists must have equal length"); } int count = this.left.Count; if (count == 0) { throw new ArgumentException("no diagonals"); } if (count - startIndex < 3) { funnelPath.Add(this.left[count - 1]); lastCorner = true; return(true); } while (this.left[startIndex + 1] == this.left[startIndex + 2] && this.right[startIndex + 1] == this.right[startIndex + 2]) { startIndex++; if (count - startIndex <= 3) { return(false); } } Vector3 vector = this.left[startIndex + 2]; if (vector == this.left[startIndex + 1]) { vector = this.right[startIndex + 2]; } while (Polygon.IsColinear(origin, this.left[startIndex + 1], this.right[startIndex + 1]) || Polygon.Left(this.left[startIndex + 1], this.right[startIndex + 1], vector) == Polygon.Left(this.left[startIndex + 1], this.right[startIndex + 1], origin)) { startIndex++; if (count - startIndex < 3) { funnelPath.Add(this.left[count - 1]); lastCorner = true; return(true); } vector = this.left[startIndex + 2]; if (vector == this.left[startIndex + 1]) { vector = this.right[startIndex + 2]; } } Vector3 vector2 = origin; Vector3 vector3 = this.left[startIndex + 1]; Vector3 vector4 = this.right[startIndex + 1]; int num = startIndex + 1; int num2 = startIndex + 1; int i = startIndex + 2; while (i < count) { if (funnelPath.Count >= numCorners) { return(true); } if (funnelPath.Count > 2000) { Debug.LogWarning("Avoiding infinite loop. Remove this check if you have this long paths."); break; } Vector3 vector5 = this.left[i]; Vector3 vector6 = this.right[i]; if (Polygon.TriangleArea2(vector2, vector4, vector6) < 0f) { goto IL_2FB; } if (vector2 == vector4 || Polygon.TriangleArea2(vector2, vector3, vector6) <= 0f) { vector4 = vector6; num = i; goto IL_2FB; } funnelPath.Add(vector3); vector2 = vector3; int num3 = num2; vector3 = vector2; vector4 = vector2; num2 = num3; num = num3; i = num3; IL_35F: i++; continue; IL_2FB: if (Polygon.TriangleArea2(vector2, vector3, vector5) > 0f) { goto IL_35F; } if (vector2 == vector3 || Polygon.TriangleArea2(vector2, vector4, vector5) >= 0f) { vector3 = vector5; num2 = i; goto IL_35F; } funnelPath.Add(vector4); vector2 = vector4; num3 = num; vector3 = vector2; vector4 = vector2; num2 = num3; num = num3; i = num3; goto IL_35F; } lastCorner = true; funnelPath.Add(this.left[count - 1]); return(true); }
public static void UpdateArea(GraphUpdateObject o, INavmesh graph) { //System.DateTime startTime = System.DateTime.UtcNow; Bounds bounds = o.bounds; Rect r = Rect.MinMaxRect(bounds.min.x, bounds.min.z, bounds.max.x, bounds.max.z); var r2 = new IntRect( Mathf.FloorToInt(bounds.min.x * Int3.Precision), Mathf.FloorToInt(bounds.min.z * Int3.Precision), Mathf.FloorToInt(bounds.max.x * Int3.Precision), Mathf.FloorToInt(bounds.max.z * Int3.Precision) ); var a = new Int3(r2.xmin, 0, r2.ymin); var b = new Int3(r2.xmin, 0, r2.ymax); var c = new Int3(r2.xmax, 0, r2.ymin); var d = new Int3(r2.xmax, 0, r2.ymax); graph.GetNodes(_node => { var node = _node as TriangleMeshNode; bool inside = false; int allLeft = 0; int allRight = 0; int allTop = 0; int allBottom = 0; for (int v = 0; v < 3; v++) { Int3 p = node.GetVertex(v); var vert = (Vector3)p; if (r2.Contains(p.x, p.z)) { inside = true; break; } if (vert.x < r.xMin) { allLeft++; } if (vert.x > r.xMax) { allRight++; } if (vert.z < r.yMin) { allTop++; } if (vert.z > r.yMax) { allBottom++; } } if (!inside) { if (allLeft == 3 || allRight == 3 || allTop == 3 || allBottom == 3) { return(true); } } for (int v = 0; v < 3; v++) { int v2 = v > 1 ? 0 : v + 1; Int3 vert1 = node.GetVertex(v); Int3 vert2 = node.GetVertex(v2); if (Polygon.Intersects(a, b, vert1, vert2)) { inside = true; break; } if (Polygon.Intersects(a, c, vert1, vert2)) { inside = true; break; } if (Polygon.Intersects(c, d, vert1, vert2)) { inside = true; break; } if (Polygon.Intersects(d, b, vert1, vert2)) { inside = true; break; } } if (node.ContainsPoint(a) || node.ContainsPoint(b) || node.ContainsPoint(c) || node.ContainsPoint(d)) { inside = true; } if (!inside) { return(true); } o.WillUpdateNode(node); o.Apply(node); return(true); }); }
public static bool ContainsPoint(TriangleMeshNode node, Vector3 pos, VInt3[] vertices) { if (!Polygon.IsClockwiseMargin((Vector3)vertices[node.v0], (Vector3)vertices[node.v1], (Vector3)vertices[node.v2])) { Debug.LogError("Noes!"); } return((Polygon.IsClockwiseMargin((Vector3)vertices[node.v0], (Vector3)vertices[node.v1], pos) && Polygon.IsClockwiseMargin((Vector3)vertices[node.v1], (Vector3)vertices[node.v2], pos)) && Polygon.IsClockwiseMargin((Vector3)vertices[node.v2], (Vector3)vertices[node.v0], pos)); }
public Vector3 ClampMovement(Vector3 direction) { Vector3 vector = direction * this.delta; Vector3 vector2 = base.transform.position + direction; Vector3 vector3 = vector2; float num = 0f; int num2 = 0; this.vos.Clear(); float magnitude = this.velocity.magnitude; foreach (LocalAvoidance localAvoidance in this.agents) { if (!(localAvoidance == this) && !(localAvoidance == null)) { Vector3 vector4 = localAvoidance.transform.position - base.transform.position; float magnitude2 = vector4.magnitude; float num3 = this.radius + localAvoidance.radius; if (magnitude2 <= vector.magnitude * this.delta + num3 + magnitude + localAvoidance.GetVelocity().magnitude) { if (num2 <= 50) { num2++; LocalAvoidance.VO vo = new LocalAvoidance.VO(); vo.origin = base.transform.position + Vector3.Lerp(this.velocity * this.delta, localAvoidance.GetVelocity() * this.delta, this.responability); vo.direction = vector4.normalized; if (num3 > vector4.magnitude) { vo.angle = 1.57079637f; } else { vo.angle = (float)Math.Asin((double)(num3 / magnitude2)); } vo.limit = magnitude2 - num3; if (vo.limit < 0f) { vo.origin += vo.direction * vo.limit; vo.limit = 0f; } float num4 = Mathf.Atan2(vo.direction.z, vo.direction.x); vo.pRight = new Vector3(Mathf.Cos(num4 + vo.angle), 0f, Mathf.Sin(num4 + vo.angle)); vo.pLeft = new Vector3(Mathf.Cos(num4 - vo.angle), 0f, Mathf.Sin(num4 - vo.angle)); vo.nLeft = new Vector3(Mathf.Cos(num4 + vo.angle - 1.57079637f), 0f, Mathf.Sin(num4 + vo.angle - 1.57079637f)); vo.nRight = new Vector3(Mathf.Cos(num4 - vo.angle + 1.57079637f), 0f, Mathf.Sin(num4 - vo.angle + 1.57079637f)); this.vos.Add(vo); } } } } if (this.resType == LocalAvoidance.ResolutionType.Geometric) { for (int j = 0; j < this.vos.Count; j++) { if (this.vos[j].Contains(vector3)) { num = float.PositiveInfinity; if (this.drawGizmos) { Debug.DrawRay(vector3, Vector3.down, Color.red); } vector3 = base.transform.position; break; } } if (this.drawGizmos) { for (int k = 0; k < this.vos.Count; k++) { this.vos[k].Draw(Color.black); } } if (num == 0f) { return(vector); } List <LocalAvoidance.VOLine> list = new List <LocalAvoidance.VOLine>(); for (int l = 0; l < this.vos.Count; l++) { LocalAvoidance.VO vo2 = this.vos[l]; float num5 = (float)Math.Atan2((double)vo2.direction.z, (double)vo2.direction.x); Vector3 vector5 = vo2.origin + new Vector3((float)Math.Cos((double)(num5 + vo2.angle)), 0f, (float)Math.Sin((double)(num5 + vo2.angle))) * vo2.limit; Vector3 vector6 = vo2.origin + new Vector3((float)Math.Cos((double)(num5 - vo2.angle)), 0f, (float)Math.Sin((double)(num5 - vo2.angle))) * vo2.limit; Vector3 end = vector5 + new Vector3((float)Math.Cos((double)(num5 + vo2.angle)), 0f, (float)Math.Sin((double)(num5 + vo2.angle))) * 100f; Vector3 end2 = vector6 + new Vector3((float)Math.Cos((double)(num5 - vo2.angle)), 0f, (float)Math.Sin((double)(num5 - vo2.angle))) * 100f; int num6 = (!Polygon.Left(vo2.origin, vo2.origin + vo2.direction, base.transform.position + this.velocity)) ? 2 : 1; list.Add(new LocalAvoidance.VOLine(vo2, vector5, end, true, 1, num6 == 1)); list.Add(new LocalAvoidance.VOLine(vo2, vector6, end2, true, 2, num6 == 2)); list.Add(new LocalAvoidance.VOLine(vo2, vector5, vector6, false, 3, false)); bool flag = false; bool flag2 = false; if (!flag) { for (int m = 0; m < this.vos.Count; m++) { if (m != l && this.vos[m].Contains(vector5)) { flag = true; break; } } } if (!flag2) { for (int n = 0; n < this.vos.Count; n++) { if (n != l && this.vos[n].Contains(vector6)) { flag2 = true; break; } } } vo2.AddInt(0f, flag, 1); vo2.AddInt(0f, flag2, 2); vo2.AddInt(0f, flag, 3); vo2.AddInt(1f, flag2, 3); } for (int num7 = 0; num7 < list.Count; num7++) { for (int num8 = num7 + 1; num8 < list.Count; num8++) { LocalAvoidance.VOLine voline = list[num7]; LocalAvoidance.VOLine voline2 = list[num8]; if (voline.vo != voline2.vo) { float num9; float num10; if (Polygon.IntersectionFactor(voline.start, voline.end, voline2.start, voline2.end, out num9, out num10)) { if (num9 >= 0f && num10 >= 0f && (voline.inf || num9 <= 1f) && (voline2.inf || num10 <= 1f)) { Vector3 p = voline.start + (voline.end - voline.start) * num9; bool flag3 = voline.wrongSide || voline2.wrongSide; if (!flag3) { for (int num11 = 0; num11 < this.vos.Count; num11++) { if (this.vos[num11] != voline.vo && this.vos[num11] != voline2.vo && this.vos[num11].Contains(p)) { flag3 = true; break; } } } voline.vo.AddInt(num9, flag3, voline.id); voline2.vo.AddInt(num10, flag3, voline2.id); if (this.drawGizmos) { Debug.DrawRay(voline.start + (voline.end - voline.start) * num9, Vector3.up, (!flag3) ? Color.green : Color.magenta); } } } } } } for (int num12 = 0; num12 < this.vos.Count; num12++) { Vector3 vector7; if (this.vos[num12].FinalInts(vector2, base.transform.position + this.velocity, this.drawGizmos, out vector7)) { float sqrMagnitude = (vector7 - vector2).sqrMagnitude; if (sqrMagnitude < num) { vector3 = vector7; num = sqrMagnitude; if (this.drawGizmos) { Debug.DrawLine(vector2 + Vector3.up, vector3 + Vector3.up, Color.red); } } } } if (this.drawGizmos) { Debug.DrawLine(vector2 + Vector3.up, vector3 + Vector3.up, Color.red); } return(Vector3.ClampMagnitude(vector3 - base.transform.position, vector.magnitude * this.maxSpeedScale)); } else { if (this.resType == LocalAvoidance.ResolutionType.Sampled) { Vector3 vector8 = vector; Vector3 normalized = vector8.normalized; Vector3 vector9 = Vector3.Cross(normalized, Vector3.up); int num13 = 10; int num14 = 0; while (num14 < 10) { float num15 = (float)(3.1415926535897931 * (double)this.circlePoint / (double)num13); float num16 = (float)(3.1415926535897931 - (double)this.circlePoint * 3.1415926535897931) * 0.5f; for (int num17 = 0; num17 < num13; num17++) { float num18 = num15 * (float)num17; Vector3 vector10 = base.transform.position + vector - (vector8 * (float)Math.Sin((double)(num18 + num16)) * (float)num14 * this.circleScale + vector9 * (float)Math.Cos((double)(num18 + num16)) * (float)num14 * this.circleScale); if (this.CheckSample(vector10, this.vos)) { return(vector10 - base.transform.position); } } num14++; num13 += 2; } for (int num19 = 0; num19 < this.samples.Length; num19++) { Vector3 vector11 = base.transform.position + this.samples[num19].x * vector9 + this.samples[num19].z * normalized + this.samples[num19].y * vector8; if (this.CheckSample(vector11, this.vos)) { return(vector11 - base.transform.position); } } return(Vector3.zero); } return(Vector3.zero); } }
/** Returns if the triangle \a ABC contains the point \a p in XZ space */ public static bool ContainsPoint(Vector3 a, Vector3 b, Vector3 c, Vector3 p) { return(Polygon.IsClockwiseMargin(a, b, p) && Polygon.IsClockwiseMargin(b, c, p) && Polygon.IsClockwiseMargin(c, a, p)); }
void CalculateConvexHull() { _convexPoints = points != null?Polygon.ConvexHullXZ(points) : null; }
public static bool RunFunnel(List <Vector3> left, List <Vector3> right, List <Vector3> funnelPath) { if (left == null) { throw new ArgumentNullException("left"); } if (right == null) { throw new ArgumentNullException("right"); } if (funnelPath == null) { throw new ArgumentNullException("funnelPath"); } if (left.Count != right.Count) { throw new ArgumentException("left and right lists must have equal length"); } if (left.Count <= 3) { return(false); } while (left[1] == left[2] && right[1] == right[2]) { left.RemoveAt(1); right.RemoveAt(1); if (left.Count <= 3) { return(false); } } Vector3 vector = left[2]; if (vector == left[1]) { vector = right[2]; } while (Polygon.IsColinear(left[0], left[1], right[1]) || Polygon.Left(left[1], right[1], vector) == Polygon.Left(left[1], right[1], left[0])) { left.RemoveAt(1); right.RemoveAt(1); if (left.Count <= 3) { return(false); } vector = left[2]; if (vector == left[1]) { vector = right[2]; } } if (!Polygon.IsClockwise(left[0], left[1], right[1]) && !Polygon.IsColinear(left[0], left[1], right[1])) { List <Vector3> list = left; left = right; right = list; } funnelPath.Add(left[0]); Vector3 vector2 = left[0]; Vector3 vector3 = left[1]; Vector3 vector4 = right[1]; int num = 1; int num2 = 1; int i = 2; while (i < left.Count) { if (funnelPath.Count > 2000) { Debug.LogWarning("Avoiding infinite loop. Remove this check if you have this long paths."); break; } Vector3 vector5 = left[i]; Vector3 vector6 = right[i]; if (Polygon.TriangleArea2(vector2, vector4, vector6) < 0f) { goto IL_279; } if (vector2 == vector4 || Polygon.TriangleArea2(vector2, vector3, vector6) <= 0f) { vector4 = vector6; num = i; goto IL_279; } funnelPath.Add(vector3); vector2 = vector3; int num3 = num2; vector3 = vector2; vector4 = vector2; num2 = num3; num = num3; i = num3; IL_2DD: i++; continue; IL_279: if (Polygon.TriangleArea2(vector2, vector3, vector5) > 0f) { goto IL_2DD; } if (vector2 == vector3 || Polygon.TriangleArea2(vector2, vector4, vector5) >= 0f) { vector3 = vector5; num2 = i; goto IL_2DD; } funnelPath.Add(vector4); vector2 = vector4; num3 = num; vector3 = vector2; vector4 = vector2; num2 = num3; num = num3; i = num3; goto IL_2DD; } funnelPath.Add(left[left.Count - 1]); return(true); }
public static List <Vector3> GetPointsOnNodes(List <GraphNode> nodes, int count, float clearanceRadius = 0f) { if (nodes == null) { throw new ArgumentNullException("nodes"); } if (nodes.Count == 0) { throw new ArgumentException("no nodes passed"); } System.Random random = new System.Random(); List <Vector3> list = ListPool <Vector3> .Claim(count); clearanceRadius *= clearanceRadius; if (nodes[0] is TriangleMeshNode || nodes[0] is GridNode) { List <float> list2 = ListPool <float> .Claim(nodes.Count); float num = 0f; for (int i = 0; i < nodes.Count; i++) { TriangleMeshNode triangleMeshNode = nodes[i] as TriangleMeshNode; if (triangleMeshNode != null) { float num2 = (float)Math.Abs(Polygon.TriangleArea2(triangleMeshNode.GetVertex(0), triangleMeshNode.GetVertex(1), triangleMeshNode.GetVertex(2))); num += num2; list2.Add(num); } else { GridNode gridNode = nodes[i] as GridNode; if (gridNode != null) { GridGraph gridGraph = GridNode.GetGridGraph(gridNode.GraphIndex); float num3 = gridGraph.nodeSize * gridGraph.nodeSize; num += num3; list2.Add(num); } else { list2.Add(num); } } } for (int j = 0; j < count; j++) { int num4 = 0; int num5 = 10; bool flag = false; while (!flag) { flag = true; if (num4 >= num5) { clearanceRadius *= 0.8f; num5 += 10; if (num5 > 100) { clearanceRadius = 0f; } } float item = (float)random.NextDouble() * num; int num6 = list2.BinarySearch(item); if (num6 < 0) { num6 = ~num6; } if (num6 >= nodes.Count) { flag = false; } else { TriangleMeshNode triangleMeshNode2 = nodes[num6] as TriangleMeshNode; Vector3 vector; if (triangleMeshNode2 != null) { float num7; float num8; do { num7 = (float)random.NextDouble(); num8 = (float)random.NextDouble(); }while (num7 + num8 > 1f); vector = (Vector3)(triangleMeshNode2.GetVertex(1) - triangleMeshNode2.GetVertex(0)) * num7 + (Vector3)(triangleMeshNode2.GetVertex(2) - triangleMeshNode2.GetVertex(0)) * num8 + (Vector3)triangleMeshNode2.GetVertex(0); } else { GridNode gridNode2 = nodes[num6] as GridNode; if (gridNode2 == null) { list.Add((Vector3)nodes[num6].position); break; } GridGraph gridGraph2 = GridNode.GetGridGraph(gridNode2.GraphIndex); float num9 = (float)random.NextDouble(); float num10 = (float)random.NextDouble(); vector = (Vector3)gridNode2.position + new Vector3(num9 - 0.5f, 0f, num10 - 0.5f) * gridGraph2.nodeSize; } if (clearanceRadius > 0f) { for (int k = 0; k < list.Count; k++) { if ((list[k] - vector).sqrMagnitude < clearanceRadius) { flag = false; break; } } } if (flag) { list.Add(vector); break; } num4++; } } } ListPool <float> .Release(list2); } else { for (int l = 0; l < count; l++) { list.Add((Vector3)nodes[random.Next(nodes.Count)].position); } } return(list); }
public static Vector3 ClosestPointOnNode(TriangleMeshNode node, VInt3[] vertices, Vector3 pos) { return(Polygon.ClosestPointOnTriangle((Vector3)vertices[node.v0], (Vector3)vertices[node.v1], (Vector3)vertices[node.v2], pos)); }
/** Generates a navmesh. Based on the supplied vertices and triangles. Memory usage is about O(n) */ void GenerateNodes(Vector3[] vectorVertices, int[] triangles, out Vector3[] originalVertices, out Int3[] vertices) { Profiler.BeginSample("Init"); if (vectorVertices.Length == 0 || triangles.Length == 0) { originalVertices = vectorVertices; vertices = new Int3[0]; //graph.CreateNodes (0); nodes = new TriangleMeshNode[0]; return; } vertices = new Int3[vectorVertices.Length]; int c = 0; for (int i = 0; i < vertices.Length; i++) { vertices[i] = (Int3)matrix.MultiplyPoint3x4(vectorVertices[i]); } var hashedVerts = new Dictionary <Int3, int> (); var newVertices = new int[vertices.Length]; Profiler.EndSample(); Profiler.BeginSample("Hashing"); for (int i = 0; i < vertices.Length; i++) { if (!hashedVerts.ContainsKey(vertices[i])) { newVertices[c] = i; hashedVerts.Add(vertices[i], c); c++; } } for (int x = 0; x < triangles.Length; x++) { Int3 vertex = vertices[triangles[x]]; triangles[x] = hashedVerts[vertex]; } Int3[] totalIntVertices = vertices; vertices = new Int3[c]; originalVertices = new Vector3[c]; for (int i = 0; i < c; i++) { vertices[i] = totalIntVertices[newVertices[i]]; originalVertices[i] = vectorVertices[newVertices[i]]; } Profiler.EndSample(); Profiler.BeginSample("Constructing Nodes"); nodes = new TriangleMeshNode[triangles.Length / 3]; int graphIndex = active.astarData.GetGraphIndex(this); // Does not have to set this, it is set in ScanInternal //TriangleMeshNode.SetNavmeshHolder ((int)graphIndex,this); for (int i = 0; i < nodes.Length; i++) { nodes[i] = new TriangleMeshNode(active); TriangleMeshNode node = nodes[i]; //new MeshNode (); node.GraphIndex = (uint)graphIndex; node.Penalty = initialPenalty; node.Walkable = true; node.v0 = triangles[i * 3]; node.v1 = triangles[i * 3 + 1]; node.v2 = triangles[i * 3 + 2]; if (!Polygon.IsClockwise(vertices[node.v0], vertices[node.v1], vertices[node.v2])) { //Debug.DrawLine (vertices[node.v0],vertices[node.v1],Color.red); //Debug.DrawLine (vertices[node.v1],vertices[node.v2],Color.red); //Debug.DrawLine (vertices[node.v2],vertices[node.v0],Color.red); int tmp = node.v0; node.v0 = node.v2; node.v2 = tmp; } if (Polygon.IsColinear(vertices[node.v0], vertices[node.v1], vertices[node.v2])) { Debug.DrawLine((Vector3)vertices[node.v0], (Vector3)vertices[node.v1], Color.red); Debug.DrawLine((Vector3)vertices[node.v1], (Vector3)vertices[node.v2], Color.red); Debug.DrawLine((Vector3)vertices[node.v2], (Vector3)vertices[node.v0], Color.red); } // Make sure position is correctly set node.UpdatePositionFromVertices(); } Profiler.EndSample(); var sides = new Dictionary <Int2, TriangleMeshNode>(); for (int i = 0, j = 0; i < triangles.Length; j += 1, i += 3) { sides[new Int2(triangles[i + 0], triangles[i + 1])] = nodes[j]; sides[new Int2(triangles[i + 1], triangles[i + 2])] = nodes[j]; sides[new Int2(triangles[i + 2], triangles[i + 0])] = nodes[j]; } Profiler.BeginSample("Connecting Nodes"); var connections = new List <MeshNode> (); var connectionCosts = new List <uint> (); for (int i = 0, j = 0; i < triangles.Length; j += 1, i += 3) { connections.Clear(); connectionCosts.Clear(); TriangleMeshNode node = nodes[j]; for (int q = 0; q < 3; q++) { TriangleMeshNode other; if (sides.TryGetValue(new Int2(triangles[i + ((q + 1) % 3)], triangles[i + q]), out other)) { connections.Add(other); connectionCosts.Add((uint)(node.position - other.position).costMagnitude); } } node.connections = connections.ToArray(); node.connectionCosts = connectionCosts.ToArray(); } Profiler.EndSample(); Profiler.BeginSample("Rebuilding BBTree"); RebuildBBTree(this); Profiler.EndSample(); //Debug.Log ("Graph Generation - NavMesh - Time to compute graph "+((Time.realtimeSinceStartup-startTime)*1000F).ToString ("0")+"ms"); }
public bool ContainsPoint(TriangleMeshNode node, Vector3 pos) { return((Polygon.IsClockwise((Vector3)this.vertices[node.v0], (Vector3)this.vertices[node.v1], pos) && Polygon.IsClockwise((Vector3)this.vertices[node.v1], (Vector3)this.vertices[node.v2], pos)) && Polygon.IsClockwise((Vector3)this.vertices[node.v2], (Vector3)this.vertices[node.v0], pos)); }
public bool FindNextCorners(Vector3 origin, int startIndex, List <Vector3> funnelPath, int numCorners, out bool lastCorner) { lastCorner = false; if (left == null) { throw new System.ArgumentNullException("left"); } if (right == null) { throw new System.ArgumentNullException("right"); } if (funnelPath == null) { throw new System.ArgumentNullException("funnelPath"); } if (left.Count != right.Count) { throw new System.ArgumentException("left and right lists must have equal length"); } int diagonalCount = left.Count; if (diagonalCount == 0) { throw new System.ArgumentException("no diagonals"); } if (diagonalCount - startIndex < 3) { //Direct path funnelPath.Add(left[diagonalCount - 1]); lastCorner = true; return(true); } #if ASTARDEBUG for (int i = startIndex; i < left.Count - 1; i++) { Debug.DrawLine(left[i], left[i + 1], Color.red); Debug.DrawLine(right[i], right[i + 1], Color.magenta); Debug.DrawRay(right[i], Vector3.up, Color.magenta); } for (int i = 0; i < left.Count; i++) { Debug.DrawLine(right[i], left[i], Color.cyan); } #endif //Remove identical vertices while (left[startIndex + 1] == left[startIndex + 2] && right[startIndex + 1] == right[startIndex + 2]) { //System.Console.WriteLine ("Removing identical left and right"); //left.RemoveAt (1); //right.RemoveAt (1); startIndex++; if (diagonalCount - startIndex <= 3) { return(false); } } Vector3 swPoint = left[startIndex + 2]; if (swPoint == left[startIndex + 1]) { swPoint = right[startIndex + 2]; } //Test while (Polygon.IsColinear(origin, left[startIndex + 1], right[startIndex + 1]) || Polygon.Left(left[startIndex + 1], right[startIndex + 1], swPoint) == Polygon.Left(left[startIndex + 1], right[startIndex + 1], origin)) { #if ASTARDEBUG Debug.DrawLine(left[startIndex + 1], right[startIndex + 1], new Color(0, 0, 0, 0.5F)); Debug.DrawLine(origin, swPoint, new Color(0, 0, 0, 0.5F)); #endif //left.RemoveAt (1); //right.RemoveAt (1); startIndex++; if (diagonalCount - startIndex < 3) { //Debug.Log ("#2 " + left.Count + " - " + startIndex + " = " + (left.Count-startIndex)); //Direct path funnelPath.Add(left[diagonalCount - 1]); lastCorner = true; return(true); } swPoint = left[startIndex + 2]; if (swPoint == left[startIndex + 1]) { swPoint = right[startIndex + 2]; } } //funnelPath.Add (origin); Vector3 portalApex = origin; Vector3 portalLeft = left[startIndex + 1]; Vector3 portalRight = right[startIndex + 1]; int apexIndex = startIndex + 0; int rightIndex = startIndex + 1; int leftIndex = startIndex + 1; for (int i = startIndex + 2; i < diagonalCount; i++) { if (funnelPath.Count >= numCorners) { return(true); } if (funnelPath.Count > 2000) { Debug.LogWarning("Avoiding infinite loop. Remove this check if you have this long paths."); break; } Vector3 pLeft = left[i]; Vector3 pRight = right[i]; /*Debug.DrawLine (portalApex,portalLeft,Color.red); * Debug.DrawLine (portalApex,portalRight,Color.yellow); * Debug.DrawLine (portalApex,left,Color.cyan); * Debug.DrawLine (portalApex,right,Color.cyan);*/ if (Polygon.TriangleArea2(portalApex, portalRight, pRight) >= 0) { if (portalApex == portalRight || Polygon.TriangleArea2(portalApex, portalLeft, pRight) <= 0) { portalRight = pRight; rightIndex = i; } else { funnelPath.Add(portalLeft); portalApex = portalLeft; apexIndex = leftIndex; portalLeft = portalApex; portalRight = portalApex; leftIndex = apexIndex; rightIndex = apexIndex; i = apexIndex; continue; } } if (Polygon.TriangleArea2(portalApex, portalLeft, pLeft) <= 0) { if (portalApex == portalLeft || Polygon.TriangleArea2(portalApex, portalRight, pLeft) >= 0) { portalLeft = pLeft; leftIndex = i; } else { funnelPath.Add(portalRight); portalApex = portalRight; apexIndex = rightIndex; portalLeft = portalApex; portalRight = portalApex; leftIndex = apexIndex; rightIndex = apexIndex; i = apexIndex; continue; } } } lastCorner = true; funnelPath.Add(left[diagonalCount - 1]); return(true); }
public void RecalcConvex() { this.convexPoints = ((!this.convex) ? null : Polygon.ConvexHullXZ(this.points)); }
private void CalculateMeshContour() { if (this.mesh == null) { return; } NavmeshCut.edges.Clear(); NavmeshCut.pointers.Clear(); Vector3[] vertices = this.mesh.vertices; int[] triangles = this.mesh.triangles; for (int i = 0; i < triangles.Length; i += 3) { if (Polygon.IsClockwise(vertices[triangles[i]], vertices[triangles[i + 1]], vertices[triangles[i + 2]])) { int num = triangles[i]; triangles[i] = triangles[i + 2]; triangles[i + 2] = num; } NavmeshCut.edges[new Int2(triangles[i], triangles[i + 1])] = i; NavmeshCut.edges[new Int2(triangles[i + 1], triangles[i + 2])] = i; NavmeshCut.edges[new Int2(triangles[i + 2], triangles[i])] = i; } for (int j = 0; j < triangles.Length; j += 3) { for (int k = 0; k < 3; k++) { if (!NavmeshCut.edges.ContainsKey(new Int2(triangles[j + (k + 1) % 3], triangles[j + k % 3]))) { NavmeshCut.pointers[triangles[j + k % 3]] = triangles[j + (k + 1) % 3]; } } } List <Vector3[]> list = new List <Vector3[]>(); List <Vector3> list2 = ListPool <Vector3> .Claim(); for (int l = 0; l < vertices.Length; l++) { if (NavmeshCut.pointers.ContainsKey(l)) { list2.Clear(); int num2 = l; do { int num3 = NavmeshCut.pointers[num2]; if (num3 == -1) { break; } NavmeshCut.pointers[num2] = -1; list2.Add(vertices[num2]); num2 = num3; if (num2 == -1) { goto Block_9; } }while (num2 != l); IL_20C: if (list2.Count > 0) { list.Add(list2.ToArray()); goto IL_227; } goto IL_227; Block_9: Debug.LogError("Invalid Mesh '" + this.mesh.name + " in " + base.gameObject.name); goto IL_20C; } IL_227 :; } ListPool <Vector3> .Release(list2); this.contours = list.ToArray(); }
public List <Vector3> SmoothOffsetSimple(List <Vector3> path) { if (path.Count <= 2 || this.iterations <= 0) { return(path); } if (this.iterations > 12) { Debug.LogWarning("A very high iteration count was passed, won't let this one through"); return(path); } int num = (path.Count - 2) * (int)Mathf.Pow(2f, (float)this.iterations) + 2; List <Vector3> list = ListPool <Vector3> .Claim(num); List <Vector3> list2 = ListPool <Vector3> .Claim(num); for (int i = 0; i < num; i++) { list.Add(Vector3.zero); list2.Add(Vector3.zero); } for (int j = 0; j < path.Count; j++) { list[j] = path[j]; } for (int k = 0; k < this.iterations; k++) { int num2 = (path.Count - 2) * (int)Mathf.Pow(2f, (float)k) + 2; List <Vector3> list3 = list; list = list2; list2 = list3; for (int l = 0; l < num2 - 1; l++) { Vector3 vector = list2[l]; Vector3 vector2 = list2[l + 1]; Vector3 normalized = Vector3.Cross(vector2 - vector, Vector3.up).normalized; bool flag = false; bool flag2 = false; bool flag3 = false; bool flag4 = false; if (l != 0 && !Polygon.IsColinear(vector, vector2, list2[l - 1])) { flag3 = true; flag = Polygon.Left(vector, vector2, list2[l - 1]); } if (l < num2 - 1 && !Polygon.IsColinear(vector, vector2, list2[l + 2])) { flag4 = true; flag2 = Polygon.Left(vector, vector2, list2[l + 2]); } if (flag3) { list[l * 2] = vector + ((!flag) ? (-normalized * this.offset * 1f) : (normalized * this.offset * 1f)); } else { list[l * 2] = vector; } if (flag4) { list[l * 2 + 1] = vector2 + ((!flag2) ? (-normalized * this.offset * 1f) : (normalized * this.offset * 1f)); } else { list[l * 2 + 1] = vector2; } } list[(path.Count - 2) * (int)Mathf.Pow(2f, (float)(k + 1)) + 2 - 1] = list2[num2 - 1]; } ListPool <Vector3> .Release(list2); return(list); }
/** Calculate a funnel path from the \a left and \a right portal lists. * The result will be appended to \a funnelPath */ public bool RunFunnel(List <Vector3> left, List <Vector3> right, List <Vector3> funnelPath) { if (left == null) { throw new System.ArgumentNullException("left"); } if (right == null) { throw new System.ArgumentNullException("right"); } if (funnelPath == null) { throw new System.ArgumentNullException("funnelPath"); } if (left.Count != right.Count) { throw new System.ArgumentException("left and right lists must have equal length"); } if (left.Count <= 3) { return(false); } //Remove identical vertices while (left[1] == left[2] && right[1] == right[2]) { //System.Console.WriteLine ("Removing identical left and right"); left.RemoveAt(1); right.RemoveAt(1); if (left.Count <= 3) { return(false); } } Vector3 swPoint = left[2]; if (swPoint == left[1]) { swPoint = right[2]; } //Test while (Polygon.IsColinear(left[0], left[1], right[1]) || Polygon.Left(left[1], right[1], swPoint) == Polygon.Left(left[1], right[1], left[0])) { left.RemoveAt(1); right.RemoveAt(1); if (left.Count <= 3) { return(false); } swPoint = left[2]; if (swPoint == left[1]) { swPoint = right[2]; } } //Switch left and right to really be on the "left" and "right" sides if (!Polygon.IsClockwise(left[0], left[1], right[1]) && !Polygon.IsColinear(left[0], left[1], right[1])) { //System.Console.WriteLine ("Wrong Side 2"); List <Vector3> tmp = left; left = right; right = tmp; } funnelPath.Add(left[0]); Vector3 portalApex = left[0]; Vector3 portalLeft = left[1]; Vector3 portalRight = right[1]; int apexIndex = 0; int rightIndex = 1; int leftIndex = 1; for (int i = 2; i < left.Count; i++) { if (funnelPath.Count > 2000) { Debug.LogWarning("Avoiding infinite loop. Remove this check if you have this long paths."); break; } Vector3 pLeft = left[i]; Vector3 pRight = right[i]; /*Debug.DrawLine (portalApex,portalLeft,Color.red); * Debug.DrawLine (portalApex,portalRight,Color.yellow); * Debug.DrawLine (portalApex,left,Color.cyan); * Debug.DrawLine (portalApex,right,Color.cyan);*/ if (Polygon.TriangleArea2(portalApex, portalRight, pRight) >= 0) { if (portalApex == portalRight || Polygon.TriangleArea2(portalApex, portalLeft, pRight) <= 0) { portalRight = pRight; rightIndex = i; } else { funnelPath.Add(portalLeft); portalApex = portalLeft; apexIndex = leftIndex; portalLeft = portalApex; portalRight = portalApex; leftIndex = apexIndex; rightIndex = apexIndex; i = apexIndex; continue; } } if (Polygon.TriangleArea2(portalApex, portalLeft, pLeft) <= 0) { if (portalApex == portalLeft || Polygon.TriangleArea2(portalApex, portalRight, pLeft) >= 0) { portalLeft = pLeft; leftIndex = i; } else { funnelPath.Add(portalRight); portalApex = portalRight; apexIndex = rightIndex; portalLeft = portalApex; portalRight = portalApex; leftIndex = apexIndex; rightIndex = apexIndex; i = apexIndex; continue; } } } funnelPath.Add(left[left.Count - 1]); return(true); }
public override Vector3 ClosestPointOnNode(Vector3 p) { INavmeshHolder navmeshHolder = TriangleMeshNode.GetNavmeshHolder(base.GraphIndex); return(Polygon.ClosestPointOnTriangle((Vector3)navmeshHolder.GetVertex(this.v0), (Vector3)navmeshHolder.GetVertex(this.v1), (Vector3)navmeshHolder.GetVertex(this.v2), p)); }
// Token: 0x0600266D RID: 9837 RVA: 0x001A7318 File Offset: 0x001A5518 public List <Vector3> SmoothSimple(List <Vector3> path) { if (path.Count < 2) { return(path); } List <Vector3> list; if (this.uniformLength) { this.maxSegmentLength = Mathf.Max(this.maxSegmentLength, 0.005f); float num = 0f; for (int i = 0; i < path.Count - 1; i++) { num += Vector3.Distance(path[i], path[i + 1]); } list = ListPool <Vector3> .Claim(Mathf.FloorToInt(num / this.maxSegmentLength) + 2); float num2 = 0f; for (int j = 0; j < path.Count - 1; j++) { Vector3 a = path[j]; Vector3 b = path[j + 1]; float num3 = Vector3.Distance(a, b); while (num2 < num3) { list.Add(Vector3.Lerp(a, b, num2 / num3)); num2 += this.maxSegmentLength; } num2 -= num3; } list.Add(path[path.Count - 1]); } else { this.subdivisions = Mathf.Max(this.subdivisions, 0); if (this.subdivisions > 10) { Debug.LogWarning("Very large number of subdivisions. Cowardly refusing to subdivide every segment into more than " + (1 << this.subdivisions) + " subsegments"); this.subdivisions = 10; } int num4 = 1 << this.subdivisions; list = ListPool <Vector3> .Claim((path.Count - 1) *num4 + 1); Polygon.Subdivide(path, list, num4); } if (this.strength > 0f) { for (int k = 0; k < this.iterations; k++) { Vector3 a2 = list[0]; for (int l = 1; l < list.Count - 1; l++) { Vector3 vector = list[l]; list[l] = Vector3.Lerp(vector, (a2 + list[l + 1]) / 2f, this.strength); a2 = vector; } } } return(list); }