//--------------------------------------------------------------------------------------------------------------------------------------------------- // // 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."); } } } }