Example #1
0
        private LinkedLevelNode SampleCell(int x, int z)
        {
            LinkedLevelNode linkedLevelNode = null;
            Vector3         vector          = base.transform.Transform(new Vector3((float)x + 0.5f, 0f, (float)z + 0.5f));

            RaycastHit[] array = this.collision.CheckHeightAll(vector);
            Vector3      rhs   = base.transform.WorldUpAtGraphPosition(vector);

            for (int i = 0; i < array.Length / 2; i++)
            {
                RaycastHit raycastHit = array[i];
                array[i] = array[array.Length - 1 - i];
                array[array.Length - 1 - i] = raycastHit;
            }
            if (array.Length > 0)
            {
                LinkedLevelNode linkedLevelNode2 = null;
                for (int j = 0; j < array.Length; j++)
                {
                    LinkedLevelNode linkedLevelNode3 = new LinkedLevelNode();
                    linkedLevelNode3.position = array[j].point;
                    if (linkedLevelNode2 != null && Vector3.Dot(linkedLevelNode3.position - linkedLevelNode2.position, rhs) <= this.mergeSpanRange)
                    {
                        linkedLevelNode2.position = linkedLevelNode3.position;
                        linkedLevelNode2.hit      = array[j];
                        linkedLevelNode2.walkable = this.collision.Check(linkedLevelNode3.position);
                    }
                    else
                    {
                        linkedLevelNode3.walkable = this.collision.Check(linkedLevelNode3.position);
                        linkedLevelNode3.hit      = array[j];
                        linkedLevelNode3.height   = float.PositiveInfinity;
                        if (linkedLevelNode == null)
                        {
                            linkedLevelNode  = linkedLevelNode3;
                            linkedLevelNode2 = linkedLevelNode3;
                        }
                        else
                        {
                            linkedLevelNode2.next   = linkedLevelNode3;
                            linkedLevelNode2.height = Vector3.Dot(linkedLevelNode3.position - linkedLevelNode2.position, rhs);
                            linkedLevelNode2        = linkedLevelNode2.next;
                        }
                    }
                }
            }
            else
            {
                linkedLevelNode = new LinkedLevelNode
                {
                    position = vector,
                    height   = float.PositiveInfinity,
                    walkable = (!this.collision.unwalkableWhenNoGround && this.collision.Check(vector))
                };
            }
            return(linkedLevelNode);
        }
Example #2
0
        public override void RecalculateCell(int x, int z, bool resetPenalties = true, bool resetTags = true)
        {
            float           num             = Mathf.Cos(this.maxSlope * 0.0174532924f);
            int             i               = 0;
            LinkedLevelNode linkedLevelNode = this.SampleCell(x, z);

            while (linkedLevelNode != null)
            {
                if (i >= this.layerCount)
                {
                    if (i + 1 > 255)
                    {
                        Debug.LogError(string.Concat(new object[]
                        {
                            "Too many layers, a maximum of ",
                            255,
                            " are allowed (required ",
                            i + 1,
                            ")"
                        }));
                        return;
                    }
                    this.AddLayers(1);
                }
                int           num2          = z * this.width + x + this.width * this.depth * i;
                LevelGridNode levelGridNode = this.nodes[num2];
                bool          flag          = levelGridNode == null;
                if (flag)
                {
                    if (this.nodes[num2] != null)
                    {
                        this.nodes[num2].Destroy();
                    }
                    levelGridNode = (this.nodes[num2] = new LevelGridNode(this.active));
                    levelGridNode.NodeInGridIndex       = z * this.width + x;
                    levelGridNode.LayerCoordinateInGrid = i;
                    levelGridNode.GraphIndex            = this.graphIndex;
                }
                if (flag || resetPenalties)
                {
                    levelGridNode.Penalty = this.initialPenalty;
                    if (this.penaltyPosition)
                    {
                        levelGridNode.Penalty += (uint)Mathf.RoundToInt(((float)levelGridNode.position.y - this.penaltyPositionOffset) * this.penaltyPositionFactor);
                    }
                }
                if (flag || resetTags)
                {
                    levelGridNode.Tag = 0u;
                }
                levelGridNode.position        = (Int3)linkedLevelNode.position;
                levelGridNode.Walkable        = linkedLevelNode.walkable;
                levelGridNode.WalkableErosion = levelGridNode.Walkable;
                if (linkedLevelNode.hit.normal != Vector3.zero && (this.penaltyAngle || num > 0.0001f))
                {
                    float num3 = Vector3.Dot(linkedLevelNode.hit.normal.normalized, this.collision.up);
                    if (resetTags && this.penaltyAngle)
                    {
                        levelGridNode.Penalty += (uint)Mathf.RoundToInt((1f - num3) * this.penaltyAngleFactor);
                    }
                    if (num3 < num)
                    {
                        levelGridNode.Walkable = false;
                    }
                }
                if (linkedLevelNode.height < this.characterHeight)
                {
                    levelGridNode.Walkable = false;
                }
                levelGridNode.WalkableErosion = levelGridNode.Walkable;
                linkedLevelNode = linkedLevelNode.next;
                i++;
            }
            while (i < this.layerCount)
            {
                int num4 = z * this.width + x + this.width * this.depth * i;
                if (this.nodes[num4] != null)
                {
                    this.nodes[num4].Destroy();
                }
                this.nodes[num4] = null;
                i++;
            }
        }
Example #3
0
        public override IEnumerable <Progress> ScanInternal()
        {
            if (this.nodeSize <= 0f)
            {
                yield break;
            }
            base.UpdateTransform();
            if (this.width > 1024 || this.depth > 1024)
            {
                Debug.LogError("One of the grid's sides is longer than 1024 nodes");
                yield break;
            }
            this.lastScannedWidth = this.width;
            this.lastScannedDepth = this.depth;
            this.SetUpOffsetsAndCosts();
            LevelGridNode.SetGridGraph((int)this.graphIndex, this);
            this.maxClimb = Mathf.Clamp(this.maxClimb, 0f, this.characterHeight);
            LinkedLevelNode[] linkedCells = new LinkedLevelNode[this.width * this.depth];
            this.collision = (this.collision ?? new GraphCollision());
            this.collision.Initialize(base.transform, this.nodeSize);
            int progressCounter = 0;

            for (int z = 0; z < this.depth; z++)
            {
                if (progressCounter >= 1000)
                {
                    progressCounter = 0;
                    yield return(new Progress(Mathf.Lerp(0.1f, 0.5f, (float)z / (float)this.depth), "Calculating positions"));
                }
                progressCounter += this.width;
                for (int i = 0; i < this.width; i++)
                {
                    linkedCells[z * this.width + i] = this.SampleCell(i, z);
                }
            }
            this.layerCount = 0;
            for (int j = 0; j < linkedCells.Length; j++)
            {
                int num = 0;
                for (LinkedLevelNode linkedLevelNode = linkedCells[j]; linkedLevelNode != null; linkedLevelNode = linkedLevelNode.next)
                {
                    num++;
                }
                this.layerCount = Math.Max(this.layerCount, num);
            }
            if (this.layerCount > 255)
            {
                Debug.LogError(string.Concat(new object[]
                {
                    "Too many layers, a maximum of ",
                    255,
                    " (LevelGridNode.MaxLayerCount) layers are allowed (found ",
                    this.layerCount,
                    ")"
                }));
                yield break;
            }
            this.nodes = new LevelGridNode[this.width * this.depth * this.layerCount];
            for (int z2 = 0; z2 < this.depth; z2++)
            {
                if (progressCounter >= 1000)
                {
                    progressCounter = 0;
                    yield return(new Progress(Mathf.Lerp(0.5f, 0.8f, (float)z2 / (float)this.depth), "Creating nodes"));
                }
                progressCounter += this.width;
                for (int k = 0; k < this.width; k++)
                {
                    this.RecalculateCell(k, z2, true, true);
                }
            }
            for (int z3 = 0; z3 < this.depth; z3++)
            {
                if (progressCounter >= 1000)
                {
                    progressCounter = 0;
                    yield return(new Progress(Mathf.Lerp(0.8f, 0.9f, (float)z3 / (float)this.depth), "Calculating connections"));
                }
                progressCounter += this.width;
                for (int l = 0; l < this.width; l++)
                {
                    this.CalculateConnections(l, z3);
                }
            }
            yield return(new Progress(0.95f, "Calculating Erosion"));

            for (int m = 0; m < this.nodes.Length; m++)
            {
                LevelGridNode levelGridNode = this.nodes[m];
                if (levelGridNode != null)
                {
                    if (!levelGridNode.HasAnyGridConnections())
                    {
                        levelGridNode.Walkable        = false;
                        levelGridNode.WalkableErosion = levelGridNode.Walkable;
                    }
                }
            }
            this.ErodeWalkableArea();
            yield break;
        }
        public override void Scan()
        {
            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);

            int gridIndex = LevelGridNode.SetGridGraph (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 = CreateNodes (width*depth*layerCount);

            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.position = (Int3)lln.position;
                        node.walkable = lln.walkable;
                        node.Bit15 = node.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.SetIndex (z*width+x);
                        //node.nodeOffset = count;
                        if (lln.height < characterHeight) {
                            node.walkable = false;
                        }
                        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++) {
                        Node node = nodes[z*width+x + width*depth*i];
                        CalculateConnections (nodes,node,x,z,i);
                    }
                }
            }

            for (int i=0;i<nodes.Length;i++) {
                LevelGridNode lgn = nodes[i] as LevelGridNode;
                if (lgn == null) continue;

                UpdatePenalty (lgn);

                lgn.SetGridIndex (gridIndex);

                //Set the node to be unwalkable if it hasn't got any connections
                if (!lgn.HasAnyGridConnections ()) {
                    lgn.walkable = false;
                }
            }
                    /*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);
        }
        /** Recalculates single cell.
         *
         * \param x X coordinate of the cell
         * \param z Z coordinate of the cell
         * \param preserveExistingNodes If true, nodes will be reused, this can be used to preserve e.g penalty when recalculating
         *
         * \returns If new layers or nodes were added. If so, you need to call
         * AstarPath.active.DataUpdate() after this function to make sure pathfinding works correctly for them
         * (when doing a scan, that function does not need to be called however).
         *
         * \note Connections are not recalculated for the nodes.
         */
        public bool RecalculateCell(int x, int z, bool preserveExistingNodes)
        {
            LinkedLevelCell llc = new LinkedLevelCell ();
            //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;
            }

            bool addedNodes = false;

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

            //=========

            {
                //llc
                LinkedLevelNode lln = llc.first;

                int count = 0;
                int layerIndex = 0;
                do {

                    if (layerIndex >= layerCount) {
                        if (layerIndex+1 > LevelGridNode.MaxLayerCount) {
                            Debug.LogError ("Too many layers, a maximum of LevelGridNode.MaxLayerCount are allowed (required "+(layerIndex+1)+")");
                            return addedNodes;
                        }

                        AddLayers (1);
                        addedNodes = true;
                    }

                    LevelGridNode node = nodes[z*width+x + width*depth*layerIndex] as LevelGridNode;

                    if (node == null || !preserveExistingNodes) {
                        //Create a new node
                        nodes[z*width+x + width*depth*layerIndex] = new LevelGridNode();
                        node = nodes[z*width+x + width*depth*layerIndex] as LevelGridNode;
                        node.penalty = initialPenalty;
                        node.SetGridIndex (LevelGridNode.SetGridGraph(this));
                        addedNodes = true;
                    }

                    node.connections = null;
            #if ASTAR_SET_LEVELGRIDNODE_HEIGHT
                    node.height = lln.height;
            #endif
                    node.position = (Int3)lln.position;
                    node.walkable = lln.walkable;
                    node.Bit15 = node.walkable;

                    //Adjust penalty based on the surface slope
                    if (lln.hit.normal != Vector3.zero) {
                        //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);
                        }

                        //Max slope in cosinus
                        float cosAngle = Mathf.Cos (maxSlope*Mathf.Deg2Rad);

                        //Check if the slope is flat enough to stand on
                        if (angle < cosAngle) {
                            node.walkable = false;
                        }
                    }

                    node.SetIndex (z*width+x);
                    //node.nodeOffset = count;
                    if (lln.height < characterHeight) {
                        node.walkable = false;
                    }
                    count++;
                    lln = lln.next;
                    layerIndex++;
                } while (lln != null);

                for (;layerIndex<layerCount;layerIndex++) {
                    nodes[z*width+x + width*depth*layerIndex] = null;
                }

                llc.count = count;
            }

            return addedNodes;
        }
		public override void ScanInternal (OnScanStatus statusCallback) {

			if (nodeSize <= 0) {
				return;
			}

			GenerateMatrix ();

			if (width > 1024 || depth > 1024) {
				Debug.LogError ("One of the grid's sides is longer than 1024 nodes");
				return;
			}

			lastScannedWidth = width;
			lastScannedDepth = depth;

			SetUpOffsetsAndCosts ();

			LevelGridNode.SetGridGraph (active.astarData.GetGraphIndex(this), this);

			maxClimb = Mathf.Clamp (maxClimb,0,characterHeight);

			var linkedCells = new LinkedLevelCell[width*depth];

			collision = 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];

					Vector3 pos = matrix.MultiplyPoint3x4 (new Vector3 (x+0.5F,0,z+0.5F));


					RaycastHit[] hits = collision.CheckHeightAll (pos);

					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) {

						LinkedLevelNode lln = null;

						for (int i=0;i<hits.Length;i++) {

							var tmp = new LinkedLevelNode ();
							tmp.position = hits[i].point;

							if (lln != null) {
								/** \todo Use hit.distance instead */
								if (tmp.position.y - lln.position.y <= mergeSpanRange) {
										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 {
						var lln = new LinkedLevelNode ();
						lln.position = pos;
						lln.height = float.PositiveInfinity;
						lln.walkable = !collision.unwalkableWhenNoGround;
						llc.first = lln;
					}
				}
			}


			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 {
						var node = nodes[z*width+x + width*depth*layerIndex];
#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;

						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++) {
					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++) {
				var lgn = nodes[i];
				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;
				}
			}

			ErodeWalkableArea ();
		}
Example #7
0
        public bool RecalculateCell(int x, int z, bool preserveExistingNodes)
        {
            LinkedLevelCell linkedLevelCell = new LinkedLevelCell();
            Vector3         position        = this.matrix.MultiplyPoint3x4(new Vector3((float)x + 0.5f, 0f, (float)z + 0.5f));

            RaycastHit[] array = this.collision.CheckHeightAll(position);
            for (int i = 0; i < array.Length / 2; i++)
            {
                RaycastHit raycastHit = array[i];
                array[i] = array[array.Length - 1 - i];
                array[array.Length - 1 - i] = raycastHit;
            }
            bool result = false;

            if (array.Length > 0)
            {
                LinkedLevelNode linkedLevelNode = null;
                for (int j = 0; j < array.Length; j++)
                {
                    LinkedLevelNode linkedLevelNode2 = new LinkedLevelNode();
                    linkedLevelNode2.position = array[j].point;
                    if (linkedLevelNode != null && linkedLevelNode2.position.y - linkedLevelNode.position.y <= this.mergeSpanRange)
                    {
                        linkedLevelNode.position = linkedLevelNode2.position;
                        linkedLevelNode.hit      = array[j];
                        linkedLevelNode.walkable = this.collision.Check(linkedLevelNode2.position);
                    }
                    else
                    {
                        linkedLevelNode2.walkable = this.collision.Check(linkedLevelNode2.position);
                        linkedLevelNode2.hit      = array[j];
                        linkedLevelNode2.height   = float.PositiveInfinity;
                        if (linkedLevelCell.first == null)
                        {
                            linkedLevelCell.first = linkedLevelNode2;
                            linkedLevelNode       = linkedLevelNode2;
                        }
                        else
                        {
                            linkedLevelNode.next   = linkedLevelNode2;
                            linkedLevelNode.height = linkedLevelNode2.position.y - linkedLevelNode.position.y;
                            linkedLevelNode        = linkedLevelNode.next;
                        }
                    }
                }
            }
            else
            {
                linkedLevelCell.first = new LinkedLevelNode
                {
                    position = position,
                    height   = float.PositiveInfinity,
                    walkable = !this.collision.unwalkableWhenNoGround
                };
            }
            uint            graphIndex       = (uint)this.active.astarData.GetGraphIndex(this);
            LinkedLevelNode linkedLevelNode3 = linkedLevelCell.first;
            int             num = 0;
            int             k   = 0;

            while (true)
            {
                if (k >= this.layerCount)
                {
                    if (k + 1 > 255)
                    {
                        break;
                    }
                    this.AddLayers(1);
                    result = true;
                }
                LevelGridNode levelGridNode = this.nodes[z * this.width + x + this.width * this.depth * k];
                if (levelGridNode == null || !preserveExistingNodes)
                {
                    this.nodes[z * this.width + x + this.width * this.depth * k] = new LevelGridNode(this.active);
                    levelGridNode            = this.nodes[z * this.width + x + this.width * this.depth * k];
                    levelGridNode.Penalty    = this.initialPenalty;
                    levelGridNode.GraphIndex = graphIndex;
                    result = true;
                }
                levelGridNode.SetPosition((Int3)linkedLevelNode3.position);
                levelGridNode.Walkable        = linkedLevelNode3.walkable;
                levelGridNode.WalkableErosion = levelGridNode.Walkable;
                if (linkedLevelNode3.hit.normal != Vector3.zero)
                {
                    float num2 = Vector3.Dot(linkedLevelNode3.hit.normal.normalized, this.collision.up);
                    if (this.penaltyAngle)
                    {
                        levelGridNode.Penalty += (uint)Mathf.RoundToInt((1f - num2) * this.penaltyAngleFactor);
                    }
                    float num3 = Mathf.Cos(this.maxSlope * 0.0174532924f);
                    if (num2 < num3)
                    {
                        levelGridNode.Walkable = false;
                    }
                }
                levelGridNode.NodeInGridIndex = z * this.width + x;
                if (linkedLevelNode3.height < this.characterHeight)
                {
                    levelGridNode.Walkable = false;
                }
                num++;
                linkedLevelNode3 = linkedLevelNode3.next;
                k++;
                if (linkedLevelNode3 == null)
                {
                    goto Block_14;
                }
            }
            Debug.LogError("Too many layers, a maximum of LevelGridNode.MaxLayerCount are allowed (required " + (k + 1) + ")");
            return(result);

Block_14:
            while (k < this.layerCount)
            {
                this.nodes[z * this.width + x + this.width * this.depth * k] = null;
                k++;
            }
            linkedLevelCell.count = num;
            return(result);
        }
Example #8
0
        public override void ScanInternal(OnScanStatus status)
        {
            this.scans++;
            if (this.nodeSize <= 0f)
            {
                return;
            }
            base.GenerateMatrix();
            if (this.width > 1024 || this.depth > 1024)
            {
                Debug.LogError("One of the grid's sides is longer than 1024 nodes");
                return;
            }
            this.lastScannedWidth = this.width;
            this.lastScannedDepth = this.depth;
            this.SetUpOffsetsAndCosts();
            LevelGridNode.SetGridGraph(this.active.astarData.GetGraphIndex(this), this);
            this.maxClimb = Mathf.Clamp(this.maxClimb, 0f, this.characterHeight);
            LinkedLevelCell[] array = new LinkedLevelCell[this.width * this.depth];
            if (this.collision == null)
            {
                this.collision = new GraphCollision();
            }
            this.collision.Initialize(this.matrix, this.nodeSize);
            for (int i = 0; i < this.depth; i++)
            {
                for (int j = 0; j < this.width; j++)
                {
                    array[i * this.width + j] = new LinkedLevelCell();
                    LinkedLevelCell linkedLevelCell = array[i * this.width + j];
                    Vector3         position        = this.matrix.MultiplyPoint3x4(new Vector3((float)j + 0.5f, 0f, (float)i + 0.5f));
                    RaycastHit[]    array2          = this.collision.CheckHeightAll(position);
                    for (int k = 0; k < array2.Length / 2; k++)
                    {
                        RaycastHit raycastHit = array2[k];
                        array2[k] = array2[array2.Length - 1 - k];
                        array2[array2.Length - 1 - k] = raycastHit;
                    }
                    if (array2.Length > 0)
                    {
                        LinkedLevelNode linkedLevelNode = null;
                        for (int l = 0; l < array2.Length; l++)
                        {
                            LinkedLevelNode linkedLevelNode2 = new LinkedLevelNode();
                            linkedLevelNode2.position = array2[l].point;
                            if (linkedLevelNode != null && linkedLevelNode2.position.y - linkedLevelNode.position.y <= this.mergeSpanRange)
                            {
                                linkedLevelNode.position = linkedLevelNode2.position;
                                linkedLevelNode.hit      = array2[l];
                                linkedLevelNode.walkable = this.collision.Check(linkedLevelNode2.position);
                            }
                            else
                            {
                                linkedLevelNode2.walkable = this.collision.Check(linkedLevelNode2.position);
                                linkedLevelNode2.hit      = array2[l];
                                linkedLevelNode2.height   = float.PositiveInfinity;
                                if (linkedLevelCell.first == null)
                                {
                                    linkedLevelCell.first = linkedLevelNode2;
                                    linkedLevelNode       = linkedLevelNode2;
                                }
                                else
                                {
                                    linkedLevelNode.next   = linkedLevelNode2;
                                    linkedLevelNode.height = linkedLevelNode2.position.y - linkedLevelNode.position.y;
                                    linkedLevelNode        = linkedLevelNode.next;
                                }
                            }
                        }
                    }
                    else
                    {
                        linkedLevelCell.first = new LinkedLevelNode
                        {
                            position = position,
                            height   = float.PositiveInfinity,
                            walkable = !this.collision.unwalkableWhenNoGround
                        };
                    }
                }
            }
            int num = 0;

            this.layerCount = 0;
            for (int m = 0; m < this.depth; m++)
            {
                for (int n = 0; n < this.width; n++)
                {
                    LinkedLevelCell linkedLevelCell2 = array[m * this.width + n];
                    LinkedLevelNode linkedLevelNode3 = linkedLevelCell2.first;
                    int             num2             = 0;
                    do
                    {
                        num2++;
                        num++;
                        linkedLevelNode3 = linkedLevelNode3.next;
                    }while (linkedLevelNode3 != null);
                    this.layerCount = ((num2 <= this.layerCount) ? this.layerCount : num2);
                }
            }
            if (this.layerCount > 255)
            {
                Debug.LogError("Too many layers, a maximum of LevelGridNode.MaxLayerCount are allowed (found " + this.layerCount + ")");
                return;
            }
            this.nodes = new LevelGridNode[this.width * this.depth * this.layerCount];
            for (int num3 = 0; num3 < this.nodes.Length; num3++)
            {
                this.nodes[num3]         = new LevelGridNode(this.active);
                this.nodes[num3].Penalty = this.initialPenalty;
            }
            int   num4 = 0;
            float num5 = Mathf.Cos(this.maxSlope * 0.0174532924f);

            for (int num6 = 0; num6 < this.depth; num6++)
            {
                for (int num7 = 0; num7 < this.width; num7++)
                {
                    LinkedLevelCell linkedLevelCell3 = array[num6 * this.width + num7];
                    LinkedLevelNode linkedLevelNode4 = linkedLevelCell3.first;
                    linkedLevelCell3.index = num4;
                    int num8 = 0;
                    int num9 = 0;
                    do
                    {
                        LevelGridNode levelGridNode = this.nodes[num6 * this.width + num7 + this.width * this.depth * num9];
                        levelGridNode.SetPosition((Int3)linkedLevelNode4.position);
                        levelGridNode.Walkable = linkedLevelNode4.walkable;
                        if (linkedLevelNode4.hit.normal != Vector3.zero && (this.penaltyAngle || num5 < 1f))
                        {
                            float num10 = Vector3.Dot(linkedLevelNode4.hit.normal.normalized, this.collision.up);
                            if (this.penaltyAngle)
                            {
                                levelGridNode.Penalty += (uint)Mathf.RoundToInt((1f - num10) * this.penaltyAngleFactor);
                            }
                            if (num10 < num5)
                            {
                                levelGridNode.Walkable = false;
                            }
                        }
                        levelGridNode.NodeInGridIndex = num6 * this.width + num7;
                        if (linkedLevelNode4.height < this.characterHeight)
                        {
                            levelGridNode.Walkable = false;
                        }
                        levelGridNode.WalkableErosion = levelGridNode.Walkable;
                        num4++;
                        num8++;
                        linkedLevelNode4 = linkedLevelNode4.next;
                        num9++;
                    }while (linkedLevelNode4 != null);
                    while (num9 < this.layerCount)
                    {
                        this.nodes[num6 * this.width + num7 + this.width * this.depth * num9] = null;
                        num9++;
                    }
                    linkedLevelCell3.count = num8;
                }
            }
            this.nodeCellIndices = new int[array.Length];
            for (int num11 = 0; num11 < this.depth; num11++)
            {
                for (int num12 = 0; num12 < this.width; num12++)
                {
                    for (int num13 = 0; num13 < this.layerCount; num13++)
                    {
                        GraphNode node = this.nodes[num11 * this.width + num12 + this.width * this.depth * num13];
                        this.CalculateConnections(this.nodes, node, num12, num11, num13);
                    }
                }
            }
            uint graphIndex = (uint)this.active.astarData.GetGraphIndex(this);

            for (int num14 = 0; num14 < this.nodes.Length; num14++)
            {
                LevelGridNode levelGridNode2 = this.nodes[num14];
                if (levelGridNode2 != null)
                {
                    this.UpdatePenalty(levelGridNode2);
                    levelGridNode2.GraphIndex = graphIndex;
                    if (!levelGridNode2.HasAnyGridConnections())
                    {
                        levelGridNode2.Walkable        = false;
                        levelGridNode2.WalkableErosion = levelGridNode2.Walkable;
                    }
                }
            }
            this.ErodeWalkableArea(0, 0, this.width, this.depth);
        }