<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
	<title>APIs and Tools - Articles</title>
	<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/</link>
	<pubDate>Sat, 25 Feb 2012 22:21:24 +0000</pubDate>
	<ttl>43200</ttl>
	<description>Resources for APIs not covered in specific categories as well as software to aid with game development</description>
	<item>
		<title>Wrapper Pattern for Silverlight and WPF</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/wrapper-pattern-for-silverlight-and-wpf-r2866</link>
		<description><![CDATA[<ul class='bbc'><br /><li><a href='http://uploads.gamedev.net/cp/1327954866-WrapperPatternExample.zip' class='bbc_url' title='External link' rel='nofollow external'>Download sample (Silverlight and WPF) - 368 KB</a><br /></li></ul><br />
<br />
License: <a href='http://www.opensource.org/licenses/ms-pl.html' class='bbc_url' title='External link' rel='nofollow external'><span class='bbc_underline'><strong class='bbc'>Ms-PL</strong></span></a><br />
 <br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Table of contents</strong></span><br />
<br />
<strong class='bbc'>	Introduction</strong><br />
<br />
<br />
It has been a long time since my last article. This one is short and a bit less creative than the previous ones, but I hope you'll like it! <img src='http://public.gamedev.net//public/style_emoticons/default/smile.png' class='bbc_emoticon' alt=':)' /><br />
<br />
I hope none of you have never particularly talked about that before, but probably you have already used what I will talk about, without naming it: the wrapper pattern in WPF and Silverlight.<br />
<br />
<strong class='bbc'>	Pattern sheet</strong><br />
<br />
<br />
<strong class='bbc'>Pattern type</strong>: Presentation pattern.<br />
<br />
<strong class='bbc'>Problem</strong>: You want to create an animation or to bind on a property which does not exist on your object -the target- or doesn't support the use of Storyboard or Binding.<br />
<br />
<strong class='bbc'>Solution</strong>: Create an object -a wrapper- which will expose this property, and will modify the target object accordingly.<br />
<br />
<strong class='bbc'>Alternatives</strong>:<br />
<ul class='bbc'><br /><li>Use attached properties; however, it will fail in Silverlight 3.0 (it does not support animation on attached properties in XAML).<br /></li><li>Use a decorator, but it doesn't exist on Silverlight, and sometimes makes your XAML harder to read.<br /></li></ul><br />
<strong class='bbc'>Actor</strong>:<br />
<ul class='bbc'><br /><li>The object we want to animate is called the "target".<br /></li><li>The object we will create to expose new properties to animate is called the "wrapper".<br /></li></ul><br />
<strong class='bbc'>	Concrete examples</strong><br />
<br />
<ul class='bbc'><br /><li>The first is a common problem in Silverlight: binding to the ActualWidth/Height property.<br /></li><li>The second is an element hider; it allows you to show or "push" an element at the border of the screen (like dockable views in Visual Studio).<br /></li></ul><br />
For these two examples, the wrapper pattern provides a really nice solution.<br />
<br />
<strong class='bbc'>	Example 1 - Binding to ActualWidth and ActualHeight</strong><br />
<br />
Here is the example:<br />
<br />
<span rel='lightbox'><img src='http://uploads.gamedev.net/cp/1327954866-SizeWrapper.jpg' alt='Posted Image' class='bbc_img' /></span><br />
<br />
The sliders are bound to the Height and Width of a grid which wraps the green rectangle. The red rectangle's width and height are bound to ActualWidth and ActualHeight of the green rectangle. The Height and Width properties of the green rectangle are not set.<br />
<br />
Here is the code:<br />
<pre class='prettyprint'><br /><br />&lt;&lt;/span&gt;StackPanel&gt;<br />	&lt;&lt;/span&gt;Canvas Background="Yellow" Height="500" Width="500" &gt;<br />		&lt;&lt;/span&gt;Grid x:Name="grid" Canvas.Top="0" Height="100" Width="100"&gt;<br />			&lt;&lt;/span&gt;Rectangle x:Name="greenRect" Fill="Green"&gt;&lt;&lt;/span&gt;/Rectangle&gt;<br />		&lt;&lt;/span&gt;/Grid&gt;<br />		&lt;&lt;/span&gt;Rectangle Canvas.Top="300" Fill="Red" <br />		  Height="{Binding ActualHeight, ElementName=greenRect}" <br />		  Width="{Binding ActualWidth, ElementName=greenRect}"&gt;&lt;&lt;/span&gt;/Rectangle&gt;<br />	&lt;&lt;/span&gt;/Canvas&gt;<br />	<br />	&lt;&lt;/span&gt;Slider Maximum="500" Minimum="0" <br />	  Value="{Binding Height, ElementName=grid, Mode=TwoWay}"&gt;&lt;&lt;/span&gt;/Slider&gt;<br />	&lt;&lt;/span&gt;Slider Maximum="500" Minimum="0" <br />	  Value="{Binding Width, ElementName=grid, Mode=TwoWay}"&gt;&lt;&lt;/span&gt;/Slider&gt;<br />&lt;&lt;/span&gt;/StackPanel&gt;<br /></pre><br />
<br />
<br />
<br />
I want the green and red rectangle to have the same size, and everything goes well in the world of WPF... but Silverlight can't bind to ActualHeight and ActualWidth. So, what is the solution? It's simple, we will create a wrapper, SizeWrapper, with three properties: RealWidth, RealHeight, and Element, the target element.<br />
<br />
<span rel='lightbox'><img src='http://uploads.gamedev.net/cp/1327954866-SizeWrapperClass.jpg' alt='Posted Image' class='bbc_img' /></span><br />
<br />
It will listen to the SizeChanged event of the target element and update its two properties. Here is the code:<br />
<pre class='prettyprint'><br /><br />public class SizeWrapper : FrameworkElement<br />{<br />	public FrameworkElement Element<br />	{<br />		get<br />		{<br />			return (FrameworkElement)GetValue(ElementProperty);<br />		}<br />		set<br />		{<br />			SetValue(ElementProperty, value);<br />		}<br />	}<br /><br />	public double RealHeight<br />	{<br />		get<br />		{<br />			return (double)GetValue(RealHeightProperty);<br />		}<br />		set<br />		{<br />			SetValue(RealHeightProperty, value);<br />		}<br />	}<br /><br />	// Using a DependencyProperty as the backing store for RealHeight.<br />	// This enables animation, styling, binding, etc...<br />	public static readonly DependencyProperty RealHeightProperty =<br />		DependencyProperty.Register("RealHeight", <br />		typeof(double), typeof(SizeWrapper), Helper.CreateMetadata(.));<br /><br />	public double RealWidth<br />	{<br />		get<br />		{<br />			return (double)GetValue(RealWidthProperty);<br />		}<br />		set<br />		{<br />			SetValue(RealWidthProperty, value);<br />		}<br />	}<br /><br />	// Using a DependencyProperty as the backing store for RealWidth.<br />	// This enables animation, styling, binding, etc...<br />	public static readonly DependencyProperty RealWidthProperty =<br />		DependencyProperty.Register("RealWidth", <br />		typeof(double), typeof(SizeWrapper), Helper.CreateMetadata(.));<br /><br />	// Using a DependencyProperty as the backing store<br />	// for Element. This enables animation, styling, binding, etc...<br />	public static readonly DependencyProperty ElementProperty =<br />		DependencyProperty.Register("Element", typeof(FrameworkElement), <br />		typeof(SizeWrapper), Helper.CreateMetadata(null, OnElementChanged));<br /><br />	private static void OnElementChanged(DependencyObject sender, <br />			DependencyPropertyChangedEventArgs args)<br />	{<br />		var wrapper = (SizeWrapper)sender;<br />		var oldElement = args.OldValue as FrameworkElement;<br />		var newElement = args.NewValue as FrameworkElement;<br />		if(oldElement != null)<br />			oldElement.SizeChanged -= wrapper.SizeChanged;<br />		if(newElement != null)<br />		{<br />			newElement.SizeChanged += wrapper.SizeChanged;<br />			wrapper.UpdateSize(new Size(newElement.ActualWidth, <br />										newElement.ActualHeight));<br />		}<br />	}<br /><br />	void SizeChanged(object sender, SizeChangedEventArgs e)<br />	{<br />		UpdateSize(e.NewSize);<br />	}<br /><br />	private void UpdateSize(Size size)<br />	{<br />		RealHeight = size.Height;<br />		RealWidth = size.Width;<br />	}<br />}<br /></pre><br />
<br />
<br />
<br />
Now, here is the slightly modified version. The only modification is that the red rectangle binds to the wrapper's properties instead of the green rectangle directly. As you will expect, it works well. The wrapper is inside the canvas.<br />
<pre class='prettyprint'><br /><br />&lt;&lt;/span&gt;StackPanel&gt;<br />	&lt;&lt;/span&gt;Canvas Height="500" Width="500" &gt;<br />		&lt;&lt;/span&gt;wrappers:SizeWrapper x:Name="sizeWrapper" <br />				   Element="{Binding ElementName=greenRect}"&gt;&lt;&lt;/span&gt;/wrappers:SizeWrapper&gt;<br />		&lt;&lt;/span&gt;Grid x:Name="grid" Canvas.Top="0" <br />				   Height="100" Width="100"&gt;<br />			&lt;&lt;/span&gt;Rectangle x:Name="greenRect" Fill="Green"&gt;&lt;&lt;/span&gt;/Rectangle&gt;<br />		&lt;&lt;/span&gt;/Grid&gt;<br />		&lt;&lt;/span&gt;Rectangle Canvas.Top="300" Fill="Red" <br />		  Height="{Binding RealHeight, ElementName=sizeWrapper}" <br />		  Width="{Binding RealWidth, ElementName=sizeWrapper}"&gt;&lt;&lt;/span&gt;/Rectangle&gt;<br />	&lt;&lt;/span&gt;/Canvas&gt;<br /><br />	&lt;&lt;/span&gt;Slider Maximum="500" Minimum="0" <br />	  Value="{Binding Height, ElementName=grid, Mode=TwoWay}"&gt;&lt;&lt;/span&gt;/Slider&gt;<br />	&lt;&lt;/span&gt;Slider Maximum="500" Minimum="0" <br />	 Value="{Binding Width, ElementName=grid, Mode=TwoWay}"&gt;&lt;&lt;/span&gt;/Slider&gt;<br />&lt;&lt;/span&gt;/StackPanel&gt;<br /></pre><br />
<br />
<br />
<br />
<strong class='bbc'>	Example 2 - Element hider</strong><br />
<br />
Some of you might say: well, it's just useful for a specific workaround; wait a second, read this second example, and you'll appreciate the simplicity!<br />
<br />
This example should deserve its own article because I suspect lots people would want it.<br />
<br />
<span rel='lightbox'><img src='http://uploads.gamedev.net/cp/1327954866-ElementHidderWrapper1.jpg' alt='Posted Image' class='bbc_img' /></span><span rel='lightbox'><img src='http://uploads.gamedev.net/cp/1327954866-ElementHidderWrapper2.jpg' alt='Posted Image' class='bbc_img' /></span><br />
<br />
This time we will use a wrapper called 'ElementHidderWrapper' to "push" an element on the border of the screen (as you can do with the dockable views in Visual Studio).<br />
<br />
<span rel='lightbox'><img src='http://uploads.gamedev.net/cp/1327954866-ElementHidderWrapperClass.jpg' alt='Posted Image' class='bbc_img' /></span><br />
<br />
If Show is 0, then the target is completely collapsed; if it is 1.0, it's completely visible. MinMargin is the minimum margin to show when Show equals 0. HideSide is the side where the element will hide. Here is how to use it:<br />
<pre class='prettyprint'><br /><br />&lt;&lt;/span&gt;Grid&gt;<br />	&lt;&lt;/span&gt;wrappers:ElementHidderWrapper<br />		x:Name="hidder"<br />		Element="{Binding ElementName=border}"<br />		MinMargin="20"<br />		HideSide="Left"<br />		Show="1.0"<br />		&gt;&lt;&lt;/span&gt;/wrappers:ElementHidderWrapper&gt;<br /><br />	&lt;&lt;/span&gt;Border x:Name="border" HorizontalAlignment="Left" <br />			VerticalAlignment="Top" BorderThickness="1.0" <br />			Width="100" Height="300" <br />			BorderBrush="Black" <br />			CornerRadius="0,10,10,0" Background="Green"&gt;<br />		&lt;&lt;/span&gt;Grid&gt;<br />			&lt;&lt;/span&gt;TextBlock Text="blabla" <br />			   HorizontalAlignment="Center" <br />			   VerticalAlignment="Top"&gt;&lt;&lt;/span&gt;/TextBlock&gt;<br />			&lt;&lt;/span&gt;CheckBox IsChecked="True" <br />			   HorizontalAlignment="Right" <br />			   VerticalAlignment="Bottom" <br />			   Click="CheckBox_Click"&gt;<br />			&lt;&lt;/span&gt;/CheckBox&gt;<br />		&lt;&lt;/span&gt;/Grid&gt;<br />	&lt;&lt;/span&gt;/Border&gt;<br />&lt;&lt;/span&gt;/Grid&gt;<br /></pre><br />
<br />
<br />
<br />
The target element is the border. Initially, everything is shown. MinMargin is set to 20 px; this way, we can always click on the checkbox. When you click on the checkbox, it will hide/show the border to the left. It's easy to do, I just need to fire an animation on the Show property of my wrapper.<br />
<pre class='prettyprint'><br /><br />private void CheckBox_Click(object sender, RoutedEventArgs e)<br />{<br />	CheckBox checkBox = (CheckBox)sender;<br />	Storyboard storyBoard = new Storyboard();<br />	DoubleAnimation showAnimation = new DoubleAnimation();<br />	Storyboard.SetTarget(showAnimation, hidder);<br />	Storyboard.SetTargetProperty(showAnimation, new PropertyPath("Show"));<br />	showAnimation.Duration = new Duration(new TimeSpan(, , , , 400));<br />	showAnimation.To = checkBox.IsChecked.Value ? 1. : .;<br />	storyBoard.Children.Add(showAnimation);<br />	storyBoard.Begin();<br />}<br /></pre><br />
<br />
<br />
<br />
The code of the wrapper is not the point, but I will quickly explain: every time a property of the wrapper changes, I recalculate the margins of the target, and it's done.<br />
<pre class='prettyprint'><br /><br />public enum HideSide<br />{<br />	Top,<br />	Bottom,<br />	Left,<br />	Right<br />}<br /><br />public class ElementHidderWrapper : FrameworkElement<br />{<br />	public double MinMargin<br />	{<br />		get<br />		{<br />			return (double)GetValue(MinMarginProperty);<br />		}<br />		set<br />		{<br />			SetValue(MinMarginProperty, value);<br />		}<br />	}<br /><br />	// Using a DependencyProperty as the backing store for MaxShow.<br />	// This enables animation, styling, binding, etc...<br />	public static readonly DependencyProperty MinMarginProperty =<br />		DependencyProperty.Register("MinMargin", typeof(double), <br />		typeof(ElementHidderWrapper), <br />		Helper.CreateMetadata(., MinMarginChanged));<br /><br />	private static void MinMarginChanged(DependencyObject sender, <br />						DependencyPropertyChangedEventArgs args)<br />	{<br />		ElementHidderWrapper hidder = (ElementHidderWrapper)sender;<br />		hidder.UpdateElement();<br />	}<br /><br />	public HideSide HideSide<br />	{<br />		get<br />		{<br />			return (HideSide)GetValue(HideSideProperty);<br />		}<br />		set<br />		{<br />			SetValue(HideSideProperty, value);<br />		}<br />	}<br /><br />	// Using a DependencyProperty as the backing store<br />	// for HideSide. This enables animation, styling, binding, etc...<br />	public static readonly DependencyProperty HideSideProperty =<br />		DependencyProperty.Register("HideSide", typeof(HideSide), <br />		typeof(ElementHidderWrapper), Helper.CreateMetadata(HideSide.Bottom));<br /><br />	public double Show<br />	{<br />		get<br />		{<br />			return (double)GetValue(ShowProperty);<br />		}<br />		set<br />		{<br />			SetValue(ShowProperty, value);<br />		}<br />	}<br /><br />	// Using a DependencyProperty as the backing store for Show.<br />	// This enables animation, styling, binding, etc...<br />	public static readonly DependencyProperty ShowProperty =<br />		DependencyProperty.Register("Show", typeof(double), <br />		typeof(ElementHidderWrapper), Helper.CreateMetadata(1., ShowChanged));<br /><br />	public FrameworkElement Element<br />	{<br />		get<br />		{<br />			return (FrameworkElement)GetValue(ElementProperty);<br />		}<br />		set<br />		{<br />			SetValue(ElementProperty, value);<br />		}<br />	}<br /><br />	// Using a DependencyProperty as the backing store for Element.<br />	// This enables animation, styling, binding, etc...<br />	public static readonly DependencyProperty ElementProperty =<br />		DependencyProperty.Register("Element", <br />		typeof(FrameworkElement), typeof(ElementHidderWrapper), <br />		Helper.CreateMetadata(null, ElementChanged));<br /><br />	private static void ElementChanged(DependencyObject sender, <br />						DependencyPropertyChangedEventArgs args)<br />	{<br />		ElementHidderWrapper hidder = (ElementHidderWrapper)sender;<br />		FrameworkElement oldValue = args.OldValue as FrameworkElement;<br />		FrameworkElement newValue = args.NewValue as FrameworkElement;<br />		if(oldValue != null)<br />			oldValue.SizeChanged -= hidder.SizeChanged;<br />		if(newValue != null)<br />			newValue.SizeChanged += hidder.SizeChanged;<br />		hidder.UpdateElement();<br />	}<br /><br />	private void SizeChanged(object sender, SizeChangedEventArgs e)<br />	{<br />		UpdateElement();<br />	}<br /><br />	private static void ShowChanged(DependencyObject sender, <br />			DependencyPropertyChangedEventArgs args)<br />	{<br />		ElementHidderWrapper hidder = (ElementHidderWrapper)sender;<br />		hidder.UpdateElement();<br />	}<br /><br />	private void UpdateElement()<br />	{<br />		if(Element == null)<br />			return;<br />		var maxValue = GetMaxShowValue(Element);<br />		var minValue = MinMargin;<br />		var calculatedShowValue = minValue + (maxValue - minValue) * Show;<br />		var marginValue = maxValue - calculatedShowValue;<br />		SetMarginValue(Element, marginValue);<br /><br />	}<br /><br />	private void SetMarginValue(FrameworkElement element, double marginValue)<br />	{<br />		if(HideSide == HideSide.Left)<br />		{<br />			element.Margin = new Thickness(-marginValue, <br />			  element.Margin.Top, element.Margin.Right, element.Margin.Bottom);<br />		}<br />		else if(HideSide == HideSide.Top)<br />		{<br />			element.Margin = new Thickness(element.Margin.Left, <br />			  -marginValue, element.Margin.Right, element.Margin.Bottom);<br />		}<br />		else if(HideSide == HideSide.Right)<br />		{<br />			element.Margin = new Thickness(element.Margin.Left, <br />			  element.Margin.Top, -marginValue, element.Margin.Bottom);<br />		}<br />		else if(HideSide == HideSide.Bottom)<br />		{<br />			element.Margin = new Thickness(element.Margin.Left, <br />			  element.Margin.Top, element.Margin.Right, -marginValue);<br />		}<br />	}<br /><br />	private double GetMaxShowValue(FrameworkElement element)<br />	{<br />		if(HideSide == HideSide.Bottom &#124;&#124; HideSide == HideSide.Top)<br />			return element.ActualHeight;<br />		else<br />			return element.ActualWidth;<br />	}<br />}<br /></pre><br />
<br />
<br />
<br />
<strong class='bbc'>	Conclusion</strong><br />
<br />
<br />
This pattern is not great news; however, putting a name on something will help people to use and remember where it fits well. This pattern should definitively be in the toolbox of the WPF/SL developer.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>About the Author</strong></span><br />
<br />
	My goal as a developer, a community member, and enterpreneur is the same : making the minimal product that will help then getting myself out the way. My work is yours.<br />
 <br />
If you are interested for working with me, this way	  <br />
<br />
<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>License</strong></span><br />
<br />
This article was authored by Nicolas Dorier and reproduced for the benefit of our viewers under the terms of the <a href='http://www.opensource.org/licenses/ms-pl.html' class='bbc_url' title='External link' rel='nofollow external'>Ms-PL</a> license.]]></description>
		<pubDate>Mon, 30 Jan 2012 20:22:05 +0000</pubDate>
		<guid isPermaLink="false">5444df470d67382653f5c5600221ddb7</guid>
	</item>
	<item>
		<title>Unity 3-0 Enter the Third Dimension</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/unity-3-0-enter-the-third-dimension-r2856</link>
		<description><![CDATA[Before getting started with any 3D package, it is crucial to understand the environment you'll be working in.<br />
<br />
As such, in this article by <strong class='bbc'>Will Goldstone</strong>, author of <a href='http://www.packtpub.com/unity-3-x-game-development-essentials-with-c-and-j&#097;v&#097;script-will-goldstone/book' class='bbc_url' title='External link' rel='nofollow external'>Unity 3.x Game Development Essentials</a>, we'll make sure you're prepared by looking at some important 3D concepts before moving on to discuss the concepts and interface of Unity itself. You will learn &#097;bout:<br />
<ul class='bbc'><br /><li>Coordinates and vectors<br /></li><li>3D shapes<br /></li><li>Materials and textures<br /></li><li>Rigidbody dynamics<br /></li><li>Collision detection<br /></li><li>GameObjects and Components<br /></li><li>Assets and Scenes<br /></li><li>Prefabs<br /></li><li>Unity editor interface<br /></li></ul><br />
<span style='font-size: 18px;'><strong class='bbc'>Getting to grips with 3D</strong></span><br />
Let's take a look at the crucial elements of 3D worlds, and how Unity lets you develop games in three dimensions.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Coordinates</strong></span><br />
If you have worked with any 3D application before, you'll likely be familiar with the concept of the Z-axis. The Z-axis, in addition to the existing X for horizontal and Y for vertical, represents depth. In 3D applications, you'll see information on objects laid out in X, Y, Z format—this is known as the Cartesian coordinate method. Dimensions, rotational values, and positions in the 3D world can all be described in this way. As in other documentation of 3D, you'll see such information written with parenthesis, shown as follows:<br />
<br />
(3, 5, 3)<br />
<br />
This is mostly for neatness, and also due to the fact that in programming, these values must be written in this way. Regardless of their presentation, you can assume that any sets of three values separated by commas will be in X, Y, Z order.<br />
<br />
In the following image, a cube is shown at location (3,5,3) in the 3D world, meaning it is 3 units from 0 in the X-axis, 5 up in the Y-axis, and 3 forward in the Z-axis:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/1444_01_14.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Local space versus world space</strong></span><br />
A crucial concept to begin looking at is the difference between local space and world space. In any 3D package, the world you will work in is technically infinite, and it can be difficult to keep track of the location of objects within it. In every 3D world, there is a point of origin, often referred to as the <strong class='bbc'>'origin'</strong>> or <strong class='bbc'>'world zero'</strong>, as it is represented by the position (0,0,0).<br />
<br />
All world positions of objects in 3D are relative to world zero. However, to make things simpler, we also use local space (also known as <strong class='bbc'>object space</strong>) to define object positions in relation to one another. These relationships are known as parent-child relationships. In Unity, <strong class='bbc'>parent-child relationships</strong> can be established easily by dragging one object onto another in the Hierarchy. This causes the dragged object to become a child, and its coordinates from then on are read in terms relative to the parent object. For example, if the child object is exactly at the same world position as the parent object, its position is said to be (0,0,0), even if the parent position is not at world zero.<br />
<br />
Local space assumes that every object has its own zero point, which is the point from which its axes emerge. This is usually the center of the object, and by creating relationships between objects, we can compare their positions in relation to one another. Such relationships, known as parent-child relationships, mean that we can calculate distances from other objects using local space, with the parent object's position becoming the new zero point for any of its child objects.<br />
<br />
This is especially important to bear in mind when working on art assets in 3D modelling tools, as you should always ensure that your models are created at 0,0,0 in the package that you are using. This is to ensure that when imported into Unity, their axes are read correctly.<br />
<br />
We can illustrate this in 2D, as the same conventions will apply to 3D. In the following example:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/1444_01_09.png' alt='Posted Image' class='bbc_img' /></span></p><ul class='bbc'><br /><li>The first diagram (i) shows two objects in world space. A large cube exists at coordinates(3,3), and a smaller one at coordinates (6,7).<br /></li><li>In the second diagram (ii), the smaller cube has been made a child object of the larger cube. As such the smaller cube's coordinates are said to be (3,4), because its zero point is the world position of the parent.<br /></li></ul><br />
<span style='font-size: 14px;'><strong class='bbc'>Vectors</strong></span><br />
You'll also see 3D vectors described in Cartesian coordinates. Like their 2D counterparts, 3D vectors are simply lines drawn in the 3D world that have a direction and a length. Vectors can be moved in world space, but remain unchanged themselves. Vectors are useful in a game engine context, as they allow us to calculate distances, relative angles between objects, and the direction of objects.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Cameras</strong></span><br />
Cameras are essential in the 3D world, as they act as the viewport for the screen.<br />
<br />
Cameras can be placed at any point in the world, animated, or attached to characters or objects as part of a game scenario. Many cameras can exist in a particular scene, but it is assumed that a single main camera will always render what the player sees. This is why Unity gives you a Main Camera object whenever you create a new scene.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Projection mode—3D versus 2D</strong></span><br />
The Projection mode of a camera states whether it renders in 3D (Perspective) or 2D (Orthographic). Ordinarily, cameras are set to Perspective Projection mode, and as such have a pyramid shaped Field of View (FOV). A Perspective mode camera renders in 3D and is the default Projection mode for a camera in Unity. Cameras can also be set to Orthographic Projection mode in order to render in 2D—these have a rectangular field of view. This can be used on a main camera to create complete 2D games or simply used as a secondary camera used to render Heads Up Display (HUD) elements such as a map or health bar.<br />
<br />
In game engines, you'll notice that effects such as lighting, motion blurs, and other effects are applied to the camera to help with game simulation of a person's eye view of the world—you can even add a few cinematic effects that the human eye will never experience, such as lens flares when looking at the sun!<br />
<br />
Most modern 3D games utilize multiple cameras to show parts of the game world that the character camera is not currently looking at—like a 'cutaway' in cinematic terms. Unity does this with ease by allowing many cameras in a single scene, which can be scripted to act as the main camera at any point during runtime. Multiple cameras can also be used in a game to control the rendering of particular 2D and 3D elements separately as part of the optimization process. For example, objects may be grouped in layers, and cameras may be assigned to render objects in particular layers. This gives us more control over individual renders of certain elements in the game.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Polygons, edges, vertices, and meshes</strong></span><br />
In constructing 3D shapes, all objects are ultimately made up of interconnected 2D shapes known as polygons. On importing models from a modeling application, Unity converts all polygons to polygon triangles. By combining many linked polygons, 3D modeling applications allow us to build complex shapes, known as meshes. Polygon triangles (also referred to as faces) are in turn made up of three connected edges. The locations at which these edges meet are known as points or vertices.<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/1444_01_05.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
By knowing these locations, game engines are able to make calculations regarding the points of impact, known as collisions, when using complex collision detection with Mesh Colliders, such as in shooting games to detect the exact location at which a bullet has hit another object. In addition to building 3D shapes that are rendered visibly, mesh data can have many other uses. For example, it can be used to specify a shape for collision that is less detailed than a visible object, but roughly the same shape. This can help save performance as the physics engine needn't check a mesh in detail for collisions. This is seen in the following image from the Unity car tutorial, where the vehicle itself is more detailed than its collision mesh:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/1444_01_10.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
In the second image, you can see that the amount of detail in the mesh used for the collider is far less than the visible mesh itself:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/1444_01_11.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
In game projects, it is crucial for the developer to understand the importance of the polygon count. The polygon count is the total number of polygons, often in reference to models, but also in reference to props, or an entire game level (or in Unity terms, 'Scene'). The higher the number of polygons, the more work your computer must do to render the objects onscreen. This is why we've seen an increase in the level of detail from early 3D games to those of today. Simply compare the visual detail in a game such as id's Quake(1996) with the details seen in Epic's Gears Of War (2006) in just a decade. As a result of faster technology, game developers are now able to model 3D characters and worlds, for games that contain a much higher polygon count and resultant level of realism, and this trend will inevitably continue in the years to come. This said, as more platforms emerge such as mobile and online, games previously seen on dedicated consoles can now be played in a web browser thanks to Unity. As such, the hardware constraints are as important now as ever, as lower powered devices such as mobile phones and tablets are able to run 3D games. For this reason, when modeling any object to add to your game, you should consider polygonal detail, and where it is most required.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Materials, textures, and shaders</strong></span><br />
Materials are a common concept to all 3D applications, as they provide the means to set the visual appearance of a 3D model. From basic colors to reflective image-based surfaces, materials handle everything.<br />
<br />
Let's start with a simple color and the option of using one or more images—known as textures. In a single material, the material works with the shader, which is a script in charge of the style of rendering. For example, in a reflective shader, the material will render reflections of surrounding objects, but maintain its color or the look of the image applied as its texture.<br />
<br />
In Unity, the use of materials is easy. Any materials created in your 3D modeling package will be imported and recreated automatically by the engine and created as assets that are reusable. You can also create your own materials from scratch, assigning images as textures and selecting a shader from a large library that comes built-in. You may also write your own shader scripts or copy-paste those written by fellow developers in the Unity community, giving you more freedom for expansion beyond the included set.<br />
<br />
When creating textures for a game in a graphics package such as Photoshop or GIMP, you must be aware of the resolution. Larger textures will give you the chance to add more detail to your textured models, but be more intensive to render. Game textures imported into Unity will be scaled to a power of 2 resolution. For example:<br />
<ul class='bbc'><br /><li>64px x 64px<br /></li><li>128px x 128px<br /></li><li>256px x 256px<br /></li><li>512px x 512px<br /></li><li>1024px x 1024px<br /></li></ul><br />
Creating textures of these sizes with content that matches at the edges will mean that they can be tiled successfully by Unity. You may also use textures scaled to values that are not powers of two, but mostly these are used for GUI elements.<br />
<br />
<br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Rigidbody physics</strong></span><br />
For developers working with game engines, physics engines provide an accompanying way of simulating real-world responses for objects in games. In Unity, the game engine uses Nvidia's PhysX engine, a popular and highly accurate commercial physics engine.<br />
<br />
In game engines, there is no assumption that an object should be affected by physics—firstly because it requires a lot of processing power, and secondly because there is simply no need to do so. For example, in a 3D driving game, it makes sense for the cars to be under the influence of the physics engine, but not the track or surrounding objects, such as trees, walls, and so on—they will remain static for the duration of the game. For this reason, when making games in Unity a Rigidbody physics component is given to any object that you wish to be under the control of the physics engine, and ideally any moving object, so that the physics engine is aware of the moving object, to save on performance.<br />
<br />
Physics engines for games use the Rigidbody dynamics system of creating realistic motion. This simply means that instead of objects being static in the 3D world, they can have properties such as mass, gravity, velocity, and friction.<br />
<br />
As the power of hardware and software increases, Rigidbody physics is becoming more widely applied in games, as it offers the potential for more varied and realistic simulation. We'll be utilizing rigid body dynamics as part of our prototype in this article.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Collision detection</strong></span><br />
More crucial in game engines than in 3D animation, collision detection is the way we analyze our 3D world for inter-object collisions. By giving an object a Collider component, we are effectively placing an invisible net around it. This net usually mimics its shape and is in charge of reporting any collisions with other colliders, making the game engine respond accordingly.<br />
<br />
There are two main types of Collider in Unity—Primitives and Meshes. Primitive shapes in 3D terms are simple geometric objects such as Boxes, Spheres, and Capsules. Therefore, a primitive collider such as a Box collider in Unity has that shape, regardless of the visual shape of the 3D object it is applied to. Often, Primitive colliders are used because they are computationally cheaper or because there is no need for precision. A Mesh collider is more expensive as it can be based upon the shape of the 3D mesh it is applied to; therefore, the more complex the mesh, the more detailed and precise the collider will be, and more computationally expensive it will become. However, as shown in the Car tutorial example earlier, it is possible to assign a simpler mesh than that which is rendered, in order to create simpler and more efficient mesh colliders.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>The following diagram illustrates the various types and subtypes of collider:</strong></span><br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/1444_01_15.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
For example, in a ten-pin bowling game, a simple Sphere collider will surround the ball, while the pins themselves will have either a simple Capsule collider, or for a more realistic collision, employ a Mesh collider, as this will be shaped the same as the 3D mesh of the pin. On impact, the colliders of any affected objects will report to the physics engine, which will dictate their reaction, based on the direction of impact, speed, and other factors.<br />
<br />
In this example, employing a Mesh collider to fit exactly to the shape of the pin model would be more accurate but is more expensive in processing terms. This simply means that it demands more processing power from the computer, the cost of which is reflected in slower performance, and hence the term expensive.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Essential Unity concepts</strong></span><br />
Unity makes the game production process simple by giving you a set of logical steps to build any conceivable game scenario. Renowned for being non-game-type specific, Unity offers you a blank canvas and a set of consistent procedures to let your imagination be the limit of your creativity. By establishing its use of the GameObject concept, you are able to break down parts of your game into easily manageable objects, which are made of many individual Component parts. By making individual objects within the game—introducing functionality to them with each component you add, you are able to infinitely expand your game in a logical progressive manner.<br />
<br />
Component parts in turn have Variables—essentially properties of the component, or settings to control them with. By adjusting these variables, you'll have complete control over the effect that Component has on your object. The following diagram illustrates this:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/1444_01_06.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
In the following image we can see a Game Object with a Light Component, as seen in the Unity interface:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/1444_01_12.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
Now let's look at how this approach would be used in a simple gameplay context.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>The Unity way—an example</strong></span><br />
If we wished to have a bouncing ball as part of a game, then we would begin with a sphere. This can quickly be created from the Unity menus, and will give you a new GameObject with a Sphere mesh (the 3D shape itself). Unity will automatically add a Renderer component to make it visible. Having created this, we can then add a Rigidbody component. A Rigidbody (Unity refers to most two-word phrases as a single word term) is a component which tells Unity to apply its physics engine to an object. With this comes properties such as mass, gravity, drag, and also the ability to apply forces to the object, either when the player commands it or simply when it collides with another object.<br />
<br />
Our sphere will now fall to the ground when the game runs, but how do we make it bounce? This is simple! The collider component has a variable called Physic Material—this is a setting for the physics engine, defining how it will react to other objects' surfaces. Here we can select Bouncy—a ready-made Physic material provided by Unity as part of an importable package and voila! Our bouncing ball is complete in only a few clicks.<br />
<br />
This streamlined approach for the most basic of tasks, such as the previous example, seems pedestrian at first. However, you'll soon find that by applying this approach to more complex tasks, they become very simple to achieve. Here is an overview of some further key Unity concepts you'll need to know as you get started.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Assets</strong></span><br />
These are the building blocks of all Unity projects. From textures in the form of image files, through 3D models for meshes, and sound files for effects, Unity refers to the files you'll use to create your game as assets. This is why in any Unity project folder all files used are stored in a child folder named Assets. This Assets folder is mirrored in the Project panel of the Unity interface; see The interface section in this article.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Scenes</strong></span><br />
In Unity, you should think of scenes as individual levels, or areas of game content—though some developers create entire games in a single scene, such as, puzzle games, by dynamically loading content through code. By constructing your game with many scenes, you'll be able to distribute loading times and test different parts of your game individually. New scenes are often used separately to a game scene you may be working on, in order to prototype or test a piece of potential gameplay.<br />
<br />
Any currently open scene is what you are working on, as no two scenes can be worked on simultaneously. Scenes can be manipulated and constructed by using the Hierarchy and Scene views.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>GameObjects</strong></span><br />
Any active object in the currently open scene is called a GameObject. Certain assets taken from the Project panel such as models and prefabs become game objects when placed (or 'instantiated') into the current scene. Other objects such as particle systems and primitives can be placed into the scene by using the Create button on the Hierarchy or by using the GameObject menu at the top of the interface. All GameObjects contain at least one component to begin with, that is, the Transform component. Transform simply tells the Unity engine the position, rotation, and scale of an object—all described in X, Y, Z coordinate (or in the case of scale, dimensional) order. In turn, the component can then be addressed in scripting in order to set an object's position, rotation, or scale. From this initial component, you will build upon GameObjects with further components, adding required functionality to build every part of any game scenario you can imagine.<br />
<br />
In the following image, you can see the most basic form of a Game Object, as shown in the Inspector panel:<br />
<br />
<p class='bbc_center'><span rel='lightbox'><img src='http://uploads.gamedev.net/packtpub/1444_01_13.png' alt='Posted Image' class='bbc_img' /></span></p><br />
<br />
GameObjects can also be nested in the Hierarchy, in order to create the parent-child relationships mentioned previously.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Components</strong></span><br />
Components come in various forms. They can be for creating behavior, defining appearance, and influencing other aspects of an object's function in the game. By attaching components to an object, you can immediately apply new parts of the game engine to your object. Common components of game production come built-in with Unity, such as the Rigidbody component mentioned earlier, down to simpler elements such as lights, cameras, particle emitters, and more. To build further interactive elements of the game, you'll write scripts, which are also treated as components in Unity. Try to think of a script as something that extends or modifies the existing functionality available in Unity or creates behavior with the Unity scripting classes provided.<br />
<br />
<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Scripts</strong></span><br />
While being considered by Unity to be components, scripts are an essential part of game production, and deserve a mention as a key concept. We will write our scripts in both C Sharp (More often written as 'C#') and J&#097;v&#097;script. You should also be aware that Unity offers you the opportunity to write in Boo (a derivative of the Python language).We have chosen to primarily focus on C# and J&#097;v&#097;script as these are the main two languages used by Unity developers, and Boo is not supported for scripting on mobile devices; for this reason it is not advised to begin learning Unity scripting with Boo.<br />
<br />
Unity does not require you to learn how the coding of its own engine works or how to modify it, but you will be utilizing scripting in almost every game scenario you develop. The beauty of using Unity scripting is that any script you write for your game will be straightforward enough after a few examples, as Unity has its own built-in Behavior class called Monobehaviour—a set of scripting instructions for you to call upon. For many new developers, getting to grips with scripting can be a daunting prospect, and one that threatens to put off new Unity users who are more accustomed to design. If this is your first attempt at getting into game development, or you have no experience in writing code, do not worry. We will introduce scripting one step at a time, with a mind to showing you not only the importance, but also the power of effective scripting for your Unity games.<br />
<br />
To write scripts, you'll use Unity's standalone script editor, Monodevelop. This separate application can be found in the Unity application folder on your PC or Mac and will be launched any time you edit a new script or an existing one. Amending and saving scripts in the script editor will immediately update the script in Unity as soon as you switch back to Unity. You may also designate your own script editor in the Unity preferences if you wish to, such as Visual Studio. Monodevelop is recommended however, as it offers auto-completion of code as you type and is natively developed and updated by Unity Technologies.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Prefabs</strong></span><br />
Unity's development approach hinges around the GameObject concept, but it also has a clever way to store objects as assets to be reused in different parts of your game, and then instantiated (also known as 'spawning' or 'cloning') at any time. By creating complex objects with various components and settings, you'll be effectively building a template for something you may want to spawn multiple instances of (hence 'instantiate'), with each instance then being individually modifiable.<br />
<br />
Consider a crate as an example—you may have given the object in the game a mass, and written scripted behaviors for its destruction, and chances are you'll want to use this object more than once in a game, and perhaps even in games other than the one it was designed for.<br />
<br />
Prefabs allow you to store the object, complete with components and current configuration. Comparable to the MovieClip concept in Adobe Flash, think of prefabs simply as empty containers that you can fill with objects to form a data template you'll likely recycle.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Summary</strong></span><br />
In this article, we saw the concepts of working in 3D and how game development works with Unity. Having covered how 3D development works, you will learn the core windows that make up the Unity Editor environment.]]></description>
		<pubDate>Fri, 27 Jan 2012 03:52:29 +0000</pubDate>
		<guid isPermaLink="false">0f40c9bdd25fd8950dc1c7e66862e6d9</guid>
	</item>
	<item>
		<title>Unreal Development Kit Upgrade Overview</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/unreal-development-kit-upgrade-overview-r2817</link>
		<description><![CDATA[The Unreal Development Kit (UDK), Epic Games’ free edition of Unreal Engine 3, has been installed by more than 900,000 developers. Powering independent games like “Hawken” and “Sanctum” for PC, and “The Dark Meadow” and “Save Our Sheep” for iOS, its feature set continues to evolve in preparation for the next generation of games. Epic has continued to release major new functionality and improvements to the Unreal Development Kit, with many important new features introduced in recent months. Anyone can check out the Unreal Engine tools for free at <a href='http://www.udk.com/download' class='bbc_url' title='External link' rel='nofollow external'>www.udk.com/download</a>.<br />
<br />
Epic’s new trailer shows off much of the technology upgrades covered in this article:<br />
 <br />
<p class='bbc_center'><object style="height: 390px; width: 640px"><param name="movie" value="http://youtube.com/v/n6UkNN-LRi0?version=3" /><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><embed src="http://youtube.com/v/n6UkNN-LRi0?version=3" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="640" height="360"></embed></object></p><br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Community Resources</strong></span><br />
<br />
  The <a href='http://udn.epicgames.com/' class='bbc_url' title='External link' rel='nofollow external'>Unreal Developer Network</a> (UDN) is by far the most valuable resource for Unreal Engine developers, with its searchable database of thousands of pages of documentation.<br />
<br />
  Epic recently redesigned the <a href='http://udn.epicgames.com/Three/WebHome.html' class='bbc_url' title='External link' rel='nofollow external'>UDK portal</a> to make it easier to find tips on getting started, <a href='http://udn.epicgames.com/Three/VideoTutorials.html' class='bbc_url' title='External link' rel='nofollow external'>video tutorials</a>, as well as <a href='http://udn.epicgames.com/Three/DevelopmentKitGems.html' class='bbc_url' title='External link' rel='nofollow external'>UDK Gems</a>, a vetted collection of real-world examples and practical applications for the Unreal Engine 3 toolset.<br />
<br />
  There are multiple channels Unreal Engine developers can use to connect with each other, such as the <a href='http://www.udk.com/forums' class='bbc_url' title='External link' rel='nofollow external'>UDK forums</a>, which include specialized sections for iOS development, programming and UnrealScript, level design, and much more.<br />
<br />
  Epic often sources the <a href='http://forums.epicgames.com/forumdisplay.php?f=385' class='bbc_url' title='External link' rel='nofollow external'>Works in Progress</a> and <a href='http://forums.epicgames.com/forumdisplay.php?f=386' class='bbc_url' title='External link' rel='nofollow external'>Released Projects</a> forums to find projects for its <a href='http://udk.com/showcase' class='bbc_url' title='External link' rel='nofollow external'>UDK Showcase</a> success stories.<br />
<br />
  Developers can also join the <a href='http://www.linkedin.com/groups?gid=2493123' class='bbc_url' title='External link' rel='nofollow external'>UDK Developers</a> and <a href='http://www.linkedin.com/groups?gid=57319' class='bbc_url' title='External link' rel='nofollow external'>Unreal Engine Developers</a> groups on LinkedIn, as well as the <a href='http://www.facebook.com/UnrealEngine' class='bbc_url' title='External link' rel='nofollow external'>Unreal Engine Facebook page</a>.<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>UDK Features: New and Improved</strong></span><br />
<br />
Check out in detail what's been added and upgraded in the latest UDK release. There is <a href='http://udk.com/news-beta-aug2011' class='bbc_url' title='External link' rel='nofollow external'>a complete list</a> in the August UDK release.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>Raised Royalty Threshold for UDK Developers</strong></span><br />
<br />
  Epic raised the royalty-free revenue threshold for UDK commercial developers earlier this year.<br />
<br />
  Under  the new license agreement, developers don’t pay any royalties until  their total revenue exceeds $50,000 (US). Beyond that, developers keep  75 percent of each dollar they receive and Epic receives 25 percent.<br />
<br />
  The first step to taking a UDK game commercial is to pay a $99 (US) fee at <a href='http://www.udk.com/' class='bbc_url' title='External link' rel='nofollow external'>www.udk.com</a>  when it’s time to start realizing financial benefit. The one-time  license fee applies to an entire studio for an unlimited number of games  and apps across multiple platforms.<br />
<br />
  Below are real-life  examples that assume the fee of $99 has been paid and that the digital  store keeps 30 percent of gross revenue. Epic takes a percentage of the  portion of the revenue that developers receive. In retail terms, this  would be known as the “wholesale” amount as opposed to the “retail”  amount.<br />
<br />
<a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5079-0-15410500-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5079" title="UDK Pricing Example 1.jpg - Size: 53.57K, Downloads: 1103"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-46918600-1314237619_thumb.jpg" id='ipb-attach-img-5079-0-15410500-1330208485' style='width:171;height:200' class='attach' width="171" height="200" alt="Attached Image: UDK Pricing Example 1.jpg" /></a> <a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5080-0-15424400-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5080" title="UDK Pricing Example 2.jpg - Size: 63.11K, Downloads: 1302"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-79708600-1314237619_thumb.jpg" id='ipb-attach-img-5080-0-15424400-1330208485' style='width:166;height:200' class='attach' width="166" height="200" alt="Attached Image: UDK Pricing Example 2.jpg" /></a><br />
<br />
  Having such a large royalty threshold makes it possible  for developers to use UDK to establish themselves financially, keep  overhead low and leverage the latest game engine technology.<br />
<br />
  Epic is always willing to speak with developers who are in need of a custom deal or wish to discuss full source terms.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>iOS Support</strong></span><br />
<br />
   In December 2010, Epic launched UDK with iOS support in conjunction with the launch of its award-winning game “Infinity Blade” for iOS. This made it possible for all developers to build their own iOS games and applications using the same technology that Steve Jobs highlighted and called "remarkable" at the Apple Special Event keynote introducing the iPhone 4. UDK enables anyone to build levels, visually script gameplay events and add visual effects for mobile applications using the Unreal Editor and its fully integrated suite of systems, including Unreal Kismet, Unreal Cascade, Unreal Matinee and Unreal Lightmass.<br />
<br />
  Included with UDK’s iOS support are handy tools such as UDK Remote, which enables iOS devices to serve as wireless controllers with full touch and tilt functionality for PC testing. The UDK mobile previewer enables an instant local preview with simulated mobile input, and the new Unreal Frontend system compiles scripts and deploys builds for multiple platforms with the simple click of a button. UDK's highly optimized mobile renderer supports per-pixel lighting, environment mapping, precomputed visibility and much more.  <br />
<br />
<br />
<p class='bbc_center'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5083-0-15465100-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5083" title="InfinityBlade.jpg - Size: 276.51K, Downloads: 1342"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-33471800-1314237873_thumb.jpg" id='ipb-attach-img-5083-0-15465100-1330208485' style='width:250;height:167' class='attach' width="250" height="167" alt="Attached Image: InfinityBlade.jpg" /></a><br />
<em class='bbc'>Infinity Blade for iOS devices</em></p><br />
<br />
  NVIDIA PhysX is supported in UDK’s iOS development environment, and this makes it possible to create realistic physics-powered gameplay, simulations and dynamic effects for mobile devices.<br />
<br />
  UDK iOS also supports gamma correction, which enables the creation of levels and content with consistent lighting across platforms.<br />
 <br />
<p class='bbc_center'><em class='bbc'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5089-0-15549400-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5089" title="gammacorrection.png - Size: 275.47K, Downloads: 1097"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-59312800-1314237883_thumb.png" id='ipb-attach-img-5089-0-15549400-1330208485' style='width:250;height:189' class='attach' width="250" height="189" alt="Attached Image: gammacorrection.png" /></a><br />
UDK iOS image gamma-corrected to match PC</em></p><br />
<br />
  Because gamma correction on mobile devices can cause a fairly noticeable impact on performance, it is mainly meant as a feature for use on iPad 2 and future mobile devices.<br />
 <br />
<p class='bbc_left'>In addition, UDK now has one unified executable and game content tree for creating PC and mobile games. Developers can preview PC levels with mobile features instantly with a simple tool bar toggle.</p><br />
<strong class='bbc'><span style='font-size: 12px;'>  DirectX 11 Technology</span></strong><br />
<br />
  At this year’s Game Developers Conference, attendees were wowed by Epic Games’ <a href='http://udk.com/showcase-samaritan' class='bbc_url' title='External link' rel='nofollow external'>Samaritan</a> presentation, a sneak peak at the amazing visual fidelity achievable with Unreal Engine 3. Offering the world a first look at a real-time demonstration constructed entirely in DirectX 11, Samaritan sent shockwaves through the industry.<br />
 <br />
<p class='bbc_center'><em class='bbc'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5076-0-15367600-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5076" title="BillboardReflections.jpg - Size: 235.03K, Downloads: 1025"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-70013000-1314236779_thumb.jpg" id='ipb-attach-img-5076-0-15367600-1330208485' style='width:250;height:139' class='attach' width="250" height="139" alt="Attached Image: BillboardReflections.jpg" /></a><br />
Billboard reflections in Epic’s Samaritan real-time demo</em></p><br />
<br />
  UDK immediately began shipping with the DirectX 11 technology that powers Epic’s Samaritan demo. As Epic Games CEO and Technical Director Tim Sweeney points out, “all of these techniques can be readily adopted in PC games today,” but more excitingly, they are readily available for anyone to use, regardless of their budget or past experience through UDK.<br />
<br />
  When asked why Epic adopts such a stance, when others restrict technology to their own studios until the launch of a particular product, Sweeney states that, “given the incredible pace of progress in the industry, software releases cannot afford to be a once-every-few-years phenomenon akin to Windows OS releases. Software must be treated as a living product, continually evolving and always available.” As such, Sweeney “wants to share Epic’s latest and greatest stuff with the world.” Making his point clear, he says, “from Unreal Engine 3 licensees building triple-A titles, to the UDK developer community, to students learning development at universities, everyone can get their hands on this stuff and check it out.”<br />
<br />
  UDK leverages DirectX features such as tessellation and displacement, geometry shaders, multisampled textures and Shader Model 5.<br />
 <br />
<p class='bbc_center'><em class='bbc'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5078-0-15397300-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5078" title="ShadowedPointLightreflections.jpg - Size: 193.08K, Downloads: 840"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-05170700-1314236781_thumb.jpg" id='ipb-attach-img-5078-0-15397300-1330208485' style='width:250;height:139' class='attach' width="250" height="139" alt="Attached Image: ShadowedPointLightreflections.jpg" /></a><br />
Shadowed point light reflections in Samaritan</em></p><br />
<br />
   High-end rendering technology includes:<ul class='bbc'><br /><li>Image-based reflections that allow surfaces of any shape to reflect an approximate version of scenes, with varying glossiness across surfaces, anisotropic HDR highlights and anti-aliasing;<br /></li><li>Subsurface scattering (SSS) that simulates the light that scatters inside semi-translucent materials, making character skin come alive;<br /></li><li>Anti-aliased masked materials that super sample the edges of masked and alpha-tested materials, making character hair more look realistic than ever before;<br /></li><li>Deferred rendering with MSAA support;<br /></li><li>Bokeh depth of field providing close to film-quality DOF, with artist-controllable Bokeh; and<br /></li><li>High-quality dynamic shadows from many lights on the environment, such as shadows for point lights.<br /></li></ul><br />
  In addition, FXAA and MLAA post-processing methods have been integrated into UDK. <span style='font-size: 12px;'><a href='http://udn.epicgames.com/Three/PostProcessAA' class='bbc_url' title='External link' rel='nofollow external'>Post-process anti-aliasing</a> is supported for DirectX 9 and DirectX 11.</span><br />
 <br />
<p class='bbc_center'><em class='bbc'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5087-0-15521500-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5087" title="postprocessaa.jpg - Size: 56.01K, Downloads: 725"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-65713100-1314237874_thumb.jpg" id='ipb-attach-img-5087-0-15521500-1330208485' style='width:250;height:181' class='attach' width="250" height="181" alt="Attached Image: postprocessaa.jpg" /></a><br />
Post-process anti-aliasing turned off vs. activated in UDK.</em></p><br />
<br />
<span style='font-size: 14px;'>  <strong class='bbc'>NVIDIA APEX</strong>  </span><br />
<br />
  UDK is fully integrated with NVIDIA APEX, a high-level scalable framework oriented on the creation of complex physical effects, such as destructible environments and dynamic character clothing.<br />
  <br />
<br />
<p class='bbc_center'><em class='bbc'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5075-0-15300300-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5075" title="Apex1.JPG - Size: 37.09K, Downloads: 706"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-04389100-1314236779_thumb.jpg" id='ipb-attach-img-5075-0-15300300-1330208485' style='width:180;height:200' class='attach' width="180" height="200" alt="Attached Image: Apex1.JPG" /></a><br />
<span style='font-size: 12px;'>Samaritan utilizes APEX physics, most notably for the movement<br />
of the main character’s coat, which flaps when in motion.</span></em></p><br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>  Unreal Landscape</strong></span><br />
<br />
  Developed by Epic Games Korea to meet the high standards of leading MMO licensees, Unreal Landscape supports huge terrains with long draw distances, and it also has great streaming support. Utilizing geo-mipmapping and texture mipmaps, Landscape morphs between vertex positions in the vertex shader to avoid seams, resulting in smooth LOD transitions.<br />
<br />
  Artists can add detailed normal maps over topography and customize the look of terrain with height painting, smoothing, flattening, fill, hydraulic and thermal erosion tools. Layers in Unreal Landscape correspond to layer blend nodes set up in the Unreal Material Editor, and each layer can be assigned a physical material, such as grass, rock, snow or sand. <a href='http://udn.epicgames.com/Three/Landscape.html' class='bbc_url' title='External link' rel='nofollow external'>Unreal Landscape</a> also supports decals, which makes it possible to add dynamic effects such as tire tracks or footsteps to surfaces.<br />
<br />
  A new Landscape copy and paste mode enables users to replicate regions of terrain with ease. Artists can copy layer height, weight and other properties, e.g., translate all the characteristics of one mountain top to another. Landscape gizmos can be arbitrarily positioned, rotated and resized.<br />
<br />
<br />
<p class='bbc_center'><em class='bbc'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5085-0-15494000-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5085" title="landscapecopypaste.jpg - Size: 38.66K, Downloads: 909"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-00486600-1314237874_thumb.jpg" id='ipb-attach-img-5085-0-15494000-1330208485' style='width:250;height:105' class='attach' width="250" height="105" alt="Attached Image: landscapecopypaste.jpg" /></a><br />
New Unreal Landscape gizmo lets artist copy and paste regions of terrain.</em></p><br />
<br />
  In addition, Wacom tablet support is available for mesh painting, and a history tab enables users to undo and recreate actions.<br />
<br />
<span style='font-size: 14px;'>  <strong class='bbc'>New Foliage Editor</strong></span><br />
<br />
  UDK also has a new foliage system that allows artists and level designers to quickly and efficiently add a variety of detail meshes such as plant life to levels.<br />
<br />
  Mesh painting can be performed anywhere in a level. Developers can choose the number of instances in an area, change the scale and paint on vegetation as desired.<br />
 <br />
<p class='bbc_center'><em class='bbc'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5082-0-15451400-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5082" title="foliageeditor.jpg - Size: 97.87K, Downloads: 961"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-52141000-1314237872_thumb.jpg" id='ipb-attach-img-5082-0-15451400-1330208485' style='width:250;height:142' class='attach' width="250" height="142" alt="Attached Image: foliageeditor.jpg" /></a><br />
A sample scene created using UDK’s new foliage editor.</em></p><br />
<br />
  The foliage system can produce a large number of instances in a single draw call, as the amount of data sent from the CPU to the graphics card is extremely small. Artists can specify a Landscape layer and use that layer's weight to affect foliage density.	<br />
<br />
<span style='font-size: 14px;'>  <strong class='bbc'>Unreal Matinee Video Capture</strong></span><br />
<br />
  UDK ships with a new integrated Unreal Matinee and game movie capture feature.<br />
<br />
  Matinees can be captured to AVI via a new button on the Unreal Matinee toolbar.<br />
 <br />
<p class='bbc_center'><em class='bbc'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5081-0-15437900-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5081" title="Aug-2011-Movie-Capture.jpg - Size: 61.05K, Downloads: 898"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-10157400-1314237872_thumb.jpg" id='ipb-attach-img-5081-0-15437900-1330208485' style='width:250;height:155' class='attach' width="250" height="155" alt="Attached Image: Aug-2011-Movie-Capture.jpg" /></a><br />
<span style='font-size: 12px;'>Movie capture in action with Samaritan</span></em></p><br />
<br />
  A running game can be captured to AVI with simple console commands.<br />
<br />
<span style='font-size: 14px;'>  <strong class='bbc'>Soft-Edge Motion Blur and Motion Blur Skinning</strong></span><br />
<br />
   In traditional film cameras, the shutter remains open for an extended period of time when an image is taken to capture more light. Moving objects appear blurred along their movement direction. The Unreal Engine’s motion blur is based on a post-processing effect that blurs image content by averaging multiple texture samples. Blurring outside of the object as seen in film images is possible but requires extra effort. Epic’s solution for the problem is <a href='http://udn.epicgames.com/Three/Moti&#111;nblurSoftEdge.html' class='bbc_url' title='External link' rel='nofollow external'>soft-edge motion blur</a>.<br />
<br />
  Using the soft-edge feature further improves the quality of the motion blur to become a more filmic effect.<br />
 <br />
<p class='bbc_center'><em class='bbc'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5077-0-15383900-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5077" title="MotionBlur_Marcus.jpg - Size: 109.14K, Downloads: 986"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-37408700-1314236780_thumb.jpg" id='ipb-attach-img-5077-0-15383900-1330208485' style='width:184;height:200' class='attach' width="184" height="200" alt="Attached Image: MotionBlur_Marcus.jpg" /></a><br />
Body parts moving in different directions show different motion blur direction and strength.</em></p><br />
<br />
  <a href='http://udn.epicgames.com/Three/Moti&#111;nblurSkinning.html' class='bbc_url' title='External link' rel='nofollow external'>Motion blur skinning</a> layers individual levels of motion blur onto different parts of a character’s body. The motion blur skinning post-process feature increases the perception of movement on characters.  <br />
<br />
  In addition, developers can utilize new features such as HDR scale and film grain.<br />
<br />
<span style='font-size: 14px;'>  <strong class='bbc'>Simplygon Skeletal and Static Mesh Reduction</strong></span><br />
<br />
   The Unreal Engine now ships with Simplygon static and skeletal mesh reduction technology. Donya Labs recently integrated Simplygon with Unreal Engine 3, and its high-quality mesh reduction features are accessible via the Unreal Editor.<br />
<br />
  UDK developers may use Simplygon’s integrated features for all projects, commercial and non-commercial, at no additional cost.<br />
 <br />
<p class='bbc_center'><em class='bbc'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5088-0-15535700-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5088" title="simplygon.jpg - Size: 82.89K, Downloads: 1021"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-05484000-1314237875_thumb.jpg" id='ipb-attach-img-5088-0-15535700-1330208485' style='width:250;height:133' class='attach' width="250" height="133" alt="Attached Image: simplygon.jpg" /></a><br />
The results of UDK’s Simplygon mesh reduction in the Unreal Editor.</em></p><br />
<br />
  This integration enables artists and level designers to quickly simplify meshes, generate LODs, and immediately see the results in their maps. Simplygon saves developers hundreds to thousands of hours of manual art adjustment, and it is especially handy for converting high-end PC assets for deployment on mobile devices.<br />
<br />
<span style='font-size: 14px;'>  <strong class='bbc'>Material Functions</strong></span><br />
<br />
  <a href='http://udn.epicgames.com/Three/MaterialFunctions' class='bbc_url' title='External link' rel='nofollow external'>Material functions</a> allow snippets of material graphs to be saved separately and be shared between multiple materials.<br />
 <br />
<p class='bbc_center'><em class='bbc'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5086-0-15508000-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5086" title="materialfunctions.jpg - Size: 67.67K, Downloads: 883"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-31619500-1314237874_thumb.jpg" id='ipb-attach-img-5086-0-15508000-1330208485' style='width:228;height:200' class='attach' width="228" height="200" alt="Attached Image: materialfunctions.jpg" /></a><br />
<span style='font-size: 12px;'>New material functions can reduce material redundancy.</span></em></p><br />
<br />
   Many new material functions have been added to the engine's function library, which exposes functions in a new categorized window in the material editor.<br />
<br />
<span style='font-size: 14px;'><strong class='bbc'>  Map Lighting Templates</strong></span><br />
<br />
  Artists and level designers can take advantage of UDK’s brand new, fully customizable map lighting templates.<br />
  <br />
<p class='bbc_center'><em class='bbc'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5090-0-15563000-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5090" title="maptemplates.png - Size: 230.65K, Downloads: 509"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-36879000-1314237884_thumb.png" id='ipb-attach-img-5090-0-15563000-1330208485' style='width:250;height:176' class='attach' width="250" height="176" alt="Attached Image: maptemplates.png" /></a><br />
Customizable UDK templates for easy map lighting.</em></p><br />
<br />
  Simply drag the appropriate thumbnail from the Unreal Content Browser into a level to populate settings for day, night, dawn or sunset lighting effects.<br />
<br />
<span style='font-size: 14px;'>	<strong class='bbc'>Unreal Kismet Debugger</strong></span><br />
<br />
  Developers can work more efficiently than ever before with the popular Unreal Kismet visual scripting system, which makes it possible to rapidly prototype concepts and gameplay mechanics.<br />
<br />
  UDK now ships with the first ever <a href='http://udn.epicgames.com/Three/KismetVisualDebugger.html' class='bbc_url' title='External link' rel='nofollow external'>Kismet debugger</a>, so it is now possible to visualize Kismet node activation, set breakpoints that pause execution when nodes are activated, and step through sequences while running PIE.<br />
 <br />
<p class='bbc_center'><em class='bbc'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5084-0-15480300-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5084" title="kismetdebugger.jpg - Size: 47.96K, Downloads: 939"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-68764100-1314237873_thumb.jpg" id='ipb-attach-img-5084-0-15480300-1330208485' style='width:250;height:169' class='attach' width="250" height="169" alt="Attached Image: kismetdebugger.jpg" /></a><br />
Unreal Kismet debugger with breakpoints</em></p><br />
<br />
  With the Kismet debugger, developers can visualize the flow of a Kismet sequence while their game is running; debug issues where nodes are being activated in the wrong order, not at the right time, not at all or too much; and step through sequences one frame at a time and set breakpoints.<br />
<br />
<span style='font-size: 14px;'>  <strong class='bbc'>Major Performance Optimizations</strong>  </span><br />
<br />
  UDK benefits from major performance and memory optimizations that were built into Unreal Engine 3 for shipping “Gears of War 3.”<br />
 <br />
<p class='bbc_center'><em class='bbc'><span style='font-size: 10px;'><a class='resized_img' rel='lightbox[db541fb3116605f86108a9eeb095acd0]' id='ipb-attach-url-5091-0-15578400-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=5091" title="stat_unitgraph.png - Size: 359.65K, Downloads: 974"><img src="http://public.gamedev.net/uploads/monthly_08_2011/ccs-8549-0-44613800-1314237885_thumb.png" id='ipb-attach-img-5091-0-15578400-1330208485' style='width:250;height:143' class='attach' width="250" height="143" alt="Attached Image: stat_unitgraph.png" /></a><br />
<span style='font-size: 12px;'>Gameplay stats visualized in “Gears of War 3”</span></span></em></p><br />
<br />
	UDK provides easy in-game visualization of performance data, making problem areas easy to detect during play. Plus, the enhanced gameplay profiler displays color-coded data captured during profiling sessions, enabling developers to dig deeper into gameplay code to analyze time spent performing functions.<br />
<br />
  Multithreaded cooking is now supported, yielding approximately 4x faster cooks. Improvements have been made to rendering, CPU and GPU performance, memory usage, and overall quality and consistency.<br />
<br />
Anyone can check out the Unreal Engine tools for free at <a href='http://www.udk.com/download' class='bbc_url' title='External link' rel='nofollow external'>www.udk.com/download</a>.]]></description>
		<pubDate>Thu, 25 Aug 2011 00:48:59 +0000</pubDate>
		<guid isPermaLink="false">410a0338f4f2038cfa92723d64c52900</guid>
	</item>
	<item>
		<title>KJam - a new build tool for game development</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/kjam-a-new-build-tool-for-game-development-r2328</link>
		<description><![CDATA[<br />
<strong class='bbc'>Introduction</strong><br />
 <a href='http://www.oroboro.com/kjam' class='bbc_url' title='External link' rel='nofollow external'>KJam </a> is a build tool - like make. It is designed to support very large software projects, especially project which require building more than just code but data as well. It is also designed to be extremely fast. <br />
<br />
 I am a game developer. After my last game project I went looking for a build tool which was better than the tools I was using, Gnu Make and MSBuild (the build tool that comes with MSVC). The best tool that I could find was something called Jam, developed by the same people who develop Perforce. The great thing about Jam is that it is simple, powerful and extremely <a href='http://www.gamesfromwithin.com/articles/0509/000100.html' class='bbc_url' title='External link' rel='nofollow external'>fast </a>. <br />
<br />
 After working with Jam for some time, I started seeing things that I wished Jam could do. Specifically: <br />
<br />
 <ul class='bbc'><li><strong class='bbc'>Batched Building: </strong> MSVC can compiled multiple source files into multiple object files in a single call to the compiler, much faster than it if you compile the files one at a time. But few build tools support that, and those that do are very slow.   </li><li><strong class='bbc'>Network Builds: </strong> Many game development projects require that data be compiled in addition to code. For example pre-computation of visibilty data, environmant maps, shadow maps and the like. I needed a build tool which could distribute these expensive build tasks over a distributed network of build machines. ( Like Incredibuild does with MSVC source files - but for data ).</li></ul> Luckily the sources for Jam are available, and I started adding these features. But the more work I did to Jam the more I realized that things could be done so much better. I didn't intend to, but I ended up working on a completely new version of Jam for more than a year. I call it KJam. <br />
<br />
 KJam has several major benefits over Jam and other build tools: <br />
<br />
 <ul class='bbc'><li><strong class='bbc'>Fast </strong>: KJam is the fastest build tool I have <a href='http://www.oroboro.com/kjam/docserv.php/page/doc_perf' class='bbc_url' title='External link' rel='nofollow external'>tested </a>. KJam can scan a large codebase and build a dependency graph more than 20 times faster than MSBuild and Gnu Make. Through the use of parallel execution, and batched building it will build source files under MSVC significantly faster than other tools. In some cases KJam can reduce full build times by more than 3x. These accelerated build times are possible on multi-processor workstations   </li><li><strong class='bbc'>Easy: </strong> KJam's build language is easy to use, and designed to support projects which target multiple build environments. Build files are split into <em class='bbc'>rules </em> and <em class='bbc'>actions </em>. Rules describe how files are related to each other, what dependencies exist and where the files can be found. The rules can be completely platform independent. The actions describe exactly what build steps need to performed on a given target platform to build. Targeting a new platform normally means writing a new set of actions. The rules remain unchanged. This is a great idea take directly from Jam.   </li><li><strong class='bbc'>Robust: </strong> KJam is designed to support large projects. For extremely large projects, determining what targets need to be rebuilt can take minutes. Every compile becomes a chore. KJam can reduce this scanning time by a factor of 20 or more.   </li><li><strong class='bbc'>Distributed: </strong> KJam has a distributed build mode. KJam servers can be set up to run in the background on workstations all over the office, spreading the build load to multiple workstations, resulting in dramatic reductions in build times even above what is already possible in non-network mode.   </li><li><strong class='bbc'>Portable: </strong> By default KJam runs all build commands in its own internal sh-like shell. This means that developers have a single shell environment no matter what platform they are on. This is mostly to the benefit of Windows programmer who would otherwise be stuck using Window's extremely limited cmd.exe shell. With the built-in shell many build actions are completely portable across platforms.</li></ul> KJam is currently still in development, but it is stable and useful enough that it is already used in production by several major game development studios for their next generation projects. A version of KJam is available for <a href='http://www.oroboro.com/kjam/docserv.php/page/download' class='bbc_url' title='External link' rel='nofollow external'>download </a> free for use by non-commercial projects. Commercial developers are encouraged to <a href='mailto:kjam@oroboro.com' title='E-mail Link' class='bbc_email'>contact us </a> and join our beta program. Eventually, when KJam is perfect we plan to sell a commercial version. For right now we just want to make it easy for people to start using KJam and to give us feedback on how well it worked for them. Comments from our users currently drive most of the development of KJam. <br />
<br />
  <br />
<strong class='bbc'>Getting Started with KJam </strong><br />
 So how do you get started using KJam? First download the binaries. They are currently available for Windows and Linux. <br />
<br />
 KJam comes configured with a standard set of build rules for c and c++ projects. For many simple projects it is possible to get started using KJam in just a few minutes by writing some very simple, yet surprisingly powerful Jamfiles. For larger projects, or to support custom tools you will need to write your own custom build rules. For now, the fastest way to try KJam is to use the default build rules. <br />
<br />
 Suppose you have a directory called src full of .cpp source files that you want to build into an application called myprog. You would create a file called jamfile with the following contents: <br />
<br />
  StaticExecutable myprog : src ;   To build myprog, run KJam in the same directory as the jamfile ( by typing kjam ). KJam will create an output directory, bin for all the generated files. It will search the directory src for source files. It will process any .l and .y files that it finds though flex and bison. It will scan all source files for #include statements and generate dependencies. It will compile all the .c and .cpp files it found or created. And finally it will link all the resulting object files into a binary. <br />
<br />
 Even though KJam does a full dependency analysis of your sources before every run, it will start building even very large projects almost immediately. KJam is extremely efficient. <br />
<br />
 This same jamfile should work without modification under Windows or Linux. The generated files will be stored in a directory under bin which specifies the platform and the debugging level. <br />
<br />
 If your machine has multiple processors, KJam will figure out which build steps can be safely done simultaneously and take advantage of them. If your compiler supports batched building (like MSVC does ) KJam will build sources in batches. <br />
<br />
 KJam will detect the width of your shell, and format all the output neatly for easy readbility. And even though many build steps will happen simultaneously, KJam will a not allow output from different steps to be interspersed. <br />
<br />
 <br />
<strong class='bbc'>Invoking Rules </strong><br />
 Suppose you don't want to build every source file in a directory, but would rather name your source files specifically. You can write your jamfile like this: <br />
<br />
  StaticExecutable myprog : src1.cpp src2.cpp src3.cpp ;   To build a library you use the StaticLibrary rule: <br />
<br />
  StaticLibrary mylib : src1.cpp src2.cpp src3.cpp ;    To build a .dll or a shared library use the SharedLibrary rule: <br />
<br />
  SharedLibrary mylib : src1.cpp src2.cpp src3.cpp ;    Under Windows this will create a .dll and its associated export library. Under Linux this will create a .so file. All the details of how to do that on each platform are dealt with for you - portably. The target names do not have to deal with non-portable file extensions like .dll and .so. <br />
<br />
 To build a program that links with a library, just list the libraries at the end of the rule: <br />
<br />
  StaticLibrary lib1 : lib1/src ; StaticLibrary lib2 : lib2/src ; StaticExecutable myprog : myprog/src : lib1.lib lib2.lib ;   The .lib extension helps KJam to know that you want to link with a static library instead of a dynamic library. But the extensions are portable between Windows and Linux. Under Linux, KJam would link with lib1.a and lib2.a. And if you had passed in lib1.a then under Windows KJam would have automatically converted it to lib1.lib. <br />
<br />
 You can also easily link with a shared library: <br />
<br />
  SharedLibrary lib1 : lib1/src ;  StaticLibrary lib2 : lib2/src ;  StaticExecutable myprog : myprog/src : lib1.dll lib2.lib ;   Under Windows, KJam will figure out that it needs to look for an export library. Under Linux, it will look for a .so shared library. The user does not have to worry about these non-portable details. KJam will even figure out all the dependencies between these different targets automatically. <br />
<br />
 By default when you run KJam without any arguments it will try to build the target all, which will build all the targets that have been declared using the above rules. So in the case of the previous jamfile, it would build lib1, lib2 and myprog. <br />
<br />
 To build only a subset of the declared targets you can declare a Group target: <br />
<br />
  SharedLibrary lib1 : lib1/src ; StaticLibrary lib2 : lib2/src ; StaticExecutable myprog : myprog/src : lib1.dll lib2.lib ; Group libs : lib1.lib lib2.lib ;   Now when you ask it to build libs, it will only build lib1 and lib2. To exclude a target from the defauilt all target, declare your own all group listing the targets you want. This will override the automatically created all target: <br />
<br />
  SharedLibrary lib1 : lib1/src ; StaticLibrary lib2 : lib2/src ; StaticLibrary special : lib2/src ; StaticExecutable myprog : myprog/src : lib1.dll lib2.lib ; Group all : lib1.lib lib2.lib myprog.exe ;   Now when you run KJam with no arguments, it will not build the library special. To get that you would have to ask for it specifically by running kjam special. <br />
<br />
 These simple jamfiles automatically create clean targets. So if you want to clear out all the generated files just run kjam clean.<br />
<br />
 <br />
<strong class='bbc'>Setting Variables </strong><br />
 The operation of the built-in rules can be modified by setting variables. <br />
<br />
 By default KJam will search for header files wherever it finds source files. If you would like it to use headers found in other directories, say the headers for an external library, set the INCLUDE_DIRS variable: <br />
<br />
  INCLUDE_DIRS = &#46;&#46;/otherlib/src ; StaticExecutable myprog : src ;   By default KJam will look for libraries to link with in the default output directory, and in the default system library directories. To add more places to look for libraries to link with, use the LIB_DIRS variable: <br />
<br />
  INCLUDE_DIRS = &#46;&#46;/otherlib/src ;  LIB_DIRS = &#46;&#46;/otherlib ;  StaticExecutable myprog : src : otherlib.lib ;   KJam will automatically chose a reasonable set of build flags when running your c compiler. To add additional build flags use the CCOPTS variable. <br />
<br />
 To add extra link options use the LINKOPTS variable. The new options will be added to every compile or link: <br />
<br />
  CCOPTS = /DSPECIAL ;  LINKOPTS = -lspecial ; StaticExecutable myprog : src ;   To change the output directory set BIN_DIR. By default BIN_DIR is set to bin/$(PLATFORM)/$(CURFLAV). You can set this to anything you want, though it is highly recommended that BIN_DIR always include $(CURFLAV) or $(BUILD_CODE), to avoid problems with mixing generated files built with different debugging levels. So for example if you want to have all your generated files go to a special directory shared by all projects, instead of a local one, and you don't care about multiple platforms, you might set BIN_DIR this way: <br />
<br />
  BIN_DIR = &#46;&#46;/shared_bin/$(CURFLAV) ;   These variables can also be set on a per target basis using the on keyword. For example to add special link options to just lib1: <br />
<br />
  LINKOPTS on lib1.a = -lspecial ;  StaticLibrary lib1 : lib1/src ;  StaticLibrary lib2 : lib2/src ;  StaticLibrary lib3 : lib3/src ;   To build targets with special compilation options, you can use the StaticObject rule. For example in the following case only special.cpp is built with the extra flags: <br />
<br />
  StaticObject special : special.cpp : /DSPECIAL ; StaticExecutable myprog : special.obj src1.cpp src2.cpp src3.cpp ;   Notice that when you need to, you can pass compiled object files as sources. <br />
<br />
 The built-in Jambase supports building targets at different optimization levels. You can do this by setting the CURFLAV variable. Set this variable in the environment. On Linux remember to <em class='bbc'>export</em> it. There are 4 levels, release, optimized, debug and extra_debug. At each setting the output files will go to their own directory, to avoid mixing output files built with different compiler flags. <br />
<br />
 KJam can also build projects with platform specific source files. Suppose you have a project with one or more source files which are different on Windows and Linux. Simply create linux and win32 subdirectories in the directory where source files would normally be found, and put the platform specific source files in each directory. KJam will build the appropriate sources for the platform. <br />
<br />
 <br />
<strong class='bbc'>Managing Sub-Projects </strong><br />
 Jamfiles can call other Jamfiles that manage individual subprojects. Suppose you have 5 directories, where each directory has its own jamfile and can build a separate library or executable. There may be dependencies between some of these sub-projects. This is easy to do: <br />
<br />
  SubProject lib1 ;  SubProject lib2 ;  SubProject lib3 ;  SubProject app1 : lib1 lib2 ; SubProject app2 : lib1 lib3 ;   With the jamfile above you can now build all the libraries and applications by running KJam in the parent directory. You can build any individual sub-project and the projects it depends on by running KJam with the name of the sub-project as the target. KJam will build the sub-projects in the right order. You can also switch to any individual sub-project directory to build and test just that sub-project. <br />
<br />
 A clean target is also automatically created. Building clean will clean all the sub-projects. <br />
<br />
 When building a sub-project KJam will invoke a copy of itself in the subproject's directory and will build the default all target. To have KJam build other targets as well, list those as the third argument to the SubProject rule: <br />
<br />
  SubProject app1 : lib1 lib2 : all verify install ;   It is also possible to make multiple SubProject targets each of which builds a particular sub-project target: <br />
<br />
  SubProject app1 : lib1 lib2 ; 		// build the 'all' target  SubProject app1 : lib1 lib2 : verify ; 	// build the 'verify' target  SubProject app1 : lib1 lib2 : install ; // build the 'install' target    Now you can invoke each of those targets in the given subproject from the main build file. Here is a jamfile which builds all your sub-projects, and has an install target: <br />
<br />
  SubProject lib1 ;  SubProject lib2 ;  SubProject lib3 ;  SubProject app1 : lib1 lib2 ;  SubProject app2 : lib1 lib3 ;  SubProject app1 : app1 : install ;  SubProject app2 : app1 : install ;  Group all : lib1 lib2 lib3 app1 app2 ;  Group install : app1 app2 ;   Note that you override the automatically created all target to exclude the install sub-project targets. Also notice that the install targets depend on their respective applications being up-to-date. <br />
<br />
 Given the jamfile above, here are some commands you can run and what they would do: <br />
<br />
  kjam 			# re-build all the libraries and applications  kjam lib2 		# re-build just lib2  kjam app2 		# re-build app2 and its dependents lib1 and lib3  kjam clean 		# clean all the sub-projects  kjam install 		# re-build all the applications, and install them all  kjam "app1" 		# re-build app1, lib1 and lib2, and then install just app1   Try <a href="http://www.oroboro.com/kjam">KJam and let me know what you think. It will really help us to refine it. <br />
<br />
]]></description>
		<pubDate>Thu, 05 Oct 2006 12:10:49 +0000</pubDate>
		<guid isPermaLink="false">0b2978ae0ca8efbfbf5af006bd7b4298</guid>
	</item>
	<item>
		<title>Introduction to GameMonkey Script Part 1</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/introduction-to-gamemonkey-script-part-1-r2282</link>
		<description><![CDATA[Get the source code <a href='http://downloads.gamedev.net/features/programming/gmscript1/part_1_src.zip' class='bbc_url' title='External link' rel='nofollow external'><strong class='bbc'>here</strong></a><br />
<br />
  <br />
<strong class='bbc'>Introduction</strong><br />
 This article will introduce you to the GameMonkey Script (abbreviated to <em class='bbc'>GM Scrip</em>t or simply <em class='bbc'>GM</em>) language and API and how it can be used in your own games. It begins with a short introduction to the language and how it compares to Lua, the most similar language to GM Script and also a popular choice in game development. The article will then show you the basic features of the script language itself and, in the second part, teach you how to bind the virtual machine with your game applications. This article does not intend to be a comprehensive tutorial on using GameMonkey Script, nor will it cover the advanced topics and techniques that can be employed when scripting, however it will be enough to <em class='bbc'>whet your appetite</em> for GM Script and provide you with enough information to explore the language on your own. You can follow along with the examples in the code by experimenting with the <em class='bbc'>gme.exe</em> program that ships with standard GameMonkey distributions and running the example scripts that are supplied with this article.<br />
<br />
  <br />
<strong class='bbc'>Prerequisites</strong><br />
 In order to get the most of this article and indeed GameMonkey script, it is assumed that:<br />
<br />
 <ul class='bbcol decimal'><li>You have a working <strong class='bbc'>C++</strong> compiler environment (an IDE or command-line, it doesn't matter) </li><li>You are able to program to an average level in C++ </li><li>You are able to understand languages with a similar syntax to C/C++ </li><li>You have an interest or requirement in embedding scripting languages</li></ul>  <br />
<strong class='bbc'>What Is GameMonkey Script?</strong><br />
 Scripting in games has long been an important technique for developers to employ. Scripting allows you to separate your game logic from your engine code and gives you the ability to tweak your content without time-consuming rebuilds of the entire engine. Some games, for example <em class='bbc'>Unreal</em>, have vastly complicated scripting environments in place which allow you to create graphical effects and perform almost every action imaginable in your game. In the past it was popular for game developers to 'roll their own' scripting language that was tied directly into their game systems, however language parsing and virtual machine design is a complex subject, meaning that many developers are now choosing to use a third party scripting language.<br />
<br />
 Influenced by the popular embedded scripting language Lua, Matthew Riek and Greg Douglas set about creating their very own language for a game project whilst employment at Auran Software; and thus GameMonkey Script was born. Created specifically for game scripting, GM Script is written with speed and simplicity in mind. The original version of GM Script has been used in several commercial ventures, from PC games to console games, and is growing in popularity amongst hobby game developers. GameMonkey Script can be downloaded from <a href='http://www.somedude.net/gamemonkey' class='bbc_url' title='External link' rel='nofollow external'>http://www.somedude.net/gamemonkey. At the time of writing, the most recent version is 1.24a.<br />
<br />
 </a> <br />
<strong class='bbc'>Comparison to Lua</strong><br />
 As GameMonkey script was originally inspired by Lua, it is useful to highlight the differences between the two environments.<br />
<br />
    GameMonkey Script Lua   Script Syntax C-like C/BASIC hybrid   Source Language C++ C   Platform Cross-platform; has been compiled and used on PC, PS2, Xbox and GameCube Cross-platform; has been used on many platforms   Numbers int, float double   Array Start Index 0 1   Default Scope local global   Multi-tasking Coroutines (called threads) Coroutines   Garbage Collection Incremental Mark & Sweep Mark & Sweep (made incremental in 5.1beta)   Parser Flex/Bison Custom Parser   Data Access method Global table / function call params Stack access   Statement terminator Semi-colon Optional semi-colon   Ease of host binding:<br />
without 3rd party tool Moderate Difficult   Ease of host binding:<br />
with 3rd party tool Simple/Moderate Simple   Community size Small Large   Syntax suited to: C/C++ programmers Beginners and non-programmers   Availability of documentation / example code Low High   Latest version 1.24a 5.1 (beta)   License MIT MIT   <br />
Lua has been used successfully in many commercial and amateur game projects, however it can be difficult to use without a third party binding library as its stack-access method can be confusing for people new to scripting. GameMonkey Script aims to address the complexities of Lua whilst still maintaining its inherent power through flexibility.<br />
<br />
  <br />
<strong class='bbc'>Introduction to the Language</strong><br />
 In the following section I will introduce you to the GameMonkey Script language. You will learn how to manipulate variables, how to create and call functions and how to use the powerful GM Script <em class='bbc'>table</em> type. This section is intended to be a primer to the language and it is assumed that you have some programming knowledge of C, C++, Java or other similar syntax styles. You can follow the simple examples I present here and experiment yourself using the <em class='bbc'>gme</em> executable that comes with standard GameMonkey Script distributions. <em class='bbc'>gme</em> is a stand-alone interpreter for GameMonkey Script which provides a basic GameMonkey Script environment for you to load your scripts into and test them. Because of this, <em class='bbc'>gme</em> will be a useful tool for your first steps into learning the GMScript language and syntax.<br />
<br />
 Using the <em class='bbc'>gme</em> interpreter is simple; from the command line you type 'gme <em class='bbc'>path_to_script_file</em>' (ensuring that gme is in your current directory). The script will then load and be executed, showing you the results in the console wind&#111;w.<br />
<br />
  <br />
<strong class='bbc'>Syntax Overview</strong><br />
 This following section will give you an overview of the syntax used by the GameMonkey Script language. You will notice from the provided examples that the basic syntax of GM Script is very much like that of C; because of this GMScript may not be as instantly accessible as Lua or Python which aim to be simple for non-programmers to pick up.<br />
<br />
 GM Script features the common elements of most programming languages:<br />
<br />
 <ul class='bbcol decimal'><li>Variables </li><li>Comments </li><li>Exp<b></b>ressi&#111;ns </li><li>Selection Statements (if / else) </li><li>Loops (for, while, foreach) </li><li>Functions</li></ul> GameMonkey Script also features a built-in cooperative threading and state system, allowing you to create multiple threads within the virtual machine to run several parallel tasks at once. However, I will not venture into that territory in this introductory article.<br />
<br />
  <br />
<strong class='bbc'>GameMonkey Scripts: Defined</strong><br />
 A <em class='bbc'>script</em> in GameMonkey is usually a plain-text ASCII file that contains a collection of functions, variable declarations and exp<b></b>ressi&#111;ns. Scripts are usually loaded in from disk and compiled into a form that the GM environment can work with, namely <em class='bbc'>bytecode</em>. There is no standard form to a GameMonkey Script; you do not have to import modules like in Python, nor do you have to adhere to any indentation formatting (again, like Python). GameMonkey script does not have a native version of the <em class='bbc'>include</em> directive, so usually a script is self-contained (although you can load and execute multiple scripts on the same machine). The only requirement in GameMonkey Script is that function variables are declared before you try and call them; the ordering of such statements is important because GMScript code is compiled in a single-pass and also it does not have a pre-processor like in C/C++.<br />
<br />
  <br />
<strong class='bbc'>GameMonkey Variables</strong><br />
 Unlike C/C++, GM Script is a <em class='bbc'>dynamically typed</em> language; variables can assume any type at any time during the execution of a script. Also, variables do not need to be declared before use; one can simply make the variable assignment and the variable will be created and be of the type relevant to the data it holds. The basic types of GameMonkey Script are integers, floats, strings, functions, <em class='bbc'>tables</em> and <em class='bbc'>null</em>. Here is an example of some simple variables in use:<br />
<br />
  myNull = null; // has type null, which is a distinct type myNum = 50; 	// has type of int myString = "Hello!";  // has type of string myFloat = 3.14; // has type of float print( myNum ); print( myString ); print( myFloat );  As you will see, a variable declaration is as simple as assigning a value; variables that haven't been assigned will have the value and type of <em class='bbc'>null</em>. You will notice that every line is terminated by a semi-colon. This denotes the end of a statement and unlike Lua, is non-optional in GameMonkey Script. To C/C++ developers this will come naturally and so shouldn't cause too many problems.<br />
<br />
 <em class='bbc'>null</em> is a distinct and important type in GMScript; a variable of null type is said to have no value. When referencing variables for the first time they automatically have the type null and will remain that way until an assignment is made. You should be careful when using nulls in comparisons and exp<b></b>ressi&#111;ns; for example, concatenating a string with a null variable will result in the text 'null' being appended to the string. However in integer exp<b></b>ressi&#111;ns, a null variable is interpreted as being <em class='bbc'>zero</em>. This behaviour is different to some languages, such a T-SQL where operations involving null variables will themselves yield a null result. It should also be noted that assigning an existing variable be of type <em class='bbc'>null</em> will allow it to be garbage collected by the GMScript machine; this consideration is especially important once you begin to create and bind your own types from C++ to the machine, but this shall be covered in the next article.<br />
<br />
  <br />
<strong class='bbc'>Comments</strong><br />
 Comments in GM Script are exactly like those in C++; you can choose between C++ style line-comments or C-style block comments:<br />
<br />
  x = 5;                // This is a line comment /* This is a block comment */  Like C++, block comments cannot be nested in GMScript. Because of this you can run into trouble if you are using the block comment features of the language to comment out sections of code. It is worth considering this when writing code as there is currently no GMScript-aware IDE that is intelligent enough detect this.<br />
<br />
  <br />
<strong class='bbc'>Exp<b></b>ressi&#111;n and Conditional Syntax</strong><br />
 GameMonkey Script can evaluate common exp<b></b>ressi&#111;ns using the standard C-style exp<b></b>ressi&#111;n syntax and as such, anyone familiar with C or C++ will feel comfortable using GameMonkey Script exp<b></b>ressi&#111;ns.<br />
<br />
  x = 5;                        // Assign a value to x print( x ); y = (x * 10) + 56;      // Assign a value to y print( y ); if (x == 10)       	// Comparison (equality) {     	print( "x is equal to 10" ); } if (x != 10)       	// Comparison (inequality) {     	print( "x is not equal to 10" ); } if (x < 10)             	// Comparison (less than) {     	print( "x is less than 10" ); } if (x > 10)             	// Comparison (greater than) {     	print( "x is greater than 10" ); }  Example code: exp<b></b>ressi&#111;ns_1.gm<br />
<br />
 GMScript also allows bitwise operations such as or ('|'), xor ('^'), and ('&') and bitwise complement ('~'). Logical operators include or ('||'), and ('&&') and logical complement ('!'). GMScript also allows the use of the keywords <em class='bbc'>and</em> and <em class='bbc'>or</em> to be used in place of && and || respectively.<br />
<br />
 One can employ conditional logic in GameMonkey script by using the <em class='bbc'>if</em> statement.<br />
<br />
  if (  ) {     	// Do something if true } else if (  ) {     	// Do if 2nd condition passes } else {     	// Do if all are false }  Unlike C/C++, GM Script does not contain a <em class='bbc'>switch</em> statement so one must emulate the functionality by using blocks of if / else if tests. Also unlike C/C++, the body of conditional statements such as <em class='bbc'>if</em> must be specified as block statements surrounded by curly braces, to do otherwise is an illegal syntax.<br />
<br />
  <br />
<strong class='bbc'>Loops and iterations</strong><br />
 GameMonkey script has several methods of executing a loop. The first is the familiar <em class='bbc'>for</em> statement:<br />
<br />
  for (; ; ) {     	// repeated statement }  A simple example to iterate a variable and print the number it contains would be:<br />
<br />
  for (it = 0; it <= 10; it = it + 1) {     	print( "it = ", it ); }  Example code: loops_1.gm<br />
<br />
 The output will be the numbers from 0 to 10 printed on separate lines in the output console.<br />
<br />
 Like C/C++, <em class='bbc'>for</em> loops may contain empty statements (effectively simulating a while loop). However like the <em class='bbc'>if</em> statement, the body of the for loop must be surrounded by curly braces. For example:<br />
<br />
  for (; it != 10;) {     	print( "it = ", it );     	it = it + 1; }  The <em class='bbc'>while</em> statement is used in situations where the conditions around the loop aren't as certain; the most common use of the while loop is to loop until a particular flag is set. Again, like the <em class='bbc'>for</em> statement the body of the while statement needs to be enclosed in curly braces.<br />
<br />
  while (  ) {     	// repeated statement }  For example, to repeat until the user has pressed the 'quit' button:-<br />
<br />
  while ( !quitButtonPressed ) {     	// do something in the game     	quitButtonPressed = host_check_for_quit();           	}  Note that the <em class='bbc'>host_check_for_quit</em> function is a hypothetical application-bound function. Similarly, an approximation of the <em class='bbc'>for</em> loop you saw previously would be:<br />
<br />
  it = 0; while (it <= 10) {     	print( "it = ", it );     	it = it + 1; }  Example code: loops_2.gm<br />
<br />
 The <em class='bbc'>foreach</em> loop allows you to iterate over the contents and keys of a table. I will cover this in more detail in the table section of this article.<br />
<br />
 That was a brief overview of the various statements, exp<b></b>ressi&#111;ns and symbols used in the GM Script language; however it is far from exhaustive. For a full list of exp<b></b>ressi&#111;ns and iterators along with their syntax you are advised to consult the <em class='bbc'>GameMonkeyScriptReference</em> which comes with the official GameMonkey Script releases. It is worth noting that the GMScript reference does contain a few errors; notably it claims that ~= is a valid assignment operation, which is not the case as it fails both to parse and make sense!<br />
<br />
  <br />
<strong class='bbc'>Scripted Functions</strong><br />
 The GameMonkey Script machine has two forms of functions. The first is the scripted function, a function that is created and coded in script. A scripted function is specified in the same way as a normal variable:<br />
<br />
  myMultiply = function( x, y ) { return x * y; };  As functions are created and specified as variables, it is extremely important to remember the terminating semi-colon at the end of the function declaration. Calling a function is as you'd expect from a C-style syntax:<br />
<br />
  a = myMultiply( 100, 2 ); print( a );  Example code: functions_1.gm<br />
<br />
 The second type of function is that of the host-declared function. An example of a native function is the <em class='bbc'>print</em> command which is contained within gmMachineLib and bound to every gmMachine you create. Only C-style functions or static class methods can be bound to the GameMonkey machine, but there are workarounds to this. I will cover the binding of native functions in the second part of this article.<br />
<br />
  <br />
<strong class='bbc'>The Table Type</strong><br />
 The table is an important and powerful structure within GameMonkey script. At its most basic, it allows you to specify arrays of data; at its most complex, you can begin to create organised structures of data and functions for use in your games.<br />
<br />
  <br />
<strong class='bbc'>Tables as Arrays</strong><br />
 A table can be used as a simple array which contains any type of data.<br />
<br />
 Initialisation Example:<br />
<br />
  myArray = table( 1, 2, 3.14, 4, 5, "dog", "cat", 100 );  Much like C/C++ arrays, you need to use indices to access the data within the table. All indices are zero-based when a table is initialised in this manner. Lua programmers should note this difference as in Lua, initialised tables begin at an index of 1.<br />
<br />
 Accessing the data:<br />
<br />
  myArray[0] = 50; print( myArray[1] ); myArray[100] = "dog_100"; 	// new item added print( myArray[100] );  Example code: tables_1.gm<br />
<br />
  <br />
<strong class='bbc'>Tables as Associative Arrays</strong><br />
 A table can also be used as an associative array, much like the <em class='bbc'>map</em> structure in the C++ standard library. An associative array can be indexed using a non-numeric key, allowing for <em class='bbc'>named</em> data lookups. Again, the data items in an associative array can be of any type.<br />
<br />
 Initialisation:<br />
<br />
  myData = table( Name = "Test", Weight = 60 );  Accessing the data is as simple as the first example:<br />
<br />
  print( myData[ "Name" ] ); print( myData[ "Weight" ] ); myData["Name"] = "Albert"; myData["Test"] = "Some Text Here"; print( myData[ "Name" ] ); print( myData[ "Test" ] );  Example code: tables_2.gm<br />
<br />
 You will have noticed that we can assign new keys and indexes at any time as the tables have no defined bounds.<br />
<br />
  <br />
<strong class='bbc'>Tables as Mixed Arrays</strong><br />
 You can use the table as a <em class='bbc'>mixed array</em>, an array that contains both indexed data and keyed data (as in an associative array). This makes the table structure very flexible:<br />
<br />
  myTest = table( 1, 4, Test = "Text!", 7, 8 ); print( myTest[0] ); print( myTest[2] ); print( myTest["Test"] );  Example code: tables_3.gm<br />
<br />
 In the example above, the second print statement prints the number 7 and not as you may expect, the word 'Text!'. The reason for this is because GM Script keeps indexes and keys separate from each other within the table.<br />
<br />
 Because GMScript tables store their indexes as gmVariables, it is theoretically possible to index a table on <em class='bbc'>any</em> type other than null (as indexing on null will return null). However, indexing tables on anything other than numbers or strings can be counter-intuitive, so it is best practise to avoid it.<br />
<br />
  <br />
<strong class='bbc'>Iterating Table Data - 'foreach'</strong><br />
 The <em class='bbc'>foreach</em> statement allows you to iterate over the contents of a table in a loop. The most basic form of the foreach statement is to examine just the values within the table:<br />
<br />
  foreach (  in  )  {  // statements  } An example of this follows:<br />
<br />
 fruits = table ( "apple", "pear", "orange" ); foreach ( frt in fruits ) {     	print(frt); } Example code: tables_4.gm<br />
<br />
The code above will print the contents of the table to the console in no particular order. However, you may have noticed that the table key is often as important as the value it references and may wish to capture that data too:<br />
<br />
 foreach (  and  in        {  // statements  } An example:<br />
<br />
 fruits = table ( "apple", "pear", Juicy = "orange" ); foreach ( k and f in fruits ) {     	print( "The value at key '", k, "' is '", f, "'" ); } Example code: tables_5.gm<br />
<br />
Will print something similar to:-<br />
<br />
     	The value at key '0' is 'apple'     	The value at key 'Juicy' is 'orange'     	The value at key '1' is 'pear' <br />
<strong class='bbc'>Simulation of 'structs' and simple classes with Tables</strong><br />
The final use of the table structure is to simulate C/C++ structs and classes. If you recall what I mentioned before, the GM Script table object can store <em class='bbc'>any</em> type of data, including functions. Because of this, you can assign a scripted function to an index or key within a table. You should be aware that when declaring a function as a table member you <em class='bbc'>should not</em> put the semi-colon line terminator as you do when declaring a function on its own.<br />
<br />
 myStruct = table(     	SayHello = function() { print( "Hello, world!" ); }    ); myStruct.SayHello();    // Call table-bound function Example code: tables_6.gm<br />
<br />
As you see in the example, you can access keyed table data using the period (dot) operator. This allows us to treat the table as a simple class structure, accessing the named elements in a familiar fashion.<br />
<br />
 myAlien = table(     	Name = "Alien",     	AttackPower = 20,     	Strength = 50,     	OnAttack = function( entity )             	{                     	entity.Damage( this.AttackPower );             	}     	); Example code: tables_7.gm<br />
<br />
The slightly more complex example shows how simply a generic alien scripted object can be created using the basic GameMonkey Script types and how it is centred primarily around the use of the table object.<br />
<br />
Unlike C++ classes, it is important to note that the GM Script table object has no constructor/destructor, cannot be inherited from and does not allow for custom operator overriding. However, you can achieve such behaviour through creating your own bound types (covered in the next instalment of this article). It should also be noted that GM tables have no concept of public, private and protected scoping as C++ presents for structs and classes. All table members are declared as being in the public scope and so can be accessed from anywhere. I will continue the scoping discussion in the next section.<br />
<br />
<br />
<strong class='bbc'>Scoping</strong><br />
GameMonkey script has a range of scopes for variables (and hence functions). If you wish your functions or methods to be accessible from outside of the script (for example, to be read directly by the host application) you must declare them as being in the <em class='bbc'>global</em> scope. The global scope is accessible everywhere in the script; even within other functions. Without this declaration, the objects are implicitly within <em class='bbc'>local</em> scope, which means they're only accessible to within the current scope or lower.<br />
<br />
 // Create a variable in the global scope global myvar = 100; // parameter 'a_param' is in function local scope myfunc = function( a_param ) {     	// variable myvar is in local scope     	myvar = a_param;     	print( myvar ); }; print( myvar ); myfunc( 50 ); print( myvar ); Example code: scoping_1.gm<br />
<br />
Hold up a minute; you will notice that I've created 2 variables called myvar, one in the function and the other in global scope. If you run this script you will notice that the value of the global <em class='bbc'>myvar</em> is unchanged, even though you set the value of <em class='bbc'>myvar</em> in the function. The reason for this is simple; they exist in different scopes! GameMonkey allows you to set global variables from within functions by explicitly specifying the scope of the variable. In this case, I add the <em class='bbc'>global</em> keyword to the <em class='bbc'>myvar</em> declaration in myfunc.<br />
<br />
 // Create a variable in the global scope global myvar = 100; // parameter 'a_param' is in function local scope myfunc = function( a_param ) {     	// Access variable myvar in global scope     	global myvar = a_param;     	print( myvar ); }; print( myvar ); myfunc( 50 ); print( myvar ); Example code: scoping_2.gm<br />
<br />
Things can begin to become tricky, however, when using tables and the <em class='bbc'>this</em> operator. Whenever a variable is part of a table or user-defined object, it exists in the <em class='bbc'>member</em> scope of the parent object, or <em class='bbc'>this</em>. This concept will be familiar to you if you've done any work in C++, so I will not dwell on it. Let's have a look at the member scoping in use:<br />
<br />
 global mytable = table(     	myMember = 50,     	setMember = function( a_value )     	{             	myMember = a_value;     	} ); print( mytable.myMember ); mytable.setMember( 100 ); print( mytable.myMember ); Example code: scoping_3.gm<br />
<br />
The script above behaves similarly to the local scoping example; the <em class='bbc'>myMember</em> method isn't altered. However, when you include the <em class='bbc'>member</em> scoping keyword you will see a different result.<br />
<br />
 global mytable = table(     	myMember = 50,     	setMember = function( a_value )     	{             	member myMember = a_value;     	} ); print( mytable.myMember ); mytable.setMember( 100 ); print( mytable.myMember ); Example code: scoping_4.gm<br />
<br />
The <em class='bbc'>this</em> scoping is fairly complicated, but at the same time is very powerful. Using <em class='bbc'>this</em> scoping you can create generic delegates that can access the data of the object that is passed as <em class='bbc'>this</em>. Confused? Take a look at the following example:<br />
<br />
 myTable = table(     	myMember = 50 ); setMember = function( a_param ) {     	this.myMember = a_param; }; print( myTable.myMember ); myTable:setMember( 100 ); print( myTable.myMember ); Example code: scoping_5.gm<br />
<br />
In this example the function <em class='bbc'>setMember</em> is completely external to the <em class='bbc'>myTable</em> object but is able to access its data and methods. The reason it is able to do this is though use of passing the <em class='bbc'>myTable</em> object as <em class='bbc'>this</em> when calling the setMember function. The body of setMember explicitly states that it will alter the data belonging to <em class='bbc'>this</em> without actually belonging to <em class='bbc'>this</em> at compile time. This allows you to create very powerful scripted functions which can exist in the global scope and be called from objects as if they were a member of that object itself. An abbreviation for typing <em class='bbc'>this</em> is to simply type a single period '.'. For a more complex example of <em class='bbc'>this</em> in action, please refer to scoping_6.gm which is included with this article.<br />
<br />
It should be noted that <em class='bbc'>this</em> scoping is different to <em class='bbc'>member</em> scoping, although you could mistake the two if you're accustomed to C++. <em class='bbc'>This</em> scoping refers to the scope of the object passed as <em class='bbc'>this</em>. <em class='bbc'>Member</em> scoping allows you to specify that a variable is a member of <em class='bbc'>this</em>, making it of use in situations where a global or local member may conflict with your attempts to access a member variable of an object.<br />
<br />
<br />
<strong class='bbc'>Further Exploration</strong><br />
By now you should have visited the most-often used aspects of the GameMonkey Scripting language and have hopefully experimented by running the example code through <em class='bbc'>gme</em> and looking at the results. There is a fairly large amount of GameMonkey Script usage to cover; the most notable of the remaining topics are those of <em class='bbc'>script threads</em> and the variable thread states that can be used in GameMonkey Script. There are also the vast machine library functions that allow you to control the virtual machine from within the script itself, but in order to keep this introduction simple I have left this up to you, the reader, to explore on your own. If there is enough interest I will happily cover the unexplored sections in a future article.<br />
<br />
The next part of this two-part introduction to GameMonkey Script will focus solely on embedding the virtual machine in your game or application. By doing this you will be able to export and use your own functions, types and structures within GameMonkey and use it to control many aspects of your program.<br />
<br />
<br />
<strong class='bbc'>Acknowledgements</strong><br />
The author would like to thank both Matthew Riek and Greg Douglas for their hard work in making GameMonkey Script what it is today. Thanks also to Jack Hoxley and Howard Jeng for their help in making this article worth reading.<br />
<br />
<br />
<strong class='bbc'>References</strong><br />
<ul class='bbc'><li>Douglas, G. & Riek, M. (2003). GameMonkey Script Reference. Included with all official GameMonkey Script distributions. [URL: <a href="http://www.somedude.net/gamemonkey"><a href='http://www.somedude.net/gamemonkey]' class='bbc_url' title='External link' rel='nofollow external'>http://www.somedude.net/gamemonkey]</a> </li><li>Lua Website. [URL: [url="http://www.lua.org"]<a href='http://www.lua.org' class='bbc_url' title='External link' rel='nofollow external'>http://www.lua.org</a>[/url]] </li><li>Wilkinson, O., (2004). evolutional's GameMonkey Zone. [URL: [url="http://www.evolutional.co.uk/gamemonkey"]<a href='http://www.evolutional.co.uk/gamemonkey' class='bbc_url' title='External link' rel='nofollow external'>http://www.evolution...o.uk/gamemonkey</a>[/url]]</li></ul>]]></description>
		<pubDate>Sat, 14 Jan 2006 11:21:29 +0000</pubDate>
		<guid isPermaLink="false">fda2217a3921c464be73975603df7510</guid>
	</item>
	<item>
		<title>Direct3D 9.0 with SDL</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/direct3d-90-with-sdl-r2249</link>
		<description><![CDATA[Let's face it, Windows code is a pain! Who wants to piece together hundreds of lines of archaic WinAPI code just to initialize a wind&#111;w. Wouldn't it be wonderful if it were possible to initialize a window, setup Direct3D 9.0, render some primitives to the screen, and construct a basic input handling system without having to touch a single line of obfuscated WinAPI code?<br />
<br />
 Well, guess what...with Sam Lantinga's SDL library, it can, and with less than 100 lines of code at that! SDL is a powerful cross platform library which allows you to perform windowing, complex graphic operations, music, input handling, and multithreading while compiling with the same code on a myriad of operating systems including Windows, Linux, and Macintosh. In this tutorial however, we will be using SDL for its elegant windowing and input. Despite your initial hopes and inclinations, since we are using Direct3D the code will not be cross platform. Sam is brilliant, but I don't think he is <em class='bbc'>that</em> brilliant! <img src='http://public.gamedev.net/public/style_emoticons/default/smile.gif' class='bbc_emoticon' alt=':)' /> With that brief and informative history, let's get started!<br />
<br />
 Assuming you have the DirectX 9.0 SDK installed all you need to do is head over to <a href='http://www.libsdl.org/' class='bbc_url' title='External link' rel='nofollow external'>http://www.libsdl.org</a>, the official website for SDL, and download the source. If it makes you more comfortable, skim the very informative DOC project to get a general feel for how SDL works, although this is not really necessary. For this project we will be including the following headers: <strong class='bbc'>windows.h, d3d9.h, d3dx9.h,</strong> and <strong class='bbc'>sdl.h</strong>. Additionally we will link to the following libraries: <strong class='bbc'>sdl.lib, sdlmain.lib, d3d9.lib,</strong> and <strong class='bbc'>d3dx9.lib</strong>.<br />
<br />
 Due to the simplicity and direct nature of this program, the only function defined is the main one, main(), so let's define it and declare all the variables this program will be using. I have commented the purpose of each variable and hope the meanings are somewhat conceptually clear in an abstract sense.<br />
<br />
  // this is the type used to describe a single vertex // each vertex has x,y,z coords and a color associated with it struct D3DVERTEX {   float fX,fY,fZ;    DWORD dwColor; }; <em class='bbc'>int main( int argc, char* argv[] ) {    SDL_Event       		event;              //used to poll for events and handle input    LPDirect3D9     		Direct3D_object;    //used to create a direct 3d device    LPDirect3DDEVICE9   	Direct3D_device;    //basic rendering object    D3DPRESENT_PARAMETERS   present_parameters; //stores the important attributes and 	D3DXMATRIX              projection_matrix;  //   properties your Direct3D_device will have    LPDirect3DVERTEXBUFFER9 tri_buffer = NULL;  //data buffer which the Direct3D_device can draw from    VOID* pData;                                //pointer to beginning of vertex buffer    //actual data to be fed to the vertex buffer    D3DVERTEX aTriangle[ ] = {{-2.0f,1.0f,10.0f,0xffff0000},                              {-3.0f,-1.0f,10.0f,0xff00ff00},                              {-1.0f,-1.0f,10.0f,0xff0000ff}}; </em>  Now you may be wondering why a win32 app would use a console style main() function. The answer is that as part of SDL's cross platform code, it takes care of the WinMain() function and layers main() over it. So effectively your entry point is main() just as it in a console program.<br />
<br />
 With that confusion settled it's time to discuss the basic Direct3D initialization process.<br />
<br />
 <ul class='bbcol decimal'><li>initialize a window</li><li>create a Direct3D object</li><li>set the important parameters for the Direct3D device you want to make</li><li>using the Direct3D object, parameters, and a handle to your window</li><li>create the Direct3D device</li><li>establish projection matrix, lighting, culling, depth buffer, and vertex format</li><li>load in primitive data</li></ul> When all those steps are taken care of, you want to generate your central game loop which will render graphics each frame as well as handle messages and input.<br />
<br />
 This will be covered in the 7<sup class='bbc'>th</sup> and final step.<br />
<br />
 <br />
<strong class='bbc'>Initialize a Window</strong><br />
 When programming with the Windows API, making windows is a pain in the arse. You have to register a window class, define callback procedures, and set a million parameters. All of this when you only want a simple window to serve as a rendering context. Fortunately for us, SDL can do all of this for us. The following lines of code will initialize the SDL_VIDEO subsystem, and create an 800 by 600 video mode. Of course you are free to adjust the resolution to your needs.<br />
<br />
  if( SDL_Init( SDL_INIT_VIDEO  ) < 0 || !SDL_GetVideoInfo() )    return 0; SDL_SetVideoMode( 800, 600, SDL_GetVideoInfo()->vfmt->BitsPerPixel, SDL_RESIZABLE );  That's it! A window has been created, and to get a handle to it all you need to do is call GetActiveWindow().<br />
<br />
 <br />
<strong class='bbc'>Create a Direct3D object</strong><br />
 This couldn't be any easier...<br />
<br />
  Direct3D_object = Direct3DCreate9(D3D_SDK_VERSION); if( Direct3D_object == NULL ) {    MessageBox(GetActiveWindow(),"Could not create Direct3D Object","D3D_OBJ ERR",MB_OK);    return 0; }  <br />
<strong class='bbc'>Direct3D Device Parameters</strong><br />
  ZeroMemory(&present_parameters, sizeof(present_parameters)); present_parameters.Windowed = false; present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD; present_parameters.EnableAutoDepthStencil = true; present_parameters.AutoDepthStencilFormat = D3DFMT_D16; present_parameters.hDeviceWindow = GetActiveWindow(); present_parameters.BackBufferWidth = 800; present_parameters.BackBufferHeight = 600; present_parameters.BackBufferFormat = D3DFMT_R5G6B5; present_parameters.MultiSampleType = D3DMULTISAMPLE_NONE;  Explaining each and every parameter would be overkill for a beginner's tutorial. Essentially they allow you to define the core properties of your Direct3D device, like the dimensions of the screen buffer, the format of the screen buffer, the way the buffer is swapped each frame, the format of the stencil buffer, and so on...<br />
<br />
 <br />
<strong class='bbc'>Creating the Direct3D Device</strong><br />
 Just like the object, creating the device is an easy task once you have the window and parameters filled in:<br />
<br />
  if( FAILED(Direct3D_object->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,            GetActiveWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING,            &present_parameters,&Direct3D_device))) {    MessageBox(GetActiveWindow(),"Could not create Direct3D Device","D3D_DEV ERR",MB_OK);    return 0; }  <br />
<strong class='bbc'>Setting States</strong><br />
 Next, we need to establish the projection matrix, lighting, culling, depth buffer, and vertex format. Sounds like a lot, doesn't it? Actually the Direct3D device can do each of these with one to two lines of code respectively, at least for our purposes.<br />
<br />
 For this projection matrix I have set the near and far planes to 1 and 1000 respectively, and used the ratio of the screen height to the screen width as the aspect ratio. (Make sure to adjust this ratio accordingly if you modified the height and width.) In the other lines of code lighting is disabled, backface culling is disabled, the depth buffer is set, and a vertex format is set. (D3DFVF_XYZ | D3DFVF_DIFFUSE) means that a vertex's data is organized in linearly in memory as its x, y, and z coords followed by its color.<br />
<br />
  D3DXMatrixPerspectiveFovLH(&projection_matrix, D3DX_PI / 4.0f,(float) 800/600,1, 1000); Direct3D_device->SetTransform(D3DTS_PROJECTION,&projection_matrix); Direct3D_device->SetRenderState(D3DRS_AMBIENT,RGB(255,255,255)); Direct3D_device->SetRenderState(D3DRS_LIGHTING,false); Direct3D_device->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); Direct3D_device->SetRenderState(D3DRS_ZENABLE,D3DZB_TRUE); Direct3D_device->SetFVF((D3DFVF_XYZ | D3DFVF_DIFFUSE));  <br />
<strong class='bbc'>Loading Primitive Data</strong><br />
 First off we need to create our vertex buffer object. It obviously needs to be as large as our triangle data is, and for now we only want to write to the buffer so let's specify that as well since the device can optimize if it knows we won't be reading from it. Also we need to specify the vertex format the buffer will use, and pass a flag telling it to manage the data. We finally pass the address of the object which will become the vertex buffer. The last parameter has its uses, but we do not need it for now so it needs to be NULL.<br />
<br />
  Direct3D_device->CreateVertexBuffer(sizeof(aTriangle),D3DUSAGE_WRITEONLY,                             		(D3DFVF_XYZ | D3DFVF_DIFFUSE),                             		D3DPOOL_MANAGED,&tri_buffer,NULL);  The following functions set pData as the main pointer to the vertex buffer, and copy the vertex data to the memory pointed by pData.<br />
<br />
  tri_buffer->Lock(0,sizeof(pData),(void**)&pData,0); memcpy(pData,aTriangle,sizeof(aTriangle)); tri_buffer->Unlock();  <br />
<strong class='bbc'>Final Step</strong><br />
 Now that everything is initialized, we need only to make our main game loop, which will render to the buffer each frame and also process incoming messages. Each frame we need to clear out the buffers. Meanwhile all data has to be drawn in between a BeginScene() and EndScene() as illustrated below.<br />
<br />
 The input as handled by SDL is fairly straightforward as well. In this case it will respond to a user hitting the escape key by the freeing Direct3D object and device, and then quitting.<br />
<br />
  while( 1 ) {    Direct3D_device->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,                              D3DCOLOR_XRGB(0,0,0),1.0f,0);    Direct3D_device->BeginScene();    Direct3D_device->SetStreamSource(0,tri_buffer,0,sizeof(D3DVERTEX));    Direct3D_device->DrawPrimitive(D3DPT_TRIANGLELIST,0,1);    Direct3D_device->EndScene();    Direct3D_device->Present(NULL,NULL,NULL,NULL);    while( SDL_PollEvent( &event ) )   	switch( event.type )   	{          case SDL_KEYDOWN:     		if ( event.key.keysym.sym == SDLK_ESCAPE )     		{                Direct3D_device->Release();                Direct3D_device = NULL;                Direct3D_object->Release();                Direct3D_object = NULL;                return 0;     		}     		break;          }    }    return 0; }  I hope this tutorial was helpful. you may also want to consult the full source code which is <a href='http://www.gamedev.net/reference/programming/features/dx9sdl/d3dtestmain.cpp' class='bbc_url' title=''>enclosed</a>. Suggestions, complaints, or complements can be emailed to me at <a href='mailto:mconway@tulane.edu' title='E-mail Link' class='bbc_email'>mconway@tulane.edu</a>.<br />
<br />
 <br />
<strong class='bbc'>Acknowledgements</strong><br />
 I want to thank Victor Saars for his wonderful tutorials at <a href='http://www.riaz.de/tutorials/d3d.html' class='bbc_url' title='External link' rel='nofollow external'>http://www.riaz.de/tutorials/d3d.html</a>. This tutorial is based off of the knowledge I gained from his excellent explanations.<br />
<br />
 <br />
<strong class='bbc'>Biography</strong><br />
 Michael Conway is a student attending Tulane University and is currently majoring in computer science and mathematics. He has been programming since his senior year of high school, but has played video games his entire life. Naturally the two coincide to game development <img src='http://public.gamedev.net/public/style_emoticons/default/smile.gif' class='bbc_emoticon' alt=':)' />. He has experience in c/c++, OpenGL, SDL, PHP, VisualBasic, and is currently working on a small scale online 3D adventure game. With the advent of this tutorial, he has now embarked on a journey to learning Direct3D in the hopes of widening his horizons in the 3D graphics domain and seeing what it is like on the other side.]]></description>
		<pubDate>Tue, 17 May 2005 16:19:18 +0000</pubDate>
		<guid isPermaLink="false">c944f1ed33079ef19b1965581683dece</guid>
	</item>
	<item>
		<title>Distributing Your Games</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/distributing-your-games-r2005</link>
		<description><![CDATA[<strong class='bbc'>Introduction</strong><br />
 Distribution and or deployment (however you want to refer to it), is a key phase of any software development process. When all the development is said and done there has to be some way for the end user to install and run software. In this article I will review some of the options available to development teams, and the reasons for implementing an install package solution.<br />
<br />
 Why do we need a way to package our files together for distribution? The most obvious reason is it makes installation for our happy users MUCH easier. Think of a game like Half-Life and think of all the files that are required to make it run properly. All files involved need to exist in a specific directory on your machine. Having one of the files in the wrong spot could result in lost functionality, a program crash, etc.<br />
<br />
 Another reason is it saves the time having to download third party software on your own. Your program may require GLUT (Graphics Library Utility Toolkit for OpenGL), the latest version of DirectX or other necessary libraries. If the user doesn't already have these software libraries they may not know or have the desire to go to get it. They may also not want to go searching on the internet for them. Having these libraries packaged in your install program saves the user time and work.<br />
<br />
 Say you have a file that you need to go in the Windows system directory. Your application is going to be installed on Windows 98/ME/2000 and XP. This operating system list is fairly common for many applications today. The Windows system directory exists in a different location for each of these different operating systems. An install package solution gives developers the ability to perform this functionality quickly and efficiently.<br />
<br />
 Game developers in particular will be interested in the install package solution. Head over to the International Games Festival home page (<a href='http://ww.igf.com/' class='bbc_url' title='External link' rel='nofollow external'>http://ww.igf.com</a>). I recently took a quote off their front page. It reads as follows,<br />
<br />
 "<strong class='bbc'>New Submission Requirement For 2004: Install/uninstall</strong><br />
Due to the large number of submissions we are expecting this year, we are requiring that all games (for both the IGF Competition and IGF Student Showcase) include an install/uninstall feature."<br />
<br />
 So all you hopefuls who are submitting you're games, read on! Hopefully this article will help point you in the right direction deciding on the right install package solution to meet your needs.<br />
<br />
 <br />
<strong class='bbc'>What is available?</strong><br />
 For many people packaging their files using Winzip, WinRAR or other popular compression software is sufficient. While this function definitely helps to download just one zip file over multiple files the user must have the appropriate decompression software to be able to open it. If we consider WinZip specifically, it's likely that many of you have it. It's been around for quite a few years and its distribution is quite high. However, there isn't a 100% guarantee that our users are going to have this software. An ideal solution would be to package all of our required files into one standalone executable.<br />
<br />
 WinRAR and Winzip do allow you to package a set of files in a standalone executable but it doesn't allow much customization. Additionally, there is a supplementary charge for the functionality to make these standalone executables. This functionality gives us a way to install our files but not to uninstall them. Other nice features to have as I mentioned earlier would be to have the ability to detect an operating system. Common compression software applications like WinZip do not give us this functionality.<br />
<br />
 There are solutions available giving us this customization ability. They allow both an install and uninstall feature, the ability to write registry keys, operating system detection, etc. These solutions include most notably InstallShield and Wise. They exist to make it easy for end user's to install applications. For open source developers or small companies the cost for an InstallShield license may be too costly. On the negative side, InstallShield and Wise give you the customizability but again there is the added cost of a license. On the positive side, InstallShield and Wise make use of a scripting language which gives the application more versatility.<br />
<br />
 An ideal solution would be to have one package which has customization, the ability to create a standalone executable, an install/uninstall feature, operating system detection, minimal cost, etc. The "ideal" list could go on for quite some time. But, is there such a magical package available?<br />
<br />
 <br />
<strong class='bbc'>Introducing NSIS</strong><br />
 One such packager/compiler on the internet which meets these "magical" criteria is NSIS. For those of you who haven't heard of NSIS before it stands for Nullsoft Superpimp Installation System, developed by the good folks at Nullsoft. If you've downloaded Winamp, you've used an NSIS installation package.<br />
<br />
 NSIS shares many of the same properties as commercial installers. This includes access to the Windows registry, an install and uninstall mechanism and extension of its functionality through plug-in DLLs. Rather than operating through a GUI oriented application (such as in InstallShield or Wise), all work is done through a scripting language. If you know a language such as C/C++ or scripting language like PHP and/or J&#097;v&#097;script you shouldn't have trouble picking up the syntax.<br />
<br />
 One of the great benefits of NSIS is its fantastic user community. There's a very good chance that when you post a question on the discussion forum you receive a response within one hour. Very often the reply is from the NSIS developers themselves. You can't ask for a much better response time than that! A number of tools have been created for working with NSIS so you don't have to worry about dealing with the syntax of the scripting language at all if that's not your "bag". They work very much like Install Shield or Wise would.<br />
<br />
 Another great feature of NSIS is the user supported archive. It contains plug-ins, script editors, useful functions developed by and for the NSIS community and a great deal more. The archive can be found here,<br />
<br />
 [indent]<a href='http://nsis.sourceforge.net/archive/' class='bbc_url' title='External link' rel='nofollow external'>http://nsis.sourceforge.net/archive/</a>[/indent] But, what about cost? NSIS has many of the features I've mentioned in this discussion for in an install package but it's got to cost a fortune for all that functionality. Quite fortunately, NSIS is open source and is free for both personal and commercial use.<br />
<br />
 <br />
<strong class='bbc'>Examples of some NSIS installations</strong><br />
 Below I've included two screenshots. One is of an NSIS installation package I have developed working at 3DNA and the other is a screenshot from an NVIDIA driver InstallShield package. The install package I have developed includes many of the features I've mentioned at several points in this article. If you'd like to check out my handiwork it's a free download off of the 3DNA website (<a href='http://www.3dna.net/' class='bbc_url' title='External link' rel='nofollow external'>www.3dna.net</a>). I would love to hear any comments you may have about it. My contact information can be found at the end of this article.<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/install/image001.jpg' alt='Posted Image' class='bbc_img' /></span><br />
Fig 1. Screenshot of a NSIS installation package<br />
<br />
 <span rel='lightbox'><img src='http://images.gamedev.net/features/programming/install/image002.jpg' alt='Posted Image' class='bbc_img' /></span><br />
Fig 2. Screenshot of an InstallShield package<br />
<br />
 There's not much of a difference which is great. One of the nice features about NSIS is it allows you to customize your application to give it that professional look.<br />
<br />
 To give you an idea of the compression NSIS is able to achieve I've included a comparison for you to look over. It's a table of file sizes from a website I work on. There's a good mix of JPEG, GIF, HTML, and regular text files. Approximately 615 files were compressed in all.<br />
<br />
 <br />
<br />
   NSIS WinZip WinRAR   31.8 MB 32.1 MB 31.2 MB   Fig 3. Comparing file sizes using NSIS, WinZip, and WinRAR Generally it's pretty even across the board. I didn't do an extensive test trying out compression on all different file types and settings but it gives you a pretty good idea of the results. Additionally, WinZip and WinRAR are not install package creators, so they do not have the additional overhead of a step by step install process that is pretty much the standard today. NSIS of course does have all the nice install wizard features and yet NSIS still stacks up quite easily against WinZip and WinRAR.<br />
<br />
 Below I have included a table comparing the packages I've discussed in this article.<br />
<br />
 All of the packages I have listed here contain many, many more features than I would care to compare. This is a short reference only.<br />
<br />
    NSIS InstallShield Wise WinZip WinRAR   <strong class='bbc'>Open source</strong> Yes No No No No   <strong class='bbc'>Cost</strong> Free Varies per package and features, approx $350 - $2400 Varies per package, starting at $450 Starting at $29 Starting at $29   <strong class='bbc'>Custom DLL plug-ins</strong> Yes Yes Yes No No   <strong class='bbc'>User community</strong> Yes, through discussion forums Yes, through discussion forums Yes, through newsgroups No No   <strong class='bbc'>Installer & uninstaller</strong> Yes Yes Yes N/A N/A   <strong class='bbc'>Multi-language support</strong> Yes Yes Yes No No   <strong class='bbc'>Standalone package after creation</strong> Yes Yes Yes Yes, extra charge for this functionality Yes   <strong class='bbc'>Customizable user interface</strong> Yes Yes Yes N/A N/A   <strong class='bbc'>Multi-platform support</strong> Windows 95, 98, ME, NT4, 2000, XP Windows 95, 98, ME, NT4, 2000, XP, Mac OS X, OS/400, Windows, AIX, Solaris, Linux, HP-UX, or any other flavor of UNIX Windows 95, 98, ME, NT, 2000, XP Windows 95, 98, ME, NT, 2000, XP There are applications that will allow you to unzip WinZip files on Unix platforms<br />
<br />
  Windows 95, 98, ME, NT, 2000, XP There are applications that will allow you to unzip WinRAR files on Unix platforms<br />
<br />
    <strong class='bbc'>IDE (Integrated Development Environment)</strong> Via user community tools and NSIS archive Yes Yes N/A N/A   What follows are some notable features about each of the packages I've discussed throughout this article.<br />
<br />
 Factors which tend to uniquely distinguish them from the rest of the group. I've tried to keep the list fairly short; this is not meant to be a feature list just a short summary of some of the more important pros and cons for each package.<br />
<br />
 <span class='bbc_underline'>NSIS</span><br />
<br />
 Pros<br />
<br />
 <ul class='bbc'><li>Cost</li><li>It's open source</li><li>Upgrades are being made constantly to improve functionality, sometimes on a day by day basis</li><li>There are very strong ties between the NSIS developers and the user community. A feature will sometimes get requested and then end up in the latest distribution the next day.</li><li>One important difference between NSIS and other installers is the size of the installer overhead. While others installer add 200 KB or even several megabytes to your data, a full featured NSIS installer has a size of only 34 KB.</li><li>Cost</li></ul> Cons<br />
<br />
 <ul class='bbc'><li>Changes that are made sometimes nullify previous scripts. You will have to occasionally modify them to comply with new functionality.</li><li>Everything needs to be done in the NSIS scripting language (but there are frontends available created by the user community)</li><li>Limits platform to Windows</li></ul> <span class='bbc_underline'>InstallShield</span><br />
<br />
 Pros<br />
<br />
 <ul class='bbc'><li>Well known and have a good reputation</li><li>Multi platform solutions are available</li><li>Built-in debugger</li></ul> Cons<br />
<br />
 <ul class='bbc'><li>Cost</li></ul> <span class='bbc_underline'>Wise</span><br />
<br />
 Pros<br />
<br />
 <ul class='bbc'><li>A lot of the functionality is done through an interface so there is less chance for user error</li><li>Built-in debugger</li></ul> Cons<br />
<br />
 <ul class='bbc'><li>Cost</li><li>Limits platforms to Windows</li></ul> <span class='bbc_underline'>WinZip & WinRAR</span><br />
<br />
 Pros<br />
<br />
 <ul class='bbc'><li>Pretty much everyone has the ability to unzip these files</li><li>If all you want to do is compress your files you don't need to worry about any kind of user interface need to design</li><li>Files are extractable on Unix platforms</li></ul> Cons<br />
<br />
 <ul class='bbc'><li>Not a complete installation package solution</li><li>Cost, this can be a con depending on how many licenses you need</li></ul> I've included links at the end of this article to other install package libraries. Some are free; some aren't which I have noted for each link. Take a look through some of the other installers and see if any of the others suit your needs. I've concentrated on NSIS the most because I've used it the most extensively. Being a developer myself I found NSIS very easy to pick up and was beginning to look into its more advanced capabilities after a week or two. If you're familiar with the basics of Win32 programming alot of the NSIS script functions will look familiar.<br />
<br />
 The other install packages available should not be ruled out. It's a case of selecting the right tool for your needs. NSIS is nice but you may not want to concentrate on your installer/uninstaller that much. Making your software easily distributable will make it easier for more people to install and enjoy it. Hopefully this article will help get you pointed in the right direction.<br />
<br />
 Questions or comments can be directed to me (Rob Segal) at <a href='mailto:rsegal@3dna.net' title='E-mail Link' class='bbc_email'>rsegal@3dna.net</a><br />
<br />
 Special thanks to Amir Szekely and Joost Verburg for their reviews and contributions of this article.<br />
<br />
 <br />
<strong class='bbc'>Install package websites</strong><br />
 NSIS – <a href='http://nsis.sourceforge.net/' class='bbc_url' title='External link' rel='nofollow external'>http://nsis.sourceforge.net</a> (FREE)<br />
Inno Setup - <a href='http://www.jrsoftware.org/isinfo.php' class='bbc_url' title='External link' rel='nofollow external'>http://www.jrsoftware.org/isinfo.php</a> (FREE)<br />
INF Tool - <a href='http://www.inner-smile.com/dl_inf.htm' class='bbc_url' title='External link' rel='nofollow external'>http://www.inner-smile.com/dl_inf.htm</a> (FREE)<br />
Click Team Install Maker – <a href='http://www.clickteam.com/' class='bbc_url' title='External link' rel='nofollow external'>http://www.clickteam.com</a> (FREE)<br />
Zip Genius - <a href='http://www.zipgenius.it' class='bbc_url' title='External link' rel='nofollow external'>www.zipgenius.it</a> (FREE)<br />
InstallLib - <a href='http://sourceforge.net/projects/installlib/' class='bbc_url' title='External link' rel='nofollow external'>http://sourceforge.n...cts/installlib/</a> (FREE)<br />
Wise – <a href='http://www.wise.com' class='bbc_url' title='External link' rel='nofollow external'>http://www.wise.com</a><br />
InstallShield - <a href='http://www.installshield.com' class='bbc_url' title='External link' rel='nofollow external'>http://www.installshield.com</a><br />
Ghost Installer – <a href='http://www.ginstall.com' class='bbc_url' title='External link' rel='nofollow external'>http://www.ginstall.com</a><br />
WinZip – <a href='http://www.winzip.com/' class='bbc_url' title='External link' rel='nofollow external'>http://www.winzip.com</a><br />
WinRAR – <a href='http://www.winrar.com/' class='bbc_url' title='External link' rel='nofollow external'>http://www.winrar.com</a>]]></description>
		<pubDate>Tue, 14 Oct 2003 01:02:54 +0000</pubDate>
		<guid isPermaLink="false">aa62458166d68ba3cffa22542733ac8c</guid>
	</item>
	<item>
		<title>SQL in 60 Seconds</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/sql-in-60-seconds-r2000</link>
		<description><![CDATA[<br />
<strong class='bbc'>About the article</strong><br />
 Learning the basics of SQL shouldn't take more than a very short while to get started. If you're used to programming and some of the theory behind data storage this tutorial will be easily understood.<br />
<br />
 However, I'm more than eager to help everybody learn so I will try to make the examples easy. This is an article for beginners; you don't need to know much to get started.<br />
<br />
 This article does not show you examples in languages like PHP or ASP. It only introduces you to the powerful language of SQL.<br />
<br />
 <br />
<strong class='bbc'>Introduction to SQL</strong><br />
 SQL (Structured Query Language), pronounced "sequel" (from the former name SEQL, Structured <span class='bbc_underline'>English</span> Query Language) is the language generally used to speak to any kind of database out there. Examples of databases are mySql (my favourite, it's free, it's fast, it's usable), Microsoft Access, Microsoft SQL Server, Oracle or literally any alternative in existence. ODBC is a driver that makes (or made, it's pretty outdated) it easier to connect to the database, but nowadays it's more common to connect directly to the database since that's generally faster.<br />
<br />
 SQL has been out there for many years and a decent SQL administrator can easily earn some serious money if he/she knows enough about it. Optimizing SQL queries is an easy way to secure your job future, since most sites want to have faster web pages (duh!). However, becoming an SQL expert takes years in the field and I wouldn't even consider myself to be an expert.<br />
<br />
 Databases are becoming more relevant to all fields of programming. Modern games connect to a global database (perhaps via a web interface) and get data for high scores, member access (ever played/watched EverQuest? A lot of database storage there my friends), etc. Also on the application front databases are becoming more and more popular on the users' edge. For instance budgeting applications, but also any other kind of application where you'd want a storage solution that is expandable, searchable and fast using as little memory as possible.<br />
<br />
 <br />
<strong class='bbc'>Creating tables and getting started</strong><br />
 Most database today come with a user interface which is like any windows/kde/gnome application out there, making it easy to watch, add, edit and remove tables in the database. Tables are the "groups" in the database where information is stored. Normally you start off with a name for the database (most software allows you to have several databases within the product). Call your database the name of your webpage for instance, to make it easier to relate the database to the software that is using it.<br />
<br />
 The tables in the database are containers of data. For instance, for a site like GameDev.net, the names of the tables might be "Member", "News" and "Article".<br />
<br />
 You can add tables through SQL queries but personally I think it is more trouble than its worth, so use your favourite GUI to try it out. If you are on Windows I really recommend you try Microsoft Access just because it's so easy to get started with. If you are on Linux/BSD I would suggest you to download one of the graphical interfaces available for mySql.<br />
<br />
 Inside the tables there are entities. Just as in a programming language, entities are like variables. There are different types, and the types are named differently between different databases but I'll try to describe what they should be and you can try to find the equivalent in the software you choose to use. They also have a name, and of course the data which is stored in them. So, to sum up, Name, Type and Data.<br />
<br />
 When you design your tables you only need to enter the Name and the Type, data will be added later. For now, we will do a simple news system for our favourite homepage. I'll try to be as brief as I can; please read carefully and try to understand each part I'm talking about.<br />
<br />
 Let's take a look at the following graphics for the tables and try to implement it in your database; I'm explaining each fuzziness under the image.<br />
<br />
 /reference/programming/features/sql60/sql_1.gif<br />
<br />
 <br />
<strong class='bbc'>The member table</strong><br />
 As we would like to store the member's name, password, email and URL to a web page (if the user has such), we need to store just that in the database.<br />
<br />
 First of all, the ID field hits you. Is this auto generated? Well, in a sense it is, in another it isn't. You need to create it yourself, but you should make sure you find the right data type for it. In Access you could choose "Autonumber", and while you're at it, make sure it runs with "no duplicates" and check that "required" is also set to yes.<br />
<br />
 The ID field you just created will need to be a primary key. I showed this with an empty circle in front of the name. There is only one primary key per table, and personally I think it should ALWAYS be a separate field called ID. The big thing about a primary key is that it has to be unique. You might think "yeah, but the email address is unique, can't I use that?". Well, you can. But I wouldn't recommend it. First of all, the email address is a text string containing up to 50 characters in our example. Making the database need to connect tables through textfields is not only slow, but a fairly risky process since the foreign keys (I'll talk about them in a moment) will need to be more complex. Second, it will also require a lot more space due to these foreign keys. Back to them later.<br />
<br />
 By the way, you can set any entity of the table to required and "allow zero length" to true, etc. This is up to you - how much you want the database to control for you. Personally, I do this check in the WebPages instead, not by checking error values from the database. I guess this is a matter of taste and also a matter of how you are using databases. Try different methods out and use whatever works for you.<br />
<br />
 The memberName, memberPassword, memberEmail and memberWeb are named using a "member" prefix, because when you do complex queries, it's nice to know which table uses which entities. The ID's are an exception to this, if I want to know which table they belong I will have to write [Table].id to get it. More about that later.<br />
<br />
 Each of these entities is a text field with a maximum length set to 50. This does not only restrict users from entering names that are too long, but also saves storage (in theory yes, in practical database implementations a string never takes up more than length(data_text)+1 so to speak, but you don't need to bother about this, it's good to set a limit anyhow). I guess the database also figures out a good strategy for saving the data intelligently according to the limits of each entity too so setting everything up is quite a good idea.<br />
<br />
 That's basically the member table. A good idea to speed up databases is to put the entity field "index" to true on such entities that are likely to be used in comparisons with other tables in the database. Primary and foreign keys are especially targeted.<br />
<br />
 <br />
<strong class='bbc'>The news table</strong><br />
 Here we also have an ID field just as with the member table. Having the same name and settings on these fields in all tables simplifies things since we never have to check the database or write down what the settings are on each of these tables.<br />
<br />
 Second you will see a field called memberID, which is our first foreign key (open up the champagne ladies and gentlemen)! This is a reference (like a link, if that makes you more comfortable) to the member table. In our case it's a reference to the member table because each news item also has an author. Now, why didn't we call this authorID, memberAuthorID or something similar? Well, I don't know. Once again, you have to make up your own mind here, I've just stuck with calling references to other tables [Tablename]ID. Of course, there can be several links to the member table from other tables. For instance all of the following could be members of an article table: memberCreatorID, memberAuthorID, memberAuthorizationID etc, for the one who created the article item in the article table, one who is actually responsible for the contents of the article, and one that verifies the article for posting on the web. When I write memberID, I'm referring to the one who created the news item, author or not.<br />
<br />
 The newsSubject entity is the same type as the member specific entities, only this entity can be 255 characters long.<br />
<br />
 The newsBody item is a new one on the heap. The memo type is from Access and simply describes the type for a whole lot of text. I believe varchar is used for text in mySql mySql and memo in Microsoft SQL Server, but I think you get the idea. This is storage that in practical use doesn't have any limits. Great for storing bodies in news items for sure!<br />
<br />
 Last but not least is the newsDate. This datafield contains the date when the table row (data is stored in "rows", entities can be seen as "columns") was created. It's a good idea to automate this feature so you don't have to enter the date yourself in your SQL queries. This is how you do it (one more time in Access - forgive me, but it's easy to start off in Access!) In the "Default" field of the entity newsDate, enter "Now()". Now() is a method that gets the date. So when the row is created, instead of entering the date through the query, it will set the date automatically. Sweet!<br />
<br />
 <br />
<strong class='bbc'>Tables done</strong><br />
 Now the tables are done. You could try to enter some data through the graphical interface, but please remove them when you're done so we can continue with the article without confusion. Btw, note how nicely the dates are generated in the news table.<br />
<br />
 In most databases, there is something called relations between tables. This is so you can set up the foreign keys to point at the primary keys of the targeted table. This is a safety issue. While we are just messing around I don't think we want to set these, but if you're building a serious web site you should consider using this. It simply restricts you from removing the user "George Smithers" if he has written news items. In that case, you will simply be forced to first remove all the news items he has written, and then, after that is completed, remove the user himself. This stops the possibility of removing a user and having unreferenced material in the database (trash so to speak). As I said, when messing around, it doesn't matter what you do, but when you gain experience, you should really look this up because it will save you some database space in the long run, trust me.<br />
<br />
 Now when we're done setting up the tables (we should be up to 60 minutes by now, damn me, hehe).<br />
<br />
 <br />
<strong class='bbc'>INSERT something into the database</strong><br />
 As the heading suggests revealed, when inserting (adding) something to the database, we're likely to use the INSERT command through SQL. Remember, a query is only a string command, you have to set up the database connection and objects in the code for yourself, but I'll post two examples.<br />
<br />
 This is the basic syntax for inserting a member into the database through a single SQL query:<br />
<br />
  INSERT INTO member(memberName, memberPassword, memberEmail, memberWeb)         	VALUES('Albert Sandberg', 'secret', 'thec@home.se', 'www.thec.org')  (All the text in above example should be on one row, I just cut it down for nicer page layout)<br />
<br />
 It's pretty self explanatory: first we have the command, INSERT, which tells the database we're about to add something, next is the INTO statement followed up by the table name which we are supposed to store the data in. Inside the parentheses we just tell the database which entities we want to store, and inside the VALUES comes the data, in the same order as specified inside the first set of parentheses. No problem? Didn't think so!<br />
<br />
 It's really that simple. The hardest part is to program a web page that contains forms and links, corrections for incorrectly entered data, etc. The SQL should be the easy part when you've gotten used to it!<br />
<br />
 Here's an example of entering some data into the news table:<br />
<br />
  INSERT INTO news(memberID, newsSubject, newsBody)              VALUES(1, 'I know something about you.', 'You're really impressed by SQL too!')  Right here, we're using some of the magic of SQL. First, we have the memberID field, now referring to the first entry of the member table, which is 1. The member with id=1 in the member table is Mr "Albert Sandberg" since we've just entered him above. <strong class='bbc'>Note</strong>: If you have entered some test info and then deleted it when you created your tables, the first id will be the the one after the last one you entered in the test, because, as we discussed before, the id field should contain NO DUPLICATES! This is a feature you know!<br />
<br />
 The date is covered by the database. We never need to manually set it through the query, since the entities we're not entering will be filled in with their default values. If we hadn't entered Now() for the newsDate field, it would probably have been an empty field instead.<br />
<br />
 <br />
<strong class='bbc'>UPDATE changed data</strong><br />
 Once again, you might have an idea of what is going down. The UPDATE command changes things in the database. To move on forward let's skip the talk and get down to business:<br />
<br />
  UPDATE member set memberPassword='wünderbaum' where memberName='Albert Sandberg'  This should be fairly self-explanatory. The above will work fine if there is only one Albert Sandberg in the database, but since there is one more guy with that name which I know of, chances are we might some day enter the same website that you have coded, and I wouldn't like to not be able to log in when the other guy changes his password. You see, the where statement in the sql query returns ALL rows which match the execution argument. So if there had been two Albert Sandberg's, both passwords would have been changed. So we need to write something smarter, like:<br />
<br />
  UPDATE member set memberPassword='wünderbaum' where id=1  Now there's no doubt. Since you keep my login in a cookie on the web server (or session variable, still a cookie though) you will know my id, and when I choose to change my password, you will enter it at the end of the line. In practice you never use static foreign/primary keys, as they are always dynamic.<br />
<br />
 <br />
<strong class='bbc'>SELECT (view) our data</strong><br />
 All right, you want to present your news on the first page of your web site. Well, wait no further!<br />
<br />
  SELECT * FROM news  That's the basics. SELECT just picks every row in the database and since we don't have a WHERE statement on this one, it will simply select every row in the table.<br />
<br />
 That's not as interesting though, since there could be 200 news items when we just want to see 20 of them, and perhaps in reversed order, or at least ordered by date (note, SQL has the power to choose in which order the items will be shown if we don't pass directions, so look ahead):<br />
<br />
  SELECT TOP 20 * FROM news ORDER BY newsDate DESC  Now we're talking. The "TOP 20" tells the database we want the 20 first occurrences of news items, sorted by newsDate! DESC just tells the order to be reversed. With dates, that means newest first, oldest last. In some databases you would use the LIMIT command instead of TOP, but TOP is used in Access. Try to read the database documentation for further hints and usage descriptions.<br />
<br />
 All right, I have one more thing to show you before I move on to the next command. It's called joins and it is a little bit tricky at first, but I will try to make this as clear as I possibly can. Think about this: when you have SELECTed each news item, how do you fetch the member's name and id?<br />
<br />
 <ul class='bbcol decimal'><li>The bad way. You take each row of the returned news data and create a second query to the database where you do:  SELECT * from member where id=1  (of course you know the id=1 from the news.memberID field, right?). Anyway, this is not the correct way of doing it. When you are forced to make a second SQL query for fetching information you know belongs to the first query to start with, you know you need to update your SQL skills. This will make a lot more sense after looking at the next option. </li><li>You do it the good way, like this:  SELECT TOP 20 news.*, member.memberName, member.id FROM news,member     	WHERE news.memberID=member.id ORDER BY newsDate DESC  Felt like punch in the belly? No? Great, open up the champagne (or just fill up your glass). Here we do a join between two tables, plus we use the basics we already used. We want the TOP 20 results, we want to SELECT the info FROM both the news and the member table (which we select by using [table].entity; * is a wildcard, telling the database that we want everything), we tell the query compiler we only want entities WHERE news.memberID matches member.id (this one actually tells the database to bind up two tables into one result, but let's just stay there for a while) and we want to ORDER it by the newsDate, but in reverse order, that is, DESCending.</li></ul> Got it? Thank god, I succeeded. No? Read it again, you will not miss the fun the second time.<br />
<br />
 <br />
<strong class='bbc'>DELETE something</strong><br />
 All right, let's face it. Albert Sandberg is the most boring guy on the planet, so you want to get rid of him and destroy all evidence of his existence. You will have to start with removing all rows in the database where the id matches Albert Sandberg's, so you do the following:<br />
<br />
  DELETE * FROM news where memberID=1  That's how you remove the row matching the where clause in Microsoft Access. In any decent database you do it without the wildcard (why would you try to delete 50% of the entities anyway?). To remove the user from the member table in, for example, a mySql database, you'd use the following:<br />
<br />
  DELETE FROM member where id=1  Done. Albert Sandberg ceases to exist. Finally, the hero knows his powers and is ready to save the world! Hurray!<br />
<br />
 <br />
<strong class='bbc'>Common questions</strong><br />
 <strong class='bbc'>How do I use this knowledge on the web?</strong><br />
You visit <a href='http://www.php.net' class='bbc_url' title='External link' rel='nofollow external'>www.php.net</a> or <a href='http://www.aspin.com' class='bbc_url' title='External link' rel='nofollow external'>www.aspin.com</a> and look up some decent tutorials on the language you want to use. Search terms such as "connect to database" would be a good start. Now that you know a little more about SQL the examples should be easy as 1,2,3.<br />
<br />
 <strong class='bbc'>How do I search for news newer than [a date]?</strong><br />
This one gave me a hard time when I was a beginner. The answer for returning all news post OLDER than 2003-01-01 is:<br />
<br />
  SELECT * from news where newsDate<'#2003-01-01#' ORDER BY newsDate DESC  It's the ## which does the magic. < means "less than" and > means "greater than". Figure it out!<br />
<br />
 <strong class='bbc'>How do I search a field for a given string?</strong><br />
This is good if you want to do a little search function for your forums or news perhaps. Use the LIKE statement as follows:<br />
<br />
  SELECT * from news WHERE newsBody LIKE "%futurama%"  The % signs are wildcards telling the database that there can be other text both in front of and after the search string. This query will return all news where the body contains the word futurama.<br />
<br />
 <strong class='bbc'>How do I count news items?</strong><br />
This is also a very common question, and a nice feature to add for that little extra on your page. Try the following code to count the number of news posts Albert Sandberg has posted (before it was all deleted by the hero):<br />
<br />
  SELECT COUNT(*) from news where memberID=1  <strong class='bbc'>How do I figure out the average age of my members?</strong><br />
Let's say you have a entity of the table member which is called memberAge, where you store the age of the member visiting your site:<br />
<br />
  SELECT AVG(memberAge) AS age from member  Here I showcased the AS command too. This way you can name your results. This comes in handy when you select multiple (otherwise) nameless variables. In the following examples, utilizing some other nice functions in SQL, using no naming simply wouldn't be appropriate (it would still work though):<br />
<br />
  SELECT AVG(memberAge) AS average, MIN(memberAge) AS youngest,     	MAX(memberAge) AS oldest FROM member  That's it!<br />
<br />
 <br />
<strong class='bbc'>Final words</strong><br />
 This has been one crazy night for me. My hands hurt from all the typing and I would really appreciate if you told me if you liked the article or have anything to add about it. My email at <a href='mailto:thec@home.se' title='E-mail Link' class='bbc_email'>thec@home.se</a> is always open for your comments and I'd love to hear from you. I hope this article has given you something to build on and that it has been some pleasant reading.<br />
<br />
 SQL is really a powerful tool to know, and the more you know, the more fun it will be. There are many aspects of SQL which I haven't shown here. Perhaps I'll write another article some time, only time can tell.<br />
<br />
 Thank you for your time.<br />
Albert "thec" Sandberg<br />
<a href='mailto:thec@home.se' title='E-mail Link' class='bbc_email'>thec@home.se</a><br />
<br />
 <br />
<strong class='bbc'>About the author</strong><br />
 You're going to be surprised. Although I love electronics and know a lot of programming in many senses and have been studying programming at the university for a while, I'm a tile layer. That's like a bricklayer only that I just do the tiles part. That is, I do bathrooms, kitchens, floors and balconies and such. Please check my homepage <a href='http://www.thec.org' class='bbc_url' title='External link' rel='nofollow external'>www.thec.org</a> for some pictures and extended information about myself.<br />
<br />
 During a couple of years in the industry and lots of home programming I mostly program/manage hobby sites and such, as well as doing some C++ code when I lose my mind... sorry, I mean am in the right mood for it!<br />
<br />
 Other than computers, I love cars and snowboarding, so that's basically my real life activities.<br />
<br />
]]></description>
		<pubDate>Sun, 28 Sep 2003 22:40:45 +0000</pubDate>
		<guid isPermaLink="false">831bb3dd5d09fb053fc65257e81b28f8</guid>
	</item>
	<item>
		<title>Creating a PAK File Format</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/creating-a-pak-file-format-r1991</link>
		<description><![CDATA[<br />
<strong class='bbc'>Introduction</strong><br />
 In this article I intend to demonstrate one way of organising all your game related media files in to a single "PAK" file. A couple of good reasons to do this would be for easier distribution of your application data and to apply a degree of protection to your individual files to stop them from being misused. This article is aimed at beginner to intermediate level game programmers but you should be au fait with C++ and concepts such as linked lists, which are used in the code.<br />
<br />
 <br />
<strong class='bbc'>The Format</strong><br />
 The format of this PAK file will be quite simple. It will consist of an unencrypted file header, a file-table containing information on each file added to the PAK and then each actual file concatenated together at the end. The file-table and the included file's data will be encrypted. For the purposes of this article I will keep it simple and stick to using a Caesar cipher.<br />
<br />
 <br />
<br />
   PAK File Header   <br />
File Table<br />
<br />
   <br />
<br />
Concatenated File Data<br />
<br />
<br />
   <br />
<strong class='bbc'>The PAK File Class</strong><br />
 I think now would be a good time to introduce the PAK class I am going to use. It is shown below:<br />
<br />
  class CPakFile { private:   // Private Variables   char         	m_szFolderPath[300];   char         	m_szPakName[300];                           	sPakHeader   	m_Header;   sFileTableEntry* m_FileTable;                            // Private Functions   BOOL  GenerateHFT();   BOOL  WorkOutOffsets();        public:   CPakFile();   ~CPakFile();         	BOOL  CreatePak( char* Path, char* Output); };  The first two variables m_szFolderPath and m_szPakName will be the absolute paths to a compilation folder and the location / filename of the PAK to be output. The compilation folder will just be a folder containing every file you want to add to the PAK collated together. These two values will be read in from edit boxes in the accompanying compile tool and passed to the Create() method. There is also a file header variable of type sPakHeader and the linked list file-table of type sFileTableEntry which are two structures I will look at below. On instantiation of this class, the constructor defaults the variables and then adds a blank dummy node to the head of the linked list file-table. To save space, I will just let you look at this in the accompanying source code. The other two private functions generate the header and the file table and then works out the individual file offsets for inside the PAK respectively. They are both called by the Create() method, which is currently the only public method.<br />
<br />
 <br />
<strong class='bbc'>The File Header</strong><br />
 The file header for this PAK can be relatively simple. I am just going to use the following structure outlined below:<br />
<br />
  struct sPakHeader                                                                        {   char   szSignature[6];   float  fVersion;   DWORD  dwNumFTEntries;   BOOL   bCipherAddition;   BYTE   iCipherValue;   char   szUniqueID[10];   DWORD  dwReserved; };  I feel that most of its contents are self-explanatory. The iCipherAddition variable just indicates whether the cipher value is added or subtracted from each BYTE sized element that is encrypted. For those of you who don't know, a Caesar cipher is where you transpose each value that is to be encrypted "left or right" by a certain, consistent value. As a quick example, the letter 'A' encrypted using a +3 Caesar cipher would become the letter 'D'. The dwNumFTEntries variable is the number of file table entries (the number of files) in the PAK.<br />
<br />
 <br />
<strong class='bbc'>The File Table</strong><br />
 The file table will be a linked list of the following data structure, sFileTableEntry, which is outlined below. Each entry will be descriptive of any one file in the PAK.<br />
<br />
  struct sFileTableEntry                                                       	{   char   szFileName[30];   DWORD  dwFileSize;   DWORD  dwOffset;   sFileTableEntry* Next;            // Constructor   sFileTableEntry()   { 	ZeroMemory( szFileName, sizeof(szFileName) ); 	dwFileSize  = 0; 	dwOffset    = 0; 	Next                = NULL;   }   // Deconstructor   ~sFileTableEntry()   { 	ZeroMemory( szFileName, sizeof(szFileName) ); 	dwFileSize  = 0; 	dwOffset    = 0; 	delete Next;   } };  The offset value will be the first byte of the particular file within the PAK archive. The file name, size and link to another entry are also included.<br />
<br />
 <br />
<strong class='bbc'>The Create Method - Part 1</strong><br />
 The functions (including private ones) are quite large so I'll leave it in the source for you to look at and just describe them here. I feel that they are well commented though and that you should have no problems keeping up with them.<br />
<br />
 The Create() method really starts when it calls the function GenerateHFT(). GenerateHFT starts by filling in the header structure. It adds the signature, version number etc and some random results for the cipher value, unique ID and cipher direction (add or subtract). It then looks at the specified compilation directory (a parameter for Create() ) and parses it file by file. With each file that is found in the directory, it creates a new sFileTableEntry() node, fills in the filename and file size variables (with a default offset value) and adds it on to the linked list file-table. With each file found a counter is incremented. When this process is finished, the dwNumFTEntries variable of the header structure is assimilated with this counter.<br />
<br />
 The next stage of Create() is the calling of the WorkOutOffsets function. The very first file offset is calculated like this:<br />
<br />
  dwOffset = sizeof(sPakHeader) + (m_Header.dwNumFTEntries *                                  sizeof(sFileTableEntry));  The head entry of the file-table will take this to be the value of its offset member variable. Then the size of the file (already calculated for each entry by GenerateHFT() ) is added to the offset. It is then a case of iterating through the other file table entries and taking the offset value for its member variable and then adding on the particular file sizes. It is much easier to see in the code than it is to describe here!<br />
<br />
 <br />
<strong class='bbc'>The Create Method - Part 2</strong><br />
 At this stage the header and file table for the PAK are completely filled in. Now we open a file stream, using the second supplied parameter for Create(), and write an unencrypted header.<br />
<br />
 To write the encrypted file table we need to iterate through the linked list file-table one entry at a time (using a local copy of a file table entry called Current). Once we have checked that we are not on the dummy entry, we create a BYTE array the same size as sFileTableEntry like this:<br />
<br />
  BYTE* Ptr = NULL; Ptr = new BYTE [sizeof(sFileTableEntry)];  We then copy the current file table entry in to this BYTE array as follows:<br />
<br />
  memcpy( Ptr, Current, sizeof(sFileTableEntry) );  We then iterate through each BYTE in this array, encrypt it and write it out to the PAK file. The code for this is:<br />
<br />
  for( int i = 0; i < sizeof(sFileTableEntry); i++ ) {   // Temporary BYTE variable   BYTE Temp = 0;   // Make equal to the relevant byte of the FT entry   Temp = Ptr[i];      // Encrypt BYTE according to the Caesar cipher   if( m_Header.bCipherAddition == TRUE ) 	Temp += m_Header.iCypherValue;   else 	Temp -= m_Header.iCypherValue;      // Write the FT encrypted BYTE value   fwrite( &Temp, sizeof(BYTE), 1, PAKStream ); }  Once this is done the file stream is closed and the Current variables is set to the head of the linked list file-table again. What we do now is open two file streams. One is for writing to the PAK file and one for reading in each file to be added. These will be used in conjunction with each other.<br />
<br />
 We set the position in the PAK file (for writing) according to the dwOffset value stored in the current file entries member variable. We then read in a BYTE at a time from the input stream (which was opened using the szFilename variable of the current file entry), encrypt it using the Caesar cipher as before and output it in to the PAK file using the write stream. This is, again, demonstrated in the attached source code.<br />
<br />
 <br />
<strong class='bbc'>Conclusion</strong><br />
 That's it for just now. A public method could easily be added that loads the header from an existing PAK file and, using that data decrypt and load the contained file-table. With that information you could easily, say, decrypt and extract files to a specified directory and dynamically load them. The way I envision using it would be to dynamically create BYTE arrays within my program the same size as the file I want to utilise and copy the data from the PAK (unencrypted) in to this array. I could then use "load from memory" functions (like D3DXLoadMeshFromXInMemory() or D3DXCreateTextureFromFileInMemory() ) to work with the data. LUA scripts would be perfect here to tell me which files I need to load and, as an example, you could load all the files you need using this method "between levels". I could always write this load function later on if anybody desires it. I hope you find this useful and that it can be a source of inspiration for your own projects.<br />
<br />
]]></description>
		<pubDate>Sat, 06 Sep 2003 10:52:01 +0000</pubDate>
		<guid isPermaLink="false">0a2090e24b6ae62b0b0fcaa67a72b5a0</guid>
	</item>
	<item>
		<title>How to Write a Simple Maya Model Exporter</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/how-to-write-a-simple-maya-model-exporter-r1906</link>
		<description><![CDATA[<a href='#1'>A Simple Example</a><br />
<a href='#2'>Maya API Basics</a><br />
<a href='#3'>Vertices</a><br />
<a href='#4'>Polygons</a><br />
<a href='#5'>Materials</a><br />
<a href='#6'>Animations</a><br />
<br />
Perhaps you have just been asked to write a data exporter for Maya. Odds are you are not working for one of those huge long term game projects that can afford to have several people dedicated 100% to writing export tools, but rather you have a few days to put together a usable tool that will rip some animated character models out of a .mb file. You went to look at all 5000 manuals that ship with Maya, and surprise! None of them appear to be Maya programming manuals. <br />
<br />
If you have not done it already you should install a copy of Maya on your system. Install everything the artists will be using. At first I thought maybe all I needed to install was the "developers kit" part of Maya. You should save yourself the trouble and install everything, including the dev kit. Make sure to install all the documentation too. The API is not documented in the paper manuals, but is in the help files. <br />
<br />
In this article I have put together all the things you need to know to get that tool done fast. You can worry about the finer points of the Maya API later. <br />
<br />
Maya data exporting tools can be written either as plug-ins or as external programs. With a plug-in you could easily make a module that presents an artist with a button right inside of Maya that they simply press and a data file pops out of Maya in a format compatible with your game engine. The other way is to have the artists save everything as a native Maya file, and to write an external tool that can be run later, maybe as part of your make system, to convert the Maya (.mb or .ma ) files to your own format. Most of the Maya programming examples are of the plug-in type. This article will show you how to write an "application"-style exporter. <br />
<br />
Maya is essentially a set of DLLs that modify a specialized database. On top of that there are a whole bunch of plugins and .mel scripts. The Maya program itself appears to be a thin user interface veneer to control the real system. Writing a stand alone application means simply linking with the same Maya DLLs as the Maya program itself uses. <br />
<br />
Using Maya's own DLL's to interpret Maya files is the best way. Don't attempt to write your own Maya file parser from scratch. It's tempting at first, when you don't understand the seemingly bizarre Maya API, and its weird data structures, and the data you want it tantalizingly easy to see in a Maya ASCII file. ( You can save any file in an ASCII version and just browse through the data structures and sure enough you will find all your vertices, transforms and meshes all pretty clearly expressed in the file ). The problem with writing your own file parser is that once you do that you will have to keep expanding your file parser forever to support more and more of Maya's features, and your artists are sure to be frustrated if they can't use a feature simply because your homegrown file reader is not yet ready to process that data type. Besides it's a complete waste of time, because even though the API is bizarre, it's not that hard to understand and is pretty forgiving. The downside is that by doing this, any computer that needs to run the exporter must have a Maya license. ( Hey Alias|Wavefront, how about a low cost license to Maya for those workstations that only need to run an exporter? )   <br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'><a name='1'></a>A Simple Example</strong></span><br />
<br />
It's easy to write a small program that tells Maya to load a file and let you wander through its data structures:  <br />
<br />
[indent]<pre class='prettyprint'>// initialize Maya, before any Maya operations are performed.<br />// You might do this in main for example:<br />void main()<br />{<br />   MStatus stat = MLibrary::initialize ( "myExporter" );<br />   if ( !stat )<br />      return false;<br /><br />   // figure out the file name to open<br />   char* fileName = getFileNameToLoad();<br /><br />   // prepare Maya to read a new scene file<br />   MFileIO::newFile( true );<br /><br />   // read the scene file<br />   stat = MFileIO::open( fileName );<br />   if ( !stat )<br />      return false;<br /><br />   // remove any temporary data created by Maya while loading<br />   // things like the undo list which we won't be using<br />   stat = MGlobal::executeCommand( "delete -ch" );<br />   if ( !stat )<br />      return false;<br /><br />   // iterate through all the nodes in the DAG, and print out their names<br />   MItDag dagIter( MItDag::kBreadthFirst, MFn::kInvalid, &stat );<br />   for ( ; !dagIter.isDone(); dagIter.next())<br />   {<br />      MDagPath dagPath;<br />      stat = dagIter.getPath( dagPath );<br /><br />      cerr &lt;&lt; "Found DAG Node: "<br />   		&lt;&lt; dagPath.fullPathName().asChar()<br />   		&lt;&lt; endl;<br />   }<br /><br />   // now shut down Maya, or if you want to process another file,<br />   // just make another call to MFileIO::newFile(), and MFileIO::open()<br />   MLibrary::cleanup();<br />}</pre>[/indent]  Compile it, and link it with these .DLLs:  <br />
<br />
[indent]<pre class='prettyprint'>Foundation.lib OpenMaya.lib</pre>[/indent]  As you use more of Maya's features in your exporter you will need to link with more of its .DLLs. You can either let the link errors be your guide, or you can just link with everything and forget about it. Be aware that linking with everything may mean that people running your exporter may need to have a license to the full Maya, instead of just a license for Maya Builder.   <br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'><a name='2'></a>Maya API Basics</strong></span><br />
<br />
Great, you finished the entire input side of your exporter! Now you can goof-off the rest of the week because you already got half your work on the exporter done, right? Ok, no, you can't. Look at that crazy API. ( You can find the Maya API documentation in the help files under maya/docs/en_US/html/DevKit/Dev_Tools_TOC.html ) It's not even clear where you start. How do you even get a reference to the scene graph, or its root object? To understand these things you should take the time to read the <a href='http://www.oroboro.com/rafael/algorithms/mayaguide/downloads/api_whitepaper_oct_2001.pdf' class='bbc_url' title='External link' rel='nofollow external'>Maya API White Paper</a>. It's kind of long and boring and you might be tempted not to read it, but trust me, you should read it. It's actually not that long, about 10 pages, and everything is much clearer after that. <br />
<br />
But you didn't go read it did you? Ok, I'll tell you whats in it, but then go back and read it later. <br />
<br />
The central data structure in Maya is the DAG, or Directed Acyclic Graph. It is what is known to almost all programmers as a "tree". Much of the data you are interested in is expressed as nodes of data on this tree. Each node has a type. Each one has a parent node ( except for the root node ), and each node may have an arbitrary number of children. There are hundreds of types of nodes, and at least in theory, any node can be the parent or the child of a node of any type. The DAG is guaranteed to be a tree. So there are no cycles in it. If you visit the nodes using an orderly tree walking algorithm you can visit every node, and you won't have to worry about infinite loops. Not all of the data is stored in the DAG, but vertices, meshes, transforms, and a model's skeletal system are stored in the DAG. <br />
<br />
The other data structure, far scarier, is the DG or Dependency Graph. Like the DAG, this is a set of nodes that refer to each other, but here there are no restrictions. DG nodes can refer to any other node, and cycles are possible. This is where the textures, materials, and animation information is stored. Technically the DAG is a subset of the DG, but getting data out of the DG is somewhat more complicated than getting stuff out of the DAG, so it's convenient to think about nodes that are in the DAG, and then all the other nodes. <br />
<br />
Finally, the way the API works is unlike anything you are probably used to. There are two major object types in the Maya API: dependency nodes and function sets. There are a large number of "dependency node" objects, each is a different type of handle to a node in the DG or DAG. Think of them as pointers into the DG. The different kinds allow you to refer to nodes with greater or lesser specificity and to iterate over the nodes in different ways. ( <em class='bbc'>MItDag</em> iterates over the DAG, <em class='bbc'>MItDepenencyNodes</em> iterates over all the nodes in the DG - including all the DAG nodes ). <br />
<br />
The function set objects represent interfaces to the nodes. You construct these interfaces by calling that function set's constructor with a node reference as an argument to its constructor. Not every node supports every function set, but it's legal to construct any function set using any node, the function set object will just be created in an invalid state which should be checked. A typical function set is <em class='bbc'>MFnMesh</em>, which allows you to extract mesh information ( vertices, polygons etc. ) from a node that contains this kind of information. <br />
<br />
Writing an exporter requires you to pretty much just iterate over the DG or DAG in various ways tracking down nodes, and then using them to create function sets that allow you to extract the data. <br />
<br />
It's also good to remember that almost all of the objects that you can create through the Maya API are handles to the real objects that are linked into the DG and that Maya manages itself. You normally create all these objects as temporaries and let them get cleaned up automatically when they go out of scope. Simple.   <br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'><a name='3'></a>Extracting Vertices</strong></span><br />
<br />
So let's write a quick function to find all the vertices in a model. We will assume that we are interested in extracting all the vertices in the file:  <br />
<br />
[indent]<pre class='prettyprint'>void extractVertices()<br />{<br />   // we assume here that Maya has been initialized and the file in<br />   // question has already been loaded.<br /><br />   MStatus stat;<br />   MItDag dagIter( MItDag::kBreadthFirst, MFn::kInvalid, &stat );<br /><br />   for ( ; !dagIter.isDone(); dagIter.next())<br />   {<br />      MDagPath dagPath;<br />      stat = dagIter.getPath( dagPath );<br /><br />      if ( stat )<br />      {<br /> 		MFnDagNode dagNode( dagPath, &stat );<br /><br /> 		// this object cannot be intermediate, and it must be a mesh<br /> 		// and it can't be a transform.<br /> 		// Intermediate objects are special meshes<br /> 		// that are not drawn used for mesh morphs or something.<br /> 		if ( dagNode.isIntermediateObject()) continue;<br /> 		if ( !dagPath.hasFn( MFn::kMesh )) continue;<br /> 		if ( dagPath.hasFn( MFn::kTransform )) continue;<br /><br /> 		MFnMesh fnMesh( dagPath );<br /><br /> 		// get the vertices that are part of the current mesh<br /> 		MPointArray vertexList;<br /> 		fnMesh.getPoints( vertexList, MSpace::kWorld );<br /><br /> 		// iterate through all the vertices<br /> 		for ( u32 i = 0; i &lt; vertexlist.length(); i++ )<br /> 		{<br />            vertexlist&#91;i&#93;.cartesianize();<br />            mpoint point = vertexlist&#91;i&#93;;<br /><br />            // here is your data... now go do whatever you want with<br />            // it. if you need a unique identifier for this vertex,<br />            // use it's index in the mesh, and some kind of mesh id.<br />            // these stay constant while exporting ( so long as the file is<br />            // not edited )<br />            processvertex( point.x, point.y, point.z );<br /> 		}<br />      }<br />   }<br />}</pre>[/indent]  The code is pretty self explanatory. dagIter iterates through all the nodes in the DAG, where your vertices are. Everytime you find a node that supports the <em class='bbc'>MFn::kMesh</em> type, and is not a transform, or an intermediate node, then you use it to make an <em class='bbc'>MFnMesh</em> object, and extract vertices. Notice when go to get the vertices themselves, you request what space you want them represented in. <em class='bbc'>MSpace::kWorld</em> will convert the vertex into world space for you ( by multiplying the vertex by all the transforms from the root of the DAG on down ). You can also ask it to give you the vertices in any number of local spaces if you are extracting skeletal data as well.   <br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'><a name='4'></a>Extracting Polygons</strong></span><br />
<br />
Extracting polygons is similarly straight-forward:  <br />
<br />
[indent]<pre class='prettyprint'>void extractPolygons()<br />{<br />   MStatus stat;<br />   MItDag dagIter( MItDag::kBreadthFirst, MFn::kInvalid, &stat );<br /><br />   for ( ; !dagIter.isDone(); dagIter.next())<br />   {<br />      MDagPath dagPath;<br />      stat = dagIter.getPath( dagPath );<br /><br />      if ( stat )<br />      {<br /> 		MFnDagNode dagNode( dagPath, &stat );<br /><br /> 		if ( dagNode.isIntermediateObject()) continue;<br /> 		if ( !dagPath.hasFn( MFn::kMesh )) continue;<br /> 		if ( dagPath.hasFn( MFn::kTransform )) continue;<br /><br /> 		// get the mesh and all its vertices<br /> 		MFnMesh fnMesh( dagPath );<br /> 		MPointArray vertexList;<br /> 		fnMesh.getPoints( vertexList, MSpace::kWorld );<br /><br /> 		// now iterate over all the polygons in the mesh<br /> 		MItMeshPolygon piter( dagPath, comp );<br /> 		for ( ; !piter.isDone(); piter.next())<br /> 		{<br />            // for each polygon you can get the indices of<br />            // each of its vertices in the vertex list above<br />            MIntArray vertexIdxs;<br />            piter.getVertices( vertexIdxs );<br /><br />            if ( vertexIdxs.length() == 3 )<br />            {<br />   			// process a triangle<br />   			MPoint point0 = vertexList&#91;vertexIdxs&#91;0&#93;&#93;;<br />   			MPoint point1 = vertexList&#91;vertexIdxs&#91;1&#93;&#93;;<br />   			MPoint point2 = vertexList&#91;vertexIdxs&#91;2&#93;&#93;;<br /><br />   			processTriangle( point0, point1, point2 );<br />            }<br /> 		}<br />      }<br />   }<br />}</pre>[/indent]  From this basic code you can get a great deal of other information. You can query each vertex for light and texture coordinate information for example. What you can't easily get this way are the textures themselves, or the color of each material. This stuff is not in the DAG and must be extracted another way. In Maya all mesh elements can be associated with a material. The material can be something very simple, like a single lambert shaded color, or something much more complex, like a hierarchy of materials that include various light models, textures, transparencies etc. It can get pretty complicated and I haven't needed to understand all the intricacies.   <br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'><a name='5'></a>Extracting Materials</strong></span><br />
<br />
Getting a single material associated with a polygon face is a little trickier than the code above but still not too bad. The trick is that this time you can't just iterate over the DAG to find the polygons, but rather you have to iterate over the whole DG to find all the materials first, and then use the materials to find all the polygons each material is associated with.  <br />
<br />
[indent]<pre class='prettyprint'>bool extractMaterials()<br />{<br />   MStatus stat;<br />   MItDag dagIter( MItDag::kBreadthFirst, MFn::kInvalid, &stat );<br /><br />   for ( ; !dagIter.isDone(); dagIter.next())<br />   {<br />      MDagPath dagPath;<br />      stat = dagIter.getPath( dagPath );<br /><br />      if ( stat )<br />      {<br /> 		MFnDagNode dagNode( dagPath, &stat );<br /><br /> 		if ( dagNode.isIntermediateObject()) continue;<br /> 		if ( !dagPath.hasFn( MFn::kMesh )) continue;<br /> 		if ( dagPath.hasFn( MFn::kTransform )) continue;<br /><br /> 		MFnMesh fnMesh( dagPath );<br /><br /> 		// Here is the trick, get all the nodes connected to this<br /> 		// mesh, whether they are on the DAG or not. This will<br /> 		// include all the materials.<br /> 		unsigned instanceNumber = dagPath.instanceNumber();<br /> 		MObjectArray sets;<br /> 		MObjectArray comps;<br /><br /> 		fnMesh.getConnectedSetsAndMembers( instanceNumber, sets,<br />                                   			comps, true );<br /><br /> 		// iterate over all the connected sets and look for materials<br /> 		{ for ( u32 i = 0; i &lt; sets.length(); i++ )<br /> 		{<br />            mobject set = sets&#91;i&#93;;<br />            mobject comp = comps&#91;i&#93;;<br /><br />            mfnset fnset( set );<br />            mfndependencynode dnset( set );<br /><br />            mobject ssattr = dnset.attribute( mstring( "surfaceShader" ) );<br /><br />            mplug ssplug( set, ssattr );<br /><br />            mplugarray srcplugarray;<br />            ssplug.connectedto( srcplugarray, true, false );<br /><br />            if ( srcplugarray.length() == 0 ) continue;<br /><br />            // this object contains a reference to a shader, or<br />            // material, so we might call our own function to write<br />            // that material to our own data structure for later export,<br />            // and return a material index so we can attach that index<br />            // to all the polygons we are going to extract below.<br />            mobject srcnode = srcplugarray&#91;0&#93;.node();<br />            u32 matidx = makematerial( srcnode );<br /><br />            // we might want to stop processing this node right now if<br />            // it is a material our exporter does not support<br />            if ( material_is_not_supported( matidx )) continue;<br /><br />            // otherwise, let's iterate over all the polygons that<br />            // are colored with this material<br />            mitmeshpolygon piter( dagpath, comp );<br />            for ( ; !piter.isdone(); piter.next())<br />            {<br />   			mintarray vertexidxs;<br />   			piter.getvertices( vertexidxs );<br /><br />   			// jump to our own code to export a polygon with a material<br />   			writepolygon( vertexidxs, matidx );<br />            }<br /> 		}<br />      }<br />   }<br />}</pre>[/indent]  Extracting information from a material node itself is pretty simple. For example let's strip out all the information for a phong shader node:  <br />
<br />
[indent]<pre class='prettyprint'>void makeMaterial( MObject& srcNode )<br />{<br />   if ( srcNode.hasFn( MFn::kPhong ))<br />   {<br />      MFnPhongShader phong( srcNode );<br /><br />      cerr &lt;&lt; "Found phong shader: &#092;""<br />   		&lt;&lt; phong.name().asChar() &lt;&lt; "&#092;" &lt;&lt; endl;<br /><br />      // extract all the phong parameters:<br />      MColor glowColor 	= phong.incandescence();<br />      MColor diffuseColor  = phong.color() * phong.diffuseCoeff();<br />      MColor specularColor = phong.specularColor();<br />      Double cosinePower   = phong.cosPower();<br />      MColor transColor    = phong.transparency();<br /><br />      // now build a material, and write it out..<br />   }<br />}</pre>[/indent]   <br />
<span style='font-size: 18px;'><strong class='bbc'><a name='6'></a>Extracting Animation Data</strong></span><br />
<br />
Getting animation information out of Maya involves a little trickery also. Essentially you want to extract information out of the DG at a given time, and then you want to alter the time parameter for each frame. There are several problems. First is how to determine where the keyframes are. Your data will either  <br />
<ul class='bbc'><li>have been animated in Maya with keyframes carefully set up by your animator for each game frame, in which case you just need to find the time for each keyframe.</li><li>Or the data has been animated without keyframes, and you only need to  evaluate it at a the desired frequency ( e.g. 60 fps ) over the length  of the animation.</li><li>Another way of course is that you will be modeling motion in your  game in a way similar to how Maya does it and you just want to extract  Maya's own data representations for motion directly ( for example you  may just want to grab the motion's actual spline parameters ).</li></ul>I can only help you with the first two ways. The following code will find all the key frames, and the length of an animation:  <br />
<br />
[indent]<pre class='prettyprint'>void findFrames()<br />{<br />   MItDag dagIter( MItDag::kBreadthFirst, MFn::kInvalid, &stat );<br />   MTime maxKeyTime = 0;<br /><br />   for ( ; !dagIter.isDone(); dagIter.next())<br />   {<br />      MDagPath dagPath;<br />      stat = dagIter.getPath( dagPath );<br /><br />      MFnDagNode dn( dagPath );<br /><br />      // find all the motion nodes<br />      MItDependencyGraph dgIter( dagPath.node(),<br />                             	MFn::kAnimCurve,<br />                             	MItDependencyGraph::kUpstream,<br />                             	MItDependencyGraph::kBreadthFirst,<br />                             	MItDependencyGraph::kNodeLevel,<br />                             	&stat );<br />      if ( stat )<br />      {<br />     	// get all the keyframe times<br />     	for ( ; !dgIter.isDone(); dgIter.next())<br />     	{<br />            MObject anim = dgIter.thisNode( &stat );<br />            MFnAnimCurve animCurve( anim, &stat );<br /><br />            // found some keyframe information<br />            if ( MS::kSuccess == stat )<br />            {<br />           	u32 numKeys = animCurve.numKeyframes( &stat );<br />           	for ( u32 currKey = 0; currKey &lt; numkeys; currkey++ )<br />           	{<br />                  // truncating values here...<br />                  mtime keytime = animcurve.time( currkey, &stat );<br /><br />                  // store this key frame time somewhere.<br />                  storekeytime( keytime );<br /><br />                  // and store the maximum frame time<br />                  if ( time &gt; maxKeyTime )<br />                 	maxKeyTime = time;<br />           	}<br />            }<br />     	}<br />      }<br />   }<br />}</pre>[/indent]  <em class='bbc'>maxKeyTime</em> hold the last keyframe time, and the length of an animation. <em class='bbc'>storeKeyTime</em> is a call to your own code to store a given keyframe time so you can evaluate the animation at that time later. Remember that probably many duplicate times will be inserted into that array. There are quite likely many <em class='bbc'>MFnAnimCurve</em> nodes in the DG with the same keyframe times to animate different parts of the model. You can either chose to use the keyframe times as they are stored, or you can chose to use the last <em class='bbc'>maxKeyTime</em> and iterate over fixed steps from 0 to that time. This is something you should probably discuss with those people responsible for making the animations. <br />
<br />
The last part of the problem is how to evaluate a model at a given time, to extract all the vertices, or transforms for a given animation. For this you use the handy <em class='bbc'>MAnimControl</em> object, like so:  <br />
<br />
[indent]<pre class='prettyprint'>void processAnimationFrame( MTime& time )<br />{<br />   // create a Dag iterator<br />   MStatus stat;<br />   MItDag dagIter( MItDag::kBreadthFirst, MFn::kInvalid, &stat );<br /><br />   // here is the magic animation time setting object. Set it to the<br />   // desired time, and presto...<br />   MAnimControl animctrl;<br />   animctrl.setCurrentTime( time );<br /><br />   for ( ; !dagIter.isDone(); dagIter.next())<br />   {<br />      MDagPath dagPath;<br />      stat = dagIter.getPath( dagPath );<br /><br />      if ( stat )<br />      {<br />     	MFnDagNode dagNode( dagPath, &stat );<br /><br />     	if ( dagNode.isIntermediateObject()) continue;<br />     	if ( !dagPath.hasFn( MFn::kMesh )) continue;<br />     	if ( dagPath.hasFn( MFn::kTransform )) continue;<br /><br />     	// your mesh object... and it should be<br />     	MFnMesh fnMesh( dagPath );<br /><br />     	// get the vertices that are part of the current mesh<br />     	MPointArray vertexList;<br />     	fnMesh.getPoints( vertexList, MSpace::kWorld );<br /><br />     	// iterate through all the vertices<br />     	for ( u32 i = 0; i &lt; vertexlist.length(); i++ )<br />     	{<br />            vertexlist&#91;i&#93;.cartesianize();<br />            mpoint point = vertexlist&#91;i&#93;;<br /><br />            // here is your data, but this time it should be different<br />            // for each time at which you evaluate it. you should be<br />            // able to get tranform information over time in a similar<br />            // way.<br />            processvertex( point.x, point.y, point.z );<br />     	}<br />      }<br />   }<br />}</pre>[/indent]  And there you have it, everything you need to know to extract basic model information out of Maya. <br />
<br />
I have not found very many Maya API programming tutorials on the net. There is at least one really great site with <a href='http://www.ewertb.com/maya/api/' class='bbc_url' title='External link' rel='nofollow external'>Maya programming tutorials</a> run by Bryan Ewert <br />
<br />
Maya is a Registered Trademark of <a href='http://www.aw.sgi.com' class='bbc_url' title='External link' rel='nofollow external'>Alias|wavefront</a>.]]></description>
		<pubDate>Fri, 18 Apr 2003 16:09:23 +0000</pubDate>
		<guid isPermaLink="false">d871c387c0f0eac2c553c7c4d59796f9</guid>
	</item>
	<item>
		<title>Using Text-To-Speech as a Game Programming Tool</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/using-text-to-speech-as-a-game-programming-tool-r1904</link>
		<description><![CDATA[The purpose of this article is to introduce the use of Microsoft's Speech API (SAPI) 5.1 as an effective tool in game development. It is necessary to have the SAPI 5.1 SDK installed, and have the library/header paths set in VC++. An understanding of C++, object-oriented programming, and Win32 programming is recommended. SAPI 5.1 is a COM based API, and so an understanding of COM would be an asset, but is not essential.<br />
<br />
<em class='bbc'> <strong class='bbc'>Note:</strong> This article will be using Visual C++ 6.0, on the Win32 platform. The source code for this article is available at the bottom of this page.</em><br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Introduction</strong></span><br />
<br />
The first thing I should tell you is my reason for writing this article. When I sobered up this morning - and inevitably started coding - I was quite annoyed, because I had to keep typing in the message box function, and lots of string formatting garbage. The repetition - without production - was really getting to me. So then, I thought to myself: "Hey, wouldn't it be cool if I could make the computer talk to me instead?" Later on, I realized that it would also save me a lot of time, since all of the string formatting could be done transparently, and I would no longer have to hit 'Enter' whenever a message appeared. Or did I think of it yesterday? It's all a real blur…<br />
<br />
 Anyway, all joking aside, most games are Win32 applications, and if you've ever programmed in Win32, the first thing you notice is that you don't have the luxury of console input and output. This, to say the least, is not going to help… ever. Now, you could just stick with the tried and true message boxes, but, as I've already said, that can get tedious. The way I see it, this situation is analogous to the difference between <span style='font-family: Courier New'><span style='color: #000080'>printf()</span></span> and cout. They are both fine for displaying intrinsic types, but cout allows you to output all sorts of data, such as the members of a class (thanks to operator overloading) with ease. Using <span style='font-family: Courier New'><span style='color: #000080'>printf()</span></span> is also fairly easy, but it is not nearly as versatile. This is similar to the message box versus Text-To-Speech problem, because message boxes can only output text, and you have to do string formatting to output other data types. Now, as the name suggests, a Text-To-Speech engine also has this restriction, but if we put the engine in a class, we can deal with converting all data types using overloaded operators - behind the scenes. The end result is a single class object that is very flexible and easy to use, and that can be employed anywhere in lieu of a message box.<br />
<br />
 I suppose you could encapsulate a message box in a similar fashion, but, on principle, I refuse to waste a Saturday morning on something so trivial - let alone write my first article about it - when there is something much more useful available. Besides, I think making my computer talk is much more entertaining.<br />
<br />
 Accompanying this article are two samples. The first is a simple "Hello World!!!" application, and the other is a complete class, that is meant to behave in a similar manner as the <span style='font-family: Courier New'><span style='color: #000080'>cout</span></span> object. For the article itself, I will be focusing on the "Hello World!!!" application, since it is the simpler of the two. The basic concepts are the same, and so my intention is that you will go through the article, the first sample, and then understand the class (second sample) without difficulty.<br />
<br />
 I will tell you now that this is a very easy subject to pick up, and I'm quite surprised that nobody has written about it yet. Microsoft has put a lot of time and effort into developing this technology, and it would be foolish for us to not at least consider using it. There are many possible applications of Text-To-Speech engines in modern game development, but using it as a debugging tool is just the <em class='bbc'>first</em> one that I thought was worth writing about. A "Hello World!!!" application, such as the one described in this article, could be made as small as ten executable lines. All of the code for the output class is no more than 500 lines (due to white space, commenting, etc.), and I have documented the code to make it as clear as possible. There are also many tutorials and whitepapers in the SDK documentation (some of which are even shorter than this article).<br />
<br />
 I'm not going to try to explain every possible use of SAPI to you, but I do hope to spark your interest in it. Maybe I'm off in Never Never Land, but I just think this is neat.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Initialization</strong></span><br />
<br />
Now, let's get to it. The first step, in any application, is to link the needed libraries, and include the header files. As it happens, SAPI doesn't have any libraries that you need to link manually, but there is one header file, "sapi.h", which must be included. The second step is to initialize COM, and the voice interface. This is shown below:<br />
<br />
 [indent]<pre class='prettyprint'>#include &lt;sapi.h&gt;<br /><br />// The voice interface pointer<br />IspVoice* Voice = NULL;<br /><br />// Initialize COM<br />CoInitialize ( NULL );<br /><br />// Create the voice instance<br />CoCreateInstance ( CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&Voice );</pre>[/indent] The first two lines are pretty straightforward. They initialize the interface pointer and COM (the parameter is reserved, and must be NULL). The third line has a few parameters, which are explained in the below:<br />
<br />
<span style='font-family: Courier New'><strong class='bbc'><span style='color: #000080'>CLSID_SpVoice</span></strong>&nbsp;&nbsp; </span>The class identifier; for us, a speech voice class<br />
<span style='font-family: Courier New'><strong class='bbc'><span style='color: #000080'>NULL</span></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>Used with COM aggregation; we don't use it<br />
<span style='font-family: Courier New'><strong class='bbc'><span style='color: #000080'>CLSCTX_ALL</span></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>Class context; we use all class contexts<br />
<span style='font-family: Courier New'><strong class='bbc'><span style='color: #000080'>IID_IspVoice</span></strong>&nbsp;&nbsp;&nbsp;&nbsp;</span>The specific object identifier<br />
<span style='font-family: Courier New'><strong class='bbc'><span style='color: #000080'>&Voice</span></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>Address of the new interface<br />
<br />
Initialization is just that simple. The next task is making the voice interface speak to us.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Speaking</strong></span><br />
<br />
Now that the voice interface is initialized, we can use it to speak. The following code accomplishes this:<br />
<br />
 [indent]<pre class='prettyprint'>// Our text to be spoken<br />WCHAR* TextBuffer = "Hello World";<br /><br />// Use our voice interface to speak the contents of the buffer<br />Voice -&gt; Speak ( TextBuffer, SPF_DEFAULT, NULL );</pre>[/indent] You'll notice that our string is in wide characters. To convert between wide characters and ASCII character, use the "MultiByteToWideChar" function in the Win32 API. For more information, please refer to the <a href='http://msdn.microsoft.com/' class='bbc_url' title='External link' rel='nofollow external'>MSDN Library</a>.<br />
<br />
 At this point, the program will suspend and you should hear the contents of the buffer being spoken by the computer's default voice. Once the voice has finished speaking, the program continues normally. The parameters for the "Speak" member function are as follows:<br />
<br />
<span style='font-family: Courier New'><strong class='bbc'><span style='color: #000080'>TextBuffer</span></strong>&nbsp;&nbsp; </span>The text that is to be spoken<br />
<span style='font-family: Courier New'><strong class='bbc'><span style='color: #000080'>SPF_DEFAULT</span></strong>&nbsp;&nbsp;</span>Rendering flags; we don't want anything fancy, just the default<br />
<span style='font-family: Courier New'><strong class='bbc'><span style='color: #000080'>NULL</span></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Current input stream number; we don't use; we don't care<br />
<strong class='bbc'><br />
<br />
<span style='font-size: 18px;'>Shutting Down</span></strong><br />
<br />
The last thing to do is shutdown the application. The following lines accomplish this:<br />
<br />
 [indent]<pre class='prettyprint'>// Safely release the voice interface<br />if ( Voice != NULL ) Voice -&gt; Release (); Voice = NULL;<br /><br />// Shutdown COM<br />CoUninitialize ();</pre>[/indent] The first line determines if the interface is in use, and if so, it is released. The pointer is then set to NULL, just to be safe. The second line shuts down COM.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Conclusion</strong></span><br />
<br />
Now, as I said at the beginning, this is a "Hello World!!!" program, and consists of about ten lines of code, the bulk of which we have just looked at. You should be able to go through the samples, and, almost immediately, implement it in the debugging code of your games. When you build the samples, you will notice that the speech quality is rather low, more specifically, words sometimes sound distorted or choppy. I presume this is just the nature of SAPI, and will improve in future versions. However, this does not, in any way, stop us from using TTS for debugging and testing.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Last Thoughts…</strong></span><br />
<br />
This is only the first application of TTS in game development. In the future, you may wish to implement this technology in the actual game. A few ideas I'm turning over include speaking into a DirectSound or OpenAL buffer, then rendering in 3D space. Alternatively, one could use SAPI to speak into a wave file, and then simply use the file, as any regular sound effect. But that's for the future…<br />
<br />
 Anyway, I hope that I've been able to you teach something useful. This is the first article that I have written, and I would appreciate any feedback you may wish to offer. Thanks.]]></description>
		<pubDate>Wed, 16 Apr 2003 10:21:30 +0000</pubDate>
		<guid isPermaLink="false">8780a72513a774d87bae314cb01856ba</guid>
	</item>
	<item>
		<title>The Simple DirectMedia Layer from a WIN32 Persp...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/the-simple-directmedia-layer-from-a-win32-persp-r1603</link>
		<description><![CDATA[<strong class='bbc'>December 5, 2001</strong><br />
<br />
 <span style='font-size: 18px;'><strong class='bbc'>Mission Statement</strong></span><br />
 <br />
Graphics make the game/application. There is no question about this. In WIN32, if you intend to do 2D graphics, you normally have two choices: GDI or DirectDraw. GDI is slow as hell, and DirectDraw is Microsoft specific. Porting an application that uses either GDI or DirectDraw to a non-WIN32 platform can be painful.<br />
<br />
 One of your other options is SDL's video component. Keep in mind that SDL can only be used (by itself) for 2D graphics. If you want 3D graphics, though, SDL works well with OpenGL. For the purposes of this article, we are going to talk only about SDL's 2D graphical capabilities.<br />
<br />
 Here are the TGOs*(Topical Guide Objectives) for this article.<br />
<br />
TGO-02-A&nbsp;&nbsp;&nbsp;Know the basic structures SDL uses for doing graphics<br />
TGO-02-B&nbsp;&nbsp;&nbsp;Know how to get information from the SDL video subsystem.<br />
TGO-02-C&nbsp;&nbsp;&nbsp;Know how to create and destroy various types of SDL surfaces<br />
TGO-02-D&nbsp;&nbsp;&nbsp;Know how to work with SDL surfaces<br />
TGO-02-D1 Know how to do filled rectangles<br />
TGO-02-D2 Know how to get and set pixels<br />
TGO-02-D3 Know how to blit from one surface to another<br />
TGO-02-D4 Know how to use color keys<br />
TGO-02-D5 Know how to clip output <br />
<br />
*About TGOs: The concept of TGOs I borrowed from the United States Navy. In training programs, the specific knowledge that you are responsible for having are all listed in a book of Topical Guide Objectives. This book is referred to as the "Topical Guide". TGOs are good for both the reader and the author, as it lets the reader know exactly what he or she will be learning at a glance, and it reminds the author exactly what he will be covering.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Basic Structures (TGO-02-A)</strong></span><br />
<br />
As of version 1.2.3 of SDL, there are seven structures in the library that deal with the video subsystem. These are SDL_Rect, SDL_Color, SDL_Palette, SDL_PixelFormat, SDL_Surface, SDL_VideoInfo, and SDL_Overlay. Most of them do exactly what you'd expect them to do. We're going to cover the first six of these (leaving out SDL_Overlay).<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>SDL_Rect</strong></span><br />
<br />
SDL_Rect is one of the simpler structures. As you probably guessed, it abstracts a rectangular area on the screen. Here's what it looks like:<br />
<br />
 [indent]<pre class='prettyprint'>typedef struct{<br />  Sint16 x, y;<br />  Uint16 w, h;<br />} SDL_Rect;</pre>[/indent] This is a pretty standard rectangle structure, unless of course you are used to working with the WIN32 RECT structure. The x and y members contain the upper left hand corner. The w and h members contain the width and height. All of these members measure units in pixels (and never anything but pixels).<br />
<br />
 A brief note about some of the odd looking types used in SDL: because it is cross platform, the writers of SDL had to make some integral types that would be the same size no matter what platform they were used on. Considering differences between platforms and the size of the int type, they came up with things like Sint16 and Uint16, there are a number of types like these. They all take the form:<br />
<br />
 [indent]<pre class='prettyprint'>&#91;S&#124;U&#93;int&#91;n&#93;</pre>[/indent] In front of the type name, you will see either an S or a U. S stands for "signed" and U stands for "unsigned". n is a number, either 8, 16, or 32.<br />
<br />
 In the case of SDL_Rect, x and y are Sint16s, and so they range from -32768 to +32767, which is more than enough to deal with rectangular areas of the screen. The w and h members are Uint16s, and so can range from 0 to 65535. Notice that these are always non-negative, since you cannot have a rectangle with a negative width or height (unlike in the WIN32 RECT structure).<br />
<br />
 A point (x,y) lies within a rectangle (rect) if the all of the following are true:<br />
<br />
 [indent]<pre class='prettyprint'>x &gt;= rect.x<br />y &gt;= rect.y<br />x &lt; ( rect.x + rect.w )<br />y &lt; ( rect.y + rect.h )</pre>[/indent] If a rectangles w or h members are 0, it is an empty rectangle, and it contains no points whatsoever. There are absolutely no functions whatsoever for working with SDL_Rects (like the ones they have for WIN32 RECTs, like OffsetRect or UnionRect or IntersectRect), so if you need them, you have to make them yourself.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>SDL_Color</strong></span><br />
<br />
The second structure is just as simple. SDL_Color abstracts an RGB color value in an independent way. Here's what it looks like:<br />
<br />
 [indent]<pre class='prettyprint'>typedef struct{<br />  Uint8 r;<br />  Uint8 g;<br />  Uint8 b;<br />  Uint8 unused;<br />} SDL_Color;</pre>[/indent] SDL_Color is a lot like the WIN32 PALETTEENTRY or RGBQUAD structure. It contains four Uint8 values (bytes), and each member can range from 0 to 255. The r, g, and b members represent a colors red, green, and blue value. The unused member is just that--unused. Just sort of pretend it doesn't exist.<br />
<br />
 No functions exist for working with the SDL_Color structure either. If you want them, you can make your own, or just work with the members themselves. I personally like wrapping SDL_Color into a class.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>SDL_Palette</strong></span><br />
<br />
In theory, the use of palettes has gone the way of the dinosaur. Still, there are times when they are useful, and so SDL has them. Palettes in SDL are strictly 8 bit palettes, for 256 different colors. However, you can make a palette whatever size you like, for example you could make one 256 color master palette, and then 8 different 8 color palettes that you use for palette animation and overwrite only a certain portion of the actual palette with those eight colors.<br />
<br />
 The SDL_Palette structure is pretty simple:<br />
<br />
 [indent]<pre class='prettyprint'>typedef struct{<br />  int ncolors;<br />  SDL_Color *colors;<br />} SDL_Palette;</pre>[/indent] The ncolors member is the number of colors in the palette. The colors member is a pointer to an array of SDL_Color values. You have to work with these members manually, allocating and deallocating colors, setting them, and so on. SDL doesn't include any functions for working with palettes, other than those that set the palette entries for a surface.<br />
<br />
 SDL_Palette is roughly akin to IDirectDrawPalette, but without any of the encapsulation.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>SDL_PixelFormat</strong></span><br />
<br />
This structure is highly useful. It is similar in purpose to the DDPIXELFORMAT structure of DirectDraw. It describes everything you'd ever want to know about how pixels are represented for a particular surface. Here's what it looks like:<br />
<br />
 [indent]<pre class='prettyprint'>typedef struct{<br />  SDL_Palette *palette;<br />  Uint8  BitsPerPixel;<br />  Uint8  BytesPerPixel;<br />  Uint32 Rmask, Gmask, Bmask, Amask;<br />  Uint8  Rshift, Gshift, Bshift, Ashift;<br />  Uint8  Rloss, Gloss, Bloss, Aloss;<br />  Uint32 colorkey;<br />  Uint8  alpha;<br />} SDL_PixelFormat;</pre>[/indent] Everything you want to know about a pixel format is right here. First, the palette member is a pointer to an SDL_Palette, if the format has one. If not, this member will be NULL.<br />
<br />
 Next, BitsPerPixel and BytesPerPixel specify how many bits and bytes are per pixel for this format (kind of obvious from the name, no?).<br />
<br />
 The next group of members are Rmask, Gmask, Bmask, and Amask. These are the bit masks in the pixel format for each of the color components, Rmask for red, Gmask for green, Bmask for blue, and Amask for alpha. These are useful for using the & operator to isolate certain color components.<br />
<br />
 The next group, Rshift, Gshift, Bshift, and Ashift specify the bit position in the pixel that begins the color component in question. After you take a pixel value and & with the Rmask value, you can >> by the Rshift value to get it in the lowest bits of the variable.<br />
<br />
 Rloss, Gloss, Bloss, and Aloss is another group of members used for color conversion. These members contain the number of bits that are lost when starting from an 8 bit value. After you have & by the Rmask, and >> by the Rshift, you can << by Rloss, and you'll have a value in the range of 0 to 255 for your red component. This makes color conversion to and from SDL_Color values really easy.<br />
<br />
 [indent]<pre class='prettyprint'>//color is an SDL_Color, and format is an SDL_PixelFormat<br />//convert color to native format<br />Uint32 native = 0 ;<br />Uint32 red , green , blue ;<br />red = color.r &gt;&gt; format.Rloss ;<br />green = color.g &gt;&gt; format.Gloss ;<br />blue = color.b &gt;&gt; format.Bloss ;<br />red &lt;&lt;= format.Rshift ;<br />green &lt;&lt;= format.Gshift ;<br />blue &lt;&lt;= format.Bshift ;<br /><br />//convert native pixel to SDL_Color<br />red = native & format.Rmask ;<br />green = native & format.Gmask ;<br />blue = native & format.Bmask ;<br />red &gt;&gt;= format.Rshift ;<br />green &gt;&gt;= format.Gshift ;<br />blue &gt;&gt;= format.Bshift ;<br />red &lt;&lt;= format.Rloss ;<br />green &lt;&lt;= format.Gloss ;<br />blue &lt;&lt;= format.Bloss ;<br />color.r = red ;<br />color.g = green ;<br />color.b = blue ;</pre>[/indent] Pretty simple, right? Don't worry too much about this code, though. SDL provides functions that will do these things for you.<br />
<br />
 The colorkey member of SDL_PixelFormat stores the transparent color for the format. This color is in the native pixel format, not as an SDL_Color.<br />
<br />
 Finally, the alpha member is an eight bit value that stores an overall alpha value for the surface.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>SDL_Surface</strong></span><br />
<br />
Just like the IDirectDrawSurface object in DirectDraw and the HDC in GDI, the SDL_Surface is the most important structure in the SDL video subsystem. It abstracts a rectangular area of pixel data. Here's what it looks like:<br />
<br />
 [indent]<pre class='prettyprint'>typedef struct SDL_Surface {<br />  Uint32 flags;<br />  SDL_PixelFormat *format;<br />  int w, h;<br />  Uint16 pitch;<br />  void *pixels;<br />  SDL_Rect clip_rect;<br />  int refcount;<br />} SDL_Surface;</pre>[/indent] There are actually more members than this, but they should not be publicly accessed, and so are not shown.<br />
<br />
 The flags member contains a combination of bit flags that describe what type of surface this is. These flags are listed and briefly explained in table 1.<br />
<br />
<span style='font-size: 12px;'><strong class='bbc'>Table 1: Surface Flags</strong></span><strong class='bbc'>Flag</strong><strong class='bbc'>Meaning</strong>SDL_SWSURFACESurface exists in software (non-video RAM)SDL_HWSURFACESurface exists in video RAM.SDL_ASYNCBLITBlits occur asynchronously.SDL_ANYFORMAT*This flag specifies to use whatever the current display format is for the display surface.  Typically, this is used when making a windowed SDL application.SDL_HWPALETTEThe surface makes use of a hardware palette.SDL_DOUBLEBUF*The surface is double buffered (i.e. a flipping chain).SDL_FULLSCREEN*The surface is full screen.SDL_OPENGL*The surface will be used as a destination for OpenGL rendering.SDL_OPENGLBLIT*The surface will be used as a destination for OpenGL rendering.SDL_RESIZABLE*(Windowed mode only) the window is resizable.SDL_HWACCELThe surface will use hardware accelerated blitting.SDL_SRCCOLORKEYThe surface has a color key.SDL_RLEACCELThe surface is used for run-length-encoded blits.SDL_SRCALPHAThe surface has an alpha component.SDL_PREALLOCThe surface came to be from a pre-allocated array of pixel data.*only the display surface may have these flags<br />
<br />
 The format member is a pointer to an SDL_PixelFormat structure that describes the pixel format for this surface.<br />
<br />
 The w and h members describe the width and height of the surface.<br />
<br />
 The pitch contains the number of bytes per scan line for the surface. Video cards being what they are, this value is often not the same as the BytesPerPixel times the width.<br />
<br />
 The pixels is a pointer to pixel data for the surface. It is used to read or write pixels to and from the surface.<br />
<br />
 The clip_rect member is an SDL_Rect that describes the clipping area of the surface. Any writing outside of this area will not be shown.<br />
<br />
 And finally, refcount is a reference count. When a surface is created, it is set to one. You can increment it manually. It is decremented whenever the surface is freed. Once it reaches 0, the surface is deleted from memory. This member is sort of like using AddRef for COM objects.<br />
<br />
 IMPORTANT NOTE: with the exception of refcount and the data pointed to by pixels, these members should not by modified by you directly. There are functions for dealing with and changing most of them.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>SDL_VideoInfo</strong></span><br />
<br />
The last structure we're going to look at is SDL_VideoInfo. As you might expect, it contains information about the video display on the machine it is running on. Here's what it looks like:<br />
<br />
 [indent]<pre class='prettyprint'>typedef struct{<br />  Uint32 hw_available:1;<br />  Uint32 wm_available:1;<br />  Uint32 blit_hw:1;<br />  Uint32 blit_hw_CC:1;<br />  Uint32 blit_hw_A:1;<br />  Uint32 blit_sw:1;<br />  Uint32 blit_sw_CC:1;<br />  Uint32 blit_sw_A:1;<br />  Uint32 blit_fill:1;<br />  Uint32 video_mem;<br />  SDL_PixelFormat *vfmt;<br />} SDL_VideoInfo;</pre>[/indent] The closest equivalent in DirectDraw is the DDCAPS structure. SDL_VideoInfo, however, is much easier to read. Most of the members are single bits, and a value of 0 means that the feature in question is not supported, and 1 means that the feature is supported.<br />
<br />
 The hw_available indicates that you may create hardware surfaces, which naturally will be faster than software surface.<br />
<br />
 The wm_available indicates that a window manager is available. In WIN32, one is, but for other platforms, one might not be. The window manager is another subsystem of SDL that deals with some pretty basic settings for a window (if you are using windowed mode versus fullscreen).<br />
<br />
 The blit_hw, blit_hw_CC, and blit_hw_A all deal with the availability of hardware acceleration for blits between surface stored in hardware. The blit_hw bit specifies that generic hardware to hardware blits are accelerated, blit_hw_CC specifies that hardware to hardware colorkeyed blits are accelerated, and blit_hw_A specifies that hardware to hardware alpha blits are accelerated.<br />
<br />
 The blit_sw, blit_sw_CC, and blit_sw_A are much the same as the blit_hw members, except that they specify the capabilities for software to hardware blits instead.<br />
<br />
 The blit_fill member specifies that color fill operations are accelerated.<br />
<br />
 The video_mem contains, in kilobytes, the amount of video RAM for the system.<br />
<br />
 The vfmt member is a pointer to an SDL_PixelFormat. Depending on when you call it, it will contain either the "best" video format (the one with the most capabilities), or the current video format (depending on if you have already set up your display surface or not).<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Video Information (TGO-02-B)</strong></span><br />
<br />
The beautiful thing about SDL is that you don't have to gather any information about the video subsystem before using it if you don't want to. SDL will emulate anything you want. Of course, emulation is slower, but it guarantees that your application will run on any platform that has an SDL implementation.<br />
<br />
 However, if you do want information about the video system, there are a few functions that you can use. The first of these is SDL_GetVideoInfo.<br />
<br />
 [indent]<pre class='prettyprint'>SDL_VideoInfo *SDL_GetVideoInfo(void);</pre>[/indent] This function returns a pointer to an SDL_VideoInfo structure. It takes no parameters. DO NOT FREE THE POINTER RETURNED FROM THIS FUNCTION!<br />
<br />
 In order to be effective, you have to call SDL_GetVideoInfo after you have initialized the SDL video subsystem. Typically, initialization of SDL is the first line in the program. The line looks like this:<br />
<br />
 [indent]<pre class='prettyprint'>SDL_Init ( SDL_INIT_VIDEO ) ;</pre>[/indent] This single line sets up the video system and the even system (which is another topic altogether). After this call, you can call SDL_GetVideoInfo, and get information about the best pixel format to use for your system, provided you call it before you call SDL_SetVideoMode. Calling SDL_GetVideoInfo after this call, you will get the information about the current display mode.<br />
<br />
 Another thing you can look at, if you really want to, is the name of the video driver (it probably won't help you much, but its something to look at, I guess). You can retrieve it with the SDL_VideoDriverName function.<br />
<br />
 [indent]<pre class='prettyprint'>char *SDL_VideoDriverName(char *namebuf, int maxlen);</pre>[/indent] This function takes two parameters, a pointer to a string (namebuf), and an int specifying the maximum length of the string to copy (including the null-terminator). The value returned is the namebuf pointer if this function is successful, and NULL if it fails. It will only fail if you haven't initialized the video subsystem. The name of the video driver isn't particularly useful, but you might want it for some sort of log file for diagnostic purposes.<br />
<br />
 This next call is useful if you are targeting full screen applications. The function is called SDL_ListModes, and it looks like the following.<br />
<br />
 [indent]<pre class='prettyprint'>SDL_Rect **SDL_ListModes(SDL_PixelFormat *format, Uint32 flags);</pre>[/indent] This function takes a pointer to an SDL_PixelFormat (or NULL to simply use the value retrieved by SDL_GetVideoInfo ( )->vfmt), and a combination of flags ( the same flags that are value for SDL_Surfaces). It spits out an array of SDL_Rect pointers that describe the various video modes that have the specified format and support the flag specified. If, for example, you need a hardware surface with double buffering, you would call SDL_ListModes in the following manner.<br />
<br />
 [indent]<pre class='prettyprint'>SDL_Rect** pModeRects = SDL_ListModes ( NULL , SDL_HWSURFACE &#124;  SDL_DOUBLEBUF ) ;</pre>[/indent] Some special notes about SDL_ListModes. First, it is a NULL terminated list of SDL_Rect* variables. Second, if all video modes accept the flag, this function will return -1 rather than a pointer. Third, if no video modes accept the flag, this function will return NULL. So, this function might be a little cumbersome to use.<br />
<br />
 A different, more directly useful function, SDL_VideoModeOK.<br />
<br />
 [indent]<pre class='prettyprint'>int SDL_VideoModeOK(int width, int height, int bpp, Uint32 flags);</pre>[/indent] This function takes the width, height, bits per pixel, and flags for a potential display surface, and determines if the match up of these values is acceptable for the display hardware. Even if they are not, you can still use the same parameters to create your display surface, and SDL will emulate for you.<br />
<br />
 If this function returns 0, then no bpp value will work for the flags specified. If the return value is non-zero, then it represents the nearest bpp that will accept the flags specified. It is best to pick one of the standard mode sizes (640x480, 800x600, 1024x768) when picking mode sizes if you are doing a full screen application. If you aren't, and the video hardware don't support that particular mode, SDL will again emulate it, by placing it on the next larger supported size, and limiting output to a rectangle in the middle of the screen. So, if you went for a 512x384 mode (which is supported on quite a bit of hardware), and the video hardware didn't support it, SDL will throw you into a 640x480 mode, and place all output in the middle 512x384.<br />
<br />
 But enough of examining video capabilities... on to creating surfaces!<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Creating and Destroying Surfaces (TGO-02-C)</strong></span><br />
<br />
Surfaces are the most important part of using SDL's video subsystem. Without them, there'd be nothing to see, and how good is an application you can't see? (Apologies to ZForm, LLC, whose clients can't read this article anyway--they make software for the blind).<br />
<br />
 The first surface you should create in any SDL based application is the display surface. You can create it with the SDL_SetVideoMode function.<br />
<br />
 [indent]<pre class='prettyprint'>SDL_Surface *SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags);</pre>[/indent] This function takes a width, height, bits per pixel, and flags, and spits out a pointer to an SDL_Surface. This pointer is to the display surface/primary surface. If you are doing a full-screen application, you will probably want to check out the modes with SDL_ListModes and/or SDL_VideoModeOK, but if you don't that's OK.<br />
<br />
 If you aren't doing a full-screen application, then you should specify 0 for bpp, and have SDL_ANYFORMAT as part of your flags. This makes SDL use the current format of the display, which makes life easier for you. In windowed mode, you can use whatever width and height you like. In WIN32, this will give you a window that has a client area of the size you requested.<br />
<br />
 After calling SDL_SetVideoMode, don't call SDL_FreeSurface on this pointer. SDL cleans up the display surface during SDL_Quit, so you don't have to worry about it.<br />
<br />
 In fact, you don't even have to store this pointer anywhere if you don't want to. You can use SDL_GetVideoSurface (it takes no parameters) to retrieve a pointer to the display surface.<br />
<br />
 Of course, you'll need more than simply a display surface to make your game, unless you plan on making a game with nothing but pixel plotting and filling rectangles. You'll need other surfaces as well.<br />
<br />
 To create a blank surface of a particular size and format, you call SDL_CreateRGBSurface.<br />
<br />
 [indent]<pre class='prettyprint'>SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth,<br />                                  Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);</pre>[/indent] To this function, you supply a size (height, width, depth--bpp), and masks for red, green, blue, and alpha, along with some flags, and this function gives you a pointer to a newly created surface that matches your specifications. Typically, you will want to use the same depth and masks as for the display surface, but even if you don't, SDL will be able to copy from one to the other, but it'll be a little slower. The only valid flags for SDL_CreateRGBSurface are SDL_HWSURFACE , SDL_SWSURFACE , SDL_SRCCOLORKEY, and SDL_SRCALPHA.<br />
<br />
 If this function fails, it returns NULL.<br />
<br />
 Another function for creating surfaces is SDL_CreateRGBSurfaceFrom. This function is much the same as SDL_CreateRGBSurface.<br />
<br />
 [indent]<pre class='prettyprint'>SDL_Surface *SDL_CreateRGBSurfaceFrom(void *pixels, int width, int height, int depth, int pitch,<br />                                      Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);</pre>[/indent] The notable differences are the lack of a flags parameter (the surface exists in system RAM), and the addition of the pixels parameter and the pitch parameter. The pixels parameter is a pointer to pixel data to use for this surface, and pitch is how many bytes exist in each scan line, which does not have to be width times depth. The other parameters are the same as for SDL_CreateRGBSurface. If this function fails, it returns NULL.<br />
<br />
 Something to keep in mind if you are using SDL_CreateRGBSurfaceFrom: the pixels parameter should not be freed until you have freed the surface, since the pixel data you supply to this function is the actual pixel data used by the surface. It does not make a copy.<br />
<br />
 The final function for creating a surface is SDL_LoadBMP. This is a damn handy function. It loads in a standard windows .bmp file onto a surface, and returns the new surface.<br />
<br />
 [indent]<pre class='prettyprint'>SDL_Surface *SDL_LoadBMP(const char *file);</pre>[/indent] This function takes a single parameter, a pointer to a string containing the name of the file you wish to load. It returns the newly created surface, or NULL if there is an error.<br />
<br />
 The SDL_LoadBMP function is a godsend. If you've worked with either DirectDraw or GDI, you know how much of a pain it can be to get a stupid bitmap loaded. In SDL, its only a single function call! If that's not reason enough to move to SDL... I don't know what is.<br />
<br />
 There are two more really cool functions that you can use to create surfaces, but they are used more for pixel format conversion rather than creating something in their own right. They take an already existing surface and create a new surface, with the same contents, but a different pixel format.<br />
<br />
 The first of these is SDL_ConvertSurface.<br />
<br />
 [indent]<pre class='prettyprint'>SDL_Surface *SDL_ConvertSurface(SDL_Surface *src, SDL_PixelFormat *fmt, Uint32 flags ) ;</pre>[/indent] The parameters are fairly straightforward. You give this function a pointer to a surface that you need converted, a pointer to the format you want it converted to, and a combinatin of flags ( these flag are the same as those used in other surface creation functions). This function creates a surface in the requested format, with the requested flags (if possible), and gives you back a pointer to a new surface. If this function fails, it'll give you NULL.<br />
<br />
 The second of these is SDL_DisplayFormat.<br />
<br />
 [indent]<pre class='prettyprint'>SDL_Surface *SDL_DisplayFormat(SDL_Surface *surface);</pre>[/indent] This function takes a surface, and converts it to the display format, so that you can make better use of hardware acceleration, if it exists. It returns a pointer to the newly converted surface, or NULL if it fails.<br />
<br />
 Typically, after calling SDL_ConvertSurface or SDL_DisplayFormat to convert a surface, you will want to destroy the old, pre-converted, surface.<br />
<br />
 Speaking of destroying surfaces, doing so is also quite easy. You simply call SDL_FreeSurface.<br />
<br />
 [indent]<pre class='prettyprint'>void SDL_FreeSurface(SDL_Surface *surface);</pre>[/indent] This function takes a pointer to a surface, and returns no values. The surface's refcount member is decremented, and if the refcount reaches 0, then the surface is deleted.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Using SDL Video (TGO-02-D)</strong></span><br />
<br />
To start with, recall the example we ended with last time (or at least something very close):<br />
<br />
 [indent]<pre class='prettyprint'>#include "SDL.h"<br /><br />enum {<br />  SCREENWIDTH = 512,<br />  SCREENHEIGHT = 384,<br />  SCREENBPP = 0,<br />  SCREENFLAGS = SDL_ANYFORMAT<br />} ;<br /><br />int main( int argc, char* argv&#91;&#93; )<br />{<br />  //initialize systems<br />  SDL_Init ( SDL_INIT_VIDEO ) ;<br /><br />  //set our at exit function<br />  atexit ( SDL_Quit ) ;<br /><br />  //create a window<br />  SDL_Surface* pSurface = SDL_SetVideoMode ( SCREENWIDTH , SCREENHEIGHT ,<br />                                         	SCREENBPP , SCREENFLAGS ) ;<br /><br />  //declare event variable<br />  SDL_Event event ;<br /><br />  //message pump<br />  for ( ; ; )<br />  {<br />    //look for an event<br />    if ( SDL_PollEvent ( &event ) )<br />    {<br />      //an event was found<br />      if ( event.type == SDL_QUIT ) break ;<br />    }<br />  }//end of message pump<br /><br />  //done<br />  return ( 0 ) ;<br />}</pre>[/indent] This is our basic shell application for SDL, and during this TGO, we will build on it. As you can see, I already have initialized SDL's video subsystem with my call to SDL_Init, and I have already set the video mode (it is currently set up for windowed mode and uses the current display format).<br />
<br />
 This application doesn't do a whole lot, other than give you a blank, black window with a border around it. You can't resize the window, but you can move it around. This program simply waits for you to quit. However, I will point out that the equivalent application in GDI or DirectDraw would be about five times as many lines as we have here.<br />
<br />
 Now we've got to make the application actually DO something. Let's get to work.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Rectangular Fills</strong></span><br />
<br />
Often, you will need a large rectangular area of a surface cleared out to a particular color. The rectangular area can be as small as a single pixel, or as large as the entire screen. The function for doing this is SDL_FillRect.<br />
<br />
 [indent]<pre class='prettyprint'>int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);</pre>[/indent] This function takes three parameters: a pointer to the destination surface, a pointer to an SDL_Rect that describes the rectangle you wish to fill, and a color (in the native pixel format of the surface). If you want to clear out the entire surface, you can use NULL for the dstrect parameter.<br />
<br />
 The surface we've got, and an SDL_Rect is easy enough to fill out. One thing we need before we can use this function is the ability to convert from a device independent color (i.e. an SDL_Color variable) into the native pixel format (and I don't want to use the code we looked at for this purpose earlier).<br />
<br />
 Luckily, SDL has such a function. It is called SDL_MapRGB.<br />
<br />
 [indent]<pre class='prettyprint'>Uint32 SDL_MapRGB(SDL_PixelFormat *fmt, Uint8 r, Uint8 g, Uint8 b);</pre>[/indent] This function takes a pointer to an SDL_PixelFormat structure, and a red, green, and blue component from 0-255, and it figures out what value works for a native pixel of that same color (or the nearest equivalent).<br />
<br />
 So, let us say we want to fill the screen with pure red. This is how we'd go about it:<br />
<br />
 [indent]<pre class='prettyprint'>SDL_FillRect ( pSurface , NULL , SDL_MapRGB ( pSurface-&gt;format , 255 , 0 , 0 ) ) ;</pre>[/indent] But we're still not done. SDL's video system doesn't automatically display any of the changes to the surface. In order to make the new data visible, we have to update the rectangle. The function for doing this is SDL_UpdateRect.<br />
<br />
 [indent]<pre class='prettyprint'>void SDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Sint32 w, Sint32 h);</pre>[/indent] This function takes four parameters: the pointer to the surface, and an x , y, w, and h values describing the rectangle to update. If you wish to update the entire surface, you can place 0 into each of x, y, w, and h, like so:<br />
<br />
 [indent]<pre class='prettyprint'>SDL_UpdateRect ( pSurface , 0 , 0 , 0 , 0 ) ;</pre>[/indent] So, let's do a quick example. Start a new project named SDLRandomFillRect (or whatever you want to call it), set it up for SDL, and put the following code into main.cpp:<br />
<br />
 [indent]<pre class='prettyprint'>#include "SDL.h"<br />#include &lt;stdlib.h&gt;<br /><br />enum {<br />  SCREENWIDTH = 512,<br />  SCREENHEIGHT = 384,<br />  SCREENBPP = 0,<br />  SCREENFLAGS = SDL_ANYFORMAT<br />} ;<br /><br />int main( int argc, char* argv&#91;&#93; )<br />{<br />  //initialize systems<br />  SDL_Init ( SDL_INIT_VIDEO ) ;<br /><br />  //set our at exit function<br />  atexit ( SDL_Quit ) ;<br /><br />  //create a window<br />  SDL_Surface* pSurface = SDL_SetVideoMode ( SCREENWIDTH , SCREENHEIGHT ,<br />                                         	SCREENBPP , SCREENFLAGS ) ;<br /><br />  //declare event variable<br />  SDL_Event event ;<br /><br />  //message pump<br />  for ( ; ; )<br />  {<br />    //look for an event<br />    if ( SDL_PollEvent ( &event ) )<br />    {<br />      //an event was found<br />      if ( event.type == SDL_QUIT ) break ;<br />    }<br /><br />    //set up random rectangle<br />    SDL_Rect rect ;<br />    rect.x = rand ( ) % ( SCREENWIDTH ) ;<br />    rect.y = rand ( ) % ( SCREENHEIGHT ) ;<br />    rect.w = rand ( ) % ( SCREENWIDTH - rect.x ) ;<br />    rect.h = rand ( ) % ( SCREENHEIGHT - rect.y ) ;<br /><br />    //fill the rectangle<br />    SDL_FillRect ( pSurface , &rect ,<br />               	SDL_MapRGB ( pSurface-&gt;format , rand ( ) % 256 ,<br />                                rand ( ) % 256 , rand ( ) % 256 ) ) ;<br /><br />    //update the screen<br />    SDL_UpdateRect ( pSurface , 0 , 0 , 0 , 0 ) ;<br />  }//end of message pump<br /><br />  //done<br />  return ( 0 ) ;<br />}</pre>[/indent] The lines in bold are new to this example (as opposed to the base shell code), if you just want to add those. Most of the lines are fairly obvious. Five of them deal with setting up the SDL_Rect variable, another does the filled rectangle, and yet another updates the display. On my display, this example runs really fast, but I've got a good video card and that's to be expected. Its output looks something like Figure 1.<br />
<br />
<p class='bbc_center'><a class='resized_img' rel='lightbox[2353ba524e55413a9e867e4abfc7195e]' id='ipb-attach-url-3685-0-69830500-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3685" title="02-01.jpg - Size: 20.45K, Downloads: 33"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-69475400-1309251570_thumb.jpg" id='ipb-attach-img-3685-0-69830500-1330208485' style='width:250;height:198' class='attach' width="250" height="198" alt="Attached Image: 02-01.jpg" /></a> <br />
<strong class='bbc'>Figure 1: Random FillRect Example Program</strong><br />
</p><br />
 Filling rectangular areas in SDL is a lot simpler than the equivalent GDI or DirectDraw code (no HBRUSH to make, no DDBLTFX structure to fill out). Just give it a rectangle, a format, and color, and you've drawn yourself a rectangle.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Pixel Plotting</strong></span><br />
<br />
In theory, you could draw pixels using SDL_FillRect, and just use a w and h of 1. That, of course, is not how the SDL_FillRect function is intended to be used, but the SDL Police won't come and stop you, and it *IS* a completely cross platform method of drawing pixels, whereas doing pixel plotting with direct memory access can have portability issues, as we shall see in a moment.<br />
<br />
 In DirectDraw, in order to start writing to the memory of a surface itself, you need to Lock the surface and Unlock it when you are done. The same is true for SDL, in general. Some surfaces never need to be locked, typically those that dwell in system memory.<br />
<br />
 How do you tell? SDL provides a macro for you called SDL_MUSTLOCK. To test a surface, you do the following:<br />
<br />
 [indent]<pre class='prettyprint'>if ( SDL_MUSTLOCK ( pSurface ) )<br />{<br />//surface must be locked for access<br />}<br />else<br />{<br />//no need to lock surface<br />}</pre>[/indent] If you don't need to lock a surface, you will typically do nothing special, and so the entire else clause above won't be there.<br />
<br />
 In order to lock a surface, you call SDL_LockSurface. In order to unlock a surface, you call SDL_UnlockSurface. I doubt either function name comes as a big surprise to you. The same sort of caveats exist for SDL locks as for DirectDraw locks. Don't lock a surface longer than you have to, and don't call any system functions while a surface is locked. Treat the locked surface time as a critical section of your code's execution. Here are the prototypes for SDL_LockSurface and SDL_UnlockSurface.<br />
<br />
 [indent]<pre class='prettyprint'>int SDL_LockSurface(SDL_Surface *surface);<br />void SDL_UnlockSurface(SDL_Surface *surface);</pre>[/indent] Each of these have only one parameter... the pointer to the surface you intend to lock. In the case of SDL_LockSurface, there is a return value. If all goes well, this return value will be 0. If there is some sort of problem, you will get -1 instead.<br />
<br />
 Something important to point out here. You can lock a surface more than once prior to unlocking it. If you do this, you need to have as many unlock calls as you have lock calls, like so:<br />
<br />
 [indent]<pre class='prettyprint'>SDL_LockSurface ( pSurface ) ;    //first lock<br />SDL_LockSurface ( pSurface ) ;    //second lock<br />SDL_UnlockSurface ( pSurface ) ;  //first unlock... surface is still locked<br />SDL_UnlockSurface ( pSurface ) ;  //second unlock... surface is now unlocked</pre>[/indent] This is just something to be aware of. Generally speaking, if you have a large operation that requires some sort of direct access to the pixels of a surface, do a lock, do the operation, and do the unlock. If you have an even larger operation that relies on other operations that lock and unlock the surface, that's ok, because locking and unlocking is recursive.<br />
<br />
 Once the surface is locked, you can begin to directly access the pixel data through the SDL_Surface's pixels member. This includes working with the pixel format of the surface as well as the pitch member of the surface.<br />
<br />
 When setting pixels, I personally like to work with a pixel format independent representation of the color, i.e the SDL_Color structure, or something very much like it. I like having red, green, and blue all represented by numbers between 0 and 255. Unfortunately, an SDL_Surface can have a variety of different formats, and so we'll need to convert from an SDL_Color structure into the native format using SDL_MapRGB. No big deal.<br />
<br />
 From there, next need to know where exactly to write to. The pixels member of SDL_Surface is a void*. I personally like to convert it to a char*, and work the on the surface as though it were like a character buffer.<br />
<br />
 The offset from the beginning of the pixels pointer depends on the x and y coordinates of the pixel you wish to set. For every value in y, you increase by the contents of the SDL_Surface's pitch member. For every value in x, you increase by the contents of the SDL_Surface's pixel format's BytesPerPixel member. Calculating the position looks something like the following.<br />
<br />
 [indent]<pre class='prettyprint'>//point to beginning of buffer<br />char* pPosition = ( char * ) pSurface-&gt;pixels ;<br /><br />//increment y<br />pPosition += ( y * pSurface-&gt;pitch ) ;<br /><br />//increment x<br />pPosition += ( x * pSurface-&gt;format-&gt;BytesPerPixel ) ;<br /><br />//pPosition now points to the proper pixel</pre>[/indent] We've got the proper position, and we've got the proper color. The only thing left is to copy the data from the color over into the buffer. This is where we meet a very small portability issue.<br />
<br />
 On WIN32 ( and many other operating systems), we can simply do the following code to copy the pixel data from the color variable into the buffer:<br />
<br />
 [indent]<pre class='prettyprint'>memcpy ( pPosition , &color , pSurface-&gt;format-&gt;BytesPerPixel ) ;</pre>[/indent] And this will work, no problem, on most of the machines that the program is likely ever to be compiled for. But then there are the oddballs. The code above relies on the fact that the target machine is little endian. On a big endian system, unless using a 32 bpp surface, you are going to get garbled colors, or black. The solution? Well, I have one in mind, but I haven't had a chance to test it out yet ( since I don't have a machine that supports SDL but has a big endian). The basic idea is that you want to reverse the order of the bytes in the color variable if the machine is big endian, and then do the writing. There are a few macros and functions in SDL that can assist with this.<br />
<br />
 So, here's a basic putpixel function. This function assumes that the surface has already been locked, or does not need locking.<br />
<br />
 [indent]<pre class='prettyprint'>void SetPixel ( SDL_Surface* pSurface , int x , int y , SDL_Color color ) <br />{<br />  //convert color<br />  Uint32 col = SDL_MapRGB ( pSurface-&gt;format , color.r , color.g , color.b ) ;<br /><br />  //determine position<br />  char* pPosition = ( char* ) pSurface-&gt;pixels ;<br /><br />  //offset by y<br />  pPosition += ( pSurface-&gt;pitch * y ) ;<br /><br />  //offset by x<br />  pPosition += ( pSurface-&gt;format-&gt;BytesPerPixel * x ) ;<br /><br />  //copy pixel data<br />  memcpy ( pPosition , &col , pSurface-&gt;format-&gt;BytesPerPixel ) ;<br />}</pre>[/indent] To retrieve a pixel, we can recycle much of our pixel setting code, because the task is simply reversed. We determine the position in the exact same way, we memcpy it into a Uint32 variable (with the same minor caveat about big endians), and then convert it to an SDL_Color variable. The function for doing that is SDL_GetRGB.<br />
<br />
 [indent]<pre class='prettyprint'>void SDL_GetRGB(Uint32 pixel, SDL_PixelFormat *fmt, Uint8 *r, Uint8 *g, Uint8 *b);</pre>[/indent] This function is much the same as SDL_MapRGB, except that this time, we send pointers to Uint8s into which are placed the various color components corresponding to the native pixel color. So, if we have a Uint32 variable called col, and an SDL_Color variable called color, this is how we would convert it.<br />
<br />
 [indent]<pre class='prettyprint'>SDL_GetRGB ( col , pSurface-&gt;format , &color.r , &color.g , &color.b ) ;</pre>[/indent] And with that, we can make a GetPixel function.<br />
<br />
 [indent]<pre class='prettyprint'>SDL_Color GetPixel ( SDL_Surface* pSurface , int x , int y ) <br />{<br />  SDL_Color color ;<br />  Uint32 col = 0 ;<br /><br />  //determine position<br />  char* pPosition = ( char* ) pSurface-&gt;pixels ;<br /><br />  //offset by y<br />  pPosition += ( pSurface-&gt;pitch * y ) ;<br /><br />  //offset by x<br />  pPosition += ( pSurface-&gt;format-&gt;BytesPerPixel * x ) ;<br /><br />  //copy pixel data<br />  memcpy ( &col , pPosition , pSurface-&gt;format-&gt;BytesPerPixel ) ;<br /><br />  //convert color<br />  SDL_GetRGB ( col , pSurface-&gt;format , &color.r , &color.g , &color.b ) ;<br />  return ( color ) ;<br />}</pre>[/indent] And now time for another example. Create a project, and call it something like SDLRandomPixels. Place the following code into main.cpp.<br />
<br />
 [indent]<pre class='prettyprint'>#include "SDL.h"<br />#include &lt;stdlib.h&gt;<br />#include &lt;memory.h&gt;<br /><br />enum {<br />  SCREENWIDTH = 512,<br />  SCREENHEIGHT = 384,<br />  SCREENBPP = 0,<br />  SCREENFLAGS = SDL_ANYFORMAT<br />} ;<br /><br />void SetPixel ( SDL_Surface* pSurface , int x , int y , SDL_Color color ) ;<br />SDL_Color GetPixel ( SDL_Surface* pSurface , int x , int y ) ;<br />int main( int argc, char* argv&#91;&#93; )<br />{<br />  //initialize systems<br />  SDL_Init ( SDL_INIT_VIDEO ) ;<br /><br />  //set our at exit function<br />  atexit ( SDL_Quit ) ;<br /><br />  //create a window<br />  SDL_Surface* pSurface = SDL_SetVideoMode ( SCREENWIDTH , SCREENHEIGHT ,<br />                                         	SCREENBPP , SCREENFLAGS ) ;<br /><br />  //declare event variable<br />  SDL_Event event ;<br /><br />  //message pump<br />  for ( ; ; )<br />  {<br />    //look for an event<br />    if ( SDL_PollEvent ( &event ) )<br />    {<br />      //an event was found<br />      if ( event.type == SDL_QUIT ) break ;<br />    }<br /><br />    //pick a random color<br />    SDL_Color color ;<br />    color.r = rand ( ) % 256 ;<br />    color.g = rand ( ) % 256 ;<br />    color.b = rand ( ) % 256 ;<br /><br />    //lock the surface<br />    SDL_LockSurface ( pSurface ) ;<br /><br />    //plot pixel at random location<br />    SetPixel ( pSurface , rand ( ) % SCREENWIDTH , rand ( ) % SCREENHEIGHT , color ) ;<br /><br />    //unlock surface<br />    SDL_UnlockSurface ( pSurface ) ;<br /><br />    //update surface<br />    SDL_UpdateRect ( pSurface , 0 , 0 , 0 , 0 ) ;<br />  }//end of message pump<br /><br />  //done<br />  return ( 0 ) ;<br />}<br />void SetPixel ( SDL_Surface* pSurface , int x , int y , SDL_Color color ) <br />{<br />  //convert color<br />  Uint32 col = SDL_MapRGB ( pSurface-&gt;format , color.r , color.g , color.b ) ;<br /><br />  //determine position<br />  char* pPosition = ( char* ) pSurface-&gt;pixels ;<br /><br />  //offset by y<br />  pPosition += ( pSurface-&gt;pitch * y ) ;<br /><br />  //offset by x<br />  pPosition += ( pSurface-&gt;format-&gt;BytesPerPixel * x ) ;<br /><br />  //copy pixel data<br />  memcpy ( pPosition , &col , pSurface-&gt;format-&gt;BytesPerPixel ) ;<br />}<br />SDL_Color GetPixel ( SDL_Surface* pSurface , int x , int y ) <br />{<br />  SDL_Color color ;<br />  Uint32 col = 0 ;<br /><br />  //determine position<br />  char* pPosition = ( char* ) pSurface-&gt;pixels ;<br /><br />  //offset by y<br />  pPosition += ( pSurface-&gt;pitch * y ) ;<br /><br />  //offset by x<br />  pPosition += ( pSurface-&gt;format-&gt;BytesPerPixel * x ) ;<br /><br />  //copy pixel data<br />  memcpy ( &col , pPosition , pSurface-&gt;format-&gt;BytesPerPixel ) ;<br /><br />  //convert color<br />  SDL_GetRGB ( col , pSurface-&gt;format , &color.r , &color.g , &color.b ) ;<br />  return ( color ) ;<br />}</pre>[/indent] Again, the code in bold is the code that has been added to the basic shell application. This example starts placing dots of random colors onto the wind&#111;w. When it runs, it looks somewhat like figure 2.<br />
<br />
<p class='bbc_center'><a class='resized_img' rel='lightbox[2353ba524e55413a9e867e4abfc7195e]' id='ipb-attach-url-3686-0-69852400-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3686" title="02-02.jpg - Size: 94.53K, Downloads: 31"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-59790600-1309251758_thumb.jpg" id='ipb-attach-img-3686-0-69852400-1330208485' style='width:250;height:198' class='attach' width="250" height="198" alt="Attached Image: 02-02.jpg" /></a><br />
<strong class='bbc'>Figure 2: Random Pixels Demo</strong><br />
</p><br />
 Once you can plot a pixel, you can do just about anything, including drawing lines, circles, rectangular frames, and so on. Doing all of that stuff is naturally beyond the scope of this article. I get you as far as plotting pixels.<br />
<br />
 <span style='font-size: 14px;'><strong class='bbc'>Blitting</strong></span><br />
<br />
The primary use of SDL_Surfaces is not to fill rectangles nor to plot pixels. The main task is to copy rectangular sections from one surface to another, much like GDI's BitBlt function and DirectDraw's Blt or BltFast function. The function for doing that is SDL_BlitSurface.<br />
<br />
 [indent]<pre class='prettyprint'>int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);</pre>[/indent] This function takes four parameters, the source surface, a source rectangle, a destination surface, and a destination rectangle. It returns 0 if everything is OK, and -1 if there was a problem. If the pointers to either rectangle are NULL, then the entire surface is assumed to be the source or destination area. Naturally, you need two surfaces in order to perform a blit, although you can use the same for both source and destination, at least in theory. The documentation warns that you should not call SDL_BlitSurface on a surface that is locked. So, time (already) for another quick example: the Amazing Bouncing Ball Demo of Death™!<br />
<br />
 Start yourself a new project, name it SDLBouncingBall or something just as clever, and place the following code into main.cpp. Also, make a small bitmap that is 32x32 pixels in size, draw a circle in it, and save it as ball.bmp.<br />
<br />
 [indent]<pre class='prettyprint'>#include "SDL.h"<br /><br />enum {<br />  SCREENWIDTH = 512,<br />  SCREENHEIGHT = 384,<br />  SCREENBPP = 0,<br />  SCREENFLAGS = SDL_ANYFORMAT<br />} ;<br /><br />int main( int argc, char* argv&#91;&#93; )<br />{<br />  //initialize systems<br />  SDL_Init ( SDL_INIT_VIDEO ) ;<br /><br />  //set our at exit function<br />  atexit ( SDL_Quit ) ;<br /><br />  //create a window<br />  SDL_Surface* pSurface = SDL_SetVideoMode ( SCREENWIDTH , SCREENHEIGHT ,<br />                                         	SCREENBPP , SCREENFLAGS ) ;<br />  //load bitmap<br />  SDL_Surface* pBitmap = SDL_LoadBMP ( "ball.bmp" ) ;<br /><br />  //source and destination rectangles<br />  SDL_Rect rcSrc , rcDst ;<br />  rcSrc.w = pBitmap-&gt;w ;<br />  rcSrc.h = pBitmap-&gt;h ;<br />  rcSrc.x = 0 ;<br />  rcSrc.y = 0 ;<br />  rcDst = rcSrc ;<br /><br />  //movement rate<br />  int dx = 2 , dy = 2 ;<br /><br />  //declare event variable<br />  SDL_Event event ;<br /><br />  //message pump<br />  for ( ; ; )<br />  {<br />    //look for an event<br />    if ( SDL_PollEvent ( &event ) )<br />    {<br />      //an event was found<br />      if ( event.type == SDL_QUIT ) break ;<br />    }<br />    //clear the screen<br />    SDL_FillRect ( pSurface , NULL , 0 ) ;<br /><br />    //place the ball<br />    SDL_BlitSurface ( pBitmap , &rcSrc , pSurface , &rcDst ) ;<br /><br />    //move the ball<br />    rcDst.x += dx ;<br />    rcDst.y += dy ;<br /><br />    //check for bounces<br />    if ( rcDst.x == 0 &#124;&#124; rcDst.x == SCREENWIDTH - rcDst.w ) dx = -dx ;<br />    if ( rcDst.y == 0 &#124;&#124; rcDst.y == SCREENHEIGHT - rcDst.h ) dy = -dy ;<br /><br />    //update the screen<br />    SDL_UpdateRect ( pSurface , 0 , 0 , 0 , 0 ) ;<br />  }//end of message pump<br /><br />  //done<br />  return ( 0 ) ;<br />}</pre>[/indent] And if you run the application, you'll see whatever image you made for your ball bounce slowly around the wind&#111;w. Its not a particularly mind-boggling example, but it does adequately demonstrate SDL_BlitSurface. Plus it's hypnotic.... you are getting sleepy... sleeeeeepy....<br />
<br />
 Anyway. That's the simple blit demo. As we go along, this stuff just keeps getting easier. Figure 3 shows what this program looks like.<br />
<br />
<p class='bbc_center'><a class='resized_img' rel='lightbox[2353ba524e55413a9e867e4abfc7195e]' id='ipb-attach-url-3687-0-69872800-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3687" title="02-03.jpg - Size: 7.54K, Downloads: 34"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-57782100-1309251833_thumb.jpg" id='ipb-attach-img-3687-0-69872800-1330208485' style='width:250;height:198' class='attach' width="250" height="198" alt="Attached Image: 02-03.jpg" /></a><br />
<strong class='bbc'>Figure 3: Bouncing Ball Demo</strong><br />
</p><br />
 Just a quick note before we move on. When using the SDL_BlitSurface function, the contents of the SDL_Rect pointed to by dstrect can change if the destination rectangle is clipped, so often it is a good idea to make a copy of the destination rectangle prior to blitting, unless you absolutely know that the destination rectangle lies entirely withing the destination surface.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Color Keys</strong></span><br />
<br />
And now we come to the issue of transparency. In GDI, in order to make transparency work, you either need to use bitmasks, or else use the TransparentBlt function, which doesn't work on all versions of Windows. In DirectDraw, you have to set up a DDCOLORKEY for a surface that uses one, and you have to pass particular flags when using the Blt or BltFast function.<br />
<br />
 In SDL, setting up a transparent color is really easy. Unlike DirectDraw, you can only have one (1) transparent color for an SDL surface (of course, it's not like DirectDraw had widespread support for transparent color spaces, but I digress). In any case, a single color is usually enough for transparency anyway. Once a color key has been set for a surface, it is used whenever that surface is the source surface in a blit operation (which is nice, because then you don't have to remember which surfaces have color keys).<br />
<br />
 The function for setting the color key of a surface is called SDL_SetColorKey.<br />
<br />
 [indent]<pre class='prettyprint'>int SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key);</pre>[/indent] This function takes three parameters: a pointer to a surface, a flag, and a key (the color, in the surfaces native pixel format). It returns an int, 0 if successful, and -1 if there is an error.<br />
<br />
 If flag contiains SDL_SRCCOLORKEY, then the value in key becomes the new transparent color key. If flag contains 0, any color key is cleared. You can retrieve the color key from the surface's pixel format, e.g. pSurface->format->colorkey.<br />
<br />
 Remember that key is in the native pixel format of the surface, and so if working with SDL_Color variables, you'll need to convert it with SDL_MapRGB.<br />
<br />
 No example for color keys, as their use is fairly obvious.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Clipping Rectangles</strong></span><br />
<br />
As a final topic, I'm going to show you how to set up a clipping rectangle for a surface. A clipping rectangle is the equivalent of an HRGN selected into an HDC in GDI, or an IDirectDrawClipper object attached to an IDirectDrawSurface object with SetClipper. Compared to their GDI or DirectDraw counterparts, the SDL clipping rectangle is not nearly as powerful or flexible. You can only have a single clipping rectangle at a time. For most purposes, that's enough. For times when it is not, you'll just have to get creative.<br />
<br />
 A clipping rectangle is just that: a rectangular area ( as described by an SDL_Rect variable) to which all destination blits are confined. Pixel plotting is unaffected by the clipping rectangle, as it directly accesses the pixel data of the surface. To set up a clipping rectangle for a surface, the function is SDL_SetClipRect.<br />
<br />
 [indent]<pre class='prettyprint'>void SDL_SetClipRect(SDL_Surface *surface, SDL_Rect *rect);</pre>[/indent] This function returns no value. It takes two parameters, a pointer to a surface (for which you are setting the clipping rectangle), and a pointer to an SDL_Rect structure (which contains the new clipping rectangle). If you pass NULL for rect, you will set the clipping area to the size of the entire surface.<br />
<br />
 To examine the contents of the clipping rectangle, you can either look at the clip_rect member of the SDL_Surface structure, or you can use SDL_GetClipRect, which has the same parameter list as SDL_SetClipRect, except that the current clipping rectangle is instead read into the variable pointed to by rect.<br />
<br />
 No example for clipping rectangles, as their use is fairly obvious.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Summary</strong></span><br />
<br />
We haven't totally exhausted the video system of SDL yet. There is still quite a bit more, but you've now been exposed to the basics. The functions shown in this article will be the ones most oft-used, although there are certainly some interesting aspects of some of the other functions, and later in the series, we shall return once again to the video subsystem. For now, this shall suffice.<br />
<br />
 Next Time: Events<br />
<br />
 Ernest S. Pazera<br />
<br />
 <a href='mailto:ernestpazera@hotmail.com' title='E-mail Link' class='bbc_email'>ernestpazera@hotmail.com</a><br />
<br />
 Sources: SDL Documentation]]></description>
		<pubDate>Mon, 17 Dec 2001 23:27:18 +0000</pubDate>
		<guid isPermaLink="false">38b4f06e27fd4f6fdcceabc6f5c068ea</guid>
	</item>
	<item>
		<title>The Simple DirectMedia Layer from a Win32 Persp...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/the-simple-directmedia-layer-from-a-win32-persp-r1598</link>
		<description><![CDATA[<strong class='bbc'>November 19, 2001</strong><br />
<br />
 <span style='font-size: 18px;'><strong class='bbc'>Mission Statement</strong></span><br />
<br />
Lots of people dislike DirectX, for one reason or another. Some say it is too complicated, others don't like being locked into a single development platform. For whatever reason, people look for alternatives. For a long time, the alternatives available have been a bunch of separate systems that were not built to work together in the same way that DirectX's components do. However, there is SDL, the Simple DirectMedia Layer. It is a cross-platform library for creating multi-media applications. For our purposes, this means games. Since it is cross-platform, and I mean TRULY cross platform, it doesn't matter what platform you are developing on. If you develop carefully, you will be able to take the exact same source code onto a different platform, and it will compile and work in exactly the same manner.<br />
<br />
 The mission of this article is to get you up and running in SDL on the WIN32 platform. For a long time, I have been primarily a WIN32 programmer, and while this might change in the future, I know that many of you are also WIN32 programmers, so we at least have that in common. During this article, we won't do a whole heck of a lot. We'll get SDL installed and a simple example program that shows a blank wind&#111;w. Believe it or not, that is the hardest part of SDL development. The rest is incredibly easy.<br />
<br />
 So, to begin, here are the Topical Guide Objectives for this article:<br />
<br />
TGO-01-A&nbsp;&nbsp;&nbsp;&nbsp;Know where to get SDL.   <br />
TGO-01-B&nbsp;&nbsp;&nbsp;&nbsp;Know how to set up Visual C++ 6.0 for SDL development.   <br />
TGO-01-C&nbsp;&nbsp;&nbsp;&nbsp;Know how to start an SDL based project in Visual C++ 6.0.   <br />
TGO-01-D&nbsp;&nbsp;&nbsp;&nbsp;Make a very simple program to test your setup.   <br />
TGO-01-E&nbsp;&nbsp;&nbsp;&nbsp;Make a very simplistic program with SDL   <br />
<br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Getting SDL(TGO-01-A)</strong></span><br />
<br />
Naturally, the first part of the process is to download SDL. You can find it at <a href='http://www.libsdl.org' class='bbc_url' title='External link' rel='nofollow external'>http://www.libsdl.org</a>. At the time of this writing, the most current version of the API is 1.2.3, and that is the version this article deals with. On the SDL site, you want to download the development libraries for WIN32. The site is well laid out, and it should be really easy for you to find it. They distribute the API as a zip file, so you'll need a copy of WinZip or some other type of archive utility to extract the files. Once you have it downloaded, unzip it somewhere, and take a look at the contents.<br />
<br />
 In the folder you unzip to, there are three subfolders: docs, include, and lib. These are fairly obvious, and we'll take a look at them a little later.<br />
<br />
 There are also a number of files, like Bugs, Copying, Readme, and so forth. You should take the time to read all of these, especially Bugs and Copying. SDL is released under the LGPL license, and if you intend to use SDL for creating applications that you wish to sell, you'll need to follow the license. See <a href='http://www.gnu.org' class='bbc_url' title='External link' rel='nofollow external'>http://www.gnu.org</a> for more information on the LGPL.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Setting up Visual C++(TGO-01-B)</strong></span><br />
<br />
The API comes with good documentation for setting up projects in WIN32 with SDL, but the docs lack just a little bit in that you have to go through the entire setup EVERY TIME you want to make an SDL base project. Well, you don't have to. There are some things that you only need to do once, and other things that you have to do for each project (which we shall cover in TGO-01-C).<br />
<br />
 The tasks you only have to do once are to set up the include path and library path for your development environment. In VC++6 you simply call up Tools->Options..., select the Directories tab, and add the appropriate directories to the Include Files and Library Files list and you are done. You will never ever have to do this again unless you uninstall VC++.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Setting up an SDL Project(TGO-01-C)</strong></span><br />
<br />
To set up a project to use SDL, you will have to go through a few steps every time. This isn't terribly uncommon-- you have to do the same thing if you are using DirectX. The type of project you want to create is a WIN32 Application, and have it start with an empty project.<br />
<br />
 Select the Project->Settings... menu item, and select the "C/C++" tab of the dialog that comes up. In the top combo box (with the word "Category" next to it on the left), select "Code Generation". Next, go over to the combo box entitled "Use Run-Time Library", and select "Multithreaded DLL".<br />
<br />
 Still in the Settings dialog, move over to the "Link" tab. In the "General" category, you want to edit the content of the "Object/Library Modules" text box. At the beginning of this text box, add "SDLmain.lib" and "SDL.lib".<br />
<br />
 Now click OK. The last step is to copy SDL.dll from the lib directory of SDL into the directory of your project. Without this dll, your application won't work.<br />
<br />
 And you are done with the SDL set up for this project. Every time you want to create a project using SDL, you have to do this. It's not too much, really.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Testing the Environment(TGO-01-D)</strong></span><br />
<br />
Now you've got the development environment set, and the project set, and it's time to test everything out to make sure it works. Create a new .cpp file for the project called main.cpp, and add the following code.<br />
<br />
 [indent]<pre class='prettyprint'>#include "SDL.h"<br />int main ( int argc , char* argv &#91;&#93; )<br />{<br />  return ( 0 ) ;<br />}</pre>[/indent] The first question to pop into your head is likely "Where did WinMain go?" This is a WIN32 Application, after all, and in WIN32 Applications, we always have to put in a WinMain, right? Well, no. In the .lib files that come with SDL all of the platform dependent stuff like WinMain are taken care of. The entry point for all SDL based applications will be main. Also, you will never want to include windows.h into any of your projects, because to do so would make it platform dependent, which nullifies one of the main goals of using SDL in the first place.<br />
<br />
 So, of course, this program does approximately nothing, but it is good for testing out the development environment. Attempt to compile and run this code. If it works, you know you've set up the environment and project successfully. If it doesn't, you forgot to do something. Don't be surprised when you run the application and nothing happens. Nothing is SUPPOSED to happen. As long as you don't get some sort of run-time error, you're OK.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>A Simple SDL Application (TGO-01-E)</strong></span><br />
<br />
Delete everything in main.cpp, and replace it with the following code:<br />
<br />
 [indent]<pre class='prettyprint'>#include "SDL.h"<br />int main( int argc, char* argv&#91;&#93; )<br />{<br />  //initialize systems<br />  SDL_Init ( SDL_INIT_VIDEO ) ;<br />  //set our at exit function<br />  atexit ( SDL_Quit ) ;<br />  //create a window<br />  SDL_Surface* pSurface = SDL_SetVideoMode ( 512 , 384 , 0, SDL_ANYFORMAT ) ;<br />  //declare event variable<br />  SDL_Event event ;<br />  //message pump<br />  for ( ; ; )<br />  {<br />    //look for an event<br />    if ( SDL_PollEvent ( &event ) )<br />    {<br />      //an event was found<br />      if ( event.type == SDL_QUIT ) break ;<br />    }<br />  }//end of message pump<br />  //done<br />  return ( 0 ) ;<br />}</pre>[/indent] Compile this and run it (we'll go though each of the lines in a moment). If you've done everything correctly, you will be met with a blank, black window with "SDL_App" in the title bar. You can move this window around, and hit the X button in the corner to close it. It is a pretty minimal application, but it's a lot easier than the equivalent WIN32 application that uses DirectX, I guarantee.<br />
<br />
 Now for a bit of explanation. We'll start with the first line of the program.<br />
<br />
 [indent]<pre class='prettyprint'>SDL_Init ( SDL_INIT_VIDEO ) ;</pre>[/indent] As you might imagine, SDL_Init is used to initialize the various subsystems of SDL. In this case, we are only initializing the video subsystem. Calling SDL_Init is akin to making use of an IDirectDraw or IDirectSound object, all rolled into one.<br />
<br />
 [indent]<pre class='prettyprint'>atexit ( SDL_Quit ) ;</pre>[/indent] If you've never used the atexit function before, it sets up another function to be called when the program terminates. This is an old C function that was used before C++ came around and made garbage collection a bit easier with the use of destructors. This line sets up SDL_Quit to be called after the program has terminated. SDL_Quit uninitializes all of SDL for you, so you don't have to. Alternately, you could call SDL_Quit at the end of your program, and you would accomplish the same thing. SDL_Quit is akin to calling IDirectDraw::Release and IDirectSound::Release all in one.<br />
<br />
 [indent]<pre class='prettyprint'>SDL_Surface* pSurface = SDL_SetVideoMode ( 512 , 384 , 0, SDL_ANYFORMAT ) ;</pre>[/indent] It's only the third line of the program, and already we are setting up the video mode. In a normal WIN32 program, we wouldn't even be half way through setting up our WNDCLASSEX structure. Without over explaining, SDL_Surface is a structure that abstracts a rectangular set of pixels on which you can draw. It is roughly akin to an HDC or an IDirectDrawSurface. The SDL_SetVideoMode function sets up your display. Despite the functions name, it doesn't always set a different display mode, and it certainly doesn't in this case. The parameters are width, height, bits per pixel, and flags. In this case, I am creating a 512x384 surface, but I have a 0 for the bits per pixel. This is because I am using the SDL_ANYFORMAT flag. With this flag, the current format of the display is taken as the format for the surface, so it doesn't really matter what is placed into the third parameter. I could indeed specify a number for this parameter and leave off the SDL_ANYFORMAT flag, and SDL would accommodate me by giving me a surface in the format I requested, regardless of the screen's format. This isn't a good idea, because it requires SDL to "fake" the format if it doesn't match the screen's format. So, if you are making a windowed application, use the SDL_ANYFORMAT flag.<br />
<br />
 [indent]<pre class='prettyprint'>SDL_Event event ;<br />//message pump<br />for ( ; ; )<br />{<br />  //look for an event<br />  if ( SDL_PollEvent ( &event ) )<br />  {<br />    //an event was found<br />    if ( event.type == SDL_QUIT ) break ;<br />  }<br />}//end of message pump</pre>[/indent] We will take a look at the rest of the code (minus the line with return on it... I assume you know what THAT does) all at once. SDL_Event is another SDL structure. This time, it abstracts events, something you are likely more than used to in WIN32 programming. Like WIN32, SDL is event driven, and so we have a message pump. The SDL message pump is a lot simpler than the equivalent WIN32 message pump, of course.<br />
<br />
 Some folks prefer while(1) for their message pump, but I'm one of those who prefer for(;;). I feel it more accurately describes what I'm doing. Both statements are equivalent, of course, so it doesn't really matter which way you do it.<br />
<br />
 The SDL_PollEvent function checks for a event in the queue. If there is no message waiting, it returns 0. If a message is waiting, it returns 1, and copies the event into the parameter passed to it, in this case the variable I have so aptly named "event".<br />
<br />
 Only if SDL_PollEvent returns non-zero (i.e. an event has occurred) does the next line get called. In this case, the type member of SDL_Event is checked to see if it is SDL_QUIT, which is the event for exiting the application. If this has happened, we break out of the message pump loop and proceed to exit the application.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Summary</strong></span><br />
<br />
So, is everything about SDL this easy? Yes, pretty much. As I said earlier, the hardest part is setting up the environment. After that, everything is mostly the same as a regular WIN32 application, just with different functions. The key is that this API is called the SIMPLE DirectMedia Layer. From here, I suggest taking a look at some of the SDL docs and playing around with the API, at least until someone convinces me to get off my duff and write another tutorial.]]></description>
		<pubDate>Tue, 04 Dec 2001 10:00:12 +0000</pubDate>
		<guid isPermaLink="false">45ea3375b621c477ab248d431b7acb87</guid>
	</item>
	<item>
		<title>Creating 3D Tools with MFC</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/creating-3d-tools-with-mfc-r1358</link>
		<description><![CDATA[<span style='font-size: 18px;'><strong class='bbc'>Introduction</strong></span><br />
<br />
Game tools have long been overlooked as an important piece of the development process. Many hobbyists and professional programmers have difficulty putting forth effort on a complete tool package, coming from a world where glorious hacks are applauded. Existing software can be supported through command line applications or file parsers, and artists can adapt to a few extra steps in the process. Many feel that their time is best spent doing "important" things, rather than squandering it all on a tool set that will never see the light of day. GUI layout and other "fluff" add tedium to the process, further frustrating the programmer. Further more, windows applications have a sort of mystique for those that are new to tool development, often times leading to intimidation and rationalization about the subject.<br />
<br />
 No problem. Using APIs like OpenGL or Direct3D (which most programmers are already familiar with) and MFC, tools can be written quickly and efficiently. More often than not code can be taken directly from the game engine and dropped right into the framework, not only saving time but maintaining consistency between the way scenes are displayed in-game and in the tools.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Who is This Article For?</strong></span><br />
<br />
The purpose of this article is to provide a lightning quick introduction to MFC and dive into 3D tools. Prior knowledge of MFC is not required, but a cursory knowledge of the MFC architecture is highly recommended. The accompanying source uses OpenGL for rendering, although other APIs can be similarly implemented. MFC is also heavily rooted in C++, so those that don’t subscribe to the object-oriented school of thought might want to read this article with a reference book in their lap. I also recommend referring back to the MSDN library throughout the course of all your projects, as I can’t possibly provide the amount of detail found therein.<br />
<br />
 Obviously this subject has the potential to be overwhelming and huge, so I’ll only be covering a fraction of the process here. However if there were an expressed interest in future articles along the same vein I’d be happy to comply.<br />
<br />
 Still here? Let the good times roll...<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Introducing MFC</strong></span><br />
<br />
So after all that, what the hell am I talking about? For those that skipped their anachronism class in high school, MFC stands for the <em class='bbc'>Microsoft Foundation Classes</em>. As this is nearly as cryptic as the abbreviation was, I’ll elaborate. Simply put, MFC is a set of C++ classes that attempt to simplify the process of creating GUI applications for windows. Alone it’s not much to look at, but combined with an uncharacteristically helpful wizard and a useful set of editors it becomes a very powerful tool. For purists MFC is viewed as an unneeded abstraction, and ranks right up there with Mr. Rogers and Hitler. Despite arguments to the contrary MFC can save you weeks of tedious guess and check coding, so if you can leave your hang-ups at the door we’ll all get along better.<br />
<br />
 The following are some terms that are used freely when discussing MFC:<br />
<br />
 <strong class='bbc'>Control:</strong> A GUI object that allows the user to control or modify the document or application in some fashion (text field, checkbox, dropdown list, button, etc).<br />
<br />
 <strong class='bbc'>Document:</strong> All the data that is contained and created by your application (the text in a word processor, a scene in a 3D modeler, etc).<br />
<br />
 <strong class='bbc'>View:</strong> A particular way to display a document or set of controls in your application.<br />
<br />
 <strong class='bbc'>SDI:</strong> <em class='bbc'>Single Document Interface</em> - an MFC application with a single document and a varying number of views.<br />
<br />
 <strong class='bbc'>MDI:</strong> <em class='bbc'>Multiple Document Interface</em> – an MFC application with many different types of documents and a varying number of views.<br />
<br />
 In our case we’ll only be looking at SDI applications that use the document/view philosophy. Most applications can easily be split into a single document and multiple views – especially in the case of a one-track tool like a level editor. Although it’s possible to create an MFC application without using documents or views it is more time consuming and generally less effective unless your application is very simple. This is just a taste of MFC terminology, so I still recommend reading through some of the MSDN entries on the subject. We’ll also be using the class wizard and the resource editor to maintain our application during development, so make sure you’re familiar with them, as I won’t be describing them in depth. Once again the MSDN library has many helpful entries on both tools.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Before We Start...</strong></span><br />
<br />
For this article we will be creating a simple 3D-model viewer. The layout will include four viewports to display the model in either a variety of orthogonal views or a perspective view. There will also be a bar of controls used to change each viewport’s type. The file format will be *.md3 files (Quake III Arena model files), however there will be little time spent on the actual model loading and drawing, as the general architecture is our focus. I chose the *.md3 file format simply because I had some old code from another project lying around and I didn’t feel like spending the time on another file format. It’s recommended that you download the accompanying source package.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Getting Started</strong></span><br />
 <br />
<span style='font-size: 12px;'><strong class='bbc'>Creating the Project</strong></span><br />
<br />
When choosing your project type (before or after you’ve created your workspace, depending on the way you do things) select MFC AppWizard EXE. By choosing the EXE option rather than DLL we make sure we’re creating a standalone application. Choosing this option will launch the AppWizard (hardly surprising). Choose "single document", and accept the defaults. You can turn off "printing and printing preview", just make sure that you’re using the document/view architecture.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Compiling the Project</strong></span><br />
<br />
After you’ve completed the wizard you should find a dozen files or so in your workspace. Don’t panic, this is just the beginning! Just take a few deep breaths and relax, they’re mostly class definitions and the like and will become clear with time. Before you continue compile, build and execute your project. MFC uses a precompiled header file, which has to compiled and saved to disk. Making sure you perform a complete build at the beginning of development will help you avoid cryptic link errors later.<br />
<br />
 Are we having fun yet?<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Creating the Layout</strong></span><br />
<br />
The first files we will be looking at will be MainFrm.h and MainFrm.cpp which contain your CMainFrame class. Like the name suggests, CMainFrame is the main frame window for your application. While your own applications will most likely spawn dialog boxes and child windows, the main frame is the base of all the action. This is where we need to add our splitter windows.<br />
<br />
 A CSplitterWnd class or splitter window is a way to split the screen into two or more different views or windows. A comparable example might be frames in HTML, or the different panes in Microsoft Developer Studio. A splitter window should be created during the initialization of the client area of the main frame wind&#111;w. In order to facilitate this we need to perform two steps.<br />
<br />
 First our CSplitterWnd objects are added as members of the CMainFrame class. Note that this doesn’t initialize or create them in anyway, it just gives us the option of doing so in the future. Since our layout plan has four viewports bordered by a single pane of controls we need to use two CSplitterWnd objects to accomplish our desired layout. The first splitter will be used to split the screen into a window for the control pane and a window for the viewports. The second splitter will be used to split the viewport window into four separate windows. Again this is similar to creating frames in HTML. Somewhere in the class definition in MainFrm.h we add the following code:<br />
<br />
 [indent]<pre class='prettyprint'>CSplitterWnd m_mainSplitter,             	// Splitter windows<br />         	m_viewportSplitter;</pre>[/indent] Secondly we must create the splitters when the client area is created. In order to do this we have to add a message map to the CMainFrame class. A message map is the way messages are passed in MFC. Whenever the class that is assigned a message map receives a certain message, it executes a named function with parameters corresponding to the pertinent information in the message. In our case we use the ClassWizard to add a message map to CMainFrame for the OnCreateClient message. Looking in MainFrm.cpp we find the following method skeleton:<br />
<br />
 [indent]<pre class='prettyprint'>BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)<br />{<br />  // TODO: Add your specialized code here and/or call the base class<br /><br />  return CFrameWnd::OnCreateClient(lpcs, pContext);<br />}</pre>[/indent] Not bad, we now have a place to create our splitter windows. Splitter windows come in two flavors, static and dynamic. A dynamic splitter can be split and collapsed by the user, while a static splitter cannot. We’ll only be dealing with static splitters since we generally don’t want to give the user that kind of control over the layout. First we create the main splitter window and check for errors:<br />
<br />
 [indent]<pre class='prettyprint'>if ( !m_mainSplitter.CreateStatic( this, 1, 2 ) )<br />{<br />  MessageBox( "Error setting up splitter frames!", "Init Error!",<br />          	MB_OK &#124; MB_IC&#111;nerror );<br />  return FALSE;<br />}</pre>[/indent] The parameters are fairly straightforward; we pass in the parent window and the number of rows and columns in the splitter. Next we must create the views that we want to fill each pane in the splitter. When creating a static splitter you must create a view or nested splitter window for each pane before it is displayed. First we create the view for our control panel:<br />
<br />
 [indent]<pre class='prettyprint'>CRect cr;  // client rectangle -<br />       	// used to calculate client sizes<br /><br />GetClientRect( &cr );<br />if ( !m_mainSplitter.CreateView( 0, 1, RUNTIME_CLASS(CYourProjectNameView),<br />    	CSize( INFOBAR_SIZE, cr.Height() ), pContext ) )<br />{<br />  MessageBox( "Error setting up splitter frames!", "Init Error!",<br />          	MB_OK &#124; MB_IC&#111;nerror );<br />  return FALSE;<br />}</pre>[/indent] This one’s more of a mouthful. The first two parameters are fairly simple – just the row column (zero based) indices of the splitter where the view is to be created. The third parameter is the class type that will be created. The RUNTIME_CLASS statement is a macro that simplifies passing in a dynamically declared class. CYourProjectNameView is the default view that is created by the wizard. We will return to this code later and change this class to our own. The last two parameters are just the size of the pane to be created and the context that was passed into the OnCreateClient method. Next we create the viewport splitter, nested inside the main splitter:<br />
<br />
 [indent]<pre class='prettyprint'>if ( !m_viewportSplitter.CreateStatic( &m_mainSplitter, 2, 2, WS_CHILD &#124;<br />        	WS_VISIBLE, m_mainSplitter.IdFromRowCol( 0, 0 ) ) )<br />{<br />  MessageBox( "Error setting up splitter frames!", "Init Error!",<br />          	MB_OK &#124; MB_IC&#111;nerror );<br />  return FALSE;<br />}</pre>[/indent] Since this is a nested splitter we have a few more things to worry about. Rather than passing <em class='bbc'>this</em> as the parent window we pass in the address of the parent splitter. Also rather than passing in the context we pass the ID from the pane where we want to insert the splitter. Views must then be created for every pane in this splitter in the exact same manner as before. For now make them all the default view type, we’ll change them later.<br />
<br />
 Note that the skeleton returns the parent class’ OnCreateClient method. This is typical behavior in message maps. Often times you’ll want to poke your head in the works, but afterwards have business proceed as usual. In this particular case this is not what we want however. If we call the parent method we’ll be creating the client area a second time, basically destroying all our hard work. To prevent this just return TRUE rather than the parent method.<br />
<br />
 If you execute your program at this point you should see the splitters in place, more or less how you expected them. However if you try resizing the window you’ll find that the splitters don’t change with your wind&#111;w. Obviously this isn’t behavior we want in our application. This can be fixed by adding another message map to CMainFrame for the WM_SIZE message:<br />
<br />
 [indent]<pre class='prettyprint'>void CMainFrame::OnSize(UINT nType, int cx, int cy)<br />{<br />  CFrameWnd::OnSize(nType, cx, cy);<br /><br />  if (  nType != SIZE_MINIMIZED )<br />  {<br />	m_mainSplitter.SetRowInfo( 0, cy, 0 );<br />	m_mainSplitter.SetColumnInfo( 0, cx - INFOBAR_SIZE, 0 );<br />	m_mainSplitter.SetColumnInfo( 1, INFOBAR_SIZE, 0 );<br /><br />	// etc...<br /><br />	m_mainSplitter.RecalcLayout();<br />	m_viewportSplitter.RecalcLayout();<br />  }<br />}</pre>[/indent] Try running this and see if you get an error. Whoops, it looks like we get a WM_SIZE message before OnCreateClient is called! To remedy this we add a flag to the CMainFrame member variables and set it to FALSE in CMainFrame’s constructor and to TRUE in OnCreateClient. By checking it in OnSize we only adjust the splitters after they’ve been initialized:<br />
<br />
 [indent]<pre class='prettyprint'>if ( m_initSplitters && nType != SIZE_MINIMIZED )<br />{<br />  // etc...</pre>[/indent] OK! Pat yourself on the back and do something soothing to relax yourself (I like to pound my head on the keyboard – make sure you note where all the keys fly, you may need them). Take an Advil and then proceed...<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Creating the Viewport Classes</strong></span><br />
<br />
The viewport, as a vital piece of our application, is one place in particular that requires careful planning. Running in headfirst will most likely turn up a bunch of hacks and a lot of redundant code. I hate having to type things twice twice.<br />
<br />
 A good place to start is a base class that contains all the functionality required to get up and running in our desired API. The rest of our viewport classes will inherit from this class, making a port from one API to another simple work. The sample code deals with OpenGL, but the process should be similar with other APIs.<br />
<br />
 <strong class='bbc'>COpenGLWnd</strong> – Our base class with the basic OpenGL setup stuff. For more information on the specifics of creating an OpenGL view with MFC check the accompanying code or the tutorial found <a href='http://nehe.gamedev.net' class='bbc_url' title='External link' rel='nofollow external'>here</a>. Note that this class doesn’t have a message map for WM_SIZE. That will be covered later.<br />
<br />
 <strong class='bbc'>CPerspective</strong> – The perspective viewport. To get an MFC class with all the right trimmings we start by creating a class with the ClassWizard with CView as the parent. Following this make sure you change <strong class='bbc'><em class='bbc'>ALL</em></strong> references to CView to COpenGLWnd. At this point we’re ready to start handling WM_SIZE messages with a message map:<br />
<br />
 [indent]<pre class='prettyprint'>// Adjust the viewport after a window sizing.<br />void CPerspective::OnSize(UINT nType, int cx, int cy)<br />{<br />  COpenGLWnd::OnSize(nType, cx, cy);<br /><br />  if ( 0 &gt;= cx &#124;&#124; 0 &gt;= cy &#124;&#124; nType == SIZE_MINIMIZED )<br />	return;<br /><br />  // Change the perspective viewing volume to<br />  // reflect the new dimensions of the wind&#111;w.<br />  SetContext();<br />  glViewport( 0, 0, cx, cy );<br />  glMatrixMode( GL_PROJECTION );<br />  glLoadIdentity();<br />  gluPerspective(45.0f, (float)(cx)/(float)(cy), 0.01f, 1000.0f);<br />  glMatrixMode( GL_MODELVIEW );<br />}</pre>[/indent] This process should look familiar to those that use OpenGL. We simple adjust the viewing volume with the new dimensions of the screen. At this point our viewport is just a boring static window, so let’s shake it up a bit. First we need to add member values to track the camera’s position and rotation:<br />
<br />
 [indent]<pre class='prettyprint'>float m_zoom,<br />  	m_xpos,<br />  	m_ypos,<br />  	m_xrot,<br />  	m_yrot;</pre>[/indent] Next we need to catch user actions to move the camera. We’ll create a process similar to camera manipulation in Maya and many other 3D packages. If the user holds down the Ctrl key and clicks and drags with the left mouse button the camera rotates, the middle mouse button zooms, and the right mouse button pans. We accomplish this by adding a message map for the WM_MOUSEMOVE message:<br />
<br />
 Where:<br />
<br />
 [indent]<pre class='prettyprint'>int  m_lastMouseX,<br /> 	m_lastMouseY;</pre>[/indent] Are class members of CPerspective:<br />
<br />
 [indent]<pre class='prettyprint'>void CPerspective::&#111;nmousemove(UINT nFlags, CPoint point) <br />{<br />  // Move the camera if control is being<br />  // pressed and the apropriate mouse<br />  // button is being held down.<br /><br />  if ( nFlags & MK_CONTROL )<br />  {<br />	if ( nFlags & MK_LBUTTON )<br />	{<br />  	// Left mouse button is being<br />  	// pressed. Rotate the camera.<br />  	if ( m_lastMouseX != -1 )<br />  	{<br />    	m_yrot += point.y - m_lastMouseY;<br />    	m_xrot += point.x - m_lastMouseX;<br />    	// Redraw the viewport.<br />    	OnDraw( NULL );<br />  	}<br />  	m_lastMouseX = point.x;<br />  	m_lastMouseY = point.y;<br />	}<br /><br />	// etc...<br /><br />	else<br />	{<br />  	m_lastMouseX = -1;<br />  	m_lastMouseY = -1;<br />	}<br />  }<br />  else<br />  {<br />	m_lastMouseX = -1;<br />	m_lastMouseY = -1;<br />  }<br /><br />  COpenGLWnd::&#111;nmousemove(nFlags, point);<br />}</pre>[/indent] Now mouse movements under the correct conditions alter the member variables representing our camera. The final step is to implement our camera variables in our WM_DRAW message map:<br />
<br />
 [indent]<pre class='prettyprint'>void CPerspective::OnDraw(CDC* pDC)<br />{<br />  SetContext();<br />  glLoadIdentity();<br /><br />  // Position the camera<br />  glTranslatef( m_xpos, -m_ypos, -m_zoom );<br /><br />  // Adjust viewport for md3 models which<br />  // use a different coordinate system -<br />  // 3DSMAX format.<br />  glRotatef( -90.0f, 1.0f, 0.0f, 0.0f );<br />  glRotatef( -90.0f, 0.0f, 0.0f, 1.0f );<br /><br />  // Rotate the camera<br />  glRotatef( m_xrot, 0.0f, 0.0f, 1.0f );<br />  glRotatef( m_yrot, 0.0f, 1.0f, 0.0f );<br />  RenderScene();<br />  SwapGLBuffers();<br />}</pre>[/indent] Huzzah! Go back to MainFrm.cpp and plug your new class into one or more of the viewport panes and put some drawing code into CPerspective::RenderScene(). I used a cube with colored faces for testing purposes. It feels good to be brilliant doesn’t it?<br />
<br />
 <strong class='bbc'>COrthographic</strong> – COrthographic inherits from COpenGLWnd, create it in the same manner you created CPerspective. While CPerspective was a finished viewport (more or less) COrthographic is one step away from being a finished viewport, with CFront, CSide, and CTop inheriting from it. COrthographic differs from CPerspective in the fact that as an orthogonal viewport it cannot be rotated by the user, and all positioning and zooming can be done in the WM_SIZE message map because of the nature of orthographic viewports:<br />
<br />
 Where:<br />
<br />
 [indent]<pre class='prettyprint'>float m_zoom,<br />  	m_xpos,<br />  	m_ypos;<br />int   m_lastMouseX,<br />  	m_lastMouseY;</pre>[/indent] Are class members of COrthographic:<br />
<br />
 [indent]<pre class='prettyprint'>void COrthographic::OnSize(UINT nType, int cx, int cy) <br />{<br />  COpenGLWnd::OnSize(nType, cx, cy);<br /><br />  if ( 0 &gt;= cx &#124;&#124; 0 &gt;= cy &#124;&#124; nType == SIZE_MINIMIZED )<br />	return;<br /><br />  // Change the orthographic viewing volume to<br />  // reflect the new dimensions of the window<br />  // and the zoom and position of the viewport.<br />  SetContext();<br />  glViewport( 0, 0, cx, cy );<br />  glMatrixMode( GL_PROJECTION );<br />  glLoadIdentity();<br />  glOrtho( (float)(cx)/(float)(cy)*-m_zoom-m_xpos, (float)(cx)/(float)(cy)*m_zoom-m_xpos,<br />       	-m_zoom+m_ypos, m_zoom+m_ypos, -200.0f, 200.0f );<br />  glMatrixMode( GL_MODELVIEW );<br />}</pre>[/indent] If you have trouble understanding the reasoning behind the orthographic sizing I suggest reading up on the difference between perspective and orthogonal views to get a clear idea of exactly what’s going on here. Note that COrthographic has no member variables for rotation. Orthographic views can be rotated, but in the context of 3D editor or modeler you don’t want them to be rotated by the user. The message map for WM_MOUSEMOVE is identical to the map for CPerspective except there is no check for the left mouse button (rotation) and OnSize is called just before OnDraw to apply the changes. Check the accompanying source for more information.<br />
<br />
 <strong class='bbc'>CFront, CSide, CTop</strong> – All inherited from COrthographic each class differs in its WM_DRAW message map with the appropriate amount of rotation for its respective viewpoint.<br />
<br />
 Double Huzzah! Go back to MainFrm.cpp and add in your orthographic viewports. Now that we have sleek sexy viewports covering most of the screen that little control panel is starting to look pretty weak. Let’s see what we can do...<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Taking Control</strong></span><br />
<br />
Adding controls to a window can be accomplished in a variety of ways. One of the easiest (and fastest) ways is to use a dialog template with a CFormView class. A dialog template is a resource file that is generated by the resource editor when you layout controls for a dialog. A CFormView class allows you to add a dialog template to a window by acting like a modeless dialog box imbedded into the wind&#111;w. A modeless dialog box is just a dialog that functions coincidentally with the main frame. A modal dialog box is the opposite, forcing the user to do what is necessary to close the box before the main frame becomes active again.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Creating the Dialog Template</strong></span><br />
 <br />
Using the resource editor create a new dialog template with four dropdown lists arranged in a square. Each of these lists will represent a viewport and allow the user to change between a front, side, top, and perspective view. Do yourself a favor and change the control IDs to meaningful names, it will make life easier later on. Since these will be static, read-only dropdown lists go ahead and enter the data for the dropdown lists (Front, Top, Side, Persp). Just a side note, there are a few aspects of making dropdown lists with the resource editor that drove me nuts, they weren’t documented very well and were quite annoying. To enter a new line in the data field you need to press Ctrl + Enter, and you must also set the dropdown height by clicking on the arrow for the list. Make sure the ordering is the same for each list.<br />
<br />
<p class='bbc_center'><a class='resized_img' rel='lightbox[7b7c3099c42744ffa521c2ed366abc0d]' id='ipb-attach-url-3489-0-83879100-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3489" title="resourceeditor.jpg - Size: 70.58K, Downloads: 87"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-78086700-1308879337_thumb.jpg" id='ipb-attach-img-3489-0-83879100-1330208485' style='width:250;height:195' class='attach' width="250" height="195" alt="Attached Image: resourceeditor.jpg" /></a> <br />
Get the point?<br />
</p><br />
 <span style='font-size: 12px;'><strong class='bbc'>Creating the Form View Class</strong></span><br />
<br />
Double click on the dialog template in the resource editor. This should open the ClassWizard with a message regarding your new template. You can also do this manually from within the ClassWizard if you don’t get a message for whatever reason. Create a new class that inherits from CFormView and uses your new dialog template (the dialog ID is selected in the dropdown list under the parent class). We’ll call this new class CInfoPannel for the rest of this article. Go back to MainFrm.cpp and change the class of the remaining window to CInfoPannel. Run the program and make sure you see the controls in the panel as expected.<br />
<br />
 So far so good. Now if only it did something...<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Adding Member Variables and Message Maps</strong></span><br />
<br />
In a normal dialog box controls are maintained by creating special member variables that are automatically updated with validated data from their associated controls. Changing those same member variables can change the controls in turn. Since a CFormView class (and classes that inherit from it) is not a true dialog box we have to take a few extra steps to use this same method. First, just as though we were dealing with a dialog box, we add the member variables using the ClassWizard. This is where it pays off if you used meaningful control IDs earlier.<br />
<br />
 In order for these variables to be updated from their respective controls we have to explicitly call UpdateData, a method that is normally called by the framework to update dialog controls and member variables. By passing this method TRUE, information from a control will be stored in a member variable. By passing it FALSE, information from a member variable will update a control. We assume that we would want to change control values during the class’ WM_UPDATE message map:<br />
<br />
 [indent]<pre class='prettyprint'>void CInfoPannel::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)<br />{<br />  UpdateData( FALSE );<br />}</pre>[/indent] Finally we need to perform some action when the dropdown selection is changed. By double clicking one of the controls in the resource editor the wizard will add a message map that corresponds to that control to the parent class. Do so for each dropdown list.<br />
<br />
 Now we’re faced with a dilemma. To change our viewports we need to access our viewport splitter. At this point the easiest thing to do is to bend the OOP rules a little bit, although C++ zealots are welcome to flame me into a cinder for it:<br />
<br />
 Where:<br />
<br />
 [indent]<pre class='prettyprint'>CSplitterWnd *m_viewports;</pre>[/indent] Is a member variable of CInfoPannel.<br />
<br />
 In CMainFrame, just after CInfoPannel is created:<br />
<br />
 [indent]<pre class='prettyprint'>// Setup a pointer to the viewport splitter to be<br />// used later by the information bar to change<br />// viewports.<br />((CInfoPannel*)(m_mainSplitter.GetPane( 0, 1 )))-&gt;m_viewports = &m_viewportSplitter;</pre>[/indent] We’re now able to alter the viewport splitter to our heart’s content, which is done during each dropdown list’s message map:<br />
<br />
 [indent]<pre class='prettyprint'>// Message handlers for the info bar<br />// controls. Viewport dropdowns.<br /><br />void CInfoPannel::OnEditchangeUpperleft()<br />{<br />  // Automatically update the form view<br />  // member variables with the values from<br />  // their associated controls.<br />  UpdateData( TRUE );<br /><br />  // Delete the view in the appropriate<br />  // splitter pane and create a new one<br />  // based on the dropdown selection.<br /><br />  CRuntimeClass *newViewClass;<br />  CRect cr;                 	// client rectange<br /><br />  switch ( m_upperLeft )<br />  {<br />	case FRONTVIEWPORT:<br />  	newViewClass = RUNTIME_CLASS( CFront );<br />  	break;<br />	case TOPVIEWPORT:<br />  	newViewClass = RUNTIME_CLASS( CTop );<br />  	break;<br />	case SIDEVIEWPORT:<br />  	newViewClass = RUNTIME_CLASS( CSide );<br />  	break;<br />	case PERSPVIEWPORT:<br />  	newViewClass = RUNTIME_CLASS( CPerspective );<br />  	break;<br />  }<br /><br />  m_viewports-&gt;GetClientRect( &cr );<br />  m_viewports-&gt;DeleteView( 0, 0 );<br />  m_viewports-&gt;CreateView( 0, 0, newViewClass,<br />  	CSize( cr.Width() / 2, cr.Height() / 2 ), NULL );<br /><br />  // Add the new view to the application's<br />  // &#100;ocument.<br />  GetDocument()-&gt;AddView( (CView*)(m_viewports-&gt;GetPane( 0, 0 )) );<br /><br />  // Recalculate the splitter window so the<br />  // changes are displayed.<br />  m_viewports-&gt;RecalcLayout();<br />}</pre>[/indent] Take minute to wrap your brain around that, there’s a bunch of stuff there. First we call UpdateData( TRUE ) to update the member variables associated with all the controls. Next the appropriate class type is chosen based on the dropdown selection. FRONTVIEWPORT, SIDEVIEWPORT, TOPVIEWPORT, and PERSPVIEWPORT are just constants that correspond to the appropriate dropdown index number. Following that the current view for the appropriate viewport is deleted and a new one is created. The document is then updated with the new view to avoid an issue further down the line.<br />
<br />
 So you run your program and find that, amazingly enough, nothing happens. After some detective work and a bunch of swearing you’ll find that the default behavior for a dropdown message map is to run when a dropdown has been edited (the actual text has been edited, rather than the selection). Since our dropdown lists are read-only our message maps will never be called. This can be fixed simply enough by editing some of the wizard-generated code:<br />
<br />
 Change:<br />
<br />
 [indent]<pre class='prettyprint'>BEGIN_MESSAGE_MAP(CInfoPannel, CFormView)<br />  //{{AFX_MSG_MAP(CInfoPannel)<br />  ON_CBN_EDITCHANGE(IDC_UPPERLEFT, OnEditchangeUpperleft)<br />  ON_CBN_EDITCHANGE(IDC_UPPERRIGHT, OnEditchangeUpperright)<br />  ON_CBN_EDITCHANGE(IDC_LOWERLEFT, OnEditchangeLowerleft)<br />  ON_CBN_EDITCHANGE(IDC_LOWERRIGHT, OnEditchangeLowerright)<br />  //}}AFX_MSG_MAP<br />END_MESSAGE_MAP()</pre>[/indent] To:<br />
<br />
 [indent]<pre class='prettyprint'>BEGIN_MESSAGE_MAP(CInfoPannel, CFormView)<br />  //{{AFX_MSG_MAP(CInfoPannel)<br />  ON_CBN_SELCHANGE(IDC_UPPERLEFT, OnEditchangeUpperleft)<br />  ON_CBN_SELCHANGE(IDC_UPPERRIGHT, OnEditchangeUpperright)<br />  ON_CBN_SELCHANGE(IDC_LOWERLEFT, OnEditchangeLowerleft)<br />  ON_CBN_SELCHANGE(IDC_LOWERRIGHT, OnEditchangeLowerright)<br />  //}}AFX_MSG_MAP<br />END_MESSAGE_MAP()</pre>[/indent] Run the program one more time and everything should be squared away. Looking good, it almost does something now...<br />
<br />
<p class='bbc_center'><a class='resized_img' rel='lightbox[7b7c3099c42744ffa521c2ed366abc0d]' id='ipb-attach-url-3490-0-83899900-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3490" title="viewerearly.jpg - Size: 43.49K, Downloads: 123"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-09118900-1308879481_thumb.jpg" id='ipb-attach-img-3490-0-83899900-1330208485' style='width:250;height:181' class='attach' width="250" height="181" alt="Attached Image: viewerearly.jpg" /></a><br />
Introducing the power of eCube, your one stop shop for displaying static-colored cubes.<br />
</p><br />
<br />
<span style='font-size: 18px;'><strong class='bbc'>Creating the Document</strong></span><br />
<br />
So now we have a flashy little app that doesn’t really do anything. If we were making a commercial product we’d be laughing our way to the bank by this time, but unfortunately we plan on using this tool so it’s going to have to do something. Up until this point we’ve dealt with views to a great extent, but now it’s time to put the "document" back into "document/view architecture". We’ll be looking at YourProjectNameDoc.cpp and YourProjectNameDoc.h from this point on.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Adding Data to the Document</strong></span><br />
<br />
The first (and most obvious step) is to add our data to our document class. In our case we’ll just add a model object, which will contain all the info the application needs to draw the *.md3 file. We also add some code to the constructor and destructor to handle memory allocation for the model:<br />
<br />
 Where:<br />
<br />
 [indent]<pre class='prettyprint'>CMd3Model *m_currentModel;</pre>[/indent] Is a member variable of CYourProjectNameDoc:<br />
<br />
 [indent]<pre class='prettyprint'>CYourProjectNameDoc:: CYourProjectNameDoc ()<br />{<br />  // No model has been loaded yet.<br />  m_currentModel = NULL;<br />}<br /><br />CYourProjectNameDoc::~ CYourProjectNameDoc ()<br />{<br />  // If a model is currently loaded<br />  // delete it.<br />  if ( m_currentModel != NULL )<br />	delete m_currentModel;<br />}</pre>[/indent] <span style='font-size: 12px;'><strong class='bbc'>Loading the Model</strong></span><br />
<br />
This step is fairly simple because all the message maps you need have already been created by the wizard. Simply add your loading code to the serialize method. This is also where you add code for saving, however we won’t be covering that here. The CArchive object that is passed to the method will be the file that the user is asking to load:<br />
<br />
 [indent]<pre class='prettyprint'>void CYourProjectNameDoc::Serialize(CArchive& ar)<br />{<br />  if (ar.IsStoring())<br />  {<br />	// TODO: add storing code here<br />  }<br />  else<br />  {<br />	// Load the MD3 file.<br /><br />	if ( m_currentModel != NULL )<br />  	delete m_currentModel;<br /><br />	m_currentModel = new CMd3Model;<br />	if ( !LoadMd3( ar, m_currentModel ) )<br />	{<br />  	MessageBox( NULL, "Not a valid md3 file!", "File Error!",<br />    	MB_OK &#124; MB_IC&#111;nerror );<br />  	return;<br />	}<br />  }<br />}</pre>[/indent] And that’s it. You can further customize this process by intersecting the menu message and applying file filters to the file dialog, etc. Refer to the accompanying source for more information on how to do this. At this point you can simply add your draw code to the RenderScene method of each of your viewports. The application document can be accessed by any of its child views with the function Get&#100;ocument. Note that I used a rather cryptic method for rendering scenes in the accompanying source. I find that method works best for me, so I included it for advanced users – however I won’t explain it here as it looks like voodoo chicken scratch ( void SetRenderFunc(void (*func) (CViewerDoc* )) { m_RenderScene = func; } ).<br />
<br />
<p class='bbc_center'><a class='resized_img' rel='lightbox[7b7c3099c42744ffa521c2ed366abc0d]' id='ipb-attach-url-3491-0-83916600-1330208485' href="http://www.gamedev.net/index.php?app=core&module=attach&section=attach&attach_rel_module=ccs&attach_id=3491" title="viewerfinished.jpg - Size: 55.52K, Downloads: 113"><img src="http://public.gamedev.net/uploads/monthly_06_2011/ccs-8549-0-68175600-1308879569_thumb.jpg" id='ipb-attach-img-3491-0-83916600-1330208485' style='width:250;height:181' class='attach' width="250" height="181" alt="Attached Image: viewerfinished.jpg" /></a><br />
Everything you’ve always wanted in an *.md3 viewer, and less!<br />
</p><br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Conclusion</strong></span><br />
<br />
Despite popular opinion, creating proprietary tools for game development doesn’t have to be time consuming, tedious, or intimidating, (like writing articles on creating proprietary tools for game development). Through experience and code reuse new applications can be written in mere hours (my first MFC app took about two days to complete, my second took about two hours). Hobbyists and professionals alike no longer have an excuse to hack about, now that they have the proper tools.<br />
<br />
 Joe Houston<br />
<br />
 <a href='mailto:Jhouston@agilitycom.com' title='E-mail Link' class='bbc_email'>jhouston@agilitycom.com</a><br />
<br />
<em class='bbc'> If you’re interested in seeing other articles relating to this subject (picking objects/verts in 3D space, drawing marquees in 3D, etc) please let me know. I’m always interested in feedback, and I welcome all comments and corrections.</em>]]></description>
		<pubDate>Tue, 01 May 2001 11:32:45 +0000</pubDate>
		<guid isPermaLink="false">2e99b7de2efefc11e5f273f35e10e0c7</guid>
	</item>
	<item>
		<title>Choosing Between Utility and Modifier Plug-Ins...</title>
		<link>http://www.gamedev.net/page/resources/_/technical/apis-and-tools/choosing-between-utility-and-modifier-plug-ins-r1140</link>
		<description><![CDATA[Programmers spend a lot of time developing tools for their artists to use, but the question of how best to develop the tool they need is not always an easy one to answer. The first time I had to develop a plug-in for 3D Studio Max, I was faced with a choice: "What kind of plug-in should I develop - a utility or a modifier?" I then spent a considerable amount of time performing tests to determine which would be the best way to go. Now, lucky for you, rather than going through that same process yourself, you can just read this article, which will hopefully help shorten that testing time.<br />
<br />
 The main topic of this article, then, will be the difference between developing a modifier and a utility plug-in. We'll discuss the advantages and drawbacks of each of these plug-in types, as well as the use of the Microsoft Foundations Class (MFC) inside a utility. Although this article could potentially be of interest to anybody working with 3D Studio Max, I'd recommend that the reader have a basic knowledge of developing 3D Studio Max plug-ins in order to get the most out of this. A good resource to check out for a little more background is the 1998 Gamasutra article "<a href='http://www.gamasutra.com/features/programming/19980220/3dsmax_01.htm' class='bbc_url' title='External link' rel='nofollow external'>From 3D Studio Max to Direct3D</a>" by Loic Baumann.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Comparing Modifier and Utility Plug-Ins</strong></span><br />
<br />
First, the basics. A modifier is a plug-in that modifies objects (also called nodes) in some way. A utility is a plug-in that is useful for implementing modal procedures such as 3D paint, dynamics, and so forth. The major difference is that utilities are not designed to modify objects, so you won't find a utility that, say, modifies the texture vertices of a mesh as the UVW Unwrap modifier does (although it can theoretically be done, as we will see later).<br />
<br />
 Let's first take a look at the advantages of using modifiers.<br />
<br />
<br />
<span style='font-size: 18px;'> <strong class='bbc'>Advantages of Developing a Modifier</strong></span><br />
<br />
The biggest advantage a modifier has over a utility is the geometry pipeline. It's a little bit complicated at the beginning to understand, but once you have an understanding of how this pipeline works, modifiers can become very powerful.<br />
<br />
 An understanding of the geometric pipeline system is important for developers creating plug-ins that deal with geometry in the scene. The pipeline is the system used by 3D Studio MAX that allows a node in the scene to be altered, perhaps repeatedly, through the application of modifiers. At the beginning of a pipeline is the Base Object. This is either a procedural object or just a simple mesh. At the end of a pipeline is the world space state of the object. This world space state is what appears in the 3D viewports and is rendered.<br />
<br />
 For the system to evaluate the state of the object at the end of the pipeline, it must apply each modification along the way, from beginning to end. For example, say a user creates a procedural cylinder in the scene, applies a Bend modifier to it, and then applies a Taper modifier to it. As the system evaluates this pipeline, it starts with the state of the cylinder object. As this object state moves along the pipeline, it first encounters the Bend modifier, and the system asks the Bend modifier to apply its deformation to the object state. The result of this operation is then passed as the source into the Taper modifier, and the Taper then applies its own deformation. The result of this operation is then passed to the system which translates the result into world space, and the state of the node in the scene is complete.<br />
<br />
 To maximize the speed with which the system can evaluate the state of a node, the system maintains a World Space Cache for each node in the scene. This world space cache is the result of the node's pipeline; it reflects the state of the object in world space after everything has been applied to it. Along with the cache, the system maintains a Validity Interval. The validity interval indicates the period of time over which the cache accurately reflects the state of the node.<br />
<br />
 With the cache structure inside modifiers, the user is able to remove, copy, or paste a modifier from the modifier stack. The pipeline is then re-evaluated to build a new world space state for the objects that have been modified, and we are able to collapse the modifier stack of an object. Collapsing the modifier stack means that:<br />
 <ul class='bbcol decimal'><li>Every modifier on the object applies its changes;</li><li>The resulting world space state becomes the current state of the object;</li><li>All modifiers are erased, so going back is no longer possible.</li></ul> It's more or less like flushing the modifier pipeline.<br />
<br />
 Remember, in Kinetix' 3DS4, the user wasn't even able to change past modifications, so this is now a very powerful feature! But this modifier pipeline is also modifiers' biggest drawback…<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Drawbacks of Developing a Modifier</strong></span><br />
<br />
Developing a modifier is no easy task even for experienced programmers, because you have to know exactly how the pipeline works. For example, you have to tell the pipeline which channels of the object you are going to change (i.e., the channels that the modifier needs in order to perform its modification) and which channels you are going to use (i.e. the channels that the modifier actually modifies). For instance, you have the texmap channel (texture vertices and procedural mappings), the geometry channel (the vertices of the object), and so on. If you don't tell the pipeline which channels you are going to change, your changes won't affect the object! This just goes to show that you need to know exactly how the pipeline works and what you are going to do to objects before developing a modifier.<br />
<br />
 As an example of the complexity of the pipeline, let's say you want to have a modifier that lets the user manually select some given number of faces, then perform several operations on those faces. To do so, you'll need to copy and paste about 800 lines from the mesh select or edit mesh modifier, and then you'll have to ensure that the code actually works in your modifier. You have to think about that before developing a modifier.<br />
<br />
 The geometry pipeline is a very nice feature when you discover it as a user, but when you use it everyday, it quickly becomes a burden. As another example, if you want to modify the texture vertices of some given number of faces, you have to first select these faces, then modify their texture vertices. To do that you'll need the edit mesh or mesh select modifier to select faces, and then you'll have to add a <span style='font-family: Courier New'><span style='color: #000080'>UVW Unwrap</span></span> modifier to change the texture vertices of the selected faces. In this silly example, two modifiers have been used to perform the desired operation. And if you want to do this operation again, you will need to add these two modifiers once again. As a result, the modifier stack keeps on growing and you are forced to collapse the modifier stack regularly to avoid filling memory with the local cache of each modifier.<br />
<br />
 So while modifier plug-ins have distinct benefits, they've also got some serious disadvantages. Now let's take a look at utility plug-ins.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Advantages of Developing a Utility</strong></span><br />
<br />
Utility plug-ins are easier to develop than modifiers; you don't need to understand a complex pipeline to develop a utility. Only a few basics of 3D Studio Max programming are even necessary really, and you generally only need to know where in the scene you can find the information that you need (although even that can become a headache!) For example, to get the number of selected nodes as well as their pointers you would use the following code:<br />
<br />
 [indent]<pre class='prettyprint'>// Get Interface pointer, Interface is the most useful<br />// class in 3D Studio Max<br />Interface* ip = GetCOREInterface();<br />if ( ! ip )<br />  return;<br /><br />// Get the number of selected nodes in NumSelNodes<br />const int NumSelNodes = ip-&gt;GetSelNodeCount();<br /><br />// Now scan all the selected nodes one at a time<br />for (int i = 0 ; i &lt; NumSelNodes; i++) {<br />  INode* node = ip-&gt;GetSelNode( i );<br />  if (!node)<br />	continue;<br />  DoSomethingOnThisNode(node);<br />}</pre><br />
[/indent] Let's have a quick overview of materials and the material editor in 3D Studio Max and how these materials are used for real time games. The material editor is used to manage the materials. It can create materials such as Blend, Composite, Double sided, Matte / Shadow, Morpher, Multi / SubObject, RayTrace, Shellac, Standard, Top / Bottom, etc.<br />
<br />
 For real time games, we only use the Standard and Multi/Subobject materials. Standard materials have properties such as ambient color, diffuse color, specular color, glossiness, opacity, bump, etc. For real time games, we set a bitmap texture in the diffuse channel of a material. (In other words, we replace the overall color with an overall texture.)<br />
<br />
 In 3D Studio Max, a node can reference one - and only one - material, any kind of material previously described. There is not (as in Alias|Wavefront Maya) the possibility to set a different material for each face. That's why the Multi/Subobject materials exist! When you want an object to have several different materials applied to individual parts of the object, you use a Multi/Sub-object material, which is a material that holds a number of different materials (called submaterials ) inside it.<br />
<br />
 We usually create a multi/subobject material that contains standard materials with each a bitmap texture in the diffuse channel. So how can we now set the good texture on a part of a mesh from this multimaterial?<br />
<br />
 Each face of the mesh has an integer which is the submaterial number in the node's multi/subobject material called the face material ID. It maintains the identification with the submaterial within the multi/subobject material. So when a multimaterial is applied on a node, if the faces from 0 to 100 have the face material ID 0, they reference the first submaterial (so it references the bitmap texture contained in this submaterial); if faces 101 to 200 have the face material ID 1, they reference the second submaterial; and so forth. When a standard material is applied on a mesh, these face material IDs are not used.<br />
<br />
 Now to get all materials that are in your scene, you can use the following code ("In the scene" means that all these materials are applied to at least one of the nodes in the scene):<br />
<br />
 [indent]<pre class='prettyprint'>//Get Interface pointer, Interface is the most useful class of 3D Studio Max<br />Interface* ip = GetCOREInterface();<br />if ( ! ip )<br />  return;<br /><br />//Get all materials stored in a library of materials<br />//The MtlBaseLib class is a library of MtlBase entries.<br />MtlBaseLib* lib = ip-&gt;GetSceneMtls();<br />if (!lib)<br />  return;<br /><br />const int NumMat = lib-&gt;Count();<br />for( int i = 0; i &lt; NumMat; i++ ){<br />  MtlBase* mtl = static_cast&lt;MtlBase*&gt;( (*lib)&#91; i &#93; );<br />  if ( ! mtl)<br />	continue;<br />  DoSomethingOnThisMat( mtl );<br />}</pre>[/indent] One advantage of using a utility over a modifier plug-in is that you can use several utilities at the same time if they have modeless dialog boxes instead of dialog boxes set in the 3D Studio Max rollup panel. This is not possible with modifiers, where the active modifier is the one which is selected in the modifier stack, but two modifiers can't be active at the same time.<br />
<br />
 Another advantage is that you can drive modifiers from a utility. Let's see how to instantiate modifiers in 3D Studio Max.<br />
<br />
 First, you can't use the new operator to instantiate all the classes you need in 3D Studio Max. It will work for some classes but most of them are not instantiable - for example the modifiers classes. The 3D Studio Max system uses unique class Ids (a unique set of 2 32-bits wide integers) to identify each class. So to instantiate a class you have to use the <span style='font-family: Courier New'><span style='color: #000080'>CreateInstance</span></span> function from the class interface . You pass the <span style='font-family: Courier New'><span style='color: #000080'>CreateInstance</span></span> function a class ID and it returns a pointer to an instance of the desired class. This is a class factory design pattern that we can find as well in the Microsoft Component Object Model (COM) with the <span style='font-family: Courier New'><span style='color: #000080'>CoCreateInstance</span></span> function.<br />
<br />
 In our case, if we have the Edit Mesh and UVW Unwrap modifiers class IDs, we can create instances of these modifiers. And we are able to apply them programmatically on some objects in the scene (See attached resource).<br />
<br />
<p class='bbc_center'> Example 1: How to create an instance of the UVW Unwrap modifier<br />
</p><br />
 [indent]<pre class='prettyprint'>#ifndef UNWRAP_CLASSID<br />  #define UNWRAP_CLASSID Class_ID(0x02df2e3a,0x72ba4e1f)<br />#endif<br />Interface* ip = GetCOREInterface();<br />if ( ! ip )<br />  return;<br />Modifier* UVWUnwrapMod =static_cast&lt;Modifier*&gt; (ip-&gt; CreateInstance(OSM_CLASS_ID, UNWRAP_CLASSID));</pre>[/indent] But now that you are able to add through code modifiers to some nodes, you'd surely like to use their functions, right? This is where things become complicated. As you've probably already seen, the C++ projects generated by the 3D Studio Max wizard have the same structure: the classes are declared in the same file as their implementation in the cpp file. It's a pity that header files don't contain class definitions, because it would be so simple to include the header file of the class you need (in our case a modifier) in your project settings and link with the lib file from the class project, as we usually do when using a library.<br />
<br />
 But it's not possible to include the header files with the 3D Studio Max modifiers classes, so here's the workaround I've found. It may well not be not the best way to do this, and I imagine I'll receive a flood of e-mails suggesting better methods, but if you do need one, this works fine. It's actually just a copy and paste operation; I copy the class definitions from the original modifier cpp file in a header file in my project, then I copy all the functions of the class that I want to use (and their dependencies) in a cpp file in my project. Then I add my own functions in the class definition to extend this class.<br />
<br />
 I was then able to call functions from the modifier. As I said, there are probably much better solutions, but as usual, I only had a limited time to reach my goal so I had to make it work in any way I could! And it does work; I succeeded in driving the Edit Mesh, the UVW Map and the UVW Unwrap modifiers from a utility plug-in.<br />
<br />
 (Notably, most of these problems concerning the header files will be solved in the future, because 3D Studio Max is becoming an open source project. See <a href='http://www2.discreet.com/games/developers_corner.html' class='bbc_url' title='External link' rel='nofollow external'>http://www2.discreet...ers_corner.html</a> for more information.)<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Drawbacks of Developing a Utility</strong></span><br />
<br />
The big drawback of utilities is that when you modify an object in a utility, say, by changing the face selection set, the changes don't "stay forever." Once the viewport is redrawn, the geometry pipeline is re-evaluated (as previously described), and your changes are lost. To make your changes "stay forever," you'll need to collapse the modifier stack (<strong class='bbc'>HTML Link on the project</strong>). This is the main constraint that you have to keep in mind when developing a utility plug-in: modifications are only allowed on collapsed objects (objects that have their modifier stack collapsed). And sometimes the artists don't want you to collapse the modifier stack of their objects because if you do so, they won't be able to go back into the modifier stack history.<br />
<br />
 Let's introduce the Physique and Skin modifiers. They are used to assign bones to some vertices of a mesh to animate it and use inverse kinematics. Physique is designed for biped character animation; it has a predefined biped skeleton with 2 arms, 2 legs, 2 feet, a head, etc. Skin is designed to add bones to any part of a mesh; there is no predefined skeleton. If Skin or Physique modifiers are applied on a node, this node can't have its modifier stack collapsed - or all the bones-to-vertices assignation will be lost! (If a node has a modifier that stores its own information and this information can't be stored in the mesh, the modifier stack of this node can't be collapsed. Well, theoretically, it can be collapsed… it won't crash, but all your information will be lost!)<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Possibility of Using the Microsoft Foundation Classes in Utility Plug-Ins</strong></span><br />
<br />
Plug-ins are usually developed using the Microsoft Windows Win32 API. But with utility plug-ins you can use the Microsoft Foundation Class as well. The Microsoft Foundation Class Library is an "application framework" for programming in Microsoft Windows. The MFC framework is a powerful approach that lets you build upon the work of expert programmers for Windows. As far as I know, utility plug-ins are the only plug-in type where MFC can be used. To download a skeleton utility that uses MFC, have a look at the Discreet web site: <a href='http://www.ktx.com/mfc' class='bbc_url' title='External link' rel='nofollow external'>http://www.ktx.com/mfc</a>.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Advantages of Using MFC</strong></span><br />
<br />
MFC shortens development time, provides tremendous support without reducing programming freedom and flexibility, and gives its user easy access to "hard to program" user-interface elements and technologies. MFC makes it easy to program features like property sheets ("tab dialogs"), print preview, and floating, customizable toolbars.<br />
<br />
 If you use the Microsoft Visual C++ compiler, MFI is fully integrated with the development environment interface. For example: you have the MFC ClassWizard which helps you to map messages and controls from your dialog boxes; since version 6.0 of Microsoft Visual C++, it automatically shows the member functions of the class while typing. This is not possible when using the Win32 API because a lot of functions use a window handle (<span style='font-family: Courier New'><span style='color: #000080'>HWND</span></span>) and global functions to deal with your dialog boxes controls. This means, for example, that there is no class regrouping all functions of the list boxes or combo boxes - while in MFC, you have the <span style='font-family: Courier New'><span style='color: #000080'>CListBox</span></span> and <span style='font-family: Courier New'><span style='color: #000080'>CComboBox</span></span> classes.<br />
<br />
 For example, when you want to empty a list box using the Win32 API, you have to use the following function:<br />
<br />
 [indent]<pre class='prettyprint'>SendMessage(<br />  (HWND) hWnd, 	// handle to destination window<br />  LB_RESETCONTENT, // message to send<br /><br />  (WPARAM) wParam; // not used; must be zero<br />  (LPARAM) lParam; // not used; must be zero<br />);</pre>[/indent] You have to know the <span style='font-family: Courier New'><span style='color: #000080'>HWND</span></span> of your list box. And messages processing is a burden to use.<br />
<br />
 In MFC, you just have to do :<br />
<br />
 [indent]<pre class='prettyprint'>CListBox MyListBox;   	// list box that has been mapped<br />MyListBox.ResetContent();<br />//This is part of the CListbox class, no message processing in<br />//your code (although it is done implicitly)</pre>[/indent] Moreover, a strong advantage of MFC over the Win32 API is that you can download a lot of complete MFC projects with source code. So you rarely start from scratch when you have to do, for instance, a treeview with the drag and drop functionalities enabled. Have a look at the following web site to download some examples of MFC projects: <a href='http://codeguru.com/' class='bbc_url' title='External link' rel='nofollow external'>http://codeguru.com/</a> . This web site has everything you need to use MFC; I managed to save a couple of weeks using existing code.<br />
<br />
 <span style='font-size: 12px;'><strong class='bbc'>Drawbacks of Using MFC</strong></span><br />
<br />
You should probably know before choosing to use the MFC inside 3D Studio Max that you won't be getting any support from Discreet. MFC is not officially supported, so you have to use it at your own risk. This will be a concern with pure MFC problems and problems with integration of MFC inside 3D Studio Max. Here are some of the strange problems you may encounter when combining the two:<br />
<br />
 Most of the problems met when using MFC are 3D Studio Max functions from the kernel that don't work. For example, when using release 3 or later, if you want to have customizable keyboard shortcuts for your plug-in (which are very useful), you need to call the functions <span style='font-family: Courier New'><span style='color: #000080'>ActivateShortCutTable</span></span> and <span style='font-family: Courier New'><span style='color: #000080'>DeactivateShortcutTable</span></span> as follows:<br />
<br />
 [indent]<pre class='prettyprint'>//This is a class to create the keyboard shortcuts<br />class PluginShortcutManagerCB : public ShortcutCallback<br />{<br />  virtual BOOL KeyboardShortcut (int id);<br />}<br />const ShortcutTableId kMappingShortcuts = 0x34f274f4;<br /><br />//Create an instance of this class<br />PluginShortcutManagerCB* mappingShortcutCB = new PluginShortcutManagerCB;<br />Interface* ip = GetCoreInterface();<br /><br />//Activate the shortcuts<br />ip-&gt;ActivateShortcutTable(static_cast &lt; ShortcutCallback* &gt;<br />   	(mappingShortcutCB), kMappingShortcuts);<br /><br />//DeActivate the shortcuts<br />ip-&gt;DeactivateShortcutTable(static_cast &lt; ShortcutCallback* &gt;<br />   	(mappingShortcutCB), kMappingShortcuts);</pre>[/indent] And <span style='font-family: Courier New'><span style='color: #000080'>DeactivateShortcutTable</span></span> crashes each time you call it when using MFC, while it works fine when you use just the Win32 API.<br />
<br />
 To solve this problem, I have created another DLL, using only the Win32 API, which links with my MFC DLL and then I register, activate and deactivate the keyboard shortcuts by calling functions in this Win32 DLL. It's a patch, but it works fine!<br />
<br />
 So there are issues with using MFC, but to date I have always been able to solve the problems that I've run into when using MFC.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Conclusions</strong></span><br />
<br />
To sum up then. A modifier is a plug-in made to modify objects in some way and that benefits from the geometry pipeline, while a utility is a plug-in that is useful for implementing modal procedures but is not designed (in theory) to modify objects.<br />
<br />
 In my opinion, modifiers should be used when you can't develop a utility, because utility plug-ins are simpler to develop. A utility should be developed to:<br />
 <ul class='bbcol decimal'><li>Get information from the scene without modifying objects, or</li><li>Modify objects only if the objects can have their modifier stacks collapsed, or</li><li>Drive modifiers and build a "super utility plug-in".</li></ul> So knowing the constraints and the specifications of the tool that you have to develop, you should now be able to choose wisely between the two types of plug-in, as well as the Microsoft Foundation Classes. And remember: programming in 3D Studio Max, your code might not always look nice, not when you have to make things work in any way you can, but you usually can make things work.<br />
<br />
 <br />
<span style='font-size: 18px;'><strong class='bbc'>Acknowledgments and References</strong></span><br />
<br />
Thanks to Jurie Horneman for his help in writing this article.<br />
<br />
 Further information about this topic can be found at:<br />
 <ul class='bbc'><li>The Discreet web site : <a href='http://www.discreet.com/' class='bbc_url' title='External link' rel='nofollow external'>http://www.discreet.com/</a></li><li>The 3D Studio Max SDK Forums : <a href='http://support.discreet.com/%7E200' class='bbc_url' title='External link' rel='nofollow external'>http://support.discreet.com/~200</a></li><li>The 3D Studio Max Open source forums: <a href='http://support.discreet.com/%7Emaxopensource' class='bbc_url' title='External link' rel='nofollow external'>http://support.discreet.com/~maxopensource</a></li><li>Gamasutra article about <a href='http://www.gamasutra.com/features/programming/19980220/3dsmax_01.htm' class='bbc_url' title='External link' rel='nofollow external'>Developing 3D Studio Max plug-ins</a></li><li>Using Max with MFC : <a href='http://www.ktx.com/mfc' class='bbc_url' title='External link' rel='nofollow external'>http://www.ktx.com/mfc</a></li></ul>]]></description>
		<pubDate>Mon, 31 Jul 2000 10:07:51 +0000</pubDate>
		<guid isPermaLink="false">81f7acabd411274fcf65ce2070ed568a</guid>
	</item>
</channel>
</rss>
