/** Sets the internal navmesh holder for a given graph index. * \warning Internal method */ public static void SetNavmeshHolder (int graphIndex, INavmeshHolder graph) { if (_navmeshHolders.Length <= graphIndex) { var gg = new INavmeshHolder[graphIndex+1]; for (int i=0;i<_navmeshHolders.Length;i++) gg[i] = _navmeshHolders[i]; _navmeshHolders = gg; } _navmeshHolders[graphIndex] = graph; }
public static void SetNavmeshHolder(int graphIndex, INavmeshHolder graph) { if (TriangleMeshNode._navmeshHolders.Length <= graphIndex) { INavmeshHolder[] array = new INavmeshHolder[graphIndex + 1]; for (int i = 0; i < TriangleMeshNode._navmeshHolders.Length; i++) { array[i] = TriangleMeshNode._navmeshHolders[i]; } TriangleMeshNode._navmeshHolders = array; } TriangleMeshNode._navmeshHolders[graphIndex] = graph; }
public static void SetNavmeshHolder(int graphIndex, INavmeshHolder graph) { if (_navmeshHolders.Length <= graphIndex) { INavmeshHolder[] gg = new INavmeshHolder[graphIndex + 1]; for (int i = 0; i < _navmeshHolders.Length; i++) { gg[i] = _navmeshHolders[i]; } _navmeshHolders = gg; } _navmeshHolders[graphIndex] = graph; }
public override VInt3 GetVertex(int i) { VInt3 result = VInt3.zero; try { INavmeshHolder navmeshHolder = TriangleMeshNode.GetNavmeshHolder(this.DataGroupIndex, base.GraphIndex); result = navmeshHolder.GetVertex(this.GetVertexIndex(i)); } catch (Exception) { } return(result); }
public override Vector3 RandomPointOnSurface() { float value; float value2; do { value = UnityEngine.Random.value; value2 = UnityEngine.Random.value; }while (value + value2 > 1f); INavmeshHolder navmeshHolder = TriangleMeshNode.GetNavmeshHolder(base.GraphIndex); return((Vector3)(navmeshHolder.GetVertex(this.v1) - navmeshHolder.GetVertex(this.v0)) * value + (Vector3)(navmeshHolder.GetVertex(this.v2) - navmeshHolder.GetVertex(this.v0)) * value2 + (Vector3)navmeshHolder.GetVertex(this.v0)); }
/// <summary> /// Sets the internal navmesh holder for a given graph index. /// Warning: Internal method /// </summary> public static void SetNavmeshHolder(int graphIndex, INavmeshHolder graph) { // We need to lock to make sure that // the resize operation is thread safe lock (lockObject) { if (graphIndex >= _navmeshHolders.Length) { var gg = new INavmeshHolder[graphIndex + 1]; _navmeshHolders.CopyTo(gg, 0); _navmeshHolders = gg; } _navmeshHolders[graphIndex] = graph; } }
public override Vector3 RandomPointOnSurface() { float num; float num2; do { num = UnityEngine.Random.value; num2 = UnityEngine.Random.value; }while ((num + num2) > 1f); INavmeshHolder navmeshHolder = GetNavmeshHolder(base.GraphIndex); return(((Vector3)((((Vector3)(navmeshHolder.GetVertex(this.v1) - navmeshHolder.GetVertex(this.v0))) * num) + (((Vector3)(navmeshHolder.GetVertex(this.v2) - navmeshHolder.GetVertex(this.v0))) * num2))) + ((Vector3)navmeshHolder.GetVertex(this.v0))); }
// Token: 0x060025EC RID: 9708 RVA: 0x001A65D4 File Offset: 0x001A47D4 public static void SetNavmeshHolder(int graphIndex, INavmeshHolder graph) { object obj = TriangleMeshNode.lockObject; lock (obj) { if (graphIndex >= TriangleMeshNode._navmeshHolders.Length) { INavmeshHolder[] array = new INavmeshHolder[graphIndex + 1]; TriangleMeshNode._navmeshHolders.CopyTo(array, 0); TriangleMeshNode._navmeshHolders = array; } TriangleMeshNode._navmeshHolders[graphIndex] = graph; } }
public bool IsVertex(VInt3 p, out int index) { INavmeshHolder navmeshHolder = GetNavmeshHolder(base.DataGroupIndex, base.GraphIndex); index = -1; if (navmeshHolder.GetVertex(this.v0).IsEqualXZ(ref p)) { index = 0; } else if (navmeshHolder.GetVertex(this.v1).IsEqualXZ(ref p)) { index = 1; } else if (navmeshHolder.GetVertex(this.v2).IsEqualXZ(ref p)) { index = 2; } return(index != -1); }
public override Vector3 ClosestPointOnNodeXZ(Vector3 p) { // Get the object holding the vertex data for this node // This is usually a graph or a recast graph tile INavmeshHolder g = GetNavmeshHolder(GraphIndex); // Get all 3 vertices for this node Int3 tp1 = g.GetVertex(v0); Int3 tp2 = g.GetVertex(v1); Int3 tp3 = g.GetVertex(v2); Vector2 closest = Polygon.ClosestPointOnTriangle( new Vector2(tp1.x * Int3.PrecisionFactor, tp1.z * Int3.PrecisionFactor), new Vector2(tp2.x * Int3.PrecisionFactor, tp2.z * Int3.PrecisionFactor), new Vector2(tp3.x * Int3.PrecisionFactor, tp3.z * Int3.PrecisionFactor), new Vector2(p.x, p.z) ); return(new Vector3(closest.x, p.y, closest.y)); }
/** Sets the internal navmesh holder for a given graph index. * \warning Internal method */ public static void SetNavmeshHolder(int graphIndex, INavmeshHolder graph) { if (_navmeshHolders.Length <= graphIndex) { // We need to lock and then check again to make sure // that this the resize operation is thread safe lock (lockObject) { if (_navmeshHolders.Length <= graphIndex) { var gg = new INavmeshHolder[graphIndex + 1]; for (int i = 0; i < _navmeshHolders.Length; i++) { gg[i] = _navmeshHolders[i]; } _navmeshHolders = gg; } } } _navmeshHolders[graphIndex] = graph; }
public override Vector3d ClosestPointOnNodeXZ(Vector3d p) { // Get the object holding the vertex data for this node // This is usually a graph or a recast graph tile INavmeshHolder g = GetNavmeshHolder(GraphIndex); // Get all 3 vertices for this node Int3 tp1 = g.GetVertex(v0); Int3 tp2 = g.GetVertex(v1); Int3 tp3 = g.GetVertex(v2); Vector2d closest = Polygon.ClosestPointOnTriangle( new Vector2d(((long)tp1.x) * FixedMath.One / 1000, ((long)tp1.z) * FixedMath.One / 1000), new Vector2d(((long)tp2.x) * FixedMath.One / 1000, ((long)tp2.z) * FixedMath.One / 1000), new Vector2d(((long)tp3.x) * FixedMath.One / 1000, ((long)tp3.z) * FixedMath.One / 1000), new Vector2d(p.x, p.z) ); return(new Vector3d(closest.x, 0, closest.y)); }
public static void SetNavmeshHolder(int graphIndex, INavmeshHolder graph) { if (_navmeshHolders.Length <= graphIndex) { object lockObject = TriangleMeshNode.lockObject; lock (lockObject) { if (_navmeshHolders.Length <= graphIndex) { INavmeshHolder[] holderArray = new INavmeshHolder[graphIndex + 1]; for (int i = 0; i < _navmeshHolders.Length; i++) { holderArray[i] = _navmeshHolders[i]; } _navmeshHolders = holderArray; } } } _navmeshHolders[graphIndex] = graph; }
public override bool ContainsPoint(VInt3 p) { INavmeshHolder navmeshHolder = GetNavmeshHolder(base.DataGroupIndex, base.GraphIndex); VInt3 vertex = navmeshHolder.GetVertex(this.v0); VInt3 num2 = navmeshHolder.GetVertex(this.v1); VInt3 num3 = navmeshHolder.GetVertex(this.v2); if ((((num2.x - vertex.x) * (p.z - vertex.z)) - ((p.x - vertex.x) * (num2.z - vertex.z))) > 0L) { return(false); } if ((((num3.x - num2.x) * (p.z - num2.z)) - ((p.x - num2.x) * (num3.z - num2.z))) > 0L) { return(false); } if ((((vertex.x - num3.x) * (p.z - num3.z)) - ((p.x - num3.x) * (vertex.z - num3.z))) > 0L) { return(false); } return(true); }
public static void SetNavmeshHolder(int dataGroupIndex, int graphIndex, INavmeshHolder graph) { if (dataGroupIndex >= _navmeshHolders.Count) { for (int i = _navmeshHolders.Count; i <= dataGroupIndex; i++) { _navmeshHolders.Add(new INavmeshHolder[0]); } } if (_navmeshHolders[dataGroupIndex].Length <= graphIndex) { INavmeshHolder[] holderArray = new INavmeshHolder[graphIndex + 1]; INavmeshHolder[] holderArray2 = _navmeshHolders[dataGroupIndex]; for (int j = 0; j < holderArray2.Length; j++) { holderArray[j] = holderArray2[j]; } _navmeshHolders[dataGroupIndex] = holderArray; } _navmeshHolders[dataGroupIndex][graphIndex] = (INavmeshHolder[])graph; }
public static void SetNavmeshHolder(int dataGroupIndex, int graphIndex, INavmeshHolder graph) { if (dataGroupIndex >= TriangleMeshNode._navmeshHolders.Count) { for (int i = TriangleMeshNode._navmeshHolders.Count; i <= dataGroupIndex; i++) { TriangleMeshNode._navmeshHolders.Add(new INavmeshHolder[0]); } } if (TriangleMeshNode._navmeshHolders[dataGroupIndex].Length <= graphIndex) { INavmeshHolder[] array = new INavmeshHolder[graphIndex + 1]; INavmeshHolder[] array2 = TriangleMeshNode._navmeshHolders[dataGroupIndex]; for (int j = 0; j < array2.Length; j++) { array[j] = array2[j]; } TriangleMeshNode._navmeshHolders[dataGroupIndex] = array; } TriangleMeshNode._navmeshHolders[dataGroupIndex][graphIndex] = graph; }
public bool GetPortal(GraphNode toNode, System.Collections.Generic.List <Vector3> left, System.Collections.Generic.List <Vector3> right, bool backwards, out int aIndex, out int bIndex) { aIndex = -1; bIndex = -1; //If the nodes are in different graphs, this function has no idea on how to find a shared edge. if (backwards || toNode.GraphIndex != GraphIndex) { return(false); } // Since the nodes are in the same graph, they are both TriangleMeshNodes // So we don't need to care about other types of nodes var toTriNode = toNode as TriangleMeshNode; var edge = SharedEdge(toTriNode); // A connection was found, but it specifically didn't use an edge if (edge == 0xFF) { return(false); } // No connection was found between the nodes // Check if there is a node link that connects them if (edge == -1) { #if !ASTAR_NO_POINT_GRAPH if (connections != null) { for (int i = 0; i < connections.Length; i++) { if (connections[i].node.GraphIndex != GraphIndex) { var mid = connections[i].node as NodeLink3Node; if (mid != null && mid.GetOther(this) == toTriNode) { // We have found a node which is connected through a NodeLink3Node mid.GetPortal(toTriNode, left, right, false); return(true); } } } } #endif return(false); } aIndex = edge; bIndex = (edge + 1) % GetVertexCount(); // Get the vertices of the shared edge for the first node Int3 v1a = GetVertex(edge); Int3 v1b = GetVertex((edge + 1) % GetVertexCount()); // Get tile indices int tileIndex1 = (GetVertexIndex(0) >> NavmeshBase.TileIndexOffset) & NavmeshBase.TileIndexMask; int tileIndex2 = (toTriNode.GetVertexIndex(0) >> NavmeshBase.TileIndexOffset) & NavmeshBase.TileIndexMask; if (tileIndex1 != tileIndex2) { // When the nodes are in different tiles, the edges might not be completely identical // so another technique is needed. // Get the tile coordinates, from them we can figure out which edge is going to be shared int x1, x2, z1, z2, coord; INavmeshHolder nm = GetNavmeshHolder(GraphIndex); nm.GetTileCoordinates(tileIndex1, out x1, out z1); nm.GetTileCoordinates(tileIndex2, out x2, out z2); if (System.Math.Abs(x1 - x2) == 1) { coord = 2; } else if (System.Math.Abs(z1 - z2) == 1) { coord = 0; } else { return(false); // Tiles are not adjacent. This is likely a custom connection between two nodes. } var otherEdge = toTriNode.SharedEdge(this); // A connection was found, but it specifically didn't use an edge. This is odd since the connection in the other direction did use an edge if (otherEdge == 0xFF) { throw new System.Exception("Connection used edge in one direction, but not in the other direction. Has the wrong overload of AddConnection been used?"); } // If it is -1 then it must be a one-way connection. Fall back to using the whole edge if (otherEdge != -1) { // When the nodes are in different tiles, they might not share exactly the same edge // so we clamp the portal to the segment of the edges which they both have. int mincoord = System.Math.Min(v1a[coord], v1b[coord]); int maxcoord = System.Math.Max(v1a[coord], v1b[coord]); // Get the vertices of the shared edge for the second node Int3 v2a = toTriNode.GetVertex(otherEdge); Int3 v2b = toTriNode.GetVertex((otherEdge + 1) % toTriNode.GetVertexCount()); mincoord = System.Math.Max(mincoord, System.Math.Min(v2a[coord], v2b[coord])); maxcoord = System.Math.Min(maxcoord, System.Math.Max(v2a[coord], v2b[coord])); if (v1a[coord] < v1b[coord]) { v1a[coord] = mincoord; v1b[coord] = maxcoord; } else { v1a[coord] = maxcoord; v1b[coord] = mincoord; } } } if (left != null) { // All triangles should be laid out in clockwise order so v1b is the rightmost vertex (seen from this node) left.Add((Vector3)v1a); right.Add((Vector3)v1b); } return(true); }
public override Vector3 ClosestPointOnNodeXZ(Vector3 _p) { // Get the object holding the vertex data for this node // This is usually a graph or a recast graph tile INavmeshHolder g = GetNavmeshHolder(GraphIndex); // Get all 3 vertices for this node Int3 tp1 = g.GetVertex(v0); Int3 tp2 = g.GetVertex(v1); Int3 tp3 = g.GetVertex(v2); // We need the point as an Int3 Int3 p = (Int3)_p; // Save the original y coordinate, we will return a point with the same y coordinate int oy = p.y; // Assumes the triangle vertices are laid out in (counter?)clockwise order tp1.y = 0; tp2.y = 0; tp3.y = 0; p.y = 0; if ((long)(tp2.x - tp1.x) * (long)(p.z - tp1.z) - (long)(p.x - tp1.x) * (long)(tp2.z - tp1.z) > 0) { float f = Mathf.Clamp01(AstarMath.NearestPointFactor(tp1, tp2, p)); return(new Vector3(tp1.x + (tp2.x - tp1.x) * f, oy, tp1.z + (tp2.z - tp1.z) * f) * Int3.PrecisionFactor); } else if ((long)(tp3.x - tp2.x) * (long)(p.z - tp2.z) - (long)(p.x - tp2.x) * (long)(tp3.z - tp2.z) > 0) { float f = Mathf.Clamp01(AstarMath.NearestPointFactor(tp2, tp3, p)); return(new Vector3(tp2.x + (tp3.x - tp2.x) * f, oy, tp2.z + (tp3.z - tp2.z) * f) * Int3.PrecisionFactor); } else if ((long)(tp1.x - tp3.x) * (long)(p.z - tp3.z) - (long)(p.x - tp3.x) * (long)(tp1.z - tp3.z) > 0) { float f = Mathf.Clamp01(AstarMath.NearestPointFactor(tp3, tp1, p)); return(new Vector3(tp3.x + (tp1.x - tp3.x) * f, oy, tp3.z + (tp1.z - tp3.z) * f) * Int3.PrecisionFactor); } else { return(_p); } /* * Equivalent to the above, but the above uses manual inlining * if (!Polygon.Left (tp1, tp2, p)) { * float f = Mathf.Clamp01 (AstarMath.NearestPointFactor (tp1, tp2, p)); * return new Vector3(tp1.x + (tp2.x-tp1.x)*f, oy, tp1.z + (tp2.z-tp1.z)*f)*Int3.PrecisionFactor; * } else if (!Polygon.Left (tp2, tp3, p)) { * float f = Mathf.Clamp01 (AstarMath.NearestPointFactor (tp2, tp3, p)); * return new Vector3(tp2.x + (tp3.x-tp2.x)*f, oy, tp2.z + (tp3.z-tp2.z)*f)*Int3.PrecisionFactor; * } else if (!Polygon.Left (tp3, tp1, p)) { * float f = Mathf.Clamp01 (AstarMath.NearestPointFactor (tp3, tp1, p)); * return new Vector3(tp3.x + (tp1.x-tp3.x)*f, oy, tp3.z + (tp1.z-tp3.z)*f)*Int3.PrecisionFactor; * } else { * return _p; * }*/ /* Almost equivalent to the above, but this is slower * Vector3 tp1 = (Vector3)g.GetVertex(v0); * Vector3 tp2 = (Vector3)g.GetVertex(v1); * Vector3 tp3 = (Vector3)g.GetVertex(v2); * tp1.y = 0; * tp2.y = 0; * tp3.y = 0; * _p.y = 0; * return Pathfinding.Polygon.ClosestPointOnTriangle (tp1,tp2,tp3,_p);*/ }
/** This performs a linear search through all polygons returning the closest one. * This will fill the NNInfo with .node for the closest node not necessarily complying with the NNConstraint, and .constrainedNode with the closest node * complying with the NNConstraint. * \see GetNearestForce(Node[],Int3[],Vector3,NNConstraint,bool) */ public static NNInfo GetNearestForceBoth(NavGraph graph, INavmeshHolder navmesh, Vector3 position, NNConstraint constraint, bool accurateNearestNode) { Int3 pos = (Int3)position; float minDist = -1; GraphNode minNode = null; float minConstDist = -1; GraphNode minConstNode = null; float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity; GraphNodeDelegateCancelable del = delegate(GraphNode _node) { TriangleMeshNode node = _node as TriangleMeshNode; if (accurateNearestNode) { Vector3 closest = node.ClosestPointOnNode(position); float dist = ((Vector3)pos - closest).sqrMagnitude; if (minNode == null || dist < minDist) { minDist = dist; minNode = node; } if (dist < maxDistSqr && constraint.Suitable(node)) { if (minConstNode == null || dist < minConstDist) { minConstDist = dist; minConstNode = node; } } } else { if (!node.ContainsPoint((Int3)position)) { float dist = (node.position - pos).sqrMagnitude; if (minNode == null || dist < minDist) { minDist = dist; minNode = node; } if (dist < maxDistSqr && constraint.Suitable(node)) { if (minConstNode == null || dist < minConstDist) { minConstDist = dist; minConstNode = node; } } } else { int dist = AstarMath.Abs(node.position.y - pos.y); if (minNode == null || dist < minDist) { minDist = dist; minNode = node; } if (dist < maxDistSqr && constraint.Suitable(node)) { if (minConstNode == null || dist < minConstDist) { minConstDist = dist; minConstNode = node; } } } } return(true); }; graph.GetNodes(del); NNInfo nninfo = new NNInfo(minNode); //Find the point closest to the nearest triangle if (nninfo.node != null) { TriangleMeshNode node = nninfo.node as TriangleMeshNode; //minNode2 as MeshNode; Vector3 clP = node.ClosestPointOnNode(position); nninfo.clampedPosition = clP; } nninfo.constrainedNode = minConstNode; if (nninfo.constrainedNode != null) { TriangleMeshNode node = nninfo.constrainedNode as TriangleMeshNode; //minNode2 as MeshNode; Vector3 clP = node.ClosestPointOnNode(position); nninfo.constClampedPosition = clP; } return(nninfo); }
/** Set the position of this node to the average of its 3 vertices */ public void UpdatePositionFromVertices() { INavmeshHolder g = GetNavmeshHolder(GraphIndex); position = (g.GetVertex(v0) + g.GetVertex(v1) + g.GetVertex(v2)) * 0.333333f; }
public override Vector3 ClosestPointOnNode(Vector3 p) { INavmeshHolder g = GetNavmeshHolder(GraphIndex); return(Pathfinding.Polygon.ClosestPointOnTriangle((Vector3)g.GetVertex(v0), (Vector3)g.GetVertex(v1), (Vector3)g.GetVertex(v2), p)); }
public void UpdatePositionFromVertices() { INavmeshHolder navmeshHolder = GetNavmeshHolder(base.DataGroupIndex, base.GraphIndex); base.position = (VInt3)(((navmeshHolder.GetVertex(this.v0) + navmeshHolder.GetVertex(this.v1)) + navmeshHolder.GetVertex(this.v2)) * 0.333333f); }
public static NNInfo GetNearestForceBoth(NavGraph graph, INavmeshHolder navmesh, Vector3 position, NNConstraint constraint, bool accurateNearestNode) { Int3 pos = (Int3)position; float minDist = -1f; GraphNode minNode = null; float minConstDist = -1f; GraphNode minConstNode = null; float maxDistSqr = (!constraint.constrainDistance) ? float.PositiveInfinity : AstarPath.active.maxNearestNodeDistanceSqr; GraphNodeDelegateCancelable del = delegate(GraphNode _node) { TriangleMeshNode triangleMeshNode3 = _node as TriangleMeshNode; if (accurateNearestNode) { Vector3 b = triangleMeshNode3.ClosestPointOnNode(position); float sqrMagnitude = ((Vector3)pos - b).sqrMagnitude; if (minNode == null || sqrMagnitude < minDist) { minDist = sqrMagnitude; minNode = triangleMeshNode3; } if (sqrMagnitude < maxDistSqr && constraint.Suitable(triangleMeshNode3) && (minConstNode == null || sqrMagnitude < minConstDist)) { minConstDist = sqrMagnitude; minConstNode = triangleMeshNode3; } } else if (!triangleMeshNode3.ContainsPoint((Int3)position)) { float sqrMagnitude2 = (triangleMeshNode3.position - pos).sqrMagnitude; if (minNode == null || sqrMagnitude2 < minDist) { minDist = sqrMagnitude2; minNode = triangleMeshNode3; } if (sqrMagnitude2 < maxDistSqr && constraint.Suitable(triangleMeshNode3) && (minConstNode == null || sqrMagnitude2 < minConstDist)) { minConstDist = sqrMagnitude2; minConstNode = triangleMeshNode3; } } else { int num = AstarMath.Abs(triangleMeshNode3.position.y - pos.y); if (minNode == null || (float)num < minDist) { minDist = (float)num; minNode = triangleMeshNode3; } if ((float)num < maxDistSqr && constraint.Suitable(triangleMeshNode3) && (minConstNode == null || (float)num < minConstDist)) { minConstDist = (float)num; minConstNode = triangleMeshNode3; } } return(true); }; graph.GetNodes(del); NNInfo result = new NNInfo(minNode); if (result.node != null) { TriangleMeshNode triangleMeshNode = result.node as TriangleMeshNode; Vector3 clampedPosition = triangleMeshNode.ClosestPointOnNode(position); result.clampedPosition = clampedPosition; } result.constrainedNode = minConstNode; if (result.constrainedNode != null) { TriangleMeshNode triangleMeshNode2 = result.constrainedNode as TriangleMeshNode; Vector3 constClampedPosition = triangleMeshNode2.ClosestPointOnNode(position); result.constClampedPosition = constClampedPosition; } return(result); }
/** This performs a linear search through all polygons returning the closest one. * This will fill the NNInfo with .node for the closest node not necessarily complying with the NNConstraint, and .constrainedNode with the closest node * complying with the NNConstraint. * \see GetNearestForce(Node[],Int3[],Vector3,NNConstraint,bool) */ public static NNInfo GetNearestForceBoth (NavGraph graph, INavmeshHolder navmesh, Vector3 position, NNConstraint constraint, bool accurateNearestNode) { Int3 pos = (Int3)position; float minDist = -1; GraphNode minNode = null; float minConstDist = -1; GraphNode minConstNode = null; float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity; GraphNodeDelegateCancelable del = delegate (GraphNode _node) { TriangleMeshNode node = _node as TriangleMeshNode; if (accurateNearestNode) { Vector3 closest = node.ClosestPointOnNode (position); float dist = ((Vector3)pos-closest).sqrMagnitude; if (minNode == null || dist < minDist) { minDist = dist; minNode = node; } if (dist < maxDistSqr && constraint.Suitable (node)) { if (minConstNode == null || dist < minConstDist) { minConstDist = dist; minConstNode = node; } } } else { if (!node.ContainsPoint ((Int3)position)) { float dist = (node.position-pos).sqrMagnitude; if (minNode == null || dist < minDist) { minDist = dist; minNode = node; } if (dist < maxDistSqr && constraint.Suitable (node)) { if (minConstNode == null || dist < minConstDist) { minConstDist = dist; minConstNode = node; } } } else { #if ASTARDEBUG Debug.DrawLine ((Vector3)vertices[node.v0],(Vector3)vertices[node.v1],Color.blue); Debug.DrawLine ((Vector3)vertices[node.v1],(Vector3)vertices[node.v2],Color.blue); Debug.DrawLine ((Vector3)vertices[node.v2],(Vector3)vertices[node.v0],Color.blue); #endif int dist = AstarMath.Abs (node.position.y-pos.y); if (minNode == null || dist < minDist) { minDist = dist; minNode = node; } if (dist < maxDistSqr && constraint.Suitable (node)) { if (minConstNode == null || dist < minConstDist) { minConstDist = dist; minConstNode = node; } } } } return true; }; graph.GetNodes (del); NNInfo nninfo = new NNInfo (minNode); //Find the point closest to the nearest triangle if (nninfo.node != null) { TriangleMeshNode node = nninfo.node as TriangleMeshNode;//minNode2 as MeshNode; Vector3 clP = node.ClosestPointOnNode (position); nninfo.clampedPosition = clP; } nninfo.constrainedNode = minConstNode; if (nninfo.constrainedNode != null) { TriangleMeshNode node = nninfo.constrainedNode as TriangleMeshNode;//minNode2 as MeshNode; Vector3 clP = node.ClosestPointOnNode (position); nninfo.constClampedPosition = clP; } return nninfo; }
public bool GetPortal(GraphNode _other, System.Collections.Generic.List <Vector3> left, System.Collections.Generic.List <Vector3> right, bool backwards, out int aIndex, out int bIndex) { aIndex = -1; bIndex = -1; //If the nodes are in different graphs, this function has no idea on how to find a shared edge. if (_other.GraphIndex != GraphIndex) { return(false); } TriangleMeshNode other = _other as TriangleMeshNode; //Get tile indices int tileIndex = (GetVertexIndex(0) >> RecastGraph.TileIndexOffset) & RecastGraph.TileIndexMask; int tileIndex2 = (other.GetVertexIndex(0) >> RecastGraph.TileIndexOffset) & RecastGraph.TileIndexMask; //When the nodes are in different tiles, the edges might not be completely identical //so another technique is needed //Only do this on recast graphs if (tileIndex != tileIndex2 && (GetNavmeshHolder(GraphIndex) is RecastGraph)) { for (int i = 0; i < connections.Length; i++) { if (connections[i].GraphIndex != GraphIndex) { #if !ASTAR_NO_POINT_GRAPH NodeLink3Node mid = connections[i] as NodeLink3Node; if (mid != null && mid.GetOther(this) == other) { // We have found a node which is connected through a NodeLink3Node if (left != null) { mid.GetPortal(other, left, right, false); return(true); } } #endif } } //Get the tile coordinates, from them we can figure out which edge is going to be shared int x1, x2, z1, z2; int coord; INavmeshHolder nm = GetNavmeshHolder(GraphIndex); nm.GetTileCoordinates(tileIndex, out x1, out z1); nm.GetTileCoordinates(tileIndex2, out x2, out z2); if (System.Math.Abs(x1 - x2) == 1) { coord = 0; } else if (System.Math.Abs(z1 - z2) == 1) { coord = 2; } else { throw new System.Exception("Tiles not adjacent (" + x1 + ", " + z1 + ") (" + x2 + ", " + z2 + ")"); } int av = GetVertexCount(); int bv = other.GetVertexCount(); //Try the X and Z coordinate. For one of them the coordinates should be equal for one of the two nodes' edges //The midpoint between the tiles is the only place where they will be equal int first = -1, second = -1; //Find the shared edge for (int a = 0; a < av; a++) { int va = GetVertex(a)[coord]; for (int b = 0; b < bv; b++) { if (va == other.GetVertex((b + 1) % bv)[coord] && GetVertex((a + 1) % av)[coord] == other.GetVertex(b)[coord]) { first = a; second = b; a = av; break; } } } aIndex = first; bIndex = second; if (first != -1) { Int3 a = GetVertex(first); Int3 b = GetVertex((first + 1) % av); //The coordinate which is not the same for the vertices int ocoord = coord == 2 ? 0 : 2; //When the nodes are in different tiles, they might not share exactly the same edge //so we clamp the portal to the segment of the edges which they both have. int mincoord = System.Math.Min(a[ocoord], b[ocoord]); int maxcoord = System.Math.Max(a[ocoord], b[ocoord]); mincoord = System.Math.Max(mincoord, System.Math.Min(other.GetVertex(second)[ocoord], other.GetVertex((second + 1) % bv)[ocoord])); maxcoord = System.Math.Min(maxcoord, System.Math.Max(other.GetVertex(second)[ocoord], other.GetVertex((second + 1) % bv)[ocoord])); if (a[ocoord] < b[ocoord]) { a[ocoord] = mincoord; b[ocoord] = maxcoord; } else { a[ocoord] = maxcoord; b[ocoord] = mincoord; } if (left != null) { //All triangles should be clockwise so second is the rightmost vertex (seen from this node) left.Add((Vector3)a); right.Add((Vector3)b); } return(true); } } else if (!backwards) { int first = -1; int second = -1; int av = GetVertexCount(); int bv = other.GetVertexCount(); /** \todo Maybe optimize with pa=av-1 instead of modulus... */ for (int a = 0; a < av; a++) { int va = GetVertexIndex(a); for (int b = 0; b < bv; b++) { if (va == other.GetVertexIndex((b + 1) % bv) && GetVertexIndex((a + 1) % av) == other.GetVertexIndex(b)) { first = a; second = b; a = av; break; } } } aIndex = first; bIndex = second; if (first != -1) { if (left != null) { //All triangles should be clockwise so second is the rightmost vertex (seen from this node) left.Add((Vector3)GetVertex(first)); right.Add((Vector3)GetVertex((first + 1) % av)); } } else { for (int i = 0; i < connections.Length; i++) { if (connections[i].GraphIndex != GraphIndex) { #if !ASTAR_NO_POINT_GRAPH NodeLink3Node mid = connections[i] as NodeLink3Node; if (mid != null && mid.GetOther(this) == other) { // We have found a node which is connected through a NodeLink3Node if (left != null) { mid.GetPortal(other, left, right, false); return(true); } } #endif } } return(false); } } return(true); }
public bool GetPortal(GraphNode _other, List <Vector3> left, List <Vector3> right, bool backwards, out int aIndex, out int bIndex) { aIndex = -1; bIndex = -1; if (_other.GraphIndex != base.GraphIndex) { return(false); } TriangleMeshNode triangleMeshNode = _other as TriangleMeshNode; int num = this.GetVertexIndex(0) >> 12 & 524287; int num2 = triangleMeshNode.GetVertexIndex(0) >> 12 & 524287; if (num != num2 && TriangleMeshNode.GetNavmeshHolder(base.GraphIndex) is RecastGraph) { for (int i = 0; i < this.connections.Length; i++) { if (this.connections[i].GraphIndex != base.GraphIndex) { NodeLink3Node nodeLink3Node = this.connections[i] as NodeLink3Node; if (nodeLink3Node != null && nodeLink3Node.GetOther(this) == triangleMeshNode && left != null) { nodeLink3Node.GetPortal(triangleMeshNode, left, right, false); return(true); } } } INavmeshHolder navmeshHolder = TriangleMeshNode.GetNavmeshHolder(base.GraphIndex); int num3; int num4; navmeshHolder.GetTileCoordinates(num, out num3, out num4); int num5; int num6; navmeshHolder.GetTileCoordinates(num2, out num5, out num6); int num7; if (Math.Abs(num3 - num5) == 1) { num7 = 0; } else { if (Math.Abs(num4 - num6) != 1) { throw new Exception(string.Concat(new object[] { "Tiles not adjacent (", num3, ", ", num4, ") (", num5, ", ", num6, ")" })); } num7 = 2; } int vertexCount = this.GetVertexCount(); int vertexCount2 = triangleMeshNode.GetVertexCount(); int num8 = -1; int num9 = -1; for (int j = 0; j < vertexCount; j++) { int num10 = this.GetVertex(j)[num7]; for (int k = 0; k < vertexCount2; k++) { if (num10 == triangleMeshNode.GetVertex((k + 1) % vertexCount2)[num7] && this.GetVertex((j + 1) % vertexCount)[num7] == triangleMeshNode.GetVertex(k)[num7]) { num8 = j; num9 = k; j = vertexCount; break; } } } aIndex = num8; bIndex = num9; if (num8 != -1) { Int3 vertex = this.GetVertex(num8); Int3 vertex2 = this.GetVertex((num8 + 1) % vertexCount); int i2 = (num7 != 2) ? 2 : 0; int num11 = Math.Min(vertex[i2], vertex2[i2]); int num12 = Math.Max(vertex[i2], vertex2[i2]); num11 = Math.Max(num11, Math.Min(triangleMeshNode.GetVertex(num9)[i2], triangleMeshNode.GetVertex((num9 + 1) % vertexCount2)[i2])); num12 = Math.Min(num12, Math.Max(triangleMeshNode.GetVertex(num9)[i2], triangleMeshNode.GetVertex((num9 + 1) % vertexCount2)[i2])); if (vertex[i2] < vertex2[i2]) { vertex[i2] = num11; vertex2[i2] = num12; } else { vertex[i2] = num12; vertex2[i2] = num11; } if (left != null) { left.Add((Vector3)vertex); right.Add((Vector3)vertex2); } return(true); } } else if (!backwards) { int num13 = -1; int num14 = -1; int vertexCount3 = this.GetVertexCount(); int vertexCount4 = triangleMeshNode.GetVertexCount(); for (int l = 0; l < vertexCount3; l++) { int vertexIndex = this.GetVertexIndex(l); for (int m = 0; m < vertexCount4; m++) { if (vertexIndex == triangleMeshNode.GetVertexIndex((m + 1) % vertexCount4) && this.GetVertexIndex((l + 1) % vertexCount3) == triangleMeshNode.GetVertexIndex(m)) { num13 = l; num14 = m; l = vertexCount3; break; } } } aIndex = num13; bIndex = num14; if (num13 == -1) { for (int n = 0; n < this.connections.Length; n++) { if (this.connections[n].GraphIndex != base.GraphIndex) { NodeLink3Node nodeLink3Node2 = this.connections[n] as NodeLink3Node; if (nodeLink3Node2 != null && nodeLink3Node2.GetOther(this) == triangleMeshNode && left != null) { nodeLink3Node2.GetPortal(triangleMeshNode, left, right, false); return(true); } } } return(false); } if (left != null) { left.Add((Vector3)this.GetVertex(num13)); right.Add((Vector3)this.GetVertex((num13 + 1) % vertexCount3)); } } return(true); }
/** This performs a linear search through all polygons returning the closest one */ public static NNInfo GetNearestForce (NavGraph graph, INavmeshHolder navmesh, Vector3 position, NNConstraint constraint, bool accurateNearestNode) { NNInfo nn = GetNearestForceBoth (graph, navmesh,position,constraint,accurateNearestNode); nn.node = nn.constrainedNode; nn.clampedPosition = nn.constClampedPosition; return nn; }
public void UpdatePositionFromVertices() { INavmeshHolder navmeshHolder = TriangleMeshNode.GetNavmeshHolder(base.GraphIndex); this.position = (navmeshHolder.GetVertex(this.v0) + navmeshHolder.GetVertex(this.v1) + navmeshHolder.GetVertex(this.v2)) * 0.333333f; }
public static NNInfoInternal GetNearestForceBoth(NavGraph graph, INavmeshHolder navmesh, Vector3 position, NNConstraint constraint, bool accurateNearestNode) {
public override Vector3 ClosestPointOnNode(Vector3 p) { INavmeshHolder navmeshHolder = GetNavmeshHolder(base.DataGroupIndex, base.GraphIndex); return(Polygon.ClosestPointOnTriangle((Vector3)navmeshHolder.GetVertex(this.v0), (Vector3)navmeshHolder.GetVertex(this.v1), (Vector3)navmeshHolder.GetVertex(this.v2), p)); }
public BBTree (INavmeshHolder graph) { this.graph = graph; }
public override Vector3 ClosestPointOnNodeXZ(Vector3 _p) { INavmeshHolder g = GetNavmeshHolder(GraphIndex); Int3 tp1 = g.GetVertex(v0); Int3 tp2 = g.GetVertex(v1); Int3 tp3 = g.GetVertex(v2); Int3 p = (Int3)_p; int oy = p.y; // Assumes the triangle vertices are laid out in (counter?)clockwise order tp1.y = 0; tp2.y = 0; tp3.y = 0; p.y = 0; if ((long)(tp2.x - tp1.x) * (long)(p.z - tp1.z) - (long)(p.x - tp1.x) * (long)(tp2.z - tp1.z) > 0) { float f = Mathf.Clamp01(AstarMath.NearestPointFactor(tp1, tp2, p)); return(new Vector3(tp1.x + (tp2.x - tp1.x) * f, oy, tp1.z + (tp2.z - tp1.z) * f) * Int3.PrecisionFactor); } else if ((long)(tp3.x - tp2.x) * (long)(p.z - tp2.z) - (long)(p.x - tp2.x) * (long)(tp3.z - tp2.z) > 0) { float f = Mathf.Clamp01(AstarMath.NearestPointFactor(tp2, tp3, p)); return(new Vector3(tp2.x + (tp3.x - tp2.x) * f, oy, tp2.z + (tp3.z - tp2.z) * f) * Int3.PrecisionFactor); } else if ((long)(tp1.x - tp3.x) * (long)(p.z - tp3.z) - (long)(p.x - tp3.x) * (long)(tp1.z - tp3.z) > 0) { float f = Mathf.Clamp01(AstarMath.NearestPointFactor(tp3, tp1, p)); return(new Vector3(tp3.x + (tp1.x - tp3.x) * f, oy, tp3.z + (tp1.z - tp3.z) * f) * Int3.PrecisionFactor); } else { return(_p); } /* * Equivalent to the above, but the above uses manual inlining * if (!Polygon.Left (tp1, tp2, p)) { * float f = Mathf.Clamp01 (AstarMath.NearestPointFactor (tp1, tp2, p)); * return new Vector3(tp1.x + (tp2.x-tp1.x)*f, oy, tp1.z + (tp2.z-tp1.z)*f)*Int3.PrecisionFactor; * } else if (!Polygon.Left (tp2, tp3, p)) { * float f = Mathf.Clamp01 (AstarMath.NearestPointFactor (tp2, tp3, p)); * return new Vector3(tp2.x + (tp3.x-tp2.x)*f, oy, tp2.z + (tp3.z-tp2.z)*f)*Int3.PrecisionFactor; * } else if (!Polygon.Left (tp3, tp1, p)) { * float f = Mathf.Clamp01 (AstarMath.NearestPointFactor (tp3, tp1, p)); * return new Vector3(tp3.x + (tp1.x-tp3.x)*f, oy, tp3.z + (tp1.z-tp3.z)*f)*Int3.PrecisionFactor; * } else { * return _p; * }*/ /* Almost equivalent to the above, but this is slower * Vector3 tp1 = (Vector3)g.GetVertex(v0); * Vector3 tp2 = (Vector3)g.GetVertex(v1); * Vector3 tp3 = (Vector3)g.GetVertex(v2); * tp1.y = 0; * tp2.y = 0; * tp3.y = 0; * _p.y = 0; * return Pathfinding.Polygon.ClosestPointOnTriangle (tp1,tp2,tp3,_p);*/ }
public static void UpdateArea(GraphUpdateObject o, INavmeshHolder graph) { Bounds bounds = graph.transform.InverseTransform(o.bounds); // Bounding rectangle with integer coordinates var irect = new IntRect( Mathf.FloorToInt(bounds.min.x * Int3.Precision), Mathf.FloorToInt(bounds.min.z * Int3.Precision), Mathf.CeilToInt(bounds.max.x * Int3.Precision), Mathf.CeilToInt(bounds.max.z * Int3.Precision) ); // Corners of the bounding rectangle var a = new Int3(irect.xmin, 0, irect.ymin); var b = new Int3(irect.xmin, 0, irect.ymax); var c = new Int3(irect.xmax, 0, irect.ymin); var d = new Int3(irect.xmax, 0, irect.ymax); var ymin = ((Int3)bounds.min).y; var ymax = ((Int3)bounds.max).y; // Loop through all nodes and check if they intersect the bounding box graph.GetNodes(_node => { var node = _node as TriangleMeshNode; bool inside = false; int allLeft = 0; int allRight = 0; int allTop = 0; int allBottom = 0; // Check bounding box rect in XZ plane for (int v = 0; v < 3; v++) { Int3 p = node.GetVertexInGraphSpace(v); if (irect.Contains(p.x, p.z)) { inside = true; break; } if (p.x < irect.xmin) { allLeft++; } if (p.x > irect.xmax) { allRight++; } if (p.z < irect.ymin) { allTop++; } if (p.z > irect.ymax) { allBottom++; } } if (!inside && (allLeft == 3 || allRight == 3 || allTop == 3 || allBottom == 3)) { return; } // Check if the polygon edges intersect the bounding rect for (int v = 0; v < 3; v++) { int v2 = v > 1 ? 0 : v + 1; Int3 vert1 = node.GetVertexInGraphSpace(v); Int3 vert2 = node.GetVertexInGraphSpace(v2); if (VectorMath.SegmentsIntersectXZ(a, b, vert1, vert2)) { inside = true; break; } if (VectorMath.SegmentsIntersectXZ(a, c, vert1, vert2)) { inside = true; break; } if (VectorMath.SegmentsIntersectXZ(c, d, vert1, vert2)) { inside = true; break; } if (VectorMath.SegmentsIntersectXZ(d, b, vert1, vert2)) { inside = true; break; } } // Check if the node contains any corner of the bounding rect if (inside || node.ContainsPointInGraphSpace(a) || node.ContainsPointInGraphSpace(b) || node.ContainsPointInGraphSpace(c) || node.ContainsPointInGraphSpace(d)) { inside = true; } if (!inside) { return; } int allAbove = 0; int allBelow = 0; // Check y coordinate for (int v = 0; v < 3; v++) { Int3 p = node.GetVertexInGraphSpace(v); if (p.y < ymin) { allBelow++; } if (p.y > ymax) { allAbove++; } } // Polygon is either completely above the bounding box or completely below it if (allBelow == 3 || allAbove == 3) { return; } // Triangle is inside the bounding box! // Update it! o.WillUpdateNode(node); o.Apply(node); }); }
public bool GetPortal(GraphNode _other, List <VInt3> left, List <VInt3> right, bool backwards, out int aIndex, out int bIndex) { aIndex = -1; bIndex = -1; if (_other.GraphIndex != base.GraphIndex) { return(false); } TriangleMeshNode node = _other as TriangleMeshNode; int tileIndex = (this.GetVertexIndex(0) >> 12) & 0x7ffff; int num2 = (node.GetVertexIndex(0) >> 12) & 0x7ffff; if ((tileIndex != num2) && (GetNavmeshHolder(base.DataGroupIndex, base.GraphIndex) is RecastGraph)) { int num3; int num4; int num5; int num6; int num7; INavmeshHolder navmeshHolder = GetNavmeshHolder(base.DataGroupIndex, base.GraphIndex); navmeshHolder.GetTileCoordinates(tileIndex, out num3, out num5); navmeshHolder.GetTileCoordinates(num2, out num4, out num6); if (Math.Abs((int)(num3 - num4)) == 1) { num7 = 0; } else if (Math.Abs((int)(num5 - num6)) == 1) { num7 = 2; } else { object[] objArray1 = new object[] { "Tiles not adjacent (", num3, ", ", num5, ") (", num4, ", ", num6, ")" }; throw new Exception(string.Concat(objArray1)); } int vertexCount = this.GetVertexCount(); int num9 = node.GetVertexCount(); int i = -1; int num11 = -1; for (int j = 0; j < vertexCount; j++) { int num13 = this.GetVertex(j)[num7]; for (int k = 0; k < num9; k++) { if ((num13 == node.GetVertex((k + 1) % num9)[num7]) && (this.GetVertex((j + 1) % vertexCount)[num7] == node.GetVertex(k)[num7])) { i = j; num11 = k; j = vertexCount; break; } } } aIndex = i; bIndex = num11; if (i != -1) { VInt3 vertex = this.GetVertex(i); VInt3 item = this.GetVertex((i + 1) % vertexCount); int num17 = (num7 != 2) ? 2 : 0; int num18 = Math.Min(vertex[num17], item[num17]); int num19 = Math.Max(vertex[num17], item[num17]); num18 = Math.Max(num18, Math.Min(node.GetVertex(num11)[num17], node.GetVertex((num11 + 1) % num9)[num17])); num19 = Math.Min(num19, Math.Max(node.GetVertex(num11)[num17], node.GetVertex((num11 + 1) % num9)[num17])); if (vertex[num17] < item[num17]) { vertex[num17] = num18; item[num17] = num19; } else { vertex[num17] = num19; item[num17] = num18; } if (left != null) { left.Add(vertex); right.Add(item); } return(true); } } else if (!backwards) { int num20 = -1; int num21 = -1; int num22 = this.GetVertexCount(); int num23 = node.GetVertexCount(); for (int m = 0; m < num22; m++) { int vertexIndex = this.GetVertexIndex(m); for (int n = 0; n < num23; n++) { if ((vertexIndex == node.GetVertexIndex((n + 1) % num23)) && (this.GetVertexIndex((m + 1) % num22) == node.GetVertexIndex(n))) { num20 = m; num21 = n; m = num22; break; } } } aIndex = num20; bIndex = num21; if (num20 == -1) { return(false); } if (left != null) { left.Add(this.GetVertex(num20)); right.Add(this.GetVertex((num20 + 1) % num22)); } } return(true); }