Exemplo n.º 1
0
        public void AddNode(NavMeshNode node, bool skipAABBUpdate)
        {
            bool boundingBoxUpdateNeeded = false;

            if (node.VertexTopLeft < minNodeValue || minNodeValue == SizeInvalid)
            {
                minNodeValue            = node.VertexTopLeft;
                boundingBoxUpdateNeeded = true;
            }

            if (node.VertexTopLeft > maxNodeValue || maxNodeValue == SizeInvalid)
            {
                maxNodeValue            = node.VertexTopLeft;
                boundingBoxUpdateNeeded = true;
            }

            if (!skipAABBUpdate && boundingBoxUpdateNeeded)
            {
                boundingBox.Min   = this.parent.TerrainComp.VertexList[minNodeValue].Position;
                boundingBox.Min.Y = 0.0f;

                NavMeshNode maxNode;
                meshNodes.TryGetValue(maxNodeValue, out maxNode);

                if (maxNode != null)
                {
                    boundingBox.Max   = this.parent.TerrainComp.VertexList[maxNode.VertexBottomRight].Position;
                    boundingBox.Max.Y = 1000.0f;
                }
            }

            meshNodes.Add(node.VertexTopLeft, node);
        }
Exemplo n.º 2
0
        public void GenerateNavMesh(BaseEntity terrain)
        {
            this.terrain     = terrain;
            this.terrainComp = this.terrain.GetComponentByType(ComponentType.TerrainComponent) as TerrainComponent;

            // Process each pixel of the heightmap as a navmeshnode.
            // Create a navmeshnode, even if the slope is too great.
            int width = this.terrainComp.Size;

            int widthMinusOne = width - 1;

            // Find four vertexs that comprise a node
            for (int x = 0; x < widthMinusOne; ++x)
            {
                for (int z = 0; z < widthMinusOne; ++z)
                {
                    NavMeshNode newNode = new NavMeshNode((x + (z * width)), width);

                    // Grab the normal of the quad that makes up this NavMeshNode, because the terrain engine organizes triangles into
                    //   quads, we don't need to check both triangles in the quad, as they'll have the same normal. So, any corner of the
                    //   quad will have the same normal, we'll just take the topleft corner's normal.
                    newNode.Normal = this.terrainComp.normals[newNode.ZCoordTopLeft, newNode.XCoordTopLeft];

                    nodeDictionary.Add(newNode.VertexTopLeft, newNode);
                }
            }

            // Postprocess step, optimize navmesh by combining navmeshnodes into navmeshchunks.
            for (int x = 0; x < widthMinusOne; ++x)
            {
                for (int z = 0; z < widthMinusOne; ++z)
                {
                    int topLeftVertex = x + (z * width);

                    // Check if there is a node at this [x, z] location, if there isn't then it has already
                    // been processed into a chunk
                    if (nodeDictionary.ContainsKey(topLeftVertex))
                    {
                        NavMeshNode node;
                        nodeDictionary.TryGetValue(topLeftVertex, out node);

                        if (node != null)
                        {
                            NavMeshChunk newChunk = new NavMeshChunk(this.parent);

                            ProcessNewChunk(newChunk, node);
                        }
                        else
                        {
                            throw new Exception("Failed to find a value in 'nodeDictionary'");
                        }
                    }
                }
            }

            // Once all chunks are created, we need to go through each chunk, and create a list of connection points between chunks so we know how
            // to navigate from chunk to chunk.

            meshGenerated = true;
        }
Exemplo n.º 3
0
        public void RemoveNode(NavMeshNode node)
        {
            if (meshNodes.Count == 0)
            {
                return;
            }

            meshNodes.Remove(node.VertexTopLeft);

            if (node.VertexTopLeft == minNodeValue || node.VertexTopLeft == maxNodeValue)
            {
                // We need to find the new lowest and highest values before RemoveNode() will function properly
                //minNodeValue = meshNodes.Keys.Min();
                //maxNodeValue = meshNodes.Keys.Max();

                UpdateAABB();
            }
        }
Exemplo n.º 4
0
        private void ProcessNewChunk(NavMeshChunk chunk, NavMeshNode startingNode)
        {
            bool columnsAvail = true;
            bool rowsAvail    = true;

            chunk.AddNode(startingNode, true);

            chunkDictionary.Add(startingNode.VertexTopLeft, chunk);
            nodeDictionary.Remove(startingNode.VertexTopLeft);

            if (startingNode.TooSteep)
            {
                return;
            }

            //// TEMP!!!!!!!!!!!!!!!!!!!!
            //if (startingNode.VertexTopLeft == 0)
            //{
            //    int i = 5;
            //    i++;
            //}

            while (columnsAvail || rowsAvail)
            {
                if (columnsAvail)
                {
                    columnsAvail = AddNewColumnToChunk(chunk);
                }

                if (rowsAvail)
                {
                    rowsAvail = AddNewRowToChunk(chunk);
                }
            }

            // Once we've made it here, that means the current chunk cannot expand any more
        }