//---------------------------------------------------------------------------------------------------------------------------------------------------
//
// Copyright (C)2007 DarkWynter Studios. All rights reserved.
//
//---------------------------------------------------------------------------------------------------------------------------------------------------
// {License Information: Creative Commons}
//---------------------------------------------------------------------------------------------------------------------------------------------------
namespace ElementalGame
{
#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
public class GameObjectList
{
public string type;
private List gameObjectList;
// Holds the vertex of one square
// private VertexBuffer vertexBuffer;
// Holds the instance data
private VertexBuffer instanceBuffer;
// Holds indices for rendering a square
// private IndexBuffer indexBuffer;
// A valid vertex declaration so the device knows what to do
private VertexDeclaration vertexDeclaration;
// The instance data itself
private VertexFogBinormalTangentWeightTess[] instanceData;
// Render To Texture, 2D Orthographic, or 3D Oriented Quads
public enum GenericRenderType { RTT, ORTHOGRAPHIC, INGAME }
public GenericRenderType renderType = GenericRenderType.INGAME; // By default set to in-game...
public static Texture2D particleHotEarthTex;
public static Texture2D particleHotEarthTexBump;
public static Texture2D particleColdEarthTex;
public static Texture2D particleColdEarthTexBump;
public static Texture2D particleHotWaterTex;
public static Texture2D particleHotWaterTexBump;
public static Texture2D particleColdWaterTex;
public static Texture2D particleColdWaterTexBump;
public static Texture2D particleHotAirTex;
public static Texture2D particleHotAirTexBump;
public static Texture2D particleColdAirTex;
public static Texture2D particleColdAirTexBump;
// Tells the GPU how to format the streams
private VertexElement[] Elements = new VertexElement[]
{
new VertexElement(0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0),
new VertexElement(0, sizeof(float) * 3, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Normal, 0),
new VertexElement(0, sizeof(float) * 6, VertexElementFormat.Vector2, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 0),
new VertexElement(1, 0, VertexElementFormat.Vector4, VertexElementMethod.Default, VertexElementUsage.Fog, 0),
new VertexElement(1, sizeof(float) * 4, VertexElementFormat.Vector4, VertexElementMethod.Default, VertexElementUsage.Binormal, 0),
new VertexElement(1, sizeof(float) * 8, VertexElementFormat.Vector4, VertexElementMethod.Default, VertexElementUsage.Tangent, 0),
new VertexElement(1, sizeof(float) * 12, VertexElementFormat.Vector4, VertexElementMethod.Default, VertexElementUsage.BlendWeight, 0),
new VertexElement(1, sizeof(float) * 16, VertexElementFormat.Vector4, VertexElementMethod.Default, VertexElementUsage.Color, 0),
};
public GameObjectList()
{
gameObjectList = new List();
vertexDeclaration = new VertexDeclaration(ElementalGame.graphics.GraphicsDevice, Elements);
instanceData = new VertexFogBinormalTangentWeightTess[0];
}
private GameObject CreateGenericObject(Mass.ObjectType objectType)
{
GameObject retVal = new GameObject();
switch (objectType)
{
case Mass.ObjectType.CIRCLE:
retVal = new Circle(ObjectLibrary.darkMatter[ObjectLibrary.darkMatterIterator++]);
break;
case Mass.ObjectType.CUBE:
retVal = new Cube(ObjectLibrary.darkMatter[ObjectLibrary.darkMatterIterator++]);
break;
case Mass.ObjectType.CYLINDER:
retVal = new Cylinder(ObjectLibrary.darkMatter[ObjectLibrary.darkMatterIterator++]);
break;
case Mass.ObjectType.PARTICLE:
retVal = new Particle(ObjectLibrary.darkMatter[ObjectLibrary.darkMatterIterator++]);
break;
case Mass.ObjectType.PROP:
retVal = new Prop(ObjectLibrary.darkMatter[ObjectLibrary.darkMatterIterator++]);
break;
case Mass.ObjectType.PYRAMID:
retVal = new Pyramid(ObjectLibrary.darkMatter[ObjectLibrary.darkMatterIterator++]);
break;
case Mass.ObjectType.QUAD:
retVal = new Quad(ObjectLibrary.darkMatter[ObjectLibrary.darkMatterIterator++]);
break;
case Mass.ObjectType.SPHERE:
retVal = new Sphere(ObjectLibrary.darkMatter[ObjectLibrary.darkMatterIterator++]);
break;
case Mass.ObjectType.SKYSPHERE:
retVal = new SkySphere(ObjectLibrary.darkMatter[ObjectLibrary.darkMatterIterator++]);
break;
case Mass.ObjectType.TERRAIN:
retVal = new Terrain(ObjectLibrary.darkMatter[ObjectLibrary.darkMatterIterator++]);
break;
case Mass.ObjectType.TRIANGLE:
retVal = new Triangle(ObjectLibrary.darkMatter[ObjectLibrary.darkMatterIterator++]);
break;
default:
break;
}
return retVal;
}
public void LoadGenerics(XmlNode objectNode, ObjectLibrary objectLibrary, Mass.ObjectType objectType)
{
Effect effect = ElementalGame.content.Load("Shaders/ElementalGPU");
type = objectNode.Attributes["type"].Value;
// Get the Location Map
Texture2D locationMap = ElementalGame.content.Load(objectNode.Attributes["locationMap"].Value);
int length = locationMap.Width * locationMap.Width;
Color[] locationColorValues = new Color[length];
locationMap.GetData(locationColorValues);
Random rand = new Random();
// Get the color value of the node
int mapColorR = int.Parse(objectNode.Attributes["red"].Value);
int mapColorG = int.Parse(objectNode.Attributes["green"].Value);
int mapColorB = int.Parse(objectNode.Attributes["blue"].Value);
// Precalculate the vertexmap/locationmap ratio for use in the for loop below
float vertexmapToObjectmapRelationship = Terrain.vertexMapSize / locationMap.Width;
// Create a ruler 1 terrain mod long (distance between verticies
float terrainModWidth = Terrain.terrainScaleFactor * vertexmapToObjectmapRelationship;
objectLibrary.modelManager.AddNewModel(type,
ElementalGame.content.Load(objectNode.Attributes["model"].Value),
ElementalGame.content.Load(objectNode.Attributes["texture"].Value),
ElementalGame.content.Load(objectNode.Attributes["bumpTexture"].Value),
effect,
GameObject.materialDiffuse,
GameObject.materialSpecular);
// For each pixel of the treeMap
for (int l = 0; l < length; l++)
{
// If the color matches create a prop
if (locationColorValues[l].R == mapColorR && locationColorValues[l].G == mapColorG && locationColorValues[l].B == mapColorB)
{
GameObject gameObject = CreateGenericObject(objectType);
gameObject.mass.objectType = objectType;
gameObject.mass.gameObjectPointer = gameObject;
gameObject.objectModelName = type;
// Get the 2D location from 1D array
int h = l % locationMap.Width;
int w = (int)l / locationMap.Width;
// Get x/z position
Vector3 locpos = new Vector3(w * terrainModWidth, 1.0f, h * terrainModWidth);
Vector3 refpos = new Vector3(w * terrainModWidth, 1.0f, h * terrainModWidth-1);
// Set Y to terrain height
float yPosition = objectLibrary.terrain.GetTerrainHeight(w * vertexmapToObjectmapRelationship,
h * vertexmapToObjectmapRelationship);
locpos.Y = yPosition;
refpos.Y = yPosition;
// Set the position
gameObject.mass.SetPosition(locpos, refpos);
gameObject.mass.Rotate(0, (float)(2 * Math.PI * rand.NextDouble()));
gameObject.mass.scale = (int)(float.Parse(objectNode.Attributes["maxScale"].Value));
gameObject.mass.mass = float.Parse(objectNode.Attributes["mass"].Value);
gameObject.mass.isMoving = false;
// Can Object be collected
gameObject.isCollectable = bool.Parse(objectNode.Attributes["isCollectable"].Value);
// Is the Object a level key
gameObject.isKey = bool.Parse(objectNode.Attributes["isKey"].Value);
if (gameObject.isKey)
{
gameObject.mass.objectType = Mass.ObjectType.KEY;
gameObject.mass.currentPosition.Y += 30.0f;
gameObject.mass.objectHeight = 30.0f;
gameObject._boundingSphere.Center = gameObject.mass.currentPosition;
gameObject._boundingSphere.Radius = gameObject.mass.scale;
}
// ===================================================================================
//if (!gameObject.isCollectable)
//{
Matrix matrix = Matrix.CreateScale(gameObject.mass.scale) *
Matrix.CreateFromQuaternion(gameObject.mass.currentRotation) *
Matrix.CreateTranslation(gameObject.mass.currentPosition);
gameObject.objectValues = new VertexFogBinormalTangentWeightTess();
gameObject.objectValues.Fog = new Vector4(matrix.M11, matrix.M12, matrix.M13, matrix.M14); // Store the scale
gameObject.objectValues.Binormal = new Vector4(matrix.M21, matrix.M22, matrix.M23, matrix.M24); // Store the quaternion rotation
gameObject.objectValues.Tangent = new Vector4(matrix.M31, matrix.M32, matrix.M33, matrix.M34); // Store the translation
gameObject.objectValues.BlendWeight = new Vector4(matrix.M41, matrix.M42, matrix.M43, matrix.M44); // Store the fourth row
//}
ObjectLibrary.lookupMap.SetPosition(gameObject.mass);
//ObjectLibrary.lookupMap.AddDynamic(gameObject.mass);
// Add the prop to the prop list
gameObjectList.Add(gameObject);
}
}
}
public void RotatePosition_HackFix(ref Color[] locationColorValues)
{
}
public void AddNewObject(GameObject gameObject)
{
gameObject.objectModelName = type;
gameObjectList.Add(gameObject);
}
public void GetUpdatedInstanceData()
{
for (int i = 0; i < gameObjectList.Count; i++)
{
instanceData[i].Tangent = gameObjectList[i].GetCurrentPosition();
}
instanceBuffer.SetData(instanceData);
}
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.modelTexture1.SetValue(modelInfo.currentTexture);
ShaderParameters.bumpTexture1.SetValue(modelInfo.bumpTexture);
ShaderParameters.World.SetValue(Matrix.Identity);
// Set the vertex declaration
ElementalGame.graphics.GraphicsDevice.VertexDeclaration = vertexDeclaration;
ElementalGame.graphics.GraphicsDevice.Vertices[0].SetFrequencyOfIndexData(instanceData.Length);
ElementalGame.graphics.GraphicsDevice.Vertices[1].SetFrequencyOfInstanceData(1);
// Tell the GPU how many times to run through the instance data and set the stream.
ElementalGame.graphics.GraphicsDevice.Vertices[1].SetSource(instanceBuffer, 0, vertexDeclaration.GetVertexStrideSize(1));
// Draw the model
foreach (ModelMesh mesh in modelInfo.model.Meshes)
{
// Set the index buffer
ElementalGame.graphics.GraphicsDevice.Indices = mesh.IndexBuffer;
// Tell the GPU how many times to run through the vertex data and set the stream.
ElementalGame.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();
ElementalGame.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,
part.BaseVertex,
0,
part.NumVertices,
part.StartIndex,
part.PrimitiveCount);
pass.End();
}
part.Effect.End();
}
}
#endif
}
public void Draw(ModelManager modelManager)
{
if ((gameObjectList.Count == 0))
{
return;
}
//if (instanceList.Count == 0 && !gameObjectList[0].isCollectable)
//{
// return;
//}
#if !XBOX360
ModelInfo modelInfo = new ModelInfo();
modelInfo = modelManager.GetModelInfo(type);
// Set the textures in the shader
if (gameObjectList[0].mass.objectType == Mass.ObjectType.PARTICLE)
{
ShaderParameters.modelTexture1.SetValue(particleColdAirTex);
ShaderParameters.modelTexture2.SetValue(particleHotAirTex);
ShaderParameters.modelTexture3.SetValue(particleColdEarthTex);
ShaderParameters.modelTexture4.SetValue(particleHotEarthTex);
ShaderParameters.modelTexture5.SetValue(particleColdWaterTex);
ShaderParameters.modelTexture6.SetValue(particleHotWaterTex);
ShaderParameters.bumpTexture1.SetValue(particleColdAirTexBump);
ShaderParameters.bumpTexture2.SetValue(particleHotAirTexBump);
ShaderParameters.bumpTexture3.SetValue(particleColdEarthTexBump);
ShaderParameters.bumpTexture4.SetValue(particleHotEarthTexBump);
ShaderParameters.bumpTexture5.SetValue(particleColdWaterTexBump);
ShaderParameters.bumpTexture6.SetValue(particleHotWaterTexBump);
}
else
{
ShaderParameters.modelTexture1.SetValue(modelInfo.currentTexture);
ShaderParameters.bumpTexture1.SetValue(modelInfo.bumpTexture);
}
// Lighting
ShaderParameters.coreShininess.SetValue(7000.0f);
ShaderParameters.coreMaterialDiffuse.SetValue(modelInfo.materialDiffuse);
ShaderParameters.coreMaterialSpecular.SetValue(modelInfo.materialSpecular);
// If Collectable =========================================================================
//if (gameObjectList[0].isCollectable)
//{
// For each game object
//foreach (GameObject gameObject in gameObjectList)
//{
// gameObject.matrix = Matrix.CreateScale(gameObject.mass.scale) *
// Matrix.CreateFromQuaternion(gameObject.mass.currentRotation) *
// Matrix.CreateTranslation(gameObject.mass.currentPosition);
// ShaderParameters.World.SetValue(gameObject.matrix);
// // Draw the model
// foreach (ModelMesh mesh in modelInfo.model.Meshes)
// {
// foreach (Effect currentEffect in mesh.Effects)
// {
// currentEffect.CurrentTechnique = currentEffect.Techniques["BasicLightingShaderMain"];
// }
// mesh.Draw();
// }
//}
//}
// If Indexed
//else
{
//instanceList = new List();
instanceData = new VertexFogBinormalTangentWeightTess[gameObjectList.Count];
for (int i = 0; i < gameObjectList.Count; i++)
{
instanceData[i] = gameObjectList[i].objectValues;
}
//instanceList.CopyTo(instanceData);
instanceBuffer = new VertexBuffer(ElementalGame.graphics.GraphicsDevice,
typeof(VertexFogBinormalTangentWeightTess),
instanceData.Length,
ResourceUsage.None,
ResourceManagementMode.Automatic);
instanceBuffer.SetData(instanceData);
// Set the vertex declaration
ElementalGame.graphics.GraphicsDevice.VertexDeclaration = vertexDeclaration;
ElementalGame.graphics.GraphicsDevice.Vertices[0].SetFrequencyOfIndexData(instanceData.Length);
// Tell the GPU how many times to run through the instance data and set the stream.
ElementalGame.graphics.GraphicsDevice.Vertices[1].SetSource(instanceBuffer, 0, vertexDeclaration.GetVertexStrideSize(1));
ElementalGame.graphics.GraphicsDevice.Vertices[1].SetFrequencyOfInstanceData(1);
// Draw the model
foreach (ModelMesh mesh in modelInfo.model.Meshes)
{
// Set the index buffer
ElementalGame.graphics.GraphicsDevice.Indices = mesh.IndexBuffer;
// Tell the GPU how many times to run through the vertex data and set the stream.
ElementalGame.graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, 0, vertexDeclaration.GetVertexStrideSize(0));
foreach (ModelMeshPart part in mesh.MeshParts)
{
if (gameObjectList[0].mass.objectType == Mass.ObjectType.PARTICLE)
{
part.Effect.CurrentTechnique = part.Effect.Techniques["InstancedParticleShaderMain"];
}
else
{
part.Effect.CurrentTechnique = part.Effect.Techniques["BasicLightingInstancedShaderMain"];
}
part.Effect.Begin();
for (int k = 0; k < part.Effect.CurrentTechnique.Passes.Count; k++)
{
EffectPass pass = part.Effect.CurrentTechnique.Passes[k];
pass.Begin();
ElementalGame.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,
part.BaseVertex,
0,
part.NumVertices,
part.StartIndex,
part.PrimitiveCount);
pass.End();
}
part.Effect.End();
}
}
}
#endif
}
public void DrawTriangleStrips(ModelManager modelManager)
{
if ((gameObjectList.Count == 0))
{
return;
}
//if (instanceList.Count == 0 && !gameObjectList[0].isCollectable)
//{
// return;
//}
#if !XBOX360
ModelInfo modelInfo = new ModelInfo();
modelInfo = modelManager.GetModelInfo(type);
// Set the textures in the shader
if (gameObjectList[0].mass.objectType == Mass.ObjectType.PARTICLE)
{
ShaderParameters.modelTexture1.SetValue(particleColdAirTex);
ShaderParameters.modelTexture2.SetValue(particleHotAirTex);
ShaderParameters.modelTexture3.SetValue(particleColdEarthTex);
ShaderParameters.modelTexture4.SetValue(particleHotEarthTex);
ShaderParameters.modelTexture5.SetValue(particleColdWaterTex);
ShaderParameters.modelTexture6.SetValue(particleHotWaterTex);
ShaderParameters.bumpTexture1.SetValue(particleColdAirTexBump);
ShaderParameters.bumpTexture2.SetValue(particleHotAirTexBump);
ShaderParameters.bumpTexture3.SetValue(particleColdEarthTexBump);
ShaderParameters.bumpTexture4.SetValue(particleHotEarthTexBump);
ShaderParameters.bumpTexture5.SetValue(particleColdWaterTexBump);
ShaderParameters.bumpTexture6.SetValue(particleHotWaterTexBump);
}
else
{
ShaderParameters.modelTexture1.SetValue(modelInfo.currentTexture);
ShaderParameters.bumpTexture1.SetValue(modelInfo.bumpTexture);
}
// Lighting
ShaderParameters.coreShininess.SetValue(7000.0f);
ShaderParameters.coreMaterialDiffuse.SetValue(modelInfo.materialDiffuse);
ShaderParameters.coreMaterialSpecular.SetValue(modelInfo.materialSpecular);
if (gameObjectList.Count != instanceData.Length)
{
instanceData = new VertexFogBinormalTangentWeightTess[gameObjectList.Count];
instanceBuffer = new VertexBuffer(ElementalGame.graphics.GraphicsDevice,
typeof(VertexFogBinormalTangentWeightTess),
instanceData.Length,
ResourceUsage.None,
ResourceManagementMode.Automatic);
}
for (int i = 0; i < gameObjectList.Count; i++)
{
instanceData[i] = gameObjectList[i].objectValues;
}
//instanceList.CopyTo(instanceData);
instanceBuffer.SetData(instanceData);
// Set the vertex declaration
ElementalGame.graphics.GraphicsDevice.VertexDeclaration = vertexDeclaration;
ElementalGame.graphics.GraphicsDevice.Vertices[0].SetFrequencyOfIndexData(instanceData.Length);
// Tell the GPU how many times to run through the instance data and set the stream.
ElementalGame.graphics.GraphicsDevice.Vertices[1].SetSource(instanceBuffer, 0, vertexDeclaration.GetVertexStrideSize(1));
ElementalGame.graphics.GraphicsDevice.Vertices[1].SetFrequencyOfInstanceData(1);
// Draw the model
foreach (ModelMesh mesh in modelInfo.model.Meshes)
{
// Set the index buffer
ElementalGame.graphics.GraphicsDevice.Indices = mesh.IndexBuffer;
int numPrimitives;
if (mesh.IndexBuffer.IndexElementSize == IndexElementSize.SixteenBits)
{
numPrimitives = mesh.IndexBuffer.SizeInBytes / sizeof(ushort);
}
else
{
numPrimitives = mesh.IndexBuffer.SizeInBytes / sizeof(int);
}
numPrimitives -= 2;
// Tell the GPU how many times to run through the vertex data and set the stream.
ElementalGame.graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, 0, vertexDeclaration.GetVertexStrideSize(0));
foreach (ModelMeshPart part in mesh.MeshParts)
{
if (gameObjectList[0].mass.objectType == Mass.ObjectType.PARTICLE)
{
part.Effect.CurrentTechnique = part.Effect.Techniques["InstancedParticleShaderMain"];
}
else
{
part.Effect.CurrentTechnique = part.Effect.Techniques["BasicLightingInstancedShaderMain"];
}
part.Effect.Begin();
for (int k = 0; k < part.Effect.CurrentTechnique.Passes.Count; k++)
{
EffectPass pass = part.Effect.CurrentTechnique.Passes[k];
pass.Begin();
ElementalGame.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleStrip,
part.BaseVertex,
0,
part.NumVertices,
part.StartIndex,
numPrimitives);
pass.End();
}
part.Effect.End();
}
}
#endif
}
public void Update(ObjectLibrary objectLibrary)
{
for (int i = 0; i < gameObjectList.Count; i++)
{
if (gameObjectList[i].mass.deadObject)
{
gameObjectList[i].mass.deadObject = false;
gameObjectList.Remove(gameObjectList[i]);
i--;
}
}
if (gameObjectList.Count == 0)
{
return;
}
if (gameObjectList[0].isKey)
{
for (int i = 0; i < gameObjectList.Count; i++)
{
gameObjectList[i].mass.Rotate(0.0f, ElementalGame.dt);
gameObjectList[i].objectValues = new VertexFogBinormalTangentWeightTess();
Matrix matrix = Matrix.CreateScale(gameObjectList[i].mass.scale) *
Matrix.CreateFromQuaternion(gameObjectList[i].mass.currentRotation) *
Matrix.CreateTranslation(gameObjectList[i].mass.currentPosition);
gameObjectList[i].objectValues.Fog = new Vector4(matrix.M11, matrix.M12, matrix.M13, matrix.M14); // Store the first row
gameObjectList[i].objectValues.Binormal = new Vector4(matrix.M21, matrix.M22, matrix.M23, matrix.M24); // Store the second row
gameObjectList[i].objectValues.Tangent = new Vector4(matrix.M31, matrix.M32, matrix.M33, matrix.M34); // Store the third row
gameObjectList[i].objectValues.BlendWeight = new Vector4(matrix.M41, matrix.M42, matrix.M43, matrix.M44); // Store the fourth row
}
}
}
}
}