//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {Contact : darkwynter.com for licensing information //--------------------------------------------------------------------------------------------------------------------------------------------------- #define GPUInstancing namespace DarkWynter.Engine.ObjectLib { #region Using Statements using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; using System.Xml; using System.Diagnostics; using Xclna.Xna.Animation.Content; using Xclna.Xna.Animation; #endregion using Globals; using GameObjects; using DarkWynter.Engine.Init; using DarkWynter.Stream; /// /// Contains a list of Generic Props. /// Locations of these props are loaded from a LocationMap, listed in the Prop xml data for the level. /// Generic Props use instancing, and consequently draw much faster than stand alone GameObjects. /// public class PropList : GameObject { // Type information private string type; public List gameObjectList; // CpuObjects run physics and collision on the cpu /// /// Constructor for a PropList. /// public PropList(Load gameObjectLoader) : base(gameObjectLoader) { // Create a GameObject list gameObjectList = new List(); } /// /// Loads a prop for each xml defined color in the xml defined LocationMap image. /// /// ObjectLibrary that these props belong to. /// True if load was successful public override bool Load(ObjectLibrary objectLibrary) { bool success = base.LoadModel(load.node); int response = int.Parse(load.node.Attributes["collisionResponse"].Value); Enums_Engine.CollisionResponses currentResponse; if (response == 4) { currentResponse = Enums_Engine.CollisionResponses.NONE; } else if (response == 3) { currentResponse = Enums_Engine.CollisionResponses.MANNALOSS; } else if (response == 2) { currentResponse = Enums_Engine.CollisionResponses.MANNABONUS; } else if (response == 1) { currentResponse = Enums_Engine.CollisionResponses.HEALTHLOSS; } else { currentResponse = Enums_Engine.CollisionResponses.HEALTHBONUS; } float collisionMultiplier = float.Parse(load.node.Attributes["collisionMultiplier"].Value); // Return unsuccessfully if can't load user supplied XML data if (!success) { return false; } string value = load.node.Attributes["animated"].Value; if (value == "Yes") { modelAnimated = true; draw.drawMethod = Enums_Stream.DrawMethod.PropListAnimated_Draw; draw.technique = "InstancedAnimation"; draw.vertexDeclaration = new VertexDeclaration(Statics_Stream.RenderSettings.graphics.GraphicsDevice, draw.InstAnimElements); // Create Animators animator = new ModelAnimator(draw.model); idle = new AnimationController(animator.Animations["idle"]); RunController(idle); } else { modelAnimated = false; draw.drawMethod = Enums_Stream.DrawMethod.PropList_Draw; draw.technique = "BasicLightingInstancedShaderMain"; draw.vertexDeclaration = new VertexDeclaration(Statics_Stream.RenderSettings.graphics.GraphicsDevice, draw.FBTDElements); } // Check to see if list is empty // Happens if XML color value is not found if (gameObjectList.Count <= 0) return false; else { draw.instanceDataFBTD = new VertexFogBinormalTangentDepth[gameObjectList.Count]; for (int i = 0; i < gameObjectList.Count; i++) { draw.instanceDataFBTD[i] = gameObjectList[i].staticObjectValues; } draw.vertexBuffer = new VertexBuffer(Statics_Stream.RenderSettings.graphics.GraphicsDevice, typeof(VertexFogBinormalTangentDepth), draw.instanceDataFBTD.Length, BufferUsage.WriteOnly); draw.vertexBuffer.SetData(draw.instanceDataFBTD); return true; } } public void AddNewObject(GameObject gameObject) { // Instancing gameObject.staticObjectValues = new VertexFogBinormalTangentDepth(); Matrix matrix = Matrix.CreateScale(gameObject.mass.scale) * Matrix.CreateFromQuaternion(gameObject.mass.currentRotation) * Matrix.CreateTranslation(gameObject.mass.currentPosition); gameObject.staticObjectValues.Fog = new Vector4(matrix.M11, matrix.M12, matrix.M13, matrix.M14); gameObject.staticObjectValues.Binormal = new Vector4(matrix.M21, matrix.M22, matrix.M23, matrix.M24); gameObject.staticObjectValues.Tangent = new Vector4(matrix.M31, matrix.M32, matrix.M33, matrix.M34); gameObject.staticObjectValues.Depth = new Vector4(matrix.M41, matrix.M42, matrix.M43, matrix.M44); // Add the prop to the prop list gameObjectList.Add(gameObject); } /// /// Updates this list of props. /// /// ObjectLibrary which these props belong to. public override void Update(ref ObjectLibrary objectLibrary) { // Physics? // Collision? // Use booleans loaded from xml... } /// /// Manages drawing all the props in this list. /// public override Draw Draw() { if (gameObjectList.Count == 0) { return null; } #if !XBOX360 GraphicsDevice gd = Statics_Stream.RenderSettings.graphics.GraphicsDevice; if (modelAnimated) { currentAnimation.Update(Statics_Engine.SystemSettings.elementalGameTime); draw.animator = animator; } return draw; #endif } } } // Legacy Code :) // public void DrawShadow(ModelManager modelManager) // { // if (instanceData.Length == 0) // { // return; // } //#if !XBOX360 // GetUpdatedInstanceData(); // ModelInfo modelInfo = new ModelInfo(); // modelInfo = modelManager.GetModelInfo(type); // // Set the values of the shader // ShaderParameters.DrawFX.modelTexture1.SetValue(modelInfo.currentTexture); // ShaderParameters.DrawFX.bumpTexture1.SetValue(modelInfo.bumpTexture); // ShaderParameters.DrawFX.World.SetValue(Matrix.Identity); // // Set the vertex declaration // Statics.SystemSettings.graphics.GraphicsDevice.VertexDeclaration = vertexDeclaration; // Statics.SystemSettings.graphics.GraphicsDevice.Vertices[0].SetFrequencyOfIndexData(instanceData.Length); // Statics.SystemSettings.graphics.GraphicsDevice.Vertices[1].SetFrequencyOfInstanceData(1); // // Tell the GPU how many times to run through the instance data and set the stream. // Statics.SystemSettings.graphics.GraphicsDevice.Vertices[1].SetSource(instanceBuffer, 0, vertexDeclaration.GetVertexStrideSize(1)); // // Draw the model // foreach (ModelMesh mesh in modelInfo.model.Meshes) // { // // Set the index buffer // Statics.SystemSettings.graphics.GraphicsDevice.Indices = mesh.IndexBuffer; // // Tell the GPU how many times to run through the vertex data and set the stream. // Statics.SystemSettings.graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, 0, vertexDeclaration.GetVertexStrideSize(0)); // foreach (ModelMeshPart part in mesh.MeshParts) // { // part.Effect.CurrentTechnique = part.Effect.Techniques["InstancedShadowMap"]; // part.Effect.Begin(); // for (int k = 0; k < part.Effect.CurrentTechnique.Passes.Count; k++) // { // EffectPass pass = part.Effect.CurrentTechnique.Passes[k]; // pass.Begin(); // Statics.SystemSettings.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, // part.BaseVertex, // 0, // part.NumVertices, // part.StartIndex, // part.PrimitiveCount); // pass.End(); // } // part.Effect.End(); // } // } //#endif // }