We're back from GDC '09 and I wanted to write a micro-blog update. If these things can be short, we'll write them more.

Our small team has been having some difficulties designing our levels and making sure we have enough environment art to make them unique without breaking the bank. We've flip-flopped between top-down and bottom-up processes. The top vexing and elusive questions often heard are:

  • "How can we make big design choices until we've proven it works?"
  • "How do we know we're hitting our visual quality goals without completely finishing an area?"
  • "How many props will we need, and what percentage of those will need to be unique landmark props versus generic props?"
  • "How will we know when we're done creating assets?"
  • "How many varied maps will we get out of each art set?"
  • "How do we do all this without wasting effort (and while having people work remotely)?"

We often create an "orange box" for our level, then decide we need the visuals to inform the layout. So we start working to add visual/finished elements, then we realize that constrains the design because we can't make layout changes without throwing away work. From time to time we "wake up" and change our process, seem to come to an agreement and we believe things will get better. Somehow we always end up back in our tar pit.

But after seeing some talks at GDC this year about top-down level creation (The Iterative Level Design Process of Bioware's Mass Effect 2, Everything I learned about level design I learned in Disneyland), I can feel a new process emerging. One where we boldly and methodically list the questions that must be answered to proceed with level creation, make a good effort to answer them, and whether we are absolutely sure or not, make the decisions with good faith and move forward.

In our efforts to make the best decisions for NS2, we've been hurting ourselves by not committing. We made many off-the-cuff decisions when making NS1 and that worked out just fine.

Are there any areas in your life you should have a little more faith about and just commit to?

31 Comments

In order to work on Natural Selection 2 regardless of where I am, I recently decided to get a new laptop. I bought my last laptop around when we started working on NS2, and at that time I went for the cheapest system I could find. I've often found that the adage of "you get what you pay for" rings true, and it certainly was in this case; a year later my brand new laptop was unusable, even after resuscitating it with numerous hardware transplants.

This wasn't the first time this has happened to me, so with this laptop I decided to go all out and get something quality, even if it cost more up front; the time (and possibly data) loss resulting from faulty hardware can be just as significant. My brand-new Macbook Pro (with the 17" matte display!) arrived last month and I immediately installed Vista via Bootcamp and setup my Windows development tools.

One of our goals is to make Natural Selection 2 and the toolset work natively across Windows, OS X and Linux. With this in mind, whenever I write code I try to keep portability in mind. This factored into our decision to use wxWidgets to build all of our tools and to keep any platform specific code (Direct3D for example) abstracted so that it can easily be replaced. This has all existed in the theoretical realm though, because I've never actually ported anything to OS X or Linux.

Since I have a shiny new computer that runs OS X, I figured it was time to put that to the test. While a complete port is out of the question at the moment, I wanted to get my foot in the door so I could begin to understand the issues, like how to organize the files that contain platform-specific code, any gotchas associated with wxWidgets, etc.

For my weekend porting project I decided to tackle the Builder application. This is our tool which is responsible for automatically converting all of our art assets into game ready formats. Of all of our projects, this particular one depends on the fewest libraries (just wxWidgets) and only has a small bit of Windows specific code which is isolated in a single class. I also spent a lot of effort when writing the Builder to make it platform independent, so I was looking forward to seeing the fruits of that labor.

Ultimately, getting the Builder running on OS X was a pretty easy process, although it took me both Saturday and Sunday to get it worked out. The first step was compiling wxWidgets for the Mac, which turned out to be pretty simple with the supplied config script and make file. Then came the task of creating my own make file for compiling and linking our project. I haven't written a make file since college, and a make file for a real project is quite a bit different than the ones I had done in the past or the simple samples you can find on the Internet. Presumably this is why there are so many alternatives out there to writing the makefile by hand (icompile, bakefiles, automake or using XCode) I looked into these a bit, but ultimately decided I'd have an easier time just writing the makefile myself.

Once I had the makefile sorted out, I quickly found a number of places where my C++ code wasn't portable to the g++ compiler. I also discovered a few errors in the code which hadn't been caught by Microsoft compiler. These were all really easy to fix, and was exactly the kind of knowledge I was hoping to discover with this process.

The final step was linking and creating a usable OS X executable file. The linking process gave me the most trouble, because I made the rookie debugging mistake of getting hung up on one possible explanation of what I was seeing. At the end of my linking process, I was left with the single error message "Undefined symbol _main". Since the main function is supplied by wxWidgets I figured this was a problem with the way I compiled the library or how I was linking to it. A few hours of head banging later I took a step back from the problem and realized the "main" function was there, but the way my code was written put it inside a namespace. Moving it outside the namespace fixed the linker problem and I had an executable file at last.

Unfortunately this executable file didn't behave like a normal OS X program. When it started, I would see the window for the Builder, but there was no menu at the top of the screen and the window didn't respond to any mouse clicks. I was lucky with this problem, and after a little bit of research I stumbled across the solution; OS X applications are actually directories, and inside that directory is where the actual executable image goes. With a few quick changes to my makefile, everything was packaged properly and I could run the Builder properly!

There are a few bits of the Builder that don't work properly on the Mac yet, but I'll be working on those soon. I also haven't rewritten the platform specific piece (which detects when files on disk have been modified), but I do have a good solution now for how to organize these files in our code base.

People often think that Direct3D is the biggest barrier to porting a game engine, but we actually have very little Direct3D code. Direct3D represents only about 2,500 lines of code out of almost 100,000 in the engine. The bigger task is all of the small things, and this process has helped me flush about a bunch of them that should make things smoother going forward. We're not sure if we'll have enough time to release an OS X or Linux version simultaneously with the Windows version, but it's something we're very interested in doing. But I'm feeling good about the portability of the engine, and since our entire game is written in Lua it doesn't need to be ported at all!

57 Comments

I don't want to alarm anyone, but zombies have taken over our code.

We'll keep you posted with updates as we track the outbreak.

45 Comments

On of the important tasks in a first person engine is occlusion culling. Occlusion culling is the process of discarding elements of the world that aren't going to contribute to the final rendered scene so that you don't spend CPU and GPU time processing them. With expensive elements like dynamic lighting and shadows, this becomes especially important. Here's a Natural Selection 1 level rendered in our engine:

Even with the textures missing, some of you will probably recognize this spot. While this may look like a simple hallway, to the rendering engine it looks a lot more complicated. Here's the same scene rendered in wireframe mode:

As you can see, there's lots of stuff behind those walls that's being rendered, but which we don't actually see. In many first person engines this problem is solved by precomputing information throughout the level about what's visible; this is known as a potentially visible set (PVS).

If you've ever done any mapping for the Quake or Half-Life engines, you're probably familiar with the "vis" tool which performs this precomputation. This can be a slow process that requires a lot of tweaking and careful modeling. Because the data is precomputed, the environment can't change much at run-time. And finally the PVS method is not very good when it comes to outdoor scenes. To alleviate all of these problems, we've chosen to use a hardware assisted occlusion culling method that doesn't require precomputation.

Here's what the scene looks like with the occlusion culling system enabled:

As expected, most of the invisible geometry has been discarded during the rendering process. Because of way the algorithm utilizes the graphics card, the structure of the level doesn't really affect the system. It works with outdoor environments as well as indoor environments and can handle polygons "soups" -- collections of polygons that don't really have any structure at all.

While real-time occlusion culling has some additional performance cost over precomputed systems like PVS, we think the benefits more than make up for it. And with clever optimizations, that cost can be reduced substantially.

For those that are technical minded and would like to learn more occlusion culling, our system is an implementation of the CHC++ algorithm (paper available online here).

68 Comments