コード例 #1
0
ファイル: NodeLink3.cs プロジェクト: luukholleman/Airchitect
		public GraphNode GetOther ( GraphNode a ) {
			
			if ( this.connections.Length < 2 ) return null;
			if ( this.connections.Length != 2 ) throw new System.Exception ("Invalid NodeLink3Node. Expected 2 connections, found " + this.connections.Length);
			
			return a == connections[0] ? (connections[1] as NodeLink3Node).GetOtherInternal(this) : (connections[0] as NodeLink3Node).GetOtherInternal(this);
		}
コード例 #2
0
ファイル: PointNode.cs プロジェクト: luukholleman/Airchitect
		/** Enqueue a connection from this node to the specified node.
		 * If the connection already exists, the cost will simply be updated and
		 * no extra connection added.
		 * 
		 * \note Only adds a one-way connection. Consider calling the same function on the other node
		 * to get a two-way connection.
		 */
		public override void AddConnection (GraphNode node, uint cost) {
			
			if (connections != null) { 
				for (int i=0;i<connections.Length;i++) {
					if (connections[i] == node) {
						connectionCosts[i] = cost;
						return;
					}
				}
			}
			
			int connLength = connections != null ? connections.Length : 0;
			
			var newconns = new GraphNode[connLength+1];
			var newconncosts = new uint[connLength+1];
			for (int i=0;i<connLength;i++) {
				newconns[i] = connections[i];
				newconncosts[i] = connectionCosts[i];
			}
			
			newconns[connLength] = node;
			newconncosts[connLength] = cost;
			
			connections = newconns;
			connectionCosts = newconncosts;
		}
コード例 #3
0
ファイル: NodeLink3.cs プロジェクト: luukholleman/Airchitect
		public override bool GetPortal (GraphNode other, List<Vector3> left, List<Vector3> right, bool backwards)
		{
			
			if ( this.connections.Length < 2 ) return false;
			
			if ( this.connections.Length != 2 ) throw new System.Exception ("Invalid NodeLink3Node. Expected 2 connections, found " + this.connections.Length);
			
			//if ( other != connections[0] || other != connections[1] ) return false;
			
			if ( left != null ) {
				//Debug.DrawLine ( portalA, portalB, Color.red);
				left.Add ( portalA );
				right.Add ( portalB );
				/*
				Vector3 normal = link.transform.forward;
				Vector3 tangent = Vector3.Dot (normal, (Vector3)(other.Position - this.Position) ) > 0 ? link.transform.right*0.5f : -link.transform.right*0.5f;
				
				Debug.DrawLine ( link.transform.position -tangent * link.portalWidth, link.transform.position +tangent * link.portalWidth, Color.red);
				
				Debug.DrawRay ( link.transform.position -tangent * link.portalWidth, Vector3.up*5, Color.red);
				Debug.Break ();
				left.Enqueue ( link.transform.position -tangent * link.portalWidth );
				right.Enqueue (link.transform.position +tangent * link.portalWidth );*/
			}
			
			return true;
		}
コード例 #4
0
		/** Updates graphs and checks if all nodes are still reachable from each other.
		 * Graphs are updated, then a check is made to see if the nodes are still reachable from each other.
		 * If they are not, the graphs are reverted to before the update and \a false is returned.\n
		 * This is slower than a normal graph update.
		 * All queued graph updates and thread safe callbacks will be flushed during this function.
		 *
		 * \note This might return true for small areas even if there is no possible path if AstarPath.minAreaSize is greater than zero (0).
		 * So when using this, it is recommended to set AstarPath.minAreaSize to 0 (A* Inspector -> Settings -> Pathfinding)
		 *
		 * \param guo The GraphUpdateObject to update the graphs with
		 * \param node1 Node which should have a valid path to \a node2. All nodes should be walkable or \a false will be returned.
		 * \param node2 Node which should have a valid path to \a node1. All nodes should be walkable or \a false will be returned.
		 * \param alwaysRevert If true, reverts the graphs to the old state even if no blocking ocurred
		 *
		 * \returns True if the given nodes are still reachable from each other after the \a guo has been applied. False otherwise.
		 *
\code
var guo = new GraphUpdateObject (tower.GetComponent<Collider>.bounds);
var spawnPointNode = AstarPath.active.GetNearest (spawnPoint.position).node;
var goalNode = AstarPath.active.GetNearest (goalNode.position).node;
if (GraphUpdateUtilities.UpdateGraphsNoBlock (guo, spawnPointNode, goalNode, false)) {
	// Valid tower position
	// Since the last parameter (which is called "alwaysRevert") in the method call was false
	// The graph is now updated and the game can just continue
} else {
	// Invalid tower position. It blocks the path between the spawn point and the goal
	// The effect on the graph has been reverted
	Destroy (tower);
}
\endcode
		 */
		public static bool UpdateGraphsNoBlock (GraphUpdateObject guo, GraphNode node1, GraphNode node2, bool alwaysRevert = false) {
			List<GraphNode> buffer = ListPool<GraphNode>.Claim ();
			buffer.Add (node1);
			buffer.Add (node2);

			bool worked = UpdateGraphsNoBlock (guo, buffer, alwaysRevert);
			ListPool<GraphNode>.Release (buffer);
			return worked;
		}
コード例 #5
0
		// Update is called once per frame
		void LateUpdate () {
			
			if (prevNode == null) {
				NNInfo nninfo = AstarPath.active.GetNearest (transform.position);
				prevNode = nninfo.node;
				prevPos = transform.position;
				
			}
			
			if (prevNode == null) {
				return;
			}
			
			if (prevNode != null) {
				
					
				IRaycastableGraph graph = AstarData.GetGraph (prevNode) as IRaycastableGraph;
				if (graph != null) {
					GraphHitInfo hit;
					if (graph.Linecast (prevPos,transform.position,prevNode, out hit)) {
						hit.point.y = transform.position.y;
						Vector3 closest = AstarMath.NearestPoint (hit.tangentOrigin,hit.tangentOrigin+hit.tangent,transform.position);
						Vector3 ohit = hit.point;
						ohit = ohit + Vector3.ClampMagnitude((Vector3)hit.node.position-ohit,0.008f);
						if (graph.Linecast (ohit,closest,hit.node, out hit)) {
							hit.point.y = transform.position.y;
							transform.position = hit.point;
						} else {
							closest.y = transform.position.y;
							
							transform.position = closest;
						}
					}
					prevNode = hit.node;
				}
			}
			
			prevPos = transform.position;
		}
コード例 #6
0
ファイル: Base.cs プロジェクト: luukholleman/Airchitect
		/** Returns if the node is in the search tree of the path.
		 * Only guaranteed to be correct if \a path is the latest path calculated.
		 * Use for gizmo drawing only.
		 */
		public static bool InSearchTree (GraphNode node, Path path) {
			if (path == null || path.pathHandler == null) return true;
			PathNode nodeR = path.pathHandler.GetPathNode (node);
			return nodeR.pathID == path.pathID;
		}
コード例 #7
0
ファイル: Base.cs プロジェクト: luukholleman/Airchitect
		/** Returns the nearest node to a position using the specified NNConstraint.
		  * \param position The position to try to find a close node to
		  * \param hint Can be passed to enable some graph generators to find the nearest node faster.
		  * \param constraint Can for example tell the function to try to return a walkable node. If you do not get a good node back, consider calling GetNearestForce. */
		public virtual NNInfo GetNearest (Vector3 position, NNConstraint constraint, GraphNode hint) {
			// This is a default implementation and it is pretty slow
			// Graphs usually override this to provide faster and more specialised implementations

			float maxDistSqr = constraint.constrainDistance ? AstarPath.active.maxNearestNodeDistanceSqr : float.PositiveInfinity;

			float minDist = float.PositiveInfinity;
			GraphNode minNode = null;

			float minConstDist = float.PositiveInfinity;
			GraphNode minConstNode = null;

			// Loop through all nodes and find the closest suitable node
			GetNodes (node => {
				float dist = (position-(Vector3)node.position).sqrMagnitude;

				if (dist < minDist) {
					minDist = dist;
					minNode = node;
				}

				if (dist < minConstDist && dist < maxDistSqr && constraint.Suitable (node)) {
					minConstDist = dist;
					minConstNode = node;
				}
				return true;
			});

			var nnInfo = new NNInfo (minNode);

			nnInfo.constrainedNode = minConstNode;

			if (minConstNode != null) {
				nnInfo.constClampedPosition = (Vector3)minConstNode.position;
			} else if (minNode != null) {
				nnInfo.constrainedNode = minNode;
				nnInfo.constClampedPosition = (Vector3)minNode.position;
			}

			return nnInfo;
		}
コード例 #8
0
		public override bool GetPortal (GraphNode _other, System.Collections.Generic.List<Vector3> left, System.Collections.Generic.List<Vector3> right, bool backwards) {
			int aIndex, bIndex;
			return GetPortal (_other,left,right,backwards, out aIndex, out bIndex);
		}
コード例 #9
0
ファイル: AstarData.cs プロジェクト: luukholleman/Airchitect
		/** Returns the graph which contains the specified node.
		 * The graph must be in the #graphs array.
		 *
		 * \returns Returns the graph which contains the node. Null if the graph wasn't found
		 */
		public static NavGraph GetGraph (GraphNode node) {
			
			if (node == null) return null;
			
			AstarPath script = AstarPath.active;
			
			if (script == null) return null;
			
			AstarData data = script.astarData;
			
			if (data == null) return null;
			
			if (data.graphs == null) return null;
			
			uint graphIndex = node.GraphIndex;
			
			if (graphIndex >= data.graphs.Length) {
				return null;
			}
			
			return data.graphs[(int)graphIndex];
		}
コード例 #10
0
		public override bool Suitable (GraphNode node) {
			return base.Suitable (node) && path.HasPathTo (node);
		}
コード例 #11
0
ファイル: Path.cs プロジェクト: luukholleman/Airchitect
		/** Reset all values to their default values.
		 *
		 * \note All inheriting path types (e.g ConstantPath, RandomPath, etc.) which declare their own variables need to
		 * override this function, resetting ALL their variables to enable recycling of paths.
		 * If this is not done, trying to use that path type for pooling might result in weird behaviour.
		 * The best way is to reset to default values the variables declared in the extended path type and then
		 * call this base function in inheriting types with base.Reset ().
		 *
		 * \warning This function should not be called manually.
		  */
		public virtual void Reset () {
#if ASTAR_POOL_DEBUG
			pathTraceInfo = "This path was got from the pool or created from here (stacktrace):\n";
			pathTraceInfo += System.Environment.StackTrace;
#endif

			if (System.Object.ReferenceEquals (AstarPath.active, null))
				throw new System.NullReferenceException ("No AstarPath object found in the scene. " +
					"Make sure there is one or do not create paths in Awake");

			hasBeenReset = true;
			state = (int)PathState.Created;
			releasedNotSilent = false;

			pathHandler = null;
			callback = null;
			_errorLog = "";
			pathCompleteState = PathCompleteState.NotCalculated;

			path = ListPool<GraphNode>.Claim();
			vectorPath = ListPool<Vector3>.Claim();

			currentR = null;

			duration = 0;
			searchIterations = 0;
			searchedNodes = 0;
			//calltime

			nnConstraint = PathNNConstraint.Default;
			next = null;

			heuristic = AstarPath.active.heuristic;
			heuristicScale = AstarPath.active.heuristicScale;

			enabledTags = -1;
			tagPenalties = null;

			callTime = System.DateTime.UtcNow;
			pathID = AstarPath.active.GetNextPathID ();

			hTarget = Int3.zero;
			hTargetNode = null;
		}
コード例 #12
0
        /** Returns whether or not the node conforms to this NNConstraint's rules */
        public virtual bool Suitable (GraphNode node) {
            if (constrainWalkability && node.Walkable != walkable) return false;

            if (constrainArea && area >= 0 && node.Area != area) return false;

            if (constrainTags && ((tags >> (int)node.Tag) & 0x1) == 0) return false;

            return true;
        }
コード例 #13
0
 public GraphHitInfo (Vector3 point) {
     tangentOrigin  = Vector3.zero;
     origin = Vector3.zero;
     this.point = point;
     node = null;
     tangent = Vector3.zero;
     //this.distance = distance;
 }
コード例 #14
0
		public override void RemoveConnection (GraphNode node) {
			throw new System.NotImplementedException("QuadTree Nodes do not have support for adding manual connections");
		}
コード例 #15
0
ファイル: ABPath.cs プロジェクト: luukholleman/Airchitect
		/** Prepares the path. Searches for start and end nodes and does some simple checking if a path is at all possible */
		public override void Prepare () {

			AstarProfiler.StartProfile ("Get Nearest");

			//Initialize the NNConstraint
			nnConstraint.tags = enabledTags;
			NNInfo startNNInfo 	= AstarPath.active.GetNearest (startPoint,nnConstraint, startHint);

			//Tell the NNConstraint which node was found as the start node if it is a PathNNConstraint and not a normal NNConstraint
			var pathNNConstraint = nnConstraint as PathNNConstraint;
			if (pathNNConstraint != null) {
				pathNNConstraint.SetStart (startNNInfo.node);
			}

			startPoint = startNNInfo.clampedPosition;

			startIntPoint = (Int3)startPoint;
			startNode = startNNInfo.node;

			//If it is declared that this path type has an end point
			//Some path types might want to use most of the ABPath code, but will not have an explicit end point at this stage
			if (hasEndPoint) {
				NNInfo endNNInfo = AstarPath.active.GetNearest (endPoint,nnConstraint, endHint);
				endPoint = endNNInfo.clampedPosition;

				// Note, other methods assume hTarget is (Int3)endPoint
				hTarget = (Int3)endPoint;
				endNode = endNNInfo.node;
				hTargetNode = endNode;
			}

			AstarProfiler.EndProfile ();

#if ASTARDEBUG
			if (startNode != null)
				Debug.DrawLine ((Vector3)startNode.position,startPoint,Color.blue);
			if (endNode != null)
				Debug.DrawLine ((Vector3)endNode.position,endPoint,Color.blue);
#endif

			if (startNode == null && (hasEndPoint && endNode == null)) {
				Error ();
				LogError ("Couldn't find close nodes to the start point or the end point");
				return;
			}

			if (startNode == null) {
				Error ();
				LogError ("Couldn't find a close node to the start point");
				return;
			}

			if (endNode == null && hasEndPoint) {
				Error ();
				LogError ("Couldn't find a close node to the end point");
				return;
			}

			if (!startNode.Walkable) {
#if ASTARDEBUG
				Debug.DrawRay (startPoint,Vector3.up,Color.red);
				Debug.DrawLine (startPoint,(Vector3)startNode.position,Color.red);
#endif
				Error ();
				LogError ("The node closest to the start point is not walkable");
				return;
			}

			if (hasEndPoint && !endNode.Walkable) {
				Error ();
				LogError ("The node closest to the end point is not walkable");
				return;
			}

			if (hasEndPoint && startNode.Area != endNode.Area) {
				Error ();
				LogError ("There is no valid path to the target (start area: "+startNode.Area+", target area: "+endNode.Area+")");
				return;
			}
		}
コード例 #16
0
ファイル: Path.cs プロジェクト: luukholleman/Airchitect
		public uint GetTraversalCost (GraphNode node) {
#if ASTAR_NO_TRAVERSAL_COST
			return 0;
#else
			unchecked { return GetTagPenalty ((int)node.Tag ) + node.Penalty ; }
#endif
		}
コード例 #17
0
ファイル: Path.cs プロジェクト: luukholleman/Airchitect
		/** May be called by graph nodes to get a special cost for some connections.
		 * Nodes may call it when PathNode.flag2 is set to true, for example mesh nodes, which have
		 * a very large area can be marked on the start and end nodes, this method will be called
		 * to get the actual cost for moving from the start position to its neighbours instead
		 * of as would otherwise be the case, from the start node's position to its neighbours.
		 * The position of a node and the actual start point on the node can vary quite a lot.
		 *
		 * The default behaviour of this method is to return the previous cost of the connection,
		 * essentiall making no change at all.
		 *
		 * This method should return the same regardless of the order of a and b.
		 * That is f(a,b) == f(b,a) should hold.
		 *
		 * \param a Moving from this node
		 * \param b Moving to this node
		 * \param currentCost The cost of moving between the nodes. Return this value if there is no meaningful special cost to return.
		 */
		public virtual uint GetConnectionSpecialCost (GraphNode a, GraphNode b, uint currentCost) {
			return currentCost;
		}
コード例 #18
0
 /** Called after the start node has been found. This is used to get different search logic for the start and end nodes in a path */
 public virtual void SetStart (GraphNode node) {
     if (node != null) {
         area = (int)node.Area;
     } else {
         constrainArea = false;
     }
 }
コード例 #19
0
		/** Traces the calculated path from the start node to the end.
		 * This will build an array (#path) of the nodes this path will pass through and also set the #vectorPath array to the #path arrays positions.
		 * This implementation will use the #flood (FloodPath) to trace the path from precalculated data.
		 */
		public void Trace (GraphNode from) {

			GraphNode c = from;
			int count = 0;

			while (c != null) {
				path.Add (c);
				vectorPath.Add ((Vector3)c.position);
				c = flood.GetParent(c);

				count++;
				if (count > 1024) {
					Debug.LogWarning ("Inifinity loop? >1024 node path. Remove this message if you really have that long paths (FloodPathTracer.cs, Trace function)");
					break;
				}
			}
		}
コード例 #20
0
        public NNInfo (GraphNode node) {
            this.node = node;
            constrainedNode = null;
            clampedPosition = Vector3.zero;
            constClampedPosition = Vector3.zero;

            UpdateInfo ();
        }
コード例 #21
0
		/** Check if a straight path between v1 and v2 is valid */
		public bool ValidateLine (GraphNode n1, GraphNode n2, Vector3 v1, Vector3 v2) {
			
			if (useRaycasting) {
				// Use raycasting to check if a straight path between v1 and v2 is valid
				if (thickRaycast && thickRaycastRadius > 0) {
					RaycastHit hit;
					if (Physics.SphereCast (v1+raycastOffset, thickRaycastRadius,v2-v1,out hit, (v2-v1).magnitude,mask)) {
						return false;
					}
				} else {
					RaycastHit hit;
					if (Physics.Linecast (v1+raycastOffset,v2+raycastOffset,out hit, mask)) {
						return false;
					}
				}
			}
			
			if (useGraphRaycasting && n1 == null) {
				n1 = AstarPath.active.GetNearest (v1).node;
				n2 = AstarPath.active.GetNearest (v2).node;
			}
			
			if (useGraphRaycasting && n1 != null && n2 != null) {
				// Use graph raycasting to check if a straight path between v1 and v2 is valid
				NavGraph graph = AstarData.GetGraph (n1);
				NavGraph graph2 = AstarData.GetGraph (n2);
				
				if (graph != graph2) {
					return false;
				}
				
				if (graph != null) {
					var rayGraph = graph as IRaycastableGraph;
					
					if (rayGraph != null) {
						if (rayGraph.Linecast (v1,v2, n1)) {
							return false;
						}
					}
				}
			}
			return true;
		}
コード例 #22
0
 /** Sets the constrained node */
 public void SetConstrained (GraphNode constrainedNode, Vector3 clampedPosition) {
     this.constrainedNode = constrainedNode;
     constClampedPosition = clampedPosition;
 }
コード例 #23
0
		/** Returns the edge which is shared with \a other.
		 * If no edge is shared, -1 is returned.
		 * The edge is GetVertex(result) - GetVertex((result+1) % GetVertexCount()).
		 * See GetPortal for the exact segment shared.
		 * \note Might return that an edge is shared when the two nodes are in different tiles and adjacent on the XZ plane, but on the Y-axis.
		 * Therefore it is recommended that you only test for neighbours of this node or do additional checking afterwards.
		 */
		public int SharedEdge (GraphNode other) {
			int a, b;
			GetPortal(other, null, null, false, out a, out b);
			return a;
		}
コード例 #24
0
        /** Should be called on every node which is updated with this GUO before it is updated.
		  * \param node The node to save fields for. If null, nothing will be done
		  * \see #trackChangedNodes
		  */
        public virtual void WillUpdateNode (GraphNode node) {
            if (trackChangedNodes && node != null) {
                if (changedNodes == null) { changedNodes = ListPool<GraphNode>.Claim(); backupData = ListPool<uint>.Claim(); backupPositionData = ListPool<Int3>.Claim(); }
                changedNodes.Add (node);
                backupPositionData.Add (node.position);
                backupData.Add (node.Penalty);
                backupData.Add (node.Flags);
#if !ASTAR_NO_GRID_GRAPH
                var gg = node as GridNode;
                if ( gg != null ) backupData.Add (gg.InternalGridFlags);
#endif
            }
        }
コード例 #25
0
		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;

			// 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 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
						var 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
							var 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;
		}
コード例 #26
0
        /** Updates the specified node using this GUO's settings */
        public virtual void Apply (GraphNode node) {
            if (shape == null || shape.Contains	(node)) {

                //Update penalty and walkability
                node.Penalty = (uint)(node.Penalty+addPenalty);
                if (modifyWalkability) {
                    node.Walkable = setWalkability;
                }

                //Update tags
                if (modifyTag) node.Tag = (uint)setTag;
            }
        }
コード例 #27
0
ファイル: Base.cs プロジェクト: luukholleman/Airchitect
		/* Color to use for gizmos.
		 * Returns a color to be used for the specified node with the current debug settings (editor only).
		 *
		 * \version Since 3.6.1 this method will not handle null nodes
		 */
		public virtual Color NodeColor (GraphNode node, PathHandler data) {
	#if !PhotonImplementation
			Color c = AstarColor.NodeConnection;

			switch (AstarPath.active.debugMode) {
				case GraphDebugMode.Areas:
					c = AstarColor.GetAreaColor (node.Area);
					break;
				case GraphDebugMode.Penalty:
					c = Color.Lerp (AstarColor.ConnectionLowLerp,AstarColor.ConnectionHighLerp, ((float)node.Penalty-AstarPath.active.debugFloor) / (AstarPath.active.debugRoof-AstarPath.active.debugFloor));
					break;
				case GraphDebugMode.Tags:
					c = AstarMath.IntToColor ((int)node.Tag,0.5F);
					break;
				default:
					if (data == null) return AstarColor.NodeConnection;

					PathNode nodeR = data.GetPathNode (node);

					switch (AstarPath.active.debugMode) {
						case GraphDebugMode.G:
							c = Color.Lerp (AstarColor.ConnectionLowLerp,AstarColor.ConnectionHighLerp, ((float)nodeR.G-AstarPath.active.debugFloor) / (AstarPath.active.debugRoof-AstarPath.active.debugFloor));
							break;
						case GraphDebugMode.H:
							c = Color.Lerp (AstarColor.ConnectionLowLerp,AstarColor.ConnectionHighLerp, ((float)nodeR.H-AstarPath.active.debugFloor) / (AstarPath.active.debugRoof-AstarPath.active.debugFloor));
							break;
						case GraphDebugMode.F:
							c = Color.Lerp (AstarColor.ConnectionLowLerp,AstarColor.ConnectionHighLerp, ((float)nodeR.F-AstarPath.active.debugFloor) / (AstarPath.active.debugRoof-AstarPath.active.debugFloor));
							break;
					}
					break;
			}

			c.a *= 0.5F;
			return c;
	#else
			return new Color (1,1,1);
	#endif

		}
コード例 #28
0
ファイル: Path.cs プロジェクト: luukholleman/Airchitect
		public uint CalculateHScore (GraphNode node) {
			uint v1;
			uint v2;
			switch (heuristic) {
			case Heuristic.Euclidean:
				v1 = (uint)(((GetHTarget () - node.position).costMagnitude)*heuristicScale);
				v2 = hTargetNode != null ? AstarPath.active.euclideanEmbedding.GetHeuristic ( node.NodeIndex, hTargetNode.NodeIndex ) : 0;
				return System.Math.Max (v1,v2);
			case Heuristic.Manhattan:
				Int3 p2 = node.position;
				v1 = (uint)((System.Math.Abs (hTarget.x-p2.x) + System.Math.Abs (hTarget.y-p2.y) + System.Math.Abs (hTarget.z-p2.z))*heuristicScale);
				v2 = hTargetNode != null ? AstarPath.active.euclideanEmbedding.GetHeuristic ( node.NodeIndex, hTargetNode.NodeIndex ) : 0;
				return System.Math.Max (v1,v2);
			case Heuristic.DiagonalManhattan:
				Int3 p = GetHTarget () - node.position;
				p.x = System.Math.Abs (p.x);
				p.y = System.Math.Abs (p.y);
				p.z = System.Math.Abs (p.z);
				int diag = System.Math.Min (p.x,p.z);
				int diag2 = System.Math.Max (p.x,p.z);
				v1 = (uint)((((14*diag)/10) + (diag2-diag) + p.y) * heuristicScale);
				v2 = hTargetNode != null ? AstarPath.active.euclideanEmbedding.GetHeuristic ( node.NodeIndex, hTargetNode.NodeIndex ) : 0;
				return System.Math.Max (v1,v2);
			}
			return 0U;
		}
コード例 #29
0
		public bool Contains (GraphNode node) {
			return Contains((Vector3)node.position);
		}
コード例 #30
0
ファイル: Path.cs プロジェクト: luukholleman/Airchitect
		/** Returns if the node can be traversed.
		  * This per default equals to if the node is walkable and if the node's tag is included in #enabledTags */
		public bool CanTraverse (GraphNode node) {
			unchecked { return node.Walkable && (enabledTags >> (int)node.Tag & 0x1) != 0; }
		}