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