//--------------------------------------------------------------------------------------------------------------------------------------------------- // // 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 Globals; using GameObjects; using Physics; using DarkWynter.Engine.Init; using DarkWynter.Stream.PhysicsGpu; using DarkWynter.Stream; using System.ComponentModel; using DarkWynter.Stream.UIInterfacing; /// /// 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 : GameObject { // 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 /// [EditorAttribute(typeof(ObjectPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))] 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. /// [EditorAttribute(typeof(ObjectPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))] public GpuWindMap windMap { get { return _windMap; } set { _windMap = value; } } private GpuWindMap _windMap = new GpuWindMap(); /// /// Spacial Data Structure used in Gpu Collision algorithm. /// [EditorAttribute(typeof(ObjectPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))] public SpatialMap locationMap { get { return _locationMap; } set { _locationMap = value; } } public SpatialMap _locationMap; // 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(XmlNode objectNode, Vector3 startingLocation) : base(objectNode, startingLocation) { gpu_Processor = new GpuProcessor(); // Create Location Map locationMap = new SpatialMap("SpatialMain", ShaderParameters.UpdateFX.LocationMap, Enums_Stream.GpuProcessorMode.Spatial, true, 0, 100); // Create Variables and add to the Object variables.Add(new Vec3("TotalForce", ShaderParameters.UpdateFX.TotalForce, Enums_Stream.GpuProcessorMode.Indexed, true, -Statics_Engine.TerrainSettings.collisionMapSize, Statics_Engine.TerrainSettings.collisionMapSize)); variables.Add(new Vec3("Acceleration", ShaderParameters.UpdateFX.Acceleration, Enums_Stream.GpuProcessorMode.Indexed, true, -Statics_Engine.TerrainSettings.collisionMapSize, Statics_Engine.TerrainSettings.collisionMapSize)); variables.Add(new Vec3("Velocity", ShaderParameters.UpdateFX.Velocity, Enums_Stream.GpuProcessorMode.Indexed, true, -Statics_Engine.TerrainSettings.collisionMapSize, Statics_Engine.TerrainSettings.collisionMapSize)); variables.Add(new Quat("Rotation", ShaderParameters.UpdateFX.Rotation, Enums_Stream.GpuProcessorMode.Indexed, true, -100, 100)); variables.Add(new Vec3("CurrentPosition", ShaderParameters.UpdateFX.CurrentPosition, Enums_Stream.GpuProcessorMode.Indexed, true, -Statics_Engine.TerrainSettings.collisionMapSize, Statics_Engine.TerrainSettings.collisionMapSize)); variables.Add(new Vec3("Dummy", ShaderParameters.UpdateFX.Dummy, Enums_Stream.GpuProcessorMode.Indexed, true, -Statics_Engine.TerrainSettings.collisionMapSize, Statics_Engine.TerrainSettings.collisionMapSize)); variables.Add(new Vec1("", ShaderParameters.UpdateFX.Radius, Enums_Stream.GpuProcessorMode.Indexed, false, 0, 100)); variables.Add(new Vec1("", ShaderParameters.UpdateFX.Scale, Enums_Stream.GpuProcessorMode.Indexed, false, 0, 100)); variables.Add(new Vec1("", ShaderParameters.UpdateFX.Mass, Enums_Stream.GpuProcessorMode.Indexed, 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 override bool Load(ObjectLibrary objectLibrary) { draw = new Draw(Enums_Stream.DrawMethod.GPUObjectList_Draw, "GPUPhysixInstancedShaderMain"); draw.vertexDeclaration = new VertexDeclaration(Statics_Stream.RenderSettings.graphics.GraphicsDevice, 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(ObjectLibrary objectLibrary) { if (runLoad) { runLoad = false; Load(objectLibrary); } // 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(Statics_Engine.SystemSettings.dt); gpu_Processor.ExecuteRTT(locationMap, variables); } /// /// Override Draw function /// public override Draw Draw() { if (masses.Count == 0) { return null; } #if !XBOX360 GraphicsDevice gd = Statics_Stream.RenderSettings.graphics.GraphicsDevice; // 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(Statics_Stream.RenderSettings.graphics.GraphicsDevice, 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(Statics_Stream.RenderSettings.graphics.GraphicsDevice, typeof(VertexFogBinormalTangentDepth), draw.instanceDataFBTD.Length, BufferUsage.WriteOnly); draw.vertexBuffer.SetData(draw.instanceDataFBTD); storeObjects.Clear(); } return draw; #endif } } }