protected override Scenery Read(ContentReader input, Scenery existingInstance)
        {
            Scenery scenery = existingInstance;

            if (scenery == null)
            {
                scenery = new Scenery();
            }

            scenery.Terrain = input.ReadObject <Texture2D>();
            scenery.TerrainBufferDeclaration  = input.ReadObject <VertexDeclaration>();
            scenery.TerrainBufferVertexStride = input.ReadInt32();
            scenery.TerrainBuffer             = input.ReadObject <VertexBuffer>();
            scenery.TerrainBufferVertexCount  = input.ReadInt32();

            List <SceneryTriangleNode> nodes = new List <SceneryTriangleNode>();

            int nodeCount = input.ReadInt32();

            for (int i = 0; i < nodeCount; i++)
            {
                SceneryTriangleNode node = input.ReadObject <SceneryTriangleNode>();

                nodes.Add(node);
            }

            SceneryNode root = BuildQuadtree(nodes.ToArray());

            scenery.Root = root;

            scenery.TerrainIndexBuffers.Add(LOD.High, input.ReadObject <IndexBuffer>());
            scenery.TerrainIndexBuffers.Add(LOD.Medium, input.ReadObject <IndexBuffer>());
            scenery.TerrainIndexBuffers.Add(LOD.Low, input.ReadObject <IndexBuffer>());

            scenery.Effect         = input.ReadObject <Effect>();
            scenery.Texture1       = input.ReadObject <Texture2D>();
            scenery.Texture2       = input.ReadObject <Texture2D>();
            scenery.Texture3       = input.ReadObject <Texture2D>();
            scenery.Texture4       = input.ReadObject <Texture2D>();
            scenery.DetailTexture1 = input.ReadObject <Texture2D>();
            scenery.DetailTexture2 = input.ReadObject <Texture2D>();
            scenery.DetailTexture3 = input.ReadObject <Texture2D>();
            scenery.DetailTexture4 = input.ReadObject <Texture2D>();

            //Leer el efecto para renderizar billboards
            scenery.BillboardEffect       = input.ReadObject <Effect>();
            scenery.BillboardGrassTexture = input.ReadObject <Texture2D>();
            scenery.BillboardTreeTexture  = input.ReadObject <Texture2D>();

            return(scenery);
        }
Beispiel #2
0
        /// <summary>
        /// Dibuja el contenido gráfico del componente atendiendo al nivel de detalle
        /// </summary>
        /// <param name="device">Dispositivo gráfico</param>
        /// <param name="gameTime">Tiempo de juego</param>
        /// <param name="nodesToDraw">Lista de nodos a dibujar</param>
        /// <param name="lod">Nivel de detalle</param>
        private void LODDraw(GraphicsDevice device, GameTime gameTime, SceneryNode[] nodesToDraw, LOD lod)
        {
            if (nodesToDraw != null && nodesToDraw.Length > 0)
            {
                // Comprobar si el nodo se debe dibujar
                if ((this.LevelOfDetail != LOD.None) && (this.LevelOfDetail != lod))
                {
                    return;
                }

                // Establecer los índices según el nivel de detalle
                device.Indices = this.TerrainIndexBuffers[lod];

                // Cantidad de vértices del buffer
                int vertexCount = this.TerrainBufferVertexCount;

                this.Effect.Begin();

                foreach (EffectPass pass in this.Effect.CurrentTechnique.Passes)
                {
                    pass.Begin();

                    foreach (SceneryNode node in nodesToDraw)
                    {
                        SceneryTriangleNode triNode = node as SceneryTriangleNode;
                        if (triNode != null)
                        {
                            int centerPrimitiveCount           = triNode.IndexInfo[lod].CenterPrimitiveCount;
                            int borderConnectionPrimitiveCount = triNode.IndexInfo[lod].BorderConnectionPrimitiveCount;
                            int borderPrimitiveCount           = triNode.IndexInfo[lod].BorderPrimitiveCount;

                            // Dibujar el centro
                            this.DrawNodePart(
                                device,
                                triNode.IndexInfo[lod].CenterOffset,
                                vertexCount,
                                centerPrimitiveCount);

                            // Dibujar los bordes si es necesario
                            if (borderPrimitiveCount > 0 || borderConnectionPrimitiveCount > 0)
                            {
                                if (triNode.IsNorthBorder)
                                {
                                    // Dibujar la conexión norte
                                    this.DrawNodePart(
                                        device,
                                        triNode.IndexInfo[lod].NorthConnectionOffset,
                                        vertexCount,
                                        borderConnectionPrimitiveCount);
                                }
                                else
                                {
                                    // Dibujar el norte
                                    this.DrawNodePart(
                                        device,
                                        triNode.IndexInfo[lod].NorthOffset,
                                        vertexCount,
                                        borderPrimitiveCount);
                                }

                                if (triNode.IsSouthBorder)
                                {
                                    // Dibujar la conexión norte
                                    this.DrawNodePart(
                                        device,
                                        triNode.IndexInfo[lod].SouthConnectionOffset,
                                        vertexCount,
                                        borderConnectionPrimitiveCount);
                                }
                                else
                                {
                                    // Dibujar el norte
                                    this.DrawNodePart(
                                        device,
                                        triNode.IndexInfo[lod].SouthOffset,
                                        vertexCount,
                                        borderPrimitiveCount);
                                }

                                if (triNode.IsWestBorder)
                                {
                                    // Dibujar la conexión norte
                                    this.DrawNodePart(
                                        device,
                                        triNode.IndexInfo[lod].WestConnectionOffset,
                                        vertexCount,
                                        borderConnectionPrimitiveCount);
                                }
                                else
                                {
                                    // Dibujar el norte
                                    this.DrawNodePart(
                                        device,
                                        triNode.IndexInfo[lod].WestOffset,
                                        vertexCount,
                                        borderPrimitiveCount);
                                }

                                if (triNode.IsEastBorder)
                                {
                                    // Dibujar la conexión norte
                                    this.DrawNodePart(
                                        device,
                                        triNode.IndexInfo[lod].EastConnectionOffset,
                                        vertexCount,
                                        borderConnectionPrimitiveCount);
                                }
                                else
                                {
                                    // Dibujar el norte
                                    this.DrawNodePart(
                                        device,
                                        triNode.IndexInfo[lod].EastOffset,
                                        vertexCount,
                                        borderPrimitiveCount);
                                }
                            }
                        }
                    }

                    pass.End();
                }

                this.Effect.End();
            }
        }
Beispiel #3
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,
            });
        }