//---------------------------------------------------------------------------------------------------------------------------------------------------
//
// Copyright (C)2007 DarkWynter Studios. All rights reserved.
//
//---------------------------------------------------------------------------------------------------------------------------------------------------
// {Contact : darkwynter.com for licensing information
//---------------------------------------------------------------------------------------------------------------------------------------------------
namespace DarkWynter.Stream
{
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Xml;
using Xclna.Xna.Animation.Content;
using Xclna.Xna.Animation;
#endregion
///
/// Stores all the draw function calls for game objects
///
public class Draw
{
///
/// Draws a stand alone model with no instancing or triangle stripping.
/// Uses model stored in ModelManager and referenced by objectModelName.
///
/// Model to be drawn
/// Shader technique to draw model with.
public void TriList(Model model, string technique)
{
foreach (ModelMesh mesh in model.Meshes)
{
Statics_Stream.RenderSettings.graphics.GraphicsDevice.Indices = mesh.IndexBuffer;
foreach (ModelMeshPart part in mesh.MeshParts)
{
Statics_Stream.RenderSettings.graphics.GraphicsDevice.VertexDeclaration = part.VertexDeclaration;
Statics_Stream.RenderSettings.graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, part.StreamOffset, part.VertexStride);
part.Effect.CurrentTechnique = part.Effect.Techniques[technique];
part.Effect.Begin();
for (int k = 0; k < part.Effect.CurrentTechnique.Passes.Count; k++)
{
EffectPass pass = part.Effect.CurrentTechnique.Passes[k];
pass.Begin();
Statics_Stream.RenderSettings.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,
part.BaseVertex,
0,
part.NumVertices,
part.StartIndex,
part.PrimitiveCount);
pass.End();
}
part.Effect.End();
}
}
}
///
/// Draws a stand alone model that uses the triangle-strip content processor for loading.
///
/// Model to draw.
/// Shader technique to draw model with.
public void TriStrips(Model model, string technique)
{
foreach (ModelMesh mesh in model.Meshes)
{
Statics_Stream.RenderSettings.graphics.GraphicsDevice.Indices = mesh.IndexBuffer;
foreach (ModelMeshPart part in mesh.MeshParts)
{
part.Effect.CurrentTechnique = part.Effect.Techniques[technique];
Statics_Stream.RenderSettings.graphics.GraphicsDevice.VertexDeclaration = part.VertexDeclaration;
Statics_Stream.RenderSettings.graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, part.StreamOffset, part.VertexStride);
int numPrimitives;
if (mesh.IndexBuffer.IndexElementSize == IndexElementSize.SixteenBits)
{
numPrimitives = mesh.IndexBuffer.SizeInBytes / sizeof(ushort);
}
else
{
numPrimitives = mesh.IndexBuffer.SizeInBytes / sizeof(int);
}
numPrimitives -= 2;
part.Effect.Begin();
foreach (EffectPass pass in part.Effect.CurrentTechnique.Passes)
{
pass.Begin();
Statics_Stream.RenderSettings.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleStrip,
part.BaseVertex,
0,
part.NumVertices,
part.StartIndex,
numPrimitives);
pass.End();
}
part.Effect.End();
}
}
}
///
/// Draws an instanced model that uses the standard content processor.
///
/// Model to draw.
/// Shader technique to draw model with.
/// The number of bits between verticies. Use "vertexDeclaration.GetVertexStrideSize()" to find this.
public void InstancedTriList(Model model, string technique, int vertexStride)
{
foreach (ModelMesh mesh in model.Meshes)
{
// Set the index buffer
Statics_Stream.RenderSettings.graphics.GraphicsDevice.Indices = mesh.IndexBuffer;
// Tell the GPU how many times to run through the vertex data and set the stream.
Statics_Stream.RenderSettings.graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, 0, vertexStride);
foreach (ModelMeshPart part in mesh.MeshParts)
{
part.Effect.CurrentTechnique = part.Effect.Techniques[technique];
part.Effect.Begin();
for (int k = 0; k < part.Effect.CurrentTechnique.Passes.Count; k++)
{
EffectPass pass = part.Effect.CurrentTechnique.Passes[k];
pass.Begin();
Statics_Stream.RenderSettings.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,
part.BaseVertex,
0,
part.NumVertices,
part.StartIndex,
part.PrimitiveCount);
pass.End();
}
part.Effect.End();
}
}
}
///
/// Draws an instanced model that uses the triangle-strip content processor.
///
/// Model to draw.
/// Shader technique to draw model with.
/// The number of bits between verticies. Use "vertexDeclaration.GetVertexStrideSize()" to find this.
public void InstancedTriStrips(Model model, string technique, int vertexStride)
{
foreach (ModelMesh mesh in model.Meshes)
{
// Set the index buffer
Statics_Stream.RenderSettings.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.
Statics_Stream.RenderSettings.graphics.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, 0, vertexStride);
foreach (ModelMeshPart part in mesh.MeshParts)
{
part.Effect.CurrentTechnique = part.Effect.Techniques[technique];
part.Effect.Begin();
for (int k = 0; k < part.Effect.CurrentTechnique.Passes.Count; k++)
{
EffectPass pass = part.Effect.CurrentTechnique.Passes[k];
pass.Begin();
Statics_Stream.RenderSettings.graphics.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleStrip,
part.BaseVertex,
0,
part.NumVertices,
part.StartIndex,
numPrimitives);
pass.End();
}
part.Effect.End();
}
}
}
///
/// Draw the animated player model
///
/// Model Animator
/// Current animation controller
/// World matrix
/// Model to be drawn
/// Technique to use when drawing
public void AnimationDraw(ModelAnimator animator, AnimationController currentAnimation, Matrix matrix, Model model, string technique)
{
try
{
int index = 0;
// Update all the effects with the palette and world and draw the meshes
for (int i = 0; i < animator.numMeshes; i++)
{
// Get the mesh
ModelMesh mesh = model.Meshes[i];
// The starting index for the modelEffects array
int effectStartIndex = index;
if (animator.palette[i] != null && animator.matrixPaletteParams[index] != null)
{
foreach (Effect effect in mesh.Effects)
{
animator.worldParams[index].SetValue(matrix);
animator.matrixPaletteParams[index].SetValue(animator.palette[i]);
index++;
}
}
else
{
foreach (Effect effect in mesh.Effects)
{
animator.worldParams[index].SetValue(animator.pose[mesh.ParentBone.Index] * matrix);
index++;
}
}
int numParts = mesh.MeshParts.Count;
GraphicsDevice device = Statics_Stream.RenderSettings.graphics.GraphicsDevice;
device.Indices = mesh.IndexBuffer;
for (int j = 0; j < numParts; j++)
{
ModelMeshPart currentPart = mesh.MeshParts[j];
if (currentPart.NumVertices == 0 || currentPart.PrimitiveCount == 0)
continue;
Effect currentEffect = animator.modelEffects[effectStartIndex + j];
currentEffect.CurrentTechnique = currentEffect.Techniques[technique];
device.VertexDeclaration = currentPart.VertexDeclaration;
device.Vertices[0].SetSource(mesh.VertexBuffer, currentPart.StreamOffset, currentPart.VertexStride);
currentEffect.Begin();
EffectPassCollection passes = currentEffect.CurrentTechnique.Passes;
int numPasses = passes.Count;
for (int k = 0; k < numPasses; k++)
{
EffectPass pass = passes[k];
pass.Begin();
device.DrawIndexedPrimitives(PrimitiveType.TriangleList, currentPart.BaseVertex,
0, currentPart.NumVertices, currentPart.StartIndex, currentPart.PrimitiveCount);
pass.End();
}
currentEffect.End();
}
}
}
catch (NullReferenceException)
{
throw new InvalidOperationException("The effects on the model for a " +
"ModelAnimator were changed without calling ModelAnimator.InitializeEffectParams().");
}
catch (InvalidCastException)
{
throw new InvalidCastException("ModelAnimator has thrown an InvalidCastException. This is " +
"likely because the model uses too many bones for the matrix palette. The default palette size "
+ "is 56 for windows and 40 for Xbox.");
}
}
///
/// Draw the instanced animated model
///
/// Model Animator
/// Current animation controller
/// World matrix
/// Model to be drawn
/// Technique to use when drawing
/// Vertex stride of stream 0
public void InstancedAnimationDraw(ModelAnimator animator,
AnimationController currentAnimation,
Matrix matrix,
Model model,
string technique,
int vertexStride)
{
try
{
int index = 0;
// Update all the effects with the palette and world and draw the meshes
for (int i = 0; i < animator.numMeshes; i++)
{
// Get the mesh
ModelMesh mesh = model.Meshes[i];
// The starting index for the modelEffects array
int effectStartIndex = index;
if (animator.palette[i] != null && animator.matrixPaletteParams[index] != null)
{
foreach (Effect effect in mesh.Effects)
{
animator.worldParams[index].SetValue(matrix);
animator.matrixPaletteParams[index].SetValue(animator.palette[i]);
index++;
}
}
else
{
foreach (Effect effect in mesh.Effects)
{
animator.worldParams[index].SetValue(animator.pose[mesh.ParentBone.Index] * matrix);
index++;
}
}
int numParts = mesh.MeshParts.Count;
GraphicsDevice device = Statics_Stream.RenderSettings.graphics.GraphicsDevice;
device.Indices = mesh.IndexBuffer;
for (int j = 0; j < numParts; j++)
{
ModelMeshPart currentPart = mesh.MeshParts[j];
if (currentPart.NumVertices == 0 || currentPart.PrimitiveCount == 0)
continue;
Effect currentEffect = animator.modelEffects[effectStartIndex + j];
currentEffect.CurrentTechnique = currentEffect.Techniques[technique];
//device.VertexDeclaration = currentPart.VertexDeclaration;
device.Vertices[0].SetSource(mesh.VertexBuffer, currentPart.StreamOffset, vertexStride);
currentEffect.Begin();
EffectPassCollection passes = currentEffect.CurrentTechnique.Passes;
int numPasses = passes.Count;
for (int k = 0; k < numPasses; k++)
{
EffectPass pass = passes[k];
pass.Begin();
device.DrawIndexedPrimitives(PrimitiveType.TriangleList, currentPart.BaseVertex,
0, currentPart.NumVertices, currentPart.StartIndex, currentPart.PrimitiveCount);
pass.End();
}
currentEffect.End();
}
}
}
catch (NullReferenceException)
{
throw new InvalidOperationException("The effects on the model for a " +
"ModelAnimator were changed without calling ModelAnimator.InitializeEffectParams().");
}
catch (InvalidCastException)
{
throw new InvalidCastException("ModelAnimator has thrown an InvalidCastException. This is " +
"likely because the model uses too many bones for the matrix palette. The default palette size "
+ "is 56 for windows and 40 for Xbox.");
}
}
}
}