Wednesday, February 8, 2012

DirectQ Update - 7th February 2012

Worked over the texture loader some today. I've added support for textures loaded from directories called the same as the value(s) of the "wad" worldspawn key (with multiwad support). This is in addition to, not instead of, the "textures/mapname/" convention, so now I support both.

I also added support for the QRP standard (i.e a "_bolt", "_cable", etc suffix on the texture name) in addition to "textures/mapname/".

Two things concern me about supporting all of these external texture paths. One is that the code would turn into a horrendous mess (which the old version had done), but that's now irrelevant as the new code has turned out quite flexible and elegant. Two is the time taken to find external texture files, and is worth talking about some more.

Since I support 7 different image formats, and since I now support two naming conventions and three directory conventions, that all adds up to a huge amount of looking for files each time I go to load a texture. The worst case is when you have no files - it must still look for all of them before it can establish that for real.

That was one of the motivations behind my old texture loader - caching the names of image files on startup so a quick scan through the list could confirm whether or not they existed (rather than attempting to open a file and seeing if it failed).

My new solution involves checking the texture paths that I'm loading from to see if the paths exist, then not bothering to look for textures in any path that doesn't exist. This is a one-time per map operation and is over and done with quite quickly. If you're running with native textures (none of the paths exist) then there is no further overhead - it won't even look for textures to load. If any path exists then it does look in that path for every texture, but that's OK - if you have one external texture then you probably have a full set, so it's what you want to happen. In any event, the overhead of loading an external texture is going to be significantly higher than that of doing the search, so things work out well.

A few other useful things got accomplished.

Beams and Temporary Entities have been worked over and made much cleaner. I guess that I had something of an aversion to using STL when I first moved the engine to C++, but in reality it's OK, and the beam and temp ent lists are now std::vector types. This means that they work in a similar way to the original engine, but without the stupid maximums.

I tracked down the cause of the "static entities in the wrong place" bug in certain RMQ maps. It turned out to be protocol-related - because of the old +/- 4096 map size limit some entity placements wrapped. Setting the correct protocol before running an RMQ map resolves it (DirectQ uses the FitzQuake protocol - which still has this limit - by default), so I need to find some way of determining if the current mod is RMQ and do this automatically.

I also worked over a lot of things relating to client-side dynamic effects (particles and dynamic lights), make much of their behaviour framerate-independent (and user configurable) and killed some more bugs with them.

For doing this I needed to select a framerate for these effects to be simulated at, and I ended up choosing 36 fps as my default (it can be changed via the cl_effectrate cvar). The reason for this is that I have very high doubts if Quake was ever originally tested at the kind of stupidly high framerates DirectQ can get, let alone the default maximum of 72 fps. Really weird things start to happen with these effects at high framerates, including colossal multitudes of particles being spawned, dynamic lights being needlessly updated every frame, odd flickering effects, and so on. It's quite obvious that they were tuned for stability at a much lower rate, so I've put them at what I feel is reasonable.

A nice side effect of this is that I've gained the ability to not bother updating dynamic lighting on a surface if it's not changed since last time it was updated. In practical terms that's not a huge performance gain, but it's good to have and certainly feels right.

I'm also restoring XBox 360 controller support (coded but currently untested) and view pitch drifting (done: I found the bug that caused me to remove it).

Overall the engine is now starting to settle down really well. I'm happy that I decided to take on the main thing that was holding me back from releasing it (the texture loader) a few weeks ago, and I think that it's going to be a much higher quality release in several important respects as a result of that.

5 comments:

gb said...

find some way of determining if the current mod is RMQ

I think Spike also wanted something like this. For turning on bigcoords support or something automatically.

mhquake said...

Yup, same reason. ;)

I think a loose heuristic based on presence of certain files and QC functions might do the job.

gb said...

I only put boxes together... I have a hard time keeping up with all this engine stuff sometimes ;-)

=peg= said...

A command line switch would seem to be to most reliable (provided the user know what he is doing..). Similar to -rogue and -hipnotic. But then again.. if it can be automatic via some heuristics, all the better I guess ;)

mhquake said...

Well -game rmq is the same as a command-line switch really, and then you've got to deal with people who forget to set it, or if the RMQ gamedir changes for demos/etc.

All in all it goes against the "you do not need to use the command-line" philosophy of DirectQ too.

Here's what I did.

Look for "maps/e*m*rq.bsp" in the filesystem when a game loads - if a file is found matching the pattern assume that it's RMQ and switch to the appropriate protocol.

I don't believe that's any worse than GLQuake looking for "gfx/pop.lmp" or "gfx/palette.lmp"...