/*
* EntityBillboardSprite.cs
* Authors:
* Copyright (c) 2007-2008 Cornell University
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Util;
namespace tAC_Engine.Graphics.Entities
{
///
/// Defines a sprite that will always face in the direction of the camera
///
public class EntityBillboardSprite : DrawableGameScreenComponent
{
#region Fields
// Size of the particle for when reserving space in vertex buffer
private readonly int SIZE_IN_BYTES;
// A vertex buffer holding our particles. This contains the same data as
// the particles array, but copied across to where the GPU can access it.
private DynamicVertexBuffer mVertexBuffer;
// Vertex declaration describes the format of our ParticleVertex structure.
private VertexDeclaration mVertexDeclaration;
///
/// Reference to the current content manager
///
protected ContentManager Content;
///
/// Effect file used for rendering the billboard sprite
///
protected Effect mBillBoardShader;
// Information for how the sprite should be drawn
SpriteData mSpriteData;
// The texture that represents the billboard sprite
Texture2D mTexture;
///
/// The name of the texture file to be used
///
protected String m_TextureName;
// The current view matrix in which to render with
Matrix mView;
// The current projection matrix in which to render with
Matrix mProjection;
#endregion
#region Properties
///
/// Gets/Sets the sprite data
///
public SpriteData Particle
{
get { return mSpriteData; }
set
{
mSpriteData = value;
Game.GraphicsDevice.Vertices[0].SetSource(null, 0, 0);
SpriteData[] tempArray = new SpriteData[1];
tempArray[0] = mSpriteData;
mVertexBuffer.SetData(tempArray, 0, 1);
}
}
///
/// Gets the texture to be used for rendering
///
public Texture2D Texture { get { return mTexture; } }
///
/// Gets/Sets the name of the texture file to be used
///
public String TextureName
{
get { return m_TextureName; }
set { m_TextureName = value; }
}
///
/// Gets/Sets the current view matrix
///
public Matrix View
{
get { return mView; }
set { mView = value; }
}
///
/// Gets/Sets the current projection matrix
///
public Matrix Projection
{
get { return mProjection; }
set { mProjection = value; }
}
#endregion
#region Creation
///
/// Constructor for the billboard spite
///
/// Reference to the current content manager
/// Path name for the texture file
/// Information of the sprite for how it should be rendered
public EntityBillboardSprite(ContentManager pContent, String pTexturePathName, SpriteData pSpriteData)
{
Content = pContent;
m_TextureName = pTexturePathName;
mSpriteData = pSpriteData;
SIZE_IN_BYTES = System.Runtime.InteropServices.Marshal.SizeOf(typeof(SpriteData));
mVertexDeclaration = new VertexDeclaration(Game.GraphicsDevice, SpriteData.VertexElements);
mVertexBuffer = new DynamicVertexBuffer(Game.GraphicsDevice, SIZE_IN_BYTES,
BufferUsage.WriteOnly | BufferUsage.Points);
}
#endregion
#region Management
///
/// Loads in necessary information for content dependent objects
///
protected override void LoadContent()
{
base.LoadContent();
mTexture = Content.Load(m_TextureName);
mBillBoardShader = Content.Load(AssemblyLocator.GetLocation(typeof(EntityBillboardSprite).Assembly.FullName) + @"\Content\ParticleEffect");
Game.GraphicsDevice.Vertices[0].SetSource(null, 0, 0);
SpriteData[] tempArray = new SpriteData[1];
tempArray[0] = mSpriteData;
mVertexBuffer.SetData(tempArray, 0, 1);
}
#endregion
#region Render
///
/// Renders the billboard sprite
///
/// Time that has passed in game
public override void Draw(GameTime gameTime)
{
// Set point sprite values
Game.GraphicsDevice.RenderState.PointSpriteEnable = true;
Game.GraphicsDevice.RenderState.PointSizeMax = 256;
Game.GraphicsDevice.RenderState.DepthBufferEnable = true;
Game.GraphicsDevice.RenderState.DepthBufferWriteEnable = false;
mBillBoardShader.Parameters["View"].SetValue(mView);
mBillBoardShader.Parameters["Projection"].SetValue(mProjection);
mBillBoardShader.Parameters["Texture"].SetValue(mTexture);
mBillBoardShader.CommitChanges();
Game.GraphicsDevice.Vertices[0].SetSource(mVertexBuffer, 0, SIZE_IN_BYTES);
Game.GraphicsDevice.VertexDeclaration = mVertexDeclaration;
mBillBoardShader.Begin();
foreach (EffectPass pass in mBillBoardShader.CurrentTechnique.Passes)
{
pass.Begin();
Game.GraphicsDevice.DrawPrimitives(PrimitiveType.PointList, 0, 1);
pass.End();
}
mBillBoardShader.End();
base.Draw(gameTime);
}
#endregion
}
///
/// Defines the data size and information needed for rendering the billboard sprite
///
public struct SpriteData
{
///
/// Vector used for the size of the particle via two-dimensions
///
public Vector2 size;
///
/// Current position of the particle
///
public Vector3 position;
///
/// Vector used for the color of the particle via RGBA
///
public Vector4 color;
///
/// Describe the layout of this structure
///
public static readonly VertexElement[] VertexElements =
{
// Size data
new VertexElement(0, 0, VertexElementFormat.Vector2, VertexElementMethod.Default, VertexElementUsage.PointSize, 0),
// Position data
new VertexElement(0, 8, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0),
// Color data
new VertexElement(0, 20, VertexElementFormat.Vector4, VertexElementMethod.Default, VertexElementUsage.Color, 0)
};
}
}