//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {Contact : darkwynter.com for licensing information //--------------------------------------------------------------------------------------------------------------------------------------------------- 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; #endregion using DarkWynter.Stream.PhysicsGpu; using DarkWynter.Stream; /// /// GpuObjectList contains a list of GpuObjects. /// It takes an object at a time and holds it till ConvertToVariables is called, at which time it transfers converts the data into textures. /// After this initialization, GpuObjects can still be added by using ConvertSubsetToVariables. /// public class GpuObjectList { // Type information private string type; /// /// A list of GpuVariables used in our algorithm. /// public List variables = new List(); public List _variables { get { return variables; } set { variables = value; } } /// /// GpuProcessor is used to process each gpu object each pass /// public GpuProcessor gpu_Processor { get { return _gpu_Processor; } set { _gpu_Processor = value; } } public GpuProcessor _gpu_Processor; ///// ///// List of mass objects being converted to GpuVariables. ///// //public List masses { get { return _masses; } set { _masses = value; } } //private List _masses = new List(); /// /// A forceMap simulating wind currents. /// public GpuWindMap windMap { get { return _windMap; } set { _windMap = value; } } private GpuWindMap _windMap = new GpuWindMap(); /// /// Spacial Data Structure used in Gpu Collision algorithm. /// public SpatialMap locationMap { get { return _locationMap; } set { _locationMap = value; } } public SpatialMap _locationMap; public Draw draw { get { return _draw; } set { _draw = value; } } public Draw _draw; // The instance data itself private List instanceList; private List removeObjects; private List storeObjects; public bool runLoad { get { return _runLoad; } set { _runLoad = value; } } private bool _runLoad = false; /// /// GpuObjectList constructor. /// Creates a list of GpuVariables used in Physics and Collision. /// public GpuObjectList(GraphicsDevice gd, XmlNode objectNode, Vector3 startingLocation) { gpu_Processor = new GpuProcessor(gd); // Create Location Map //locationMap = new SpatialMap(gd, "SpatialMain", ShaderParameters.UpdateFX.LocationMap,true, 0, 100); // Create Variables and add to the Object variables.Add(new Vec3(gd, "TotalForce", ShaderParameters.UpdateFX.TotalForce, true, 0, 100)); variables.Add(new Vec3(gd, "Acceleration", ShaderParameters.UpdateFX.Acceleration, true, 0, 100)); variables.Add(new Vec3(gd, "Velocity", ShaderParameters.UpdateFX.Velocity, true, 0, 100)); variables.Add(new Quat(gd, "Rotation", ShaderParameters.UpdateFX.Rotation, true, -100, 100)); variables.Add(new Vec3(gd, "CurrentPosition", ShaderParameters.UpdateFX.CurrentPosition, true, 0, 100)); variables.Add(new Vec3(gd, "Dummy", ShaderParameters.UpdateFX.Dummy, true, 0, 100)); variables.Add(new Vec1(gd, "", ShaderParameters.UpdateFX.Radius, false, 0, 100)); variables.Add(new Vec1(gd, "", ShaderParameters.UpdateFX.Scale, false, 0, 100)); variables.Add(new Vec1(gd, "", ShaderParameters.UpdateFX.Mass, false, 0, 100)); removeObjects = new List(); storeObjects = new List(); } /// /// Override load function, parses and loads xml data. /// /// ObjectLibrary that this list belongs to. /// True if load was successful public bool Load(GraphicsDevice gd) { //draw = new Draw(Draw.DrawMethod.GPUObjectList_Draw, "GPUPhysixInstancedShaderMain"); //draw.vertexDeclaration = new VertexDeclaration(gd, draw.FBTDElements); //if (masses.Count > 0) //{ // // Add a list of CPU Objects to the GPU Object // ConvertToVariables(); // draw.textureList = masses[0].gameObjectPointer.draw.textureList; // draw.model = masses[0].gameObjectPointer.draw.model; // instanceList = new List(); // for (int i = 0; i < masses.Count; i++) // { // instanceList.Add(masses[i].gameObjectPointer.staticObjectValues); // } // draw.instanceDataFBTD = new VertexFogBinormalTangentDepth[instanceList.Count]; // instanceList.CopyTo(draw.instanceDataFBTD); // draw.vertexBuffer = new VertexBuffer(Statics_Stream.RenderSettings.graphics.GraphicsDevice, // typeof(VertexFogBinormalTangentDepth), // draw.instanceDataFBTD.Length, // BufferUsage.WriteOnly); // draw.vertexBuffer.SetData(draw.instanceDataFBTD); //} //// Add Wind Map //windMap.Load(node.Attributes["windMap"].Value, Statics_Engine.SystemSettings.content); // Set Wind Map handle in shader windMap.SetWindMap(ShaderParameters.UpdateFX.WindMap); //// Set Scale and Min Value range //ShaderParameters.DrawFX.scaleRange.SetValue(variables[4].scaleRange); //ShaderParameters.DrawFX.minimumValue.SetValue(variables[4].minimumValue); ShaderParameters.UpdateFX.cpScaleRangeY.SetValue(variables[4].scaleRange); ShaderParameters.UpdateFX.cpScaleMinY.SetValue(variables[4].minimumValue); //ShaderParameters.UpdateFX.scaleMinY.SetValue(objectLibrary.terrain.terrainScaleMinY); //ShaderParameters.UpdateFX.scaleRangeY.SetValue(objectLibrary.terrain.terrainScaleMaxY - objectLibrary.terrain.terrainScaleMinY); //// Set HeightMap, NormalMap, ForceMap, and Scale Values //ShaderParameters.UpdateFX.TerrainHeightMap.SetValue(objectLibrary.terrain.heightMapTexture); //ShaderParameters.UpdateFX.TerrainNormalMap.SetValue(objectLibrary.terrain.normalMapTexture); //ShaderParameters.UpdateFX.gpuObjectScale.SetValue(Statics_Engine.TerrainSettings.collisionMapSize); return true; } ///// ///// Adds a mass object to be converted to a GpuObject. ///// Used by attack methods. ///// ///// Game object being added. //public void AddNewObject(GameObject gameObject, bool convertNow) //{ // masses.Add(gameObject.mass); // variables[0].AddProperty(gameObject.mass.totalForce); // variables[1].AddProperty(gameObject.mass.acceleration); // variables[2].AddProperty(gameObject.mass.velocity); // variables[3].AddProperty(gameObject.mass.currentRotation); // variables[4].AddProperty(gameObject.mass.currentPosition); // variables[5].AddProperty(gameObject.mass.totalForce); // Dummy Texture // variables[6].AddProperty(gameObject.mass.boundingVolume.radius); // variables[7].AddProperty(gameObject.mass.scale); // variables[8].AddProperty(gameObject.mass.mass); // int i = masses.Count - 1; // Matrix matrix = Matrix.CreateScale(gameObject.mass.scale) * // Matrix.CreateFromQuaternion(gameObject.mass.currentRotation); // gameObject.staticObjectValues = new VertexFogBinormalTangentDepth(); // 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); // masses[i].gameObjectPointer.staticObjectValues.Depth = new Vector4((float)i % 256 / 256, (float)((int)i / 256) / 256, 0, matrix.M44); // if (convertNow) // { // if (masses.Count == 1) // { // runLoad = true; // } // storeObjects.Add(gameObject.staticObjectValues); // ConvertSubsetToVariables(i, 1); // } //} ///// ///// Adds a List of mass objects to be converted to a GpuObject. ///// Used by attack methods. ///// ///// List of Mass objects being added. //public void AddMass(List massList) //{ // if (masses.Count == 0) // { // runLoad = true; // } // // Get insertion point // int startIndex = masses.Count; // int massCount = massList.Count; // for (int i = 0; i < massList.Count; i++) // { // masses.Add(massList[i]); // variables[0].AddProperty(massList[i].totalForce); // variables[1].AddProperty(massList[i].acceleration); // variables[2].AddProperty(massList[i].velocity); // variables[3].AddProperty(massList[i].currentRotation); // variables[4].AddProperty(massList[i].currentPosition); // variables[5].AddProperty(massList[i].totalForce); // Dummy Texture // variables[6].AddProperty(massList[i].boundingVolume.radius); // variables[7].AddProperty(massList[i].scale); // variables[8].AddProperty(massList[i].mass); // int massNum = masses.Count - 1; // Matrix matrix = Matrix.CreateScale(massList[i].scale) * // Matrix.CreateFromQuaternion(massList[i].currentRotation); // massList[i].gameObjectPointer.staticObjectValues.Fog = new Vector4(matrix.M11, matrix.M12, matrix.M13, matrix.M14); // massList[i].gameObjectPointer.staticObjectValues.Binormal = new Vector4(matrix.M21, matrix.M22, matrix.M23, matrix.M24); // massList[i].gameObjectPointer.staticObjectValues.Tangent = new Vector4(matrix.M31, matrix.M32, matrix.M33, matrix.M34); // massList[i].gameObjectPointer.staticObjectValues.Depth = new Vector4((float)massNum % 256 / 256, (float)((int)massNum / 256) / 256, 0, matrix.M44); // storeObjects.Add(massList[i].gameObjectPointer.staticObjectValues); // } // ConvertSubsetToVariables(startIndex, massCount); //} ///// ///// Remove a mass object from the GpuObjectList. ///// ///// Mass to be removed. //public void RemoveMass(Mass mass) //{ // int index; // index = masses.IndexOf(mass); // masses.Remove(mass); // removeObjects.Add(mass.gameObjectPointer.staticObjectValues); // variables[0].ClearProperty(index); // variables[1].ClearProperty(index); // variables[2].ClearProperty(index); // variables[3].ClearProperty(index); // variables[4].ClearProperty(index); // variables[5].ClearProperty(index); // Dummy Texture // variables[6].ClearProperty(index); // variables[7].ClearProperty(index); // variables[8].ClearProperty(index); // ConvertSubsetToVariables(index, 1); //} /// /// Convert a list of GameObjects into a Gpu Object /// private void ConvertToVariables() { variables[0].SetTexData(); // totalForce variables[1].SetTexData(); // acceleration variables[2].SetTexData(); // velocity variables[3].SetTexData(); // rotation variables[4].SetTexData(); // currentPosition variables[5].SetTexData(); // dummy variables[6].SetTexData(); // radius variables[7].SetTexData(); // scale variables[8].SetTexData(); // mass } private void ConvertSubsetToVariables(int index, int count) { variables[0].SetSubTexData(index, count); // totalForce variables[1].SetSubTexData(index, count); // acceleration variables[2].SetSubTexData(index, count); // velocity variables[3].SetSubTexData(index, count); // rotation variables[4].SetSubTexData(index, count); // currentPosition variables[5].SetSubTexData(index, count); // dummy variables[6].SetSubTexData(index, count); // radius variables[7].SetSubTexData(index, count); // scale variables[8].SetSubTexData(index, count); // mass } //private void RetrieveValues() //{ // // Unscale the Gpu Objectvariables // for (int variableCount = 0; variableCount < variables.Count; variableCount++) // { // variables[variableCount].UnScale(); // } // // Get current position for each object // for (int massCount = 0; massCount < masses.Count; massCount++) // { // masses[massCount].totalForce = new Vector3(variables[0].properties[massCount].X, // variables[0].properties[massCount].Y, // variables[0].properties[massCount].Z); // masses[massCount].acceleration = new Vector3(variables[1].properties[massCount].X, // variables[1].properties[massCount].Y, // variables[1].properties[massCount].Z); // masses[massCount].velocity = new Vector3(variables[2].properties[massCount].X, // variables[2].properties[massCount].Y, // variables[2].properties[massCount].Z); // masses[massCount].currentRotation = new Quaternion(variables[3].properties[massCount].X, // variables[3].properties[massCount].Y, // variables[3].properties[massCount].Z, // variables[3].properties[massCount].W); // masses[massCount].currentPosition = new Vector3(variables[4].properties[massCount].X, // variables[4].properties[massCount].Y, // variables[4].properties[massCount].Z); // masses[massCount].scale = new Vector3(variables[7].properties[massCount].X); // masses[massCount].mass = variables[8].properties[massCount].X; // } //} /// /// Update using GpuProcessor. /// /// ObjectLibrary that this list belongs to. public void Update(GraphicsDevice gd, float dt) { if (runLoad) { runLoad = false; Load(gd); } //// Calc the player's current position //Vector2 playerPos2d = // new Vector2(Statics_Engine.PlayerSettings.playerPosition.X, Statics_Engine.PlayerSettings.playerPosition.Y ) / // new Vector2(Statics_Engine.TerrainSettings.collisionMapSize) / new Vector2(2.0f) + new Vector2(0.5f); //ShaderParameters.UpdateFX.playerPosition.SetValue(playerPos2d); // Set Change in Time ShaderParameters.UpdateFX.dt.SetValue(dt); //gpu_Processor.ExecuteRTT(gd, locationMap, variables); } /// /// Override Draw function /// public Draw Draw(GraphicsDevice gd) { //if (masses.Count == 0) //{ // return null; //} #if !XBOX360 // Transfer Current Position Reference from Update Effect to Draw Effect //ShaderParameters.DrawFX.CurrentPosition.SetValue(variables[4]._read); if (removeObjects.Count != 0) { for (int i = 0; i < removeObjects.Count; i++) { instanceList.Remove(removeObjects[i]); } instanceList.CopyTo(draw.instanceDataFBTD); draw.vertexBuffer = new VertexBuffer(gd, typeof(VertexFogBinormalTangentDepth), draw.instanceDataFBTD.Length, BufferUsage.WriteOnly); draw.vertexBuffer.SetData(draw.instanceDataFBTD); removeObjects.Clear(); } if (storeObjects.Count != 0) { for (int i = 0; i < storeObjects.Count; i++) { instanceList.Add(storeObjects[i]); } draw.instanceDataFBTD = new VertexFogBinormalTangentDepth[instanceList.Count]; instanceList.CopyTo(draw.instanceDataFBTD); draw.vertexBuffer = new VertexBuffer(gd, typeof(VertexFogBinormalTangentDepth), draw.instanceDataFBTD.Length, BufferUsage.WriteOnly); draw.vertexBuffer.SetData(draw.instanceDataFBTD); storeObjects.Clear(); } return draw; #endif } } }