Hi there!


Thanks for checking out my portfolio.

I’m a graduate student in the Game Design and Development program at the Rochester Institute of Technology.

-Jay Austin

 

Zeal – An AR RTS in 3D (now with more acronyms)


The latest game I’ve been working on is an augmented reality (AR), real time strategy (RTS) project for my 3d graphics programming class. It was completed in about 10 weeks using a six person team made up of Nimesh Desai, Chip Hilseberg, Jon Lobaugh, Eric Moreau, Josh Wilson and me.

Essentially, “augmented reality” is the process of blending the real world with virtual stuff created on the computer. In Zeal, we made a strategy game where you move physical game pieces around on a regular table but you see the results in a virtual world built by a computer.

Typical game marker

Typical game marker

The computer is able to identify whats going on in the real world thanks to a hanging camera suspended above game table. With a little help from ARToolKit our software is able to recognize printed markers and translate their location, orientation and movement into game coordinates. This lets us move game pieces across the board (like chess or warhammer) and see reciprocating action on the game map. Finally we overlay the game map and all the game units on top of the input from the camera for a blended image that merges real life with the game.

Gameplay is a simplified real time strategy system. Two opposing players use a set of twenty markers to spawn units that can be moved across the game map. Control points are scattered across the map and players receive points for capturing and defending control points. Four different unit types (three offensive and one healer) automatically move to the location of the physical marker they’re attached to and automatically battle with any nearby enemy forces.

To top it off, we slapped a covered marker on the back of the players hands allowing them to uncover the maker during gameplay to release special powers like area attacks and unit teleportation.

We’ve got some good video demos too, Ill update the post as soon as they’re uploaded.

Title "screen" hovering over the physical game table

Title "screen" hovering over the physical game table

Josh "calibrating" the camera

Josh "calibrating" the camera

The overhead camera

The overhead camera

zeal7

Prepping for a game

Side view of the playfield

Side view of the playfield

Overhead view

Overhead view

See the physical markers underneath the virtual units

See the physical markers underneath the virtual units

zeal4

Overhead shot with more units

Side view with control points

Side view with control points

 

Spore Islands


The party has started on Facebook with the Beta release of Spore Islands. I worked on this app over the summer as part of my internship with Area/Code in New York City.

It’s a great game and it implements a lot of features that were surprisingly missing in the original. As a player you get five creatures that you can evolve to your heart’s content. Your creature’s look is dependent on the personality and attributes you give it and the kicker comes when you drop your custom creature on to an island filled with creatures created by your friends. The game is balanced so that every creature has a natural predator and you have to keep up with daily evolution to stay ahead of your friends.

Check it out, http://apps.facebook.com/sporeislands/

Time to party

Time to party

Challengers approach

Challengers approach

Awww yeah

Awww yeah

 

Flash 10 3D: Good, Bad and Ugly


I’ve been playing around with the Flash 10 3D API a lot lately and it’s time to break down the pros and cons using some of the stuff I’ve learned. The current implementation lacks a lot of features that you’d normally get for free with libraries like DirectX and OpenGL but hopefully Adobe will keep making improvements with future versions.

Lets talk specifics…

3D into 2D
When you’re using a traditional 3D renderer you build a 3D scene (a.k.a. a list of vertices that exist across an x, y, z coordinate system), set up a viewport, add a few lights and then pass those lists off to the “draw” function. That function looks at the scene through the viewport you defined and calculates how your set of 3D coordinates should be mapped on to a 2D surface (your screen). In Flash, the drawTriangles() function needs the 2D coordinates up front so it’s up to you to do the 3D to 2D conversion. On the bright side the Utils3D class has a handy projectVectors() function to handle most of the grunt work but being forced to keep track of the separate 2D and 3D coordinate lists is a hassle.

Z-Sorting
The trend of passing tedious calculations off to the user continues when you start drawing polygons that overlap when viewed through your given perspective. The “Z” depth (the distance between your camera and the objects in the scene) should determine which polygons (or pieces of polygons) are visible at any given time. In simpler terms, the polygons closest to the screen should be drawn last to ensure that they’re completely visible. Z-sorting is something you usually get for free but drawTriangles() only draws its list of shapes in the order you send it which means the list needs to get sorted before you start drawing. For my projects I maintain a list of all faces in the scene (Vector3Ds) and sort on “w” attribute.  The reasons for this limitation are rooted in the whole 3D to 2D problem and a solution could be rolled into either a more unified draw call or at a minimum a better Utils3D.projectVectors() function.

Here is a short example of the sortOn(“w”) method.

Camera Location
Perhaps the most annoying quirk that I’ve encountered with the new 3D system is the position of the camera in the Debug Flash Player vs. the Standalone Player vs. viewing a .swf in a browser. For some reasons,  matrix transforms on the camera behave differently depending on which Flash player you’re using. This might sound nuts (and it is) but if you move the camera back by ~500 units in the debugger then you’re going to have to move it back ~6500 units for the standalone player to have the same perspective. The fact that Adobe let this problem slip through is a little disconcerting.

If you want to see an example of this phenomenon, check this demo in your browser and then compile the code with the Flash IDE.

Culling
Culling is a mixed back. It’s one of the few features in the API that Adobe implemented really well except for one very fatal flaw. Normally culling is used to only draw one side of a polygon which saves on cycles on the CPU (or GPU). After doing a few quick experiments Flash doesn’t experience a performance hit for “Culling On” vs “Culling Off,” leading me to believe culling is automatic and triangle faces out of view are not drawn. The only time you’ll even need culling  active is when you one side of your triangles to be transparent.

Sadly, the automatic culling doesn’t extend behind the camera so everything in the scene better have a positive Z (relative to the camera) or else. Shapes sitting behind the viewport will cause the Flash Player to lose its mind and start drawing garbage across the screen. This is especially annoying when the standalone Flash player  screws up camera translation and zooms in to the middle of the scene.

Transparency
Transparent shapes are usually a source of headaches. If you cull “unseen” shapes from the scene making some shapes transparent will  break basic
hidden surface detection. It also complicates lighting, shadow casting and shading. drawTriangles() handles hidden surfaces, and by “handles” I mean  it draws everything but at least transparency works correctly.

Shaders
The fact that you can use PixelBender to program shaders for Flash is pretty dang cool. The fact that a shader can only be applied statically once per draw call is pretty dang stupid.
Let me explain what I mean; normally a shader (vertex, pixel, etc) gets data about each triangle that the renderer is currently drawing. Using that data the shader can perform the necessary calculations to figure out things like lighting and texturing. In Flash you can only feed data to the shader  prior to the draw call and while the call is being executed the shader doesn’t know “which” triangle it’s working on, just that it’s working on a triangle. So, if you want dynamic lighting there only a few ways to get around this limitation (and neither of them are pretty).

One solution is to compute all the shading information prior to calling draw and storing in one giant bitmap. When you’re ready to draw just add in an extra list of UV coordinates and you’re good to go. The drawback is the fact that the resulting bitmap will be huge (assuming you have a large number of faces). The other solution is to call drawTriangles() once per triangle and pass new information to the shader between each call. It’s highly inefficient and it defeats the purpose of a single draw call but it gets the shading done.

Hardware Acceleration
The biggest downfall of the current system is the complete lack of hardware acceleration. GPUs are optimized to draw triangles and yet drawTriangles() operates entirely on the CPU. As a result you can only draw an extremely low and very disappointing number of triangles at any time. My amateur benchmarking (calling draw once per triangle and using a PixelBender shader to calculate N.L lighting) maxed out around ~2000 triangles before the framerate dropped to 1.

So, Flash 10’s 3D is cool but its not going to really take off until they fix some of these problems.

 

Flash 10's 3D API


Lately I’ve been doing some recreational tinkering with Flash 10’s brand new 3D API. It’s a quirky little system that has a lot of pros and cons (mostly cons) but it’s fun to see how far you can push Flash in the new 3D realm.

I’m planning a to do a more detailed writeup about what I’ve learned so far but in the mean time let me whet your appetite with this little demo. It’s your standard heightmap with flat shading but considering the fact that it’s being pumped out of a 2D rendering engine, it’s pretty spiffy.

Get Adobe Flash player

 

Rift – The 30 minute RTS


Rift is a real time strategy game that I created with David Huynh, Brian Johnstone and Nick Wilsey. The goal we started with was to create a multiplayer Real Time Strategy (RTS) with short games that could be completed in under 30 minutes (a casual RTS, if you will). It was our spring quarter project in 2D graphics programming.

Keeping that in mind we started by removing the tedious tasks that you find in most RTS titles, resource gathering, construction and tech upgrades. In Rift, new units are automatically produced and players can enter combat immediately. Skill enters the equation when users decide how to position their fleet across the map.

The game works a little bit like chess. Every player (up to 4) starts with a mothership, which acts like a command center or a “king” piece. The goal on each map is to destroy all enemy motherships while keeping yours safe. Motherships are key because their primary function is terraforming planets; terraformed planets act like ship factories, the more you’ve got, the more ships you will be able to command. The tradeoff comes when players decide how quickly they want new planets becuase pushing the mothership towards the front lines places it in greater danger.

Once you’ve got a terraformed planet, you’ve got the option to produce three types of regular ships, small, medium and large. As their names imply, the three ships have a balanced set of abilities with specific strengths and weaknesses. Small ships get built quickly and they’re very fast but their lasers don’t pack a hard punch. In contrast, large ships arive slowly but they’re much more powerful. The player controls which type of ship each terraformed planet produces allowing them to diversify the fleet.

Finally, we implemented a “Command Point” system to provide special abilities and tide-turning powerups. As players perform tasks in the game like terraforming planets and fighting enemies they acrue command points. These points can be redeemed for a variety of special abilities like extra units, sight through fog of war, planetary attacks and more powerful ships. Since tterritory control is an important element in Rift, we wanted to make sure that players in 1v1 matches wouldn’t be instantly steamrolled if they failed to control as much of the map as their opponent. Command point abilities are one mechanism we employed to accomplish this goal.

After ten weeks, we were able to create a very fun game that supports up to four players.

On the technical side, Rift includes several features that we’re very proud of; a custom vertex buffer, an index buffer, a custom renderer, a custom render queue, distance sorting based on alpha value and custom render states. The graphic user interface was implemented in Flash using a special system Brian built to apply swfs as DirectX textures. I designed all the user interface menus and created the graphcis.

Rift also includes a map editor to simplify level design. Maps in Rift feature Fog of War and consist of a set of planets and moons (which are capable of orbiting around one another). The map featured in the final build is a complete solar system where all the plants orbit a central sun. The moving map is an interesting and very fun feature that grew out of our desire to build realistic solar systems.

Check out the Design Document (V1, V2 and final) for in depth info about the game.

Rift on games.rit.edu

Click the images to enlarge

Docking Mothership

Docking Mothership

A pair of red planets

A pair of red planets

A yellow sun

A yellow sun

Large ships

Large ships

A few explosions

A few explosions

Planet under attack!

Planet under attack!

More battleships

More battleships

Big space battle

Big space battle

More battles

More battles

Sun at full power

Dave's killer sun

Fleet of small ships

Fleet of small ships

Fleets collide

Fleets collide

 

Rift art and models


Here are a few more shots of the art and 3D models from Rift.

I handled most of the art and textures while the models were built by Nick Wilsey

Click the images to enlarge

shipsmall2 shipmedium shiplarge
rift1 rift2 rift3
 

World of Soarcraft


World of Soarcraft is a game concept proposed by Professor Jon Schull during my Spring Quarter course on Emerging Themes in Entertainment Technology. The concept is fairly simple; build a simulator that immerses the user in the feeling of flight. Professor Schull wanted a system where users could soar across a digital landscape and use their own body to control the movement.

In one week, my partner Brian Johnstone and I developed the first Soarcraft prototype in time to demo for the Imagine RIT festival on the RIT campus.

The prototype is made of three parts, the software, the peripherals and the harness. I’ll give a brief description of each.

Software: The terrain is pretty straightforward. Using L3DT, Brian made a fjord style heightmap to show off a variety of terrain. The map includes steep cliffs, valleys, water and open plains. Movement is also simple; going forward is automatic while pitch and yaw are controlled using WASD. To make turning seem more natural, we also modify roll values while turning. The final effect looks like a bird or an airplane banking through the sky.

The system is rendered on the Luster 3D platform using Lua.

Me, showing off Soarcraft during Imagine RIT

Me, showing off Soarcraft during Imagine RIT

Peripherals: The keys to Soarcraft are the input and output devices. Body motion is tracked using a Nintendo WiiMote attached to the users chest. It replaces the WASD keys and forces the user to sway side to side and lean forward and backward for movement. We decided to use a single WiiMote over a pair of handheld WiiMotes because we felt that the novelty of flapping your arms to maintain altitude would wear off quickly.  Our body movement method is fairly intuitive and much more comfortable.

The output was handled using a new pair of Vuzix iWear VR920 glasses, which the Vuzix company graciously donated to RIT’s Game department. The VR920’s have built in motion tracking allowing us to track the user’s head movement. Once we integrated the glasses into Soarcraft we could move the in-game camera based on the user’s real world orientation. This allows the user to look in any direction as they soar through the environment. The camera is no longer locked in the direction that the user is travelling.

The Vuzix glasses were the project’s greatest asset since they did the most to maximize user immersion. During the demo at Imagine RIT, the glasses produced the most “Wow” factor from the audience.

Brian and Prof. Schull showing off Soarcraft

Brian and Prof. Schull showing off Soarcraft

Harness: The final piece of the puzzle was a harness that we could use to suspend users in a “natural” flying position. This was both the most unorthodox and most challenging part of the job. Professor Schull’s initial idea was to attach bungee cords to the user’s waist and then to a wall. The user’s could lean forward and pivot on their feet. Initial testing proved that idea to be uncomfortable and unsafe.

My idea was to borrow climbing equipment from RIT’s rock wall and suspend user’s from the steel beams in the Innovation Center’s ceiling. Unfortunately the rock wall only provides leg and waist harnesses, no upper body rigs.

From there we envisioned a handful of additional designs including a hammock, a suspended folding chair and even a witch’s cradle. The harness was eventually scrapped over safety concerns but I believe that given more time we could have constructed something viable.

You can read our project report here (PDF).

standalone-2009-05-06-14-35-31-92 standalone-2009-05-06-14-35-44-47 standalone-2009-05-06-14-35-54-95
standalone-2009-05-06-14-36-27-41 standalone-2009-05-06-14-37-34-94 logo
 

Asteroids


Get Adobe Flash player

This is an asteroids game I coded up to test out the Flash Collision Detection Kit. The kit is very straightforward and easy to use, it defines a pair of new data types that handle everything you need for collision detection.

Controls are:
Up Arrow: Forward Thrust
Down Arrow: Reverse Thrust
Left Arrow: Rotate Left 
Right Arrow: Rotate Right
A: Port Thrust
D: Starboard Thrust
Space Bar: Fire

 

Variable Terrain Generation


My friend Kapish Rawat and I started the new year together by working on a computer graphics project designed to create variable terrain from static images. Our original intent was to create a program that could parse an overhead image of terrain and generate an accurate map 3D map of the pictured terrain.

The main problem this task presented was figuring out a way to accurately determine which parts of the image should or should not be elevated. To solve the problem we built a standard height-mapper that allows the heights to be adjusted based on color.

A height-mapper is a program that accepts a black and white image and then uses the color values in the image to raise and lower vertices on a grid. Typically absolute white is the highest value while absolute black is the lowest meaning shades of grey represent the various heights inbetween black and white.

Our program constructs a three dimensional grid with one vertex for every pixel in the image.

A flat grid

A flat grid

After loading the image and creating the grid, initial height values are calculated by greyscaling the image and using the black and white color values (the same way you generate a traditional height map). For this task we used astandard greyscale formula (similar to the one used in televisions) which weights the Red, Green and Blue color channels in order to compensate for the sensitivity response curve of the detector to light as a function of wavelength.

//Our generic weighted greyscale formula
0.3 * Red + 0.59 * Green + 0.11 * Blue

To allow for a variable height for each colors in an image we created two formulas:

//Create your own weights

dR * Red + dG * Green + dB * Blue
//Combination of generic and custom weights

0.3 * dR * Red + 0.59 * dG * Green + 0.11 * dB * Blue

The first simply lets the user input their own weights for the Red, Green and Blue color channels. We implemented this in two ways; first a set of sliders that range from 0 to 255 and constrain the user to a limited set of inputs, second an open method where the user can enter any weight they choose without constraint.

The second formula combines the original greyscale formula with a user generated set of weights. This combined formula is generally the smothest of the three because it allows for variations in the image’s height but it also constrains the proportions based on the original formula.

Original 2D Image

Original 2D Image

Flat Image

Flat Image

The default equation

The default equation

The RGB sliders with user input

The RGB sliders with user input

Combination of default equation with RGB sliders

Combination of default equation with RGB sliders

The image when converted to black and white

The image when converted to black and white

Here is an example of a satellite image being manipulate with the program. It’s an overhead shot of the Golisano College of Computing and Information Sciences on the RIT campus (click for full size images).

The original overhead image

The original overhead image

The 3D model of the GCCIS building

The 3D model of the GCCIS building

As long as you have a good idea about what the terrain should look like it’s only a matter of adjusting the RGB scalars to generate a reasonable fascilime. The biggest problem with our implementation is that the heights for every color are relative to one another meaning adjusting one height will affect any other point with similar values in its RGB channels. Ideally we’d want to be able to give each unique color (or range of colors) its own height. Additionally, black and white are two colors whose heights can not be set. Solid black will always appear as the lowest possible value while solid white will be higher than anything else.

Kapish and I would have liked to have fix both of these problems (and we still might) but our original development cycle didn’t provide enough time for us to do so.

Our implementation was written in C++ using OpenGL. The user interface was added on with the Fast Light ToolKit (FLTK). We also used the cIMG Library for image manipulation and ImageMagik for various file type support.