Pathfinding.LayerGridGraph.ScanInternal C# (CSharp) Method

ScanInternal() public method

public ScanInternal ( OnScanStatus status ) : void
status OnScanStatus
return void
		public override void ScanInternal (OnScanStatus status) {
			
			scans++;
			
			if (nodeSize <= 0) {
				return;
			}
			
			GenerateMatrix ();
			
			if (width > 1024 || depth > 1024) {
				Debug.LogError ("One of the grid's sides is longer than 1024 nodes");
				return;
			}
			
			//GenerateBounds ();
			
			/*neighbourOffsets = new int[8] {
				-width-1,-width,-width+1,
				-1,1,
				width-1,width,width+1
			}*/
			
			SetUpOffsetsAndCosts ();
			
			//GridNode.RemoveGridGraph (this);
			
			LevelGridNode.SetGridGraph (active.astarData.GetGraphIndex(this), this);
			
			//graphNodes = new LevelGridNode[width*depth];
			
			//nodes = CreateNodes (width*depth);
			//graphNodes = nodes as LevelGridNode[];
			
			maxClimb = Mathf.Clamp (maxClimb,0,characterHeight);
			
			LinkedLevelCell[] linkedCells = new LinkedLevelCell[width*depth];
			
			if (collision == null) {
				collision = new GraphCollision ();
			}
			collision.Initialize (matrix,nodeSize);
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
					
					linkedCells[z*width+x] = new LinkedLevelCell ();
					
					LinkedLevelCell llc = linkedCells[z*width+x];
					//GridNode node = graphNodes[z*width+x];//new LevelGridNode ();
					
					//node.SetIndex (z*width+x);
					
					Vector3 pos = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F));
					
					
					RaycastHit[] hits = collision.CheckHeightAll (pos);
					
					//Sort the hits based on distance with bubble sort (fast enough)
					//Furthest away first (i.e lowest nodes in the graph)
					/*bool changed = true;
					while (changed) {
						changed = false;
						for (int i=0;i<hits.Length-1;i++) {
							if (hits[i].distance < hits[i+1].distance) {
								RaycastHit tmp = hits[i];
								hits[i] = hits[i+1];
								hits[i+1] = tmp;
								changed = true;
							}
						}
					}*/
					
					for (int i=0;i<hits.Length/2;i++) {
						RaycastHit tmp = hits[i];
						
						hits[i] = hits[hits.Length-1-i];
						hits[hits.Length-1-i] = tmp;
					}
					
					if (hits.Length > 0) {
						
						//lln.position = hits[0].point;
						//lln.walkable = collision.Check (lln.position);
						
						
						/*LinkedLevelNode lln = new LinkedLevelNode ();
						lln.position = hits[0].point;
						lln.walkable = collision.Check (lln.position);
						llc.first = lln;*/
						
						LinkedLevelNode lln = null;
						
						for (int i=0;i<hits.Length;i++) {
							
							LinkedLevelNode tmp = new LinkedLevelNode ();
							tmp.position = hits[i].point;
							
							if (lln != null) {
								/** \todo Use hit.distance instead */
								if (tmp.position.y - lln.position.y <= mergeSpanRange) {
									//if (tmp.position.y > lln.position.y) {
										lln.position = tmp.position;
										lln.hit = hits[i];
										lln.walkable = collision.Check (tmp.position);
									//}
									continue;
								}
							}
							
							tmp.walkable = collision.Check (tmp.position);
							tmp.hit = hits[i];
							tmp.height = float.PositiveInfinity;
							
							if (llc.first == null) {
								llc.first = tmp;
								lln = tmp;
							} else {
								lln.next = tmp;
								
								lln.height = tmp.position.y - lln.position.y;
								lln = lln.next;
							}
						
						}
					} else {
						LinkedLevelNode lln = new LinkedLevelNode ();
						lln.position = pos;
						lln.height = float.PositiveInfinity;
						lln.walkable = !collision.unwalkableWhenNoGround;
						llc.first = lln;
					}
					
					//node.penalty = 0;//Mathf.RoundToInt (Random.value*100);
					
					//node.walkable = collision.Check (node.position);
					
					//node.SetGridIndex (gridIndex);
				}
			}
			
			
			int spanCount = 0;
			layerCount = 0;
			//Count the total number of nodes in the graph
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
					
					LinkedLevelCell llc = linkedCells[z*width+x];
					
					LinkedLevelNode lln = llc.first;
					int cellCount = 0;
					//Loop through all nodes in this cell
					do {
						cellCount++;
						spanCount++;
						lln = lln.next;
					} while (lln != null);
					
					layerCount = cellCount > layerCount ? cellCount : layerCount;
				}
			}
			
			if (layerCount > LevelGridNode.MaxLayerCount) {
				Debug.LogError ("Too many layers, a maximum of LevelGridNode.MaxLayerCount are allowed (found "+layerCount+")");
				return;
			}
			
			//Create all nodes
			nodes = new LevelGridNode[width*depth*layerCount];
			for (int i=0;i<nodes.Length;i++) {
				nodes[i] = new LevelGridNode (active);
				nodes[i].Penalty = initialPenalty;
			}
			
			int nodeIndex = 0;
			
			//Max slope in cosinus
			float cosAngle = Mathf.Cos (maxSlope*Mathf.Deg2Rad);
			
			for (int z = 0; z < depth; z++) {
				for (int x = 0; x < width; x++) {
					
					LinkedLevelCell llc = linkedCells[z*width+x];
					LinkedLevelNode lln = llc.first;
					
					llc.index = nodeIndex;
					
					int count = 0;
					int layerIndex = 0;
					do {
						LevelGridNode node = nodes[z*width+x + width*depth*layerIndex] as LevelGridNode;
#if ASTAR_SET_LEVELGRIDNODE_HEIGHT
						node.height = lln.height;
#endif
						node.SetPosition ((Int3)lln.position);
						node.Walkable = lln.walkable;
						
						//Adjust penalty based on the surface slope
						if (lln.hit.normal != Vector3.zero && (penaltyAngle || cosAngle < 1.0f)) {
							//Take the dot product to find out the cosinus of the angle it has (faster than Vector3.Angle)
							float angle = Vector3.Dot (lln.hit.normal.normalized,collision.up);
							
							//Add penalty based on normal
							if (penaltyAngle) {
								node.Penalty += (uint)Mathf.RoundToInt ((1F-angle)*penaltyAngleFactor);
							}
							
							//Check if the slope is flat enough to stand on
							if (angle < cosAngle) {
								node.Walkable = false;
							}
						}
						
						node.NodeInGridIndex = z*width+x;
						//node.nodeOffset = count;
						if (lln.height < characterHeight) {
							node.Walkable = false;
						}
						
						node.WalkableErosion = node.Walkable;
						
						nodeIndex++;
						count++;
						lln = lln.next;
						layerIndex++;
					} while (lln != null);
					
					for (;layerIndex<layerCount;layerIndex++) {
						nodes[z*width+x + width*depth*layerIndex] = null;
					}
					
					llc.count = count;
				}
			}
			
			nodeIndex = 0;
			
			nodeCellIndices = new int[linkedCells.Length];
			
			for (int z = 0; z < depth; z ++) {
				for (int x = 0; x < width; x++) {
					
					/*LinkedLevelCell llc = linkedCells[z*width+x];
					LinkedLevelNode lln = llc.first;
					
					nodeCellIndices[z*width+x] = llc.index;
					
					do {
						LevelGridNode node = (LevelGridNode)nodes[nodeIndex];
						
						CalculateConnections (nodes,linkedCells,node,x,z,n);
						nodeIndex++;
						lln = lln.next;
					} while (lln != null);*/
					
					for (int i=0;i<layerCount;i++) {
						GraphNode node = nodes[z*width+x + width*depth*i];
						CalculateConnections (nodes,node,x,z,i);
					}
				}
			}
			
			uint graphIndex = (uint)active.astarData.GetGraphIndex(this);
			
			for (int i=0;i<nodes.Length;i++) {
				LevelGridNode lgn = nodes[i] as LevelGridNode;
				if (lgn == null) continue;
				
				UpdatePenalty (lgn);
				
				lgn.GraphIndex = graphIndex;
				
				//Set the node to be unwalkable if it hasn't got any connections
				if (!lgn.HasAnyGridConnections ()) {
					lgn.Walkable = false;
					lgn.WalkableErosion = lgn.Walkable;
				}
			}
					/*GridNode node = graphNodes[z*width+x];
				
					CalculateConnections (graphNodes,x,z,node);
					
					if (z == 5 && x == 5) {
						int index = z*width+x;
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.red);
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.green);
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.blue);
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.yellow);
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.cyan);
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.magenta);
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.black);
						Debug.DrawRay (node.position,(nodes[index+neighbourOffsets[0]].position-node.position)*0.5F,Color.white);
					}*/
				//}
			//}
			
			ErodeWalkableArea (0,0,width,depth);
		}