Beispiel #1
0
        /// <summary>
        /// Outside code should only call this on the root. This method will recursively construct an entire quadtree starting
        /// from the root node. It will continue to expand a branch of the tree until any new nodes would have to
        /// have a resolution greater than that of the heightmap itself.
        /// </summary>
        public void RecursivelyBuildTree()
        {
            // Get this chunk's index.

            index = quadTree.GetNextChunkIndex();

            // First compute the net world transform for this node.

            worldTransform = Matrix.CreateScale(scaleFactor, 1.0f, scaleFactor) * Matrix.CreateTranslation(centerWorldPosition);

            // Calculate the texture coordinate range for this chunk.

            textureCoordinates = new TerrainChunkTextureCoordinates();

            float terrainDimension = 2 * quadTree.Parameters.TerrainScale;

            textureCoordinates.UStart = ((centerWorldPosition.X - scaleFactor / 2.0f + terrainDimension / 2.0f) / terrainDimension - 0.25f) * 2f;
            textureCoordinates.UEnd = ((centerWorldPosition.X + scaleFactor / 2.0f + terrainDimension / 2.0f) / terrainDimension - 0.25f) * 2f;
            textureCoordinates.VStart = ((centerWorldPosition.Z - scaleFactor / 2.0f + terrainDimension / 2.0f) / terrainDimension - 0.25f) * 2f;
            textureCoordinates.VEnd = ((centerWorldPosition.Z + scaleFactor / 2.0f + terrainDimension / 2.0f) / terrainDimension - 0.25f) * 2f;

            // Construct the bounding box to be used for frustum culling

            boundingBox = new BoundingBox(new Vector3(centerWorldPosition.X - scaleFactor / 2.0f, 0.0f, centerWorldPosition.Z - scaleFactor / 2.0f),
                                         new Vector3(centerWorldPosition.X + scaleFactor / 2.0f, quadTree.Parameters.MaxHeight, centerWorldPosition.Z + scaleFactor / 2.0f));

            // If this node has a lower resolution than the heightmap itself, we expand it into four children.
            // Otherwise, this branch of the tree ends.

            children = new List<TerrainChunk>();

            if (quadTree.HeightMap.Width / quadTree.Parameters.TerrainScale >= quadTree.CommonGrid.Dimension / scaleFactor)
            {
                // This isn't a leaf chunk, so we compute/look up its geometric error.

                if (quadTree.Parameters.DoPreprocessing)
                {
                    // Compute it manually

                    geometricError = ComputeRawGeometricError();
                    quadTree.ChunkGeometricErrors[index] = geometricError;
                }
                else
                {
                    // Look it up from the precomputed table

                    geometricError = quadTree.ChunkGeometricErrors[index];
                }

                // Expand into four children

                TerrainChunk child1 = new TerrainChunk(quadTree, this,
                                                       centerWorldPosition + new Vector3(scaleFactor / 4.0f, 0.0f, scaleFactor / 4.0f),
                                                       scaleFactor / 2.0f);

                TerrainChunk child2 = new TerrainChunk(quadTree, this,
                                                       centerWorldPosition + new Vector3(scaleFactor / 4.0f, 0.0f, -scaleFactor / 4.0f),
                                                       scaleFactor / 2.0f);

                TerrainChunk child3 = new TerrainChunk(quadTree, this,
                                                       centerWorldPosition + new Vector3(-scaleFactor / 4.0f, 0.0f, scaleFactor / 4.0f),
                                                       scaleFactor / 2.0f);

                TerrainChunk child4 = new TerrainChunk(quadTree, this,
                                                       centerWorldPosition + new Vector3(-scaleFactor / 4.0f, 0.0f, -scaleFactor / 4.0f),
                                                       scaleFactor / 2.0f);

                children.Add(child1);
                children.Add(child2);
                children.Add(child3);
                children.Add(child4);

                child1.RecursivelyBuildTree();
                child2.RecursivelyBuildTree();
                child3.RecursivelyBuildTree();
                child4.RecursivelyBuildTree();
            }

            // Finally, as the recursion unwinds, we accumulate the geometric error from children.

            if (children.Count > 0)
            {
                geometricError += (float)Math.Max(children[0].GeometricError, Math.Max(children[1].GeometricError,
                                                  Math.Max(children[2].GeometricError, children[3].GeometricError)));
            }

            minimumDistanceToSplit = geometricError / quadTree.Parameters.MaxScreenSpaceError * quadTree.Parameters.PerspectiveScalingFactor;
        }
        /// <summary>
        /// This method constructs the terrain quad tree structure, creating all the terrain chunks and geometry.
        /// </summary>
        private void ConstructQuadTree()
        {
            // Set up the root node centered at the origin and scaled to fit the entire terrain.

            rootNode = new TerrainChunk(this, null, new Vector3(), parameters.TerrainScale);

            // This will take care of the rest!

            rootNode.RecursivelyBuildTree();
        }