//---------------------------------------------------------------------------------------------------------------------------------------------------
//
// 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
}
}
}