XNA DebugOverlay Utility

November 21st, 2009 shyam No comments

The DebugOverlay utility is a class that I’ve been using in my XNA projects for a while. It allows me to draw visualization objects from anywhere in my application – even in separate threads.

Some areas where I have used this utility are:

  • The AI system can display a units’ velocity and position through Lines, Arrows, and Spheres. Use ScreenText to show the current state or goal hierarchy of a given unit.
  • The Physics system can use bounding boxes and spheres to show collision volumes. Points can be used to show raycast intersections or points of impact.
  • The Graphics system can use Spheres, Lines, and Arrows to show the position and direction of lights.
  • The Editor (or other tools) can use Lines, Arrows, and Bounding Boxes for axis representation during translate/rotate/scale.
  • Vertex Display – For a software-based skinning implementation, I used Points to visualize the locations of my vertices, and Spheres for the locations of the bones. It’s possible to use Spheres for everything, but thousands of Spheres can get a little expensive.

This utility is only meant for Debug purposes, and therefore uses the [Conditional("DEBUG")] tag on each of it’s exposed methods.

To use the DebugOverlay, create the object during Initialization:

1
new DebugOverlay(GraphicsDevice, Content);

Call the visualization functions from anywhere in your code:

1
2
3
4
5
6
void ScreenText(string text, Vector2 pos, Color c)
void Line(Vector3 start, Vector3 end, Color color)
void Arrow(Vector3 start, Vector3 end, float arrowSize, Color color)
void BoundingBox(BoundingBox boundingBox, Color color)
void Point(Vector3 pos, Color color)
void Sphere(Vector3 pos, float radius, Color color)

In your Draw routine, call the DebugOverlay.Draw method, passing in the projection and view matrices:

1
DebugOverlay.Singleton.Draw(mCamera.ProjectionMatrix, mCamera.ViewMatrix);

I made a small sample application to show off the functionality. Below is a screenshot and the complete source code.

Download: source + demo

Categories: Code Tags: , , ,

Artemis Chronicle Tools

August 15th, 2009 shyam No comments

During the first semester of working on NitroX and Artemis Chronicle, our design and content pipeline was very slow. Simple things like creating a level and placing a box were arduous tasks. Placing an item involved flying the camera around the level, writing down it’s rough coordinates, hard coding the coordinates, and then tweak these values until the box is in the desired position. (Thankfully, we were using C# which pretty much eliminated any compile time. Doing this in C++ would have been impossible).

This created a situation where we were unable to prototype levels quickly, and time that could be better used somewhere else was being wasted.

Because of this, I devoted the first few weeks of the second semester to full-time tool development. Two of the more useful tools created are described below. These tools, once created, were continuously used and refined throughout the entire life of the project.

Level Editor:

Artemis Chronicle and the NitroX engine have a completely integrated level editor. The editor allows 3D navigation through the world (using Maya camera controls), object placement (translation, rotation, scale), object property exposure (including physics volumes), trigger volumes (used for scripted events), and interactive camera sequencing (allows us to create cut-scenes and cinematics in a point-and-click fashion instead of in code).

The editor runs on Windows and is written in C#, allowing for close integration into the XNA content pipeline. The editor data is serialized out to an XML format (which is later compressed for application deployment), sent through the content pipeline, and imported directly into the NitroX engine for use on both Windows and Xbox 360.

Mesh Viewer:

The Mesh Viewer is a tool that lets our artists quickly preview their work before sending it off to be integrated into the latest build of the game. As anyone who’s used the FBX exporter knows, exporting from Maya does not always go smoothly, so this tool allows the artist to catch any errors early, thus saving time for the entire team.

Animations can be chained together to create sequences, and then previewed in a real-time manner. Playback speed, blending parameters, and looping can also be adjusted via the user interface.

Categories: Code, General Tags: , , , ,

Tatami Mat Unit Converter

March 31st, 2009 shyam No comments

Recently I’ve begun searching for apartments in Tokyo for a tentative move. In Japan, the tatami mat is widely used as the unit of measurement for apartments and other living quarters. From a Western perspective, it can be a little hard to grasp exactly what “15 tatami mats” is. Below is a little converter application that I wrote, to aid me in my search for real estate :)

In: Units:
Value:
Out: Units:
Result:
Tatami Units*:

* Tatami mat sizes vary slightly by region. Edoma (江戸間), in the Tokyo region, are around 176 x 88cm. Kyoma (京間), in the Kyoto region, are around 191 x 95.5cm. For more information, see Wikipedia.

You can download the properly formatted source code here.

Categories: Code, Japan (日本) Tags:

Non-Linear Roots

December 24th, 2008 shyam No comments

An implementation of the Newton-Raphson method to compute the root of a non-linear equation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
//--------------------------------------------------------------------
// Name: Shyam M Guthikonda
// Email: shyamguth@gmail.com
// URL: http://shy.am
// Desc: Program to calculate the root of a non-linear function, utilizing
//		 the Newton-Raphson method.
//--------------------------------------------------------------------
 
//--------------------------------------------------------------------
// Include Files
//--------------------------------------------------------------------
#include "math.h"
#include "windows.h"
 
//--------------------------------------------------------------------
// Globals
//--------------------------------------------------------------------
unsigned int	Iter;			// Keeps track of the number of iterations each
								// root location method requires. Avoids the need
								// to pass an extra parameter by reference.
 
ULONG			ErrorFlags = 0;	// Used to keep track of any errors.
 
// Possible error flags
enum ERRORS
{
	ERRORS_DERIV_EQ_ZERO	= 1,
	ERRORS_DENOM_EQ_ZERO	= 2,
	ERRORS_MAX_ITERATION	= 4,
	ERROR_FORCE_32BIT		= 0x7FFFFFFF
};
 
// Struct to hold the X and Y roots of a non-linear system
struct Point
{
	double X;
	double Y;
};
 
//--------------------------------------------------------------------
// Name: F1()
// Desc: The first function.
//--------------------------------------------------------------------
double F1( double x, double y )
{
	return ( (x * x) + 1 - y );
}
 
//--------------------------------------------------------------------
// Name: F2()
// Desc: The second function.
//--------------------------------------------------------------------
double F2( double x, double y )
{
	return ( 3 * cos( x ) - y );
}
 
//--------------------------------------------------------------------
// Name: F1dx()
// Desc: Derivative of the first function with respect to x.
//--------------------------------------------------------------------
double F1dx( double x, double y )
{
	return ( 2 * x );
}
 
//--------------------------------------------------------------------
// Name: F1dy()
// Desc: Derivative of the first function with respect to y.
//--------------------------------------------------------------------
double F1dy( double x, double y )
{
	return ( -1 );
}
 
//--------------------------------------------------------------------
// Name: F2dx()
// Desc: Derivative of the second function with respect to x.
//--------------------------------------------------------------------
double F2dx( double x, double y )
{
	return ( -3 * sin( x ) );
}
 
//--------------------------------------------------------------------
// Name: F2dy()
// Desc: Derivative of the second function with respect to y.
//--------------------------------------------------------------------
double F2dy( double x, double y )
{
	return ( -1 );
}
 
//--------------------------------------------------------------------
// Name: Es()
// Desc: Calculates the percent tolerance, given a desired number of
//		 significant figures.
//--------------------------------------------------------------------
double Es( unsigned int SigFigs )
{
	return (.5 * pow( 10.0, (2.0 - (double)SigFigs) ));
}
 
//--------------------------------------------------------------------
// Name: NewtonRaphson()
// Desc: Determines the root of a non-linear function using the
//		 Newton-Raphson method.
//--------------------------------------------------------------------
Point NewtonRaphsonNonLinear( double Xi, double Yi, double Es, unsigned int Imax )
{
	double Ea = 1000.0, Denom;
	double Xrold = Xi, Yrold = Yi;
	Point Root;
	Iter = 0;
 
	Root.X = Xi;
	Root.Y = Yi;
 
	// No errors yet with this method!
	ErrorFlags = 0;
 
	while ( 1 )
	{
		Xrold = Root.X; Yrold = Root.Y;
		Iter++;
 
		// Prevent division by 0.
		Denom = F1dx( Root.X, Root.Y ) * F2dy( Root.X, Root.Y ) - F1dy( Root.X, Root.Y ) * F2dx( Root.X, Root.Y );
		if (Denom == 0.0)
		{
			// Set the given error flag and return the most recent root estimates.
			ErrorFlags |= ERRORS_DENOM_EQ_ZERO;
			return Root;
		}
 
		// Newton-Raphson formula for a non-linear system.
		Root.X = Xrold - ( (F1( Xrold, Yrold ) * F2dy( Xrold, Yrold )) - (F2( Xrold, Yrold ) * F1dy( Xrold, Yrold )) ) / Denom;
		Root.Y = Yrold - ( (F2( Xrold, Yrold ) * F1dx( Xrold, Yrold )) - (F1( Xrold, Yrold ) * F2dx( Xrold, Yrold )) ) / Denom;
 
		// Calculate the relative absolute error, Ea (of X term)
		// Don't calculate the error on the first iteration since there is no previous term
		if ( (Root.X != 0.0) && (Iter != 1) ) Ea = abs( (Root.X - Xrold) / Root.X ) * 100;
 
		// Root found within error range desired, or number of iterations has
		// reached the maximum amount permitted by Imax. Either way: return.
		if ( Ea < Es	  )	{ return Root;									   }
		if ( Iter >= Imax ) { ErrorFlags |= ERRORS_MAX_ITERATION; return Root; }
 
	} // End while
}
 
//--------------------------------------------------------------------
// Name: ErrorMsg()
// Desc: Function to print the currently set bits in ErrorFlags, of enum
//		 type ERRORS.
//--------------------------------------------------------------------
void ErrorMsg()
{
	if ( ErrorFlags )
	{
		printf( "Errors:\n" );
		if ( ErrorFlags & ERRORS_DERIV_EQ_ZERO  ) printf( "\tDerivative = 0\n"			);
		if ( ErrorFlags & ERRORS_DENOM_EQ_ZERO  ) printf( "\tDenominator = 0\n"			);
		if ( ErrorFlags & ERRORS_MAX_ITERATION  ) printf( "\tMax Iterations Reached\n"	);
	} // End if errors
}
 
//--------------------------------------------------------------------
// Name: _tmain() (Application Entry Point)
// Desc: Entry point for the program.
//--------------------------------------------------------------------
int _tmain()
{
	Point		Root;
	double		fEs = Es( 6 );	// Number of desired significant figures.
 
	printf( "\nRoots Accurate to 6 Sig Figs\n\n" );
 
	// NEWTON-RAPHSON-----------------------------------------------
	Root = NewtonRaphsonNonLinear(
					1.5,			// Initial X guess
					3.5,			// Initial Y guess
					fEs,			// Percent tolerance
					1000			// Maximum iterations allowed
					);
 
	printf( "Method: Newton-Raphson (Non-Linear)\n" );
 
	// Display any errors.
	ErrorMsg();
 
	printf( "X_Root = %g\n", Root.X );
	printf( "Y_Root = %g\n", Root.Y );
	printf( "Iterations = %i\n", Iter );
 
	return 0;
}
Categories: Code Tags:

WoWCalc

April 7th, 2008 shyam No comments

This is an in-game World of Warcraft calculator, similar to the standard Windows calculator. It was written with XML and Lua.

Download: source

Categories: Code Tags: , , , ,

Finite State Machine Framework

February 15th, 2008 shyam No comments

A simple FSM Framework and example application written in C++, based on ideas presented in “Programming Game AI by Example” by Mat Buckland.

Download: source

Categories: Code Tags: , , , ,

Depth of Field

December 10th, 2007 shyam No comments

A flexible, GPU-based depth of field module built on top of the OGRE 3D engine. Uses GLSL.

Download: source (Ogre)

Categories: Code Tags: , , , , ,

WoWSlang

November 30th, 2007 shyam No comments

It is an in-game World of Warcraft dictionary, with definitions of commonly used terms and acronyms. There is a GUI component, as well as useful console commands for quick-lookups. Written with XML and Lua.

Download: source

Categories: Code Tags: , , , ,

Procedural Clouds

November 21st, 2007 shyam No comments

A procedurally generated, real-time, GPU-based cloud module, written on top of the OGRE 3D engine. Cloud formation, movement, lighting and layers. One version was also done in pure OpenGL/C++. Both implementations make use of GLSL.

There is also a paper that goes along with this project, to better explain the techniques used.

Download: source (Ogre), source (OpenGL)

Categories: Code Tags: , , , , ,

Portals in Ogre

October 25th, 2007 shyam No comments

A portal system, similar to that found in Half Life 2: Portal. Utilizes multiple viewports to achieve the effect. Implemented on top of the OGRE 3D engine.

Download: source (Ogre)

Categories: Code Tags: , , , , ,