<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
	<title>DirectX and XNA - Articles</title>
	<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/</link>
	<pubDate>Sat, 25 Feb 2012 22:21:08 +0000</pubDate>
	<ttl>43200</ttl>
	<description>Resources for the popular DirectX API and XNA framework</description>
	<item>
		<title>Using Animated Pieces in a Board-based Game wit...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/using-animated-pieces-in-a-board-based-game-wit-r2884</link>
		<description><![CDATA[This article by <strong class='bbc'>Kurt Jaegers</strong>, author of <a href='http://www.packtpub.com/xna-4-0-game-development-by-example-beginners-guide/book/rk/xna4_abr2/0910?utm_source=rk_xna4_abr2_0910&utm_medium=content&utm_campaign=ramsai' class='bbc_url' title='External link' rel='nofollow external'>XNA 4.0 Game Development by Example: Beginner's Guide</a>, enhances a board-based puzzle game called <a href='http://www.packtpub.com/article/building-board-based-puzzle-game-with-microsoft-xna-4' class='bbc_url' title='External link' rel='nofollow external'>Flood Control in XNA 4.0</a> using animation. In this article, we will cover:<ul class='bbc'><br /><li>Animating the rotation of pieces when manipulated by the player<br /></li><li>Gradually fading out pieces of completed scoring chains<br /></li><li>Animating the falling of pieces into place on the board<br /></li></ul><br />
All of these enhancements will give the player a better game experience, as well as give us the opportunity to learn more about how the SpriteBatch class can be used for animation.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Animated pieces</strong></span><br />
We will define three different types of animated pieces: rotating, falling, and fading. The animation for each of these types will be accomplished by altering the parameters of the <em class='bbc'>SpriteBatch.Draw()</em> call.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Classes for animated pieces</strong></span><br />
In order to represent the three types of animated pieces, we will create three new classes. Each of these classes will inherit from the GamePiece class, meaning they will contain all of the methods and members of the GamePiece class, but add additional information to support the animation.<br />
 <br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'><strong class='bbc'>Child classes</strong><br />
Child classes inherit all of their parent's members and methods. The RotatingPiece class can refer to the <em class='bbc'>pieceType</em> and <em class='bbc'>suffix</em> of the piece without recreating them within RotatingPiece itself. Additionally, child classes can extend the functionality of their base class, adding new methods and properties or overriding old ones. In fact, Game1 itself is a child of the <em class='bbc'>Micrsoft.Xna.Game</em> class, which is why all of the methods we use (<em class='bbc'>Update()</em>, <em class='bbc'>Draw()</em>, <em class='bbc'>LoadContent()</em>, and so on) are declared as "override".</em></p><br />
Let's begin by creating the class we will use for rotating pieces.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action – rotating pieces</strong></span><br />
Open your existing Flood Control project in Visual C# Express if it is not already active.<br />
<br />
Add a new class to the project called "RotatingPiece".<br />
<br />
Add "<em class='bbc'>using Microsoft.Xna.Framework;</em>" to the <em class='bbc'>using</em> area at the top of the class.<br />
<br />
Update the declaration of the class to read <em class='bbc'>class RotatingPiece : GamePiece</em>.<br />
<br />
Add the following declarations to the <em class='bbc'>RotatingPiece</em> class:<br />
<br />
	<pre class='prettyprint'>public bool clockwise;<br /><br />public static float rotationRate = (MathHelper.PiOver2 / 10);<br />private float rotationAmount = 0;<br />public int rotationTicksRemaining = 10;</pre><br />
Add a property to retrieve the current rotation amount:<br />
<br />
	<pre class='prettyprint'>public float RotationAmount<br />{<br />get<br />{<br />  if (clockwise)<br />	return rotationAmount;<br />  else<br />	return (MathHelper.Pi*2) - rotationAmount;<br />}<br />}</pre><br />
Add a constructor for the RotatingPiece class:<br />
<br />
	<pre class='prettyprint'>public RotatingPiece(string pieceType, bool clockwise)<br />	  : base(pieceType)<br />{<br />  this.clockwise = clockwise;<br />}</pre><br />
Add a method to update the piece:<br />
<br />
	<pre class='prettyprint'>public void UpdatePiece()<br />{<br />   rotationAmount += rotationRate;<br />   rotationTicksRemaining = (int)MathHelper.Max(0,<br />							rotationTicksRemaining-1);<br />}</pre><br />
<span style='font-size: 14px;'><strong class='bbc'>	What just happened?</strong></span><br />
In step 2, we modified the declaration of the RotatingPiece class by adding <em class='bbc'>: GamePiece</em> to the end of it. This indicates to Visual C# that the RotatingPiece class is a child of the GamePiece class.<br />
<br />
The clockwise variable stores a "true" value if the piece will be rotating clockwise and "false" if the rotation is counter-clockwise.<br />
<br />
When a game piece is rotated, it will turn a total of 90 degrees (or pi/2 radians) over <em class='bbc'>10</em> animation frames. The MathHelper class provides a number of constants to represent commonly used numbers, with <em class='bbc'>MathHelper.PiOver2</em> being equal to the number of radians in a 90 degree angle. We divide this constant by <em class='bbc'>10</em> and store the result as the <em class='bbc'>rotationRate</em> for use later. This number will be added to the <em class='bbc'>rotationAmount</em> float, which will be referenced when the animated piece is drawn.<br />
 <br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'><strong class='bbc'>Working with radians</strong><br />
All angular math is handled in radians from XNA's point of view. A complete (360 degree) circle contains 2*pi radians. In other words, one radian is equal to about 57.29 degrees. We tend to relate to circles more often in terms of degrees (a right angle being 90 degrees, for example), so if you prefer to work with degrees, you can use the <em class='bbc'>MathHelper.ToRadians()</em> method to convert your values when supplying them to XNA classes and methods.</em></p><br />
The final declaration, <em class='bbc'>rotationTicksRemaining</em>, is reduced by one each time the piece is updated. When this counter reaches zero, the piece has finished animating.<br />
<br />
When the piece is drawn, the <em class='bbc'>RotationAmount</em> property is referenced by a <em class='bbc'>spriteBatch</em>. <em class='bbc'>Draw()</em> call and returns either the <em class='bbc'>rotationAmount</em> property (in the case of a clockwise rotation) or 2*pi (a full circle) minus the <em class='bbc'>rotationAmount</em> if the rotation is counter-clockwise.<br />
<br />
The constructor in step 7 illustrates how the parameters passed to a constructor can be forwarded to the class' parent constructor via the <em class='bbc'>:base</em> specification. Since the GamePiece class has a constructor that accepts a piece type, we can pass that information along to its constructor while using the second parameter (clockwise) to update the clockwise member that does not exist in the GamePiece class. In this case, since both the clockwise member and the clockwise parameter have identical names, we specify <em class='bbc'>this.clockwise</em> to refer to the clockwise member of the RotatingPiece class. Simply <em class='bbc'>clockwise</em> in this scope refers only to the parameter passed to the constructor.<br />
 <br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'><strong class='bbc'>this notation</strong><br />
You can see that it is perfectly valid C# code to have method parameter names that match the names of class variables, thus potentially hiding the class variables from being used in the method (since referring to the name inside the method will be assumed to refer to the parameter). To ensure that you can always access your class variables even when a parameter name conflicts, you can preface the variable name with <em class='bbc'>this</em>. when referring to the class variable. <em class='bbc'>this</em>. indicates to C# that the variable you want to use is part of the class, and not a local method parameter.</em></p><br />
Lastly, the <em class='bbc'>UpdatePiece()</em> method simply increases the <em class='bbc'>rotationAmount</em> member while decreasing the <em class='bbc'>rotationTicksRemaining</em> counter (using <em class='bbc'>MathHelper.Max()</em> to ensure that the value does not fall below zero).<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action – falling pieces</strong></span><br />
Add a new class to the Flood Control project called "FallingPiece".<br />
<br />
Add <em class='bbc'>using Microsoft.Xna.Framework;</em> to the <em class='bbc'>using</em> area at the top of the class.<br />
<br />
Update the declaration of the class to read <em class='bbc'>class FallingPiece : GamePiece</em><br />
<br />
Add the following declarations to the <em class='bbc'>FallingPiece</em> class:<br />
<br />
	<pre class='prettyprint'>public int VerticalOffset;<br />public static int fallRate = 5;</pre><br />
Add a constructor for the FallingPiece class:<br />
<br />
	<pre class='prettyprint'>public FallingPiece(string pieceType, int verticalOffset)<br />	: base(pieceType)<br />{<br />  VerticalOffset = verticalOffset;<br />}</pre><br />
Add a method to update the piece:<br />
<br />
	<pre class='prettyprint'>public void UpdatePiece()<br />{<br />   VerticalOffset = (int)MathHelper.Max(<br />			0,<br />			VerticalOffset - fallRate);<br />}</pre><br />
<span style='font-size: 14px;'><strong class='bbc'>	What just happened?</strong></span><br />
Simpler than a RotatingPiece, a FallingPiece is also a child of the GamePiece class. A falling piece has an offset (how high above its final destination it is currently located) and a falling speed (the number of pixels it will move per update).<br />
<br />
As with a RotatingPiece, the constructor passes the <em class='bbc'>pieceType</em> parameter to its base class constructor and uses the <em class='bbc'>verticalOffset</em> parameter to set the <em class='bbc'>VerticalOffset</em> member. Note that the capitalization on these two items differs. Since <em class='bbc'>VerticalOffset</em> is declared as public and therefore capitalized by common C# convention, there is no need to use the "this" notation, since the two variables technically have different names.<br />
<br />
Lastly, the <em class='bbc'>UpdatePiece()</em> method subtracts <em class='bbc'>fallRate</em> from <em class='bbc'>VerticalOffset</em>, again using the <em class='bbc'>MathHelper.Max()</em> method to ensure the offset does not fall below zero.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action – fading pieces</strong></span><br />
Add a new class to the Flood Control project called "FadingPiece".<br />
<br />
Add using <em class='bbc'>Microsoft.Xna.Framework;</em> to the <em class='bbc'>using</em> area at the top of the class.<br />
<br />
Update the declaration of the class to read class <em class='bbc'>FadingPiece : GamePiece</em><br />
<br />
Add the following declarations to the <em class='bbc'>FadingPiece</em> class:<br />
<br />
	<pre class='prettyprint'>public float alphaLevel = 1.0f;<br />public static float alphaChangeRate = 0.02f;</pre><br />
Add a constructor for the <em class='bbc'>FadingPiece</em> class:<br />
<br />
	<pre class='prettyprint'>public FadingPiece(string pieceType, string suffix)<br />	: base(pieceType, suffix)<br />{<br />}</pre><br />
Add a method to update the piece:<br />
<br />
	<pre class='prettyprint'>public void UpdatePiece()<br />{<br />alphaLevel = MathHelper.Max(<br />	   0,<br />	   alphaLevel - alphaChangeRate);<br />}</pre><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
The simplest of our animated pieces, the <em class='bbc'>FadingPiece</em> only requires an alpha value (which always starts at 1.0f, or fully opaque) and a rate of change. The <em class='bbc'>FadingPiece</em> constructor simply passes the parameters along to the base constructor.<br />
<br />
When a <em class='bbc'>FadingPiece</em> is updated, <em class='bbc'>alphaLevel</em> is reduced by <em class='bbc'>alphaChangeRate</em>, making the piece more transparent.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Managing animated pieces</strong></span><br />
Now that we can create animated pieces, it will be the responsibility of the GameBoard class to keep track of them. In order to do that, we will define a <em class='bbc'>Dictionary</em> object for each type of piece.<br />
<br />
A <em class='bbc'>Dictionary</em> is a collection object similar to a List, except that instead of being organized by an index number, a dictionary consists of a set of key and value pairs. In an array or a List, you might access an entity by referencing its index as in <em class='bbc'>dataValues[2] = 12;</em> With a <em class='bbc'>Dictionary</em>, the index is replaced with your desired key type. Most commonly this will be a string value. This way, you can do something like <em class='bbc'>fruitColors["Apple"]="red";</em><br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action – updating GameBoard to support animated pieces</strong></span><br />
In the declarations section of the GameBoard class, add three dictionaries:<br />
<br />
	<pre class='prettyprint'>public Dictionary&lt;string, FallingPiece&gt; fallingPieces =<br />new Dictionary&lt;string, FallingPiece&gt;();<br />public Dictionary&lt;string, RotatingPiece&gt; rotatingPieces =<br />new Dictionary&lt;string, RotatingPiece&gt;();<br />public Dictionary&lt;string, FadingPiece&gt; fadingPieces =<br />new Dictionary&lt;string, FadingPiece&gt;();</pre><br />
Add methods to the GameBoard class to create new falling piece entries in the dictionaries:<br />
<br />
	<pre class='prettyprint'>public void AddFallingPiece(int X, int Y,<br />  string PieceName, int VerticalOffset)<br />{<br />  fallingPieces&#91;X.ToString() + "_" + Y.ToString()&#93; = new<br />	   FallingPiece(PieceName, VerticalOffset);<br />}<br /><br />public void AddRotatingPiece(int X, int Y,<br />string PieceName, bool Clockwise)<br />{<br />  rotatingPieces&#91;X.ToString() + "_" + Y.ToString()&#93; = new<br />	   RotatingPiece(PieceName, Clockwise);<br />}<br /><br />public void AddFadingPiece(int X, int Y, string PieceName)<br />{<br />  fadingPieces&#91;X.ToString() + "_" + Y.ToString()&#93; = new<br />	   FadingPiece(PieceName,"W");<br />}</pre><br />
Add the <em class='bbc'>ArePiecesAnimating()</em> method to the GameBoard class:<br />
<br />
	<pre class='prettyprint'>{<br />if ((fallingPieces.Count == 0) &&<br />	 (rotatingPieces.Count == 0) &&<br />	 (fadingPieces.Count == 0))<br />{<br />   return false;<br />}<br />else<br />{<br />   return true;<br />}<br />}</pre><br />
Add the <em class='bbc'>UpdateFadingPieces()</em> method to the GameBoard class:<br />
<br />
	<pre class='prettyprint'>private void UpdateFadingPieces()<br />{<br />  Queue&lt;string&gt; RemoveKeys = new Queue&lt;string&gt;();<br /><br />  foreach (string thisKey in fadingPieces.Keys)<br />  {<br />	fadingPieces&#91;thisKey&#93;.UpdatePiece();<br />	if (fadingPieces&#91;thisKey&#93;.alphaLevel == 0.0f)<br />		RemoveKeys.Enqueue(thisKey.ToString());<br />  }<br />  while (RemoveKeys.Count &gt; 0)<br />	  fadingPieces.Remove(RemoveKeys.Dequeue());<br />}</pre><br />
Add the <em class='bbc'>UpdateFallingPieces()</em> method to the GameBoard class:<br />
<br />
	<pre class='prettyprint'>private void UpdateFallingPieces()<br />{<br />  Queue&lt;string&gt; RemoveKeys = new Queue&lt;string&gt;();<br />  foreach (string thisKey in fallingPieces.Keys)<br />  {<br />   fallingPieces&#91;thisKey&#93;.UpdatePiece();<br />   if (fallingPieces&#91;thisKey&#93;.VerticalOffset == 0)<br />	   RemoveKeys.Enqueue(thisKey.ToString());<br />  }<br />  while (RemoveKeys.Count &gt; 0)<br />	 fallingPieces.Remove(RemoveKeys.Dequeue());<br />}</pre><br />
Add the <em class='bbc'>UpdateRotatingPieces()</em> method to the GameBoard class:<br />
<br />
	<pre class='prettyprint'>private void UpdateRotatingPieces()<br />{<br />  Queue&lt;string&gt; RemoveKeys = new Queue&lt;string&gt;();<br />  foreach (string thisKey in rotatingPieces.Keys)<br />  {<br />   rotatingPieces&#91;thisKey&#93;.UpdatePiece();<br />   if (rotatingPieces&#91;thisKey&#93;.rotationTicksRemaining == 0)<br />	   RemoveKeys.Enqueue(thisKey.ToString());<br />  }<br />  while (RemoveKeys.Count &gt; 0)<br />	   rotatingPieces.Remove(RemoveKeys.Dequeue());<br />}</pre><br />
Add the <em class='bbc'>UpdateAnimatedPieces()</em> method to the GameBoard class:<br />
<br />
	<pre class='prettyprint'>public void UpdateAnimatedPieces()<br />{<br />  if (fadingPieces.Count == 0)<br />  {<br />	UpdateFallingPieces();<br />	UpdateRotatingPieces();<br />  }<br />  else<br />  {<br />	UpdateFadingPieces();<br />  }<br />}</pre><br />
<span style='font-size: 14px;'><strong class='bbc'>	What just happened?</strong></span><br />
After declaring the three <em class='bbc'>Dictionary</em> objects, we have three methods used by the GameBoard class to create them when necessary. In each case, the key is built in the form "X_Y", so an animated piece in column 5 on row 4 will have a key of "5_4". Each of the three <em class='bbc'>Add...</em> methods simply pass the parameters along to the constructor for the appropriate piece types after determining the key to use.<br />
<br />
When we begin drawing the animated pieces, we want to be sure that animations finish playing before responding to other input or taking other game actions (like creating new pieces). The <em class='bbc'>ArePiecesAnimating()</em> method returns "true" if any of the <em class='bbc'>Dictionary</em> objects contain entries. If they do, we will not process any more input or fill empty holes on the game board until they have completed.<br />
<br />
The <em class='bbc'>UpdateAnimatedPieces()</em> method will be called from the game's <em class='bbc'>Update()</em> method and is responsible for calling the three different update methods above (<em class='bbc'>UpdateFadingPiece()</em>, <em class='bbc'>UpdateFallingPiece()</em>, and <em class='bbc'>UpdateRotatingPiece()</em>) for any animated pieces currently on the board. The first line in each of these methods declares a <em class='bbc'>Queue</em> object called RemoveKeys. We will need this because C# does not allow you to modify a <em class='bbc'>Dictionary</em> (or List, or any of the similar "generic collection" objects) while a <em class='bbc'>foreach</em> loop is processing them.<br />
<br />
A <em class='bbc'>Queue</em> is yet another generic collection object that works like a line at the bank. People stand in a line and await their turn to be served. When a bank teller is available, the first person in the line transacts his/her business and leaves. The next person then steps forward. This type of processing is known as FIFO, or First In, First Out.<br />
<br />
Using the <em class='bbc'>Enqueue()</em> and <em class='bbc'>Dequeue()</em> methods of the Queue class, objects can be added to the <em class='bbc'>Queue</em> (<em class='bbc'>Enqueue()</em>) where they await processing. When we want to deal with an object, we <em class='bbc'>Dequeue()</em> the oldest object in the <em class='bbc'>Queue</em> and handle it. <em class='bbc'>Dequeue()</em> returns the first object waiting to be processed, which is the oldest object added to the <em class='bbc'>Queue</em>.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Collection classes</strong></span><br />
C# provides a number of different "collection" classes, such as the Dictionary, Queue, List, and Stack objects. Each of these objects provides different ways to organize and reference the data in them. For information on the various collection classes and when to use each type, see the following MSDN entry: <a href='http://msdn.microsoft.com/en-us/library/6tc79sx1(VS.80).aspx' class='bbc_url' title='External link' rel='nofollow external'>http://msdn.microsof.&#46;&#46;/6tc79sx1(VS.80).aspx</a><br />
<br />
Each of the update methods loops through all of the keys in its own <em class='bbc'>Dictionary</em> and in turn calls the <em class='bbc'>UpdatePiece()</em> method for each key. Each piece is then checked to see if its animation has completed. If it has, its key is added to the <em class='bbc'>RemoveKeys</em> queue. After all of the pieces in the <em class='bbc'>Dictionary</em> have been processed, any keys that were added to <em class='bbc'>RemoveKeys</em> are then removed from the <em class='bbc'>Dictionary</em>, eliminating those animated pieces.<br />
<br />
If there are any FadingPieces currently active, those are the only animated pieces that <em class='bbc'>UpdateAnimatedPieces()</em> will update. When a row is completed, the scoring tiles fade out, the tiles above them fall into place, and new tiles fall in from above. We want all of the fading to finish before the other tiles start falling (or it would look strange as the new tiles pass through the fading old tiles).<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Fading pieces</strong></span><br />
In the discussion of <em class='bbc'>UpdateAnimatedPieces()</em>, we stated that fading pieces are added to the board whenever the player completes a scoring chain. Each piece in the chain is replaced with a fading piece.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action – generating fading pieces</strong></span><br />
In the Game1 class, modify the <em class='bbc'>CheckScoringChain()</em> method by adding the following call inside the <em class='bbc'>foreach</em> loop before the square is set to "Empty":<br />
<br />
	<pre class='prettyprint'>gameBoard.AddFadingPiece(<br />(int)ScoringSquare.X,<br />(int)ScoringSquare.Y,<br />gameBoard.GetSquare(<br />  (int)ScoringSquare.X,<br />  (int)ScoringSquare.Y));</pre><br />
<span style='font-size: 14px;'><strong class='bbc'>	What just happened?</strong></span><br />
Adding fading pieces is simply a matter of getting the square (before it is replaced with an empty square) and adding it to the <em class='bbc'>FadingPieces</em> dictionary. We need to use the <em class='bbc'>(int)</em> typecasts because the <em class='bbc'>ScoringSquare</em> variable is a <em class='bbc'>Vector2</em> value, which stores its X and Y components as floats.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Falling pieces</strong></span><br />
Falling pieces are added to the game board in two possible locations: From the <em class='bbc'>FillFromAbove()</em> method when a piece is being moved from one location on the board to another, and in the <em class='bbc'>GenerateNewPieces()</em> method, when a new piece falls in from the top of the game board.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action – generating falling pieces</strong></span><br />
Modify the <em class='bbc'>FillFromAbove()</em> method of the GameBoard class by adding a call to generate falling pieces right before the <em class='bbc'>rowLookup = -1;</em> line:<br />
<br />
	<pre class='prettyprint'>AddFallingPiece(x, y, GetSquare(x, y),<br />   GamePiece.PieceHeight *(y-rowLookup));</pre><br />
Update the <em class='bbc'>GenerateNewPieces()</em> method by adding the following call right after the <em class='bbc'>RandomPiece(x,y)</em> line:<br />
<br />
	<pre class='prettyprint'>AddFallingPiece(x, y, GetSquare(x, y),<br />   GamePiece.PieceHeight * GameBoardHeight);</pre><br />
<span style='font-size: 14px;'><strong class='bbc'>	What just happened?</strong></span><br />
When <em class='bbc'>FillFromAbove()</em> moves a piece downward, we now create an entry in the <em class='bbc'>FallingPieces</em> dictionary that is equivalent to the newly moved piece. The vertical offset is set to the height of a piece (40 pixels) times the number of board squares the piece was moved. For example, if the empty space was at location 5,5 on the board, and the piece above it (5,4) is being moved down one block, the animated piece is created at 5,5 with an offset of 40 pixels (5-4 = 1, times 40).<br />
<br />
When new pieces are generated for the board, they are added with an offset equal to the height (in pixels) of the game board, determined by multiplying the <em class='bbc'>GamePiece.PieceHeight</em> value by the <em class='bbc'>GameBoardHeight</em>. This means they will always start above the playing area and fall into it.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Rotating pieces</strong></span><br />
The last type of animated piece we need to deal with adding during play is the rotation piece. This piece type is added whenever the user clicks on a game piece.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action – modify Game1 to generate rotating pieces</strong></span><br />
Update the <em class='bbc'>HandleMouseInput()</em> method in the Game1 class to add rotating pieces to the board by adding the following inside the <em class='bbc'>if (mouseState.LeftButton == ButtonState.Pressed)</em> block before <em class='bbc'>gameBoard.RotatePiece()</em> is called:<br />
<br />
	<pre class='prettyprint'>gameBoard.AddRotatingPiece(x, y,<br />	gameBoard.GetSquare(x, y), false);</pre><br />
Still in <em class='bbc'>HandleMouseInput()</em>, add the following in the same location inside the <em class='bbc'>if</em> block for the right mouse button:<br />
<br />
	<pre class='prettyprint'>gameBoard.AddRotatingPiece(x, y,<br />   gameBoard.GetSquare(x, y), true);</pre><br />
<span style='font-size: 14px;'><strong class='bbc'>	What just happened?</strong></span><br />
Recall that the only difference between a clockwise rotation and a counter-clockwise rotation (from the standpoint of the <em class='bbc'>AddRotatingPiece()</em> method) is a true or false in the final parameter. Depending on which button is clicked, we simply add the current square (before it gets rotated, otherwise the starting point for the animation would be the final position) and "true" for right mouse clicks or "false" for left mouse clicks.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Calling UpdateAnimatedPieces()</strong></span><br />
In order for the <em class='bbc'>UpdateAnimatedPieces()</em> method of the GameBoard class to run, the game's <em class='bbc'>Update()</em> method needs to be modified to call it.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action – updating Game1 to update animated pieces</strong></span><br />
Modify the <em class='bbc'>Update()</em> method of the Game1 class by replacing the current <em class='bbc'>case</em> statement for the <em class='bbc'>GameState.Playing</em> state with:<br />
<br />
	<pre class='prettyprint'>case GameStates.Playing:<br />  timeSinceLastInput +=<br />	(float)gameTime.ElapsedGameTime.TotalSeconds;<br />  if (gameBoard.ArePiecesAnimating())<br />  {<br />   gameBoard.UpdateAnimatedPieces();<br />  }<br />  else<br />  {<br />   gameBoard.ResetWater();<br /><br />   for (int y = 0; y &lt; GameBoard.GameBoardHeight; y++)<br />   {<br />	CheckScoringChain(gameBoard.GetWaterChain(y));<br />   }<br />   gameBoard.GenerateNewPieces(true);<br /><br />   if (timeSinceLastInput &gt;= MinTimeSinceLastInput)<br />   {<br />	HandleMouseInput(Mouse.GetState());<br />   }<br />  }<br />  break;</pre><br />
<span style='font-size: 14px;'><strong class='bbc'>	What just happened?</strong></span><br />
This method is very similar to its previous incarnation. In this instance, we check to see if there are outstanding animated pieces to process. If there are, <em class='bbc'>UpdateAnimatedPieces()</em> is run. If no animated pieces currently exist, the previous behaviour of the <em class='bbc'>GameStates</em>. <em class='bbc'>Playing</em> case is executed.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Drawing animated pieces</strong></span><br />
Our animated pieces are almost completed. In fact, they all function right now but you cannot see them because we have not yet updated <em class='bbc'>Draw()</em> to take them into account.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action – update Game1 to draw animated pieces</strong></span><br />
Add methods to the Game1 class to draw each potential type of game piece (animated and non-animated):<br />
<br />
	<pre class='prettyprint'>private void DrawEmptyPiece(int pixelX, int pixelY)<br />{<br />  spriteBatch.Draw(<br />   playingPieces,<br />   new Rectangle(pixelX, pixelY,<br />	GamePiece.PieceWidth, GamePiece.PieceHeight),<br />	EmptyPiece,<br />	Color.White);<br />}<br /><br />private void DrawStandardPiece(int x, int y,<br />  int pixelX, int pixelY)<br />{<br />  spriteBatch.Draw(<br />   playingPieces, new Rectangle(pixelX, pixelY,<br />	 GamePiece.PieceWidth, GamePiece.PieceHeight),<br />   gameBoard.GetSourceRect(x, y),<br />   Color.White);<br />}<br /><br />private void DrawFallingPiece(int pixelX, int pixelY,<br />	string positionName)<br />{<br />  spriteBatch.Draw(<br />   playingPieces,<br />   new Rectangle(pixelX, pixelY -<br />	 gameBoard.fallingPieces&#91;positionName&#93;.VerticalOffset,<br />	  GamePiece.PieceWidth, GamePiece.PieceHeight),<br />	  gameBoard.fallingPieces&#91;positionName&#93;.GetSourceRect(),<br />	 Color.White);<br />}<br /><br />private void DrawFadingPiece(int pixelX, int pixelY,<br />   string positionName)<br />{<br />  spriteBatch.Draw(<br />   playingPieces,<br />   new Rectangle(pixelX, pixelY,<br />	GamePiece.PieceWidth, GamePiece.PieceHeight),<br />   gameBoard.fadingPieces&#91;positionName&#93;.GetSourceRect(),<br />   Color.White *<br />	gameBoard.fadingPieces&#91;positionName&#93;.alphaLevel);<br />}<br /><br />private void DrawRotatingPiece(int pixelX, int pixelY,<br />   string positionName)<br />{<br />  spriteBatch.Draw(<br />   playingPieces,<br />   new Rectangle(pixelX + (GamePiece.PieceWidth / 2),<br />	   pixelY + (GamePiece.PieceHeight / 2),<br />	   GamePiece.PieceWidth,<br />	   GamePiece.PieceHeight),<br />   gameBoard.rotatingPieces&#91;positionName&#93;.GetSourceRect(),<br />   Color.White,<br />   gameBoard.rotatingPieces&#91;positionName&#93;.RotationAmount,<br />   new Vector2(GamePiece.PieceWidth / 2,<br />	 GamePiece.PieceHeight / 2),<br />   SpriteEffects.None, 0.0f);<br />}</pre><br />
Modify the <em class='bbc'>Draw()</em> method of the Game1 class by replacing the <em class='bbc'>for</em> loop that currently draws the playing pieces with:<br />
<br />
	<pre class='prettyprint'>for (int x = 0; x &lt; GameBoard.GameBoardWidth; x++)<br />  for (int y = 0; y &lt; GameBoard.GameBoardHeight; y++)<br />  {<br />   int pixelX = (int)gameBoardDisplayOrigin.X +<br />	   (x * GamePiece.PieceWidth);<br />   int pixelY = (int)gameBoardDisplayOrigin.Y +<br />	   (y * GamePiece.PieceHeight);<br /><br />   DrawEmptyPiece(pixelX, pixelY);<br /><br />   bool pieceDrawn = false;<br /><br />   string positionName = x.ToString() + "_" + y.ToString();<br /><br />   if (gameBoard.rotatingPieces.ContainsKey(positionName))<br />   {<br />	DrawRotatingPiece(pixelX, pixelY, positionName);<br />	pieceDrawn = true;<br />   }<br /><br />   if (gameBoard.fadingPieces.ContainsKey(positionName))<br />   {<br />	DrawFadingPiece(pixelX, pixelY, positionName);<br />	pieceDrawn = true;<br />   }<br /><br />   if (gameBoard.fallingPieces.ContainsKey(positionName))<br />   {<br />	DrawFallingPiece(pixelX, pixelY, positionName);<br />	pieceDrawn = true;<br />   }<br /><br />   if (!pieceDrawn)<br />   {<br />	DrawStandardPiece(x, y, pixelX, pixelY);<br />   }<br />}</pre><br />
Try it out! Run your game and complete a few rows.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>	What just happened?</strong></span><br />
To keep things organized, we have split the drawing of each of the different potential piece types into its own small method. These methods (<em class='bbc'>DrawEmptyPiece()</em>, <em class='bbc'>DrawStandardPiece()</em>, <em class='bbc'>DrawFallingPiece()</em>, <em class='bbc'>DrawFadingPiece()</em>, and <em class='bbc'>DrawRotatingPiece()</em>) each contain only a single statement to draw the piece.<br />
<br />
Before we look at how each of the pieces is actually drawn, let's examine the way we determine which of these methods to call when drawing a piece. The structure of the drawing loop is still the same as it was before we added animated pieces: each square on the board is looped through, with a blank square being drawn first in each position.<br />
<br />
After the blank space, a new Boolean value called <em class='bbc'>pieceDrawn</em> is declared and set to false. If an animated piece occupies a square, only the animated piece will be drawn, and not the underlying game piece.<br />
<br />
The reason for this is that when the user clicks on the mouse button to rotate a piece, in memory the piece is rotated immediately. The animated piece that the user sees is inserted into the drawing process so it looks like the piece is turning. If both the animated piece and the real underlying piece were to be drawn, the final rotation position would be visible overlaid on top of the rotating piece while the rotation animation was playing.<br />
<br />
The <em class='bbc'>positionName</em> string contains the dictionary key for the space we are currently drawing (in "X_Y" format). We use this to check each of the animated piece dictionaries to see if they contain an entry for that key.<br />
<br />
If they do, the animated piece is drawn and the <em class='bbc'>pieceDrawn</em> variable is set to true. If the piece still has not been drawn after all of the dictionaries have been checked, the base piece is drawn just as it was before.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>SpriteBatch overloads</strong></span><br />
Both falling and fading pieces are drawn using the <em class='bbc'>SpriteBatch.Draw()</em> overload that we are already familiar with; where a <em class='bbc'>Texture2D</em>, destination <em class='bbc'>Rectangle</em>, source <em class='bbc'>Rectangle</em>, and <em class='bbc'>Color</em> are specified when drawing. By multiplying our base drawing color (white) by the alpha value for a fading piece, we cause the whole piece to be drawn partially transparent. As the time passes, the alpha value will reach zero, and the piece will be fully transparent.<br />
<br />
However, rotated pieces need to use an extended version of the <em class='bbc'>SpriteBatch.Draw()</em> call. The first four parameters are the same as our existing <em class='bbc'>Draw()</em> calls. To these parameters, we add a float for the rotation amount, a <em class='bbc'>Vector2</em> for the origin around which the rotation takes place, a <em class='bbc'>SpriteEffects</em> property (set to <em class='bbc'>SpriteEffects.None</em> in this case) and a sorting depth (set to 0, or the top level).<br />
<br />
When using a rotation with this form of the <em class='bbc'>SpriteBatch.Draw()</em> call, it is necessary to specify the point around which the sprite should be rotated. If we were to set the origin to <em class='bbc'>Vector2.Zero</em> (equivalent to 0, 0) the sprite would rotate around the upper left corner of the image, swinging into the spaces of other tiles on the board. The center point of the sprite is specified in local sprite coordinates (as opposed to screen coordinates, or even coordinates within the texture the sprite is being pulled from). The local coordinates of the sprite range from 0, 0 in the upper left corner to the height and width of the sprite in the lower right. In our case, the lower right corner of the sprite is <em class='bbc'>GamePiece.PieceWidth</em>, <em class='bbc'>GamePiece.PieceHeight</em>, or 40, 40.<br />
<br />
By specifying <em class='bbc'>new Vector2(GamePiece.PieceWidth/2, GamePiece.PieceHeight/2)</em> we are setting the origin to the center of the sprite, meaning it will rotate in place as expected.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Summary</strong></span><br />
In the above article we covered:<ul class='bbc'><br /><li>Animating the rotation of pieces when manipulated by the player<br /></li><li>Gradually fading out pieces of completed scoring chains<br /></li><li>Animating the falling of pieces into place on the board<br /></li></ul>]]></description>
		<pubDate>Sat, 25 Feb 2012 04:33:01 +0000</pubDate>
		<guid isPermaLink="false">697782646a61d39ff18134e51fe7db85</guid>
	</item>
	<item>
		<title>3D Animation Techniques with XNA Game Studio 4.0</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/3d-animation-techniques-with-xna-game-studio-40-r2879</link>
		<description><![CDATA[In this article, we will look at several ways to make the objects in our scene move. First, we will look at the animation of objects as a whole. We will do this through simple linear interpolation between start and end values, and through a more complex curve interpolation. We will also look at more complex animations through keyframed animation.<br />
<br />
This article by <strong class='bbc'>Sean James</strong>, author of <a href='http://www.packtpub.com/3d-graphics-with-xna-game-studio-4-0/book/rk/3dxna-abr4/0111?utm_source=rk_3dxna_abr4_0111&utm_medium=content&utm_campaign=ramsai' class='bbc_url' title='External link' rel='nofollow external'>3D Graphics with XNA Game Studio 4.0</a>, covers:<ul class='bbc'><br /><li>Object animation<br /></li><li>Keyframed animation<br /></li><li>Curve interpolation<br /></li></ul><br />
<span style='font-size: 18px;'><strong class='bbc'>Object animation</strong></span><br />
We will first look at the animation of objects as a whole. The most common ways to animate an object are rotation and translation (movement). We will begin by creating a class that will interpolate a position and rotation value between two extremes over a given amount of time. We could also have it interpolate between two scaling values, but it is very uncommon for an object to change size in a smooth manner during gameplay, so we will leave it out for simplicity's sake.<br />
<br />
The <em class='bbc'>ObjectAnimation</em> class has a number of parameters—starting and ending position and rotation values, a duration to interpolate during those values, and a Boolean indicating whether or not the animation should loop or just remain at the end value after the duration has passed:<br />
<br />
<pre class='prettyprint'>public class ObjectAnimation<br />{<br />  Vector3 startPosition, endPosition, startRotation, endRotation;<br />  TimeSpan duration;<br />  bool loop;<br />}</pre><br />
We will also store the amount of time that has elapsed since the animation began, and the current position and rotation values:<br />
<br />
<pre class='prettyprint'>TimeSpan elapsedTime = TimeSpan.FromSeconds(0);<br /><br />public Vector3 Position { get; private set; }<br />public Vector3 Rotation { get; private set; }</pre><br />
The constructor will initialize these values:<br />
<br />
<pre class='prettyprint'>public ObjectAnimation(Vector3 StartPosition, Vector3 EndPosition,<br />  Vector3 StartRotation, Vector3 EndRotation, TimeSpan Duration,<br />  bool Loop)<br />{<br />  this.startPosition = StartPosition;<br />  this.endPosition = EndPosition;<br />  this.startRotation = StartRotation;<br />  this.endRotation = EndRotation;<br />  this.duration = Duration;<br />  this.loop = Loop;<br />  Position = startPosition;<br />  Rotation = startRotation;<br />}</pre><br />
Finally, the <em class='bbc'>Update()</em> function takes the amount of time that has elapsed since the last update and updates the position and rotation values accordingly:<br />
<br />
<pre class='prettyprint'>public void Update(TimeSpan Elapsed)<br />{<br />  // Update the time<br />  this.elapsedTime += Elapsed;<br /><br />  // Determine how far along the duration value we are (0 to 1)<br />  float amt = (float)elapsedTime.TotalSeconds / (float)duration.<br />TotalSeconds;<br /><br />  if (loop)<br />	 while (amt &gt; 1) // Wrap the time if we are looping<br />		   amt -= 1;<br />  else // Clamp to the end value if we are not<br />	 amt = MathHelper.Clamp(amt, 0, 1);<br /><br />  // Update the current position and rotation<br />  Position = Vector3.Lerp(startPosition, endPosition, amt);<br />  Rotation = Vector3.Lerp(startRotation, endRotation, amt);<br />}</pre><br />
As a simple example, we'll create an animation (in the <em class='bbc'>Game1</em> class) that rotates our spaceship in a circle over a few seconds:<br />
<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/0041OT_09_01.png' alt='Posted Image' class='bbc_img' /></span></p><br />
We'll also have it move the model up and down for demonstration's sake:<br />
<br />
<pre class='prettyprint'>ObjectAnimation anim;</pre><br />
We initialize it in the constructor:<br />
<br />
<pre class='prettyprint'>models.Add(new CModel(Content.Load("ship"),<br />  Vector3.Zero, Vector3.Zero, new Vector3(0.25f), GraphicsDevice));<br /><br />anim = new ObjectAnimation(new Vector3(0, -150, 0),<br />	   new Vector3(0, 150, 0),<br />	   Vector3.Zero, new Vector3(0, -MathHelper.TwoPi, 0),<br />	   TimeSpan.FromSeconds(10), true);</pre><br />
We update it as follows:<br />
<br />
<pre class='prettyprint'>anim.Update(gameTime.ElapsedGameTime);<br /><br />models&#91;0&#93;.Position = anim.Position;<br />models&#91;0&#93;.Rotation = anim.Rotation;</pre><br />
<span style='font-size: 18px;'><strong class='bbc'>Keyframed animation</strong></span><br />
Our <em class='bbc'>ObjectAnimation</em> class allows us to create simple linear animations, but we can't create anything more complex. For example, we can't make our spaceship move in a circle with this class. To achieve more complex animations, we will use what is called <strong class='bbc'>keyframed animation</strong>. In this method, we specify "key" frames where we want the object to be in a specific position and orientation. We then rely on the code to interpolate between those values to fill in the frames between the key frames.<br />
<br />
The following screenshot shows our spaceship at the keyframed positions along a path, and the black line shows the path that would be taken by interpolating between keyframes:<br />
 <br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/0041OT_09_02.png' alt='Posted Image' class='bbc_img' /></span></p><br />
Keyframed animation is useful because it is a fast way to create somewhat complex animations without having to animate each frame. For example, birds flying through the air, soldiers on patrol, or even a camera flying through a scene, can all be animated through keyframes. This is probably the easiest way to move the camera during a cutscene, for example. We represent a key frame with the <em class='bbc'>ObjectAnimationFrame</em> class. Like the previous class, it contains position and rotation values. It also, however, contains a time value, marking this frame's time offset from the beginning of the animation.<br />
<br />
<pre class='prettyprint'>public class ObjectAnimationFrame<br />{<br />  public Vector3 Position { get; private set; }<br />  public Vector3 Rotation { get; private set; }<br />  public TimeSpan Time { get; private set; }<br /><br />  public ObjectAnimationFrame(Vector3 Position, Vector3 Rotation,<br />   TimeSpan Time)<br />  {<br />	this.Position = Position;<br />	this.Rotation = Rotation;<br />	this.Time = Time;<br />  }<br />}</pre><br />
We can now create a new animation class that uses key frames:<br />
<br />
<pre class='prettyprint'>public class KeyframedObjectAnimation<br />{<br />List frames = new List();<br />bool loop;<br />TimeSpan elapsedTime = TimeSpan.FromSeconds(0);<br /><br />public Vector3 Position { get; private set; }<br />public Vector3 Rotation { get; private set; }<br /><br />public KeyframedObjectAnimation(List Frames,<br />  bool Loop)<br />{<br />  this.frames = Frames;<br />   this.loop = Loop;<br />  Position = Frames&#91;0&#93;.Position;<br />  Rotation = Frames&#91;0&#93;.Rotation;<br />}<br />}</pre><br />
Finally, the <em class='bbc'>Update()</em> function fï»¿igures out which frame we are on and interpolates between its values and the next frame's values, based on how far between them we are:<br />
<br />
<pre class='prettyprint'>public void Update(TimeSpan Elapsed)<br />{<br />  // Update the time<br />  this.elapsedTime += Elapsed;<br /><br />  TimeSpan totalTime = elapsedTime;<br />  TimeSpan end = frames&#91;frames.Count - 1&#93;.Time;<br /><br />  if (loop) // Loop around the total time if necessary<br />	while (totalTime &gt; end)<br />	   totalTime -= end;<br />  else // Otherwise, clamp to the end values<br />  {<br />	Position = frames&#91;frames.Count - 1&#93;.Position;<br />	Rotation = frames&#91;frames.Count - 1&#93;.Rotation;<br />	return;<br />  }<br /><br />  int i = 0;<br />  // Find the index of the current frame<br />  while(frames&#91;i + 1&#93;.Time	  i++;<br />  // Find the time since the beginning of this frame<br />  totalTime -= frames&#91;i&#93;.Time;<br /><br />  // Find how far we are between the current and next frame (0 to 1)<br />  float amt = (float)((totalTime.TotalSeconds) /<br />	 (frames&#91;i + 1&#93;.Time - frames&#91;i&#93;.Time).TotalSeconds);<br /><br />  // Interpolate position and rotation values between frames<br />  Position = Vector3.Lerp(frames&#91;i&#93;.Position, frames&#91;i + 1&#93;.Position,<br />   amt);<br />  Rotation = Vector3.Lerp(frames&#91;i&#93;.Rotation, frames&#91;i + 1&#93;.Rotation,<br />   amt);<br />}</pre><br />
For example, we can now create a new animation to move our spaceship in a square:<br />
<br />
<pre class='prettyprint'>KeyframedObjectAnimation anim;</pre><br />
We set it up as follows:<br />
<br />
<pre class='prettyprint'>List frames = new List();<br /><br />frames.Add(new ObjectAnimationFrame(new Vector3(-1000, 100, -1000),<br />  new Vector3(0, MathHelper.ToRadians(-90), 0),<br />  TimeSpan.FromSeconds(0)));<br />frames.Add(new ObjectAnimationFrame(new Vector3(1000, 100, -1000),<br />  new Vector3(0, MathHelper.ToRadians(-90), 0),<br />  TimeSpan.FromSeconds(3)));<br />frames.Add(new ObjectAnimationFrame(new Vector3(1000, 100, -1000),<br />  new Vector3(0, MathHelper.ToRadians(-180), 0),<br />  TimeSpan.FromSeconds(6)));<br />frames.Add(new ObjectAnimationFrame(new Vector3(1000, 100, 1000),<br />  new Vector3(0, MathHelper.ToRadians(-180), 0),<br />  TimeSpan.FromSeconds(9)));<br />frames.Add(new ObjectAnimationFrame(new Vector3(1000, 100, 1000),<br />  new Vector3(0, MathHelper.ToRadians(-270), 0),<br />  TimeSpan.FromSeconds(12)));<br />frames.Add(new ObjectAnimationFrame(new Vector3(-1000, 100, 1000),<br />  new Vector3(0, MathHelper.ToRadians(-270), 0),<br />  TimeSpan.FromSeconds(15)));<br />frames.Add(new ObjectAnimationFrame(new Vector3(-1000, 100, 1000),<br />  new Vector3(0, MathHelper.ToRadians(-360), 0),<br />  TimeSpan.FromSeconds(18)));<br />frames.Add(new ObjectAnimationFrame(new Vector3(-1000, 100, -1000),<br />  new Vector3(0, MathHelper.ToRadians(-360), 0),<br />  TimeSpan.FromSeconds(21)));<br />frames.Add(new ObjectAnimationFrame(new Vector3(-1000, 100, -1000),<br />  new Vector3(0, MathHelper.ToRadians(-450), 0),<br />  TimeSpan.FromSeconds(24)));<br /><br />anim = new KeyframedObjectAnimation(frames, true);</pre><br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/0041OT_09_03.png' alt='Posted Image' class='bbc_img' /></span></p><br />
The <em class='bbc'>Update</em> code remains the same. Running the game, you will see the spaceship move from corner to corner of a box, turning towards the next corner at each stop.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Curve interpolation</strong></span><br />
We now have the ability to make animations with multiple key frames, which allows us to create more complex animations. However, we are still interpolating linearly between those key frames. This looks good for rotations, for example, but it would not look good for an object following a path, as the object would abruptly change direction after reaching a key frame in its animation. Instead, we want to be able to have our objects follow a smooth curve through the positions defined in the key frames. We will do this with what is called <strong class='bbc'>Catmull-Rom interpolation</strong>. This is a process that will create a curve through our key frame positions, allowing for much smoother object animation:<br />
 <br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/0041OT_09_04.png' alt='Posted Image' class='bbc_img' /></span></p><br />
Let's modify the <em class='bbc'>KeyframedObjectAnimation</em> class to use Catmull-Rom interpolation for the position value. XNA has a built-in function to calculate an interpolated position between the second and third points in a set of four points using Catmull-rom interpolation. However, it works only in one dimension, so we'll need to create a function that will interpolate between a set of instances of <em class='bbc'>Vector3</em>:<br />
<br />
<pre class='prettyprint'>Vector3 catmullRom3D(Vector3 v1, Vector3 v2, Vector3 v3,<br />Vector3 v4, float amt)<br />{<br />return new Vector3(<br />  MathHelper.CatmullRom(v1.X, v2.X, v3.X, v4.X, amt),<br />  MathHelper.CatmullRom(v1.Y, v2.Y, v3.Y, v4.Y, amt),<br />  MathHelper.CatmullRom(v1.Z, v2.Z, v3.Z, v4.Z, amt));<br />}</pre><br />
The <em class='bbc'>amt</em> argument specifies how far (0 to 1) between the second and third vectors the new position should be. We can now modify the position calculation to use this new function:<br />
<br />
<pre class='prettyprint'>// Interpolate position and rotation values between frames<br />Position = catmullRom3D(frames&#91;wrap(i - 1, frames.Count - 1)&#93;.<br />Position,<br />  frames&#91;wrap(i, frames.Count - 1)&#93;.Position,<br />  frames&#91;wrap(i + 1, frames.Count - 1)&#93;.Position,<br />  frames&#91;wrap(i + 2, frames.Count - 1)&#93;.Position, amt);</pre><br />
The <em class='bbc'>wrap()</em> function wraps the value that it is given around a certain interval—in this case [0, <em class='bbc'>frames.Count</em> – 1]. This means that we will not have to worry about our indices going out of range when finding the last point, next point, and so on, but it does mean that this type of interpolation will work best with a closed curve—a circle, for example:<br />
<br />
<pre class='prettyprint'>// Wraps the "value" argument around &#91;0, max&#93;<br />int wrap(int value, int max)<br />{<br />  while (value &gt; max)<br />	value -= max;<br /><br />  while (value	 value += max;<br />  return value;<br />}</pre><br />
We could now create the following keyframed animation with a curved path to demonstrate our new interpolation method:<br />
<br />
<pre class='prettyprint'>List frames = new List();<br /><br />frames.Add(new ObjectAnimationFrame(new Vector3(-500, 100, 1000),<br />  new Vector3(0, MathHelper.ToRadians(0), 0),<br />  TimeSpan.FromSeconds(0)));<br />frames.Add(new ObjectAnimationFrame(new Vector3(500, 100, 500),<br />  new Vector3(0, MathHelper.ToRadians(0), 0),<br />  TimeSpan.FromSeconds(3)));<br />frames.Add(new ObjectAnimationFrame(new Vector3(-500, 100, 0),<br />  new Vector3(0, MathHelper.ToRadians(0), 0),<br />  TimeSpan.FromSeconds(6)));<br />frames.Add(new ObjectAnimationFrame(new Vector3(500, 100, -500),<br />  new Vector3(0, MathHelper.ToRadians(0), 0),<br />  TimeSpan.FromSeconds(9)));<br />frames.Add(new ObjectAnimationFrame(new Vector3(-500, 100, -1000),<br />  new Vector3(0, MathHelper.ToRadians(180), 0),<br />  TimeSpan.FromSeconds(12)));<br />frames.Add(new ObjectAnimationFrame(new Vector3(-500, 100, 1000),<br />  new Vector3(0, MathHelper.ToRadians(180), 0),<br />  TimeSpan.FromSeconds(15)));<br />frames.Add(new ObjectAnimationFrame(new Vector3(-500, 100, 1000),<br />  new Vector3(0, MathHelper.ToRadians(360), 0),<br />  TimeSpan.FromSeconds(18)));<br /><br />anim = new KeyframedObjectAnimation(frames, true);</pre><br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/0041OT_09_05.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<span style='font-size: 18px;'><strong class='bbc'>Summary</strong></span><br />
In this article we have covered the following concepts:<ul class='bbc'><br /><li>Object animation<br /></li><li>Keyframed animation<br /></li><li>Curve interpolation<br /></li></ul>]]></description>
		<pubDate>Thu, 23 Feb 2012 20:34:11 +0000</pubDate>
		<guid isPermaLink="false">1ada62a8c0df8c2909a8669d78a338cb</guid>
	</item>
	<item>
		<title>Building a Complete Board-based Puzzle Game wit...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/building-a-complete-board-based-puzzle-game-wit-r2871</link>
		<description><![CDATA[This article by <strong class='bbc'>Kurt Jaegers</strong>, author of <a href='http://www.packtpub.com/xna-4-0-game-development-by-example-beginners-guide/book/rk/xna4_abr1/0910?utm_source=rk_xna4_abr1_0910&utm_medium=content&utm_campaign=ramsai' class='bbc_url' title='External link' rel='nofollow external'>XNA 4.0 Game Development by Example: Beginner's Guide</a>, introduces a board-based puzzle game called Flood Control. We introduce the XNA Content Pipeline, and build a recursive function to determine the state of the game board while playing.<br />
<br />
This article focuses on the following concepts:<br />
<ul class='bbc'><br /><li>Using the Content Pipeline to load textures from disk<br /></li><li>Creating classes to divide code into logical units<br /></li><li>Recursively evaluating the status of the game board to check for scoring chains<br /></li><li>Drawing textures using the <em class='bbc'>SpriteBatch.Draw()</em> method<br /></li><li>Managing simple game states<br /></li></ul><br />
<br />
<br />
<br />
<br />
<br />
<br />
<em class='bbc'>It was just another day at the bottom of the ocean until an explosion in one of</em> <em class='bbc'>the storage bays cracked the protective dome around Deep Sea Research Lab</em> <em class='bbc'>Alpha. Now the entire place is flooding, and the emergency pump system is a chaotic jumble of loose parts.</em><br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/0669_02_01.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Designing a puzzle game</strong></span><br />
The Puzzler has always been a popular game genre. From old standbys like Tetris to modern crazes like Bejeweled, puzzle games are attractive to players because they do not require a long-term time investment or a steep learning curve.<br />
<br />
The game mechanic is the heart of any good puzzle game. This mechanic is usually very simple, with perhaps a few twists to keep the players on their toes.<br />
<br />
In Flood Control, the player will be faced with a board containing 80 pieces of pipe. Some will be straight pipes and some will be curved. The objective of the game is to rotate the pipes to form a continuous line to pump water from the left side of the board to the right side of the board.<br />
<br />
Completing a section of pipe drains water out of the base and scores points for the player, but destroys the pipes used. New pipes will fall into place for the player to begin another row.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - set up the Flood Control project</strong></span><span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
You have now set up a workspace for building Flood Control, and created a couple of folders for organizing game content. You have also imported the sample graphics for the Flood Control game into the project.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Introducing the Content Pipeline</strong></span><br />
The <strong class='bbc'>Flood ControlContent (Content)</strong> project inside <strong class='bbc'>Solution Explorer</strong> is a special kind of project called a Content Project. Items in your game's content project are converted into .XNB resource files by Content Importers and Content Processors.<br />
<br />
If you right-click on one of the image files you just added to the Flood Control project and select <strong class='bbc'>Properties</strong>, you will see that for both the Importer and Processor, the Content Pipeline will use <strong class='bbc'>Texture - XNA Framework</strong>. This means that the Importer will take the file in its native format (.PNG in this case) and convert it to a format that the Processor recognizes as an image. The Processor then converts the image into an <em class='bbc'>.XNB</em> file which is a compressed binary format that XNA's content manager can read directly into a Texture2D object.<br />
<br />
There are Content Importer/Processor pairs for several different types of content—images, audio, video, fonts, 3D models, and shader language effects files. All of these content types get converted to .XNB files which can be used at runtime.<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/0669_02_02.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
In order to see how to use the Content Pipeline at runtime, let's go ahead and write the code to read these textures into memory when the game starts:<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - reading textures into memory</strong></span><ul class='bbcol decimal'><br /><li>Double-click on <em class='bbc'>Game1.cs</em> in <strong class='bbc'>Solution Explorer</strong> to open it or bring it to the front if it is already open.<br /></li><li>In the Class Declarations area of Game1 (right below SpriteBatch spriteBatch;), add:<br />	<pre class='prettyprint'>	<br />Texture2D playingPieces;<br />	Texture2D backgroundScreen;<br />	Texture2D titleScreen;	<br />	</pre><br /></li><li>Add code to load each of the Texture2D objects at the end of <em class='bbc'>LoadContent()</em>:<br />	<pre class='prettyprint'>	<br />playingPieces = Content.Load(@"Textures&#092;Tile_Sheet");<br />	backgroundScreen = <br />		Content.Load(@"Textures&#092;Background");<br />	titleScreen = Content.Load(@"Textures&#092;TitleScreen");	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
In order to load the textures from disk, you need an in-memory object to hold them. These are declared as instances of the <em class='bbc'>Texture2D</em> class.<br />
<br />
A default XNA project sets up the Content instance of the ContentManager class for you automatically. The Content object's <em class='bbc'>Load()</em> method is used to read .XNB files from disk and into the Texture2D instances declared earlier.<br />
<br />
One thing to note here is that the <em class='bbc'>Load()</em> method requires a type identifier, specified in angled brackets (), before the parameter list. Known in C# as a "Generic", many classes and methods support this kind of type specification to allow code to operate on a variety of data types. We will make more extensive use of Generics later when we need to store lists of objects in memory. The <em class='bbc'>Load()</em> method is used not only for textures, but also for all other kinds of content (sounds, 3D models, fonts, etc.) as well. It is important to let the <em class='bbc'>Load()</em> method know what kind of data you are reading so that it knows what kind of object to return.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Sprites and sprite sheets</strong></span><br />
As far as XNA and the SpriteBatch class are concerned, a sprite is a 2D bitmapped image that can be drawn either with or without transparency information to the screen.<br />
<br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'><strong class='bbc'>Sprites vs. Textures</strong><br />
XNA defines a "sprite" as a 2D bitmap that is drawn directly to the screen. While these bitmaps are stored in Texture2D objects, the term "texture" is used when a 2D image is mapped onto a 3D object, providing a visual representation of the surface of the object. In practice, all XNA graphics are actually performed in 3D, with 2D sprites being rendered via special configurations of the XNA rendering engine.</em></p><br />
<br />
The simple form of the <em class='bbc'>SpriteBatch.Draw()</em> call when drawing squares only needs three parameters: a <em class='bbc'>Texture2D</em> to draw, a <em class='bbc'>Rectangle</em> indicating where to draw it, and a <em class='bbc'>Color</em> to specify the tint to overlay onto the sprite.<br />
<br />
Other overloads of the <em class='bbc'>Draw()</em> method, however, also allow you to specify a <em class='bbc'>Rectangle</em> representing the source area within the <em class='bbc'>Texture2D</em> to copy from. If no source <em class='bbc'>Rectangle</em> is specified, the entire <em class='bbc'>Texture2D</em> is copied and resized to fit the destination <em class='bbc'>Rectangle</em>.<br />
<br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'><strong class='bbc'>Overloads</strong><br />
When multiple versions of the same method are declared with either different parameters lists or different return values, each different declaration is called an "overload" of the method. Overloads allow methods to work with different types of data (for example, when setting a position you could accept two separate X and Y coordinates or a Vector2 value), or leave out parameters that can then be assigned default values.</em></p><br />
<br />
By specifying a source <em class='bbc'>Rectangle</em>, however, individual pieces can be pulled from a large image. A bitmap with multiple sprites on it that will be drawn this way is called a "sprite sheet".<br />
<br />
The <em class='bbc'>Tile_Sheet.png</em> file for the Flood Control project is a sprite sheet containing 13 different sprites that will be used to represent the pieces of pipe used in the game. Each image is 40 pixels wide and 40 pixels high, with a one pixel border between each sprite and also around the entire image. When we call <em class='bbc'>SpriteBatch.Draw()</em> we can limit what gets drawn from our texture to one of these 40 by 40 squares, allowing a single texture to hold all of the playing piece images that we need for the game:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/0669_02_03.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
The <em class='bbc'>Tile_Sheet.png</em> file was created with alpha-based transparency. When it is drawn to the screen, the alpha level of each pixel will be used to merge that pixel with any color that already occupies that location on the screen.<br />
<br />
Using this fact, you can create sprites that don't look like they are rectangular. Internally, you will still be drawing rectangles, but visually the image can be of any shape.<br />
<br />
What we really need now to be able to work with the playing pieces is a way to reference an individual piece, knowing not only what to draw to the screen, but what ends of the pipe connect to adjacent squares on the game board.<br />
<br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'><strong class='bbc'>Alpha blending</strong><br />
Each pixel in a sprite can be fully opaque, fully transparent, or partially transparent. Fully opaque pixels are drawn directly, while fully transparent pixels are not drawn at all, leaving whatever has already been drawn to that pixel on the screen unchanged. In 32-bit color mode, each channel of a color (Red, Green, Blue, and Alpha) are represented by 8 bits, meaning that there are 256 different degrees of transparency between fully opaque (255) and fully transparent (0). Partially transparent pixels are combined with the current pixel color at that location to create a mixed color as if the pixels below were being seen through the new color.</em></p><br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Classes used in Flood Control</strong></span><br />
While it would certainly be possible to simply pile all of the game code into the Game1 class, the result would be difficult to read and manage later on. Instead, we need to consider how to logically divide the game into classes that can manage themselves and help to organize our code.<br />
<br />
A good rule of thumb is that a class should represent a single thing or type of thing. If you can say "This object is made up of these other objects" or "This object contains these objects", consider creating classes to represent those relationships.<br />
<br />
The Flood Control game contains a game board made up of 80 pipes. We can abstract these pipes as a class called GamePiece, and provide it with the code it needs to handle rotation and provide the code that will display the piece with a Rectangle that can be used to pull the sprite off the sprite sheet.<br />
<br />
The game board itself can be represented by a <em class='bbc'>GameBoard</em> class, which will handle managing individual GamePiece objects and be responsible for determining which pieces should be filled with water and which ones should be empty.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>The GamePiece class</strong></span><br />
The GamePiece class represents an individual pipe on the game board. One GamePiece has no knowledge of any other game pieces (that is the responsibility of the GameBoard class), but it will need to be able to provide information about the pipe to objects that use the GamePiece class. Our class has the following requirements:<br />
<ul class='bbc'><br /><li>Identify the sides of each piece that contain pipe connectors<br /></li><li>Differentiate between game pieces that are filled with water and that are empty<br /></li><li>Allow game pieces to be updated<br /></li><li>Automatically handle rotation by changing the piece type to the appropriate new piece type<br /></li><li>Given one side of a piece, provide the other sides of the piece in order to facilitate determining where water can flow through the game board<br /></li><li>Provide a Rectangle that will be used when the piece is drawn, to locate the graphic for the piece on the sprite sheet<br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>Identifying a GamePiece</strong></span><br />
While the sprite sheet contains thirteen different images, only twelve of them are actual game pieces (the last one is an empty square). Of the twelve remaining pieces, only six of them are unique pieces. The other six are the water-filled versions of the first six images.<br />
<br />
Each of the game pieces can be identified by which sides of the square contain a connecting pipe. This results in two straight pieces and four pieces with 90 degree bends in them.<br />
<br />
A second value can be tracked to determine if the piece is filled with water or not instead of treating filled pieces as separate types of pieces.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - build a GamePiece class - declarations</strong></span><ul class='bbcol decimal'><br /><li>Switch back to your Visual C# window if you have your image editor open.<br /></li><li>Right-click on <strong class='bbc'>Flood Control</strong> in <strong class='bbc'>Solution Explorer</strong> and select <strong class='bbc'>Add | Class...</strong><br /></li><li>Name the class <strong class='bbc'>GamePiece.cs</strong> and click on <strong class='bbc'>Add</strong>.<br /></li><li>At the top of the GamePiece.cs file, add the following to the using directives already in the class:<br />	<pre class='prettyprint'>	<br />using Microsoft.Xna.Framework.Graphics;<br />	using Microsoft.Xna.Framework;	<br />	</pre><br /></li><li>In the class declarations section, add the following:<br />	<pre class='prettyprint'>	<br />public static string&#91;&#93; PieceTypes = <br />	{ <br />	  "Left,Right", <br />	  "Top,Bottom", <br />	  "Left,Top", <br />	  "Top,Right",<br />	  "Right,Bottom", <br />	  "Bottom,Left",<br />	  "Empty"<br />	};<br />	<br />	public const int PieceHeight = 40;<br />	public const int PieceWidth = 40;<br />	<br />	public const int MaxPlayablePieceIndex = 5;<br />	public const int EmptyPieceIndex = 6;<br />	<br />	private const int textureOffsetX = 1;<br />	private const int textureOffsetY = 1;<br />	private const int texturePaddingX = 1;<br />	private const int texturePaddingY = 1;<br />	<br />	private string pieceType = "";<br />	private string pieceSuffix = "";	<br />	</pre><br /></li><li>Add two properties to retrieve information about the piece:<br />	<pre class='prettyprint'>	<br />public string PieceType<br />	{<br />		get { return pieceType; }<br />	}<br />	<br />	public string Suffix<br />	{<br />		get { return pieceSuffix; }<br />	}	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
You have created a new code file called <em class='bbc'>GamePiece.cs</em> and included the using statements necessary to access the pieces of the XNA Framework that the class will use.<br />
<br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'><strong class='bbc'>Using Directives</strong><br />
Adding the XNA Framework using directives at the top of the class file allows you to access classes like Rectangle and Vector2 without specifying their full assembly names. Without these statements, you would need Microsoft.Xna.Framework.Rectangle in your code every time you reference the type, instead of simply typing Rectangle.</em></p><br />
<br />
In the declarations area, you have added an array called <em class='bbc'>PieceTypes</em> that gives a name to each of the different types of game pieces that will be added to the game board. There are two straight pieces, four angled pieces, and an empty tile with a background image on it, but no pipe. The array is declared as <em class='bbc'>static</em> because all instances of the GamePiece class will share the same array. A <em class='bbc'>static</em> member can be updated at execution time, but all members of the class will see the same changes.<br />
<br />
Then, you have declared two integer constants that specify the height and width of an individual playing piece in pixels, along with two variables that specify the array index of the last piece that can be placed on the board (<em class='bbc'>MaxPlayablePieceIndex</em>) and of the fake "Empty" piece.<br />
<br />
Next are four integers that describe the layout of the texture file you are using. There is a one pixel offset from the left and top edge of the texture (the one pixel border) and a single pixel of padding between each sprite on the sprite sheet.<br />
<br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'><strong class='bbc'>Constants vs. Numeric literals</strong><br />
Why create constants for things like PieceWidth and PieceHeight and have to type them out when you could simply use the number 40 in their place? If you need to go back and resize your pieces later, you only need to change the size in one place instead of hoping that you find each place in the code where you entered 40 and change them all to something else. Even if you do not change the number in the game you are working on, you may reuse the code for something else later and having easily changeable parameters will make the job much easier.</em></p><br />
<br />
There are only two pieces of information that each instance of GamePiece will track about itself—the type of the piece and any suffix associated with the piece. The instance members <em class='bbc'>pieceType</em> and <em class='bbc'>pieceSuffix</em> store these values. We will use the suffix to determine if the pipe that the piece represents is empty or filled with water.<br />
<br />
However, these members are declared as <em class='bbc'>private</em> in order to prevent code outside the class from directly altering the values. To allow them to be read but not written to, we create a pair of properties (<em class='bbc'>pieceType</em> and <em class='bbc'>pieceSuffix</em>) that contain get blocks but no set blocks. This makes these values accessible in a read-only mode to code outside the GamePiece class.<br />
<br />
<br />
<br />
<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Creating a GamePiece</strong></span><br />
The only information we need to create an instance of GamePiece is the piece type and, potentially, the suffix.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - building a GamePiece class: constructors</strong></span><ul class='bbcol decimal'><br /><li>Add two constructors to your GamePiece.cs file after the declarations:<br />	<pre class='prettyprint'>	<br />public GamePiece(string type, string suffix)<br />	{<br />		pieceType=type;<br />		pieceSuffix=suffix;<br />	}<br />	<br />	public GamePiece(string type)<br />	{<br />		pieceType=type;<br />		pieceSuffix="";<br />	}	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
A constructor is run when an instance of the GamePiece class is created. By specifying two constructors, we will allow future code to create a GamePiece by specifying a piece type with or without a suffix. If no suffix is specified, an empty suffix is assumed.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Updating a GamePiece</strong></span><br />
When a GamePiece is updated, you can change the piece type, the suffix, or both.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - GamePiece class methods - part 1 - updating</strong></span><ul class='bbcol decimal'><br /><li>Add the following methods to the GamePiece class:<br />	<pre class='prettyprint'>	<br />public void SetPiece(string type, string suffix)<br />	{<br />		pieceType = type;<br />		pieceSuffix = suffix;<br />	}<br />	<br />	public void SetPiece(string type)<br />	{<br />		  SetPiece(type,"");<br />	}<br />	<br />	public void AddSuffix(string suffix)<br />	{<br />		if (!pieceSuffix.Contains(suffix))<br />			pieceSuffix += suffix;<br />	}<br />	<br />	public void RemoveSuffix(string suffix)<br />	{<br />		pieceSuffix = pieceSuffix.Replace(suffix, "");<br />	}	<br />	</pre><br /></li></ul><br />
The first two methods are overloads with the same name, but different parameter lists. In a manner similar to the GamePiece constructors, code that wishes to update a GamePiece can pass it a piece type, and optionally a suffix.<br />
<br />
Additional methods have been added to modify suffixes without changing the <em class='bbc'>pieceType</em> associated with the piece. The <em class='bbc'>AddSuffix()</em> method first checks to see if the piece already contains the suffix. If it does, nothing happens. If it does not, the suffix value passed to the method is added to the <em class='bbc'>pieceSuffix</em> member variable.<br />
<br />
The <em class='bbc'>RemoveSuffix()</em> method uses the <em class='bbc'>Replace()</em> method of the string class to remove the passed suffix from the <em class='bbc'>pieceSuffix</em> variable.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Rotating pieces</strong></span><br />
The heart of the Flood Control play mechanic is the ability of the player to rotate pieces on the game board to form continuous pipes. In order to accomplish this, we can build a table that, given an existing piece type and a rotation direction, supplies the name of the piece type after rotation. We can then implement this code as a switch statement:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/0669_02_04.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - GamePiece class methods - part 2 - rotation</strong></span><ul class='bbcol decimal'><br /><li>Add the <em class='bbc'>RotatePiece()</em> method to the GamePiece class:<br />	<pre class='prettyprint'>	<br />public void RotatePiece(bool Clockwise)<br />	{<br />		 switch (pieceType)<br />		{<br />			case "Left,Right":<br />				pieceType = "Top,Bottom";<br />				break;<br />			case "Top,Bottom":<br />				pieceType = "Left,Right";<br />				break;<br />			case "Left,Top":<br />				if (Clockwise)<br />					pieceType = "Top,Right";<br />				else<br />					pieceType = "Bottom,Left";<br />				break;<br />			case "Top,Right":<br />				if (Clockwise)<br />					pieceType = "Right,Bottom";<br />				else<br />					pieceType = "Left,Top";<br />				break;<br />			case "Right,Bottom":<br />				if (Clockwise)<br />					pieceType = "Bottom,Left";<br />				else<br />					pieceType = "Top,Right";<br />				break;<br />			case "Bottom,Left":<br />				if (Clockwise)<br />					pieceType = "Left,Top";<br />				else<br />					pieceType = "Right,Bottom";<br />				break;<br />			case "Empty":<br />				break;<br />		}<br />	}	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
The only information the <em class='bbc'>RotatePiece()</em> method needs is a rotation direction. For straight pieces, rotation direction doesn't matter (a left/right piece will always become a top/bottom piece and vice versa).<br />
<br />
For angled pieces, the piece type is updated based on the rotation direction and the diagram above.<br />
<br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'><strong class='bbc'>Why all the strings?</strong><br />
It would certainly be reasonable to create constants that represent the various piece positions instead of fully spelling out things like Bottom,Left as strings. However, because the Flood Control game is not taxing on the system, the additional processing time required for string manipulation will not impact the game negatively and helps clarify how the logic works.</em></p><br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Pipe connectors</strong></span><br />
Our GamePiece class will need to be able to provide information about the connectors it contains (<em class='bbc'>Top, Bottom, Left,</em> and <em class='bbc'>Right</em>) to the rest of the game. Since we have represented the piece types as simple strings, a string comparison will determine what connectors the piece contains.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - GamePiece class methods - part 3 -connection methods</strong></span><ul class='bbcol decimal'><br /><li>Add the <em class='bbc'>GetOtherEnds()</em> method to the GamePiece class:<br />	<pre class='prettyprint'>	<br />public string&#91;&#93; GetOtherEnds(string startingEnd)<br />	{<br />		List opposites = new List();<br />	<br />		foreach (string end in pieceType.Split(','))<br />		{<br />			if (end != startingEnd)<br />				opposites.Add(end);<br />		}<br />		 return opposites.ToArray();<br />	}	<br />	</pre><br /></li><li>Add the <em class='bbc'>HasConnector()</em> method to the <em class='bbc'>GamePiece</em> class:<br />	<pre class='prettyprint'>	<br />public bool HasConnector(string direction)<br />	{<br />		return pieceType.Contains(direction);<br />	}	<br />	</pre><br /></li></ul><br />
The <em class='bbc'>GetOtherEnds()</em> method creates an empty List object for holding the ends we want to return to the calling code. It then uses the Split() method of the string class to get each end listed in the pieceType. For example, the Top,Bottom piece will return an array with two elements. The first element will contain Top and the second will contain Bottom. The comma delimiter will not be returned with either string.<br />
<br />
If the end in question is not the same as the startingEnd parameter that was passed to the method, it is added to the list. After all of the items in the string have been examined, the list is converted to an array and returned to the calling code.<br />
<br />
In the previous example, requesting GetOtherEnds("Top") from a GamePiece with a pieceType value of Top,Bottom will return a string array with a single element containing Bottom.<br />
<br />
We will need this information in a few moments when we have to figure out which pipes are filled with water and which are empty.<br />
<br />
The second function, <em class='bbc'>HasConnector()</em> simply returns "true" if the pieceType string contains the string value passed in as the direction parameter. This will allow code outside the GamePiece class to determine if the piece has a connector facing in any particular direction.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Sprite sheet coordinates</strong></span><br />
Because we set up the <em class='bbc'>PieceTypes</em> array listing the pieces in the same order that they exist on the sprite sheet texture, we can calculate the position of the rectangle to draw from based on the <em class='bbc'>pieceType</em>.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - GamePiece class methods - part 4 - GetSourceRect</strong></span><ul class='bbcol decimal'><br /><li>Add the <em class='bbc'>GetSourceRect(</em>) method to the GamePiece class:<br />	<pre class='prettyprint'>	<br />public Rectangle GetSourceRect()<br />	{<br />		int x = textureOffsetX;<br />		int y = textureOffsetY;<br />	<br />		if (pieceSuffix.Contains("W"))<br />			x += PieceWidth + texturePaddingX;<br />	<br />		y += (Array.IndexOf(PieceTypes, pieceType) * <br />			 (PieceHeight + texturePaddingY));<br />	<br />	<br />		return new Rectangle(x, y, PieceWidth, PieceHeight);<br />	}	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
Initially, the x and y variables are set to the <em class='bbc'>textureOffsets</em> that are listed in the GamePiece class declaration. This means they will both start with a value of one.<br />
<br />
Because the sprite sheet is organized with a single type of pipe on each row, the x coordinate of the <em class='bbc'>Rectangle</em> is the easiest to determine. If the <em class='bbc'>pieceSuffix</em> variable does not contain a W (signifying that the piece is filled with water), the x coordinate will simply remain 1.<br />
<br />
If the <em class='bbc'>pieceSuffix</em> does contain the letter W (indicating the pipe is filled), the width of a piece (40 pixels), along with the padding between the pieces (1 pixel), are added to the x coordinate of the source <em class='bbc'>Rectangle</em>. This shifts the x coordinate from 1 to a value of <strong class='bbc'>1</strong> + <strong class='bbc'>40</strong> + <strong class='bbc'>1</strong>, or <strong class='bbc'>42</strong> which corresponds to the second column of images on the sprite sheet.<br />
<br />
To determine the y coordinate for the source rectangle, <em class='bbc'>Array.IndexOf(PieceTypes, pieceType)</em> is used to locate the <em class='bbc'>pieceType</em> within the <em class='bbc'>PieceTypes</em> array. The index that is returned represents the position of the tile on the sprite sheet (because the array is organized in the same order as the pieces on the image). For example, <em class='bbc'>Left</em>,<em class='bbc'>Right</em> returns zero, while <em class='bbc'>Top</em>,<em class='bbc'>Bottom</em> returns one and <em class='bbc'>Empty</em> returns six.<br />
<br />
The value of this index is multiplied by the height of a game piece plus the padding between pieces. For our sprite sheet, an index of 2 (the <em class='bbc'>Left</em>,<em class='bbc'>Top</em> piece) would be multiplied by <strong class='bbc'>41</strong> (<em class='bbc'>PieceHeight</em> of <strong class='bbc'>40</strong> plus <em class='bbc'>texturePaddingY</em> of <strong class='bbc'>1</strong>) resulting in a value of <strong class='bbc'>82</strong> being added to the y variable.<br />
<br />
Finally, the new <em class='bbc'>Rectangle</em> is returned, comprised of the calculated x and y coordinates and the predefined width and height of a piece:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/0669_02_05.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>The GameBoard class</strong></span><br />
Now that we have a way to represent pieces in memory, the next logical step is to create a way to represent an entire board of playing pieces.<br />
<br />
The game board is a two-dimensional array of GamePiece objects, and we can build in some additional functionality to allow our code to interact with pieces on the game board by their X and Y coordinates.<br />
<br />
The GameBoard class needs to:<br />
<ul class='bbc'><br /><li>Store a GamePiece object for each square on the game board<br /></li><li>Provide methods for code using the GameBoard to update individual pieces by passing calls through to the underlying GamePiece instances<br /></li><li>Randomly assign a piece type to a GamePiece<br /></li><li>Set and clear the "Filled with water" flags on individual GamePieces<br /></li><li>Determine which pipes should be filled with water based on their position and orientation and mark them as filled<br /></li><li>Return lists of potentially scoring water chains to code using the GameBoard<br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - create the GameBoard.cs class</strong></span><ul class='bbcol decimal'><br /><li>As you did to create the GamePiece class, right-click on <strong class='bbc'>Flood Control</strong> in <strong class='bbc'>Solution Explorer</strong> and select <strong class='bbc'>Add | Class...</strong> Name the new class file <strong class='bbc'>GameBoard.cs</strong>.<br /></li><li>Add the using directive for the XNA framework at the top of the file:<br />	<pre class='prettyprint'>	<br />using Microsoft.Xna.Framework;	<br />	</pre><br /></li><li>Add the following declarations to the GameBoard class:<br />	<pre class='prettyprint'>	<br />Random rand = new Random();<br />	<br />	public const int GameBoardWidth = 8;<br />	public const int GameBoardHeight = 10;<br />	<br />	private GamePiece&#91;,&#93; boardSquares = <br />	  new GamePiece&#91;GameBoardWidth, GameBoardHeight&#93;;<br />	<br />	private List WaterTracker = new List();	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
We used the Random class in SquareChase to generate random numbers. Since we will need to randomly generate pieces to add to the game board, we need an instance of Random in the GameBoard class.<br />
<br />
The two constants and the boardSquares array provide the storage mechanism for the GamePiece objects that make up the 8 by 10 piece board.<br />
<br />
Finally, a List of Vector2 objects is declared that we will use to identify scoring pipe combinations. The List class is one of C#'s Generic Collection classes—classes that use the Generic templates (angle brackets) we first saw when loading a texture for SquareChase. Each of the Collection classes can be used to store multiple items of the same type, with different methods to access the entries in the collection. We will use several of the Collection classes in our projects. The List class is much like an array, except that we can add any number of values at runtime, and remove values in the List if necessary.<br />
<br />
A <em class='bbc'>Vector2</em> is a structure defined by the XNA Framework that holds two floating point values, X and Y. Together the two values represent a vector pointing in any direction from an imaginary origin (0, 0) point. We will use <em class='bbc'>Vector2</em> structures to represent the locations on our game board in Flood Control, placing the origin in the upper left corner of the board.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Creating the game board</strong></span><br />
If we were to try to use any of the elements in the <em class='bbc'>boardSquares</em> array, at this point, we would get a Null Reference exception because none of the GamePiece objects in the array have actually been created yet.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - initialize the game board</strong></span><ul class='bbcol decimal'><br /><li>Add a constructor to the GameBoard class:<br />	<pre class='prettyprint'>	<br />public GameBoard()<br />	{<br />	  ClearBoard();<br />	}	<br />	</pre><br /></li><li>Add the <em class='bbc'>ClearBoard()</em> helper method to the GameBoard class:<br />	<pre class='prettyprint'>	<br />public void ClearBoard()<br />	{<br />		for (int x = 0; x		 for (int y = 0; y			 boardSquares&#91;x, y&#93; = new GamePiece("Empty");<br />	}	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
When a new instance of the <em class='bbc'>GameBoard</em> class is created, the constructor calls the <em class='bbc'>ClearBoard()</em> helper method, which simply creates 80 empty game pieces and assigns them to each element in the array.<br />
<br />
<p class='bbc_indent' style='margin-left: 40px;'><em class='bbc'><strong class='bbc'>Helper methods</strong><br />
Why not simply put the two for loops that clear the board into the GameBoard constructor? Splitting the work into methods that accomplish a single purpose greatly helps to keep your code both readable and maintainable. Additionally, by splitting ClearBoard() out as its own method we can call it separately from the constructor. When we add increasing difficulty levels, we  make use of this call when a new level starts.</em></p><br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Updating GamePieces</strong></span><br />
The <em class='bbc'>boardSquares</em> array in the GameBoard class is declared as a private member, meaning that the code that uses the GameBoard will not have direct access to the pieces contained on the board.<br />
<br />
In order for code in our Game1 class to interact with a GamePiece, we will need to create public methods in the GameBoard class that expose the pieces in boardSquares.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - manipulating the game board</strong></span><ul class='bbcol decimal'><br /><li>Add public methods to the GameBoard class to interact with GamePiece:<br />	<pre class='prettyprint'>	<br />public void RotatePiece(int x, int y, bool clockwise)<br />	{<br />		boardSquares&#91;x, y&#93;.RotatePiece(clockwise);<br />	}<br />	<br />	public Rectangle GetSourceRect(int x, int y)<br />	{<br />		return boardSquares&#91;x, y&#93;.GetSourceRect();<br />	}<br />	<br />	public string GetSquare(int x, int y)<br />	{<br />		return boardSquares&#91;x, y&#93;.PieceType;<br />	}<br />	<br />	public void SetSquare(int x, int y, string pieceName)<br />	{<br />		boardSquares&#91;x, y&#93;.SetPiece(pieceName);<br />	}<br />	<br />	public bool HasConnector(int x, int y, string direction)<br />	{<br />		return boardSquares&#91;x, y&#93;.HasConnector(direction); <br />	}<br />	<br />	public void RandomPiece(int x, int y)<br />	{<br />	  boardSquares&#91;x, y&#93;.SetPiece(GamePiece.PieceTypes&#91;rand.Next(0, <br />		   GamePiece.MaxPlayablePieceIndex+1)&#93;);<br />	}	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
<em class='bbc'>RotatePiece()</em>, <em class='bbc'>GetSourceRect()</em>, <em class='bbc'>GetSquare()</em>, <em class='bbc'>SetSquare()</em>, and <em class='bbc'>HasConnector()</em> methods simply locate the appropriate <em class='bbc'>GamePiece</em> within the <em class='bbc'>boardSquares</em> array and pass on the function request to the piece.<br />
<br />
The <em class='bbc'>RandomPiece()</em> method uses the rand object to get a random value from the <em class='bbc'>PieceTypes</em> array and assign it to a <em class='bbc'>GamePiece</em>. It is important to remember that with the Random.Next() method overload used here, the second parameter is non-inclusive. In order to generate a random number from 0 through 5, the second parameter needs to be 6.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Filling in the gaps</strong></span><br />
Whenever the player completes a scoring chain, the pieces in that chain are removed from the board. Any pieces above them fall down into the vacated spots and new pieces are generated.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - filling in the gaps</strong></span><ul class='bbcol decimal'><br /><li>Add the <em class='bbc'>FillFromAbove()</em> method to the GameBoard class.<br />	<pre class='prettyprint'>	<br />public void FillFromAbove(int x, int y)<br />	{<br />		int rowLookup = y - 1;<br />	<br />		while (rowLookup &gt;= 0)<br />		{<br />			if (GetSquare(x, rowLookup) != "Empty")<br />			{<br />				SetSquare(x, y,<br />				  GetSquare(x, rowLookup));<br />				SetSquare(x, rowLookup, "Empty");<br />				rowLookup = -1;<br />			}<br />			rowLookup--;<br />		}<br />	}	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
Given a square to fill, <em class='bbc'>FillFromAbove()</em> looks at the piece directly above to see if it is marked as Empty. If it is, the method will subtract one from rowLookup and start over until it reaches the top of the board. If no non-empty pieces are found when the top of the board is reached, the method does nothing and exits.<br />
<br />
When a non-empty piece is found, it is copied to the destination square, and the copied piece is changed to an empty piece. The <em class='bbc'>rowLookup</em> variable is set to -1 to ensure that the loop does not continue to run.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Generating new pieces</strong></span><br />
We can create a single method that will fill any empty spaces on the game board, and use it when the game begins and when pieces are removed from the board after scoring.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - generating new pieces</strong></span><ul class='bbcol decimal'><br /><li>Add the <em class='bbc'>GenerateNewPieces()</em> method to the GameBoard class:<br />	<pre class='prettyprint'>	<br />public void GenerateNewPieces(bool dropSquares)<br />	{<br />	<br />		if (dropSquares)<br />		{<br />			for (int x = 0; x		 {<br />				for (int y = GameBoard.GameBoardHeight - 1; y &gt;= 0; y--)<br />				{<br />					if (GetSquare(x, y) == "Empty")<br />					{<br />						FillFromAbove(x, y);<br />					}<br />				}<br />			}<br />		}<br />	<br />		for (int y = 0; y		 for (int x = 0; x		 {<br />				if (GetSquare(x, y) == "Empty")<br />				{<br />					RandomPiece(x, y);<br />				}<br />			}<br />	}	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
When <em class='bbc'>GenerateNewPieces()</em> is called with "true" passed as dropSquares, the looping logic processes one column at a time from the bottom up. When it finds an empty square it calls <em class='bbc'>FillFromAbove()</em> to pull a filled square from above into that location.<br />
<br />
The reason the processing order is important here is that, by filling a lower square from a higher position, that higher position will become empty. It, in turn, will need to be filled from above.<br />
<br />
After the holes are filled (or if <em class='bbc'>dropSquares</em> is set to false) <em class='bbc'>GenerateNewPieces()</em> examines each square in <em class='bbc'>boardSquares</em> and asks it to generate random pieces for each square that contains an empty piece.<br />
<br />
<br />
<br />
<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Water filled pipes</strong></span><br />
Whether or not a pipe is filled with water is managed separately from its orientation. Rotating a single pipe could change the water-filled status of any number of other pipes without changing their rotation.<br />
<br />
Instead of filling and emptying individual pipes, however, it is easier to empty all of the pipes and then refill the pipes that need to be marked as having water in them.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - water in the pipes</strong></span><ul class='bbcol decimal'><br /><li>Add a method to the GameBoard class to clear the water marker from all pieces:<br />	<pre class='prettyprint'>	<br />public void ResetWater()<br />	{<br />		for (int y = 0; y		 for (int x = 0; x			 boardSquares&#91;x,y&#93;.RemoveSuffix("W");<br />	}	<br />	</pre><br /></li><li>Add a method to the GameBoard class to fill an individual piece with water:<br />	<pre class='prettyprint'>	<br />public void FillPiece(int X, int Y)<br />	{<br />		boardSquares&#91;X,Y&#93;.AddSuffix("W");<br />	}	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
The <em class='bbc'>ResetWater()</em> method simply loops through each item in the <em class='bbc'>boardSquares</em> array and removes the W suffix from the GamePiece. Similarly, to fill a piece with water, the <em class='bbc'>FillPiece()</em> method adds the W suffix to the GamePiece. Recall that by having a W suffix, the <em class='bbc'>GetSourceRect()</em> method of GamePiece shifts the source rectangle one tile to the right on the sprite sheet, returning the image for a pipe filled with water instead of an empty pipe.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Propagating water</strong></span><br />
Now that we can fill individual pipes with water, we can write the logic to determine which pipes should be filled depending on their orientation.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - making the connection</strong></span><ul class='bbcol decimal'><br /><li>Add the <em class='bbc'>PropagateWater()</em> method to the GameBoard class:<br />	<pre class='prettyprint'>	<br />public void PropagateWater(int x, int y, string fromDirection)<br />	{<br />		if ((y &gt;= 0) && (y		 (x &gt;= 0) && (x	 {<br />			if (boardSquares&#91;x,y&#93;.HasConnector(fromDirection) &&<br />				!boardSquares&#91;x,y&#93;.Suffix.Contains("W"))<br />			{<br />				FillPiece(x, y);<br />				WaterTracker.Add(new Vector2(x, y));<br />				foreach (string end in<br />						 boardSquares&#91;x,y&#93;.GetOtherEnds(fromDirection))<br />					switch (end)<br />						  {<br />						case "Left": PropagateWater(x - 1, y, "Right");<br />							break;<br />						case "Right": PropagateWater(x + 1, y, "Left");<br />							break;<br />						case "Top": PropagateWater(x, y - 1, "Bottom");<br />							break;<br />						case "Bottom": PropagateWater(x, y + 1, "Top");<br />							break;<br />					}<br />			}<br />		}<br />	}	<br />	</pre><br /></li><li>Add the <em class='bbc'>GetWaterChain()</em> method to the GameBoard class:<br />	<pre class='prettyprint'>	<br />public List GetWaterChain(int y)<br />	{<br />		WaterTracker.Clear();<br />		PropagateWater(0, y, "Left");<br />		return WaterTracker;<br />	}	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
Together, <em class='bbc'>GetWaterChain()</em> and <em class='bbc'>PropagateWater()</em> are the keys to the entire Flood Control game, so understanding how they work is vital. When the game code wants to know if the player has completed a scoring row, it will call the <em class='bbc'>GetWaterChain()</em> method once for each row on the game board:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/0669_02_06.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
The WaterTracker list is cleared and <em class='bbc'>GetWaterChain()</em> calls <em class='bbc'>PropagateWater()</em> for the first square in the row, indicating that the water is coming from the <strong class='bbc'>Left</strong> direction.<br />
<br />
The <em class='bbc'>PropagateWater()</em> method checks to make sure that the <strong class='bbc'>x</strong> and <strong class='bbc'>y</strong> coordinates passed to it exist within the board and, if they do, checks to see if the piece at that location has a connector matching the fromDirection parameter and that the piece is not already filled with water. If all of these conditions are met, that piece gets filled with water and added to the WaterTracker list.<br />
<br />
Finally, <em class='bbc'>PropagateWater()</em> gets a list of all other directions that the piece contains (in other words, all directions the piece contains that do not match fromDirection). For each of these directions <em class='bbc'>PropagateWater()</em> recursively calls itself, passing in the new <strong class='bbc'>x</strong> and <strong class='bbc'>y</strong> location as well as the direction the water is coming from.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Building the game</strong></span><br />
We now have the component classes we need to build the Flood Control game, so it is time to bring the pieces together in the Game1 class.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Declarations</strong></span><br />
We only need a handful of game-wide declarations to manage things like the game board, the player's score, and the game state.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - Game1 declarations</strong></span><ul class='bbcol decimal'><br /><li>Double click on the Game1.cs file in <strong class='bbc'>Solution Explorer</strong> to reactivate the <strong class='bbc'>Game1.cs</strong> code file wind&#111;w.<br /></li><li>Add the following declarations to the Game1 class member declaration area:<br />	<pre class='prettyprint'>	<br />GameBoard gameBoard;<br />	<br />	Vector2 gameBoardDisplayOrigin = new Vector2(70, 89);<br />	<br />	int playerScore = 0;<br />	<br />	enum GameStates { TitleScreen, Playing };<br />	GameStates gameState = GameStates.TitleScreen;<br />	<br />	Rectangle EmptyPiece = new Rectangle(1, 247, 40, 40);<br />	<br />	const float MinTimeSinceLastInput = 0.25f;<br />	float timeSinceLastInput = 0.0f;	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
The <em class='bbc'>gameBoard</em> instance of GameBoard will hold all of the playing pieces, while the <em class='bbc'>gameBoardDisplayOrigin</em> vector points to where on the screen the board will be drawn. Using a vector like this makes it easy to move the board in the event that you wish to change the layout of your game screen.<br />
<br />
As we did in SquareChase, we store the player's score and will display it in the window title bar.<br />
<br />
In order to implement a simple game state mechanism, we define two game states. When in the <em class='bbc'>TitleScreen</em> state, the game's title image will be displayed and the game will wait until the user presses the <em class='bbc'>Space bar</em> to start the game. The state will then switch to <em class='bbc'>Playing</em>, which will display the game board and allow the user to play.<br />
<br />
If you look at the sprite sheet for the game, the pipe images themselves do not cover the entire 40x40 pixel area of a game square. In order to provide a background, an empty tile image will be drawn in each square first. The <em class='bbc'>EmptyPiece Rectangle</em> is a convenient pointer to where the empty background is located on the sprite sheet.<br />
<br />
Just as we used an accumulating timer in SquareChase to determine how long to leave a square in place before moving it to a new location, we will use the same timing mechanism to make sure that a single click by the user does not send a game piece spinning unpredictably. Remember that the <em class='bbc'>Update()</em> method will be executing up to 60 times each second, so slowing the pace of user input is necessary to make the game respond in a way that feels natural.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Initialization</strong></span><br />
Before we can use the gameBoard instance, it needs to be initialized. We will also need to enable the mouse cursor.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - updating the Initialize() method</strong></span><ul class='bbcol decimal'><br /><li>Update the <em class='bbc'>Initialize()</em> method to include the following:<br />	<pre class='prettyprint'>	<br />this.IsMouseVisible = true;<br />	graphics.PreferredBackBufferWidth = 800;<br />	graphics.PreferredBackBufferHeight = 600;<br />	graphics.ApplyChanges();<br />	gameBoard = new GameBoard();	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
After making the mouse cursor visible, we set the size of the <em class='bbc'>BackBuffer</em> to <em class='bbc'>800</em> by <em class='bbc'>600</em> pixels. On Windows, this will size the game window to <em class='bbc'>800</em> by <em class='bbc'>600</em> pixels as well.<br />
<br />
The constructor for the GameBoard class calls the <em class='bbc'>ClearBoard()</em> member, so each of the pieces on the <em class='bbc'>gameBoard</em> instance will be set to <em class='bbc'>Empty</em>.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>The Draw() method - the title screen</strong></span><br />
In the declarations section, we established two possible game states. The first (and default) state is <em class='bbc'>GameStates.TitleScreen</em>, indicating that the game should not be processing actual game play, but should instead be displaying the game's logo and waiting for the user to begin the game.<br />
<br />
Time for action - drawing the screen - the title screen<br />
<ul class='bbcol decimal'><br /><li>Modify the <em class='bbc'>Draw()</em> method of Game1 to include the code necessary to draw the game's title screen after <em class='bbc'>GraphicsDevice.Clear(Color.CornflowerBlue)</em>;<br />	<pre class='prettyprint'>	<br />if (gameState == GameStates.TitleScreen)<br />	{<br />		spriteBatch.Begin();<br />		spriteBatch.Draw(titleScreen,<br />			new Rectangle(0, 0,<br />				this.wind&#111;w.ClientBounds.Width,<br />				this.wind&#111;w.ClientBounds.Height),<br />			Color.White);<br />		spriteBatch.End();<br />	}	<br />	</pre><br /></li><li>Run the game and verify that the title screen is displayed. You will not be able to start the game however, as we haven't written the <em class='bbc'>Update()</em> method yet.<br /></li><li>Stop the game by pressing <em class='bbc'>Alt</em> + <em class='bbc'>F4</em>.<br /></li></ul><br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/0669_02_07.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
The title screen is drawn with a single call to the <em class='bbc'>Draw()</em> method of the <em class='bbc'>spriteBatch</em> object. Since the title screen will cover the entire display, a rectangle is created that is equal to the width and height of the game wind&#111;w.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>The Draw() method - the play screen</strong></span><br />
Finally, we are ready to display the playing pieces on the screen. We will accomplish this by using a simple loop to display all of the playing pieces in the <em class='bbc'>gameBoard</em> object.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - drawing the screen - the play screen</strong></span><ul class='bbcol decimal'><br /><li>Update the <em class='bbc'>Draw()</em> method of the Game1 class to add the code to draw the game board after the code that draws the title screen:<br />	<pre class='prettyprint'>	<br />if (gameState == GameStates.Playing)<br />	{<br />		spriteBatch.Begin();<br />	<br />		spriteBatch.Draw(backgroundScreen,<br />			new Rectangle(0, 0,<br />				this.wind&#111;w.ClientBounds.Width,<br />				this.wind&#111;w.ClientBounds.Height),<br />			Color.White);<br />	<br />		for (int x = 0; x		 for (int y = 0; y		 {<br />				int pixelX = (int)gameBoardDisplayOrigin.X + <br />					(x * GamePiece.PieceWidth);<br />				int pixelY = (int)gameBoardDisplayOrigin.Y + <br />					(y * GamePiece.PieceHeight);<br />	<br />				spriteBatch.Draw(<br />					playingPieces,<br />					new Rectangle(<br />					  pixelX, <br />					  pixelY, <br />					  GamePiece.PieceWidth, <br />					  GamePiece.PieceHeight),<br />					EmptyPiece,<br />					Color.White);<br />	<br />				spriteBatch.Draw(<br />					playingPieces, new Rectangle(<br />						pixelX, <br />						pixelY, <br />						GamePiece.PieceWidth, <br />						GamePiece.PieceHeight),<br />					gameBoard.GetSourceRect(x, y),<br />					Color.White);<br />			}<br />	<br />		this.wind&#111;w.Title = playerScore.ToString();<br />	<br />		spriteBatch.End();<br />	}	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
As you can see, the code to draw the game board begins exactly like the code to draw the title screen. Since we are using a background image that takes up the full screen, we draw it exactly the same way as the title screen.<br />
<br />
Next, we simply loop through gameBoard to draw the squares. The <em class='bbc'>pixelX</em> and <em class='bbc'>pixelY</em> variables are calculated to determine where on the screen each of the game pieces will be drawn. Since both x and y begin at 0, the <em class='bbc'>(x * GamePiece.PieceWidth)</em> and <em class='bbc'>(y * GamePiece.PieceHeight)</em> will also be equal to zero, resulting in the first square being drawn at the location specified by the <em class='bbc'>gameBoardDisplayOrigin</em> vector.<br />
<br />
As x increments, each new piece is drawn 40 pixels further to the right than the previous piece. After a row has been completed, the y value increments, and a new row is started 40 pixels below the previous row.<br />
<br />
The first <em class='bbc'>spriteBatch.Draw()</em> call uses Rectangle(<em class='bbc'>pixelX</em>, <em class='bbc'>pixelY</em>, <em class='bbc'>GamePiece.PieceWidth</em>, <em class='bbc'>GamePiece.PieceHeight</em>) as the destination rectangle and <em class='bbc'>EmptyPiece</em> as the source rectangle. Recall that we added this <em class='bbc'>Rectangle</em> to our declarations area as a shortcut to the location of the empty piece on the sprite sheet.<br />
<br />
The second <em class='bbc'>spriteBatch.Draw()</em> call uses the same destination rectangle, overlaying the playing piece image onto the empty piece that was just drawn. It asks the <em class='bbc'>gameBoard</em> to provide the source rectangle for the piece it needs to draw.<br />
<br />
The player's score is displayed in the window title bar, and <em class='bbc'>spriteBatch.End()</em> is called to finish up the <em class='bbc'>Draw()</em> method.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Keeping score</strong></span><br />
Longer chains of filled water pipes score the player more points. However, if we were to simply assign a single point to each piece in the pipe chain, there would be no scoring advantage to making longer chains versus quickly making shorter chains.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - scores and scoring chains</strong></span><ul class='bbcol decimal'><br /><li>Add a method to the Game1 class to calculate a score based on the number of pipes used:<br />	<pre class='prettyprint'>	<br />private int DetermineScore(int SquareCount)<br />	{<br />		return (int)((Math.Pow((SquareCount/5), 2) + SquareCount)*10);<br />	}	<br />	</pre><br /></li><li>Add a method to evaluate a chain to determine if it scores and process it:<br />	<pre class='prettyprint'>	<br />private void CheckScoringChain(List WaterChain)<br />	{<br />	<br />		if (WaterChain.Count &gt; 0)<br />		{<br />			Vector2 LastPipe = WaterChain&#91;WaterChain.Count - 1&#93;;<br />	<br />			if (LastPipe.X == GameBoard.GameBoardWidth - 1)<br />			{<br />				if (gameBoard.HasConnector(<br />					(int)LastPipe.X, (int)LastPipe.Y, "Right"))<br />				{<br />					playerScore += DetermineScore(WaterChain.Count);<br />	<br />					foreach (Vector2 ScoringSquare in WaterChain)<br />					{<br />						gameBoard.SetSquare((int)ScoringSquare.X,<br />							(int)ScoringSquare.Y, "Empty");<br />					}<br />				}<br />			}<br />		}<br />	}	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
<em class='bbc'>DetermineScore()</em> accepts the number of squares in a scoring chain and returns a score value for that chain. The number of squares in the chain is divided by 5, and that number is squared. The initial number of squares is added to the result, and the final amount is multiplied by 10.<br />
<br />
<pre class='prettyprint'><br />Score = (((Squares / 5) ^ 2) + Squares) * 10<br /><br /></pre><br />
For example, a minimum scoring chain would be 8 squares (forming a straight line across the board). This would result in 1 squared plus 8 times 10, or 90 points. If a chain had 18 squares the result would be 3 squared plus 18 times 10, or 270 points. This makes longer scoring chains (especially increments of five squares) award much higher scores than a series of shorter chains.<br />
<br />
The <em class='bbc'>CheckScoringRow()</em> method makes sure that there are entries in the <em class='bbc'>WaterChain</em> list, and then examines the last piece in the chain and checks to see if it has an X value of 7 (the right-most column on the board). If it does, the <em class='bbc'>HasConnector()</em> method is checked to see if the last pipe has a connector to the right, indicating that it completes a chain across the board.<br />
<br />
After updating <em class='bbc'>playerScore</em> for the scoring row, <em class='bbc'>CheckScoringRow()</em> sets all of the pieces in the scoring row to Empty. They will be refilled by a subsequent call to the <em class='bbc'>GenerateNewPieces()</em> method.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Input handling</strong></span><br />
The player interacts with Flood Control using the mouse. For readability reasons, we will create a helper method that deals with mouse input and call it when appropriate from the <em class='bbc'>Update()</em> method.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - handling mouse input</strong></span><ul class='bbcol decimal'><br /><li>Add the <em class='bbc'>HandleMouseInput()</em> helper method to the Game1 class:<br />	<pre class='prettyprint'>	<br />private void HandleMouseInput(MouseState mouseState)<br />	{<br />	<br />		int x = ((mouseState.X -<br />			(int)gameBoardDisplayOrigin.X) / GamePiece.PieceWidth);<br />	<br />		int y = ((mouseState.Y -<br />			(int)gameBoardDisplayOrigin.Y) / GamePiece.PieceHeight);<br />	<br />		if ((x &gt;= 0) && (x	   (y &gt;= 0) && (y	 {<br />			if (mouseState.LeftButton == ButtonState.Pressed)<br />			{<br />				gameBoard.RotatePiece(x, y, false);<br />				timeSinceLastInput = 0.0f;<br />			}<br />	<br />			if (mouseState.RightButton == ButtonState.Pressed)<br />			{<br />				gameBoard.RotatePiece(x, y, true);<br />				timeSinceLastInput = 0.0f;<br />			}<br />		}<br />	}	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
The MouseState class reports the X and Y position of the mouse relative to the upper left corner of the wind&#111;w. What we really need to know is what square on the game board the mouse was over.<br />
<br />
We calculate this by taking the mouse position and subtracting the <em class='bbc'>gameBoardDisplayOrigin</em> from it and then dividing the remaining number by the size of a game board square.<br />
<br />
If the resulting X and Y locations fall within the game board, the left and right mouse buttons are checked. If the left button is pressed, the piece is rotated counterclockwise. The right button rotates the piece clockwise. In either case, the input delay timer is reset to <em class='bbc'>0.0f</em> since input was just processed.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Letting the player play!</strong></span><br />
Only one more section to go and you can begin playing Flood Control. We need to code the <em class='bbc'>Update()</em> method to tie together all of the game logic we have created so far.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Time for action - letting the player play</strong></span><ul class='bbcol decimal'><br /><li>Modify the <em class='bbc'>Update()</em> method of <em class='bbc'>Game1.cs</em> by adding the following before the call to <em class='bbc'>base.Update(gameTime)</em>:<br />	<pre class='prettyprint'>	<br />switch (gameState)<br />	{<br />		case GameStates.TitleScreen:<br />			if (Keyboard.GetState().IsKeyDown(Keys.Space))<br />			{<br />				gameBoard.ClearBoard();<br />				gameBoard.GenerateNewPieces(false);<br />				playerScore = 0;<br />				gameState = GameStates.Playing;<br />			}<br />			break;<br />	<br />		case GameStates.Playing:<br />			timeSinceLastInput +=<br />			  (float)gameTime.ElapsedGameTime.TotalSeconds;<br />	<br />			if (timeSinceLastInput &gt;= MinTimeSinceLastInput)<br />			{<br />				HandleMouseInput(Mouse.GetState());<br />			}<br />	<br />			gameBoard.ResetWater();<br />	<br />			for (int y = 0; y		 {<br />				CheckScoringChain(gameBoard.GetWaterChain(y));		<br />			}<br />	<br />			gameBoard.GenerateNewPieces(true);<br />	<br />			break;<br />	}	<br />	</pre><br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>What just happened?</strong></span><br />
The <em class='bbc'>Update()</em> method performs two different functions, depending on the current gameState value. If the game is in <em class='bbc'>TitleScreen</em> state, <em class='bbc'>Update()</em> examines the keyboard, waiting for the <em class='bbc'>Space bar</em> to be pressed. When it is, <em class='bbc'>Update()</em> clears the <em class='bbc'>gameBoard</em>, generates a new set of pieces, resets the player's score, and changes <em class='bbc'>gameState</em> to <em class='bbc'>Playing</em>.<br />
<br />
While in the <em class='bbc'>Playing</em> state, <em class='bbc'>Update()</em> accumulates time in <em class='bbc'>timeSinceLastInput</em> in order to pace the game play properly. If enough time has passed, the <em class='bbc'>HandleMouseInput()</em> method is called to allow the player to rotate game pieces.<br />
<br />
<em class='bbc'>Update()</em> then calls <em class='bbc'>ResetWater()</em> to clear the water flags for all pieces on the game board. This is followed by a loop that processes each row, starting at the top and working downward, using <em class='bbc'>CheckScoringChain()</em> and <em class='bbc'>GetWaterChain()</em> to "fill" any pieces that should have water in them and check the results of each row for completed chains.<br />
<br />
Finally, <em class='bbc'>GenerateNewPieces()</em> is called with the "true" parameter for <em class='bbc'>dropSquares</em>, which will cause <em class='bbc'>GenerateNewPieces()</em> to fill the empty holes from the squares above, and then generate new pipes to replace the empty squares.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Play the game</strong></span><br />
You now have all of the components assembled, and can run Flood Control and play!<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Summary</strong></span><br />
You now have a working Flood Control game. In this article we have looked at:<br />
<ul class='bbc'><br /><li>Adding content objects to your project and loading them into textures at runtime using an instance of the ContentManager class<br /></li><li>Dividing the code into classes that represent objects in the game<br /></li><li>Building a recursive method<br /></li><li>Use the <em class='bbc'>SpriteBatch.Draw()</em> method to display images<br /></li><li>Divide the <em class='bbc'>Update()</em> and <em class='bbc'>Draw()</em> code into different units based on the current game state<br /></li></ul><br />
In the next article, we will spruce up the Flood Control game, adding animation by modifying the parameters of the <em class='bbc'>SpriteBatch.Draw()</em> method and creating text effects in order to make the game visually more appealing.]]></description>
		<pubDate>Wed, 01 Feb 2012 17:51:05 +0000</pubDate>
		<guid isPermaLink="false">f1b9528d5fb5c272d2f05a5b82611b3c</guid>
	</item>
	<item>
		<title>Getting Started with XNA Game Studio Development</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/getting-started-with-xna-game-studio-development-r2848</link>
		<description></description>
		<pubDate>Wed, 11 Jan 2012 12:25:22 +0000</pubDate>
		<guid isPermaLink="false">b8c4464e7ee7dc326d7807a8549e449f</guid>
	</item>
	<item>
		<title>XNA 4.0 Beginner Tutorials - Breakout</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/xna-40-beginner-tutorials-breakout-r2842</link>
		<description></description>
		<pubDate>Tue, 10 Jan 2012 18:05:33 +0000</pubDate>
		<guid isPermaLink="false">3521a3a5bcfea0fe1189f8bc13af1f99</guid>
	</item>
	<item>
		<title>DigitalRune 3D .NET and XNA Game Engine</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/digitalrune-3d-net-and-xna-game-engine-r2836</link>
		<description></description>
		<pubDate>Thu, 29 Dec 2011 05:48:03 +0000</pubDate>
		<guid isPermaLink="false">4b4984066015df12cfc4e8f6d60b7147</guid>
	</item>
	<item>
		<title>App Hub - content catalog</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/app-hub-content-catalog-r2835</link>
		<description></description>
		<pubDate>Thu, 29 Dec 2011 04:41:14 +0000</pubDate>
		<guid isPermaLink="false">dbf138511ed1d9278bde43cc0000e49a</guid>
	</item>
	<item>
		<title>Microsoft XNA Game Studio 3.0 Unleashed</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/microsoft-xna-game-studio-30-unleashed-r2641</link>
		<description><![CDATA[<br />
<strong class='bbc'>Creating the Tunnel Vision Game</strong><br />
 The game is set in outer space. The tunnel to our space station is being attacked, so we need to defend the tunnel and not let our enemies breach the opening. We have missiles that we can fire. Fortunately, the enemies do not have any. They simply attack in swarms, which means we need to take swift action to destroy them. <br />
<strong class='bbc'>Creating the Game States</strong><br />
 To get started, we need to make a copy of our GameStateDemo from Chapter 17, “Finite State Machines and Game State Management.” We want to use the latest XELibrary from the last chapter, and we need to add the project to our solution because we will be making a modification to it a little later. Rename Game1.cs to TunnelVision.cs. We can also change the name of this class and the namespace to TunnelVision. Figure 22.1 shows how we can rename our namespace through the IDE. This will modify all our source files for us. We also need to rename our Game1 class to TunnelVision.<br />
<br />
  <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/xnaGS3Book/22fig01.jpg' alt='Posted Image' class='bbc_img' /></span><br />
FIGURE 22.1 Visual Studio allows renaming the namespace through the IDE.<br />
<br />
  <br />
<strong class='bbc'>Adding a Skybox to Our Game</strong><br />
 Let’s add a skybox to our world. Find the skybox.tga file and add it to the Skyboxes folder in the Content project. We need to add a skybox content processor to our Content project as well as select SkyboxProcessor as the content processor for the skybox texture. Then we can add the following private member field to our game:  private Skybox skybox;  Next, we can load the skybox in our LoadContent method:  skybox = Content.Load(@”Skyboxes&#092;skybox”);  To finish up our skybox, we only need to draw it. We can add the following statement to the Draw method:  skybox.Draw(Camera.View, Camera.Projection, Matrix.CreateScale(1000));  <br />
<strong class='bbc'>Compiling the Game</strong><br />
 While we are in our Draw method, we can remove the Begin and End methods for SpriteBatch because each game component will need to call its own. We need to leave the base.Draw method, of course. Let’s add a camera to our game. We are going to change this camera to one that is more suitable for our game, but for now we can just reference the normal Camera class. We need to change our private member field camera to the public member field Camera:<br />
<br />
  public Camera Camera;  We utilized the camera variable in the constructor (const). The variable will need to be changed from camera to Camera there as well. To get our game to run successfully, we need to modify our game states that utilize the sprite batch to call Begin and End because we removed it from the main TunnelVision game class. Once those methods are modified, we can compile and run our game. <br />
<strong class='bbc'>Creating the Game Logic</strong><br />
 After we successfully compile and run our game, we can start working on our game logic. Fortunately, we have the framework in place where we can easily put in our game code. We will first work on our game play by modifying the playing state code file (/GameStates/PlayingState.cs). We need to remove SpriteFont from our member fields and add in the following fields:<br />
<br />
  private MissileManager missileManager; private EnemyManager enemyManager; private List Levels; private int currentLevel; private float totalCreatedEnemies; public int TotalCollisions; private BoundingSphere playerSphere;  We are going to manage our enemies and our missiles, so we have set up some variables for those. We also created a list to store our levels. Before we dig into our playing state any further, we can build out these classes. The code for our Level class, which can be added as Level.cs to our main game folder, is as follows:  public class Level {    public int Missiles;    public int Enemies;    public int Time;    public float EnemySpeed;        public Level(int missiles, int enemies, int time, float enemySpeed)    {   	Missiles = missiles;   	Enemies = enemies;   	Time = time + 1;   	EnemySpeed = enemySpeed;    } }  The class is pretty straightforward—we are providing a way to store the number of missiles that we are allowing on the screen at one time. One of the challenges of the game is to not expend too many bullets at once. The next challenge is how many enemies this level needs to generate before the level is over. We also have a timer that we will be using to award bonus points if all the enemies are killed before it runs out. Finally, we store the speed at which the enemy is moving in this level. The enemy and missile managers do as their names imply and manage the missiles and the enemies, respectively. These objects share a lot of the same properties. Therefore, we are going to introduce a SceneObject and then have a PhysicalObject that inherits from our SceneObject. Although everything in this game will really be a physical object, we could have a trigger that, if reached, kicks off some animation; this would need to be a scene object, not a physical object. You’ll see that this makes more sense as we look at the code, starting with the SceneObject:<br />
<br />
  public abstract class SceneObject {    public Matrix World;    public BoundingSphere BoundingSphere; }  This is a very simplistic abstract class that stores our world matrix for the object as well as a bounding sphere. This allows us to place the object in the world and assign it a sphere so that if something collides with it, we could kick off an event such as spawning enemies, opening doors, doing a cut scene, or anything else we wanted. In our game, we will not be using an object that is purely a scene object, but it is good to have it here for future projects. The Microsoft.Xna.Framework namespace will need to be included because this class uses BoundingSphere. Our physical object inherits from this and has more properties for an actual drawable object. Here is the code for the PhysicalObject class:  public abstract class PhysicalObject : SceneObject {    public Vector3 Position;    public Vector3 Velocity;    public Vector3 Acceleration;    public float Mass;    public float Scale = 1.0f;    public float Radius = 1.0f;    public Color Color;    public Matrix Rotation = Matrix.Identity;        public virtual void Move(float elapsed)    {   	//adjust velocity with our acceleration   	Velocity += Acceleration;              //adjust position with our velocity   	Position += elapsed * Velocity;              World = Matrix.CreateScale(Scale) * Rotation * Matrix.CreateTranslation(Position);              BoundingSphere = new BoundingSphere(Position, Radius);    } }  We inherit from SceneObject so we get the bounding sphere and the world matrix, but we also add position, velocity, acceleration, mass, scale, radius, color, and rotation. This allows us to assign physical properties to our objects. We have a Move method that applies the physical forces we talked about in Chapter 16, “Physics Basics.” This method adds the acceleration to our velocity and adds our velocity (taking the time delta into account) to our position. It then uses the scale, rotation, and position to update the world matrix for the object. Finally, it recalculates the bounding sphere based on the position and radius of the object. We need to add the following using statements:  using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics;  Now we are ready to look at our EnemyManager and MissileManager, which manage objects that inherit from our PhysicalObject. We will start with our MissileManager and our Missile class in particular:  class Missile : PhysicalObject {    public DateTime StartTime;    public bool IsActive; }  The missile object inherits all the properties from our physical object class and also includes the start time and a flag that states whether the missile is active. We will be treating this much like we did our particle system. We can jump right into our MissileManager to see how to manage these objects. Our MissileManager object will inherit from the DrawableGameComponent. As usual, we can start with our member fields and constructor:  public const int MISSILE_LIFE = 5; //5 seconds private Model missile; private Effect effect; public Matrix View; public Matrix Projection; private Missile[] missiles; private Texture2D missileTexture; private int lastMissileIndex; private float timer = 0; public MissileManager(Game game) : base(game) { }  We have a constant that determines how long our missile should stay on the screen if it does not hit any enemies. One of the challenges we are presenting gamers is that only a certain number of missiles can be on the screen at any given time for each level. The more accurate the players are, the more frequently they can fire a missile. If they miss, the missile is active for 5 seconds, and if they have fired their allotment, players need to wait until the 5 seconds are up before they can fire another missile. We also have fields that store the missile model and the effect we will be using for that model. We set our View and Projection properties (which our effect needs) inside of the game, so we set those fields with the public modifier. We have an array where we store and manage our missile objects and the texture we apply to those objects. Much like we did for our particle system, we are going to keep track of the last index in our array to which we added a missile so we know where to start when a new request is created to add a missile to our list.<br />
<br />
 Our constructor is empty and only passes the game object to the base DrawableGameComponent class. Next, we can look at the Load method that our game will call every time we start a new level. Each time a new level is started, we reset our array of missiles to handle the maximum amount the level allows the player to fire at one time. The code for the Load method is as follows:<br />
<br />
  public void Load(int capacity) {    missiles = new Missile[capacity];    lastMissileIndex = 0;        for (int i = 0; i < missiles.Length; i++)    missiles[i] = new Missile(); }  At the beginning of the level, we reallocate our array and reset our last missile index. Finally, we loop through all the missiles and store an instance of each. Our LoadContent and UnloadContent methods are next:  protected override void LoadContent() {    missileTexture = Game.Content.Load(@”Textures&#092;FireGrade”);    missile = Game.Content.Load(@”Models&#092;sphere”);    effect = Game.Content.Load(@”Effects&#092;VertexDisplacement”);    effect.Parameters[“ColorMap”].SetValue(missileTexture);    effect.Parameters[“AmbientColor”].SetValue(0.8f);        base.LoadContent(); } protected override void UnloadContent() {    missiles = null;        base.UnloadContent(); }  In our LoadContent method, we retrieve the texture from our TextureManager and the effect from our EffectManager. We then set the parameters on the effect. Our UnloadContent method sets our missiles array to null. We need to add the FireGrade texture to our Content project. We also need to add the sphere model to our project. Both of these assets can be found on the accompanying CD in this chapter’s code folder.<br />
<br />
 When the player fires a missile, we need to tell our MissileManager to add a missile to its array. Therefore, we provide a public method called AddMissile:<br />
<br />
  public bool AddMissile(Vector3 position, Vector3 direction, DateTime startTime) {    int index = lastMissileIndex;    for (int i = 0; i < missiles.Length; i++)    {   	if (!missiles[index].IsActive)          break;   	else   	{          index++;          if (index >= missiles.Length)         	index = 0;   	}              if (index == lastMissileIndex)          return (false);    }        //at this point index is the one we want ...    InitializeMissile(index, position, direction, startTime);        missiles[index].IsActive = true;        lastMissileIndex = index;        return (true); }  The AddMissile method loops through the entire array, finding the first empty slot it can initialize a missile into. If there are no free slots, the user has fired all the missiles allowed and the method returns false. The details of the InitializeMissile method are as follows:  private void InitializeMissile(int index, Vector3 position, Vector3 direction, DateTime startTime) {    missiles[index] = new Missile();    missiles[index].Position = position;    missiles[index].Acceleration = direction * 10f;    missiles[index].Velocity = Vector3.Zero;    missiles[index].StartTime = startTime; }  The InitializeMissile method sets the values passed in from AddMissile, which gets the values from the game. Our MissileManager class also has a collision detection method. CheckCollision is used to determine if any of the missiles have collided with the bounding sphere passed in:  public bool CheckCollision(BoundingSphere check) {    for (int i = 0; i < missiles.Length; i++)    {   	if ((missiles[i].IsActive) && (missiles[i].BoundingSphere.Intersects(check)))   	{          RemoveMissile(i);          return (true);   	}    }        return (false); }  If a collision is detected, we remove the missile from the list by setting its active flag to false. This is done in the RemoveMissile method:  private void RemoveMissile(int index) {    missiles[index].IsActive = false; }  This leaves just the Update and Draw methods. The Update method simply loops through all the active missiles and checks to see how long they have lived. If they have lived too long, they are removed from the array. If they are still alive, they are moved by calling the Move method on the Missile object, which ultimately calls the Move method on the PhysicalObject class:  public override void Update(GameTime gameTime) {    float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;        timer += 0.655f;        for (int mi = 0; mi < missiles.Length; mi++)    {   	//we do not want to update any inactive missiles   	if (!missiles[mi].IsActive)          continue;              if ((DateTime.Now - missiles[mi].StartTime) > TimeSpan.FromSeconds(MissileManager.MISSILE_LIFE))          RemoveMissile(mi);   	else          missiles[mi].Move(elapsed);    }        base.Update(gameTime); }  The Update method also adds a fixed amount to a timer, which is used for the effect of the missile. The Draw method is shown here:  public override void Draw(GameTime gameTime) {    GraphicsDevice.RenderState.DepthBufferEnable = true;    GraphicsDevice.RenderState.AlphaBlendEnable = true;        effect.Parameters[“Timer”].SetValue(timer);        effect.Parameters[“View”].SetValue(View);    effect.Parameters[“Projection”].SetValue(Projection);        for (int mi = 0; mi < missiles.Length; mi++)    {   	if (!missiles[mi].IsActive)          continue;              effect.Parameters[“World”].SetValue(missiles[mi].World);              Matrix[] transforms = new Matrix[missile.Bones.Count];   	missile.CopyAbsoluteBoneTransformsTo(transforms);              foreach (ModelMesh mesh in missile.Meshes)   	{          for (int i = 0; i < mesh.MeshParts.Count; i++)          {         	// Set this MeshParts effect to our RedWire effect         	mesh.MeshParts[i].Effect = effect;          }             	mesh.Draw();             	missiles[mi].BoundingSphere = mesh.BoundingSphere;          missiles[mi].BoundingSphere.Center += missiles[mi].World.Translation;   	}    }        base.Draw(gameTime); }  The Draw method makes sure the render state is in the right state before drawing anything. It sets the appropriate effect parameters; then it loops through all the missiles and applies the effect to them. It also recalculates the bounding sphere of the missile. Before we get back to the PlayingState, we need to add the enemy manager. The concept is the same as our missile manager: Only a certain number of enemies can be displayed at one time, determined by each level. The enemy object has tracking AI built in to it as well. We start by creating the Enemy class, which inherits from PhysicalObject:<br />
<br />
  public class Enemy : PhysicalObject {    Random random = new Random(DateTime.Now.Millisecond);        public Vector3 Target = Vector3.Zero;    public Texture2D Texture;    private float moveSpeed;    private Vector3 Up, Forward;        public Enemy(Texture2D texture, float moveSpeed)    {   	Texture = texture;   	this.moveSpeed = moveSpeed;   	Scale = 0.01f;   	Radius = 5f;   	Position = XELibrary.Utility.GetRandomVector3(          new Vector3(-300, -100, -100), new Vector3(300, 100, -100));              Up = Vector3.Up;   	Forward = Vector3.Forward;    }        public override void Move(float elapsed)    {   	Vector3 tv = Target - Position;   	tv.Normalize();              Velocity = tv * moveSpeed;              Forward = tv;              Vector3 Right = Vector3.Normalize(Vector3.Cross(Forward, Vector3.Up));              Up = Vector3.Normalize(Vector3.Cross(Right, Forward));              Rotation = Matrix.Identity;   	Rotation.Forward = Forward;   	Rotation.Up = Up;   	Rotation.Right = Right;              base.Move(elapsed);    } }  moveSpeed is the speed at which the enemies are moving toward the player. The Up and Forward vectors are stored so we can calculate the rotation. The position in which an enemy is generated is random. The Move method handles the AI for tracking the player as well as setting the rotation so the enemy is always facing the player. We define two vectors: Up and Forward. Then we calculate our Right vector by normalizing the cross-product of the Forward and Up vectors. Then we recalculate the Up vector again to make sure the vectors are truly perpendicular. Once we have all three vectors perfectly perpendicular to each other, we set our rotation matrix’s vectors so we can use it inside our base class. After setting all the properties for our enemy, the base class is called to finish the move process. Our EnemyManager class inherits from the DrawableGameComponent class, just like our MissileManager class. The member fields we need for this class are as follows:<br />
<br />
  public const int MAX_ENEMIES = 10; private Texture2D[] enemyTextures; private Model enemy; private Effect effect; private Random rand = new Random(); public Matrix View; public Matrix Projection; public List Enemies = new List(MAX_ENEMIES);  In our constructor, we need to store a reference to our game object:  public EnemyManager(Game game) : base(game) { }  Microsoft.Xna.Framework, Microsoft.Xna.Framework.Graphics, and System.Collections.Generic will need to be added to the EnemyManager.cs file. The LoadContent method of EnemyManager is as follows:  protected override void LoadContent() {    enemyTextures = new Texture2D[3];    enemyTextures[0] = Game.Content.Load(@”Textures&#092;wedge_p2_diff_v1”);    enemyTextures[1] = Game.Content.Load(@”Textures&#092;wedge_p2_diff_v2”);    enemyTextures[2] = Game.Content.Load(@”Textures&#092;wedge_p2_diff_v3”);    enemy = Game.Content.Load(@”Models&#092;p2_wedge”);    effect = Game.Content.Load(      @”Effects&#092;AmbientTexture”);        effect.Parameters[“AmbientColor”].SetValue(.8f);        base.LoadContent(); }  We are loading three different textures that the model we are loading can use. This model and these textures are taken from the Spacewar starter kit. They can also be found on the accompanying CD in this chapter’s code folder. The assets should be added to the appropriate folders in which the code is expecting to find them. The UnloadContent method, which gets called by the XNA Framework whenever the graphics device is reset or the game exits, simply clears out the list of enemies:<br />
<br />
  protected override void UnloadContent() {    Enemies.Clear();    Enemies = null;        base.UnloadContent(); }  The next method in our enemy manager class is the Draw method:  public override void Draw(GameTime gameTime) {    GraphicsDevice.RenderState.AlphaTestEnable = false;    GraphicsDevice.RenderState.AlphaBlendEnable = false;    GraphicsDevice.RenderState.PointSpriteEnable = false;    GraphicsDevice.RenderState.DepthBufferWriteEnable = true;    GraphicsDevice.RenderState.DepthBufferEnable = true;        effect.Parameters[“View”].SetValue(View);    effect.Parameters[“Projection”].SetValue(Projection);        for (int ei = 0; ei < Enemies.Count; ei++)    {   	effect.Parameters[“World”].SetValue(Enemies[ei].World);   	effect.Parameters[“ColorMap”].SetValue(Enemies[ei].Texture);              Matrix[] transforms = new Matrix[enemy.Bones.Count];   	enemy.CopyAbsoluteBoneTransformsTo(transforms);              foreach (ModelMesh mesh in enemy.Meshes)   	{          foreach (ModelMeshPart mp in mesh.MeshParts)          {         	mp.Effect = effect;          }                    mesh.Draw();   	}    }        base.Draw(gameTime); }  First, we set our render state properties to the values we require. Then we set our effect’s view and projection properties. Finally, we loop through all our enemies and draw each one with the appropriate texture and world matrix being passed into the effect. The last method we need to add in our EnemyManager class is the AddEnemy method:<br />
<br />
  public void AddEnemy(float moveSpeed) {    Enemies.Add(new Enemy(enemyTextures[rand.Next(0, 3)], moveSpeed)); }  This is a public method the playing state code will use to tell the manager to add another enemy to the list. The enemy will be assigned one of the three textures we have specified, along with its movement speed. Creating the Game Logic (Con't) Let’s return to the playing state code and add the following to the constructor:<br />
<br />
  playerSphere = new BoundingSphere(OurGame.Camera.Position, 1.5f); missileManager = new MissileManager(Game); Game.Components.Add(missileManager); missileManager.Enabled = false; missileManager.Visible = false; enemyManager = new EnemyManager(Game); Game.Components.Add(enemyManager); enemyManager.Enabled = false; enemyManager.Visible = false; Levels = new List(10); Levels.Add(new Level(50, 10, 60, 9.0f)); Levels.Add(new Level(25, 10, 60, 9.0f)); Levels.Add(new Level(15, 15, 60, 9.0f)); Levels.Add(new Level(10, 15, 60, 9.0f)); Levels.Add(new Level(5, 15, 60, 9.0f)); Levels.Add(new Level(5, 20, 60, 9.0f)); Levels.Add(new Level(5, 25, 60, 9.0f)); Levels.Add(new Level(5, 30, 60, 10.0f)); Levels.Add(new Level(5, 40, 90, 10.0f)); Levels.Add(new Level(3, 50, 90, 10.0f)); currentLevel = 0; enemyManager.Enemies = new List(Levels[CurrentLevel].Enemies);  In this game, we are using a stationary camera, so we are not going to continually update the player’s bounding sphere. Instead, it is set once in the constructor. We add the missile manager and enemy manager game components and create all our levels. Our PlayingState will start the game. The exposed method calls two private methods to prepare for the game and then to start the level. These methods are shown here:<br />
<br />
  public void StartGame() {    SetupGame();    StartLevel(); } private void SetupGame() {    TotalCollisions = 0;    currentLevel = 0; } public void StartLevel() {    GamePad.SetVibration(0, 0, 0);    enemyManager.Enemies.Clear();    totalCreatedEnemies = 0;        missileManager.Load(Levels[CurrentLevel].Missiles);        GameManager.PushState(OurGame.StartLevelState.Value); }  The only thing to point out in this code is that we push the StartLevelState onto the stack inside the StartLevel method. Next, we can look at the Update method in our PlayingGameState. We can replace the contents of the existing Update method with the following:<br />
<br />
  float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds; if (Input.WasPressed(0, Buttons.Back, Keys.Escape))    GameManager.PushState(OurGame.StartMenuState.Value); if (Input.WasPressed(0, Buttons.Start, Keys.Enter)) {    // push our paused state onto the stack    GameManager.PushState(OurGame.PausedState.Value); } if ((Input.WasPressed(0, Buttons.A, Keys.Space)) ||    (Input.WasPressed(0, Buttons.RightShoulder, Keys.LeftControl)) ||    Input.GamePads[0].Triggers.Right > 0) {    if (missileManager.AddMissile(new Vector3(   	OurGame.Camera.Position.X,   	OurGame.Camera.Position.Y - 1,   	OurGame.Camera.Position.Z + 1   	), OurGame.Camera.Target - OurGame.Camera.Position,   	DateTime.Now))    {      //play sound    } } if (enemyManager.Enabled) {    UpdateEnemies(elapsed);        while (CheckCollisions())    {   	//increase score if enemy was hit    }        //Are we finished with this level?    if (TotalCollisions == Levels[CurrentLevel].Enemies)    {   	TotalCollisions = 0;   	currentLevel++;              //Are we finished with the game?   	if (CurrentLevel == Levels.Count)   	{          //You won the game!!!          GameManager.PushState(OurGame.WonGameState.Value);          currentLevel--; //reset count back   	}   	else   	{          StartLevel();   	}    } } base.Update(gameTime);  We check our input and push on the start menu state or the paused state if it is appropriate. We check to see if the player has fired a missile and have a placeholder for playing a sound. We update all the enemies that are on the screen and then check to see if any of the missiles have collided with them. We will review the CheckCollisions method next. If a collision did occur, we have a placeholder to increase the score. Now we check to see if any more enemies are left. If there aren’t, we check to see if any more levels are left. If all the levels have been finished, the game is won. Otherwise, the game moves on to the next level. The CheckCollisions method is as follows:<br />
<br />
  private bool CheckCollisions() {    for (int ei = 0; ei < enemyManager.Enemies.Count; ei++)    {   	//See if an enemy is too close first   	if (enemyManager.Enemies[ei].BoundingSphere.Intersects(playerSphere))   	{          GameManager.PushState(OurGame.LostGameState.Value);          return (false);   	}              //if not, then we can check our missiles   	if (missileManager.CheckCollision(enemyManager.Enemies[ei].BoundingSphere))   	{          enemyManager.Enemies.RemoveAt(ei);             	TotalCollisions++;             	return (true);   	}    }        return (false); }  First, we check to see if an enemy has collided with the camera. If that happens, the game is over. Otherwise, we check to see if any of the missiles have collided with the enemies. Our Update method also calls the UpdateEnemies method, which is shown here:  private void UpdateEnemies(float elapsed) {    if (totalCreatedEnemies < Levels[CurrentLevel].Enemies)    {   	if (enemyManager.Enemies.Count < EnemyManager.MAX_ENEMIES)   	{          enemyManager.AddEnemy(Levels[CurrentLevel].EnemySpeed);          totalCreatedEnemies++;   	}    }        for (int ei = 0; ei < enemyManager.Enemies.Count; ei++)    {   	enemyManager.Enemies[ei].Target = OurGame.Camera.Position;   	enemyManager.Enemies[ei].Move(elapsed);    } }  The UpdateEnemies method checks to see if there are still enemies to be generated. We only allow MAX_ENEMIES on the screen at one time, so if a level has more than that, we wait until an enemy is destroyed before another one is spawned. The method then loops through all the enemies and updates their target based on the camera’s position. For this game, this really isn’t needed because we have a stationary camera. We then move each enemy. For now our Draw method is very lightweight—it is only setting the view and projection properties for the missile manager and the enemy manager. We can replace the current contents of the Draw method with the following:<br />
<br />
  missileManager.View = OurGame.Camera.View; missileManager.Projection = OurGame.Camera.Projection; enemyManager.View = OurGame.Camera.View; enemyManager.Projection = OurGame.Camera.Projection; base.Draw(gameTime  We need to clear out the contents of the LoadContent method. We will be adding code to that method a little later, but for now we just need to remove the old font we used in the previous demo. We need to know which level we are on outside of our playing state, so we need to make a public property to expose it:<br />
<br />
  public int CurrentLevel {    get { return (currentLevel); } }  We also need to modify our GameStateInterfaces code. Specifically, we need to modify the IPlayingState interface to include our StartGame method and this CurrentLevel property:  void StartGame(); int CurrentLevel { get; }  The final method we need to add to our PlayingState class is the StateChanged method. We override this method so we can turn on and off the appropriate game components:  protected override void StateChanged(object sender, EventArgs e) {    base.StateChanged(sender, e);        if (GameManager.State != this.Value)    {   	Visible = true;   	Enabled = false;   	missileManager.Enabled = false;   	missileManager.Visible = false;   	enemyManager.Enabled = false;   	enemyManager.Visible = false;    }    else    {   	missileManager.Enabled = true;   	missileManager.Visible = true;   	enemyManager.Enabled = true;   	enemyManager.Visible = true;    } }  We specified an effect file for both the missile manager and the enemy manager. The enemy manager is using the AmbientTexture effect file from last chapter. The file needs to be added to our projects. The missile manager, however, is using a new effect file. The basis of the effect is the vertex deformation effect we created in Chapter 15, “Advanced HLSL.” Here’s the code for VertexDisplacement.fx:  float4x4 World : WORLD; float4x4 View; float4x4 Projection; float4 AmbientColor : COLOR0; float Timer : TIME; float Offset = 1.0f; texture ColorMap; sampler ColorMapSampler = sampler_state {    texture = ;    magfilter = LINEAR;    minfilter = LINEAR;    mipfilter = LINEAR;    AddressU = Wrap;    AddressV = Wrap; }; struct VertexInput {    float4 Position : POSITION0;    float2 TexCoord : TEXCOORD0; }; struct VertexOutput {    float4 Position : POSITION0;    float2 TexCoord : TEXCOORD0; }; VertexOutput vertexShader(VertexInput input) {    VertexOutput output = (VertexOutput)0;    float4x4 WorldViewProjection = mul(mul(World, View), Projection);    output.TexCoord = input.TexCoord  + Timer * .005;        float4 Pos = input.Position;    float y = Pos.y * Offset + Timer;    float x = sin(y) * Offset;    Pos.x += x;        output.Position = mul(Pos, WorldViewProjection);        return( output ); } struct PixelInput {    float2 TexCoord : TEXCOORD0; }; float4 pixelShader(PixelInput input) : COLOR {    float4 color;    color = tex2D(ColorMapSampler, input.TexCoord);    return(color); } technique Default {    pass P0    {   	VertexShader = compile vs_1_1 vertexShader();   	PixelShader = compile ps_1_4 pixelShader();    } }  This effect code is identical to the code we used in Chapter 15. The only difference is inside the vertex shader. Besides modifying the vertex position, we also modify the texture coordinates. When we shoot our missiles, they will wobble. The next state we need to modify is our StartLevelState. We need to clear out the code inside the class and add the following private member fields:<br />
<br />
  private bool demoMode = true; private bool displayedDemoDialog = false; private DateTime levelLoadTime; private readonly int loadSoundTime = 2500; private string levelText = “LEVEL”; private string currentLevel; bool startingLevel = false; private Vector2 levelTextPosition; private Vector2 levelTextShadowPosition; private Vector2 levelNumberPosition; private Vector2 levelNumberShadowPosition;  We are going to play a sound as we are loading the level. We want the actual game play to start as soon as the sound is over. There is no way to get notified of a sound being completed, so we put in our own timer. We will add the sound later but put the code into place now to handle the timing. The start level state will also display the number of the level we are starting. We store the level text once so we can use it multiple times. We also set up two sets of vectors to hold the locations of the level text (that is, LEVEL) as well as the level number (that is, 1) and their drop-shadow locations. The constructor did not change but is listed here for completeness:<br />
<br />
  public StartLevelState(Game game) : base(game) {    game.Services.AddService(typeof(IStartLevelState), this); }  The updated StateChanged method allows us to start the logic when we enter our start level state:  protected override void StateChanged(object sender, EventArgs e) {    base.StateChanged(sender, e);        if (GameManager.State == this.Value)    {   	startingLevel = true;              if (demoMode && !displayedDemoDialog)   	{          //We could set properties on our YesNoDialog          //so it could have a custom message and custom          //Yes / No buttons ...          //YesNoDialogState.YesCaption = “Of course!”;          GameManager.PushState(OurGame.YesNoDialogState.Value);          this.Visible = true;          displayedDemoDialog = true;          startingLevel = false;   	}    }        if (startingLevel)    {   	//play sound              levelLoadTime = DateTime.Now;              currentLevel = (OurGame.PlayingState.CurrentLevel + 1).ToString();              Vector2 viewport = new Vector2(GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);   	Vector2 levelTextLength = OurGame.Font.MeasureString(levelText);   	Vector2 levelNumberLength = OurGame.Font.MeasureString(currentLevel);   	levelTextShadowPosition = (viewport – levelTextLength * 3) / 2;   	levelNumberShadowPosition = (viewport – levelNumberLength * 3) / 2;   	levelNumberShadowPosition.Y += OurGame.Font.LineSpacing * 3;   	levelTextPosition.X = levelTextShadowPosition.X + 2;   	levelTextPosition.Y = levelTextShadowPosition.Y + 2;   	levelNumberPosition.X = levelNumberShadowPosition.X + 2;   	levelNumberPosition.Y = levelNumberShadowPosition.Y + 2;    } }  The first part of the method is the same as it was in our previous game state demo. However, we also set the startingLevel flag with the initial value of true. We modify the demo condition to set the startingLevel flag to false. Assuming we are really starting the level, which will occur the first time if we are not in demo mode (or after the dialog box is closed if we are in demo mode), we begin playing our starting level sound. We have put a placeholder in to play that sound for now. We also initialize our level load time and set our current level variable. Finally, we initialize the vectors that store the position of the text we want to display when the level starts. The text will be centered on the screen. The Update method for this state is as follows:<br />
<br />
  public override void Update(GameTime gameTime) {    if (DateTime.Now > levelLoadTime + new TimeSpan(0, 0, 0, 0, loadSoundTime))    {   	//stop sound              // change state to playing   	GameManager.ChangeState(OurGame.PlayingState.Value);    }        base.Update(gameTime); }  Inside the Update method, we change to the PlayingState and stop the sound if enough time has passed. For now, we just have a placeholder where we will eventually stop the sound. The last method in this state is the Draw method:  public override void Draw(GameTime gameTime) {    if (startingLevel)    {   	OurGame.SpriteBatch.Begin();   	OurGame.SpriteBatch.DrawString(OurGame.Font, levelText,          levelTextShadowPosition, Color.Yellow, 0, Vector2.Zero, 3.0f,          SpriteEffects.None, 0);   	OurGame.SpriteBatch.DrawString(OurGame.Font, levelText,          levelTextPosition, Color.Red, 0, Vector2.Zero, 3.0f,          SpriteEffects.None, 0);   	OurGame.SpriteBatch.DrawString(OurGame.Font, currentLevel,          levelNumberShadowPosition, Color.Yellow, 0, Vector2.Zero, 3.0f,          SpriteEffects.None, 0);   	OurGame.SpriteBatch.DrawString(OurGame.Font, currentLevel,          levelNumberPosition, Color.Red, 0, Vector2.Zero, 3.0f,          SpriteEffects.None, 0);   	OurGame.SpriteBatch.End();    }        base.Draw(gameTime); }  The Draw method simply draws the level text and the level number in the right position, complete with a drop-shadow effect. It only draws this text if we are actually starting the level. If the YesNoDialog (Demo mode) is on the stack, we do not want to display the text. We need to declare a font variable in our TunnelVision game class:<br />
<br />
  public SpriteFont Font;  Inside the LoadContent method we need to load our font:  Font = Content.Load(@”Fonts&#092;Arial”);  Before we compile and run our changes, we need to modify the StartMenuState class. Inside the Update method, we need to replace the contents of the condition where we check if either Start or Enter was pressed with the following code:  if (GameManager.ContainsState(OurGame.PlayingState.Value))    GameManager.PopState(); else {    //starting game, queue first level    GameManager.ChangeState(OurGame.PlayingState.Value);    OurGame.PlayingState.StartGame(); }  We are still popping off our start menu state if our stack contains a playing state. However, instead of changing the state to the StartLevelState like in the previous demo, we are changing the state to PlayingState and calling its StartGame method. At this point we can compile and run the game. The game logic is in place, but it is rather rough around the edges.<br />
<br />
 <br />
<strong class='bbc'>Creating the Crosshair</strong><br />
 To allow better aiming, we need to add a crosshair to our screen. To start, we need to add the following texture to our member field list of the PlayingState class:  private Texture2D crossHair;  Inside our Draw method we need to add the following code:  OurGame.SpriteBatch.Begin(); if (OurGame.DisplayCrosshair) {    OurGame.SpriteBatch.Draw(crossHair, new Rectangle(      (GraphicsDevice.Viewport.Width - crossHair.Width) / 2,      (GraphicsDevice.Viewport.Height - crossHair.Height) / 2,      crossHair.Width, crossHair.Height), Color.White); } OurGame.SpriteBatch.End();  We actually populate the crosshair texture inside our LoadContent method:  protected override void LoadContent() {    crossHair = Content.Load(@”Textures&#092;crosshair”);    base.LoadContent(); }  The texture can be found in the usual place. Later, we are going to provide an option to turn on and off the crosshair, so we need to create the public Boolean DisplayCrosshair field in our TunnelVision game code. It should be initialized to true. Now, we can more easily see where we are aiming! <br />
<strong class='bbc'>Creating the Game-Specific Camera</strong><br />
 Now we are going to add a new camera directly to our game. We are not going to add this to the XELibrary because it is a special camera that most likely will not be reused. The purpose of this new camera is to handle input a little differently and to restrict movement. The code for the new TunnelVisionCamera.cs file is as follows:  using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; using XELibrary; namespace TunnelVision {    public partial class TunnelVisionCamera : Camera    {    private float spinLeft = 0;    private float spinRight = 0;    private float spinDown = 0;    private float spinUp = 0;        private float spinLeftChange = 0;    private float spinRightChange = 0;    private float spinDownChange = 0;    private float spinUpChange = 0;        public TunnelVisionCamera(Game game) : base(game) {}        public override void Update(GameTime gameTime)    {   	if (!UpdateInput)   	return;              float timeDelta = (float)gameTime.ElapsedGameTime.TotalSeconds;              if (input.KeyboardState.IsKeyDown(Keys.Left))          spinLeftChange += .1f;   	else          spinLeftChange -= .1f;   	spinLeftChange = MathHelper.Clamp(spinLeftChange, 0, 1);   	spinLeft = spinLeftChange;   	if (input.GamePads[playerIndex].ThumbSticks.Left.X < 0)          spinLeft = -input.GamePads[playerIndex].ThumbSticks.Left.X;   	if (spinLeft > 0)          cameraYaw += (Utility.PowerCurve(spinLeft) * SpinRate * timeDelta);              if (input.KeyboardState.IsKeyDown(Keys.Right))          spinRightChange += .1f;   	else          spinRightChange -= .1f;   	spinRightChange = MathHelper.Clamp(spinRightChange, 0, 1);   	spinRight = spinRightChange;   	if (input.GamePads[playerIndex].ThumbSticks.Left.X > 0)          spinRight = input.GamePads[playerIndex].ThumbSticks.Left.X;   	if (spinRight > 0)          cameraYaw -= (Utility.PowerCurve(spinRight) * SpinRate * timeDelta);              if (input.KeyboardState.IsKeyDown(Keys.Down))          spinDownChange += .1f;   	else          spinDownChange -= .1f;   	spinDownChange = MathHelper.Clamp(spinDownChange, 0, 1);   	spinDown = spinDownChange;   	if (input.GamePads[playerIndex].ThumbSticks.Left.Y < 0)          spinDown = -input.GamePads[playerIndex].ThumbSticks.Left.Y;   	if (spinDown > 0)          cameraPitch -= (Utility.PowerCurve(spinDown) * SpinRate *              timeDelta);              if (input.KeyboardState.IsKeyDown(Keys.Up))          spinUpChange += .1f;   	else          spinUpChange -= .1f;   	spinUpChange = MathHelper.Clamp(spinUpChange, 0, 1);   	spinUp = spinUpChange;   	if (input.GamePads[playerIndex].ThumbSticks.Left.Y > 0)          spinUp = input.GamePads[playerIndex].ThumbSticks.Left.Y;   	if (spinUp > 0)          cameraPitch += (Utility.PowerCurve(spinUp) * SpinRate *              timeDelta);              //reset camera angle if needed   	if (cameraYaw > 80)          cameraYaw = 80;   	else if (cameraYaw < -80)          cameraYaw = -80;              //keep camera from rotating a full 90 degrees in either direction   	if (cameraPitch > 89)          cameraPitch = 89;   	if (cameraPitch < -89)          cameraPitch = -89;              Matrix rotationMatrix;   	Vector3 transformedReference;              Matrix.CreateRotationY(MathHelper.ToRadians(cameraYaw),          out rotationMatrix);              //add in pitch to the rotation   	rotationMatrix = Matrix.CreateRotationX(          MathHelper.ToRadians(cameraPitch)) * rotationMatrix;              // Create a vector pointing the direction the camera is facing.   	Vector3.Transform(ref cameraReference, ref rotationMatrix,          out transformedReference);   	// Calculate the position the camera is looking at.   	Vector3.Add(ref cameraPosition, ref transformedReference,          out cameraTarget);              Matrix.CreateLookAt(ref cameraPosition, ref cameraTarget,          ref cameraUpVector, out view);   	}    } }  This is very similar to the base object’s Update method, except that we are restricting movement. We only allow the camera to move 80 degrees left or right. The pitch did not change. Instead of going through the entire class, line by line, we’ll just look at the section of code that handles if the user rotated to the left and infer how the rest of the movements work:  if (input.KeyboardState.IsKeyDown(Keys.Left))    spinLeftChange += .1f; else    spinLeftChange -= .1f; spinLeftChange = MathHelper.Clamp(spinLeftChange, 0, 1); spinLeft = spinLeftChange; if (input.GamePads[playerIndex].ThumbSticks.Left.X < 0)    spinLeft = -input.GamePads[playerIndex].ThumbSticks.Left.X; if (spinLeft > 0)    cameraYaw += (Utility.PowerCurve(spinLeft) * SpinRate * timeDelta);  During game play, the keyboard movement was too fast and too jerky. To solve this, we build up our spin left value. In the base class, it simply gets set to 1. Here, we are adding 10% each frame and clamping the results to 1. Now we can tap the keyboard to have more precise control over targeting our enemies. If the game pad is used to rotate the camera, we use a new helper method to produce a curve in the movement. In the Utility.cs file in the XELibrary we can add the following code  Private const float power = 3; public static float PowerCurve(float value) {    return ((float)Math.Pow(Math.Abs(value), power) * Math.Sign(value)); }  The PowerCurve helper method provides a curve we can apply to the values our thumbstick produces. Instead of strictly using the value of the thumbstick, we are making the low values lower, which gives us more control. Now as we barely move the thumbstick, the camera will barely move. And when we move the controller to target our enemies, we have more precise control. We need to modify our Camera object in the XELibrary. The following public member field needs to be created:<br />
<br />
  public bool UpdateInput = true;  The following condition needs to be added at the very top of the Update method:  if (!UpdateInput) {    base.Update(gameTime);    return; }  We also want to change the modifier for the cameraReference, cameraTarget, cameraUpVector, view, cameraYaw, and cameraPitch fields to be protected instead of private. The private const spinRate and moveRate should be changed to public and no longer be a const because we need to be able to set them anywhere. To use this new camera, we need to change our TunnelVision game class to use TunnelVisionCamera instead of Camera. We also need to modify our PlayingState class to use the new UpdateMethod Boolean property. Inside the StateChanged method we need to add the following code to the first branch of our condition:<br />
<br />
  OurGame.Camera.UpdateInput = false;  We need to do the opposite in the else of our if condition:  OurGame.Camera.UpdateInput = true;  Inside the constructor of PlayingState, we need to add the following code to set the move rate and spin rate of our camera:  OurGame.Camera.MoveRate = 10; OurGame.Camera.SpinRate = 60;  We have improved our input handling and have restricted movement on our camera so we only rotate 80 degrees to the left or right instead of the full 360 degrees. <br />
<strong class='bbc'>Summary</strong><br />
 In this chapter, we have laid the foundation for creating our game. We have put into place all the game logic. There were not really any new concepts in this chapter, but by putting what you learned in previous chapters into practice, we should be well on our way to creating our own masterpieces. The next two chapters are spent updating our game states and UI enhancements. Reproduced from the book <a href='http://www.amazon.com/Microsoft-XNA-Game-Studio-Unleashed/dp/0672330229' class='bbc_url' title='External link' rel='nofollow external'>Microsoft XNA Game Studio 3.0 Unleashed</a>. Copyright? 2009. Reproduced by permission of Pearson Education, Inc., 800 East 96th Street, Indianapolis, IN 46240. Written permission from Pearson Education, Inc. is required for all other uses<br />
<br />
]]></description>
		<pubDate>Fri, 29 May 2009 20:37:20 +0000</pubDate>
		<guid isPermaLink="false">e2e46f7e10a42f41da2b9a6cb1f32a43</guid>
	</item>
	<item>
		<title>Designing a Flexible Vertex Element System for...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/designing-a-flexible-vertex-element-system-for-r2589</link>
		<description><![CDATA[<strong class='bbc'>Introduction</strong><br />
Anyone who’s done 3D graphics work with DirectX or XNA has undoubtedly had to learn about the concept of vertex formats. All vertex data passed to the graphics card needs to be described in order for the data it contains to be used correctly, and each graphics API has slightly different ways of doing so. In the past, when programmable shaders were not a factor, DirectX used a system called the Flexible Vertex Format (FVF), which was a system of flags that could be combined in complex ways to describe the location and format of the different bits of data contained in the vertex structure. With the introduction of shaders, the old system became too impractical for general use. The vertex element system was devised that is still used for both Direct3D9 and XNA. Direct3D10 has introduced a slightly newer system based upon this one, but I’m only going to be focusing on the one used by XNA.<br />
<br />
<br />
<strong class='bbc'>The Problem</strong><br />
XNA allows you to describe your custom vertex structures by creating an array of vertex elements that correspond to each of the data elements in your vertex structure. Each element in the array contains information such as the data format, the intended usage, the offset into structure in bytes, and other bits of data that are used less often, such as tessellator modes. While this system is very flexible and works quite well in practice, it still has two main issues that could be improved:<ul class='bbc'><br /><li>Hard coding the offset of each vertex element can be quite unsafe. Providing the wrong value won’t be caught by the compiler, and will probably just cause your rendering to appear strange, making it a difficult bug to track down.<br /></li><li>In a more academic view, it’s wasteful to have to provide information in your code that already exists. Whenever you need to duplicate code, you increase your maintenance load and introduce the possibility that the two can become out-of-sync with each other.<br /></li></ul><br />
So that’s the problem. How do we go about fixing it?<br />
<br />
<strong class='bbc'>The Solution</strong><br />
I’m always looking for ways to apply the high level features of C# to real-world problems. In this case, attributes immediately came to mind as an elegant way to make this situation easier. Attributes are a concept in .NET that allow you to apply metadata to types and code elements. On their own, they have no intrinsic meaning, but using reflection you can look them up and use the data they contain to alter how your code executes.<br />
<br />
To better see how attributes can help, let’s look at a simple example using both the vertex element system and the newly proposed attribute system.<br />
<br />
<pre class='prettyprint'><br /><br />&#91;StructLayout(LayoutKind.Sequential)&#93;<br />public struct VertexPositionColor<br />{<br />  public Vector3 Position;<br />  public Color Color;<br />  public static readonly VertexElement&#91;&#93; VertexElements;<br />  static VertexPositionColor()<br />  {<br />	VertexElements = new VertexElement&#91;&#93;<br />	{<br />	  new VertexElement(0, 0, VertexElementFormat.Vector3,<br />		VertexElementMethod.Default, VertexElementUsage.Position, 0), new<br />		VertexElement(0, 12, VertexElementFormat.Color,<br />		VertexElementMethod.Default, VertexElementUsage.Color, 0)<br />	};<br />  }<br />}<br /><br />VertexDeclaration declaration = new VertexDeclaration(GraphicsDevice,<br />  VertexPositionColor.VertexElements);<br />Notice how we declare two vertex elements, one for each piece of data in our<br />  vertex structure(the position and color)<br />. Also, because we are hardcoding the byte offset for each data element, we<br />  need to apply the StructLayout attribute to the structure to ensure that its<br />  fields don ’t get moved around by the compiler. Now, we ’ll look at attribute<br />  version. struct VertexPositionColor<br />{<br />	&#91;VertexElement(VertexElementUsage.Position)<br />	  public Vector3 Position;<br />  &#91;VertexElement(VertexElementUsage.Color)&#93;<br />  public Color Color;<br />} VertexDeclaration declaration = GraphicsDevice.CreateVertexDeclaration(typeof<br />  (VertexPositionColor));<br /></pre><br />
<br />
Wow, we were able to cut that down quite nicely. We no longer need to build up an array of data elements, since we will be using reflection to find the information for us. Further, we no longer need to specify the StructLayout attribute, since the byte offset will be calculated by the program at runtime. OK, so now we can just use these attributes to mark each element instead of building the element array by hand. How exactly does this all work?<br />
<br />
<br />
<strong class='bbc'>The Attribute</strong><br />
Before we look at the method that actually does the messy work of building up the vertex element data, let’s take a look at the attribute that we’ll be using to mark each data element.<br />
<br />
<pre class='prettyprint'><br /><br />&#91;AttributeUsage(AttributeTargets.Field &#124; AttributeTargets.Property)&#93;<br />public sealed class VertexElementAttribute: Attribute<br />{<br />  public int Stream<br />  {<br />	get;<br />	set;<br />  }<br />  public VertexElementMethod Method<br />  {<br />	get;<br />	set;<br />  }<br />  public VertexElementFormat Format<br />  {<br />	get;<br />	set;<br />  }<br />  public VertexElementUsage Usage<br />  {<br />	get;<br />	private set;<br />  }<br />  internal int Offset<br />  {<br />	get;<br />	set;<br />  }<br />  public VertexElementAttribute(VertexElementUsage usage)<br />  {<br />	Usage = usage;<br />	Format = VertexElementFormat.Unused;<br />  }<br />  public VertexElementAttribute(VertexElementUsage usage, VertexElementFormat<br />	format)<br />  {<br />	Usage = usage;<br />	Format = format;<br />  }<br />}<br /></pre><br />
<br />
What do we have here? Well, for starters, we can see that the attribute exposes the same set of data that XNA’s VertexElement system does. While we don’t provide constructors for all of this information, the user can optionally specify it by using named parameters, a C# feature that can be used with attributes. Another thing that might pop out at you is that Offset is marked as internal. Since we will be calculating this field, it’s only necessary as a temporary storage location for the creation method. If you were to place this system inside of a separate DLL as part of an engine or framework, the Offset member would be completely hidden from the client’s view, which is what we want since they shouldn’t be messing with it manually.<br />
<br />
Finally, we have a few constructors containing the parameters that are absolutely necessary for the vertex element system to do its job. Some of you may ask, “Why is format an optional parameter?” Well, we can easily determine the format in some cases, such as if the underlying field is a Vector3 or a Color. However, some of the formats cannot be determined so easily, so we allow the user the option of specifying the format in non-trivial cases.<br />
<br />
OK, that’s the extent of the attribute, something that’s not very amazing to look at actually. Now let’s move on to the real meat of the attribute system, the CreateVertexDeclaration method.<br />
<br />
<br />
<strong class='bbc'>The Reflection</strong><br />
For anyone who’s never seen reflection code (especially those coming from a C++ background), what I’m about to show you may shock and amaze. For the rest of you, this should be old hat.<br />
<br />
<pre class='prettyprint'><br /><br />	  public static class AttributeSystem<br />	  {<br />		static Dictionary cachedData = new Dictionary();<br />		public static VertexDeclaration CreateVertexDeclaration(this<br />		  GraphicsDevice device, Type vertexType)<br />		{<br />		  if (cachedData.ContainsKey(vertexType))<br />			return new VertexDeclaration(device, cachedData&#91;vertexType&#93;);<br />		  if (!vertexType.IsValueType)<br />			throw new InvalidOperationException(<br />			  "Vertex types must be value types.");<br />		  List objectAttributes = new List();<br />		  FieldInfo&#91;&#93; fields = vertexType.GetFields(BindingFlags.NonPublic &#124;<br />			BindingFlags.Public &#124; BindingFlags.Instance);<br />		  foreach (FieldInfo field in fields)<br />		  {<br />			VertexElementAttribute&#91;&#93; attributes = (VertexElementAttribute&#91;&#93;)<br />			  field.GetCustomAttributes(typeof(VertexElementAttribute), false);<br />			if (field.Name.Contains("&lt;") && field.Name.Contains("&gt;"))<br />			{<br />			  int index1 = field.Name.IndexOf('&lt;');<br />			  int index2 = field.Name.IndexOf('&gt;');<br />			  string propertyName = field.Name.Substring(index1 + 1, index2 -<br />				index1 - 1);<br />			  PropertyInfo property = vertexType.GetProperty(propertyName,<br />				field.FieldType);<br />			  if (property != null)<br />				attributes = (VertexElementAttribute&#91;&#93;)<br />				  property.GetCustomAttributes(typeof(VertexElementAttribute),<br />				  false);<br />			}<br />			if (attributes.Length == 1)<br />			{<br />			  if (attributes&#91;0&#93;.Format == VertexElementFormat.Unused)<br />			  {<br />				if (field.FieldType == typeof(Vector2))<br />				  attributes&#91;0&#93;.Format = VertexElementFormat.Vector2;<br />				else if (field.FieldType == typeof(Vector3))<br />				  attributes&#91;0&#93;.Format = VertexElementFormat.Vector3;<br />				else if (field.FieldType == typeof(Vector4))<br />				  attributes&#91;0&#93;.Format = VertexElementFormat.Vector4;<br />				else if (field.FieldType == typeof(Color))<br />				  attributes&#91;0&#93;.Format = VertexElementFormat.Color;<br />			  }<br />			  attributes&#91;0&#93;.Offset = Marshal.OffsetOf(vertexType, field.Name)<br />				.ToInt32();<br />			  objectAttributes.Add(attributes&#91;0&#93;);<br />			}<br />		  }<br />		  if (objectAttributes.Count &lt; 1)<br />			throw new InvalidOperationException(<br />			  "The vertex type must have at least one field or property marked with the VertexElement attribute.");<br />		  List elements = new List();<br />		  Dictionary usages = new Dictionary();<br />		  foreach (VertexElementAttribute attribute in objectAttributes)<br />		  {<br />			if (!usages.ContainsKey(attribute.Usage))<br />			  usages.Add(attribute.Usage, 0);<br />			int index = usages&#91;attribute.Usage&#93;;<br />			usages&#91;attribute.Usage&#93;++;<br />			elements.Add(new VertexElement((short)attribute.Stream, (short)<br />			  attribute.Offset, attribute.Format, attribute.Method,<br />			  attribute.Usage, (byte)index));<br />		  }<br />		  VertexElement&#91;&#93; elementArray = elements.ToArray();<br />		  cachedData.Add(vertexType, elementArray);<br />		  return new VertexDeclaration(device, elementArray);<br />		}<br />	  }<br /><br /></pre><br />
<br />
So that’s the extent of the attribute system in its entirety. I’m not going to go step by step through the code, but I will point out some of the more interesting bits and explain the rationale behind them.<ul class='bbcol decimal'><br /><li>I’ve placed the method in a static class and made it an extension method. This isn’t actually required for the method to be useful, but I like extension methods so that’s how I made it.<br /></li><li>Another feature I added that is entirely optional is the use of a dictionary to cache reflected data. This could save you some processing power if you are recreating vertex declarations all the time, but it isn’t strictly necessary for the system to work.<br /></li><li>Our method requires that the vertex type be a value type (struct keyword in C#). While this will be obvious to C# developers, it could end up being unintuitive for those coming over to XNA from C++. Suffice it to say, struct isn’t the same as class in C#. Read up on value types and reference types before working with C# further.<br /></li><li>While iterating over each field seems to be the logical way to handle things, I also wanted to support automatic properties, since I absolutely love them. To do this, you need to check the name of each field to see if it contains the ‘<’ and ‘>’ characters. As far as I’ve seen, this is only possible for backing store fields generated by the compiler for automatic properties, so I extract the actual property name and look for the attribute there.<br /></li><li>You can see that I only provide default support for four formats: Vector2, Vector3, Vector4, and Color. All others will need to be specified manually. I suppose providing automatic support for more would be possible. I’ll leave that as an exercise for the reader.<br /></li><li>That strange bit of code near the end is how I calculate usage indices for each data element. Basically, each occurrence of a particular usage is given an increasing usage index, starting from 0. While this seems correct to me and works fine, I’ve been told that it’s possible that this doesn’t always work. If you want, you could always add a UsageIndex property to the attribute and give the user the option of specifying the usage index manually.<br /></li></ul><br />
<strong class='bbc'>The Downsides</strong><br />
To be honest, I can’t think of any. All the power of the original method is still there, but wrapped up in a safer and easier to use format. If you think of anything that I missed, be sure to let me know.<br />
<br />
<br />
<strong class='bbc'>The End</strong><br />
That’s about all I have to say about that. When I hit upon this system I felt quite pleased with myself, and I was surprised to learn that nobody else on the internet had already developed something similar. It’s simple, elegant, and makes the code easier to read and maintain. Hopefully you will find it as cool as I do. Even if you don’t, be sure to let me know what you think. I’m always eager to hear what others think of my work.<br />
<br />
<br />
<strong class='bbc'>The References</strong><br />
As always, see <a href='http://msdn.microsoft.com/' class='bbc_url' title='External link' rel='nofollow external'>MSDN</a> for a complete reference to both .NET and XNA.]]></description>
		<pubDate>Tue, 02 Dec 2008 09:17:25 +0000</pubDate>
		<guid isPermaLink="false">ff111e4a5406ed4024a901c57e811167</guid>
	</item>
	<item>
		<title>Resolution Independence in 2D Direct3D Games –...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/resolution-independence-in-2d-direct3d-games-%e2%80%93-r2585</link>
		<description><![CDATA[<br />
<strong class='bbc'>Introduction</strong><br />
 We all understand that writing resolution-independent 2D games can be a lot more challenging than 3D games. This article outlines an approach I have been experimenting with recently that I believe is producing far better results than the more usual method of scaling vertices.<br />
<br />
 The following two screenshots are taken from an old platform game of mine. In both cases, the “native” resolution of the game is 1024x768, but the game is running at 1280x1024 on my LCD, so the graphics have been scaled up accordingly.<br />
<br />
 The first image is as a result of storing a scaling factor based on 1024/ActualScreenWidth, which all vertices are then multiplied by prior to being rendered.<br />
<br />
  <span rel='lightbox'><img src='http://images.gamedev.net/features/snippets/dx3d2dIndieRes/fig1.png' alt='Posted Image' class='bbc_img' /></span><br />
<br />
  The next image uses the alternative method that I describe in more detail below. Note the smoother main sprite, the lack of the edge error on the door and the cleaner looking stars on the boxes.<br />
<br />
  <span rel='lightbox'><img src='http://images.gamedev.net/features/snippets/dx3d2dIndieRes/fig2.png' alt='Posted Image' class='bbc_img' /></span><br />
<br />
  <br />
<strong class='bbc'>The Basic Idea</strong><br />
 The basic idea is not complicated and is also no silver bullet – there are some obvious cons to this approach which I will discuss later on.<br />
<br />
 In essence, I am using a “fake” back buffer to render to, in the same dimensions as the game’s “native” resolution. At the end of the rendering look, I am then copying this onto the actual back buffer using IDirect3DDevice9::StretchRect().<br />
<br />
 StretchRect() appears to be able to do a much cleaner job of scaling an already composited image than the results generated from manually scaling vertices. It also avoids errors such as the slight inaccuracy in the door in the first screenshot above.<br />
<br />
 <br />
<strong class='bbc'>The Implementation</strong><br />
 Here’s my GraphicsDevice interface, omitting all functions not actually relevant to this technique:<br />
<br />
  class GraphicsDevice { private:    IDirect3DDevice9 *Device;    IDirect3DSurface9 *BackSurface,*DrawSurface;    RECT DestRect; public:    GraphicsDevice() : Direct3D(0),Device(0),DrawSurface(0) { }    ~GraphicsDevice(){ Release(); }    void Acquire(HWND Hw,const GraphicsOptions &Options);    void Release();    void Begin(D3DCOLOR Clear);    void End(); };  You can see that in addition to my device pointer, I need to store two IDirect3DSurface9 pointers; one for the fake buffer we will create and one to hold onto the actual back buffer while we are rendering to the fake one. We also calculate the destination rectangle when we create the device to save some processing every loop, so this becomes another member of GraphicsDevice.<br />
<br />
 GraphicsOptions is just a small struct that contains the resolution height and width, filtering options, vertical sync options, etc.<br />
<br />
 The first task is in Acquire(), where in addition to setting up the device, we also need to create the fake back buffer.<br />
<br />
  void GraphicsDevice::Acquire(HWND Hw,const GraphicsOptions &Options) {    // set up device as normal, code omitted    R=Device->CreateRenderTarget(1024,768,D3DFMT_A8R8G8B8,                             	D3DMULTISAMPLE_NONE,0,FALSE,                             	&DrawSurface,NULL);    if(FAILED®) throw Error("Unable to create draw surface");    DestRect=CreateAspectRect(Params.BackBufferWidth,                              Params.BackBufferHeight); }  CreateAspectRect() is a helper function that just calculates the largest 4:3 rectangle that will fit on the current resolution. If the resolution is 4:3 as well, the resolution is returned as the rectangle, otherwise the rectangle is smaller than the resolution along one or the other dimension and the result is letterboxed on to the back buffer.  RECT CreateAspectRect(int Width,int Height) {    int Fx,Fy;    float X,Y;    Y=float(Height)/3;    X=Y*4;    if(Width>=int(X)){ Fx=int(X); Fy=Height; }    else   	{   	X=float(Width)/4;   	Y=X*3;   	Fx=Width; Fy=int(Y);   	}    int Ox=0,Oy=0;    if(Fx]]></description>
		<pubDate>Thu, 20 Nov 2008 12:20:32 +0000</pubDate>
		<guid isPermaLink="false">4bea6954f150dffe36b732708adb1a2b</guid>
	</item>
	<item>
		<title>Integrating Your XNA Engine With XSI ModTool</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/integrating-your-xna-engine-with-xsi-modtool-r2547</link>
		<description><![CDATA[<br />
<strong class='bbc'>Introduction</strong><br />
 For many a hobbyist developer, the XNA Framework has been a gift from above.  The combination of a robust game-development framework with MicrosoftÆs venerable Direct3D graphics back-end can be a winning combination for student programmers making their first game, or bedroom coders who donÆt have time to waste on creating tedious boilerplate code.  With all of the framework classes and samples dedicated to showing you how easy it is to get a very simple game up and running in 30 minutes, itÆs pretty easy to forget that with XNA itÆs possible to craft complex, professional-level games by making the most of features like the Content Pipeline (even without a professional budget!).  In that regard, this article is going to walk you through an implementation a 3D content authoring system that can allow you to seamlessly integrate <a href='http://www.softimage.com/products/modtool/' class='bbc_url' title='External link' rel='nofollow external'>XSI ModTool</a> with your gaming engine. <br />
<br />
<br />
<strong class='bbc'>Prerequisites</strong><br />
 This article assumes at least basic familiarity with: C#, the XNA Framework graphics classes, the XNA Framework Content Pipeline, and HLSL.  To compile the sample code, you will need to have XNA Game Studio 2.0 installed as well as Visual Studio 2005 (Visual C# Express 2005 can be used).  The sample project also references the XSI Crosswalk Importer assembly, which is installed to the ModTool installation directory.  Make sure this reference is properly set before compiling (the section titled ôPublishing The Model And Importing It Into The Content Pipelineö details this process).   <br />
<br />
<br />
<strong class='bbc'>Why Bother With Content Authoring Integration?</strong><br />
 If you scan through the rest of the article and see the amount of work involved, you may be wondering ôwhy should I even bother with this?ö  Or you may be thinking ôthis seems like overkill for my small project.ö  After all the XNA Framework is rather flexible, and itÆs perfectly feasible to find other ways to get content into your game that doesnÆt just use BasicEffect.  For example, the ShipGame starter pack uses a custom NormalMapping effect for all meshes.  And it does it in a very simple way: by simply ignoring the effect assigned to the mesh being rendered and using the NormalMapping effect instead.  This of course works, but has limitations: What if you donÆt want to use just one effect for everything?  What about effect parameters that arenÆt texture-based?  Should the artists be messing around with the code to get what they want?   <br />
<br />
Content authoring integration does not have these disadvantages.  Instead it has the following advantages: <br />
<br />
<ul class='bbc'><li>Artists can handle creation and importing of models without programmers getting involved </li><li>Artists can get a real-time preview of the model in the modeling application, allowing them to get what they want quicker </li><li>Every aspect of a modelÆs appearance is defined in the modeling tool, and completely contained in the model fileÆs data.  If a consistent material parameter interface is used as well, this allows you to greatly simplify your rendering code as it wonÆt need to handle any special cases ù all models are treated the same (this is a benefit even if youÆre a one-man-band: simple code is always better).</li></ul> <br />
<strong class='bbc'>Why XSI ModTool?</strong><br />
 When it comes to 3D modeling, 3D Studio Max and Maya are usually the first names to come up.  TheyÆre fantastic, full-featured applications and itÆs much more likely that a 3D artist is going to be familiar with one of them.  However they pose a huge problem for any hobbyist developer: they cost money ù a lot of money.  ModTool, on the other hand, is completely free for non-commercial use.  While there are other free tools available (such as Blender), ModTool is conveniently designed to be integrated with XNA Game Studio project.  Plus, it supports the ability to use real-time previewing of Direct3D effects with models, which is crucial for our content integration system. <br />
<br />
<br />
<strong class='bbc'>Implementation</strong><br />
 <br />
<strong class='bbc'>An Effect-Based Material System</strong><br />
 3D models have two important attributes weÆre concerned with: geometry and materials.  The geometry will determine the shape of the model, while the materials will determine what the surface of that geometry actually looks like.  For our content authoring pipeline, weÆre going to use Effects as primary building blocks for materials.  Each material effect will determine the basic type of material weÆre working with: some examples can include a basic texture-mapped surface, a normal-mapped surface, a reflective surface that uses an environment map, a surface with a fur shader, a metallic surface, a cel-shaded surface... whatever it is the actual game calls for.   <br />
<br />
Each material effect will have a set of artist-editable parameters, which can be tweaked in ModTool (in real-time) in order to further customize an effect.  In the actual effect these parameters are implemented as textures or as shader constants.    <br />
<br />
<br />
<strong class='bbc'>A Consistent Effect Interface</strong><br />
 One of the goals we laid out earlier was that we wanted our material effects to be interchangeable as far as our rendering code is concerned.  This means we donÆt want to have to treat any of our materials any differently: the code should be able to just set the shader constants it needs to set the same way for every effect.  To facilitate this, weÆre going to create a file containing the shader constants common to every effect and #include it in every material.  WeÆll call this file ômat_Common.fxhö, and it looks like this: <br />
<br />
 float4x4 g_matWorld; float4x4 g_matWorldInverse; float4x4 g_matView; float4x4 g_matProj; float3 g_vCameraPositionWS; float3 g_vLightAmbient; float3 g_vLightDirectionWS; float3 g_vDirectionalLightColor;  We have a few basic constants here: transform matrices used to transform vertices to the various coordinate spaces, the camera position in world-space, and ambient lighting color, the direction of a directional light in world-space, and the color of the directional light.  For now weÆll keep things simple and leave it at one directional light. <br />
<strong class='bbc'>A Normal-Mapping Shader</strong><br />
 As our first material type, weÆre going to implement a basic normal-mapping shader.  If youÆre not familiar with normal-mapping, it works by sampling a per-pixel normal value from a texture and using that value for lighting calculations.  This allows an otherwise flat surface to have the appearance of having much more geometry.  These normal values we sample from the texture are in tangent-space, which means in the vertex shader we transform the light direction and the view direction to tangent-space so that we can perform the lighting calculations.   <br />
<br />
Before we write our vertex shader and pixel shader, letÆs set up some parameters and textures.  For parameters weÆre going to need a specular color and power (glossiness), and for textures weÆre going to need a diffuse map and a texture map. <br />
<br />
 float3 g_vSpecularAlbedo; float g_fSpecularPower; texture2D DiffuseMap; sampler2D DiffuseSampler = sampler_state { 	Texture = ; 	MinFilter = anisotropic; 	MagFilter = linear; 	MipFilter = linear; 	MaxAnisotropy = 16; }; texture2D NormalMap; sampler2D NormalSampler = sampler_state { 	Texture = ; 	MinFilter = anisotropic; 	MagFilter = linear; 	MipFilter = linear; 	MaxAnisotropy = 16; };  For our vertex shader, we first need to set up our vertex inputs.  Models that are exported from XSI ModTool have a particular vertex format, which actually encodes the binormal and tangent in order to save space.  The inputs for our vertex shader look like this:  in float4 in_vPositionOS	: POSITION0, in float3 in_vNormalOS		: NORMAL0,   in float4 in_vColor0		: COLOR0,  in float4 in_vColor1		: COLOR1, in float2 in_vTexCoord		: TEXCOORD0, in float4 in_vTexCoord1	: TEXCOORD1, in float4 in_vTexCoord2	: TEXCOORD2, in float4 in_vTexCoord3	: TEXCOORD3, in float4 in_vTexCoord4	: TEXCOORD4, in float4 in_vTexCoord5	: TEXCOORD5, in float4 in_vTexCoord6	: TEXCOORD6, in float4 in_vTexCoord7	: TEXCOORD7  Now like I mentioned, we need to do some unpacking of our binormal and tangent.  The code for that looks like this:  // Calculate the tangent and binormal float3 vTangentOS = (in_vColor0 * 2) - 1;  float fSign = (in_vColor0.a * 2) - 1;  fSign  = (fSign > 0) ? 1 : -1;  float3 vBinormalOS = in_vNormalOS.yzx * vTangentOS.zxy;  Okay now wereÆ all set up and ready to code our shaders.  HereÆs the final mat_NormalMapping.fx file:  float3 g_vSpecularAlbedo; float g_fSpecularPower; texture2D DiffuseMap; sampler2D DiffuseSampler = sampler_state { 	Texture = ; 	MinFilter = anisotropic; 	MagFilter = linear; 	MipFilter = linear; 	MaxAnisotropy = 16; }; texture2D NormalMap; sampler2D NormalSampler = sampler_state { 	Texture = ; 	MinFilter = anisotropic; 	MagFilter = linear; 	MipFilter = linear; 	MaxAnisotropy = 16; }; void NormalMappingVS(	in float4 in_vPositionOS	: POSITION0,				     			in float3 in_vNormalOS		: NORMAL0,   			in float4 in_vColor0		: COLOR0,  			in float4 in_vColor1		: COLOR1, 			in float2 in_vTexCoord          : TEXCOORD0, 			in float4 in_vTexCoord1     	: TEXCOORD1, 			in float4 in_vTexCoord2     	: TEXCOORD2, 			in float4 in_vTexCoord3     	: TEXCOORD3, 			in float4 in_vTexCoord4     	: TEXCOORD4, 			in float4 in_vTexCoord5     	: TEXCOORD5, 			in float4 in_vTexCoord6     	: TEXCOORD6, 			in float4 in_vTexCoord7     	: TEXCOORD7, 			out float4 out_vPositionCS	: POSITION0, 			out float2 out_vTexCoord	: TEXCOORD0, 			out float3 out_vLightDirTS	: TEXCOORD1, 			out float3 out_vViewDirTS	: TEXCOORD2, 			out float3 out_vPositionWS	: TEXCOORD3 ) {   // Figure out the position of the vertex in clip space   out_vPositionWS = mul(in_vPositionOS, g_matWorld);   float4x4 matViewProj = mul(g_matView, g_matProj);   float4x4 matWorldViewProj = mul(g_matWorld, matViewProj);   out_vPositionCS = mul(in_vPositionOS, matWorldViewProj);   out_vTexCoord = in_vTexCoord;        // We need these in object space before converting to tangent space   float3 vLightDirectionOS = mul(-g_vLightDirectionWS, g_matWorldInverse);   float3 vCameraPosOS = mul(float4(g_vCameraPositionWS, 1.0f), g_matWorldInverse);        // Calculate the tangent and binormal   float3 vTangentOS = (in_vColor0 * 2) - 1;    float fSign = (in_vColor0.a * 2) - 1;    fSign  = (fSign > 0) ? 1 : -1;    float3 vBinormalOS = in_vNormalOS.yzx * vTangentOS.zxy;     	vBinormalOS = (-vTangentOS.yzx * in_vNormalOS.zxy) + vBinormalOS;    vBinormalOS = (vBinormalOS * fSign);   // Build the TBN matrix   float3x3 matTBN = float3x3(vTangentOS, vBinormalOS, in_vNormalOS);        // Convert to tangent space   out_vLightDirTS = mul(matTBN, vLightDirectionOS);   out_vViewDirTS = mul(matTBN, vCameraPosOS - in_vPositionOS.xyz);    }   float3 CalcLighting (	float3 vDiffuseAlbedo,  			float3 vSpecularAlbedo,  			float  fSpecularPower,  			float3 vLightColor,  			float3 vNormal,  			float3 vLightDir,  			float3 vViewDir	) {   float3 R = normalize(reflect(-vLightDir, vNormal));        // Calculate the raw lighting terms   float fDiffuseReflectance = saturate(dot(vNormal, vLightDir));   float fSpecularReflectance = saturate(dot(R, vViewDir));   if (fDiffuseReflectance == 0)   fSpecularReflectance = 0;   // Modulate the lighting terms based on the material colors, and the attenuation factor   float3 vSpecular = vSpecularAlbedo * vLightColor;   pow(fSpecularReflectance, fSpecularPower);   float3 vDiffuse = vDiffuseAlbedo * vLightColor * fDiffuseReflectance;       // Lighting contribution is the sum of ambient, diffuse and specular terms   return vDiffuse + vSpecular; } float4 NormalMappingPS( in float2 in_vTexCoord   : TEXCOORD0,                     	in float3 in_vLightDirTS : TEXCOORD1,                     	in float3 in_vViewDirTS  : TEXCOORD2,                     	in float3 in_vPositionWS : TEXCOORD3	) : COLOR0 {   // Sample the texture maps   float3 vDiffuseAlbedo = tex2D(DiffuseSampler, in_vTexCoord).rgb;   float3 vNormalTS = tex2D(NormalSampler, in_vTexCoord).rgb;   // Normalize after interpolation   vNormalTS = vNormalTS = 2.0f * (vNormalTS.xyz - 0.5f);   in_vLightDirTS = normalize(in_vLightDirTS);   in_vViewDirTS = normalize(in_vViewDirTS);   // Calculate the lighting term for the directional light   float3 vColor = CalcLighting( vDiffuseAlbedo,                                  g_vSpecularAlbedo,                                  g_fSpecularPower,                             	g_vDirectionalLightColor,                                  vNormalTS,                                  in_vLightDirTS,                                  in_vViewDirTS); 				       // Add in ambient term       vColor += vDiffuseAlbedo * g_vLightAmbient;									       return float4(vColor, 1.0f); } Technique Render { 	Pass 	{     	VertexShader = compile vs_2_0 NormalMappingVS();     	PixelShader = compile ps_2_0 NormalMappingPS();     	ZEnable = true;     	ZWriteEnable = true;     	AlphaBlendEnable = false;            } }  <br />
<strong class='bbc'>Setting Up SAS Annotations</strong><br />
 Okay so weÆve got our fancy normal-mapping shader now, and if we want we could use it to render some stuff in our XNA application.  But what about in ModTool?  If we used it as-is, ModTool would have no idea what to do without effect.  What parameters should be set by the user?  Which ones should be set automatically?  And to what values?  To make sure ModTool can make heads or tails of everything, we need to add some SAS (ôStandard Annotations and Semanticsö) annotations. <br />
<br />
WeÆll start off with the shader constants in mat_Common.fxh.  We said earlier that these are going to be the constants set by our rendering code, which means we donÆt want the artist to be messing with these.  Instead weÆll use annotations that tell ModTool what values to set there for us.  First for the matrices, we can use standard HLSL semantics to bind them to certain transforms: <br />
<br />
 float4x4 g_matWorld : WORLD; float4x4 g_matWorldInverse : WORLDINVERSE; float4x4 g_matView : VIEW; float4x4 g_matProj : PROJECTION;  For our lighting constants, we have to use some SAS annotations to specify what we want. Those annotations look like this:  float3 g_vCameraPositionWS < 	string SasBindAddress = "SAS.CAMERA.POSITION";  >; float3 g_vLightAmbient < 	string SasBindAddress = "SAS.AMBIENTLIGHT[0].COLOR"; >; float3 g_vLightDirectionWS < 	string SasBindAddress = "SAS.DIRECTIONALLIGHT[0].DIRECTION"; > = {1, -1, 1}; float3 g_vDirectionalLightColor < 	string SasBindAddress = "SAS.DIRECTIONALLIGHT[0].COLOR"; >;  WeÆre also going to add some SAS annotations to the material parameters to specify that they are artist-editable.  We can also specify some other information: the name of the parameter to be displayed, the type of UI control to use, and minimum/maximum values.  float3 g_vSpecularAlbedo  < 	string SasUiControl = "ColorPicker"; 	string SasUiLabel =  "Specular Albedo";     > =  {1.0f, 1.0f, 1.0f}; float g_fSpecularPower < 	string SasUiControl = "Slider"; 	string SasUiLabel = "Specular Power"; 	float SasUiMin = 1; 	float SasUiMax = 200;     > = 32.0f;   texture2D DiffuseMap < 	string ResourceType = "2D"; >; sampler2D DiffuseSampler = sampler_state { 	Texture = ; 	MinFilter = anisotropic; 	MagFilter = linear; 	MipFilter = linear; 	MaxAnisotropy = 16; }; texture2D NormalMap < 	string ResourceType = "2D"; >; sampler2D NormalSampler = sampler_state { 	Texture = ; 	MinFilter = anisotropic; 	MagFilter = linear; 	MipFilter = linear; 	MaxAnisotropy = 16; };  <br />
<strong class='bbc'>Setting Up Our Rendering Code</strong><br />
 Now weÆre ready to set up some code for rendering models in our game.  As promised, thanks to our consistent material effect interface, this is easy. <br />
<br />
 protected void RenderModel(Model model, Matrix modelTransform) { 	Matrix[] bones = new Matrix[model.Bones.Count]; 	model.CopyAbsoluteBoneTransformsTo(bones);          // Get camera matrices 	Matrix cameraTransform, viewMatrix, projMatrix; 	camera.GetWorldMatrix(out cameraTransform); 	camera.GetViewMatrix(out viewMatrix); 	camera.GetProjectionMatrix(out projMatrix);                for (int i = 0; i <: model.Meshes.Count; i++) 	{     	ModelMesh mesh = model.Meshes[i];     	Matrix worldMatrix = bones[mesh.ParentBone.Index];     	Matrix.Multiply(ref worldMatrix, ref modelTransform, out worldMatrix);     	Matrix worldInverseMatrix;     	Matrix.Invert(ref worldMatrix, out worldInverseMatrix);     	for (int j = 0; j < mesh.MeshParts.Count; j++)     	{         	ModelMeshPart meshPart = mesh.MeshParts[j];         	// If primitives to render         	if (meshPart.PrimitiveCount > 0)         	{             	// Setup vertices and indices             	GraphicsDevice.VertexDeclaration = meshPart.VertexDeclaration;             	GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer,                                                      meshPart.StreamOffset,                                                      meshPart.VertexStride);             	GraphicsDevice.Indices = mesh.IndexBuffer;             	// Setup the parameters for the sun             	Effect effect = meshPart.Effect;             	effect.Parameters["g_matWorld"].SetValue(worldMatrix);             	effect.Parameters["g_matWorldInverse"].SetValue(worldInverseMatrix);             	effect.Parameters["g_matView"].SetValue(viewMatrix);             	effect.Parameters["g_matProj"].SetValue(projMatrix);             	effect.Parameters["g_vCameraPositionWS"].SetValue(cameraTransform.Translation);             	effect.Parameters["g_vLightDirectionWS"].SetValue(sunLightDirection);             	effect.Parameters["g_vDirectionalLightColor"].SetValue(sunLightColor);             	effect.Parameters["g_vLightAmbient"].SetValue(ambientLight);             	// Begin effect             	effect.Begin(SaveStateMode.SaveState);             	effect.CurrentTechnique.Passes[0].Begin();             	// Draw primitives             	GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,                                                      meshPart.BaseVertex,                                                      0,                                                      meshPart.NumVertices,                                                      meshPart.StartIndex,                                                      meshPart.PrimitiveCount);             	effect.CurrentTechnique.Passes[0].End();             	effect.End();             	GraphicsDevice.Vertices[0].SetSource(null, 0, 0);             	GraphicsDevice.Indices = null;             	GraphicsDevice.VertexDeclaration = null;         	}     	} 	} }  <br />
<strong class='bbc'>Working With XSI ModTool</strong><br />
 <br />
<strong class='bbc'>Setting Up ModTool</strong><br />
 Make sure youÆve downloaded and installed <a href='http://www.softimage.com/downloads/XSI_Mod_Tool/default.aspx' class='bbc_url' title='External link' rel='nofollow external'>XSI ModTool</a>, along with both the latest patch as well as the CROSSWALK import/export system.  If this has been done, start up ModTool.  If youÆve never used ModTool before, you may want to perform some customizations.  This article will assume that youÆre operating in XSI Default mode (go to Modes->XSI Default).  You may also find it helpful to activate the main toolbar, which you can do by clicking on View->Optional Panels->Main Shelf.   <br />
<br />
ModTool works by connecting to an existing XNA project and creating an XSI project.  This XSI project contains a workspace which contains saved scenes, along with other data used by these scenes.  This project is created in a subfolder of the Content folder in your project folder, which means you can include this XSI project in your source control in order to have all artists share a common workspace.  To have ModTool connect to your project, click on XNA Game Studio->Connect To XNA Project.  In the dialog that appears, browse for the main folder that contains your project.  The dialog should say that a project has not been detected at this location, and that one will be created for you.  Close this dialog to let ModTool create the project. <br />
<br />
<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/XSIinXNA/fig1.png' alt='Posted Image' class='bbc_img' /></span>  <br />
<strong class='bbc'>Making A Model</strong><br />
 Now weÆre ready to make a model that will test out our new content authoring system.  First, click on XNA Game Studio->New XNA Scene to create a new scene.  Save it in the scenes folder of the new XSI project that was created in your Content folder.   <br />
<br />
Now that we have a scene, we can add a model to it.  We do this by going to XNA Game Studio->Create Model. You should get a cube mesh added to the scene when you do this. You can view this cube in several ways by switching the view mode, which you do by clicking one of the buttons in the bottom left corner of the screen.  <br />
<br />
<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/XSIinXNA/fig2.png' alt='Posted Image' class='bbc_img' /></span>  The default is Four Views, which is the top right button. This gives you four different views at a time. The three views in the top left, bottom left and bottom right are typically configured to give you an orthographic (2D) view from a certain direction. The top right view is typically configured to give a 3D view of the scene. Switch the top-right view to ôExplorerö mode (click on the bluish button that says ôCameraö and select Explorer). This view presents the scene graph for your current scene. The scene graph is a hierarchal representation of everything in the scene: meshes, lights, submeshes, etc. YouÆll see that you have your camera, 3 lights, and your model in the scene. If you expand the model node, youÆll see thereÆs a mesh in there: thatÆs our cube that you see in the views. We always want meshes to be part of a model, since anything thatÆs not part of a model wonÆt be exported when we publish the model to our project. Remember this if you ever add additional polygon meshes (you can add any mesh to the model by dragging it to the Model node).  <br />
<br />
<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/XSIinXNA/fig3.png' alt='Posted Image' class='bbc_img' /></span>  In order to use normal-mapping and other effects that require a tangent basis, we need to add tangents to the mesh. To do this, first select the polygon mesh by expanding the Model node and selecting the ôMeshö node. Now in the toolbar on the left side of the screen, change it to ôRenderö mode by clicking on the purple button on top that says ôModelö and then click on ôRenderö. Then click on the ôPropertyö button, and click on ôTangentö. Just leave the settings at default in the dialog that pops up. After you do this, there should be a new ôTangentö node under the Mesh node. <br />
<br />
Now we want to set up the lighting for our scene.  We designed our material effect to work with one single directional.  This means we canÆt use those point lights; go ahead and delete them from your scene.  Now add an Infinite Light to the scene: you can do this by clicking on the ôPrimitiveö button on the left side of the screen and then going to Light->Infinite. In the dialog that pops up, donÆt worry about anything except for the ôRGBö and Intensityö values in the ôColorö area. <br />
<br />
Once the light is added, we can position it and rotate it. Position of course doesnÆt matter for an Infinite Light, since theyÆre global light sources. Direction is what matters, and you can see the direction indicated by the arrow that points away from the light when you select it (you can select the light by clicking on it in the scene graph). To position it, go to translate mode by hitting ôVö, or by clicking on it in the main toolbar, or by clicking on the ôTö in the transform toolbar on the right side of the screen. Then you can drag it around in any of the views. To rotate it, go to rotation mode by hitting ôCö, by clicking on it in the main toolbar, or by clicking on the ôRö in the transform toolbar. You can then rotate it by dragging the mouse on one of the circles, which represent the 3 transform axes. If you need to get a better view of things, go to zoom and pan mode by hitting ôZö on the keyboard. You can then drag the mouse to move the view, zoom in by clicking the middle mouse button, or zoom out by clicking the right mouse button. If you have the top-right view set to Camera mode, you can also rotate the view by going to orbit mode (hit ôOö on the keyboard) and dragging the mouse. <br />
<br />
Go back to the normal ôSelection cursorö by clicking on the big arrow in the top left corner of the screen. Set it to object mode as well. Now select the cube by dragging and making a box that includes it (donÆt select the light). We can now manipulate it in the same way we manipulated the light previously. However for this tutorial, just leave it positioned and oriented where it is. You can also scale the cube: to do this, either go to scaling mode (hit ôXö on the keyboard, or click on the button in the main toolbar or the transform toolbar) and drag the mouse, or set a value directly next to the ôSö in the transform toolbar.  <br />
<br />
WeÆre now going to assign a material to the mesh. As we said earlier, a material is comprised of one of our material effects, some material parameters, and some textures. Together these all define what the surface of the mesh looks like, and how it responds to lighting. Make sure the mesh is selected, and then go to the Materials Manager by either clicking on ôMaterialsö in the left-hand toolbar or by going to View->Rendering/Texturing->Materials Manager. In here we have one material already made for us already, but we canÆt use it since it doesnÆt use a DX9 effect. Now weÆll make a new one: to do this, open up an explorer window and go where you saved your mat_NormalMapping effect.  With explorer on top, drag the .fx file right into the Material Manager wind&#111;w.  You should see a new material appear with the same name as the effect.  Double click on it to open up the material properties. On the first tab, we have some properties to play with. The first is the name: name it ôBrickö, since weÆre going to use a brick texture and normal map.  In the middle is the .fx file being used; leave that alone, itÆs already set up to use our effect (note that you can click on the ôReloadö button if you ever make changes to the .fx file). At the bottom are the shader properties we defined, complete with the names and controls we specified.  You can leave them at the default values for now. <br />
<br />
<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/XSIinXNA/fig4.png' alt='Posted Image' class='bbc_img' /></span>  Move over to the ôImagesö tab of the dialog. This is where we set textures for the effect. The dialog should be prompting for two textures: the diffuse map and the normal.  Click on the ônewö button to browse for a texture for each: set the diffuse map to ôBrick_Diffuse.pngö and the normal map to ôBrick_Normal.pngö.   We also need to set the texture space for each texture: next to where it says ôTexture Spaceö click on ôNewö, and then select ôUnique UVs (polymesh)ö. <br />
<br />
Now we have to assign this new material to our mesh. To do this, first make sure the mesh is selected. Then, assign the material by pressing the button that has a purple sphere with two arrows pointing at a cone (when you hover over the button, the tooltip should say ôAssign material to selected objects or clusters.ö) After this you can close the Material Manager.  <br />
<br />
<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/XSIinXNA/fig5.png' alt='Posted Image' class='bbc_img' /></span>  In order to see how our material actually looks, we need to turn on the DX9 real-time preview. First make sure the top-right view is set to ôCameraö mode. Then click where it says ôWireframeö and choose Realtime Shaders->DirectX9 from the dropdown. You should see the mesh in all its normal-mapped glory now. <br />
<br />
<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/XSIinXNA/fig6.png' alt='Posted Image' class='bbc_img' /></span>  <br />
<strong class='bbc'>Publishing The Model And Importing It Into The Content Pipeline</strong><br />
 To export a model from ModTool, go to XNA Game Studio->Publish Model. In the dialog that pops up, hit the ôàö button and browse to the content folder of your project. Pick a name for your model, then hit OK. Now click on ôConsolidate Images and FX Filesö, and then click OK (Consolidating images and files copies all textures to Content&#092;Textures, and effects to Content&#092;Effects).  You should now have an .xsi model in your Content folder. <br />
<br />
Before we can add this new model to the Content Pipeline, we need to add a reference to the Crosswalk content importer.  To do this, right-click on the Content project and go to the ôReference Pathsö tab.  Here you need to add a path to the Addons&#092;XNAGSE&#092;Application&#092;References&#092;XNA 2.0&#092; subfolder of your ModTool installation directory.  Then add a reference to the importer assembly by right-clicking on References and adding the ôXW4XNAö assembly.   <br />
<br />
Once youÆve added the importer, we can add the model to your project.  Right click on the Content project and click on Add->Existing Item....  Set the dialog to browse for ôall files(*.*)ö, and then navigate to the Content folder add your model.  Once the model is added, set it to use the Crosswalk Importer by right-clicking and going to Properties, and then selecting the correct importer in the dropdown.  Then set it to use the standard Model content processor. <br />
<br />
Now that the model is added to the Content project, we can load it in our code through the content pipeline. <br />
<br />
 protected override void LoadContent() { 	model = Content.Load("TestModel"); }  And finally, weÆre ready to run our game and see our model in action! <br />
<strong class='bbc'>Conclusion</strong><br />
 By integrating our effects and rendering code with XSI ModTool, weÆve created a Content Authoring pipeline that allows the artists to control their content all the way up to the step of adding it to the gameÆs Content project.  This allows both artists and programmers to adopt a streamlined workflow that keeps both groups focused on their main tasks, and also keeps rendering code simplified and data-driven.  The techniques used can also be extended to a full material library featuring effect types for a wide variety of rendering scenarios.  <br />
<br />
]]></description>
		<pubDate>Mon, 11 Aug 2008 11:31:52 +0000</pubDate>
		<guid isPermaLink="false">a3fc34dce15cda93287496c84af5203c</guid>
	</item>
	<item>
		<title>Hosting a C++ D3D engine in C# Winforms</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/hosting-a-c-d3d-engine-in-c-winforms-r2526</link>
		<description><![CDATA[<strong class='bbc'>Motivation</strong><br />
  <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/D3DCsharpWinform/screenshot.jpg' alt='Posted Image' class='bbc_img' /></span><br />
<br />
  So you have invested man-years of effort in your C++ D3D graphics/visualization/game engine. Now you want to build a nice GUI that utilizes this engine, such as a scene editor or modeler, but low and behold you are inundated by potential hosting solutions: MFC, wxWidgets, QT, Winforms, WPF. All with different challenges and subtleties.<br />
<br />
Back in the day I solved this problem with MFC. Microsoft has not yet abandoned MFC (given the recent release of MFC 9.0), but they have seemed to shift their GUI development focus to Winforms (and more recently WPF). Having spent considerable time struggling with MFC in the past, I have found Winforms’ ease of use, consistency of design, and community support, more than enough reason to switch.<br />
<br />
When adapting an existing engine to be hosted in Winforms, you must forgo creating your own window, and be able to attach to any given wind&#111;w. You must also be able to react to changes that window might undergo (loss of focus, minimization, resize, etc). Also keep in mind that your engine does not really own the window it is given, so changing properties of the window should be discouraged, as this may break Winforms’ management of that wind&#111;w.<br />
<br />
For this article I am going to adapt a small unmanaged C++ D3D9 engine to be hosted in a C# Winforms panel via a C++/CLI glue DLL (and I will then explain how to adapt this to a WPF app). The actual rendering engine is kept to an absolute minimum, as to not obscure the actual goal of the article. Also note that the techniques described in this article are not necessarily restricted to D3D, and can be adapted to OpenGL as well<br />
<br />
This article will be broken up into:<br />
 <ul class='bbc'><br /><li>Creating a simple D3D management class<br /></li><li>Hooking an HWND for messages<br /></li><li>Application specific derived class<br /></li><li>Exposing the derived class in a Win32 DLL<br /></li><li>Creating a C++/CLI wrapper DLL<br /></li><li>Utilizing the wrapper in a C# application<br /></li><li>Extracting an HWND from a panel control<br /></li><li>Setting up an efficient render loop<br /></li><li>What about WPF???<br /></li><li>Conclusion<br /></li></ul><br />
You can download the source code for this article <a href='http://downloads.gamedev.net/features/programming/D3DCsharpWinform/D3DContainerSrc.zip' class='bbc_url' title='External link' rel='nofollow external'>here</a><br />
<strong class='bbc'>Creating a simple D3D management class</strong><br />
I am not going to spend too much time explaining how to write a D3D9 rendering framework, but lets write a simple wrapper class to handle this for us. This class is very similar to the DXUT demo framework, only extremely simplified, and not able to handle full screen rendering.<br />
<br />
  class CD3DManager { public:	 	CD3DManager();	 	virtual ~CD3DManager();	 	HRESULT  Initialize(HWND hWnd, BOOL bRenderOnPaint, BOOL bHookWnd);	 	HRESULT  Shutdown();							   	HRESULT  Reset();	 	HRESULT  ProcessFrame();	 	HRESULT  Resize();	 	HRESULT  HandleW32Msg(HWND hWnd, UINT message,WPARAM wparam, LPARAM lparam); protected:	 	virtual HRESULT OnInit();	 	virtual HRESULT OnShutdown();	 	virtual HRESULT OnUpdate(double dTime, double dElapsedTime);	 	virtual HRESULT OnRender(LPDIRECT3DDEVICE9 pd3dDevice);	 	virtual HRESULT OnMsg(HWND hWnd, UINT message,WPARAM wparam, LPARAM lparam);	 	virtual HRESULT OnInitDeviceObjects(LPDIRECT3DDEVICE9 pd3dDevice);	 	virtual HRESULT OnRestoreDeviceObjects();	 	virtual HRESULT OnInvalidateDeviceObjects();	 	virtual HRESULT OnDeleteDeviceObjects(); };  Given an HWND we initialize our D3D device. When the device is lost we call Reset, when we wish to update and draw a frame we call ProcessFrame, and so on. We then add some virtual functions that a derived class will override to receive essential events it must handle.<ul class='bbc'><br /><li>OnInit: Called after the device has been initialized, a good place to load resources, and create objects<br /></li><li>OnShutdown: Called right before the device is about to be destroyed. Destroy or release what you created or loaded in OnInit<br /></li><li>OnUpdate: Update your simulation state<br /></li><li>OnRender: Render your frame<br /></li><li>OnMsg: Handle windows messages<br /></li><li>OnInitDeviceObjects: Handle initialization of device objects<br /></li><li>OnRestoreDeviceObjects: Handle restoration of device objects<br /></li><li>OnInvalidateDeviceObjects: Handle invalidation of device objects<br /></li><li>OnDestroyDeviceObjects: Handle destruction of device objects<br /></li></ul><br />
<strong class='bbc'>Hooking an HWND for messages</strong><br />
One of the issues with hosting your rendering display in a C# Winforms application is gaining access to the appropriate windows events that must be handled. For example the WM_RESIZE and/or WM_EXITSIZEMOVE message(s) must be handled with care, since resizing our host HWND requires a D3D device reset. There is also the potential of many more windows message we might want to handle.<br />
<br />
One approach is to add to the appropriate event delegate handler to our Winforms panel like this:<br />
<br />
  panel1.Resize += new EventHandler(myForm.Panel1_Resize);  One problem with this approach is that there are many events that Winforms does not expose in this manner. Another issue is that you might have existing input code that responds to raw windows messages (like I did). In light of this I have elected to use a low-level Win32 message hooking approach. Essentially we can monitor all messages a window produces, by replacing its WndProc with one of our own, then invoking its original WndProc. Like this:<br />
<br />
  BOOL CD3DManager::hookWindow( HWND hWndNew) {	 	m_bHookedWnd = TRUE;	 	//adds  HWND to a static map associating that HWND with this instance of D3DManager	 	addHWNDPtr(m_hDevWindow);  if(m_lpfnChildWndProc = (WNDPROC)SetWindowLong( m_hDevWindow, GWL_WNDPROC,	(LONG)RenderWndProc ) )			 	return TRUE;	 	return FALSE; } LRESULT CALLBACK CD3DManager::RenderWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {	 	LRESULT lRet = 0;	 	CD3DManager* pThis = getHWNDPtr(hwnd);	 	if(pThis==NULL)  return lRet;	 	switch(uMsg)	 	{	 	case WM_EXITSIZEMOVE:  pThis->Resize(); break;	 	case WM_PAINT:			 	if(pThis->m_bRenderOnPaint)  pThis->ProcessFrame(); break;	 	case WM_CLOSE:			 	pThis->unhookWindow(); break;	 	}	 	pThis->HandleW32Msg(hwnd,uMsg,wParam,lParam);	 	lRet = CallWindowProc(pThis->m_lpfnChildWndProc, hwnd, uMsg, wParam,lParam);	 	return lRet; }  One issue with overriding a window’s WndProc is that, the function itself is a static function of type CALLBACK, with no implicit <em class='bbc'>this</em> pointer sent along with it. There is no direct way of associating the system’s call to our WndProc (with a specific HWND), to a specific instance of our CD3Dmanager class. One way to accomplish this is through the use of a static map member variable that links a HWND to a CD3Dmanager*. Our WndProc is called and we use the given HWND to find the corresponding object instance. We add to this map via the supplied addHWNDPtr function and retrieve from this map via the getHWNDPtr function.<br />
<strong class='bbc'>Application specific code</strong><br />
Now CD3Dmanager by itself doesn’t actually do anything useful. We can derive from this class and override its virtual member functions with code specific to our application. The following code snippet defines a renderer that draws some dynamically updated text using a ID3Dfont.<br />
<br />
  class CD3DTestRender : public CD3Dmanager { … }; HRESULT CD3DTestRender::OnUpdate(double dTime, double dElapsedTime) {	 	m_Time = dTime;	 	m_FPS = 1.0 / dElapsedTime;	 	return S_OK; } HRESULT CD3DTestRender::OnRender(LPDIRECT3DDEVICE9 pd3dDevice) {	 	HRESULT hr;	 	// Clear the render target and the zbuffer		  ATTEMPT(pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff000000, 1.0f, 0) );	 	// Render the scene	 	if(SUCCEEDED( pd3dDevice->BeginScene()))	 	{			 	RECT rc;			 	TCHAR szInfo[256];			 	_stprintf(szInfo,_T("Time: %f&#092;nFPS: %f&#092;nRes: %d %d&#092;nMState:0x%x&#092;nMXY:%d %d"),			   	m_Time,m_FPS,m_uiWidth,m_uiHeight,m_dwMouseButtonStates,m_iMouseX,m_iMouseY);			 	SetRect(&rc, 10, 10, 0, 0 );			 	m_pFont->DrawText( NULL, szInfo, -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ));			 	ATTEMPT(pd3dDevice->EndScene());			 	ATTEMPT(pd3dDevice->Present( NULL, NULL, NULL, NULL ));	 	}	 	Sleep(10);	 	return S_OK; } HRESULT CD3DTestRender::OnInitDeviceObjects(LPDIRECT3DDEVICE9 pd3dDevice) {	 	m_pd3dDevice = pd3dDevice;	 	return  D3DXCreateFont(m_pd3dDevice,				// D3D device						   	12,					   	// Height						   	0,							// Width						   	FW_REGULAR,			   	// Weight						   	1,							// MipLevels, 0 = autogen mipmaps						   	FALSE,						// Italic						   	DEFAULT_CHARSET,			  // CharSet						   	OUT_DEFAULT_PRECIS,	   	// OutputPrecision						   	DEFAULT_QUALITY,			  // Quality						   	DEFAULT_PITCH | FF_DONTCARE,  // PitchAndFamily						   	L"Courier",			   	// pFaceName						   	&m_pFont);					// ppFont } HRESULT CD3DTestRender::OnRestoreDeviceObjects() {	 	return m_pFont->&#111;nresetDevice(); } HRESULT CD3DTestRender::OnInvalidateDeviceObjects() {	 	return m_pFont->OnLostDevice(); } HRESULT CD3DTestRender::OnDeleteDeviceObjects() {	 	SAFE_RELEASE(m_pFont);	 	return S_OK; }  <br />
<strong class='bbc'>Why expose the derived class in a Win32 DLL?</strong><br />
Now comes the task of exposing our derived class in a Win32 DLL. Why can’t we just stick all of this code into our C++/CLI DLL? Well we can, C++/CLI is real C++ code, just with some additions and a few not so obvious restrictions (like no inline assembly, no variable argument lists,..). When importing your derived class code into a C++/CLI project, be aware that your class will be compiled as managed code, and there might be performance penalties (as for how much, that is up for debate).<br />
<br />
At some point I attempted to import a large C++ code base into a C++/CLI project, and came across a number of problems with the acceptance of my own code and the code of third parties as valid C++/CLI code. I am sure there are ways around these problems, but for this article I elected to wrap my C++ code into an unmanaged Win32 DLL, for use by the C++/CLI DLL. This Win32 DLL will now run in an unmanaged environment and not suffer any performance penalties.<br />
<br />
Given the simplicity of the given CD3Dmanager and CTestRenderer classes, they could have been placed directly in the C++/CLI project, but for illustrative purposes I am using this Win32 DLL.<br />
<br />
To accomplish this, create a new Win32 DLL project in Visual Studio, and add the code for our CD3Dmanager and CTestRenderer classes. To expose our classes and their public member functions from the DLL, we can prepend this define to our class declarations:<br />
<br />
  #ifdef _EXPORTING #define CLASS_DECLSPEC	__declspec(dllexport) #else #define CLASS_DECLSPEC	__declspec(dllimport) #endif  Like so:  class CLASS_DECLSPEC CD3Dmanager …  class CLASS_DECLSPEC CD3DTestRender : public CD3Dmanager …  Where _EXPORTING is defined when building the DLL, and not defined when using the DLL.<br />
<strong class='bbc'>Creating a C++/CLI wrapper DLL</strong><br />
Now how do we expose our fancy C++ engine DLL to our equally fancy C# Winforms application? Well there are many ways: pInvoke, SWIG, COM, etc. But the way I prefer is a C++/CLI DLL. With C++/CLI, exposing a class for usage in a C# application is as simple as declaring it as a ref class, like so:<br />
<br />
  class CD3DTestRender;  public ref class D3DWrap { public:	 	D3DWrap();	 	~D3DWrap();	 	HRESULT  Initialize(IntPtr hWnd);	 	HRESULT  Shutdown();	 	HRESULT  ProcessFrame();	 	HRESULT  Resize(); protected:	 	CD3DTestRender* m_pRenderer; };  As long as the public member functions of D3DWrap take valid .NET types everything is as right as rain. Your private and protected members can do anything their C++ hearts desire. Also make sure not to expose any header files that C# might take offense to. I forward declare my CD3DTestRenderer class and keep a protected pointer to an instance of it. The associated .cpp file is where I actually include D3DTestRenderer.h. Then we import the D3DEngine.dll for use by linking with the stub .lib file generated when we built it. The D3Dwrap implementation merely creates and destroys an instance of CD3DTestRenderer and forwards the function calls, but we can do much more if we like. This is also the class where we would add functions that our Winforms code would call to manipulate our internal C++ engine state.<br />
<br />
<br />
<strong class='bbc'>Utilizing the wrapper in a C# application</strong><br />
Ok now that we have our C++/CLI DLL (D3DWrap.dll), using it in our C# application is trivial. Simply right click on the Reference subfolder of the C# project (under the Solution Explorer view of Visual Studio) and add a reference to our new DLL. We can then allocate an instance of D3DWrap in our form (or anywhere we like) like so:<br />
<br />
  m_D3DWrap = new D3DWrap();  <br />
<strong class='bbc'>Extracting an HWND from a panel control</strong><br />
To initialize our engine we have to supply it with an HWND. The panel we wish to draw to is nothing more than a high-level wrapper on a Win32 window, of which we can attain a HWND. To extract a HWND from a Winforms panel and pass it to our initialization, we do this:<br />
<br />
  m_D3DWrap.Initialize(panel1.Handle); //in our C# m_pRenderer->Initialize((HWND)(hWnd.ToPointer()),TRUE,TRUE); //in our C++/CLI  <br />
<strong class='bbc'>Setting up an efficient render loop</strong><br />
Setting up an efficient render loop in a C# Winforms application is actually non-trivial, and has been hotly debated for some time. The technique I am using was developed by Tom Miller and presented in <a href='http://blogs.msdn.com/tmiller/archive/2005/05/05/415008.aspx' class='bbc_url' title='External link' rel='nofollow external'>his blog</a>.<br />
<br />
MFC used to have a virtual member function you could override called OnIdle that would be called continuously in a loop when there were no windows messages to process. This was the ideal place for the update and draw functions of a rendering framework to be called.<br />
<br />
Winforms, on the other hand, does not supply such a function. Instead we only have the Idle event that is pulsed when our application goes into and out of an idle state. So how do we draw on the equivalent of MFC’s OnIdle? The basic gist of the technique is to loop (in the handler for the Idle event) on the condition that there are no waiting messages to be processed, by using a low-level PeekMessage to test that criteria. It's actually quite clever, and you can refer the link provided for a more in depth explanation.<br />
<br />
There are also many situations where you would not wish to draw on idle, and would rather just draw when the user manipulates the scene (such as in a modeler). Instead of placing your call to ProcessFrame in the idle loop we could just as well place it in the response to a WM_PAINT message.<br />
<br />
<br />
<strong class='bbc'>What about WPF???</strong><br />
WPF (Windows Presentation Foundation) is Microsoft’s new(ish) wiz bang GUI platform, simultaneously providing a potential replacement for Winforms, GDI+, Adobe Flash (Silverlight), and much more. With the release of Visual Studio 2008, a fully integrated WPF forms editor was finally introduced, making it a viable choice for GUI development. Some might argue that it was viable before the release VS 2008, but without that beautiful forms editor, I would beg to differ. Much deserved attention has been lavished on WPF recently, but in my opinion it is still incomplete and immature in comparison to Winforms (which Microsoft plans to support and actively develop for some time). However, many people are indeed migrating to WPF, so for them has this article been in vain? Nope!!<br />
<br />
The funny thing about WPF is that unlike previous incarnations of Microsoft GUI APIs, controls are no longer actually windows! Luckily, Microsoft has left in a backdoor for those of us that need a HWND to get anything useful done. HwndHost is a WPF control that actually exposes an HWND. An HwndHost (or its derived class WindowsFormsHost) can be placed into a form, from which we can attain our much needed HWND, and everything should just work as it did before.<br />
<br />
<br />
<strong class='bbc'>Conclusion</strong><br />
With a little effort, drawing your D3D scene into a control of a .NET application can be quite straightforward. Adding the advanced GUI capabilities of Winforms or WPF to your rendering application can be enormously beneficial, be it a game engine, a scientific visualization, or even a simple graphics technique demo (with all their wonderful adjustable parameters).]]></description>
		<pubDate>Tue, 17 Jun 2008 11:11:33 +0000</pubDate>
		<guid isPermaLink="false">fef873297a8a4a4bc01ca5f2df08eeba</guid>
	</item>
	<item>
		<title>Cubic Shadow Mapping in Direct3D</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/cubic-shadow-mapping-in-direct3d-r2457</link>
		<description><![CDATA[As GPUs grow faster, GPU friendly algorithms become more popular. Thus shadow mapping, compared with other shadowing techniques, is probably the most widely used technique for generating shadows. This article will explore the basics of implementing shadow mapping for Omni-directional lights and provides some theories for optimizing and improving the technique. Since there are different approaches and methods, I will not attempt to deal with the details of optimization. Also, it's assumed that the reader is familiar with basic shadow mapping technique and the basics of C++ and Direct3D.<br />
<br />
 <br />
<strong class='bbc'>The Algorithm</strong><br />
 To enable comparison of normal shadow mapping with shadow mapping for Omni-Directional lights, I will represent the basic shadow mapping algorithm for spot lights so you can compare these methods. Shadowing using spot lights consists of two major steps (or passes):<br />
<br />
 <ul class='bbcol decimal'><li>Placing a camera on the spot-light's position and rendering the scene depth from the spot light's point of view to a single component texture(preferably a floating point) </li><li>Using the resulting depth texture(shadow map) for depth comparison by means of projective texturing</li></ul> Shadowing for Omni-Directional lights also consists of two steps, but some simple modifications should be applied to the spot-light shadow mapping algorithm: <ul class='bbcol decimal'><li>Place a camera on the omni light's position and render the scene depth six times, storing depth values in six faces of a cube map. Each time the view vector of the camera should be toward one of these directions: positive X, negative X, positive Y, negative Y, positive Z and negative Z. This is almost identical to generating a cube map for environment mapping except that here we store depth values instead of color. </li><li>Use the resulting cube texture (cubic shadow map) for depth comparison by means of environment mapping.</li></ul> As you can see, there are two differences in the aforementioned algorithms: first of all, we should create our shadow map in six passes. Secondly, we use environment mapping instead of projective texturing in the second step. Now that we have a brief understanding of the basic algorithm, we can jump to implementation and get into more details. <br />
<strong class='bbc'>Implementation</strong><br />
 I will divide the implementation into three steps:<br />
<br />
 <ul class='bbc'><li>Initialization </li><li>Rendering scene depth to the cubic shadow map </li><li>Rendering the Scene using the cubic shadow map</li></ul> <br />
<strong class='bbc'>Step 1: Initialization</strong><br />
 The initialization part is pretty simple. There are five tasks in this part but I will cover the second and the third ones since others are not in the scope of this article (the accompanying source code covers all parts):<br />
<br />
 <ul class='bbc'><li>Initialize Direct3D </li><li>Create a cube texture to be used as cubic shadow map and retrieve all six surfaces of it </li><li>Create a virtual camera (to be placed at the light's position for rendering the scene's depth) </li><li>Load effects </li><li>Load meshes</li></ul> The following code snippet is used for creating the cubic shadow map:  m_pd3dDevice->CreateCubeTexture(m_iCubeFaceSize, //cube face edge length                                  1, //mip levels                                  D3DUSAGE_RENDERTARGET,                               	D3DFMT_R32F, //could be D3DFMT_R16F                                  D3DPOOL_DEFAULT,                               	&m_pCubicShadowTex,                               	NULL);  The next thing to do is to get all six surfaces of our cubic render target. This is necessary since we are going to use the SetRenderTarget() function in order to render to each face. For the positive X face of the cube map the following C++ code will do the trick:  cubicShadowMap->GetCubeMapSurface(D3DCUBEMAP_FACE_POSITIVE_X, 0, &depthCubeFacePX);  For other faces we should change the first argument depending on the cube face we want retrieve its surface and pass its corresponding Direct3D surface to the function. (So we will need a cube texture and six surfaces for each light we use in our scene) Initializing the virtual camera is trivial; the only point to keep in mind is to create a projection matrix with a field of view (FOV) of 90 degrees and initialize the aspect ratio with 1.0f. The following code uses D3DXMatrixPerspectiveFovLH for creating a projection matrix with a FOV of 90 degrees and an aspect ratio of 1.0.<br />
<br />
  D3DXMatrixPerspectiveFovLH( &m_ProjMat, D3DX_PI / 2.0f, 1.0f, 1.0f, 500.0f);  <br />
<strong class='bbc'>Step 2: Rendering to the cubic shadow map</strong><br />
 In order to render the scene's depth to the cubic shadow map, we will use the virtual camera described in the previous section. The direction of this camera will change every pass, looking at positive X, negative X, positive Y, etc. which means for each pass we should change the view vector of the camera and update the view matrix accordingly.<br />
<br />
  <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/cubicd3d/fig1.jpg' alt='Posted Image' class='bbc_img' /></span><br />
<em class='bbc'>Figure 1: Light's camera in six directions for rendering the scene's depth to cubic shadow map</em><br />
<br />
  Thus, for the first pass we should:<br />
<br />
 <ul class='bbcol decimal'><li>Set up the camera looking at the positive X axis </li><li>set the render target to the corresponding cube face acquired in the initialization step and clear it </li><li>Render scene depth (just like rendering depth in spot-light shadow mapping)</li></ul> For the second pass: <ul class='bbcol decimal'><li>Set up the camera looking at the positive Y axis </li><li>set the render target to the corresponding cube face acquired in the initialization step and clear it </li><li>Render scene depth</li></ul> And so on. Rendering the scene depth to the cubic shadow map faces is identical to normal shadow mapping, for we are using a camera and our target is a 2D floating-point texture. Here is the vertex shader that will do the job for this part:<br />
<br />
  VS_OUTPUT_DEPTH depthMap_VS( float4 inPosition : POSITION ) {   VS_OUTPUT_DEPTH output;        float4 positionW = mul( inPosition, worldMat );   output.oPositionLight = mul( inPosition, worldViewProjMat );        output.lightVec = lightPosition - positionW.xyz;   return output; }  The pixel shader will just compute the length of light vector using HLSL's intrinsic function, length(), and outputs the result to flow down the pipeline. The following C++ code will do the job for the second step of implementation:<br />
<br />
  //enable red channel for color write m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE , D3DCOLORWRITEENABLE_RED ); m_pShadowEffect->m_pEffect->SetTechnique(m_pShadowEffect->m_DepthMapHandle); m_pShadowEffect->m_pEffect->Begin(&numOfPasses, NULL); //render the scene depth to positive X side of the cube map createCamForPositiveX(); //a helper function for setting up the light's camera looking toward positive X axis renderDepthToCubeFace(depthCubeFacePX); //render the scene depth to positive Y face of the cube map createCamForPositiveY(); renderDepthToCubeFace(depthCubeFacePY); //render the scene depth to positive Z face of the cube map createCamForPositiveZ(); renderDepthToCubeFace(depthCubeFacePZ); //render the scene depth to negative X face of the cube map createCamForNegativeX(); renderDepthToCubeFace(depthCubeFaceNX); //render the scene depth to negative Y face of the cube map createCamForNegativeY(); renderDepthToCubeFace(depthCubeFaceNY); //render the scene depth to negative Z face of the cube map createCamForNegativeZ(); renderDepthToCubeFace(depthCubeFaceNZ); m_pShadowEffect->m_pEffect->End(); //enable color writes m_pd3dDevice->SetRenderState(D3DRS_COLORWRITEENABLE,                           	D3DCOLORWRITEENABLE_ALPHA |                           	D3DCOLORWRITEENABLE_RED |                           	D3DCOLORWRITEENABLE_GREEN |                           	D3DCOLORWRITEENABLE_BLUE);  Where renderDepthToCubeFace(…) and createCamFor***() functions are:  void CCubicShadowMapping::renderDepthToCubeFace(LPDIRECT3DSURFACE9 inCubeFaceSurface) {   D3DXMATRIXA16 worldViewProjMat;      //set and clear the cube map face surface   if(SUCCEEDED(m_pd3dDevice->SetRenderTarget( 0, inCubeFaceSurface )))   { 	m_pd3dDevice->Clear(NULL, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, NULL);   }      //render all geometries of the scene(assuming that there is no scene management or frustum culling algorithm) } void CCubicShadowMapping::createCamFor***() {   m_pLightCamera->setLook(/*m_PositiveLookX for example*/);   m_pLightCamera->setUp(/*m_PositiveLookY for example*/);   m_pLightCamera->setRight(/*m_NegativeLookZ for example*/);   //update the camera's concatenated view-projection matrix with new look, up and right vectors   m_pLightCamera->updateViewProjMat(); }  Note that since we have an R32F texture format and only the red channel is used, it's almost essential that we disable color writes except for the red channel when we render scene depth to our cube texture. Because cubic shadow maps are large textures, we need to consider fill-rate issues when using this technique. For example, a cubic shadow with an edge size of 512 pixels, occupies (6 faces * 262,144 pixels * 32 bits = 6144KB) in video memory. This is why there are several optimization techniques for implementing the first part of the technique (creating the cubic shadow map). You can refer to the "Optimization" part to get familiar with these performance improvement techniques. <br />
<strong class='bbc'>Step 3: Rendering the Scene using cubic shadow map</strong><br />
 Having the cubic shadow map, it's time for implementing the final step which will do the depth comparison of each pixel with the corresponding pixel in our cube map. If the depth of the current pixel is greater than the depth sampled from the cubic shadow map, then the pixel is in shadow, otherwise it's lighted. As mentioned in the algorithm, the only difference is we sample a cube map instead of sampling a 2D texture using projective texturing.<br />
<br />
 Sampling a cube texture requires a three component vector. For this, we use the reverse of the light's direction vector which is a vector originating at the light's position pointing to the current pixel. Remember that when we where rendering the depth of each pixel to the cube map, we used the length of light vector as our depth factor. So here we will do the same thing for depth of the current pixel and sample our cube map in order to do the depth comparison. The following HLSL code is a function extracted from the effect which will compute the lighting and shadowing of the scene:<br />
<br />
  lightFuncOutput LightPointSH(float3 inObjPos,                           	float3 inNormal,                           	float3 inCam2Vertex) {   lightFuncOutput output;   output.diffuseResult = float4(0.0f, 0.0f, 0.0f, 1.0f);   output.specularResult = float4(0.0f, 0.0f, 0.0f, 1.0f);   float4 PLightDirection = 0.0f;   PLightDirection.xyz = lightPosition.xyz – inObjPos ;//inObjPos is the pixel's position in world space   float distance = length(PLightDirection.xyz(; //the depth of current pixel   PLightDirection.xyz = PLightDirection.xyz / distance;   //compute attenuation factor   PLightDirection.w = max(0, 1 / (lightAttenuation.x +                            lightAttenuation.y * distance +                            lightAttenuation.z * distance * distance) );   //sample the cubic shadow map using the inverse of light direction                float shadowMapDepth = texCUBE(cubeShadowMapSampler, float4(-(PLightDirection.xyz), 0.0f)).x;   //do the depth comparison   if(distance > shadowMapDepth)    {          return output;//the pixel is in shadow so only the ambient light is visible to eye    }                else   {            //the pixel is not in shadow so the phong lighting is applied 	float3 floatVecTmp = normalize(inCam2Vertex + PLightDirection.xyz (; 	output.diffuseResult = PLightDirection.w * lightDiffuse * max(0, dot(inNormal, PLightDirection.xyz)); 	output.specularResult = PLightDirection.w * lightSpecular * pow(max (0, dot(inNormal,  floatVecTmp) ), specPower); 	return output;   } }  And finally the vertex and pixel shader of this step is as follows:  VS_OUTPUT cubicShadowMapping_VS(float4 inPosition  : POSITION,                             	float3 inNormal    : NORMAL) {   VS_OUTPUT output;   float4 positionW = mul(inPosition, worldMat);   output.cam2Vert = (eyePosition - positionW).xyz;    output.position = mul(inPosition, worldViewProjMat);   output.worldPos = positionW.xyz;   output.normalW = mul(inNormal, worldMat).xyz;   return output; } float4 cubicShadowMapping_PS(VS_OUTPUT In) : COLOR0 {   lightFuncOutput lightResult;   float3 normal = normalize(In.normalW);   float3 cam2Vert = normalize(In.cam2Vert);   lightResult = LightPointSH(In.worldPos, normal, cam2Vert);   float4 ambient = materialAmbient * globalAmbient;   float4 diffuse = materialDiffuse * lightResult.diffuseResult;   float4 specular = materialSpecular * lightResult.specularResult;   float4 lightingColor = (ambient + (diffuse + specular));   return lightingColor; }   <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/cubicd3d/fig2.jpg' alt='Posted Image' class='bbc_img' /></span><br />
<em class='bbc'>Figure 2: The final results for an omni-directional light</em><br />
<br />
  <br />
<strong class='bbc'>Optimization</strong><br />
 The technique presented in this article is the most basic shadow mapping technique for omni-directional lights. There are several optimization and quality improvement techniques which will help the basic technique to run faster and achieve accurate results. This part will help you to get a brief understanding of these techniques but will not give details of implementation, since doing so will make this article a book on shadow mapping! With that in mind, here are some techniques you can do some research &#097;bout:<br />
<br />
 <ul class='bbc'><li>The first thing that comes to mind is frustum culling. Remember that we had to render the scene six times in order to fill our depth cube map. Thus, applying frustum culling will help a lot to reduce draw calls. </li><li>The second is to reduce rendering passes of the first step as much as possible; In other words, not rendering the faces of the cubic shadow map. The depth rendering step requires six cameras, but what if the frusta of these cameras are not inside the frustum of our main camera or there are only three visible frusta, for instance. In these cases we can skip rendering, because if one of the light's frustums is not visible then the shadow it generates is not visible. This technique is easy to implement and has great impact on improving the rendering performance. </li><li>The third is to cull shadow casting objects. For this, we should create a virtual cone covering both the light and the shadow caster with its narrow side based on the light's position. Then we can perform frustum culling on this cone and decide whether the shadow caster is visible or not. If you are wondering why we use a cone instead of simply culling casters against the frustum, it's because doing so will prevent popping shadows into view. </li><li>The fourth is to define a scissor rectangle that represents the region of the screen affected by light and use the hardware's scissor test to reject any pixels that are not affected by light. This technique is also easy to implement and improves the performance vastly, for each omni-light that we place in our scene has a limited range and processing pixels beyond this range is vain. </li><li>The fifth is to use hardware shadow mapping which has been available via NVidia GeForce3 and above. Using hardware shadow mapping has several benefits such as less memory bandwidth consumption, no color buffer writes and hardware accelerated depth-only writes. Using hardware shadow mapping for normal shadow mapping is trivial but since we are using a cube texture for our depth map we cannot directly implement this technique for omni-light shadow mapping. This is because shadow depth textures (D24, D16) do not support cube textures but that doesn't mean we cannot use hardware shadow mapping with cubic shadow mapping. The solution is to merge all six faces of the cube map in a large depth texture and use special addressing techniques to sample Texels from this texture. In other words, we treat this texture as a cube map by converting our three component texture coordinate vector to a two component one for sampling this texture which is called "VSDCT" or "Virtual Shadow Depth Cube Texture".</li></ul> <br />
<strong class='bbc'>The Source code</strong><br />
 There are a few notes I'd like to mention about the <a href='http://downloads.gamedev.net/features/programming/cubicd3d/source%20code.zip' class='bbc_url' title='External link' rel='nofollow external'>source code</a> of this article:<br />
<br />
 <ul class='bbc'><li>The source code is NVidia PerfHUD ready. So feel free to explore the pipeline (if you have video card that is compatible with the program) and see the visualization of the algorithm in real-time. Also you can find performance intensive parts of the algorithm and maybe come up with new ideas. </li><li>The source code is not optimized (neither the C++ nor the HLSL code) so you can add the code for optimization techniques described earlier.</li></ul>  <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/cubicd3d/fig3.jpg' alt='Posted Image' class='bbc_img' /></span><br />
<em class='bbc'>Figure 3: The sample application ran with NVidia PerfHUD</em><br />
<br />
  <br />
<strong class='bbc'>References</strong><br />
 <ul class='bbcol decimal'><li>Gerasimov and Philipp. Omnidirectional Shadow Maps. In GPU Gems, Addison-Wesley. Pages 193-203, 2004. </li><li>G king and W Newhall. Efficient Omnidirectional Shadow Maps. In ShaderX3: Advanced Rendering with DirectX and OpenGL, Charles River Media. Pages 435-448, 2004.</li></ul> <br />
<strong class='bbc'>About me</strong><br />
 I am a senior student of software engineering in Azad University of Tehran(Central Branch) and have been a freelance graphics programmer for almost five years. Also, as a researcher in Shahid Rezayi Research Center(Sharif University), I have contributed in several simulation projects focusing on Graphics Programming and Rendering Techniques for two years.<br />
<br />
 Thank you for reading this article. If you have any doubts, questions or comments, please feel free to mail me at <a href='mailto:Ehsan_the_tiamat@yahoo.com' title='E-mail Link' class='bbc_email'>Ehsan_the_tiamat@yahoo.com</a><br />
<br />
]]></description>
		<pubDate>Tue, 05 Feb 2008 11:52:02 +0000</pubDate>
		<guid isPermaLink="false">842efe847039f0f979d17167a42f1acd</guid>
	</item>
	<item>
		<title>The Future of PC Gaming – The Possibilities of...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/the-future-of-pc-gaming-%e2%80%93-the-possibilities-of-r2316</link>
		<description><![CDATA[

<p>APRIL 24, NEW YORK &#8211; The excitement was palpable as Will Willis, Senior PR Manager for ATI Technologies, Inc., opened the door into the suite at the W Hotel in Times Square where the company
was giving a <a href="http://downloads.gamedev.net/features/programming/atid3d10/ATI-TheFutureofPCGaming.pdf"><strong>preview presentation</strong></a> under the ostentatious title, "The Future of PC
Gaming &#8211; The Possibilities of DirectX 10." Dominating the wall that immediately came into view as the door opened was a simply mammoth flat-screen HDTV hanging on the wall, with the oh so
familiar Windows XP desktop on display. Palpable anticipation&#8230;</p>
<p>I turned to receive introductions and warm handshakes to Guennardi Rigeur, a Senior ISV Engineer, and Bob Drevin, who has the fascinating title "ATI Fellow," and who has the aura of an evangelist
&#8211; which I quickly discover is about right. Bob explains that he helps craft ATI's technology directions and is a representative for the company to Microsoft's DirectX architectural group.
Guennardi then tells me that he and other ISV Engineers often spend time with game developers on site at their studios, working on production code and helping them squeeze every last bit of
performance out of the company's GPUs. Which provides the ideal segue into the substance of this session.</p>
<p>We begin with a discussion of the limitations inherent in DirectX 9, specifically in Direct3D. Guennardi explains that the API as it currently stands is "batch limited." "You can only perform so
many operations within the allotted frame time, because of the amount of overhead inherent in state changes, texture unit access and so on, as well as the organization of the vertex and pixel
shaders." By way of explanation, he shows me a slide in which the vertex shader is heavily loaded while performing geometry operations but the pixel shader is virtually idle, and then the load is
inverted when framebuffer operations are being performed. The fundamental limitations in terms of access to computing resources, he explains, are limiting what developers can do &#8211; forcing them
to continue to bring a "false reality" to life.</p>
<p>Guennardi is referring to the variety of mathematically inaccurate models for environmental effects and objects that are used as "good enough" approximations for the real thing, due to the
inability of current hardware to keep up with full simulations. Or, at least, that's what I thought.</p>
<p>Bob takes over, talking about ATI's objective of eliminating the DX 9 constraints and solving the small batch problem &#8211; reducing the overhead associated with operations such that more
operations can be performed in each batch, to the point where accurate mathematical models can power our simulations. The challenge, he explains, is balancing the diverse needs of vertex and pixel
processing, which seem to be orthogonal at best, if not anti-parallel. In a sense, Bob expounds, "things are about to get worse&#8230; in the hopes of getting better."</p>
<p>And then he really gets into his element, letting out his inner technology evangelist, and before I know it I've drunk the Kool-Aid and I'm seeing happy-happy joy-joy images of developers
frolicking in glorious rendered fields of Direct3D 10 goodness. Bob introduces me to the Unified Shader Architecture.</p>
<p>"Current shader architectures use fairly different approaches for the vertex and pixel shader units, and this is reflected in their supporting different operations and sometimes requiring
different techniques to program. With Direct3D 10, all shader units support the same basic operations and use the same syntax." In addition, Guennardi chips in to tell me about optimizations to the
low-level graphics driver such that shader development no longer necessitates the use of assembly language. "Everything can be done in HLSL," he gushes. "<i>Almost</i> everything," Bob corrects. I
make the analogy to contemporary use of high(er)-level languages like C or C++ with only occasional use of assembly for machine-specific extensions (such as SSE3) and they both eagerly seize and run
with it. The driver analyzes the bytecode produced by the runtime and generates optimized opcodes for the specific hardware, a process I compare to just-in-time (JIT) compilation and which Guennardi
is quite pleased with.</p>
<p>Bob continues, "This is the Unified Shader Architecture, and it enables us to do a lot of really cool things that were just really difficult and tedious before, stuff that was either being
bus-limited or CPU-limited but is now possible because of how we've been able to reorganize the GPU's internal architecture." Now all shader units can fetch textures or access vertex memory, and some
operations can be shifted from one unit to another &#8211; some operations are, in essence, shader unit agnostic. As a consequence, an executive process running on the GPU known as Arbitration that
decides what gets to execute next can avoid stalls by determining that the next several operations are not dependent on the result of a block unit, perhaps waiting on I/O. I say that it's like having
a spare CPU, except that it's sort of running on the GPU.</p>
<p>Bob likes the analogy. "We actually have the unified shader architecture running on a production system already &#8211; in the Xbox 360, with the custom GPU we designed for that. It's allowed
developed for the 360 to do all sorts of cool stuff, and we'll get into that in a minute." He takes a minute to point out, however, that the Unified Shader Architecture is not a requirement of the
Direct3D 10 specification. Rather, "the specification is written in such a way that encourages and is compatible with the Unified Shader Architecture. This is just ATI's take &#8211; and just a first
take at that, and you'll see some of the amazing stuff we've been able to do with it. Essentially, the Direct3D 10 'refresh' of the API presents an opportunity for a more natural mapping to the
capabilities of the underlying hardware."</p>
<p>And now for some demos. Guennardi takes over the keyboard and mouse from Will and first tempers my expectations by reminding me that what I will be shown is actually running on current-generation
hardware. "It's an X1900. What we've done is take the pixel shader unit and run everything in a Direct3D 10-like fashion on it &#8211; vertex shader, geometry shader, pixel shader."</p>
<p>"Essentially, you're emulating the Unified Shader Architecture on just the pixel shader?" I ask.</p>
<p>"Exactly."</p>
<p>Returning to a point made earlier, one of the real upsides to the D3D 10 API refresh, and to the Unified Shader Architecture, at least in Bob's and Guennardi's eyes, is that it offloads a number
of tasks from the CPU, making more cycles available for artificial intelligence and to otherwise create more immersive, interactive worlds. "With the Unified Shader Architecture, and specifically
with the geometry shader, we can do a lot of things purely on the GPU that used to require CPU involvement, like collision detection." I believe I took a minute here to gather my jaw from the floor.
Collision detection on the GPU?! I am incredulous, and Guennardi clearly enjoys my enthusiasm, while I may remember Will and Bob high-fiving themselves in the background. Or not.</p>
<p>Guennardi shows me a prairie-like environment with shrubbery, a fire and smoke billowing and being blown about by the wind. He pans and zooms around, showing how the smoke particles interact with
the polygons of the vegetation without experiencing planar clipping. The visual simulation is virtually seamless, and it's all running on the GPU.</p>
<p>Next, he shows a large space populated with a crowd of about 10,000 textured and animated characters milling about, performing somersaults and flying kicks, running around and generally getting
their activity on. "Imagine, for example, the battles in Lord of the Rings," Guennardi says, "and being able to have thousands and thousands of individually articulated and driven characters on the
field." "RTS programmers are going to love this!" is my only reply. "By the way, we're using only two meshes. With instancing, which is significantly improved, we scale them and apply different
textures and animations to them, giving us a rich visual environment with very few resources."</p>
<p>Bob pipes up, reiterating a distinction we talked about earlier. "Essentially, we are moving from game rendering, again, to game computing." Guennardi takes control of a slider oriented vertically
along the right side of the screen and drags it up and down, and I see the number of on-screen characters swell and shrink in relation. Around 100,000 characters, the simulation bogs down and the
frame rate begins to stutter sharply. Pulling back to a comfortable number, he points out that the scene is fully interactive. "We can collide with each and every character," he says, as he drives
the camera through the crowd with the mouse and characters go flying, bouncing off the collision volume created around the camera. "And all that code is running on the GPU, all done using
shaders."</p>
<p>Switching demonstrations again, Guennardi shows me an undulating ocean and a beautifully rendered sky. The sky is a skybox, and is of no interest to us. Hitting a key, he shows me the wireframe
mesh, and points out that the wave effects are being computed using the geometry shader &#8211; again, running on the GPU. Pointing to the distant areas of the ocean surface, where the mesh devolves
into a sea of solid color, I recall another difference we touched on earlier. "Yes. In DirectX 9, that area would heavily load the vertex shader but underutilize the pixel shader because the mesh was
resulting in very few pixels drawn. In Direct3D 10, and in particular with the Unified Shader Architecture, the arbitration balances the load and prevents stalling and other forms of performance
degradation."</p>
<p>Grabbing yet another slider, he modifies the size of the waves by changing the velocity of the wind blowing over the ocean's surface. "All the physics behind the wave generation is being computed
on the GPU, using the geometry shader." He then brings up a menu and enables CPU computation instead of using the GPU (remember, this is all being emulated using solely the pixel shader unit). The
simulation goes choppy. The windspeed has to be brought way down before the simulation runs at all smoothly, and even then at framerates under 50. Switching off CPU computation, the framerate
immediately jumps back over 97. "We're seeing nearly double the performance, even on current-generation hardware, using this approach."</p>
<p>"And the CPU isn't even loaded. Can I see the CPU utilization?" I ask. Guennardi points out that it'll be at 100%, simply because Direct3D and OpenGL both require that the application loop be
within 3 frames of the video refresh. "The CPU is running an empty loop, basically, as fast as it can, which would result in 100% utilization. But it is by no means indicative of actual processing
load or availability."</p>
<p>Giddy like a kid on a sugar high, I lean back as Guennardi ends the demonstrations. Asked what I think, I enthuse about getting back into graphics programming myself. Bob and Guennardi rattle off
a list of tasks that are ideally suited for the sort of parallelization that the Unified Shader Architecture and the friendly Direct3D 10 API enable. I remark on the huge opportunity for PC
developers of all stripes, from AAA to casual, given that Windows Vista will ship with Direct3D 10 included, and on PCs that can exploit all its basic features. As we wrap up the preview, we muse as
to what creative uses developers will find for the capabilities made available to them.</p>
<p>"Basically," Bob concludes, "our objective is to eliminate some of the current constraints faced by developers and push them further back, so developers have more room to grow and explore." Yes,
indeed.</p>

]]></description>
		<pubDate>Fri, 28 Apr 2006 19:00:32 +0000</pubDate>
		<guid isPermaLink="false">e1ff36b97044a1c7c73c73e4d27aeba4</guid>
	</item>
	<item>
		<title>An Overview of Microsoft</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/an-overview-of-microsoft-r2280</link>
		<description><![CDATA[<br />
<strong class='bbc'>About This Article</strong><br />
 This article is intended as a high-level overview for developers familiar with Direct3D 9 development. The contents are primarily an elaboration of the many personal notes I made whilst reading all of the available information I have as an MVP. Some of the details in this document will be familiar if you've watched the <a href='http://msdn.microsoft.com/directx/archives/pdc2005/' class='bbc_url' title='External link' rel='nofollow external'>PDC presentations</a>. It is also worth noting that the API is not finished yet – as far as the contents of this article are concerned it should remain accurate, but it's worth realising that if you're reading this long after December 2005 then some parts might have changed.<br />
<br />
 Given the number of changes and the general complexity of Direct3D 10 this document won't be able to cover <em class='bbc'>everything</em> but it'll hopefully give you a starting point. To go beyond the information covered in this article (or simply to try it out), make sure you <a href='http://msdn.microsoft.com/directx/sdk/' class='bbc_url' title='External link' rel='nofollow external'>get the latest DirectX SDK</a> – as of December 2005 the DirectX 9 SDK also contains the Direct3D 10 Technical Preview.<br />
<br />
 I've divided the document into five sections:<br />
<br />
 <ul class='bbcol decimal'><li><strong class='bbc'>About Direct3D 10</strong>. For those who haven't been sucking up each and every piece of publicly available information, this section gives a brief introduction to the latest API revision. </li><li><strong class='bbc'>The Programmable Pipeline</strong>. Fixed function graphics are a thing of the past with Direct3D 10; this section explains what this means and why it's a good thing. </li><li><strong class='bbc'>Direct3D 10 Application Development</strong>. Some of the changes to the API will require software developers to modify the way they write applications. This section covers some of these modifications. </li><li><strong class='bbc'>HLSL and the Effects Framework</strong>. Both of these exist under Direct3D 9, but they've been vastly improved over what we currently have – and not just to take advantaged of the new API changes. </li><li><strong class='bbc'>Going Forward</strong>. What you need to think about if you want to write Direct3D 10 applications, if you want to convert from 9 to 10 and if you are unsure how to handle this new transition period.</li></ul> <br />
<strong class='bbc'>About Direct3D 10</strong><br />
 The most important point to realise with Direct3D 10 is that whilst it retains many similarities with previous iterations it was fundamentally redesigned from the ground up. For a start, it's intended to be for Windows Vista only – that is, you will not be running Direct3D 10 applications on Windows XP.<br />
<br />
 Amongst a number of other technologies, Windows Vista will be introducing the Vista Display Driver Model (VDDM). Graphical features and effects are a much bigger part of Windows Vista than they have been in previous Windows operating systems – as such it requires the GPU to go beyond its current (primary) role as gaming hardware. Take a look at the "Aero Glass" GUI skin for a perfect example of this.<br />
<br />
 The GPU is to be viewed as a shared resource in the system with multiple applications using and relying upon it – making stability a much more important factor. It's also worth noting that as GPU's become more powerful it is necessary to have a clean and efficient path for utilizing them. VDDM moves much more of the command scheduling and translation into 'user mode' and keeps only the essential parts in 'kernel mode' – such that if the hardware or driver crashes it's possible for the system to effectively restart the driver/hardware and avoid taking the whole system down.<br />
<br />
 Sharing the GPU is a big part of VDDM; to the extent that the video memory will be virtualized by the operating system. This will in turn allow for resource sharing across threads, which could become an important feature with the recent turn towards multi-programming. Another bonus of the GPU becoming a more central resource to the system is that the "lost device" scenario is gone – so applications no longer need to worry about handling it. However, there is a "device removed" state – which exists for the increasing number of laptops that come with docking stations.<br />
<br />
 Direct3D 10 also introduces the DirectX Graphics Infrastructure (DXGI) – a common foundation for this new release as well as any subsequent versions (e.g. Direct3D 10.1, 10.2, 11, 12 etc…). Much of the basic low-level resources and operations stay constant and common across most versions of Direct3D such that they've now been isolated from the core runtime. The benefit being that there is a stable and consistent foundation for the API to be based upon, and for application developers it should allow different API's (e.g. D3D10 and D3D11) to share resources.<br />
<br />
 <br />
<strong class='bbc'>The Programmable Pipeline</strong><br />
 We've had some form of programmable pipeline for five years now – ever since Direct3D 8 back in the year 2000. Over the number of revisions since then it has become both more powerful and more flexible – and with Direct3D 10 it becomes the only choice. That's right – the fixed function pipeline is history!<br />
<br />
 With the fixed function pipeline gone it won't be too surprising to see a lot of complaints online – many people still seem quite happy with the style of programming. More importantly, it provides for a much easier "step-up" into the world of graphics programming – you don't really need to understand what's happening internally to get some basic graphics running. Yet, at the same time it becomes a confusion when it comes to moving over to the programmable pipeline as it's not always entirely clear where the boundary between fixed-function and programmable exists. Moving away from the fixed function hardware might make it initially more complicated for beginners, but in the long run it is by far the best way to learn. Being able to directly express algorithms and equations should make learning from one of the many textbooks much more straightforward.<br />
<br />
 The advantages of a programmable pipeline have been discussed many times across the internet and printed media. Suffice to say that "one size fits all" doesn't really apply now that we have the desire for richer and more intense graphics. It's already made itself evident in recent titles and it's likely to become even more prevalent – individual "characteristics" of a game. With the programmers directly expressing the equations and then exposing the parameters to artists it allows for many subtle differences in the final images.<br />
<br />
 With Direct3D 10 we have a new programmable unit – giving three in total: Vertex Shaders (VS), Geometry Shaders (GS) and Pixel Shaders (PS). All three form "Shader Model 4.0". Both vertex and pixel shaders are fundamentally the same as they always have been – but with a few added bells and whistles. However, the Geometry Shader is completely new – and allows us to write code that operates on a per-primitive basis. Not only that, but it also allows us to add geometry procedurally – effectively extending the hardware to a whole new class of algorithm.<br />
<br />
 A powerful feature connected to Geometry Shaders is Stream Output (SO). Conventionally the graphics pipeline has moved in one direction – data gets fed in by the application and via a number of steps generates an image on the screen. Locking render targets is about as close to being able to retrieve the outputs of a given stage. The stream output mechanism allows the GS to circulate its results back to the Input Assembler (discussed further on) such that it can be re-processed. Although, it doesn't exclusively have to circulate it back – it can circulate <em class='bbc'>and</em> render by passing the output to both the rasterizer and Input Assembler.<br />
<br />
 SO essentially allows for multi-pass geometry processing with minimal intervention by the CPU (good for parallelism). Examples of this might be to create geometry in the first pass (Bezier patches and/or skinning) and then doing shadow-volume extrusion on a second pass.<br />
<br />
 Despite mentioning that the fixed-function methodology was dead, there are two major components in the pipeline that are essentially fixed function.<br />
<br />
 The Input Assembler (IA) is a refinement on a number of existing technologies – its responsibility being to take the index and vertex streams and composes the actual geometric data that is fed into the VS and GS components. At the simplest level this component takes the various primitive types (line list, triangle strip etc…) and constructs the actual triangles (remember that some primitive types share vertices). At the more complex level it'll be dealing with geometry instancing and stream-out data. A useful feature that it will generate is a set of counters as it walks through the geometry – vertex ID's and primitive ID's. This can be used further down the pipeline to vary processing (or source data) depending on the result.<br />
<br />
 The Output Merger (OM) is fixed function and also the final stage in the pipeline. Its job is to take all of the results generated by the pipeline and merge them into the final pixel value that we see on the screen. It uses the stencil values, depth values along with multiple render targets along with various blending functions to create the final result.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/d3d10overview/pipeline.gif' alt='Posted Image' class='bbc_img' /></span><br />
The Direct3D 10 Pipeline<br />
<br />
 The Direct3D 10 pipeline should allow for not only a wider class of algorithms (neural networks and physics on a GPU…) and improved performance (single pass cube map rendering) but it should allow application developers to offload more work.<br />
<br />
 An interesting part of the new attributes that the IA generates as well as the GS's ability to work at the triangle level is that of GPU-selectable properties. It is quite conceivable that most (if not all) of a material system can be executed directly on the GPU. Consider a case where each triangle is given a Primitive ID by the IA which is used by the GS or PS to look up a set of attributes from an array provided as a set of constants that determines how the pixels are finally rendered. Whether this eliminates the need for material-based sorting in the application won't be known until developers get their hands on some real Direct3D 10 hardware – but it definitely opens up the possibilities.<br />
<br />
 Data inputs for the programmable pipeline are less strict in Direct3D 10 – further blurring the potential of what the different components are actually capable of. Under Direct3D 9's shader model 3.0 it was possible (albeit performance made it prohibitive) to sample some textures inside the vertex shader. This still exists in Direct3D 10, but courtesy of the more unified resource model it is now what it probably should always have been.<br />
<br />
 The unified resource model is supported by "views" – that is, different stages (or even separate uses of the same stages) can view the same resource in different ways. This allows complex resources to become a lot more flexible – which should simplify the application-side of D3D programming as well as offload more work to the GPU and hopefully act as a performance optimization. Examples of this include interpreting a cube-map as an array of 6 separate render targets and performing single pass cube-map rendering; being able to use different mip-map levels as inputs/outputs should also help to avoid the "ping-pong" nature of down-sampling algorithms.<br />
<br />
 <br />
<strong class='bbc'>Direct3D 10 Application Development</strong><br />
 Given the features and general information discussed so far in this article, it should be expected that application development will have to change to make use of the new API. This is true, but at the same time it's an evolution of what seasoned Direct3D programmers should be used to – the core theory remains the same.<br />
<br />
 Enabled by Direct3D 10 being targeted at a new operating system, driver model and internal re-design is that it only has a few variable capabilities. This is no small change – under Direct3D 9 the D3DCAPS9 structure contains enumerations that cover a huge spectrum of hardware (as demonstrated by the 'CardCaps' files in the SDK). Initial application development with such a number of potential combinations was at least an interesting balancing act; testing the final product against all combinations was difficult if not impossible.<br />
<br />
 With fixed capabilities it is conceivable that the testing will become more for performance than stability and correctness. This works well for both professional studios who can reduce the overhead (time and cost) of testing as well as for indie developers who simply don't have access to such wide-ranging resources. It has been hinted at that there will be more frequent point releases of Direct3D to allow for innovation of hardware features.<br />
<br />
 Given that the IHV's can no longer compete on who's got the best feature-set it will come down to whom has the best performance and quality. This does pose the question of whether performance-related capabilities will become the new problem – an IHV might be <em class='bbc'>required</em> to provide a feature, but whether it's actually <em class='bbc'>usable</em> is another issue entirely. In current Direct3D 9 development, it is possible on some hardware to use "vertex texturing" – but it is generally regarded as being too slow to rely on as a central component. With this in mind it's unlikely that a graphics engine can be abstracted completely from the hardware and that multiple code-paths will still exist (optimized for each IHV).<br />
<br />
 Another big aspect of Direct3D that has changed with this release is the push for create-time validation of resources. On the surface this is about performance – moving any expensive checking to the time of creation and avoid doing it each-and-every time it's used by the core rendering functions. By having resources and configurations verified at create-time it should allow application developers to write cleaner and simpler code in the core parts of an application. Checking and handling of errors should become less of an intrusion into the core code. Also, by verifying resources when they are loaded it should give the application a better ability to handle any incorrect resources. With the increasing bias towards data-driven effects (more shaders, more textures…) any additional 'safety' can't be a bad thing!<br />
<br />
 Render states have undergone some changes with Direct3D10 that could require some changes to existing code bases. Simply put they are now organised into a number of immutable state objects. Each of these object types encompasses the group of render states related to its part of the pipeline – for example the D3D10_DEPTH_STENCIL_DESC object describes render states related to depth and stencil buffering. This makes things a bit easier to manage – it would be quite simple to create a number of these state objects for each effect to be used. Where it could get difficult is for existing scene graphs and state management systems that are finely tuned to the current Direct3D API. Efficient state management and ordered drawing has become the cornerstone of high performance Direct3D applications – and if existing implementations are fine-grained down to individual states then this change towards immutable groups could invalidate much of that code.<br />
<br />
 <br />
<strong class='bbc'>HLSL and the Effects Framework</strong><br />
 Direct3D 8's shaders were entirely written in assembly (which was still an intermediary step) and Direct3D 9 continued to allow this form but also introduced HLSL. With Direct3D 10 the use of assembly shaders has been almost eliminated – effect files and "pure" shaders are now expressed only in HLSL form. The output from the HLSL compiler will still be visible so that you can use it for sanity checking and debugging, but it won't be a valid input from the application. The compiler itself has been merged into the core Direct3D 10 runtime – it's no longer owned by D3DX as it was under Direct3D 9.<br />
<br />
 HLSL-only fits into the previous point about having create-time validation. By examining the input/output semantics the runtime can verify that the output of one stage matches the input of the next stage – and not only produce an error indicating that the shader will fail, but also eliminate the need to check shader linkage during the core rendering segments.<br />
<br />
 The fundamentals of HLSL shaders (and their related "fx" files) hasn't changed, but there are a number of new instructions and functions available – refinements on what most developers will be familiar with. It is notable that apart from a few specialist instructions (such as cut and emit in the GS) all three programmable units share a common set of instructions. 'Standard Annotations and Semantics' has featured in later Direct3D 9 updates and still exists in Direct3D 10 – albeit it is more standardised and likely to be more widely used and relied upon. With annotations becoming a more basic part of the effects and HLSL systems, it should be more convenient to move effects between tools (e.g. authoring a shader effect inside 3DSMax and having it automatically picked up and used by your Direct3D application).<br />
<br />
 One of the bigger changes that will be apparent with HLSL is the introduction of "constant buffers" – these apply logical groupings to the constants that the application can feed into a stage of the pipeline. These buffers allow the API and hardware to manipulate constants in a much cleaner way; in current applications it is very possible to adversely affect performance with inefficient constant updates. Despite the way they appear, they are more of a semantic than syntactic feature – they don't work like namespaces (it's still a flat global namespace) and constants can get assigned to namespaces based on their usage. For example, a number of constant buffers can be created to indicate how often they are updated (always constant, per frame and user input etc..).<br />
<br />
 HLSL now allows for a full set of integer instructions and operations which appear much like you would expect from most progamming languages – logical and bitwise operators. Given that stages in the pipeline can now access multiple resources, it can be useful to work in integer format so as to get correct addressing (and where filtering by floating point addressing is not desirable). With clean and direct access to the raw binary data (via bitwise operations) it will be interesting to see what geometry compression systems can be mapped directly to the GPU hardware.<br />
<br />
 Direct3D 10 shaders have no instruction count limit. Looping and extended execution time can be covered by the new Vista driver model – because the GPU is considered as a shared resource the drivers and OS monitor situations where the GPU is deemed to have "hung" and require resetting.<br />
<br />
 The effects framework has undergone a complete re-design in part so that it matches the changes in the API but also to take advantage of the opportunity offered by a completely new API.<br />
<br />
 The memory footprint for effects files has been reduced by internal restructuring, but changes to the reflection system allow application developers to query for information and then discard all information that is no longer required.<br />
<br />
 Access to the internals of the effect file (constants/parameters, techniques etc…) has been refined and is now through a series of lightweight interfaces rather than through the slightly complicated handles system currently employed by Direct3D 9. Performance-wise, updating and applying changes is in line with the other design changes explained in this article – fast! Validation is done at load-time such that no runtime checking is required, consequently changing becomes a constant-time operation.<br />
<br />
 Related to both of these is the ability to have "effect pools" – it is advised that you load <em class='bbc'>all</em> effects into a pool such that any common information can be efficiently stored and updated.<br />
<br />
 <br />
<strong class='bbc'>Going Forward</strong><br />
 The article you've just been reading has been focussed on the changes and enhancements in Direct3D 10 with reference to existing technologies where applicable. For this section of the article the focus does a 180 and covers some of the issues that application writers might need to consider <em class='bbc'>today</em>.<br />
<br />
 The first big change is going to be to stop relying on fixed-function processing. Obviously there will be a lot of legacy code around that uses this functionality, but any attempts to deprecate and slowly fade it away will be a good plan. Writing any new Direct3D code should be done entirely in the form of shaders (doesn't have to be via the Effect framework). Remember that FX files (via the Effect Framework) can contain fixed-function statements, so it's worth checking those as well.<br />
<br />
 Following on from this, you should also look at any shaders written in assembly code. As mentioned in the main body of the article, the new Direct3D runtimes deal with HLSL only – such that your ASM code becomes obsolete. Given that most assembly code shaders are for the older 1.x targets it shouldn't be too hard to write up an equivalent HLSL version. Going forwards, it would be best to start writing all shaders in HLSL so that they are Direct3D 10 ready.<br />
<br />
 Consider making use of the new pipeline-generated values (VertexID, PrimitiveID and InstanceID). Their values can almost be simulated by attaching per-vertex attributes under Direct3D 9; but it might have to be something you need to wait before using. The reasoning for considering these attributes as it can, with a bit of creative thinking, be used to simplify the application-level code by getting the programmable pipeline to select properties for you.<br />
<br />
 When thinking about the new geometry shader functionality it is probably best not to think of it as a programmable unit for higher-order surfaces (e.g. Bezier patches) or compressed meshes. Whilst the GS has much of the functionality required for these tessellation algorithms it is quite likely that the first round of Direct3D 10 compliant hardware won't have the necessary performance to make <em class='bbc'>heavy</em> use of it. As hinted at previously in this article it is probably worth utilizing the GS as more of an optimization (single-pass rendering to multiple render targets) and a means by which to gather additional information about what is being rendered. For example, it's possible to compute plane equations and surface (rather than vertex) properties.<br />
<br />
 Combined with the increased availability of information inside the pipeline and the new grouping of render states, it will be worth considering how any scene graphs and state management algorithms work. Emulating state objects should be simple enough, and designing your algorithm(s) such that it can take advantage of the pipeline would definitely be beneficial for any future upgrades.<br />
<br />
 As you could quite rightly expect, Windows XP and DirectX 9 are still going to be around for some time yet. Officially Windows XP will cease to be supported at the end of 2006, but that doesn't mean it'll just vanish off home users machines (it may well vanish very quickly off corporate networks though). Application compatibility is a big factor in a new OS such that DirectX 9 applications built for Windows XP will still work under Windows Vista, and there will even be an updated version of DirectX 9 to take advantage of the new driver model in Vista ("DirectX 9.L").<br />
<br />
 For the time period running up to Windows Vista (currently estimated somewhere towards the end of 2006) it makes sense to continue developing for DirectX 9 with an eye towards targeting DirectX 9.L (as and when details are available). If you follow the guidelines in this article (as well as any others you can find) then updating to be Direct3D 10 compatible (or to make use of its features) should be fairly straight forward.<br />
<br />
 <br />
<strong class='bbc'>About The Author</strong><br />
 Jack Hoxley is a Microsoft Most Valuable Professional (MVP) for <a href='https://mvp.support.microsoft.com/communities/mvplist.aspx?Product=Windows+-+DirectX' class='bbc_url' title='External link' rel='nofollow external'>DirectX</a>. You can view his full profile <a href='https://mvp.support.microsoft.com/profile=574f03f7-8bdb-4a5a-ac3f-ce6c05c04c83' class='bbc_url' title='External link' rel='nofollow external'>here</a>. He maintains a <a href='http://www.gamedev.net/community/forums/mod/journal/journal.asp?jn=316777' class='bbc_url' title=''>developer journal</a> on the game development website <a href='http://www.gamedev.net' class='bbc_url' title=''>GameDev.net</a> and answers questions in their forums under the alias "<a href='http://www.gamedev.net/profile/profile.asp?mode=view&id=3290' class='bbc_url' title=''>Jollyjeffers</a>". You can contact Jack by email at the following address: Jack *dot* Hoxley *at* f1cm *dot* co *dot* uk.<br />
<br />
 13<sup class='bbc'>th</sup> December 2005<br />
Version 1.1<br />
<br />
]]></description>
		<pubDate>Thu, 15 Dec 2005 15:37:34 +0000</pubDate>
		<guid isPermaLink="false">aae094199bf30b0b1a58e8ec1bbad5ec</guid>
	</item>
	<item>
		<title>Loading and displaying .X files without DirectX</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/loading-and-displaying-x-files-without-directx-r2221</link>
		<description><![CDATA[<br />
<strong class='bbc'>Introduction</strong><br />
 I like the .X file format: its organisation and structure suits me. But why would I need to load and display X files without DirectX? My needs were simple:<br />
<br />
 <ul class='bbc'><li>I often use Borland C++ 5.01 compiler. The dxguid.lib cannot simply be converted from COFF to OMF without losing much information and rendering the DirectX SDK almost useless. </li><li>I wanted to be platform independent. </li><li>I wanted to understand how DirectX was rendering meshes and what was hidden in the helper functions.</li></ul> The <a href='http://downloads.gamedev.net/features/programming/xfilepc/XFilePC.zip' class='bbc_url' title='External link' rel='nofollow external'>code samples</a> use Freeglut and were written using DevCpp 5.0 (4.9.9.1) and minGw 3.4.2. This article is designed to be read while referencing the sample source code.<br />
<br />
 <br />
<strong class='bbc'>1. Loading and displaying the Mesh from an X File</strong><br />
 Before getting into any kind of development, we need to define first what a mesh is and how it is stored within the X file. We will then derive and implement a design.<br />
<br />
 <br />
<strong class='bbc'>1.1. Design</strong><br />
 <br />
<strong class='bbc'>1.1.1. Descriptions</strong><br />
 A polygonal mesh is a structured list of points (called vertices) connected together to describe a surface. In our case, the mesh will define the surface of our model.<br />
<br />
 To texture the polygonal mesh, we associate texture coordinates with each vertex to know which part of an associated bitmap to draw on the mesh (e.g.: drawing tiny's jacket on the mesh part modelling the jacket).<br />
<br />
 Each face of a mesh can also be associated with a material. A material describes the colour reflected by an illuminated model. The colour is often defined as a set of Red, Green, Blue and Alpha components.<br />
<br />
 Let's now look into the X File format.<br />
<br />
 The .X File format can be either in plain text or in binary. This is given in the header of the file. We will look into the text format. The binary format will be addressed in the fifth chapter.<br />
<br />
 The X file format is structured into blocks describing elements of the model. You can browse [MSDN] to find descriptions of all the different blocks. A pair of braces delimits each block. An opening brace must always be paired with a closing brace. There is a hierarchical relationship between the blocks since some may contain others. The table below will outline the hierarchies non-exhaustively:<br />
<br />
   Block Contains   Frame FrameTransformMatrix   Frame   Mesh   Mesh MeshNormals   MeshTextureCoords   MeshMaterialList   SkinMeshHeader   SkinWeights   MeshMaterialList Material   Material TextureFileName   AnimationSet Animation   Animation AnimationKey   We are interested in the Mesh Block. This block can be either directly accessible or embedded within a frame. We may find many meshes within the same X file. For example, there are two meshes in tiny_4anim.x. The mesh block holds all the necessary information for its display:<br />
<br />
 <ul class='bbc'><li>MeshNormals: a list of normal vectors used in case the model is illuminated. </li><li>MeshTextureCoords: Texture coordinates for each Material. </li><li>MeshMaterialList: the list of Materials for the mesh. This block also associate a Material index to each face of the model.</li></ul> Since we want to have a working demo, we need to support the following:<br />
<br />
 <ul class='bbc'><li>Recognise the type of the format of the file (text or binary), </li><li>Extract all the meshes and their associated blocks into a model, </li><li>Concatenate the meshes of a model to simplify the use of the model, </li><li>Create a mesh subset for each material used, </li><li>Calculate the bounding box coordinates of the mesh, </li><li>Display the model mesh under OpenGL.</li></ul> Whew! Though that list is small, there is much work to do before we are able to display a mesh.<br />
<br />
 <br />
<strong class='bbc'>1.1.2. Code Design</strong><br />
 The graph below sums up the class hierarchy for the Model object derived from the descriptions above:<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/xfilepc/model.png' alt='Posted Image' class='bbc_img' /></span><br />
<br />
 The Model class has a single method to concatenate meshes.<br />
<br />
 The Mesh class maintains static lists of vertices, texture coordinates and normal vectors.<br />
<br />
 The Material class holds a colour and the Bitmap texture.<br />
<br />
 Wait a minute! How are we going to draw the model?<br />
<br />
 We could use the Model Object and add a Draw method. But doing this will cause some problems down the road: when we get into mesh animation, we will calculate a new set of vertices from the original mesh vertices at each animation frame. If we want to display the same model but with different poses (say like in a mob of monsters), we would have to calculate the model mesh for each monster. Instead we will create an Object3D class which will be used to perform all calculations on a model mesh. This Object3D class will be initiated with a Model class and will contain the methods to draw and calculate the bounding box of the mesh.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/xfilepc/Object3D.png' alt='Posted Image' class='bbc_img' /></span><br />
<br />
 Why don't we have a Load method within the Model object?<br />
<br />
 There is a simple answer. There are many 3D-model file formats. We would need to implement a load method for each existing file format plus a function to get the correct loading function from the file extension. This would transform our code into some ungainly spaghetti.<br />
<br />
 We will use a loading interface for ease of implementing future loading functionality. From this loading interface, we will derive our X File loading class.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/xfilepc/IO_X.png' alt='Posted Image' class='bbc_img' /></span><br />
<br />
 <br />
<strong class='bbc'>1.2. Implementation</strong><br />
 At last! We can now begin coding. But before diving into the implementation of our design, I will quickly describe the framework into which our code will be embedded. You can find the framework in the file Sample0.zip.<br />
<br />
 <br />
<strong class='bbc'>1.2.1. Quick description of the framework (file Sample0.zip)</strong><br />
 This framework is built on top of Glut. All the screen manipulations are encapsulated within a Screen object. This Screen object is also responsible for Font manipulation and texture loading and registration under OpenGL.<br />
<br />
 The Sample0 example shows how the OpenGL logo texture is loaded and selected before being displayed on the screen.<br />
<br />
 There is also a timer class used to calculate the elapsed time since the last call. This class is based on the Win32 function GetTickCount. This can easily be replaced by the function glutGet(GLUT ELAPSED TIME)).<br />
<br />
 Finally, there are some tracing macros defined in ToolBox&#092;MyTrace.h.:<br />
<br />
 <ul class='bbc'><li>DECLARE_TRACE: declares the tracing object. </li><li>START_TRACE: initialises the tracing file in the directory Debug. </li><li>END_TRACE: removes and deletes the tracing object. </li><li>MYTRACE: prints the data in the Glut console window and in the tracing file.</li></ul> All code modifications explained in this article will be signalled within the source by the following tags:<br />
<br />
  /***********************************************  NEW-NEW- NEW- NEW- NEW- NEW- NEW*/ … Code modification … /***END***************************************/  All right! Let's first look at the code in the file Sample1.zip.<br />
<br />
 <br />
<strong class='bbc'>1.2.2. Parsing the file (file Sample1.zip)</strong><br />
 The loading interface is defined in framework&#092;Frm_IO.h. This is a template interface with two protected methods to help users to convert text to floating point numbers and to remove all occurrences of a character from a string.<br />
<br />
 The X File loading class is defined in files ToolBox&#092;IOModel_x.h and cpp.<br />
<br />
 This is what happens in pseudo-code:<br />
<br />
 <em class='bbc'>Open the file<br />
Check the file Header<br />
Grab a reference to the Model Object to fill in<br />
Enter the main processing loop:</em> <em class='bbc'>While we have not reached the end of file<br />
Read the block name (ProcessBlock)<br />
</em> If the block name is recognised, process it.<br />
Else avoid the block (AvoidTemplate)   The file Header is checked by comparing the value read from the file with macros defined in the file XfileStructs.h and given by Microsoft in [MSDN]. These macros are important since they can also be used to process binary files.<br />
<br />
 There are two main utility functions:<br />
<br />
 <ul class='bbc'><li>ProcessBlock: This function checks the current character to identify the start of a block name and avoid comments (which start by the characters # or //). If a valid character is detected, this function reads in the string until it finds a space, then calls the utility function Block. This second function will look up in the list of XOF_TEMPLATEID structure (this structure pairs a block name with a token identifier). If it recognises the string as a valid Block Name, it will return the corresponding Token Identifier else this function returns a X_UNKNOWN Token. </li><li>AvoidTemplate: This function will avoid all the data enclosed between a matched pair of braces. It consumes an opening brace character then checks each successive character. If it finds another opening brace character, this function will call itself recursively. This function returns whenever it finds a closing brace.</li></ul> These utility functions are invaluable to process a text X File since they help us narrow down the blocks we want to process. If a block is contained within another one like in the Frame structure, it will suffice to duplicate the processing loop inside a specialised processing function for the frame structure (see the function ProcessBone(void)).<br />
<br />
 We found a mesh! Hallelujah! Now we have to process it. This is the task of the specialised function ProcessMesh. Here is what happens in pseudo-code:<br />
<br />
 <em class='bbc'>Create an empty Mesh object and initialise it.<br />
Read in the name of the mesh.<br />
If there is no name, assign a name to that mesh.<br />
Read in the number of vertices.<br />
Load the list of vertices into the Mesh object.<br />
Read in the number of faces<br />
Load the list of faces into the Mesh object.<br />
Enter the mesh processing loop:<br />
</em> <em class='bbc'>While we have not reached the end of the block<br />
Read the block name (ProcessBlock)</em> If the block name is recognised, process it.<br />
Else avoid the block (AvoidTemplate)  <em class='bbc'>Once the Mesh block is fully processed we add the Mesh object to the Model's list of Meshes.</em> Why do we need a mesh name? The X file format either declares the mesh or only references the mesh name within the block that is concerned by it. To be able to trace what happens and check that the mesh is correctly associated, we need a unique mesh name. If there are no names, we need to create a unique name (this is done by the utility function SetUID).<br />
<br />
 Next we process the Mesh block data (see [MSDN] for the description of that data). Then we enter a loop to process all embedded blocks.<br />
<br />
 The Texture Coordinates block is very simple to process: we read in the number of texture coordinates, and then we load in the list of texture coordinates. The block is processed.<br />
<br />
 The Mesh Normal Vectors block isn't any more difficult. We read in the number of vectors, and then we load in the list of vectors. Next we load in the list of vector indices per face: this gives us the vertex normals for each face allowing for correct illumination of the model.<br />
<br />
 Material list blocks are a little trickier. Here is the pseudo-code:<br />
<br />
 <em class='bbc'>Read in the number of Materials used by that mesh.<br />
Read in the material index for each face<br />
Enter the material list processing loop:<br />
While we have not reached the end of the block<br />
</em> <em class='bbc'>Read the block name (ProcessBlock)<br />
</em> If the block name is recognised, process it.<br />
Else avoid the block (AvoidTemplate)   All that is left is to process each Material description block within the Material list. Here we go:<br />
<br />
 <em class='bbc'>Read in the face colour.<br />
Read in the emissive power.<br />
Read in the specular colour.<br />
Read in the emissive colour.<br />
Enter the material description processing loop<br />
While we have not reached the end of the block</em> <em class='bbc'>Read the block name (ProcessBlock)<br />
</em> If the block is TextureFileName, we read in the bitmap name.<br />
Else avoid the block (AvoidTemplate)  <em class='bbc'>Once the material is processed, we add it to the mesh's list of materials.</em> And that's it! All the meshes are loaded into the model object.<br />
<br />
 <br />
<strong class='bbc'>1.2.3. Concatenating meshes and creating subsets</strong><br />
 We will now look into the files framework&#092;Frm_Mesh.h and cpp.<br />
<br />
 We can't yet display the meshes loaded within the model. First, we want to concatenate the meshes because:<br />
<br />
 <ul class='bbc'><li>This simplifies the mesh maintenance (only one material list, one normal vectors list and one list of vertices and faces). </li><li>This simplifies the drawing step further down the line: we remove a loop through a list of meshes and we only draw a single vertex array.</li></ul> If you look closely at the Mesh block parsing code, you see at the beginning the initialisation of a series of values for the mesh: these values are the sum of the previous meshes indexes (number of vertices, number of faces, … ). These values will be used:<br />
<br />
 <ul class='bbc'><li>To deduce the final size of the concatenated mesh. </li><li>To increment all index references by their starting values to have a correctly displayed mesh.</li></ul> Now let's have a look at the pseudo-code:<br />
<br />
 <em class='bbc'>Create a new mesh and retrieve its dimension from the last mesh in the list.<br />
Check the new mesh dimensions and resolve all discrepancies.<br />
Create all the new mesh arrays.<br />
Process each mesh from the model list</em> For each mesh increment the index references.<br />
Copy each mesh data into the new mesh.<br />
Move each mesh material into the new mesh material list. <em class='bbc'>Delete the model mesh list.<br />
Add to the model mesh list the new concatenated one.</em> When we calculate the new mesh dimensions, we need to take care of differences between mesh descriptions. One mesh may use textures and thus have texture coordinates while another may just be coloured and have no texture coordinates. To solve that problem, we duplicate the vertex array size to initialise the texture coordinates array. If we didn't do that, the face list would be divided between indexed faces with colour information and indexed faces with texture coordinates.<br />
<br />
 Now that we have concatenated our meshes, there is one step left: we need to create subsets. Let me explain: we have created a mesh with multiple materials. We want to divide our array of faces into a list of faces for each material used. The aim is to have only one call to set a material before drawing our mesh subset.<br />
<br />
 The code is very straightforward:<br />
<br />
 <em class='bbc'>For each Material in the material list</em> Count the number of occurrences of that material in the FaceMaterial list<br />
Initialise the subset<br />
For each occurrence of that material in the face material list copy the face data to the subset <em class='bbc'>Add the subset to the list of subsets</em> <br />
<strong class='bbc'>1.2.4. Displaying the result</strong><br />
 At last, we have parsed our X File, we have concatenated our Meshes and our Model Object is ready for display. Only one part of our design is left for implementation: the Object3D class that will be in charge of all the calculations based on the original mesh.<br />
<br />
 Let's look at the file Sample1.cpp. During the initialization of the Glut demo, we call our specialised loader object to parse the file tiny_4anim.x into our Model instance. If the Model was successfully loaded, we concatenate the meshes. We load up into OpenGL all bitmap textures declared within the Meshes material list.<br />
<br />
 Now we enter the meat of our subject: we initialise an instance of Object3D with our loaded Model. This initialisation keeps a pointer to the Model, gets a pointer to the first mesh of the Model Mesh list and initialises an empty vertex array with the same size as the Model Vertex Array. Then we call the Object3D Update method, which copies the Model Vertex Array into its own array. Last but not least we compute the bounding box coordinates and deduce the centre of the bounding sphere.<br />
<br />
 Let's display our Object3D! First, we calculate our camera position with the centre of the bounding sphere, and then we call the draw method with our Screen object as a parameter. This draw method will parse the mesh material and subset lists. It will set up each material and draw the corresponding subset until there are no more materials to process.<br />
<br />
 In the Idle function, we clear the Object3D vertex array and call back the Update function. That's all there is to it. Whew! We finally made it.<br />
<br />
 Let's increase the complexity. Time for us to look into tiny's skeleton and skin her.<br />
<br />
 <br />
<strong class='bbc'>2. Bone hierarchy and skinning</strong><br />
 We know how to process a mesh. Still we are not any closer to skeletal animation. We are missing the model skeleton. The example code in Sample2.zip builds upon the previous code to support skinning information.<br />
<br />
 <br />
<strong class='bbc'>2.1. Design</strong><br />
 <br />
<strong class='bbc'>2.1.1. Descriptions</strong><br />
 In drawing courses, the first thing taught to students for drawing a character is anatomy. To correctly draw a character in a pose, students must know how the body is composed (how the skeleton is made, where the muscles go, how the skin drapes the muscles and the skeleton). Computer graphics are no exception.<br />
<br />
 A 3D model of a character consists of a skeleton and a skin. The skeleton describes the underlying structure of the model: it helps modelling any pose for a given 3D character. The skin is represented by a polygonal mesh. Below you see below an outline for a gorilla (that's all my drawing capabilities permit ;) ): the skeleton is black and the skin is grey.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/xfilepc/Char3D.png' alt='Posted Image' class='bbc_img' /></span><br />
<br />
 The skeleton is a hierarchic set of bones. The bones are represented by matrices. What does that mean? All bones are defined with a joint at the origin, this is called bone space. The associated matrix of a bone scales, rotates and translates the bone to connect it to its immediate parent. This is a local transform matrix since the bone is placed relative to its immediate parent. To place all the bones of a skeleton in character space we must combine the bone local matrix with its parent combined matrix:<br />
<br />
 Combined_Matrix<sub class='bbc'>bone</sub> = Local_Matrix<sub class='bbc'>bone</sub> * Combined_Matrix<sub class='bbc'>parent</sub><br />
<br />
 This combined matrix will be used to display our vertebrate model. There still is one problem: how do we link the polygonal mesh to the underlying skeleton?<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/xfilepc/bind.png' alt='Posted Image' class='bbc_img' /></span><br />
<br />
 The brute polygonal mesh (like the one we extracted in sample1) is said to be in bind space. To combine the skeleton with the mesh in bone space, we use another set of matrices called skin offset transform matrices. These matrices displace the mesh vertices to conform it to the bones. To display the boned mesh into character space, we combine the skin offset matrix of each bone with its corresponding combined matrix:<br />
<br />
 Final_Matrix<sub class='bbc'>bone</sub> = Skin_Offset<sub class='bbc'>bone</sub> * Combined_Matrix<sub class='bbc'>bone</sub><br />
<br />
 This means we first displace the mesh from bind space to bone space, and then we transform the skinned mesh from bone space to character space. Now the mesh is draped around the bones in character space simply by multiplying each vertex by its corresponding bone final matrix.<br />
<br />
 There still is one problem. When bones are making an angle the mesh may show ungainly angles or gaps (see drawing below).<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/xfilepc/vblending.png' alt='Posted Image' class='bbc_img' /></span><br />
<br />
 We need to weight each vertex to define the influence of each bone Final Matrix. Thus the final vertex position in character space is defined by:<br />
<br />
 Vertex<sub class='bbc'>dest</sub> = SUM ( Vertex<sub class='bbc'>source</sub> * Underlying_Bone_Final_Matrix * Underlying_Bone_Weight[Vertex<sub class='bbc'>source</sub>])<br />
<br />
 Where shall we find the information in the X file format? Microsoft uses two different blocks:<br />
<br />
 <ul class='bbc'><li>Frame: this block describes the bone. It names the bone. It contains one FrameTransformMatrix block describing the bone local matrix and other Frame blocks defining all the children bones. The frame also references the mesh it applies to either by name or by declaration of a Mesh Block. The children of a frame inherit the mesh reference if they do not define their own. </li><li>SkinWeight: this block contains the bone name, the skin offset matrix, the list of vertices to apply this matrix on and the list of weights for these vertices. We find this block within the Mesh block.</li></ul> Now let's look at the functionalities we need this time:<br />
<br />
 <ul class='bbc'><li>Extract the bone hierarchy with all its related matrices. </li><li>Concatenate the meshes and update the bone references </li><li>Calculate the character space matrices </li><li>Display the skinned model.</li></ul> <br />
<strong class='bbc'>2.1.2. Code Design</strong><br />
 If we look closely at the way matrices are combined, we won't be able to rely on the glMultMatrix function: The glMultMatrix function multiplies the current Matrix on top of the stack with the matrix passed as a parameter:<br />
<br />
 Top_of_Stack = Top_of_Stack * Parameter Matrix<br />
<br />
 We need to combine matrices the other way around:<br />
<br />
 Top_of_Stack = Parameter Matrix * Top_of_Stack<br />
<br />
 Since matrix multiplication is not commutative ( A*B != B*A), we need our own matrix class with overloaded multiplication operators for Matrix multiplication (for calculating Bone combined matrices) and scalar multiplication (for weighting the final transformation matrix).<br />
<br />
 We need a Bone class to store the local transform matrix, the skin offset matrix, the list of vertices the bone is linked to and their associated weights, and pointers to the children bones. The Model stores a pointer to the first bone of the hierarchy.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/xfilepc/Model2.png' alt='Posted Image' class='bbc_img' /></span><br />
<br />
 Now let's draw our model. We first want an ObjectBone class. This class holds and does all the matrix calculations (Combined and final transform matrices). It references a bone from the Model to get the Local Transform Matrix and the Skin Offset Matrix. The Object3D class evolves to store a reference to a hierarchical list of ObjectBones strictly replicating the Model-Bone structure.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/xfilepc/Object3D2.png' alt='Posted Image' class='bbc_img' /></span><br />
<br />
 Thus whenever we need to update the skinned mesh, we call the update function from Object3D that will calculate all the matrices in the hierarchical set of ObjectBone before multiplying each of the final matrices by the Model Mesh to get the final skinned mesh.<br />
<br />
 That's all for the design.<br />
<br />
 <br />
<strong class='bbc'>2.2. Implementation</strong><br />
 I will not discuss the Matrix class implementation. This is pretty standard and any quick search on the web will give you all you need to know about matrices operations. There are also existing implementations of Matrix classes like the [WML] library you can reuse.<br />
<br />
 <br />
<strong class='bbc'>2.2.1. Parsing the file (file sample2.zip)</strong><br />
 The modified X File loading class is in files ToolBox&#092;IOModel_x.h and cpp.<br />
<br />
 We must modify our Frame processing function. This function gets a pointer to a model Bone as a parameter. You will understand when you look at the pseudo-code:<br />
<br />
 <em class='bbc'>Create an empty Bone object.<br />
Read in the name of the bone.<br />
If there is no name, assign a name to that bone.<br />
If the Parent Bone parameter is null</em> Store the bone as the head of the hierarchy in the variable _Skeleton <em class='bbc'>Else</em> Push the current bone into the parent bone children list <em class='bbc'>Enter the Bone processing loop:</em> <em class='bbc'>While we have not reached the end of the block<br />
Read the block name (ProcessBlock)</em> If the block name is recognised, process it.<br />
If it is an open brace token, read in the mesh name reference.<> Else avoid the block (AvoidTemplate)   In the Bone processing loop, if the recognised block name is Frame, we recursively call this processing function with the current bone as a parameter.<br />
<br />
 Processing the FrameTransformMatrix block is simple. We just read in the 16 values into the bone Local Transform matrix.<br />
<br />
 Processing the SkinWeight block is a little bit trickier since we need to map the SkinWeight data to the bone class. Let's look at the pseudo-code:<br />
<br />
 Get the bone name<br />
Retrieve the correct bone object from its name<br />
Read in the number of vertices attached to this bone<br />
Load in the vertex indices<br />
Load in the vertex weights<br />
Read in the Skin Offset matrix To retrieve the correct bone object, we use the IsName method from the bone object. This method checks first if the bone is the one searched for. If not, then it processes all the children bones. If no bones are found, the method returns null.<br />
<br />
 When we have finished loading the model, we map the mesh to the bones. We propagate the mesh name of a bone to all its children without mesh names. This step is important for when we concatenate the meshes.<br />
<br />
 <br />
<strong class='bbc'>2.2.2. Concatenating Meshes</strong><br />
 When we concatenate the meshes, we must update the mesh reference and the vertex indices in each bone class. The pseudo-code for the private method UpdateBoneIndices of the Model Class is:<br />
<br />
 Retrieve a pointer to the mesh assigned to the current bone.<br />
Add the Mesh Starting Vertex Index to the Bone Vertices index list<br />
Recursively process the bone children When we load multiple meshes, each subsequent mesh has a special variable initiated which is the sum of the previous meshes vertices number (see 1.2.3). This variable is used to update the bone vertices index list to keep the link between the bone and the concatenated mesh.<br />
<br />
 <br />
<strong class='bbc'>2.2.3. Displaying the result</strong><br />
 We are now left with the last part of our implementation. When we initialise an instance of Object3D with our loaded Model, we replicate the Model Bone hierarchy into a corresponding ObjectBone hierarchy. This is the task of the private Object3D method ReplicateSkeletton. This method takes a Model Bone pointer as a parameter and returns an ObjectBone:<br />
<br />
 <em class='bbc'>Create an ObjectBone instance<br />
Get the Model Bone name<br />
Get a pointer to the Model Bone<br />
Initialise the Transform matrix with the Model Bone Local transform matrix<br />
For each Model Bone children</em> Recursively replicate the Model Bone children<br />
Add to the ObjectBone children list the result of the replication  Whoa! What is that transform matrix? This matrix variable within the Object Bone class is used to hold a local transform matrix before any matrix calculation. We will come back to that matrix in the 3<sup class='bbc'>rd</sup> chapter on animations. Suffice to say it is just a copy of the local transform matrix.<br />
<br />
 Once the skeleton is replicated, we clear the skinned mesh in Object3D then we call our Update method. This method is modified to calculate all the matrices before skinning the mesh. This calculation is done by the function CalcAttitude with two parameters: the current ObjectBone and its immediate parent:<br />
<br />
 Calculate the current ObjectBone combined and final matrices.<br />
For each children ObjectBone recursively call this function. It's pretty straight forward code.<br />
<br />
 Eventually we call the SkinMesh method to recursively process each ObjectBone to transform each bone vertex by the Final Matrix and the bone weight list.<br />
<br />
 The character is ready to display. Note that we put the Update method in the idle function: this means that our skinned mesh is calculated back at each call of our Idle function.<br />
<br />
 <br />
<strong class='bbc'>3. Animating the model</strong><br />
 All that is left is to parse and display the animation sets of our model. The example code in Sample3.zip builds on the previous one to support animation information.<br />
<br />
 <br />
<strong class='bbc'>3.1. Design</strong><br />
 <br />
<strong class='bbc'>3.1.1. Descriptions</strong><br />
 Animating a skinned model is as simple as animating a cartoon character. The lead cartoonist draws key animation frames. Each of these key frames represents an important character pose at a precise time. If we were to look at key animation frames of the mouse Jerry (from Tom & Jerry), we might see 3 key frames:<br />
<br />
 <ul class='bbc'><li>Instant 0: Jerry hides a hammer behind its back. </li><li>Instant + 5 frames: Jerry brandishes the hammer over Tom's foot. </li><li>Instant + 15 frames: Jerry hammers Tom's foot.</li></ul> The other cartoonists will use these key frames to draw all the intermediate frames (meaning they will draw frames 1 to 4 and 6 to 14).<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/xfilepc/bind.png' alt='Posted Image' class='bbc_img' /></span><br />
<br />
 The animation in a 3D model is only composed of key frames with a timing identification. The Key frame is a picture at a precise moment of the skeleton position. So a key frame can be represented by a set of local transform matrix describing all the bones orientation in character space. The local transform matrix can also be decomposed into:<br />
<br />
 <ul class='bbc'><li>a scaling vector, </li><li>a translation vector, </li><li>a quaternion rotation. A quaternion is a mathematical representation of a rotation around an axis as a 4 dimensional "vector".</li></ul> Thus a local bone transformation can be either represented by a matrix or by a set of vectors and quaternions.<br />
<br />
 The programmer must calculate all the intermediate key frames by interpolating the key local bone transformations in relation to the time elapsed between two keyframes. The interpolation method is linear for matrices and vectors:<br />
<br />
 Interpolation = A + (B - A) * FrameID / DeltaKey<br />
<br />
 Where A and B are two key frames separated by DeltaKey frames, and FrameID is the frame number between both key frames.<br />
<br />
 Quaternions use spherical linear interpolation (aka SLERP):<br />
<br />
 Interpolation = A*[sin((1-Elapsed) * Angle)/sin(Angle)] + B * [sin (Elapsed * Angle) / sin(Angle)]<br />
<br />
 Where A and B are two key quaternion frames, Angle is the total angle between both quaternions and Elapsed = FrameID / DeltaKey.<br />
<br />
 In DirectX .X file, the animations are grouped into Animation Sets blocks. Within each Animation Set there is an Animation block for each animated bone. Each animation block is composed of one or many Animation Key blocks depending on the representation of the local bone transformations. The table below gives the correspondence between Key types and local bone transformation representations:<br />
<br />
   Key Type Representation   0 Quaternion rotation   1 Scaling vector   2 Translation vector   4 Matrix transformation   That's all we should know about skinned model animations.<br />
<br />
 Now let's define our list of desired functionalities:<br />
<br />
 <ul class='bbc'><li>Extract all the animation sets. </li><li>Map the animations to the model bones. </li><li>Calculate the animation matrices. </li><li>Display the animated model. </li><li>Switch between animation sets.</li></ul> <br />
<strong class='bbc'>3.1.2. Code design</strong><br />
 The design to store animation sets is straightforward:<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/xfilepc/Model3.png' alt='Posted Image' class='bbc_img' /></span><br />
<br />
 The MaxKey member variable in the animation set class stores the last key frame timing index. Each animation set stores a list of animation description. An animation description corresponds to a bone. Inside an animation description, there is a list of each type of transformation representation possible. A transformation structure follows the same template as the Rotate Key below:<br />
<br />
  typedef struct {    Uint32 Time;    Frm::Quaternion Rotation } RotateKey;  The responsibility to calculate the new local transformation matrix is given to our Object3D class: <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/xfilepc/Object3D3.png' alt='Posted Image' class='bbc_img' /></span><br />
<br />
 Whoa! That looks complex. If we compare with the design in chapter 2, we see that Object3D takes an additional pointer to an animation set: the Object3D stores the current animation set played. It also has a new method MapAnimation. This method is called when the user switches animations to change the current animation set pointer and update the ObjectBone class.<br />
<br />
 The ObjectBone class gets a pointer to the animation class corresponding to its bone name reference. The Object3D method MapAnimation maps the animation to the ObjectBone. ObjectBone also gets a new method CalcAnimation that calculates the local transformation matrix from the current animation timing. So far, so good.<br />
<br />
 <br />
<strong class='bbc'>3.2. Implementation</strong><br />
 <br />
<strong class='bbc'>3.2.1. Parsing the file</strong><br />
 We add to the main parsing loop a new method to process animations sets. The pseudo-code:<br />
<br />
 <em class='bbc'>Create an instance of an AnimationSet object<br />
Get the Animation Set name<br />
If there is no name, we assign a name.<br />
While we have not reached the end of the block</em> <em class='bbc'>Read the block name (ProcessBlock)</em> If the block name is recognised, we process it.<br />
Else avoid the block (AvoidTemplate)  <em class='bbc'>Once the animation set is processed, we add it to the model's list of sets.</em> Now let's process animation blocks:<br />
<br />
 <em class='bbc'>Create an instance of an Animation object<br />
While we have not reached the end of the block</em> <em class='bbc'>Read the block name (ProcessBlock)</em> If the block name is recognised, we process it.<br />
If it is an open brace, we read in the Bone name<br />
Else avoid the block (AvoidTemplate)  <em class='bbc'>When the animation is processed, we add it to the AnimationSet animation list</em> There are animation key blocks inside each animation. We process the animation key block:<br />
<br />
 <em class='bbc'>Read in the type of transformation<br />
Read in the number of transformations stored in the animationkey<br />
Switch according to the type of transformation</em> <em class='bbc'>For each transformation listed</em> Create a transformation key<br />
Read in the Timing<br />
Read in the transformation data<br />
Push the transformation key to the Animation corresponding transformation key.   Now we are ready.<br />
<br />
 <br />
<strong class='bbc'>3.2.2. Displaying a single animation set</strong><br />
 Displaying the animated model is another matter. We setup as before in sample 2. The difference resides in that we call two new methods of Object3D for animation:<br />
<br />
 <ul class='bbc'><li>MapAnimationSet: there are two versions of that function. One uses a string as a parameter, the other an index number. This function will retrieve the animation set either by name or by index and map all the enclosed Animation instances to the ObjectBone hierarchy. </li><li>SetAnimationStep: sets up the step increase for the animation. At each timer call (or user keypress like in the sample), the animation set will advance the main animation set time counter by this step.</li></ul> The drawing steps are almost the same:<br />
<br />
 Clear the skinned mesh in Object3D<br />
Calculation the animation set local transform matrices<br />
Update the skinned mesh. The new step is the calculation of each bone local transform matrices. This step calls a recursive private method CalcAnimation, which:<br />
<br />
 <em class='bbc'>Calls the animation method of the ObjectBone passed in parameter<br />
For each children ObjectBone</em> Calls CalcAnimation(children ObjectBone)  The animation method of the ObjectBone does the following: If no animation instance is linked to that bone, bail out.<br />
<br />
 <em class='bbc'>If the transformations are expressed as matrices=</em> Advance the internal matrix animation index according to the main Time count<br />
If we are at the last matrix index use the last matrix as a transform matrix<br />
Else interpolate the transform matrix between this matrix index and the next using the Time count parameter. <em class='bbc'>Else</em> <em class='bbc'>Set the transform matrix to identity<br />
If there are rotations</em> Advance the internal rotation animation index according to the main Time count<br />
If we are at the last rotation index multiply use the last quaternion<br />
Else interpolate the rotation quaternion between this rotation index and the next using the Time count parameter.<br />
Convert quaternion to a rotation matrix<br />
Multiply the transform matrix by the rotation matrix obtained <em class='bbc'>If there are scalings</em> Advance the internal scaling animation index according to the main Time count<br />
If we are at the last scaling index multiply use the last vector<br />
Else interpolate the scaling vector between this scaling index and the next using the Time count parameter.<br />
Convert the scaling vector to a scaling matrix<br />
Multiply the transform matrix by the scaling matrix obtained<br />
If there are translations<br />
Advance the internal translation animation index according to the main Time count<br />
If we are at the last translation index multiply use the last translation vector<br />
Else interpolate the translation vector between this translation index and the next using the Time count parameter.<br />
Convert the translation vector to a translation matrix<br />
Multiply the transform matrix by the translation matrix obtained   As you can see, we either use an interpolated matrix or a combined transformation matrix. Be aware that matrix multiplication is not commutative: the multiplication of rotation, scaling and translation matrices must always be done in that order.<br />
<br />
 Now that we have our new local transform matrices, we can calculate our final matrices as usual and obtain our animated skinned mesh.<br />
<br />
 <br />
<strong class='bbc'>Conclusion</strong><br />
 Whew, that was a long tutorial. I hope you liked it. You are free to use the sample code as you see fit.<br />
<br />
 Enjoy!<br />
<br />
 Ghostly yours,<br />
Red<br />
<br />
 <br />
<strong class='bbc'>References</strong><br />
 [MSDN]<br />
<a href='http://msdn.Microsoft.com/archive/en-us/directx9_c/directx/graphics/reference/fileformat/xfileformat.asp' class='bbc_url' title='External link' rel='nofollow external'>msdn.Microsoft.com/archive/en-us/directx9_c/directx/graphics/reference/fileformat/xfileformat.asp</a><br />
 This document describes the full format of a text and binary X File. You can also find this document in the DirectX SDK documentation.<br />
<br />
 [WML]<br />
<a href='http://www.geometrictools.com/Mathematics.html' class='bbc_url' title='External link' rel='nofollow external'>http://www.geometric...athematics.html</a><br />
These are the source code for mathematics objects. I urge you to look at them since you can directly reuse them as such in your source code. (see the license <a href='http://www.magic-software.com/License/WildMagic.pdf' class='bbc_url' title='External link' rel='nofollow external'>http://www.magic-sof...e/WildMagic.pdf</a>)<br />
<br />
 [LUNA]<br />
Skinned Mesh Character Animation with Direct3D 9.0b - FrankLuna<br />
<a href='http://www.moon-labs.com/' class='bbc_url' title='External link' rel='nofollow external'>www.moon-labs.com</a><br />
Very interesting article<br />
<br />
 [XBDEV]<br />
<a href='http://www.xbdev.net/3dformats/x/xfileformat.php' class='bbc_url' title='External link' rel='nofollow external'>www.xbdev.net/3dformats/x/xfileformat.php</a><br />
Some tutorials and descriptions of 3D file formats. A good read.<br />
<br />
 [ADAMS]<br />
<a href='http://www.gamedev.net/columns/books/bookdetails.asp?productid=422' class='bbc_url' title=''>Programming Role Playing Games with DirectX</a> - Jim Adams - Premier Press<br />
ISBN: 1-931841-09-8<br />
<br />
]]></description>
		<pubDate>Wed, 30 Mar 2005 15:11:50 +0000</pubDate>
		<guid isPermaLink="false">00c1de56b1cbab48f9869c1460d70e76</guid>
	</item>
	<item>
		<title>Occlusion Culling Using DirectX 9</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/occlusion-culling-using-directx-9-r2128</link>
		<description><![CDATA[<br />
<strong class='bbc'>Introduction to Occlusion Culling</strong><br />
 Object culling is a very important facet of graphics programming. It is incredibly wasteful and time consuming to render objects that are not even going to be visible to the user. However, it is critical to optimize the culling process itself. Often, it can use up a lot of processing time instead of saving it.<br />
<br />
 Even though the culling process needs to be optimized to every extent possible, numerous traditional methods, which have proven themselves to be fast and adequate enough for standard situations, leave much to be desired. Some cull too many objects, and others do not perform enough culling.<br />
<br />
 The theory of occlusion culling spawns from the fact that even though an object is inside the camera frustum, it could still be hidden and out of view.<br />
<br />
 <br />
<br />
   <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/occlusionculling/scene.jpg' alt='Posted Image' class='bbc_img' /></span><br />
<strong class='bbc'>Diagram 1.1:</strong> Example scene layout   <br />
<br />
   <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/occlusionculling/render.jpg' alt='Posted Image' class='bbc_img' /></span><br />
<strong class='bbc'>Diagram 1.2:</strong> Example scene render   Here, as Diagram 1.1 shows, five primitives are displayed in a scene. However, in the final render (Diagram 1.2), only 3 of them are actually visible. Even though those other two objects turn out to be hidden, they are still rendered, wasting a lot of time. A simple frustum-based culling procedure would still result in the objects being rendered, since they are inside the camera’s view.<br />
<br />
 Occlusion-based culling procedures are used to determine which objects will actually be visible. Only those objects will actually be rendered, thus saving loads of time. An occluder is an object that hides other objects (for example, the large red box in Diagram 1.1). Half-occluded objects are partly visible (the blue pentagon and purple wedge), and are still rendered. Fully-occluded objects are completely hidden (the green sphere and orange box), and are excluded from being rendered.<br />
<br />
 For more background information on occlusion culling, please refer to <a href='http://www.gamasutra.com/features/19991109/moller_haines_01.htm' class='bbc_url' title='External link' rel='nofollow external'>Occlusion Culling Algorithms</a>, by Tomas Möller and Eric Haines.<br />
<br />
 <br />
<strong class='bbc'>Introduction to IDirect3DQuery9</strong><br />
 The IDirect3DQuery9 interface is one of the new features of DirectX9. It allows developers to access a wealth of statistics, including optimization information, objects handled by the resource manager, and triangle processing.<br />
<br />
 IDirect3DQuery9 can also perform occlusion queries, which calculate the number of pixels visible on the screen. Only pixels that were rendered between the query start and the query finish are included in this count. If the result is zero, the vertices rendered are fully occluded, meaning they are not visible from the current camera position. So, if the occlusion result is greater than zero, the vertices rendered are visible to the user.<br />
<br />
   Query Type Datatype Use   D3DQUERYTYPE_VCACHE D3DDEVINFO_VCACHE Information about optimization, pertaining to data layout for vertex caching   D3DQUERYTYPE_RESOURCEMANAGER D3DDEVINFO_RESOURCEMANAGER Number of objects sent, created, evicted, and managed in video memory   D3DQUERYTYPE_VERTEXSTATS D3DDEVINFO_D3DVERTEXSTATS Number of triangles that have been processed and clipped   D3DQUERYTYPE_EVENT bool For any and all asynchronous events issued from API calls   D3DQUERYTYPE_OCCLUSION DWORD The number of pixels that pass Z-testing, or are visible on-screen.   <strong class='bbc'>Table 2.1:</strong> Uses of IDirect3DQuery9   The ATI <a href='http://www.ati.com/developer/samples/dx9/OcclusionQuery.html' class='bbc_url' title='External link' rel='nofollow external'>Occlusion Query</a> demo conveys the basics of IDirect3DQuery9 implementation.<br />
<br />
 <br />
<strong class='bbc'>Occlusion Culling with DirectX9</strong><br />
 The emergence of IDirect3DQuery9 provides an easy way to implement effective occlusion culling. The basic process is presented below:<br />
<br />
 <ul class='bbcol decimal'><li>Render every object's bounding mesh </li><li>For every object:<ul class='bbcol decimal'><li>Begin query </li><li>Re-render the bounding mesh </li><li>End query </li><li>Retrieve occlusion query data. If the pixels visible are greater than zero, the object should be rendered. Otherwise, the object should be occluded from rendering.</li></ul></li></ul> <br />
<strong class='bbc'>Step 1</strong><br />
 The actual mesh contains too many vertices to use in the occlusion culling process, so a bounding mesh, with a much lower vertex count, will be used as a substitute. Why use a bounding mesh instead of a bounding box or sphere?<br />
<br />
 <br />
<br />
   <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/occlusionculling/Bounding%20Types.jpg' alt='Posted Image' class='bbc_img' /></span><br />
<strong class='bbc'>Diagram 3.1:</strong> Types of bounding volumes   Diagram 3.1 shows multiple types of bounding volumes, including box, sphere, and mesh. Note that the number of vertices of the sphere and mesh are the same, in this particular case. However, even though the vertex count is close, the fit of the volumes drastically varies. The bounding mesh is the only volume that truly approximates the original mesh well enough to be accurate. This is very important in the occlusion process, as a large amount of vertices may be mistakenly rendered or excluded based on their bounding volume.<br />
<br />
 However, a bounding mesh cannot be calculated through an algorithm like a bounding box or mesh can. It needs to be modeled and loaded at runtime, just like a normal mesh.<br />
<br />
 Each object’s bounding mesh is rendered first to make sure the entire scene is present in the Z-buffer. If the occlusion query were to take place before all the objects were present in the Z-buffer, then the object being queried could mistakenly be found to be visible, even though it would actually be occluded in the final scene.<br />
<br />
 <br />
<strong class='bbc'>Step 2</strong><br />
 Now that every object's bounding mesh is in the Z-buffer, the same thing must be done again, except this time, the occlusion query is used to determine each object's visibility status. If the query finds zero visible pixels, the object is excluded from the final, full-scale rendering. If the query finds one or more visible pixels, the object is included in the render.<br />
<br />
 It is important to note that the occlusion cull rendering does not take place on the primary, full-size surface. A much smaller surface (320 pixels by 240 pixels seems to work well) is used to improve performance.<br />
<br />
 <br />
<strong class='bbc'>The Code</strong><br />
 <br />
<strong class='bbc'>Type Declarations</strong><br />
 SObject (Code Listing 4.1) is the main object entity. CMesh is a class that encapsulates the loading, rendering, and release of an ID3DXMesh interface.<br />
<br />
  struct SObject { 	CMesh* meshReference;    // Reference to a mesh object 	CMesh* boundingMesh; 	// Reference to low-poly bounding mesh 	D3DXVECTOR3 pos;     	// Position of this object 	D3DXMATRIX matTranslate; // Translation matrix for this object 	bool render;         	// If true, render the object 	float distanceToCamera;  // The distance to the camera (player position)            // Constructor 	SObject( CMesh* meshRef, CMesh* boundMesh, D3DXVECTOR3 position ) 	{     	meshReference = meshRef;          boundingMesh = boundMesh;     	pos = position;     	render = false;     	distanceToCamera = 0.0f; 	} }; Code Listing 4.1: SObject definition  <br />
<strong class='bbc'>Object Declaration</strong><br />
 For the occlusion process, interfaces of LPDIRECT3DQUERY9, LPD3DXRENDERTOSURFACE, LPDIRECT3DSURFACE9, and LPDIRECT3DTEXTURE9 need to be declared.<br />
<br />
  LPDIRECT3D9 d3dObject;             	// Direct3D Object LPDIRECT3DDEVICE9 d3dDevice;       	// Direct3D Device LPDIRECT3DQUERY9 d3dQuery;         	// The occlusion query LPD3DXRENDERTOSURFACE occlusionRender; // Occlusion's render to surface LPDIRECT3DSURFACE9 occlusionSurface;   // Occlusion's surface that it uses LPDIRECT3DTEXTURE9 occlusionTexture;   // Texture to get surface from std::vector objects;          // Vector of objects<br />
<br />
Code Listing 4.2: Declarations of objects pertaining to the occlusion culling procedure   <br />
<strong class='bbc'>Setting up the Occlusion Objects</strong><br />
 The query itself must be created, along with the texture and the render-to-surface. D3DUSAGE_RENDERTARGET is used during the creation of the texture, since it will be rendered to. The surface itself is obtained through the GetSurfaceLevel() function of LPDIRECT3DTEXTURE9. A Z-buffer format of D3DFMT_D16 is used for the LPD3DXRENDERTOSURFACE interface, as it will be needed for use.<br />
<br />
  //----------------------------------------------------------------------------- // Name: SetupOcclusion() // Desc: Create the objects needed for the occlusion culling //----------------------------------------------------------------------------- HRESULT SetupOcclusion() { 	// Create the query 	d3dDevice->CreateQuery( D3DQUERYTYPE_OCCLUSION, &d3dQuery ); 	// Get the display mode to obtain the format 	D3DDISPLAYMODE mode; 	d3dDevice->GetDisplayMode( 0, &mode ); 	// Create the texture first, so we can get access to it's surface 	if( FAILED( D3DXCreateTexture( d3dDevice, 320, 240, 1, D3DUSAGE_RENDERTARGET,                                    mode.Format, D3DPOOL_DEFAULT, &occlusionTexture ) ) ) 	{     	return E_FAIL; 	} 	// Obtain the surface (what we really need) 	D3DSURFACE_DESC desc; 	occlusionTexture->GetSurfaceLevel(0, &occlusionSurface); 	occlusionSurface->GetDesc(&desc); 	// Create the render to surface 	if( FAILED( D3DXCreateRenderToSurface( d3dDevice, desc.Width, desc.Height, desc.Format,                                            TRUE, D3DFMT_D16, &occlusionRender ) ) ) 	{     	return E_FAIL; 	} 	return S_OK; } Code Listing 4.3: The SetupOcclusion() function  <br />
<strong class='bbc'>Culling the Objects</strong><br />
 The OcclusionCull() function implements the theory presented earlier. First, the LPD3DXRENDERTOSURFACE is activated and cleared. Second, every object's bounding mesh is rendered. The meshes are re-rendered and then their occlusion queries are retrieved. Finally, the surface's scene is ended and deactivated.<br />
<br />
  //----------------------------------------------------------------------------- // Name: OcclusionCull() // Desc: Cull the objects //----------------------------------------------------------------------------- HRESULT OcclusionCull() { 	// Begin occlusionRender 	if( SUCCEEDED( occlusionRender->BeginScene( occlusionSurface, NULL ) ) ) 	{     	// Clear the occlusionRender's surface     	d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,                         	D3DCOLOR_XRGB( 200, 200, 200 ), 1.0f, 0);     	// First, render every object's bounding box     	for(int i = 0; i < objects.size(); i++ )     	{         	objects[i].boundingMesh->Render( d3dDevice, objects[i].matTranslate );     	}     	// Now, render each box again, except this time, count how many pixels are visible     	// by using an occlusion query. We are guaranteed to get the right amount,     	// since all the bounding boxes have already been rendered     	for( int i = 0; i < objects.size(); i++ )     	{         	// Start the query         	d3dQuery->Issue( D3DISSUE_BEGIN );         	// Render         	objects[i].boundingMesh->Render( d3dDevice, objects[i].matTranslate );         	// End the query, get the data         	d3dQuery->Issue( D3DISSUE_END );         	// Loop until the data becomes available         	DWORD pixelsVisible = 0;                    while (d3dQuery->GetData((void *) &pixelsVisible,                                   	sizeof(DWORD), D3DGETDATA_FLUSH) == S_FALSE);         	if( pixelsVisible == 0 )             	objects[i].render = false; // No pixels visible, do not render         	else         	objects[i].render = true;      // Pixels visible, render     	}     	// End the occlusion render scene     	occlusionRender->EndScene( 0 );                // User is pressing the 'M' key, save this buffer to .BMP file     	if( keys['M'] )         	D3DXSaveSurfaceToFile( "buffer.bmp", D3DXIFF_BMP,                                    occlusionSurface, NULL, NULL ); 	} 	return S_OK; } Code Listing 4.4: The OcclusionCull() function  <br />
<strong class='bbc'>The Render Loop</strong><br />
 The render loop consists of building all the matrices, including the camera and object transforms, then culling. Finally, the objects that will be visible in the final scene are rendered.<br />
<br />
  //----------------------------------------------------------------------------- // Name: Render // Desc: Render a frame //----------------------------------------------------------------------------- HRESULT Render() { 	// Setup the matrices for this frame 	SetupMatrices(); 	// Cull the objects 	OcclusionCull(); 	if( SUCCEEDED( d3dDevice->BeginScene() ) ) 	{     	// Clear the main device     	d3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,                            D3DCOLOR_XRGB(255,0,0), 1.0f, 0 );     	// Render the appropriate objects     	// Leave out objects that are occluded     	for( int i = 0; i < objects.size(); i++ )     	{         	if( objects[i].render )         	{             	objects[i].meshReference->Render( d3dDevice, objects[i].matTranslate );         	}        }           	d3dDevice->EndScene(); 	}            // Present the scene 	d3dDevice->Present( NULL, NULL, NULL, NULL ); 	return S_OK; } Code Listing 4.5: The simplified render loop  <br />
<strong class='bbc'>Conclusion</strong><br />
 <br />
<strong class='bbc'>Pros and Cons</strong><br />
 There are many pros and cons to the occlusion culling interpretation presented. It is very easy to implement, and it is very accurate and flexible. For example, objects behind a pane of glass can be culled appropriately (this can be achieved by making the glass object's bounding mesh an outline of the glass). Also, the level of accuracy and speed of the algorithm can be altered easily by changing the bounding meshes that are used. More vertices means more accurate and slower; less vertices means less accurate and faster.<br />
<br />
 However, there are numerous faults in this method. For one, it renders every object up to 3 times (twice during the culling operation, and possibly again during the primary render). This slows the cull down tremendously. Also, it requires a DirectX 9 compliant graphics card.<br />
<br />
 <br />
<strong class='bbc'>Possible Optimizations</strong><br />
 <ul class='bbc'><li>If frustum culling were to be implemented, the sectors and objects outside of the view volume could be thrown out from the start. </li><li>The size of the occlusion texture and surface could be decreased, although smaller sizes tend to decrease the accuracy of the occlusion culling.</li></ul> <br />
<strong class='bbc'>The Demo</strong><br />
 Included is a <a href='http://downloads.gamedev.net/features/programming/occlusionculling/dxocclusion.zip' class='bbc_url' title='External link' rel='nofollow external'>fully working demo</a> (with source code) that implements the method discussed. It renders a small forest of 300 randomly placed trees, totaling over 100,000 vertices. The demo requires a DirectX9 compliant card to run. The controls are as follows:<br />
<br />
 <ul class='bbc'><li>WASD: Slide camera </li><li>IJKL: Rotate camera </li><li>M: Save bitmap of occlusion surface (saves to buffer.bmp)</li></ul> <br />
<br />
   <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/occlusionculling/demo.jpg' alt='Posted Image' class='bbc_img' /></span><br />
Diagram 5.1: Demo screenshot   <br />
<strong class='bbc'>Final Thoughts</strong><br />
 Well, thank-you for checking out my implementation of occlusion culling. I hope that you gained some knowledge from it. I welcome any ideas, suggestions, or corrections.<br />
<br />
 Dustin Franklin<br />
<a href='mailto:dustinhimer@comcast.net' title='E-mail Link' class='bbc_email'>dustinhimer@comcast.net</a><br />
<br />
 Dustin Franklin (aka circlesoft) is a high school student in Mount Joy, Pennsylvania. You can feel free to email him at <a href='mailto:dustinhimer@comcast.net' title='E-mail Link' class='bbc_email'>dustinhimer@comcast.net</a> or contact him through MSN (at that address) or AIM (dutsin2323).<br />
<br />
]]></description>
		<pubDate>Fri, 06 Aug 2004 15:56:25 +0000</pubDate>
		<guid isPermaLink="false">6d620ec78d3291c35fc5c59d91cf2548</guid>
	</item>
	<item>
		<title>Getting DirectX 8.1 to Work with Dev-C++</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/getting-directx-81-to-work-with-dev-c-r2067</link>
		<description><![CDATA[

<p class="c1"><span class="title">Getting DirectX 8.1 to Work with Dev-C++ 4.9.8.1</span><br>
<span class="author">by <a href="http://www.Sherman3D.com">Sherman Chin</a></span></p>
<p>I have noticed that many people would like to know how to use DirectX with Dev-C++ because the beta version of Dev-C++ does not seem to work with DirectX very well until you do some tweaking and
the official Dev-C++ site itself does not provide much help. So, I will write about how to get the <a href="http://www.bloodshed.net/dev/devcpp.html">free Dev-C++ compiler</a> to work with DirectX
8.1 and thus, provide the user with a major tool that is needed to code state-of-the-art games . Now, even my game engine (www.Sherman3D.net/download/files/VFVer1.zip) is fully compilable in Dev-C++
4.9.8.1.</p>
<p>Want to know how? Then follow these easy steps (they might look simple now but it took a lot of trial and error):</p>
<ol>
<li>Install Dev-C++</li>
<li>Use the "Check for Updates/Packages" option in the Tools menu.</li>
<li>Download the Direct9 package (which also includes DirectX 8.1)</li>
<li>Select the "Project Options" item from the Project menu. Click on the Parameters tab.</li>
<li>In the "Linker" section, click on "Add Library or Object" and add the necessary library files for DirectX. Here is what my list looks like:
<pre>
-lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32
../../../Dev-Cpp/lib/libdsound.a
../../../Dev-Cpp/lib/libdxguid.a
../../../Dev-Cpp/lib/libd3d8.a
../../../Dev-Cpp/lib/libd3dx8d.a
../../../Dev-Cpp/lib/libd3dxof.a
../../../Dev-Cpp/lib/libdplayx.a
../../../Dev-Cpp/lib/libwinmm.a
../../../Dev-Cpp/lib/libdxapi.a
../../../Dev-Cpp/lib/libwsock32.a
../../../Dev-Cpp/lib/libdinput8.a
../../../Dev-Cpp/lib/dinput.lib
../../../Dev-Cpp/lib/strmiids.lib
</pre>
<p>As you can see, I am using Direct3D, DirectSound, DirectPlay, DirectInput and DirectShow. There are a few other necessary Windows libraries as well. I also added dinput.lib from the Microsoft
DirectX 8.1 SDK (download it from Microsoft's site) because the one included with Dev-C++ (libdinput.a) seems to be missing some required data formats. The strmiids.lib, a DirectShow library for
playing cutscenes, is not present in Dev-C++ so I added it from the DirectX 8.1 SDK as well.</p>
</li>
<li>You are bound to run into compile time errors as the *.a DirectX library files that come with Dev-C++ have some typo errors in them. They are usually quite easy to fix though. Here is an example:
<pre>
Error message: something or other already defined in example.h
Reason: #ifdef _EXAMPLE_
Correction: #ifdef _EXAMPLE_H
</pre>
<p>I can't really remember the exact typos as I corrected all of them without keeping the original files.</p>
<p>In dxfile.h, delete the last line.<br>
In dmdls.h, change #ifndef MAKE_FOURCC to #ifndef MAKEFOURCC<br>
In dmdls.h, change WLOOP[1] to Wloop[1];<br>
In strmif.h, change #ifndef _WINGDI_ to #ifndef _WINGDI_H</p>
</li>
<li>The biggest problem for me was getting DirectShow to work. First of all, comment out all the VMR stuff in strmif.h. I seem to get a GUID conflict if I don't. So just comment out lines
20551-20556, 28733-28759, 28759 till 28945. It is going to be a tedious process as there are many /**/ in between and you need to do a // for each line lest you miss out one of those #endif's like I
originally did >_<.</li>
<li>Another DirectShow problem is that you need to include atlbase.h to for automatic conversions from char to wchar but Dev-C++ doesn't come with atlbase.h. I did the filename conversion manually
using a Win32 function. Replace wcscpy(wFileName, lpszMedia); (the function that is used by the DirectShow examples in the SDK) with
<pre class="code">
   MultiByteToWideChar(CP_ACP    ,     // code page
                       MB_PRECOMPOSED, // character-type options
                       lpszMedia,      // address of string to map
                       -1,             // number of characters in string
                       wFileName,      // address of wide-character buffer
                       MAX_PATH        // size of buffer);
</pre></li>
<li>Dev-C++ doesn't seem to support the allocation of memory space with the "new" command using a variable for the size of memory to allocate. So, if you have something like this:
<p class="code">m_Polygons = new sPolygon[m_NumPolygons]();</p>
<p>Replace it with:</p>
<p class="code">(void*)m_Polygons = malloc(m_NumPolygons*sizeof(sPolygon));</p>
</li>
<li>Dev-C++ uses the debug libraries of DirectX so please put d3dx8d.dll (which can be found in the DLL subdirectory of Dev-C++) in your program's directory when you distribute it.</li>
<li>If you are using Windows resource files (*.rc), make sure to include "windows.h" in the resource file itself and remove any reference to "afxres.h". Open the resource header file, "resource.h"
and write a definition for IDC_STATIC in the list.</li>
</ol>
<p>There might be some other minor complications when using Dev-C++ with DirectX 8.1 so please post your questions at <a href="http://forum.Sherman3D.com">http://forum.Sherman3D.com</a> and I will
try to help the best I can.</p>

]]></description>
		<pubDate>Tue, 16 Mar 2004 18:15:32 +0000</pubDate>
		<guid isPermaLink="false">366c97caa1e66d39a0c21edb8fdc9caf</guid>
	</item>
	<item>
		<title>Real-Time Cartoon Rendering with Direct-X 8.0 H...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/real-time-cartoon-rendering-with-direct-x-80-h-r2021</link>
		<description><![CDATA[<br />
<strong class='bbc'>Introduction</strong><br />
 In an era of increasingly realistic game graphics, buzzwords like bump-mapping and per-pixel lighting take all the glory. The programmable hardware in today's consumer graphics cards does make these highly-realistic techniques available in real-time, but this same hardware makes stylized rendering available as well. Non-photorealistic rendering (NPR) is a branch of 3D graphics that has yet to be fully tapped for game use. With the advent of programmable shaders, a whole range of NPR styles are available that previously existed only in the pre-rendered domain.<br />
<br />
 This article focuses on using programmable hardware for a popular NPR technique: creating cartoon-like graphics from 3D models. Games are released every year that are based on cartoons but fail to convey the same look and feel as their subject matter. This work attempts to make cartoon-style graphics available to 3D game developers. It culminates in a powerful, fast cartoon renderer that will run on any Direct-X 8.0 compatible hardware.<br />
<br />
 We'll start by taking a quick look at our selected hardware, continue with a brief definition of cartoon rendering, describe the implementation details of our renderer, and finish with some benchmarks and ideas for the future. As you will see, our renderer is accessible: It runs on ATI and nVidia hardware and even the X-Box console. It is flexible: we can change the thickness, color, and style of our ink lines. We can modify shading styles by altering a single texture. It is fast: it runs at game-acceptable frame rates for scenes in excess of 40,000 polygons. Best of all, the frames generated by our renderer look great!<br />
<br />
 <br />
<strong class='bbc'>Limitations of our Hardware</strong><br />
 Since the goal of this article is to create a DirectX 8.0 compatible cartoon renderer, there are certain things regarding our selected hardware that we should be aware of:<br />
<br />
 Vertex Shaders: We are limited to Vertex Shader language version 1.1 (VS 1.1) which means the 2.0 control instructions (if, call, etc.) will not be available to us. We are also limited in the number of registers and total instructions we can use, although all of the vertex programs in this article stay well under these limits.<br />
<br />
 Pixel Shaders: The first incarnation of the pixel shader language, PS 1.1, is a far-cry from what is available on more modern pixel shader hardware. The useful instructions that were added in language versions 1.2, 1.3, 1.4 and 2.0 will not be available. We are also limited to eight instructions per pixel program (sixteen if we are good at co-issuing instructions to the RGB and alpha pipelines).<br />
<br />
 Texture stages: We have only four texture stages, which is somewhat unfortunate, as the outlining technique we use would be more accurate with five. On the other hand, the 5<sup class='bbc'>th</sup> stage wouldn't be all that useful without a higher pixel shader instruction limit, so the absence of the additional stage is somewhat moot.<br />
<br />
 Rendering passes: Ideally, the entire scene would be rendered in one pass, but without the multiple render target support that exists on more modern hardware, our renderer is limited to a two-pass approach.<br />
<br />
 <br />
<strong class='bbc'>What Is Cartoon Rendering?</strong><br />
 Cartoon rendering (sometimes referred to as cel-shading) has two major constituents: painting and inking. In the traditional sense, painting is filling a cartoon object with areas of color. A simple cartoon will use solid colors for different objects (flat-shading), but more complex cartoons use two or even three colors for each material. This is often called stepped-shading because the color "steps" dramatically from the shadow color to the highlight color. The stepped-shading effect looks quite different from realistic rendering techniques as there isn't a smooth gradient between the shadowed and highlighted areas of an object.<br />
<br />
 Inking mimics a traditional cartoonist's use of black ink to create a stylized world. In a cel-shaded scene, each object needs an "ink" line to separate it from other objects. It also needs lines to emphasize its features, to show sharp edges, and to separate any areas of differing color. In the examination of our renderer, we will look at the algorithms and implementations for painting and inking separately, as it represents a logical division of concepts.<br />
<br />
 <br />
<strong class='bbc'>The Evolution of a Cartoon Renderer</strong><br />
 The cartoon renderer discussed in this article has been through many incarnations. A great deal of research and experimentation went into developing the current implementation of both the painting and inking components of the renderer. While the details of the different methods I have tested are beyond the scope of this article, more information about these methods accompanies the sample program and source code available from <a href='http://downloads.gamedev.net/features/programming/cartoon/DemoProgram.zip' class='bbc_url' title='External link' rel='nofollow external'>here</a>. With that brief caveat, let's get our hands dirty with the renderer itself.<br />
<br />
 <br />
<strong class='bbc'>Painting</strong><br />
 The first part of our cartoon renderer is the painter. As a minimum, a painter needs to support rendering an object with solid colors. A more advanced painter will generate stepped shadows and highlights using light direction, vary this shading with brightness, and even support multiple light sources.<br />
<br />
 Displaying objects with solid colors is rather trivial, but some research has been done into different stepped shading techniques. According to Claes [1], it is possible to choose a constant color (either highlight or shadow) for each polygon, but better results occur if some polygons are subdivided into two shades using linear interpolation. In order to use programmable hardware to achieve a similar effect, it is necessary to use the light direction vector and vertex normal to to sample a specialized shading texture. This is similar to the algorithm used by Lake [2].<br />
<br />
 The simplest hardware implementation of a painting algorithm that supports stepped shading uses a one-dimensional texture. A vertex program takes the direction of a single light and calculates the dot-product between the light and the vertex normal. A value of one means that the two vectors point in exactly the same direction, but as the angle between the two vectors increases, the value decreases. We can clamp the negative values to zero and use this result as a texture coordinate. A coordinate of 1.0 represents normals that are facing the light and should be bright, and a coordinate of 0.0 will represent normals that are facing away from the light and should be dark.<br />
<br />
 Our painter improves on this basic algorithm in three ways. Firstly, we calculate the dot-product per-pixel instead of per-vertex. This smoothes jagged shadow lines that can appear on low-poly models. Secondly, we support two directional lights for each mesh. Thirdly, we scale the texture coordinates with the brightness of the light, allowing brighter lights to expand the highlighted areas or even use an extra highlight shade.<br />
<br />
 The relevant part of the vertex program for our painter is shown in listing 1. It puts the transformed vertex normal into the first set of texture coordinates and the angle of the two lights in the second and third sets of texture coordinates. The light vectors are scaled by the brightness of the light before they are passed to the vertex program. This has the effect of scaling the eventual dot-product between the light and normal vectors.<br />
<br />
 Listing 1<br />
<br />
  vs.1.1  ; painter vertex shader dcl_normal v3 ; transform normal dp3 r1.x, v3, c[INVERSE_WORLD_MATRIX] dp3 r1.y, v3, c[INVERSE_WORLD_MATRIX_1] dp3 r1.z, v3, c[INVERSE_WORLD_MATRIX_2] ; renormalize it dp3 r1.w, r1, r1 rsq r1.w, r1.w mul r1, r1, r1.w ; stick normal vector in first stage mov oT0, r1 ; stick first light position in second stage mov oT1, c[LIGHT_POSITION_A] ; stick second light position in third stage mov oT2, c[LIGHT_POSITION_B]  Most of the work is done in the pixel program that is shown in listing 2. The first stage contains a normalizing cube-map. This is a specialized cube-map that converts interpolated normal values into renormalized values biased into the 0.0 to 1.0 range. This is more accurate than using the texcoord instruction to grab the coordinates directly, as linearly interpolated values can result in vectors with lengths less than one. Figure 1 shows how this occurs. The _bx2 instruction modifier is used to return the vectors into the proper range when they are needed for calculations.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/cartoon/Figure1.png' alt='Posted Image' class='bbc_img' /></span><br />
Figure 1: Because the vertex normal is passed to the pixel shader in texture coordinates, it is linearly interpolated per pixel. This interpolated value follows the blue line, leading to non-normalized values on smoothed polygons. The proper normal should follow the red line.<br />
<br />
 Listing 2<br />
<br />
  ps.1.1 ; painter pixel shader def c0, 0.0f, 0.0f, 0.0f, 0.75f   ; light scale def c1, 0.0f, 0.0f, 0.0f, 1.0f    ; black tex t0             	; grab the normalized normal                        ; normalizing cube map is in t0 texm3x2pad t1, t0_bx2  ; dot with light a for u value texm3x2tex t2, t0_bx2  ; dot with light b for v value                        ; 2d shade texture is in stage t2 tex t3             	; regular texture data mov r0, C_MATERIAL_DIFFUSE  ; load constant color in cnd r0, r0.a, r0, t3        ; if alpha, use color                         	; else, use texture mul r1.rgb, r0, t2          ; modulate with shading mul r0.rgb, C_LIGHT_COLOR, c0.a ; scale down light value mul_x2 r0.rgb, r0, r1       	; modulate x2 with light color  The texm3x2pad and texm3x2tex instructions are used to perform the dot-products between the light angles and the normal. The resulting two scalars are used as u and v coordinates to sample the shading texture which is placed in the third stage. As seen in figure 2, the shading texture has dark pixels at (u=0, v=0) and lightens in steps as the values increase to (u=1, v=1). The number of steps and their relative size is determined by the texture, so it is easy to create a completely different shading style by swapping in a new one.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/cartoon/Figure2.png' alt='Posted Image' class='bbc_img' /></span><br />
Figure 2: The shading texture used by our painter. Shadow shades appear in the upper left corner and lighten toward the right and bottom of the texture.<br />
<br />
 Remember that the light angle is scaled by the brightness of the light, so a half-bright light will generate texture coordinates lower than 0.5. It is therefore possible to create a highlight shade that only shows up around bright lights. This scaling also makes it possible for one of the two lights that are illuminating the model to appear brighter than the other.<br />
<br />
 Our shading is modulated with either a constant color from the material or the sample from the fourth texture stage, which can contain a standard texture. We then modulate this color with a light color that is passed to the pixel program via a constant. We use a combined light color because applying one color to some pixels and a second color to other pixels creates a gradient that spoils the stepped shading. We also overbrighten the model color based on the light color. Modulating by 2 is too extreme, so we scale the light color by 0.75 before doubling it. This results in 1.5x modulation and gives very nice results.<br />
<br />
 <br />
<strong class='bbc'>Inking</strong><br />
 The second portion of our cartoon renderer is the Inker. There are three different categories of lines that we want our inker to take care of. The first type is an outline that surrounds each model, distinguishing it from surrounding objects. The second type of line is drawn on sharp edges or creases in the model to accentuate its features. The third type of line is the characteristic line created by an artist. These lines could be used on a flat model, for example, or to emphasize a character's facial features that aren't distinct enough in geometry to generate an edge-line.<br />
<br />
 A great deal of investigation has been done into world-space line-generation techniques. Buchanan [3] recommended using an edge buffer to keep track of edge polygons. Raskar [4] developed methods of extending back-facing polygons to create outlines and edges. The researchers at nVidia [5] show how to use a vertex program to generate outlines on a model. Mitchell [6], was the first to suggest using modern hardware to create outlines by comparing pixels in image-space.<br />
<br />
 Despite the prevalence of world space techniques, edge-lines and and artist-lines almost always require the generation of new geometry and/or the maintenance of software information that doesn't translate well to programmable hardware. The vertex-shader outlining technique is reasonably effective for high-poly, smooth models, but its quality is simply unacceptable for low-poly and angular models. Programmable pixel shaders make image-space edge detection techniques possible at real-time frame rates. We are therefore going to use image-space techniques for our inker.<br />
<br />
 So, how do we use pixel programs for image filtering? It is first necessary to put the source image in all four texture stages. Then we create a vertex program that offsets the texture coordinates slightly. For example, we move the coordinates for the first stage up and to the left the equivalent of one pixel. We move the third stage down and to the right and similarly offset the second and forth stage down-left and up-right, respectively. Listing 3 shows the code for a simple vertex program that does this. The four texture stages allow a pixel program to sample four input pixels for each output pixel. It is possible to do sharpening, blurring, and even luminance edge detection in short pixel shader programs.<br />
<br />
 Listing 3<br />
<br />
  vs.1.1 ; texture coordinate offset vertex shader dcl_texcoord0 v1 mov a0.x, c[OFFSET_SET].x ; grab the proper offset ; c[OFFSET_SET].x is the number of the constant register ; that contains the first of four x and y offsets. add oT0, v1, c[a0.x + 0] add oT1, v1, c[a0.x + 1] add oT2, v1, c[a0.x + 2] add oT3, v1, c[a0.x + 3]  The only disadvantage of the image-filter approach is that it is now necessary to render every object in the scene twice: once, into the back buffer to create the cartoon shading and, again, into a texture that can be placed in the four texture stages of the image-filter pixel program. More modern hardware can use multiple render targets to do this in one pass, but our selected hardware doesn't allow it. For now, we have to live with a 50% frame rate hit that will translate into lower poly in-game models than could otherwise be used.<br />
<br />
 Our inker generates a set of lines in a texture that is the same size as the back-buffer. This texture will be applied to a single quad and rendered over the top of our shaded scene. This doesn't really constitute a third rendering pass, because only two triangles are sent to the hardware. It can have an impact on frame rate, though, as it pushes the hardware's fill-rate, especially in high-resolution modes. Remember that our pixel program will have to run once for each pixel on the screen, so higher resolution means lower frame rate. Fortunately, the impact is fairly constant for each resolution, regardless of how many polygons are in the underlying scene.<br />
<br />
 To use an image-filter for ink line generation, we need to render a version of the scene that has information encoded into color values. The RGBA components represent the only data available to our pixel program, so we need to use them wisely. We will use the alpha component to store depth information that our image-filter will turn into outlines. The RGB values will be used for both the edge-lines and the artist-lines. Edge-lines need to be generated when neighboring pixels have vertex normals that face in drastically different directions, so we need to encode these normals as RGB colors. To do this we can use the same normalizing cube-map that we used for the Painter.<br />
<br />
 Our shader supports artist-lines via two different methods. It can use info stored in vertex colors or info stored in a texture. Unfortunately, we can only generate one set of RGB values for each pixel in the scene. Therefore each set of polygons can use either edge-lines, vertex color artist-lines, or texture artist-lines, but only one of the three. It is easiest to specify the type of line per-material, so each section of an object can use a different method.<br />
<br />
 Our pixel program will calculate the dot-product between neighboring pixels to determine if an edge-line is required. It is to our advantage to encode artist-lines as normalized vectors in order to use the same dot-product method. We don't want our artist-generated colors to interfere with the normal-generated colors, so we're going to use the set of RGB encoded normals that is facing away from the camera. Essentially, we're going to use four colors that represent normals that are not in view from the current camera location. The two artist-line algorithms do this in slightly different ways.<br />
<br />
 The first method for artist-lines uses vertex-color information. We pick four colors that represent normals that are equidistant from the x-y plane and from each other and paint polygons in the model with these colors. An example of four possible vectors and colors is shown in figure 3. These four colors should be enough to generate lines on even complex models if they are used wisely. Lines will appear in between polygons that we have painted with different colors. In the renderer, a vertex program converts the colors back into normals and rotates them so they point in the same direction as the eye-to-vertex vector. This generates normals that are always pointing away from the eye and therefore colors that won't interfere with our edge-line colors.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/cartoon/Figure3.png' alt='Posted Image' class='bbc_img' /></span><br />
Figure 3: The figure shows four unit vectors that are separated from each other and a plane by approximately 45 degrees. The encoded RGB values for these vectors are included below the XYZ coordinates.<br />
<br />
 The second method uses four colors as well, but in this case we generate a dynamic 2x2 to contain them. The four normals are rotated to face the same direction as the eye-to-object vector, encoded, and placed in the texture in every frame. Because we rotate the vectors per-object, the results won't be quite as accurate as the per-vertex method. When we are close to large objects, some lines may disappear as the artist-line colors enter the same range as the edge-line colors. We sample the dynamic 2x2 texture using the pixel shader texreg2ar instruction. This instruction interprets the red and alpha values of a supplied texture as texture coordinates to sample a second texture. This essentially replaces four input colors from an artist-supplied texture with our four dynamic colors.<br />
<br />
 Our render texture now has the data needed to generate ink lines. Listing 4 shows the image-filter pixel program that does this. It compares opposite pixels, looking for differing colors and depth values. Ultimately, it depends on the one conditional instruction available in PS 1.1: cnd. This instruction will choose between two source colors and based on a single scalar. There are constant-supplied depth and edge thresholds that will specify the difference needed for RGB and alpha values to generate ink lines.<br />
<br />
 Listing 4<br />
<br />
  ps.1.1 ; inker pixel shader def c0, 0.0f, 0.0f, 0.0f, 0.9f    ; threshold for normals  def c1, 0.0f, 0.0f, 0.0f, 0.25f   ; depth threshold def c2, 1.0f, 1.0f, 1.0f, 0.0f    ; white and transparent def c3, 0.0f, 0.0f, 0.0f, -0.25f  ; depth adjustment tex t0 tex t1 tex t2 tex t3 dp3 r0.rgb, t0_bx2, t2_bx2  ; dot the normals for opposite pixels +sub r0.a, t0.a, t2.a   	; find depth differences dp3 r1.rgb, t1_bx2, t3_bx2  ; repeat for other set +sub r1.a, t1.a, t3.a mad t0.a, t0.a, c3.a, c0.a  ; scale the normal threshold with depth                         	; uses first texture stage pixel sub_x4_sat r0.rgb, r0, t0.a ; subtract the normal threshold and clamp +mad r0.a, r0.a, r0.a, c1.a ; square the differences + add threshold sub_x4_sat r1.rgb, r1, t0.a ; repeat for other set +mad r1.a, r1.a, r1.a, c1.a mul_x4_sat r0.rgb, r0, r1   ; combine the clamped normal values +add r0.a, r0.a, r1.a   	; combine the differences add r0.a, 1 - r0.b, r0.a    ; combine depth and normal values cnd r0, r0.a, C_LINE_COLOR, c2 ; set pixel line color  We also scale the edge threshold with the depth value of one of the pixels. This solves an annoying problem of smooth sections of the model turning into lines in the distance. You may need to modify the edge threshold and depth adjustment values. Optimal values depend on resolution, far plane distance, and the general look of different models in your game.<br />
<br />
 It is common for games to use partially-transparent textures for objects like fences and leaves, where modeling features in geometry would increase the polygon count drastically. This will work with our inker as long as we include alpha values when we render the object into the overlay texture. The best method for this is to use 1-bit alpha and turn on alpha-testing. Zero alpha pixels will be discarded and lines will be drawn around areas that remain visible.<br />
<br />
 Our inker also supports different line widths by changing the size of the render texture. A texture that is twice the size of the back buffer creates nice thin lines, assuming the hardware can support render surfaces that large. Smaller textures can create thicker lines, but these lines tend to look more pixilated as they thicken.<br />
<br />
 A better approach for thickening lines is to render the overlay lines into a second render texture instead of the back-buffer. This second texture is overlaid again with a "dilating" pixel program. This method is quite fast for low-resolution output, but can be limited by fill-rate in high-resolution modes. Listing 5 contains two pixel programs that use slightly different algorithms to "dilate" the original ink lines. The first pixel program thickens the lines by outputting an ink line pixel if any of the four sampled pixels are ink line pixels. The second pixel program creates smoothed lines by linearly interpolating between the line-color and transparent depending on how many ink line pixels are sampled.<br />
<br />
 Listing 5<br />
<br />
  ps.1.1 ; dilation pixel shader def c0, 0.0f, 0.0f, 0.0f, 0.25f   ; for 1/4 multiplication def c1, 0.0f, 0.0f, 0.0f, -0.75f  ; for subtracting  def c2, 1.0f, 1.0f, 1.0f, 0.0f    ; white and transparent tex t0 tex t1 tex t2 tex t3 mul r0.a, 1 - t0.a, c0.a        ; sum 1/4 of inverse samples mad r0.a, 1 - t1.a, c0.a, r0.a  ; alpha of lines are 1.0 alpha mad r0.a, 1 - t2.a, c0.a, r0.a mad r0.a, 1 - t3.a, c0.a, r0.a add_x4 r0.a, r0.a, c1.a     	; subtract .75 and mul * 4                             	; only transparent pixels will                             	; remain transparent cnd r0, r0.a, c2, C_LINE_COLOR  ; conditionally choose between                             	; transparent and line color ps.1.1  ; smooth dilation pixel shader def c0, 0.0f, 0.0f, 0.0f, 0.5f  ; smoothing threshold                             	; 0.25 = max smoothing                             	; 1.0 = no smoothing def c2, 1.0f, 1.0f, 1.0f, 0.0f  ; white and transparent tex t0 tex t1 tex t2 tex t3 mul r0.a, t0.a, c0.a        ; combine the four samples using mad r0.a, t1.a, c0.a, r0.a  ; threshold and clamp mad r0.a, t2.a, c0.a, r0.a mad_sat r0.a, t3.a, c0.a, r0.a mov r1.rgb, C_LINE_COLOR  ; create a zero alpha version + mov r1.a, c2            ; of line color lrp r0, r0.a, C_LINE_COLOR, r1  ; interpolate line color  <br />
<strong class='bbc'>Speed and Quality</strong><br />
 Figure 4 shows a frame-rate comparison using a 64 megabyte Radeon 9000 mobile card. As you can see, the speed of the painter is highly-dependant on the number of triangles in the scene. In the worst case, its speed is 67% of the speed of rendering the same polygons normally. The initial rendering of the inker is similar in speed to painter, but there is a consistent speed loss for each quad that is overlaid on the screen. This loss is about 4 ms per frame at 800x600 and about 17 ms per frame at 1280x1024. The results from this card are completely acceptable at 800x600 with the shading, outlining, and dilation turned on, and the results are passable at 1280x1024.<br />
<br />
 800 x 600<br />
<br />
     40,000 poly model 26,000 poly model 1200 poly model   Untextured Polygons 187 fps 232 640   Painter 137 173 555   Inker 91 104 150   Inker + Dilation 67 72 94   Painter + Inker 56 68 140   Painter + Inker + Dilation 46 53 89   1280 x 1024<br />
<br />
     40,000 poly model 26,000 poly model 1200 poly model   Untextured Polygons 128 fps 134 250   Painter 87 91 220   Inker 35 36 43   Inker + Dilation 22 22 25   Painter + Inker 27 28 41   Painter + Inker + Dilation 19 19 24   Figure 4: The above results were obtained using a 64 megabyte Radeon 9000 Mobile graphics card in a laptop with a 3.06 GHz processor and 512 Megabytes of RAM<br />
<br />
 Figure 5 shows a couple of screenshots from the cartoon renderer we have developed. As you can see, the results are quite satisfactory. There are only two potential problems with the quality of our renderer. First, lines will occasionally disappear or reappear as we move around a model. This is due to new pixels coming into view and therefore new edges appearing that were not visible in the previous frame. Second, the shadow-boundaries generated by our painter can appear a bit fuzzy. It is a matter of preference as to whether these soft edges improve or worsen the look of the renderer.<br />
<br />
 <br />
<br />
   <a href='http://images.gamedev.net/features/programming/cartoon/Figure5a.png' class='bbc_url' title='External link' rel='nofollow external'><img src='http://images.gamedev.net/features/programming/cartoon/figure5at.png' alt='Posted Image' class='bbc_img' /></a> <a href='http://images.gamedev.net/features/programming/cartoon/Figure5b.png' class='bbc_url' title='External link' rel='nofollow external'><img src='http://images.gamedev.net/features/programming/cartoon/figure5bt.png' alt='Posted Image' class='bbc_img' /></a>   <a href='http://images.gamedev.net/features/programming/cartoon/Figure5c.png' class='bbc_url' title='External link' rel='nofollow external'><img src='http://images.gamedev.net/features/programming/cartoon/figure5ct.png' alt='Posted Image' class='bbc_img' /></a> <a href='http://images.gamedev.net/features/programming/cartoon/Figure5d.png' class='bbc_url' title='External link' rel='nofollow external'><img src='http://images.gamedev.net/features/programming/cartoon/figure5dt.png' alt='Posted Image' class='bbc_img' /></a>   Figure 5: Screenshots from the demo program illustrating the high-quality achieved by the Cartoon Renderer. As a whole, the results are far better than the results I have seen from other methods. In my opinion, the renderer is powerful enough to be used in a commercial game in its current incarnation, and any improvements that are made to it would simply be icing on the cake.<br />
<br />
 <br />
<strong class='bbc'>Future Refinements</strong><br />
 While quite powerful in its own right, there is no doubt that further additions could be made to the cartoon renderer we have developed in this article. One possible modification would be to change our painter to use point lights instead of directional lights. To accomplish this it would be necessary to implement light-falloff and brightness calculations inside the vertex program. The light direction vector would need to be scaled inside the vertex program as well.<br />
<br />
 Another fascinating addition would be to create varied line-styles for the inker. This could be accomplished by rendering the lines onto something other than a simple quad. For example, one could use a 16x16 mesh of quads that could be perturbed according to some semi-random calculations in a vertex program. This could give a sketchy look to the lines, as they would move slightly each frame. Other interesting line-styles are made possible by replacing the "dilation" pixel program. We have only used this second pixel program to thicken the line, but one could also change look of the ink lines by offsetting individual pixels or changing their colors.<br />
<br />
 <br />
<strong class='bbc'>Conclusion</strong><br />
 Our cartoon renderer gives us freedom in the look of our painting, even allowing us to use different highlighting depending on light brightness. It also has the flexibility to completely change highlighting schemes by switching out a single texture. It supports two, colored, per-pixel lights that can have varying brightness. Our outlining algorithm supports depth-based lines, automatic edge and crease lines, as well as artist-specified lines. All of these lines are rendered with a consistent style and can be drawn in varying widths and even smoothed.<br />
<br />
 This all adds up to possibly the most robust cartoon renderer developed to date, and it runs on all Direct-X 8.0 compatible hardware. It will even work on an X-Box! I would love to see the techniques described in this article implemented in a commercial game. We need to break the monotony of run-of-the-mill "realistic" graphics that are so prevalent in today's entertainment software. If anyone has questions regarding the cartoon renderer or any improvements that they wish to share, please contact me at <a href='mailto:vishvananda@yahoo.com' title='E-mail Link' class='bbc_email'>vishvananda@yahoo.com</a>.<br />
<br />
 <br />
<strong class='bbc'>For Further Information</strong><br />
 Most of the papers referenced below can be found at the Citeseer website at <a href='http://citeseer.nj.nec.com/' class='bbc_url' title='External link' rel='nofollow external'>http://citeseer.nj.nec.com</a>. You can also find more information included with the demo program <a href='http://downloads.gamedev.net/features/programming/cartoon/DemoProgram.zip' class='bbc_url' title='External link' rel='nofollow external'>here</a>.<br />
<br />
 [1] J. Claes, F. Di Fiore, G. Vansichem, F. Van Reeth. Fast 3D Cartoon Rendering with Improved Quality by Exploiting Graphics Hardware. 2001<br />
<br />
 [2] A. Lake, C. Marshall, M. Harris, M. Blackstein. Stylized Rendering Techniques for Scalable Real-Time 3D Animation. 2000.<br />
<br />
 [3] J. Buchanan, M. Sousa. The edge buffer: A data structure for easy silhouette rendering. 2000<br />
<br />
 [4] R. Raskar. Hardware Support for Non-Photorealistic Rendering. 2001.<br />
<br />
 [5] NVIDIA's Vertex Toon Shader <a href='http://developer.nvidia.com/object/Toon_Shading.html' class='bbc_url' title='External link' rel='nofollow external'>http://developer.nvi...on_Shading.html</a><br />
<br />
 [6] J. Mitchell, C. Brennan, D. Card. Real-Time Image-Space Outlining for Non-Photorealistic Rendering. 2002. <a href='http://mirror.ati.com/developer/SIGGRAPH02/NPROutlining_Mitchell.pdf' class='bbc_url' title='External link' rel='nofollow external'>http://mirror.ati.co...ng_Mitchell.pdf</a><br />
<br />
]]></description>
		<pubDate>Sat, 06 Dec 2003 19:21:33 +0000</pubDate>
		<guid isPermaLink="false">49ca03822497d26a3943d5084ed59130</guid>
	</item>
	<item>
		<title>2D in Direct3D using Textured Quads</title>
		<link>http://www.gamedev.net/page/resources/_/technical/directx-and-xna/2d-in-direct3d-using-textured-quads-r1972</link>
		<description><![CDATA[This article is for people trying to make a 2D graphics engine using Direct3D 9. It assumes you already have a basic Direct3D 9 application up and running, possibly using ID3DXSprite functions.<br />
<br />
If you do not, the code for a fully working application using the methods presented in this article is included.<br />
<br />
This article is divded into the following sections:<ul class='bbcol decimal'><br /><li>The concept<br /></li><li>The vertex format<br /></li><li>Initialization code<br /></li><li>Loading a texture<br /></li><li>Drawing a texture<br /></li><li>The CTexture class<br /></li></ul><br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>1. The concept</strong></span><br />
<br />
So you've decided to write a 2d game. Great, I love 2d games. You've also decided to use Direct3D as your API of choice. Groovy, you get to use cool tricks like fully hardware-supported alpha blending. If you're using Direct3D 8 instead, the code is pretty much the same (just change all the 8's to 9's and update <strong class='bbc'>CreateVertexBuffer()</strong> and <strong class='bbc'>SetStreamSource()</strong> calls). Now, you're probably wondering "How exactly do I put a 2d graphic on screen using an API designed exclusively for 3d graphics?"<br />
<br />
Don't worry. It's not particularly hard. Anyways, you only have to actually write the code once ;-)<br />
<br />
The basic idea is to draw a rectangular polygon on screen textured with your 2d image. The great thing about this is that the image can have its own alpha channel, so you don't get the opaque rectangular frame around your image (accomplishing the same thing as colour-keying) and at the same time, you can have certain areas of the image be partially transparent.<br />
<br />
In order to draw a quad on the screen, you have to give the positions of the four corners of the quad. This means with a little toying around with the coordinates, you can easily add transformations like skewing and perspective effects. Those, however, are left as an exercise for the reader.<br />
<br />
The main benefit, however, to using textured quads for a 2d engine is speed. You're actually using the 3d hardware to do exactly what it was designed for: spitting out a bunch of textured shapes on screen really fast.<br />
<br />
Of course, with so many benefits to using textured quads, there must be some drawbacks. And there are a few.<br />
<br />
The most significant drawback to using 3d hardware for drawing is that most 3d cards cannot support textures whose side lengths are not powers of 2. Furthermore, some cards cannot support non-square textures. What this means is that you should try to make your graphics have dimensions such as: 1x1, 2x2, 4x4, 8x8, 16x16, 32x32, 64x64, 128x128, etc. The maximum size you should use is 512x512. Most video cards can support textures up to 2048x2048, but some can't, and a texture that big would consume a massive amount of memory on the video card.<br />
<br />
The <strong class='bbc'>CTexture</strong> class I provide at the end of this article will provide a work-around for these limitations, allowing you to use rectangular textures of weird dimensions. Even so, using non-square, non-power-of-2 textures is pretty much guaranteed to result in more processing time and more memory consumption.<br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>2. The vertex format</strong></span><br />
<br />
It's time to get down to business: putting a quad on the screen.<br />
<br />
Every quad is made up of two triangle and four vertices as shown below:<br />
<br />
<span style='font-family: courier new,courier,monospace'><span style='font-size: 12px;'>&nbsp;&nbsp;v0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v1<br />
&nbsp;&nbsp; |---------------|<br />
&nbsp;&nbsp; |&#092;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
&nbsp;&nbsp; |&nbsp;&nbsp;&#092;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&#092;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#092;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#092;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#092;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#092;&nbsp;&nbsp;|<br />
&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#092;|<br />
&nbsp;&nbsp; |---------------|<br />
&nbsp;&nbsp;v3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; v2</span></span><br />
<br />
I like to keep that particular diagram as a comment in my code as it comes in handy when I want to change the colour tint of a particular corner on a quad I'm drawing (more on this later).<br />
<br />
The first thing you need in order to write your own quad-based engine for 2d drawing is a flexible vertex format. The vertex format decides exactly what information is available about the vertices that make up the quads you draw. This one should do you well:<br />
<br />
<pre class='prettyprint'>const DWORD D3DFVF_TLVERTEX = D3DFVF_XYZRHW &#124; D3DFVF_DIFFUSE &#124; D3DFVF_TEX1;</pre><br />
<br />
Put it somewhere where all of your graphics code can see it. It's very important.<br />
<br />
Here's a quick run-down of exactly what the each of the flags in the above vertex format does:<br />
<br />
<strong class='bbc'>D3DFVF_XYZRHW</strong> - Specifies what position information the vertex will hold. In this case, X, Y, Z coordinates, as well as a "reciprocal of homogenous W" coordinate. All you really need to know about that is it lets you use screen coordinates to draw your quads instead of 3d-space coordinates. As you may have guessed, the Z coordinate is irrelevant. It will always be set to 0.<br />
<br />
<strong class='bbc'>D3DFVF_DIFFUSE</strong> - Allows you to specify a colour and alpha for the vertex, letting you shade the corners of a quad in different colours. ID3DXSprite offers limited support for this, allowing you to shade the whole a quad a certain colour. The code in this article allows you to change the colour and alpha value of each corner of a quad.<br />
<br />
<strong class='bbc'>D3DFVF_TEX1</strong> - Specifies that the vertex is to hold texture coordinates. You need this to put a texture on the quads you draw.<br />
<br />
Now that you've got your vertex format defined, you need a structure to hold a vertex. This one will work swimmingly with the above vertex format:<br />
<br />
<pre class='prettyprint'>//Custom vertex<br />struct TLVERTEX<br />{<br />	float x;<br />	float y;<br />	float z;<br />	float rhw;<br />	D3DCOLOR colour;<br />	float u;<br />	float v;<br />};</pre><br />
<br />
You'll need this structure to be available to all of your drawing code as well.<br />
<br />
A brief description of the members:<br />
<br />
<strong class='bbc'>x, y, z</strong> - The coordinates the vertex is located at. <strong class='bbc'>x</strong> and <strong class='bbc'>y</strong> are the screen coordinates at which the vertex is located. In 2d-land, <strong class='bbc'>z</strong> is always 0.0f. While <strong class='bbc'>x</strong> and <strong class='bbc'>y</strong> are floats, they should contain integral values, or they will be rounded when it comes time to draw the quad.<br />
<br />
<strong class='bbc'>rhw</strong> - This is always 1.0f. It allows you to use screen coordinates to specify the position of the vertex rather than 3d-space coordinates,<br />
<br />
<strong class='bbc'>colour</strong> - The colour/alpha value of the vertex in standard 32-bit AARRGGBB format.<br />
<br />
<strong class='bbc'>u, v</strong> - The texture coordinates of the vertex. For the vertices on the left, <strong class='bbc'>u</strong> is 0.0f. On the right, <strong class='bbc'>u</strong> is 1.0f. On the top, <strong class='bbc'>v</strong> is 0.0f. On the bottom, <strong class='bbc'>v</strong> is 1.0f.<br />
<br />
If you didn't get all of that, don't worry about it. As long as you copy-and-pasted the <strong class='bbc'>const</strong> and <strong class='bbc'>struct</strong> properly, you'll have no problem using the code accompanying this article ;)<br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>3. Initialization code</strong></span><br />
<br />
So you've got your Direct3D object, presented your parameters, created your device, whatever. All you need to do now is add a couple lines and you'll be drawing textured quads in no time.<br />
<br />
First things first, you need to make a vertex buffer. In the same scope your IDirect3DDevice9 pointer is located, add:<br />
<br />
<pre class='prettyprint'>IDirect3DVertexBuffer9* vertexBuffer;</pre><br />
<br />
Groovy. Now, in your initalization function, <strong class='bbc'>AFTER</strong> the device is created, add the following:<br />
<br />
<pre class='prettyprint'>//Set vertex shader<br />DEVICE-&gt;SetVertexShader(NULL);<br />DEVICE-&gt;SetFVF(D3DFVF_TLVERTEX);<br /><br />//Create vertex buffer<br />DEVICE-&gt;CreateVertexBuffer(sizeof(TLVERTEX) * 4, NULL,<br />	D3DFVF_TLVERTEX, D3DPOOL_MANAGED, &vertexBuffer, NULL);<br />DEVICE-&gt;SetStreamSource(0, vertexBuffer, 0, sizeof(TLVERTEX));</pre><br />
<br />
NOTE 1: Replace <strong class='bbc'>DEVICE</strong> with the name of your IDirect3DDevice9* object<br />
NOTE 2: This code does not have to be directly after the <strong class='bbc'>CreateDevice()</strong> call; as long as the device is created, it should work fine<br />
<br />
Also the following render states should be set if they are not:<br />
<br />
<pre class='prettyprint'>DEVICE-&gt;SetRenderState(D3DRS_LIGHTING, FALSE);<br />DEVICE-&gt;SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);<br />DEVICE-&gt;SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);<br />DEVICE-&gt;SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);<br />DEVICE-&gt;SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);</pre><br />
<br />
NOTE: Replace <strong class='bbc'>DEVICE</strong> with the name of your IDirect3DDevice9* object<br />
<br />
Alright, now we're ready to go. Let's load some textures.<br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>4. Loading a texture</strong></span><br />
<br />
Using D3DX this is incredibly simple. Here's a code dump:<br />
<br />
<pre class='prettyprint'>//Load texture from file with D3DX<br />//Supported formats: BMP, PPM, DDS, JPG, PNG, TGA, DIB<br />IDirect3DTexture9 *LoadTexture(char *fileName)<br />{<br />  IDirect3DTexture9 *d3dTexture;<br />  D3DXIMAGE_INFO SrcInfo;	  //Optional<br /><br />  //Use a magenta colourkey<br />  D3DCOLOR colorkey = 0xFFFF00FF;<br /><br />  // Load image from file<br />  if (FAILED(D3DXCreateTextureFromFileEx (DEVICE, fileName, 0, 0, 1, 0,<br />		D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_DEFAULT,<br />		colorkey, &SrcInfo, NULL, &d3dTexture)))<br />  {<br />	return NULL;<br />  }<br /><br />  //Return the newly made texture<br />  return d3dTexture;<br />}</pre><br />
<br />
NOTE: Replace <strong class='bbc'>DEVICE</strong> with the name of your IDirect3DDevice9* object<br />
<br />
You pass it a graphics file, it passes you a pointer to a texture. Couldn't be easier. Upon failure, a NULL pointer is returned. While the loaded graphics file will retain its own alpha map, there is also a magenta colour key, meaning all pixels with a colour value of 0xFFFF00FF will be given an alpha value of 0 upon loading.<br />
<br />
Please note that if you load an image file whose dimensions are not powers of 2, and your video card cannot support non-power-of-2 textures, this function will automatically put the image in a texture with dimensions that are powers of 2. For example, if you tried to load a 100x100 image, it would be put into a 128x128 texture. The extra space on the texture will have an alpha value of 0, so it will not show up when the texture is drawn. However, it will cause the drawing functions below to draw the image with a scaled size. That is, if you tried to draw the 100x100 image in a 100x100 square on screen, the drawing function would have to scale the 128x128 texture to fit inside it. This would make the image appear smaller than it actually is. Using the drawing functions in the <strong class='bbc'>CTexture</strong> class (provided at the end of the article) will prevent this scaling. Even so, I urge the reader to avoid the whole mess and use square, power-of-2-sized graphics.<br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>5. Drawing a texture</strong></span><br />
<br />
Time to get something on the screen. Two main drawing functions will be used -- <strong class='bbc'>BlitD3D()</strong> and <strong class='bbc'>BlitExD3D()</strong>. The only difference between the two is that <strong class='bbc'>BlitExD3D()</strong> supports colour modulation of all four corners of the quad, while <strong class='bbc'>BlitD3D()</strong> can only tint the whole quad.<br />
<br />
Please be aware that the rotation code provided here is horrible, and should be rewritten. Use it at your own risk.<br />
<br />
<pre class='prettyprint'>//Draw a textured quad on the back-buffer<br />void BlitD3D (IDirect3DTexture9 *texture, RECT *rDest,<br />    D3DCOLOR vertexColour, float rotate)<br />{<br />  TLVERTEX* vertices;<br /><br />  //Lock the vertex buffer<br />  vertexBuffer-&gt;Lock(0, 0, (void**)&vertices, NULL);<br /><br />  //Setup vertices<br />  //A -0.5f modifier is applied to vertex coordinates to match texture<br />  //and screen coords. Some drivers may compensate for this<br />  //automatically, but on others texture alignment errors are introduced<br />  //More information on this can be found in the Direct3D 9 documentation<br />  vertices&#91;0&#93;.colour = vertexColour;<br />  vertices&#91;0&#93;.x = (float) rDest-&gt;left - 0.5f;<br />  vertices&#91;0&#93;.y = (float) rDest-&gt;top - 0.5f;<br />  vertices&#91;0&#93;.z = 0.0f;<br />  vertices&#91;0&#93;.rhw = 1.0f;<br />  vertices&#91;0&#93;.u = 0.0f;<br />  vertices&#91;0&#93;.v = 0.0f;<br /><br />  vertices&#91;1&#93;.colour = vertexColour;<br />  vertices&#91;1&#93;.x = (float) rDest-&gt;right - 0.5f;<br />  vertices&#91;1&#93;.y = (float) rDest-&gt;top - 0.5f;<br />  vertices&#91;1&#93;.z = 0.0f;<br />  vertices&#91;1&#93;.rhw = 1.0f;<br />  vertices&#91;1&#93;.u = 1.0f;<br />  vertices&#91;1&#93;.v = 0.0f;<br /><br />  vertices&#91;2&#93;.colour = vertexColour;<br />  vertices&#91;2&#93;.x = (float) rDest-&gt;right - 0.5f;<br />  vertices&#91;2&#93;.y = (float) rDest-&gt;bottom - 0.5f;<br />  vertices&#91;2&#93;.z = 0.0f;<br />  vertices&#91;2&#93;.rhw = 1.0f;<br />  vertices&#91;2&#93;.u = 1.0f;<br />  vertices&#91;2&#93;.v = 1.0f;<br /><br />  vertices&#91;3&#93;.colour = vertexColour;<br />  vertices&#91;3&#93;.x = (float) rDest-&gt;left - 0.5f;<br />  vertices&#91;3&#93;.y = (float) rDest-&gt;bottom - 0.5f;<br />  vertices&#91;3&#93;.z = 0.0f;<br />  vertices&#91;3&#93;.rhw = 1.0f;<br />  vertices&#91;3&#93;.u = 0.0f;<br />  vertices&#91;3&#93;.v = 1.0f;<br /><br />  //Handle rotation<br />  if (rotate != 0)<br />  {<br />    RECT rOrigin;<br />    float centerX, centerY;<br /><br />    //Find center of destination rectangle<br />    centerX = (float)(rDest-&gt;left + rDest-&gt;right) / 2;<br />    centerY = (float)(rDest-&gt;top + rDest-&gt;bottom) / 2;<br /><br />    //Translate destination rect to be centered on the origin<br />    rOrigin.top = rDest-&gt;top - (int)(centerY);<br />    rOrigin.bottom = rDest-&gt;bottom - (int)(centerY);<br />    rOrigin.left = rDest-&gt;left - (int)(centerX);<br />    rOrigin.right = rDest-&gt;right - (int)(centerX);<br /><br />    //Rotate vertices about the origin<br />    bufferVertices&#91;index&#93;.x = rOrigin.left * cosf(rotate) -<br />							  rOrigin.top * sinf(rotate);<br />    bufferVertices&#91;index&#93;.y = rOrigin.left * sinf(rotate) +<br />							  rOrigin.top * cosf(rotate);<br /><br />    bufferVertices&#91;index + 1&#93;.x = rOrigin.right * cosf(rotate) -<br />								  rOrigin.top * sinf(rotate);<br />    bufferVertices&#91;index + 1&#93;.y = rOrigin.right * sinf(rotate) +<br />								  rOrigin.top * cosf(rotate);<br /><br />    bufferVertices&#91;index + 2&#93;.x = rOrigin.right * cosf(rotate) -<br />								  rOrigin.bottom * sinf(rotate);<br />    bufferVertices&#91;index + 2&#93;.y = rOrigin.right * sinf(rotate) +<br />								  rOrigin.bottom * cosf(rotate);<br /><br />    bufferVertices&#91;index + 3&#93;.x = rOrigin.left * cosf(rotate) -<br />								  rOrigin.bottom * sinf(rotate);<br />    bufferVertices&#91;index + 3&#93;.y = rOrigin.left * sinf(rotate) +<br />								  rOrigin.bottom * cosf(rotate);<br /><br />    //Translate vertices to proper position<br />    bufferVertices&#91;index&#93;.x += centerX;<br />    bufferVertices&#91;index&#93;.y += centerY;<br />    bufferVertices&#91;index + 1&#93;.x += centerX;<br />    bufferVertices&#91;index + 1&#93;.y += centerY;<br />    bufferVertices&#91;index + 2&#93;.x += centerX;<br />    bufferVertices&#91;index + 2&#93;.y += centerY;<br />    bufferVertices&#91;index + 3&#93;.x += centerX;<br />    bufferVertices&#91;index + 3&#93;.y += centerY;<br />  }<br /><br />  //Unlock the vertex buffer<br />  vertexBuffer-&gt;Unlock();<br /><br />  //Set texture<br />  DEVICE-&gt;SetTexture (0, texture);<br /><br />  //Draw image<br />  DEVICE-&gt;DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);<br />}</pre><br />
<br />
NOTE: Replace <strong class='bbc'>DEVICE</strong> with the name of your IDirect3DDevice9* object<br />
<br />
Here's a description of the arguments passed to the function:<br />
<br />
<strong class='bbc'>texture</strong> - A pointer to the texture to use on the quad. Whatever is passed here will show up on screen.<br />
<br />
<strong class='bbc'>rDest</strong> - A rectangle containing the screen coordinates of the quad. If the rectangle is of a different size than the texture, the image will be scaled.<br />
<br />
<strong class='bbc'>vertexColour</strong> - The colour used to tint the quad in 32-bit 0xAARRGGBB format. A value of 0xFFFFFFFF will not modify the appearance of the texture.<br />
<br />
<strong class='bbc'>fRotate</strong> - How much the quad should be rotated about its center. The value should be in radians. A value of 0 will, of course, not rotate the quad at all.<br />
<br />
The extended blitting function follows:<br />
<br />
<pre class='prettyprint'>//Draw a textured quad on the back-buffer<br />void BlitExD3D (IDirect3DTexture9 *texture, RECT *rDest,<br />    D3DCOLOR *vertexColours /* -&gt; D3DCOLOR&#91;4&#93; */, float rotate)<br />{<br />  TLVERTEX* vertices;<br /><br />  //Lock the vertex buffer<br />  vertexBuffer-&gt;Lock(0, 0, (void**)&vertices, NULL);<br /><br />  //Setup vertices<br />  //A -0.5f modifier is applied to vertex coordinates to match texture<br />  //and screen coords. Some drivers may compensate for this<br />  //automatically, but on others texture alignment errors are introduced<br />  //More information on this can be found in the Direct3D 9 documentation<br />  vertices&#91;0&#93;.colour = vertexColours&#91;0&#93;;<br />  vertices&#91;0&#93;.x = (float) rDest-&gt;left - 0.5f;<br />  vertices&#91;0&#93;.y = (float) rDest-&gt;top - 0.5f;<br />  vertices&#91;0&#93;.z = 0.0f;<br />  vertices&#91;0&#93;.rhw = 1.0f;<br />  vertices&#91;0&#93;.u = 0.0f;<br />  vertices&#91;0&#93;.v = 0.0f;<br /><br />  vertices&#91;1&#93;.colour = vertexColours&#91;1&#93;;<br />  vertices&#91;1&#93;.x = (float) rDest-&gt;right - 0.5f;<br />  vertices&#91;1&#93;.y = (float) rDest-&gt;top - 0.5f;<br />  vertices&#91;1&#93;.z = 0.0f;<br />  vertices&#91;1&#93;.rhw = 1.0f;<br />  vertices&#91;1&#93;.u = 1.0f;<br />  vertices&#91;1&#93;.v = 0.0f;<br /><br />  vertices&#91;2&#93;.colour = vertexColours&#91;2&#93;;<br />  vertices&#91;2&#93;.x = (float) rDest-&gt;right - 0.5f;<br />  vertices&#91;2&#93;.y = (float) rDest-&gt;bottom - 0.5f;<br />  vertices&#91;2&#93;.z = 0.0f;<br />  vertices&#91;2&#93;.rhw = 1.0f;<br />  vertices&#91;2&#93;.u = 1.0f;<br />  vertices&#91;2&#93;.v = 1.0f;<br /><br />  vertices&#91;3&#93;.colour = vertexColours&#91;3&#93;;<br />  vertices&#91;3&#93;.x = (float) rDest-&gt;left - 0.5f;<br />  vertices&#91;3&#93;.y = (float) rDest-&gt;bottom - 0.5f;<br />  vertices&#91;3&#93;.z = 0.0f;<br />  vertices&#91;3&#93;.rhw = 1.0f;<br />  vertices&#91;3&#93;.u = 0.0f;<br />  vertices&#91;3&#93;.v = 1.0f;<br /><br />  //Handle rotation<br />  if (rotate != 0)<br />  {<br />    RECT rOrigin;<br />    float centerX, centerY;<br /><br />    //Find center of destination rectangle<br />    centerX = (float)(rDest-&gt;left + rDest-&gt;right) / 2;<br />    centerY = (float)(rDest-&gt;top + rDest-&gt;bottom) / 2;<br /><br />    //Translate destination rect to be centered on the origin<br />    rOrigin.top = rDest-&gt;top - (int)(centerY);<br />    rOrigin.bottom = rDest-&gt;bottom - (int)(centerY);<br />    rOrigin.left = rDest-&gt;left - (int)(centerX);<br />    rOrigin.right = rDest-&gt;right - (int)(centerX);<br /><br />    //Rotate vertices about the origin<br />    bufferVertices&#91;index&#93;.x = rOrigin.left * cosf(rotate) -<br />							  rOrigin.top * sinf(rotate);<br />    bufferVertices&#91;index&#93;.y = rOrigin.left * sinf(rotate) +<br />							  rOrigin.top * cosf(rotate);<br /><br />    bufferVertices&#91;index + 1&#93;.x = rOrigin.right * cosf(rotate) -<br />								  rOrigin.top * sinf(rotate);<br />    bufferVertices&#91;index + 1&#93;.y = rOrigin.right * sinf(rotate) +<br />								  rOrigin.top * cosf(rotate);<br /><br />    bufferVertices&#91;index + 2&#93;.x = rOrigin.right * cosf(rotate) -<br />								  rOrigin.bottom * sinf(rotate);<br />    bufferVertices&#91;index + 2&#93;.y = rOrigin.right * sinf(rotate) +<br />								  rOrigin.bottom * cosf(rotate);<br /><br />    bufferVertices&#91;index + 3&#93;.x = rOrigin.left * cosf(rotate) -<br />								  rOrigin.bottom * sinf(rotate);<br />    bufferVertices&#91;index + 3&#93;.y = rOrigin.left * sinf(rotate) +<br />								  rOrigin.bottom * cosf(rotate);<br /><br />    //Translate vertices to proper position<br />    bufferVertices&#91;index&#93;.x += centerX;<br />    bufferVertices&#91;index&#93;.y += centerY;<br />    bufferVertices&#91;index + 1&#93;.x += centerX;<br />    bufferVertices&#91;index + 1&#93;.y += centerY;<br />    bufferVertices&#91;index + 2&#93;.x += centerX;<br />    bufferVertices&#91;index + 2&#93;.y += centerY;<br />    bufferVertices&#91;index + 3&#93;.x += centerX;<br />    bufferVertices&#91;index + 3&#93;.y += centerY;<br />  }<br /><br />  //Unlock the vertex buffer<br />  vertexBuffer-&gt;Unlock();<br /><br />  //Set texture<br />  DEVICE-&gt;SetTexture (0, texture);<br /><br />  //Draw image<br />  DEVICE-&gt;DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);<br />}</pre><br />
<br />
NOTE: Replace <strong class='bbc'>DEVICE</strong> with the name of your IDirect3DDevice9* object<br />
<br />
The only argument here that is different from the <strong class='bbc'>BlitD3D()</strong> function is <strong class='bbc'>vertexColours</strong>.<br />
<br />
<strong class='bbc'>vertexColours</strong> must be a pointer to a D3DCOLOR array of size 4. The indices of the array correspond to the numbers of the vertices in the kick-ass diagram provided at the beginning of this article. Each vertex in the quad will have its colour and alpha modulated based on its corresponding value in <strong class='bbc'>vertexColours</strong>.<br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>6. The CTexture class</strong></span><br />
<br />
Okay, we can load textures and we can draw textures. What more could a programmer want?<br />
<br />
A programmer could want a way to keep track of the textures. The <strong class='bbc'>CTexture</strong> class features a built-in resource manager so a single texture is not loaded more than once. It also keeps track of information about the texture for quick and easy access at runtime.<br />
<br />
First off, the class has a struct inside its private scope: <strong class='bbc'>LOADEDTEXTURE</strong>. This struct contains an IDirect3DTexture9* pointer as well as information about the texture, such as its filename and dimensions. It's declaration is:<br />
<br />
<pre class='prettyprint'>//Loaded texture struct<br />struct LOADEDTEXTURE<br />{<br />  int referenceCount;		 //# of CTexture instances containing this texture<br />  IDirect3DTexture9* texture; //The texture<br />  string sFilename;		   //The filename of the texture<br />  int width;				  //Width of the texture<br />  int height;				 //Height of the texture<br />};</pre><br />
<br />
You'll notice that the struct keeps a reference count of <strong class='bbc'>CTexture</strong> instances that use the texture it contains. This is helpful as we can periodically run through the list of loaded textures and delete any unreferenced ones, or even delete the texture as soon as it becomes unreferenced. By default, the <strong class='bbc'>CTexture</strong> class does not release textures as soon as they become unreferenced, but it's not a particularly taxing job to make it do so. However, I do not recommend it. It would be best to wait until you have some free processing time (such as the loading time between levels) before you start deleting textures. This way you can clear all the unreferenced ones at once without causing any hiccups in the game.<br />
<br />
Next up, also in the private scope, we have the list of loaded textures:<br />
<br />
<pre class='prettyprint'>//Linked list of all loaded textures<br />static list &lt;LOADEDTEXTURE*&gt; loadedTextures;</pre><br />
<br />
We want it to be static so there is only ever one list, instead of a list in every instance of <strong class='bbc'>CTexture</strong>. Don't forget to initialize the list outside of the class declaration, as it is static.<br />
<br />
Each instance of <strong class='bbc'>CTexture</strong> needs to know if it has already loaded a texture or not, and which texture that is. This is easily taken care of by adding a flag and LOADEDTEXTURE pointer in the private scope, as well as a constructor in the public scope.<br />
<br />
<pre class='prettyprint'>public:<br /><br />  //Set default member values<br />  CTexture()<br />  {<br />    bLoaded = FALSE;<br />    texture = NULL;<br />  }<br /><br />private:<br /><br />  BOOL bLoaded;		   //Texture loaded flag<br />  LOADEDTEXTURE* texture; //The texture</pre><br />
<br />
Alright, it's time once again to load a texture. The following function looks through the <strong class='bbc'>loadedTextures</strong> list to see if the requested texture has been loaded. If so, it assigns that to the <strong class='bbc'>CTexture</strong>. If not, it loads the texture using the <strong class='bbc'>LoadTexture()</strong> function provided above and adds it to the list before assigning it to the <strong class='bbc'>CTexture</strong>. This function goes in the public scope of <strong class='bbc'>CTexture</strong>:<br />
<br />
<pre class='prettyprint'>//Load texture from file<br />int CTexture::Init (string sFilename)<br />{<br />  D3DSURFACE_DESC surfaceDesc;<br />  LOADEDTEXTURE* newTexture;<br />  list&lt;LOADEDTEXTURE*&gt;::iterator itTextures;<br /><br />  //Make sure texture is not already loaded<br />  if (bLoaded)<br />    return FALSE;<br /><br />  //Convert filename to lowercase letters<br />  sFilename = strlwr((char *)sFilename.c_str ());<br /><br />  //Check if texture is in the loaded list<br />  for (itTextures = loadedTextures.begin ();<br />	   itTextures != loadedTextures.end ();<br />	   itTextures++)<br />    if ((*itTextures)-&gt;sFilename == sFilename)<br />    {   <br />	  //Get LOADEDTEXTURE object<br />	  texture = *itTextures;  <br /><br />	  //Increment reference counter<br />	  (*itTextures)-&gt;referenceCount++;<br /><br />	  //Set loaded flag<br />	  bLoaded = TRUE;<br /><br />	  //Successfully found texture<br />	  return TRUE;<br />    }<br /><br />  //Texture was not in the list, make a new texture<br />  newTexture = new LOADEDTEXTURE;<br /><br />  //Load texture from file<br />  newTexture-&gt;texture = LoadTexture ((char*)sFilename.c_str());<br />    <br />  //Make sure texture was loaded<br />  if (!newTexture-&gt;texture)<br />    return FALSE;<br /><br />  //Get texture dimensions<br />  newTexture-&gt;texture-&gt;GetLevelDesc(0, &surfaceDesc);<br /><br />  //Set new texture parameters<br />  newTexture-&gt;referenceCount = 1;<br />  newTexture-&gt;sFilename = sFilename;<br />  newTexture-&gt;width = surfaceDesc.Width;<br />  newTexture-&gt;height = surfaceDesc.Height;<br /><br />  //Push new texture onto list<br />  loadedTextures.push_back (newTexture);<br /><br />  //Setup current texture instance<br />  texture = loadedTextures.back();<br />  bLoaded = TRUE;<br /> <br />  //Successfully loaded texture<br />  return TRUE;<br />}</pre><br />
<br />
You'll notice that the filename is converted to lowercase at the beginning of the function. This is because filenames are not case-sensitive in Windows. We do not want the program to load the same texture twice if sFilename is "hello.jpg" one time and "Hello.JPG" the next.<br />
<br />
Next up, a function to call when we're done with a particular instance of the texture. This function doesn't do much besides decrease the reference count of the <strong class='bbc'>LOADEDTEXTURE</strong> and clear the loaded flag of the <strong class='bbc'>CTexture</strong> instance. Here it is:<br />
<br />
<pre class='prettyprint'>//Unload a texture<br />int CTexture::Close()<br />{<br />  //Make sure texture is loaded<br />  if (!bLoaded)<br />    return FALSE;<br />    <br />  //Decrement reference counter and nullify pointer<br />  texture-&gt;referenceCount--;<br />  texture = NULL;<br /><br />  //Clear loaded flag<br />  bLoaded = FALSE;<br /><br />  //Successfully unloaded texture<br />  return TRUE;<br />}</pre><br />
<br />
So now we can load and clear our texture instances. We still have no way of getting them out of memory. Thats where the following two functions come in handy. The first goes through the list and releases all unreferenced textures. This can safely be called at any time, as none of the textures it releases are in use. The next releases all of the texture in the list. It should only be called at program termination to catch any textures other parts of the program failed to release.<br />
<br />
Here is the function that releases all unreferenced textures:<br />
<br />
<strong class='bbc'>Declaration:</strong><br />
<br />
<pre class='prettyprint'>//Release all unreferenced textures<br />static int GarbageCollect();</pre><br />
<br />
<strong class='bbc'>Function:</strong><br />
<br />
<pre class='prettyprint'>//Release all unreferenced textures<br />int CTexture::GarbageCollect()<br />{<br />  list&lt;LOADEDTEXTURE*&gt;::iterator it;<br />  list&lt;LOADEDTEXTURE*&gt;::iterator itNext;<br /><br />  //Go through loaded texture list<br />  for (it = loadedTextures.begin(); it != loadedTextures.end ();)   <br />    if ((*it)-&gt;referenceCount &lt;= 0)<br />    {<br />	  //Get next iterator<br />	  itNext = it;<br />	  itNext++;<br /><br />	  //Release texture<br />	  if ((*it)-&gt;texture)<br />	    (*it)-&gt;texture-&gt;Release();<br />	  (*it)-&gt;texture = NULL;<br /><br />	  //Delete LOADEDTEXTURE object<br />	  delete (*it);<br />	  loadedTextures.erase (it);<br /><br />	  //Move to next element<br />	  it = itNext;<br />    } else it++; //Increment iterator<br /><br />  //Successfully released unreferenced textures<br />  return TRUE;<br />}</pre><br />
<br />
And this function will release all loaded textures:<br />
<br />
<strong class='bbc'>Declaration:</strong><br />
<br />
<pre class='prettyprint'>//Release all unreferenced textures<br />static int CleanupTextures();</pre><br />
<br />
<strong class='bbc'>Function:</strong><br />
<br />
<pre class='prettyprint'>//Release all textures<br />int CTexture::CleanupTextures()<br />{<br />  list&lt;LOADEDTEXTURE*&gt;::iterator it;<br /> <br />  //Go through loaded texture list<br />  for (it = loadedTextures.begin(); it != loadedTextures.end (); it++)<br />  {<br />    //Release texture<br />    if ((*it)-&gt;texture)<br />	  (*it)-&gt;texture-&gt;Release();<br />    (*it)-&gt;texture = NULL;<br />	    <br />    //Delete LOADEDTEXTURE object<br />    delete (*it);<br />  }<br /><br />  //Clear list<br />  loadedTextures.clear ();<br /><br />  //Successfully released all textures<br />  return TRUE;<br />}</pre><br />
<br />
Make sure both of the above functions are declared static in the class declaration.<br />
<br />
Alright, we're well equipped to manage our graphical resources. The only thing left to do is put them on the screen. Here are the functions for the <strong class='bbc'>CTexture</strong> class that use the two drawing functions provided above:<br />
<br />
<pre class='prettyprint'>//Draw texture with limited colour modulation<br />void CTexture::Blit (int X, int Y, D3DCOLOR vertexColour, float rotate)<br />{<br />  RECT rDest;<br /><br />  //Setup destination rectangle<br />  rDest.left = X;<br />  rDest.right = X + texture-&gt;width;<br />  rDest.top = Y;<br />  rDest.bottom = Y + texture-&gt;height;<br /><br />  //Draw texture<br />  BlitD3D (texture-&gt;texture, &rDest, vertexColour, rotate);<br />}<br /><br /><br />//Draw texture with full colour modulation<br />void CTexture::BlitEx (int X, int Y, D3DCOLOR* vertexColours, float rotate)<br />{<br />  RECT rDest;<br /><br />  //Setup destination rectangle<br />  rDest.left = X;<br />  rDest.right = X + texture-&gt;width;<br />  rDest.top = Y;<br />  rDest.bottom = Y + texture-&gt;height;<br /><br />  //Draw texture<br />  BlitExD3D (texture-&gt;texture, &rDest, vertexColours, rotate);<br />}</pre><br />
<br />
Like the <strong class='bbc'>BlitExD3D()</strong> provided earlier, <strong class='bbc'>CTexture::BlitEx()</strong> takes a pointer to a D3DCOLOR [4] array for its <strong class='bbc'>vertexColours</strong> argument.<br />
<br />
You may notice that these functions have no support for scaling. This helps them account for texture sizes being not what they seem (e.g. a 100x100 image being loaded onto a 128x128 texture). If you want to add scaling, make sure you account for this. It shouldn't be too much trouble.<br />
<br />
This concludes my article. You can check out the included sample code for a demonstration of the methods presented here in action.<br />
<br />
Please send any bugs, suggestions, feedback, or better rotation code to <a href='mailto:SiberianKiss@gdnMail.net' title='E-mail Link' class='bbc_email'>SiberianKiss@gdnMail.net</a>.<br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Appendix</strong></span><br />
<br />
This appendix is to address a few issues that were not sufficiently explained in the article (or in some cases left out altogether). The article is intended for beginners using Direct3D for 2D applications. For this reason, when writing the code I decided to go with flexibility over speed in many areas. However, I neglected to mention other, faster methods. I will attempt to do so here, as well as point out some omissions from the sample code.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Issue 1: Cleanup</strong></span><br />
<br />
This is just a little one, but apparently not very well known. When a call is made to <strong class='bbc'>IDirect3DDevice9::SetStreamSource()</strong>, a reference count is increased in the passed vertex buffer. If you do not call <strong class='bbc'>SetStreamSource()</strong> with another vertex buffer, or NULL, the <strong class='bbc'>Release()</strong> method of the previously passed vertex buffer will fail. This is just a small memory leak, and is cleaned up by DirectX upon program termination anyways. However if you're using a lot of different vertex buffers, you will notice some slowdown as your video memory is consumed. Also, it's just good programming practice to release everything properly yourself.<br />
<br />
For you copy-and-pasters, you'll want to add the following to your DirectX cleanup code:<br />
<br />
<pre class='prettyprint'>//Clear stream source<br />DEVICE-&gt;SetStreamSource (0, NULL, 0, 0);</pre><br />
<br />
It must be before this:<br />
<br />
<pre class='prettyprint'>//Release vertex buffer<br />if (vertexBuffer)<br />   vertexBuffer-&gt;Release ();</pre><br />
<br />
NOTE: Replace <strong class='bbc'>DEVICE</strong> with the name of your IDirect3DDevice9* object<br />
<br />
And voila, no memory lost.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Issue 2: Direct3D Uses Inclusive-Exclusive Coordinates</strong></span><br />
<br />
Wow I can't believe people complained about this one. It's fairly common knowledge. When you're setting up a destination rectangle, the bottom and right coordinates are:<br />
<br />
<pre class='prettyprint'>RECT.bottom = RECT.top + height<br />RECT.right = RECT.left + width</pre><br />
<br />
You even save two cycles over inclusive-inclusive coordinates by losing the "- 1"s.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Issue 3: Locking the Vertex Buffer</strong></span><br />
<br />
Here's where we get into some optimization. Locking is more expensive than simply using transformation and scaling matrices to move the vertexes of the quad around, but it also affords more flexibility. If you want to use colour modulation, you're pretty much stuck locking the vertex buffer in order to get access to that sweet, sweet <strong class='bbc'>colour</strong> member (don't worry, you're probably not losing too much processing time). However, if you're not using colour modulation and want an extra bit of speed, read on.<br />
<br />
This method uses transformation matrices to move around the vertices in the buffer. Understand that this method is not particularly compatible with the drawing methods presented in the first article. In fact, it requires a change to a fairly major item from the first article: the vertex format. You should use this one instead:<br />
<br />
<pre class='prettyprint'>//Custom vertex format<br />const DWORD D3DFVF_TLVERTEX = D3DFVF_XYZ &#124; D3DFVF_DIFFUSE &#124; D3DFVF_TEX1;<br /><br />//Custom vertex<br />struct TLVERTEX<br />{<br />   float x;<br />   float y;<br />   float z;<br />   D3DCOLOR colour;<br />   float u;<br />   float v;<br />};</pre><br />
<br />
In order to use matrix transformations, an orthographic projection matrix must first be set up. This must be done at initialization, after the device is open for business. Here is the code:<br />
<br />
<pre class='prettyprint'>D3DXMATRIX matOrtho;<br />D3DXMATRIX matIdentity;<br /><br />//Setup orthographic projection matrix<br />D3DXMatrixOrthoLH (&matOrtho, RESOLUTION_WIDTH, RESOLUTION_HEIGHT, 1.0f, 10.0f);<br />D3DXMatrixIdentity (&matIdentity);<br />DEVICE-&gt;SetTransform (D3DTS_PROJECTION, &matOrtho);<br />DEVICE-&gt;SetTransform (D3DTS_WORLD, &matIdentity);<br />DEVICE-&gt;SetTransform (D3DTS_VIEW, &matIdentity);</pre><br />
<br />
NOTE: Replace <strong class='bbc'>DEVICE</strong> with the name of your IDirect3DDevice9* object<br />
<br />
NOTE 2: Replace <strong class='bbc'>RESOLUTION_WIDTH</strong> with the width of the backbuffer<br />
<br />
NOTE 3: Replace <strong class='bbc'>RESOLUTION_HEIGHT</strong> with the height of the backbuffer<br />
<br />
Please note that this method does not allow colour modulation (though a similar effect can be acheived with a simple vertex shader). It simply uses the vertex colours that are already specified in the buffer. Before using this method, we must ensure that the colour values in the buffer are all white, and that there is a valid quad in the buffer. This function will see to that:<br />
<br />
<pre class='prettyprint'>//Setup the quad<br />void SetupQuad ()<br />{<br /><br />    TLVERTEX* vertices = NULL;<br />    vertexBuffer-&gt;Lock(0, 4 * sizeof(TLVERTEX), (VOID**)&vertices, 0);<br /><br />    //Setup vertices<br />    vertices&#91;0&#93;.colour = 0xffffffff;<br />    vertices&#91;0&#93;.x = 0.0f;<br />    vertices&#91;0&#93;.y = 0.0f;<br />    vertices&#91;0&#93;.z = 1.0f;<br />    vertices&#91;0&#93;.u = 0.0f;<br />    vertices&#91;0&#93;.v = 0.0f;<br /><br />    vertices&#91;1&#93;.colour = 0xffffffff;<br />    vertices&#91;1&#93;.x = 1.0f;<br />    vertices&#91;1&#93;.y = 0.0f;<br />    vertices&#91;1&#93;.z = 1.0f;<br />    vertices&#91;1&#93;.u = 1.0f;<br />    vertices&#91;1&#93;.v = 0.0f;<br /><br />    vertices&#91;2&#93;.colour = 0xffffffff;<br />    vertices&#91;2&#93;.x = 1.0f;<br />    vertices&#91;2&#93;.y = -1.0f;<br />    vertices&#91;2&#93;.z = 1.0f;<br />    vertices&#91;2&#93;.u = 1.0f;<br />    vertices&#91;2&#93;.v = 1.0f;<br /><br />    vertices&#91;3&#93;.colour = 0xffffffff;<br />    vertices&#91;3&#93;.x = 0.0f;<br />    vertices&#91;3&#93;.y = -1.0f;<br />    vertices&#91;3&#93;.z = 1.0f;<br />    vertices&#91;3&#93;.u = 0.0f;<br />    vertices&#91;3&#93;.v = 1.0f;<br /><br />    vertexBuffer-&gt;Unlock();<br />}</pre><br />
<br />
If you are not using colour modulation at all in your program, this only needs to be called once, upon program startup.<br />
<br />
Here is code to actually draw the textured quad:<br />
<br />
<pre class='prettyprint'>//Draw a textured quad on the backbuffer<br />void Blit(IDirect3DTexture9* texture, RECT* rDest, float rotate)<br />{<br />    float X;<br />    float Y;<br />    D3DXMATRIX matTranslation;<br />    D3DXMATRIX matScaling;<br />    D3DXMATRIX matTransform;<br />    <br />    //Get coordinates<br />    X = rDest-&gt;left - (float)(RESOLUTION_WIDTH) / 2;<br />    Y = -rDest-&gt;top + (float)(RESOLUTION_HEIGHT) / 2;<br /><br />    //Setup translation and scaling matrices<br />    D3DXMatrixScaling (&matScaling, (float)(rDest-&gt;right - rDest-&gt;left),<br />	    (float)(rDest-&gt;bottom - rDest-&gt;top), 1.0f);<br />    D3DXMatrixTranslation (&matTranslation, X, Y, 0.0f);<br />    matTransform = matScaling * matTranslation;<br /><br />    //Check if quad is rotated<br />    if (rotate)<br />    {<br />	    D3DXMATRIX matRotate;<br /><br />	    //Create rotation matrix about the z-axis<br />	    D3DXMatrixRotationZ (&matRotate, rotate);<br /><br />	    //Multiply matrices together<br />	    matTransform *= matRotate;<br />    }<br /><br />    //Draw the quad<br />    DEVICE-&gt;SetTransform (D3DTS_WORLD, &matTransform);<br />    DEVICE-&gt;SetTexture (0, texture);<br />    DEVICE-&gt;DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);<br />}</pre><br />
<br />
NOTE: Replace <strong class='bbc'>DEVICE</strong> with the name of your IDirect3DDevice9* object<br />
<br />
NOTE 2: Replace <strong class='bbc'>RESOLUTION_WIDTH</strong> with the width of the backbuffer<br />
<br />
NOTE 3: Replace <strong class='bbc'>RESOLUTION_HEIGHT</strong> with the height of the backbuffer<br />
<br />
Though slightly less powerful, this function should be faster than the ones presented in the article. It also has better-looking rotation.<br />
<br />
Please see NoLocking.zip in the attached source for a demonstration of this technique in action.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Issue 4: Batching</strong></span><br />
<br />
It's time for a bit of batching. If you manage this well, this could potentially give you a rather large speed increase.<br />
<br />
In the <strong class='bbc'>Blit()</strong> functions provided in the article, <strong class='bbc'>SetTexture()</strong> is called every time you want to draw something, even if you're drawing the same texture on screen many times in a row. You can save some valuable cycles by simply not calling it if you're drawing the same texture multiple times.<br />
<br />
Another feature the blitting methods could use is setting up a source rectangle to blit from. This way you can have many images on one texture and draw all that are needed in the current frame with a single call to <strong class='bbc'>SetTexture()</strong>. Since texture coordinates are not specified in pixels (or texels), but rather as a value from 0.0f to 1.0f, a quick conversion must be done from pixel coordinates to texture coordinates.<br />
<br />
Furthermore, when drawing multiple quads from the same texture, it is possible to put them all in one large vertex buffer and draw them all in a single call. To do this, we must use the triangle-list primitive type, as opposed to the triangle fans used up to this point. To accomodate this, we will also need an index buffer to so we do not create duplicate vertices in the buffer. More information about index buffers can be found in the Two Kings tutorial here: <a href='http://www.two-kings.de/tutorials/d3d08/d3d08.html' class='bbc_url' title='External link' rel='nofollow external'>http://www.two-kings...3d08/d3d08.html</a><br />
<br />
So, first thing we need to do is add another vertex buffer and an index buffer, as well as some state information about the vertex buffer and texture. Put this in a scope visible to all of your graphics code:<br />
<br />
<pre class='prettyprint'>//Vertex buffer and index buffer for batched drawing<br />IDirect3DVertexBuffer9* vertexBatchBuffer;<br />IDirect3DIndexBuffer9* indexBatchBuffer;<br /><br />//Max amount of vertices that can be put in the batching buffer<br />const int BATCH_BUFFER_SIZE = 1000;<br /><br />//Vertices currently in the batching buffer<br />int numBatchVertices;<br />TLVERTEX* batchVertices;<br /><br />//Info on texture used for batched drawing<br />float batchTexWidth;<br />float batchTexHeight;</pre><br />
<br />
You can tweak the <strong class='bbc'>BATCH_BUFFER_SIZE</strong> constant to a number that works best with your app. The lower it is, the more often it has to be flushed. The higher it is, the longer it takes to lock. Make sure it's a multiple of four though, so you can completely fill it with quads.<br />
<br />
Now we need to initialize our new buffers. Do this around the same time as you initialize the other vertex buffer (just make sure it's after the device is created):<br />
<br />
<pre class='prettyprint'>//Create batching vertex and index buffers<br />d3dDevice-&gt;CreateVertexBuffer(BATCH_BUFFER_SIZE * sizeof(TLVERTEX),<br />    D3DUSAGE_WRITEONLY, D3DFVF_TLVERTEX, D3DPOOL_MANAGED, &vertexBatchBuffer, NULL);<br />d3dDevice-&gt;CreateIndexBuffer (BATCH_BUFFER_SIZE * 3, D3DUSAGE_WRITEONLY,<br />    D3DFMT_INDEX16, D3DPOOL_MANAGED, &indexBatchBuffer, NULL);<br />numBatchVertices = 0;</pre><br />
<br />
You may have noticed that the vertex and index buffers are both static. The vertex buffer is static because there will likely be a lot of switching between it and our original vertex buffer. The index buffer is static because we only change its contents once. Also, by making them static, we can keep them in the managed pool which makes for easier handling of alt-tabbing in a fullscreen app.<br />
<br />
Of course, you must remember to set the buffers free when you're done with them. Add this to your cleanup routine:<br />
<br />
<pre class='prettyprint'>//Release batching buffers<br />if (vertexBatchBuffer)<br />    vertexBatchBuffer-&gt;Release ();<br />if (indexBatchBuffer)<br />    indexBatchBuffer-&gt;Release ();</pre><br />
<br />
Since you'll only be putting quads in the vertex buffer, you'll only need to fill up the index buffer once and never modify it again. Use this function to fill it (call it after the index buffer has been initialized):<br />
<br />
<pre class='prettyprint'>//Fill the index buffer<br />void FillIndexBuffer ()<br />{<br />    int index = 0;<br />    short* indices = NULL;<br /><br />    //Lock index buffer<br />    indexBatchBuffer-&gt;Lock(0, BATCH_BUFFER_SIZE  * 3,<br />						   (void**) &indices, 0);<br /><br />    for (int vertex = 0; vertex &lt; BATCH_BUFFER_SIZE; vertex += 4)<br />    {<br />	    indices&#91;index&#93; = vertex;<br />	    indices&#91;index + 1&#93; = vertex + 2;<br />	    indices&#91;index + 2&#93; = vertex + 3;<br />	    indices&#91;index + 3&#93; = vertex;<br />	    indices&#91;index + 4&#93; = vertex + 1;<br />	    indices&#91;index + 5&#93; = vertex + 2;<br />	    index += 6;<br />    }<br /><br />    //Unlock index buffer<br />    indexBatchBuffer-&gt;Unlock ();<br />}</pre><br />
<br />
Alright. Now you just have to let your computer know you're ready to batch a bunch of quads together. Call this function every time you want to draw a series of images from a single texture:<br />
<br />
<pre class='prettyprint'>//Get ready for batch drawing<br />void BeginBatchDrawing (IDirect3DTexture9* texture)<br />{<br />    D3DXMATRIX matIdentity;<br />    D3DSURFACE_DESC surfDesc;<br /><br />    //Lock the batching vertex buffer<br />    numBatchVertices = 0;<br />    vertexBatchBuffer-&gt;Lock (0, BATCH_BUFFER_SIZE * sizeof(TLVERTEX),<br />							 (void **) &batchVertices, 0);<br /><br />    //Get texture dimensions<br />    texture-&gt;GetLevelDesc (0, &surfDesc);<br />    batchTexWidth = (float) surfDesc.Width;<br />    batchTexHeight = (float) surfDesc.Height;<br /><br />    //Set texture<br />    d3dDevice-&gt;SetTexture (0, texture);<br /><br />    //Set world matrix to an identity matrix<br />    D3DXMatrixIdentity (&matIdentity);<br />    d3dDevice-&gt;SetTransform (D3DTS_WORLD, &matIdentity);<br /><br />    //Set stream source to batch buffer<br />    d3dDevice-&gt;SetStreamSource (0, vertexBatchBuffer,<br />							    0, sizeof(TLVERTEX));<br />}</pre><br />
<br />
You should probably make this function set a flag somewhere so the program can tell it's in the middle of a batch drawing process. I'm leaving it out of the example to keep things simple (the demos already have far too many global variables for my liking).<br />
<br />
Now it's time to put some quads in the vertex buffer. This function will do just that for you:<br />
<br />
<pre class='prettyprint'>//Add a quad to the batching buffer<br />void AddQuad (RECT* rSource, RECT* rDest, D3DCOLOR colour)<br />{<br />    float X;<br />    float Y;<br />    float destWidth;<br />    float destHeight;<br /><br />    //Calculate coordinates<br />    X = rDest-&gt;left - (float)(d3dPresent.BackBufferWidth) / 2;<br />    Y = -rDest-&gt;top + (float)(d3dPresent.BackBufferHeight) / 2;<br />    destWidth = (float)(rDest-&gt;right - rDest-&gt;left);<br />    destHeight = (float)(rDest-&gt;bottom - rDest-&gt;top);<br /><br />    //Setup vertices in buffer<br />    batchVertices&#91;numBatchVertices&#93;.colour = colour;<br />    batchVertices&#91;numBatchVertices&#93;.x = X;<br />    batchVertices&#91;numBatchVertices&#93;.y = Y;<br />    batchVertices&#91;numBatchVertices&#93;.z = 1.0f;<br />    batchVertices&#91;numBatchVertices&#93;.u = rSource-&gt;left / batchTexWidth;<br />    batchVertices&#91;numBatchVertices&#93;.v = rSource-&gt;top / batchTexHeight;<br />   <br />    batchVertices&#91;numBatchVertices + 1&#93;.colour = colour;<br />    batchVertices&#91;numBatchVertices + 1&#93;.x = X + destWidth;<br />    batchVertices&#91;numBatchVertices + 1&#93;.y = Y;<br />    batchVertices&#91;numBatchVertices + 1&#93;.z = 1.0f;<br />    batchVertices&#91;numBatchVertices + 1&#93;.u = rSource-&gt;right / batchTexWidth;<br />    batchVertices&#91;numBatchVertices + 1&#93;.v = rSource-&gt;top / batchTexHeight;<br /><br />    batchVertices&#91;numBatchVertices + 2&#93;.colour = colour;<br />    batchVertices&#91;numBatchVertices + 2&#93;.x = X + destWidth;<br />    batchVertices&#91;numBatchVertices + 2&#93;.y = Y - destHeight;<br />    batchVertices&#91;numBatchVertices + 2&#93;.z = 1.0f;<br />    batchVertices&#91;numBatchVertices + 2&#93;.u = rSource-&gt;right / batchTexWidth;<br />    batchVertices&#91;numBatchVertices + 2&#93;.v = rSource-&gt;bottom / batchTexHeight;<br /><br />    batchVertices&#91;numBatchVertices + 3&#93;.colour = colour;<br />    batchVertices&#91;numBatchVertices + 3&#93;.x = X;<br />    batchVertices&#91;numBatchVertices + 3&#93;.y = Y - destHeight;<br />    batchVertices&#91;numBatchVertices + 3&#93;.z = 1.0f;<br />    batchVertices&#91;numBatchVertices + 3&#93;.u = rSource-&gt;left / batchTexWidth;<br />    batchVertices&#91;numBatchVertices + 3&#93;.v = rSource-&gt;bottom / batchTexHeight;<br /><br />    //Increase vertex count<br />    numBatchVertices += 4;<br /><br />    //Flush buffer if it's full<br />    if (numBatchVertices == BATCH_BUFFER_SIZE)<br />    {<br />	    //Unlock vertex buffer<br />	    vertexBatchBuffer-&gt;Unlock();<br />	   <br />	    //Draw quads in the buffer<br />	    d3dDevice-&gt;DrawIndexedPrimitive (D3DPT_TRIANGLELIST, 0, 0,<br />			  numBatchVertices, 0, numBatchVertices / 2);	   <br /><br />	    //Reset vertex count	   <br />	    numBatchVertices = 0;	   <br /><br />	    //Lock vertex buffer<br />	    vertexBatchBuffer-&gt;Lock (0, BATCH_BUFFER_SIZE * sizeof(TLVERTEX),<br />			  (void **) &batchVertices, 0);<br />    }<br /><br />}</pre><br />
<br />
As you can see, the function has basic colour modulation functionality. It can easil bey extended this to behave similarly to the <strong class='bbc'>BlitExD3D()</strong> function from the article, but I'll leave that up to you. Also, when the vertex buffer gets full, this function automatically draws whatever's inside it, and prepares to receive a new batch of quads.<br />
<br />
<pre class='prettyprint'>//Finish batch drawing<br />void EndBatchDrawing()<br />{<br />    //Unlock vertex buffer<br />    vertexBatchBuffer-&gt;Unlock();<br /><br />    //Draw the quads in the buffer if it wasn't just flushed<br />    if (numBatchVertices)<br />	    d3dDevice-&gt;DrawIndexedPrimitive (D3DPT_TRIANGLELIST, 0, 0,<br />			  numBatchVertices, 0, numBatchVertices / 2);<br /><br />    //Set stream source to regular buffer<br />    d3dDevice-&gt;SetStreamSource (0, vertexBuffer, 0, sizeof(TLVERTEX));<br /><br />    //Reset vertex count	   <br />    numBatchVertices = 0;	   <br />}</pre><br />
<br />
A demonstration of batching building on the NoLocking.zip app can be found in Batching.zip. The batching code presented relies heavily upon global variables and has very little error checking. I urge the reader to encapsulate the batching functionality in a class, and add a lot of error checking (asserting that the vertex buffer is not overflowing in <strong class='bbc'>AddQuad()</strong> would be a good start).]]></description>
		<pubDate>Thu, 31 Jul 2003 22:31:28 +0000</pubDate>
		<guid isPermaLink="false">6d79e030371e47e6231337805a7a2685</guid>
	</item>
</channel>
</rss>
