/// <summary>
        /// Loads a Daggerfall flat (billboard).
        /// </summary>
        /// <param name="textureArchive">Texture archive index.</param>
        /// <param name="textureRecord">Texture record index.</param>
        /// <param name="textureFlags">Texture create flags.</param>
        /// <param name="material">Material.</param>
        /// <param name="startSize">Start size before scaling.</param>
        /// <param name="finalSize">Final size after scaling.</param>
        private void LoadDaggerfallFlat(
            int textureArchive,
            int textureRecord,
            MaterialManager.TextureCreateFlags textureFlags,
            out BaseMaterialEffect material,
            out Vector2 startSize,
            out Vector2 finalSize)
        {
            // Get path to texture file
            string path = Path.Combine(
                core.MaterialManager.Arena2Path,
                TextureFile.IndexToFileName(textureArchive));

            // Get size and scale of this texture
            System.Drawing.Size size  = TextureFile.QuickSize(path, textureRecord);
            System.Drawing.Size scale = TextureFile.QuickScale(path, textureRecord);

            // Set start size
            startSize.X = size.Width;
            startSize.Y = size.Height;

            // Apply scale
            int xChange = (int)(size.Width * (scale.Width / BlocksFile.ScaleDivisor));
            int yChange = (int)(size.Height * (scale.Height / BlocksFile.ScaleDivisor));

            finalSize.X = size.Width + xChange;
            finalSize.Y = size.Height + yChange;

            // Load material
            material = core.MaterialManager.CreateDaggerfallMaterialEffect(
                textureArchive,
                textureRecord,
                renderBillboards,
                MaterialManager.DefaultBillboardFlags);
        }
        /// <summary>
        /// Loads a Daggerfall texture as a billboard.
        /// </summary>
        /// <param name="archive">Texture archive.</param>
        /// <param name="record">Texture record.</param>
        /// <param name="flat">Flat data.</param>
        public void LoadBillboard(DaggerfallBlockComponent.BlockFlat flat)
        {
            // Get path to texture file
            string path = Path.Combine(
                core.MaterialManager.Arena2Path,
                TextureFile.IndexToFileName(flat.Archive));

            // Get size and scale of this texture
            System.Drawing.Size size  = TextureFile.QuickSize(path, flat.Record);
            System.Drawing.Size scale = TextureFile.QuickScale(path, flat.Record);

            // Set start size
            Vector2 startSize;

            startSize.X = size.Width;
            startSize.Y = size.Height;

            // Apply scale
            Vector2 finalSize;
            int     xChange = (int)(size.Width * (scale.Width / BlocksFile.ScaleDivisor));
            int     yChange = (int)(size.Height * (scale.Height / BlocksFile.ScaleDivisor));

            finalSize.X = (size.Width + xChange);
            finalSize.Y = (size.Height + yChange);
            finalSize  *= ModelManager.GlobalScale;

            // Load material
            this.material = core.MaterialManager.CreateDaggerfallMaterialEffect(
                flat.Archive,
                flat.Record,
                null,
                MaterialManager.DefaultBillboardFlags);

            // Save settings
            this.size = finalSize;

            // Calcuate offset for correct positioning in scene
            if (flat.Dungeon)
            {
                this.offset = Vector3.Zero;
            }
            else
            {
                this.offset = new Vector3(0, (finalSize.Y / 2) - (4 * ModelManager.GlobalScale), 0);
            }

            // Set bounding sphere
            BoundingSphere sphere;

            sphere.Center = Vector3.Zero;
            if (finalSize.X > finalSize.Y)
            {
                sphere.Radius = finalSize.X / 2;
            }
            else
            {
                sphere.Radius = finalSize.Y / 2;
            }
            this.BoundingSphere = sphere;
        }
Beispiel #3
0
        /// <summary>
        /// Loads model data from DFMesh.
        /// </summary>
        /// <param name="id">Key of source mesh.</param>
        /// <param name="modelData">ModelData out.</param>
        /// <returns>True if successful.</returns>
        private bool LoadModelData(uint id, out ModelData modelData)
        {
            // Return from cache if present
            if (cacheModelData && modelDataDict.ContainsKey(id))
            {
                modelData = modelDataDict[id];
                return(true);
            }

            // New model object
            modelData = new ModelData();

            // Find mesh index
            int index = arch3dFile.GetRecordIndex(id);

            if (index == -1)
            {
                return(false);
            }

            // Get DFMesh
            DFMesh dfMesh = arch3dFile.GetMesh(index);

            if (dfMesh.TotalVertices == 0)
            {
                return(false);
            }

            // Load mesh data
            modelData.DFMesh = dfMesh;
            LoadVertices(ref modelData);
            LoadIndices(ref modelData);
            AddModelTangents(ref modelData);
            CreateModelBuffers(graphicsDevice, ref modelData);

            // Load materials
            for (int i = 0; i < modelData.SubMeshes.Length; i++)
            {
                // Create material
                BaseMaterialEffect material = CreateModelMaterial(
                    modelData.DFMesh.SubMeshes[i].TextureArchive,
                    modelData.DFMesh.SubMeshes[i].TextureRecord);

                // Save key in submesh
                modelData.SubMeshes[i].MaterialKey = material.ID;
            }

            // Add to cache
            if (cacheModelData)
            {
                modelDataDict.Add(id, modelData);
            }

            return(true);
        }
Beispiel #4
0
 /// <summary>
 /// Submit a billboard to be drawn in GBuffer.
 /// </summary>
 /// <param name="material">Material used when rendering the billboard.</param>
 /// <param name="position">Position of billboard in world space.</param>
 /// <param name="size">Dimensions of billboard.</param>
 public void SubmitBillboard(BaseMaterialEffect material, Vector3 position, Vector2 size)
 {
     if (visibleBillboardsCount < maxVisibleBillboards)
     {
         // Add billboard to array
         visibleBillboards[visibleBillboardsCount].Material = material;
         visibleBillboards[visibleBillboardsCount].Position = position;
         visibleBillboards[visibleBillboardsCount].Size     = size;
         visibleBillboardsCount++;
     }
 }
        /// <summary>
        /// Draws the component.
        /// </summary>
        /// <param name="caller">Entity calling the draw operation.</param>
        public override void Draw(BaseEntity caller)
        {
            // Do nothing if no static geometry
            if (staticGeometry == null)
            {
                return;
            }

            // Do nothing if no batches or component is disabled
            if (staticGeometry.StaticBatches == null || !enabled)
            {
                return;
            }

            // Calculate world matrix
            Matrix worldMatrix = matrix * caller.Matrix;

            // Set transforms
            core.ModelManager.ModelEffect_World      = worldMatrix;
            core.ModelManager.ModelEffect_View       = core.ActiveScene.Camera.ViewMatrix;
            core.ModelManager.ModelEffect_Projection = core.ActiveScene.Camera.ProjectionMatrix;

            // Set buffers
            core.GraphicsDevice.SetVertexBuffer(staticGeometry.VertexBuffer);
            core.GraphicsDevice.Indices = staticGeometry.IndexBuffer;

            // Draw batches
            foreach (var item in staticGeometry.StaticBatches)
            {
                // Apply material
                BaseMaterialEffect materialEffect = core.MaterialManager.GetMaterialEffect(item.Key);
                materialEffect.Apply();

                // Render geometry
                foreach (EffectPass pass in materialEffect.Effect.CurrentTechnique.Passes)
                {
                    // Apply effect pass
                    pass.Apply();

                    // Draw primitives
                    core.GraphicsDevice.DrawIndexedPrimitives(
                        PrimitiveType.TriangleList,
                        0,
                        0,
                        staticGeometry.VertexBuffer.VertexCount,
                        item.Value.StartIndex,
                        item.Value.PrimitiveCount);
                }
            }
        }
        /// <summary>
        /// Draws component.
        /// </summary>
        /// <param name="caller">Entity calling the draw operation.</param>
        public override void Draw(BaseEntity caller)
        {
            // Do nothing if disabled or no model data
            if (!enabled || modelData == null)
            {
                return;
            }

            // Exit if model data is empty
            if (modelData.SubMeshes == null)
            {
                return;
            }

            // Calculate world matrix
            Matrix worldMatrix = matrix * caller.Matrix;

            // Set transforms
            core.ModelManager.ModelEffect_World      = worldMatrix;
            core.ModelManager.ModelEffect_View       = core.ActiveScene.Camera.ViewMatrix;
            core.ModelManager.ModelEffect_Projection = core.ActiveScene.Camera.ProjectionMatrix;

            // Set buffers
            core.GraphicsDevice.SetVertexBuffer(modelData.VertexBuffer);
            core.GraphicsDevice.Indices = modelData.IndexBuffer;

            // Draw batches
            foreach (var sm in modelData.SubMeshes)
            {
                // Apply material
                BaseMaterialEffect materialEffect = core.MaterialManager.GetMaterialEffect(sm.MaterialKey);
                materialEffect.Apply();

                // Render geometry
                foreach (EffectPass pass in materialEffect.Effect.CurrentTechnique.Passes)
                {
                    // Apply effect pass
                    pass.Apply();

                    // Draw indexed primitives
                    core.GraphicsDevice.DrawIndexedPrimitives(
                        PrimitiveType.TriangleList,
                        0,
                        0,
                        modelData.VertexBuffer.VertexCount,
                        sm.StartIndex,
                        sm.PrimitiveCount);
                }
            }
        }
Beispiel #7
0
        /// <summary>
        /// Creates a new Daggerfall texture material.
        /// </summary>
        /// <param name="archive">Texture archive.</param>
        /// <param name="record">Texture record.</param>
        /// <returns>BaseMaterialEffect</returns>
        public BaseMaterialEffect CreateModelMaterial(int archive, int record)
        {
            // Create default material effect
            BaseMaterialEffect material = materialManager.CreateDaggerfallMaterialEffect(
                archive,
                record,
                modelEffect,
                MaterialManager.DefaultModelFlags);

            // Setup material effect
            material.Technique           = modelEffect.Techniques["Default"];
            material.DiffuseTextureParam = modelEffect.Parameters["Texture"];

            return(material);
        }
        /// <summary>
        /// Adds exterior ground tiles to the batch.
        /// </summary>
        /// <param name="blockData">Block data.</param>
        private void AddRMBGroundTiles(ref DFBlock blockData)
        {
            // Make ground slightly lower to minimise depth-fighting on ground aligned polygons
            const float groundHeight = 0f;

            // Corner positions
            Vector3 topLeftPos, topRightPos, bottomLeftPos, bottomRightPos;
            Vector2 topLeftUV, topRightUV, bottomLeftUV, bottomRightUV;

            // Create vertices. These will be updated for each tile based on position and UV orientation.
            VertexPositionNormalTextureBump[] vertices = new VertexPositionNormalTextureBump[4];

            // Create indices. These are the same for every tile.
            int[] indices = new int[] { 0, 1, 2, 1, 3, 2 };

            // Loop through tiles
            int   tileCount     = 16;
            float tileDimension = 256.0f * ModelManager.GlobalScale;

            for (int y = 0; y < tileCount; y++)
            {
                for (int x = 0; x < tileCount; x++)
                {
                    // Get source tile data
                    DFBlock.RmbGroundTiles tile = blockData.RmbBlock.FldHeader.GroundData.GroundTiles[x, y];

                    // Set random terrain marker back to grass
                    int textureRecord = (tile.TextureRecord > 55) ? 2 : tile.TextureRecord;

                    // Create material
                    BaseMaterialEffect material = core.ModelManager.CreateModelMaterial(
                        (int)DFLocation.ClimateTextureSet.Exterior_Terrain,
                        textureRecord);
                    material.SamplerState0 = SamplerState.AnisotropicClamp;

                    // Create vertices for this quad
                    topLeftPos     = new Vector3(x * tileDimension, groundHeight, y * tileDimension);
                    topRightPos    = new Vector3(topLeftPos.X + tileDimension, groundHeight, topLeftPos.Z);
                    bottomLeftPos  = new Vector3(topLeftPos.X, groundHeight, topLeftPos.Z + tileDimension);
                    bottomRightPos = new Vector3(topLeftPos.X + tileDimension, groundHeight, topLeftPos.Z + tileDimension);

                    // Set UVs
                    if (tile.IsRotated && !tile.IsFlipped)
                    {
                        // Rotate only
                        topLeftUV     = new Vector2(1, 0);
                        topRightUV    = new Vector2(1, 1);
                        bottomLeftUV  = new Vector2(0, 0);
                        bottomRightUV = new Vector2(0, 1);
                    }
                    else if (tile.IsFlipped && !tile.IsRotated)
                    {
                        // Flip only
                        topLeftUV     = new Vector2(1, 1);
                        topRightUV    = new Vector2(0, 1);
                        bottomLeftUV  = new Vector2(1, 0);
                        bottomRightUV = new Vector2(0, 0);
                    }
                    else if (tile.IsRotated && tile.IsRotated)
                    {
                        // Rotate and flip
                        topLeftUV     = new Vector2(0, 1);
                        topRightUV    = new Vector2(0, 0);
                        bottomLeftUV  = new Vector2(1, 1);
                        bottomRightUV = new Vector2(1, 0);
                    }
                    else
                    {
                        // No rotate or flip
                        topLeftUV     = new Vector2(0, 0);
                        topRightUV    = new Vector2(1, 0);
                        bottomLeftUV  = new Vector2(0, 1);
                        bottomRightUV = new Vector2(1, 1);
                    }

                    // Set vertices
                    vertices[0] = new VertexPositionNormalTextureBump(topLeftPos, Vector3.Up, topLeftUV, Vector3.Zero, Vector3.Zero);
                    vertices[1] = new VertexPositionNormalTextureBump(topRightPos, Vector3.Up, topRightUV, Vector3.Zero, Vector3.Zero);
                    vertices[2] = new VertexPositionNormalTextureBump(bottomLeftPos, Vector3.Up, bottomLeftUV, Vector3.Zero, Vector3.Zero);
                    vertices[3] = new VertexPositionNormalTextureBump(bottomRightPos, Vector3.Up, bottomRightUV, Vector3.Zero, Vector3.Zero);

                    // Add to builder
                    staticGeometry.AddToBuilder(material.ID, vertices, indices, Matrix.Identity);
                }
            }
        }