Friday, February 15, 2008

Tech Article #2: XNA's Content Pipeline

This is pretty cool. Whenever you create a game, one of the hard parts is writing some sort of processor that can, well, process the assets you want in the game. What does that mean?

Let's say I design a kick ass airport in 3DS. I now want to import that into my simulator. How do I do it? My game doesn't just have an "Open file" option, and it sure doesn't understand a .3DS or .MAX extension. So, what are our options?

I could go to Wotsit and take a look at the structure of these file types, meaning their innards, and write some code that can sift through that data and find useful things I need, such as vertices locations, UV map coordinates, etc.

Great, now I can import my cool looking airport and we're in business! Well, not quite. I still need to be able to draw it, and that means I have to write code to run through the vertices and see what textures goes where, load those textures, check everything, then draw.

And what if someone else makes a good airport in another 3D creation tool and I want to add it? What about audio? Can you see how in depth this can get? As a matter of fact, game studios have hordes of people working on just these portions of the code. Lots of work. Boring work, if you ask me.

Enter the Content Pipeline. XNA Game Studio was created by guys who created games for a living, so they know where the pains of the process are. With that in mind, they have created a very cool and streamlined "pipeline" through which we can import all kinds of files. OK, so it's not any kind, they are limited to:

- 3D Files: .X and .FBX
- 2D Files: .DDS, .BMP, .JPG, .PNG, .TGA
- Material files: .FX
- Audio files: .XAP (XACT)

The Content Pipeline takes you all the way from step one, importing, to the last step, loading the asset in memory, ready for use. Check out this graphical description of the pipeline:

How do you use it in code? Very, very simple:

ContentManager myManager = new ContentManager(GameServices);
model = myManager.Load<Model>("ship");

You can now call "ship" in your Draw code and bam!, it's on the screen.

Of course there are shortcomings. The pipeline, as shipped, is pretty limited, but it was meant to be so, since the XNA Team cannot think of all different ways you need to import and convert assets. So they made this a very easy class to inherit and change, adapt, gut, add to, whatever you need, to get exactly what you want out of it. Nice, huh?