This is my current project right now. I had the chance to get the source code and assets of an old game: Resurrection, the return of the Black Dragon. And I wondered “wouldn’t be fun to upgrade its rendering algorithms and that stuff to something more up to date”? And well, that’s my pet project at home. When the other more serious projects allow me, or when I simply want to do something funny, I spent some hours with it.
Here do you have a gameplay of the original game (yep, some people still play to games from 1999), and later a peek of where I’m now.
And what have I done on the code? Well, when I took it it had a fixed pipeline forward shading renderer, and that was my start point. Currently it is a opengl 3.3 (formerly OpenGL 4.5 but the port to osx on a macbook from 2009 forced me to go down to 3.3) deferred renderer with omni shadowmapping and an exagerated SSAO :). Ah! and I don’t draw transparent meshes yet :)
The shadows are simple Shadowmapping with no filter yet, and the lighting it’s still a lambertian/blinn. Easy peasy, but I have to admit it’s funny to dive into the code and find ways to improve the rendering.
Here is the little video I’ve recorded this morning. Just the character moving, and I enable/disable the SSAO, otherwise no one would notice it’s there.
It’s embarassing but I admit that 1999 resurrection still looks better than mine, but give me time :)
Ok, I know, I said I would implement sound, and I swear I started, but I can explain what happened and why I’m still without sound.
For each kind of data (i.e textures, materials, loaders, etc) I had a manager. Each manager was a singleton, and after coding the Sound manager I said “Dude! I have tons of singletons, it’s time to change that!”. And that’s what I’ve been doing. I’ve centralized managers, factories and containers under the Engine’s hood. To ensure there’s only one instance of each manager I’ve tangled a bit managers and engine :). It’s something like this:
An excerpt of IManager’s code class IManager
{
public:
IManager(int type, Engine* e); //Constructor
virtual int GetType() = 0; //some RTTI
...
};
// Adds the manager to the engine
IManager::IManager(int type, Engine * e)
{
e->AddManager(type,this);
}
An excerpt of Sound Manager’s code class SoundManager : public IManager
public:
explicit SoundManager(Engine* e); //Constructor...
virtual int GetType() { return MGRT_SOUND;}
};
// Adds the manager to the engine
SoundManager::SoundManager(int type, Engine * e) : IManager(GetType(),e)
{
}
So as you can see, it’s engine (called from IManager::IManager who decides what to do with the manager’s instance). In my case I stored it in an array.
So once I had all managers de-singletonized (?) I thought:”mmm, I’m not sharing data”. Yes believe it or not, I was loading models, animations and textures as many times as they appeared in the data files. So well, just some more coding following the same schema I had used for managers and well, at the end of the night I was sharing data correctly.
And this morning… I’ve woken up thinking “Ok Toni, so you’re sharing data but, do you know how much memory is your application consuming?”. At Insideo, shash had coded a memory checker, and I’ve thought that doing something similar I could know, at runtime and with a per frame granularity, what was the ammount of memory I was using.
I’ve searched on the internet and I’ve found 2 sources one at flipcode (RIP) and another at CodeProject. I have adapted to my needs and at the end of the day I was tracking the memory consumption…
To my surprise my application was a RAM eater monster :| just loading de imp animation and it was taken as much as 78 MB! WTF!!
78 MB!! The RAM eater monster attacks!
The first think I’ve thought has been: “textures, probably I don’t release the texture data”. So I’ve checked it, and indeed, I wasn’t releasing it. I fixed it but as I expected I didn’t had a big gain, after all currently I’m only loading 5 textures :).
75 MB the RAM eater monster is on diet! :D
So… I’ve been thinking… where do I have tons of data and it’s not released? Where? Where? Obviously it was on the loaders, so I just simply added a Reset method to all loaders, call it after loading and that’s it! :)… And you can be wondering :” And where were those dozens of MB?”. Well, the md5 material loader was keeping a table with a translation from material name to material file and some other info. And that table was consuming 70 MB!!
5MB ! The Ram Eater monster is now thin like a ballet dancer!! :D
Well, now I have the Ram under control, and I suppose now it’s the momment for sound. The journey of this 2 last days has been interesting, reallocating some classes and studing how to keep track of memory has taught me some good things I didn’t know about memory allocation and new and delete operator overriding :). Probably this will evolve in a near future to some kind of memory allocation manager and custom allocators and all this stuff I’m willing to learn :).
Two status update on the same day? GOSH I’m crazy! The world is ending! Penitenciagite! :P
I’ve just followed shash’s advice and implemented frame interpolation. Obviously it didn’t work the first time I tried, but the second. As always I’ve recorded the progress so you can enjoy and laugh.
Implementing frame interpolation was really easy but if your interpolation value is greater than 1.0 you get things like this
Once I changed that i got a nice interpolated animation
And now, once this is completed… it’s time for sound!
As I said on my last post, I was pursuing animation, and guess what: I have it!
Even when I haven’t implemented frames interpolation yet the animations look funny. So let’s start with the usual postmortem of what went wrong.
First I started parsing the md5 anim files, and guess what I don’t like it either. It’s not hard to parse, it’s just nonsense. It starts with a hierarchy and a base frame, well, everything seems ok until here, right? But then you have the frames, defined as a series of floats that, with some kind of obscure craft applied over the base frame and with the information in the hierarchy gives you the skeleton for the given frame. Sure it works, sure it has few data and sure: WHAT THE HELL WERE YOU THINKING OF? I think, honestly, that it would have been simpler to have an skeleton for each frame, easy and simple. Why do people think that being clever is ALWAYS the right way? Sometimes a simpler approach makes life easier :)
Well, once I have it loaded I faced another decision: coupling an animation and a model with a custom file or being a real macho man and loading the doom 3 def files? Obviously I’m a macho and def files was the way to go :).
And what are the def files? Def files for models at least define the entity informatio, in particular you can find there for each model what mesh and animations it uses. I have to say that this is the first file format that likes me :). It’s simple and does what it has to do. For each model defines a mesh and a series of animations, and for each animation what events applies and in what frames. Wonderful! :)
So I made a little loader for it and here’s the result:
Amorphous blob from the pitt!
WTF!?! I had a correct skinning system! What was happening here? At least I have to say it was indeed animated :)
YEAH! I have videos, thanks to glc capturing application, fraps-like for GNU/Linux. Well, it looked really weird, didn’t it? So I checked the def file and I discovered that it contained 3 imps models, so click click click I just hacked the loader a bit to have them separated and what did I got? Well, this:
Which… well, looked at least strange :) The first 2 imps remind me that Edvard Munch painting: The scream
I didn't know Id inspiration for imps came from expressionism!
Well, once they were separated I was wondering what failed, because the only model that was animated was the right-most one, but in fact it wasn’t properly animated but somewhat convulsing :S.
Well, it was due 3 little bugs
Quaternions, my friends, are composed of 4 floats, and when I was reading frames I was just missing one component
When I readed a frame and I send it to process, I only processed it when it had movable parts (that is, was different from the abse frame). But the base frame wasn’t processed so I had to process the base frame to get good results.
The tutorial I was following said something like “I assume that parent index < current index so parents are always processed”. So did I, and when I was processing a frame I assumed that parents had been previously processed. Well that’s simply not true, so I had to do some adjustments to have a correct processing.
With all that fixing here and there I ended with this:
It was ok, just that it wasn’t moving due the first 2 models had an animation with 0 frames, nice isn’t? So i did a little more fixing-typing-hacking to cicle among all models’ actions to get this: