Sunday, September 19, 2010

Multi-Headaches

As you may have seen, there are a few links added to the top-right corner on this blog page. Somebody suggested to add some project summaries and well, I think he was right. I was struggling what to tell and what not to tell about the story and gameplay elements, so I tried to outline the game, without spoiling too much. Nevertheless, you can find some details about the game itself that you may not have found between all the weekly yapyap.

There is also a "Movies !" section, without any movies. However, there is a list with remaining points that need to be done. If you ever get impatient, you could check the list to follow the progress. As you can see, I needed to model a fuse box, the end-section of the hallways I made earlier, storing animated sprites, and improving some camera work. When running, the player would actually pass the camera. Since there is this so called "body awareness", I would see my own eyeballs in front of the camera. That may happen when Chewbacca flies with the speed of light in its reversal, but here it occur. Turns out the camera matrix was always 1 cycle behind. Doh.


Then there is also that “Uncle Sam needs you” section in the top right corner. First I planned to finish that movie before asking any help, but since I was writing anyway, I added that too. I’m not in a hurry to assemble a huge team of programmers and artists to make a big commercial game, but one or two artists to help with a second demo movie are surely welcome.

When the first movie is finished, probably somewhere at the end of this year, I’ll have to plot the next targets. Improving ambient lighting, and real enemies with AI are two main goals. But also creating a second demo movie is one of those things to do. See, you are looking mostly at programmer art right now. It isn’t that bad, but it doesn’t really represent my actual ideas for this game either. It can be done a lot better, so the magic wand of an artist is what this project really needs sooner or later. So if you know somebody with talent and too much free time, you could send him or her that link. Who knows.

Anything else to report? Not really. Spend most of the time modeling and fixing(finding) the camera bug. The apartment and spooky corridor sectors are all connected now, so you can walk from A to B without needing teleporters. For the info, the map is divided into small pieces; “sectors”. A hallway or chamber would be a typical example of a sector. Each sector contains portals, the openings(doors, windows, …) that show connected neighbor sectors.

While walking around, the surrounding sectors will be loaded at a certain level of detail. Distant sectors will have a simple mesh and possibly simplified materials without all the fancy shader effects. Close sectors on the other hand are fully loaded with all the details. All the loading and dumping of sectors that were left behind, happens in a background process to prevent the game getting halted by the loading times. In short, pretty much how free roaming games like GTA work.

It did take me a few billion frustrating hours to remove the bugs caused by multithreading madness though. If you have no idea what I’m talking about… If you have a Dual- or Quadcore processor, you basically have 2 or 4 CPU's that can process tasks at the same time. But you'll have to tell your program how. Multi-Threading means you make another separate "thread" that runs a part of the program. For example, thread A does rendering, thread B physics, thread C sound and game logic, and thread D loads the sectors. The OS and CPU internals will cleverly throw tasks towards the processor(s) to make things run parallel. Sounds easy, but it isn't.

Ever worked as a team, or better said, NOT as a team? You bought a can of red paint. Bob didn't know that, so he bought the same can as well. You started to paint that wall, but crippled Joe walks in the way all the time. When you have a break, Jimmy decides to continue your work, but forgets to lacquer the wall first. The boss promised the client that his house will be finished yesterday, but the work isn’t even half done… If you want to work as a team, you'll need to communicate, make appointments and eventually clearly divide the work into separate tasks.

The problem with MT(Multithreading) is that you can't simply read/write variables. If process A reads while B writes on the same value, you'll read something terrible. If both A and B write at the same time, the value is messed up. Bob and Jim can't paint at the same place either, you'll have to pause either A or B. But having lots of pauses is not exactly the idea of MT. Your boss didn't hire 10 men to work in turns either.


In this case, the background thread loads data that is heavily used by the other thread for rendering, collisions, AI stuff, and so on. To prevent the main thread from using half-loaded bullshit, the sector will be loaded in “quarantine” first, then transferred to a "ready list". The other main thread will check this list every time to see if anything new became available. If so, it will be grabbed from the list and placed in another "active list".
- Thread A >>> load item apart from the rest
- Thread A >>> once finished loading, put it in a “ready list” (lock / unlock while inserting)
- Thread B >>> check if there is something in the “ready list” (again, lock / unlock while reading)
- Thread B >>> Ifso, move item to the active list. Delete from the ready list.
Here's where both threads can touch each other. Since the loading thread can insert items into that "ready list" while the other process reads from them. Again, do not do this at the same time. Lock the list with a “mutex’ or “critical section” while one of them either reads or writes. A common mechanism to share values between 2 (or more) threads.

After a long struggle, frustration and many bugs, it worked (for more than a year already). It introduces some extra difficulties like having an changing/unpredictable set of data for AI or special rendering routines. Or being careful about all the garbage(unused textures/models) will get removed 100%, otherwise the memory will flow over sooner or later. All in all, not the easiest way, but having the environment getting loaded without annoying loading times is worth it.

4 comments:

  1. Crazy, I think I'll avoid multi-threading until absolutely necessary, which will be a while,

    I've been wanting to ask you, how do you set up collision for the geometry you modeled, like the hallways and stuff? do you model additional collision meshes/boxes/sphere's etc. with the actual models and save it as your own format to be read in? Or do you Have an editor that loads the models and lets you draw the collision shapes and export to your own map format? (heh, kind of similar options) or something of that nature?

    ReplyDelete
  2. Multithreading is hell, I'm telllng you! Well not 100% true, as long as you plan MT right from the start.

    Collisions; The sector maps are modelled in Lightwave. The LWO format supports multiple layers, one of them is used for the collision model:
    - layer1 = high detail geometry
    - layer2 = medium detail geometry
    - layer3 = low detail geometry
    - layer4 = ultra detail geometry
    - layer5 = portals
    - layer6 = collision geometry
    - layer7 = sound occlusion geometry
    - layer8 = high detail geometry (small details)

    The collision shape is usually just a copy of the high detail mesh. But you can remove small crap like pipes, or flatten the stairs for a smoother walk. Or place invisible obstacles.

    In the game itself, the Newton physics library uses this mesh to setup a collision shape. Dynamic objects such as boxes, furniture or characters have a similiar system, but with primitive shapes. The LWO model of a character for examply contains a layer with 1 or more very low poly shapes. These can be boxes for example, but also somewhat more complex shapes. In Newton those are called "convex hulls". A chair for example could be a compilation of 5 boxes. Each hull has its own ID, so I can trace back which part was hit (headshot!).


    The sound occluder geometry is not used yet, but FMOD can use a 3D mesh for fancy sound calculations as well. This is a very low detailed version of the mesh.

    ReplyDelete
  3. Got to add that the Lightwave models are only the initial meshes. Once imported, they are converted to my own format that contains additional data as well (ambient settings, entities, script, AI stuff, etcetera). One of the reasons for that is to keep everything in a single file, and to make it suitable for the background streaming I was talking about.

    The editor can be used then to texture the walls, rebuild normals, and so on. So far I can't move vertices yet, but that would be perfectly possible as well.

    ReplyDelete
  4. That is quite awesome,
    I have to begin creating an editor for my game, since I would like to move past using a tile-based format.

    This way I can simply load images and place them for the art of the levels and draw Box2d shapes for collision, though I'll still keep a grid for setting up A* pathfinding for AI, the art won't be dependent on it.
    Im just seriously dreading the GUI stuff I will need to do however :/
    Im using SFML for Graphics/Events but It doesn't cover GUI's
    I've been procrastinating that for months...

    ReplyDelete