/// <summary>
        /// Procesar el mapa de alturas
        /// </summary>
        /// <param name="input">Información del escenario de entrada</param>
        /// <param name="context">Contexto de procesado</param>
        /// <returns>Devuelve la información de escenario leída</returns>
        public override SceneryInfo Process(SceneryFile input, ContentProcessorContext context)
        {
            // Cargar la textura del mapa de alturas
            Texture2DContent terrain = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.HeightMapFile), null);

            // Obtener el mapa de alturas
            HeightMap heightMap = this.BuildHeightMap(terrain, input.HeightMapCellScale, context);

            // Generar los vértices e inicializar el buffer de vértices
            VertexMultitextured[] vertList = heightMap.BuildVertices(
                input.HeightMapCellSize,
                input.ProportionTexture1,
                input.ProportionTexture2,
                input.ProportionTexture3);
            VertexBufferContent vertexBuffer = new VertexBufferContent(VertexMultitextured.SizeInBytes * vertList.Length);

            vertexBuffer.Write <VertexMultitextured>(0, VertexMultitextured.SizeInBytes, vertList, context.TargetPlatform);

            // Generar los índices e inicializar los buffers de índices
            double          lowOrderLevels   = (Math.Sqrt(heightMap.DataLength) - 1) * 0.5f;
            int             levelCount       = Convert.ToInt32(Math.Log(lowOrderLevels, 4.0d));
            SceneryNodeInfo sceneryIndexInfo = SceneryNodeInfo.Build(
                vertList,
                heightMap.Width,
                heightMap.Deep,
                levelCount);

            // Efecto de renderización
            CompiledEffect effect = Effect.CompileEffectFromFile(
                input.EffectFile,
                null,
                null,
                CompilerOptions.None,
                context.TargetPlatform);

            // Texturas del terreno
            Texture2DContent texture1       = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.Texture1File), null);
            Texture2DContent texture2       = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.Texture2File), null);
            Texture2DContent texture3       = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.Texture3File), null);
            Texture2DContent texture4       = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.Texture4File), null);
            Texture2DContent detailTexture1 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.DetailTexture1File), null);
            Texture2DContent detailTexture2 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.DetailTexture2File), null);
            Texture2DContent detailTexture3 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.DetailTexture3File), null);
            Texture2DContent detailTexture4 = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.DetailTexture4File), null);

            CompiledEffect billboardEffect = Effect.CompileEffectFromFile(
                input.BillboardEffectFile,
                null,
                null,
                CompilerOptions.None,
                context.TargetPlatform);

            Texture2DContent billboardGrassTexture = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.BillboardGrassTextureFile), null);
            Texture2DContent billboardTreeTexture  = context.BuildAndLoadAsset <Texture2DContent, Texture2DContent>(new ExternalReference <Texture2DContent>(input.BillboardTreeTextureFile), null);
            int   billboardsPerTriangle            = input.BillboardsPerTriangle;
            float billboardTreesPercent            = input.BillboardTreesPercent;

            return(new SceneryInfo()
            {
                Terrain = terrain,
                TerrainBuffer = vertexBuffer,
                TerrainBufferVertexCount = vertList.Length,
                TerrainInfo = sceneryIndexInfo,
                Effect = effect,
                Texture1 = texture1,
                Texture2 = texture2,
                Texture3 = texture3,
                Texture4 = texture4,
                DetailTexture1 = detailTexture1,
                DetailTexture2 = detailTexture2,
                DetailTexture3 = detailTexture3,
                DetailTexture4 = detailTexture4,
                BillboardEffect = billboardEffect,
                BillboardGrass = billboardGrassTexture,
                BillboardTree = billboardTreeTexture,
                BillboardsPerTriangle = billboardsPerTriangle,
                BillboardTreesPercent = billboardTreesPercent,
            });
        }
Exemple #2
0
        /// <summary>
        /// Construye la información de nodos del terreno
        /// </summary>
        /// <param name="vertList">Lista de vértices</param>
        /// <param name="width">Anchura del terreno</param>
        /// <param name="deep">Profundidad del terreno</param>
        /// <param name="levels">Niveles distintos de detalle</param>
        /// <returns>Devuelve la información de nodos del terreno</returns>
        public static SceneryNodeInfo Build(
            VertexMultitextured[] vertList,
            int width,
            int deep,
            int levels)
        {
            // Lista resultante de nodos
            List <SceneryTriangleNode> nodes = new List <SceneryTriangleNode>();

            // Diccionario de índices
            Dictionary <LOD, IndexCollection> indices = new Dictionary <LOD, IndexCollection>();

            IndexCollection highIndices   = new IndexCollection();
            IndexCollection mediumIndices = new IndexCollection();
            IndexCollection lowIndices    = new IndexCollection();

            // Tamaño de la cuadrícula
            int totalCellsX = width;
            int totalCellsZ = deep;

            // Número de divisiones
            int divisions  = Convert.ToInt32(Math.Pow(4, levels));
            int divisionsX = divisions / 2;
            int divisionsZ = divisions / 2;

            // Número de vértices en X y en Z
            int numVertexesX = (totalCellsX / divisionsX);
            int numVertexesZ = (totalCellsZ / divisionsZ);

            // Número total de vértices, triángulos e índices
            int totalVertices  = totalCellsX * totalCellsZ;
            int totalTriangles = (totalCellsX - 1) * (totalCellsZ - 1) * 2;
            int totalIndices   = totalTriangles * 3;

            for (int x = 0; x < divisionsX; x++)
            {
                int offsetX = x * numVertexesX;
                int cellsX  = numVertexesX;

                for (int z = 0; z < divisionsZ; z++)
                {
                    int offsetZ = z * numVertexesZ;
                    int cellsZ  = numVertexesZ;

                    // Crear índices para generar la lista de triángulos de colisión
                    int[] collisionIndices = SceneryNodeInfo.CreateCollisionIndices(
                        offsetX,
                        offsetZ,
                        cellsX,
                        cellsZ,
                        totalCellsX,
                        totalCellsZ);

                    // Crear la lista de triángulos
                    Triangle[] quadTriangles = SceneryNodeInfo.BuildPrimitiveList(vertList, collisionIndices);

                    // Crear los índices para alta resolución
                    SceneryNodeIndexInfo quadHighInfo = null;
                    Int32[] quadHighIndices           = Build(
                        LOD.High,
                        highIndices.Count,
                        offsetX,
                        offsetZ,
                        cellsX,
                        cellsZ,
                        totalCellsX,
                        totalCellsZ,
                        out quadHighInfo);

                    // Crear los índices para media resolución
                    SceneryNodeIndexInfo quadMediumInfo = null;
                    Int32[] quadMediumIndices           = Build(
                        LOD.Medium,
                        mediumIndices.Count,
                        offsetX,
                        offsetZ,
                        cellsX,
                        cellsZ,
                        totalCellsX,
                        totalCellsZ,
                        out quadMediumInfo);

                    // Crear los índices para baja resolución
                    SceneryNodeIndexInfo quadLowInfo = null;
                    Int32[] quadLowIndices           = Build(
                        LOD.Low,
                        lowIndices.Count,
                        offsetX,
                        offsetZ,
                        cellsX,
                        cellsZ,
                        totalCellsX,
                        totalCellsZ,
                        out quadLowInfo);

                    // Añadir los índices a la colección de índices para cada resolución
                    highIndices.AddRange(quadHighIndices);
                    mediumIndices.AddRange(quadMediumIndices);
                    lowIndices.AddRange(quadLowIndices);

                    Dictionary <LOD, SceneryNodeIndexInfo> info = new Dictionary <LOD, SceneryNodeIndexInfo>();
                    info.Add(LOD.High, quadHighInfo);
                    info.Add(LOD.Medium, quadMediumInfo);
                    info.Add(LOD.Low, quadLowInfo);

                    // Crear el nodo con los triángulos para la colisión, los índices de inicio y el número de triángulos para cada resolución
                    SceneryTriangleNode newQuadNode = new SceneryTriangleNode(quadTriangles, info);
                    nodes.Add(newQuadNode);
                }
            }

            // Crear el diccionario de buffers de índices para cada resolución
            indices = new Dictionary <LOD, IndexCollection>();
            indices.Add(LOD.High, highIndices);
            indices.Add(LOD.Medium, mediumIndices);
            indices.Add(LOD.Low, lowIndices);

            // Devolver la información de nodos del escenario
            return(new SceneryNodeInfo()
            {
                Nodes = nodes.ToArray(),
                Indices = indices,
            });
        }