OT (ish): Quake2 Source Code

Hello,
Just been browsing the Quake2 source code.
It’s not very efficient drawing code, is it?
It doesn’t use vertex arrays (for bsp drawing). Immediate mode using the GL_POLYGONS transfer mode…mmm.
It does a lot of texture bindings (doesn’t appear to add polys into texture bins, with a renderbins function at the end of the traversal) - this is odd, because it has the depth test enabled, so it’s not like it needs to render in a rigid back-to-front order (there could be a separate transparent poly bin container).

Any thoughts on the reason why this GL code is so bad? Taking into account it was written in 1997, it’s still pretty naive coding considering vertex arrays were around at the time.

Just a lazy sunday conversation - so forgive me if I irritate you.

By the way - another thought on the quake2 code - it doesn’t appear to have been “designed”, if you know what I mean? It looks really like a couple of guys have decided on a basic client/server structure, come up with an agreed function prefix protocol, and just gone for it…heads down…let’s get typing!!
I’m surprised because John Carmack is regarded as a supreme programmer - yet, all I’m left with is some respect at writing a very fast software rasterizer for Doom years ago.

I didn´t look into the actual drawing code, but i was also surprised about the “design”. It really doesn´t look that superior.
But then look into how it handles particles, it´s damned optimized with assembler.

Actually i don´t think the Q2 sourcecode is really helpful. I mean, when i look at my “engine” then all it does is traversing a tree, culling nodes, back-facing polys and using quite a good vertex-array structure.
However all the real hard work is not done by the engine, it´s done by the level-compiler, which culls lots of never-to-be-seen polys, creates the tree and does some other important stuff.

So, what i really would be interessted in, is the source of id´s level-complier, but as far as i know, that source is not released, is it?

Jan.

So, what i really would be interessted in, is the source of id´s level-complier, but as far as i know, that source is not released, is it?

The source code to the Quake3 level compiliers is available on ID’s FTP server. You also get the code to the radiosity processor (qrad3). Which is nice

I have taken a (little)look at the quake 2 code recently too. First off, correct me if I’m wrong but it is pure C code isn’t it? Does JC still code in C. I think I read somewhere that he is using C++ and was somehow surprised(that he uses C++).
I too don’t like the way the q2 and q3 engines does lots of things but other ‘features’ (rather trends it seems, wich I believe JC introduced) like the console, mods, shaders etc. are much more worthy of respect (as application-system design) than code design. Besides don’t forget that deadlines and competition sometimes don’t leave room for carefull planning of every detail.

In some article it was said, that at the beginning of Doom 3 id decided to move on to C++. So Q3 is certainly also coded in C.
I was very surprised about them not using C++ in Q3, but i think it is better to use plain C, instead of a mixture of both.

id´s ftp server? What´s the exact url? ftp.id.com had nothing to offer.

Jan.

id’s FTP server is ftp.idsoftware.com

Remember that Quake2 was written a long time ago (in the scheme of accelerated graphics), and it’s data set also had to cater for a software renderer too. Also, if Quake’s software renderer could render them all in effectively the same way (immediate mode) then an accelerator card would almost certainly be able to do it.

-Mezz

I used the quake1 source (and looked quite a bit at the quake2 source).
They obviously never really taught about software design. It all works as long as you don’t change it. If you do you’ll quicly run into globals being modified, wich ones were?? you never know so just add your own
Then it’s all plain vanilla C and even a “library” is something they don’t use mucy I mean just some handy utitlity routines, thinks you often need… (like the Distance between 2 points )
You can give them some excuse because of “the speed” but still, look at the unreal engine that’s fast to and it’s all written in c++ with abstract classes and whatnot.
The map compilers are nice algothithms, but again they’re hacky code, statically allocated big arrays etc…
I can only hope for the people who are going to licence the doom3 engine it’s going to be cleaner (Maybe quake3 is cleaner… dunno…)

Charles

Originally posted by Pentagram:
I used the quake1 source (and looked quite a bit at the quake2 source).
They obviously never really taught about software design. It all works as long as you don’t change it. If you do you’ll quicly run into globals being modified, wich ones were?? you never know so just add your own :wink:

Speaking as someone who’ve coded against the Quake2 source code for a “real” game, licencing the Q2 code base for enormous amounts of money, I can tell you that it’s a MESS. :slight_smile: Tons of things that could have been done better, tons of things that could have been done cleaner.

Still, in essence, it’s a game engine written by one guy before any other game engines existed. Carmack is IMHO worthy all seven shades of respect for it. (Quake 2 is based off Quake 1, BTW, so much of the stuff is ugly because Quake 1 was ugly :slight_smile:

It’s not pretty, it’s not superb, but he put it out there. He made his money and he proved that he could “Get it Done”, which is what software development really is about. :slight_smile:

The GOOD thing about this is that it makes us all feel much better. I mean, we can all say that we would have coded the damn thing a LOT cleaner, with a nice object hierarchy (instead of binary compatible C structs, that are extended differently depending on where in the code you are :slight_smile:

At the end of the day, he drives a Ferrari to where he flies rockets, all paid for by his own software, so… I say he’s still worth all kinds of cred.

/Henrik, formerly “Switz” of Ion Storm’s Anachronox team.

Yes, I understand it was all written a long time ago in the context of hardware acceleration (1997 as documented in the source code). But, taking that into account, the core drawing code looks very similar to my quick-hack demos from a few years back, when I was just getting into realtime rendering - before I concerned myself with the efficiency/design/functionality balancing act.
I don’t know, it’s probably all the globals, the huge macros, the empty for loops, the goto’s, the ambigious variable naming convention, the huge swathes of commented out but not deleted code segments, the fixme comments, the “should this work?” comments…etc.etc.
Shocking, sort of like catching the pope taking a prozy up the wrong 'un!

Originally posted by KuriousOrange:
I don’t know, it’s probably all the globals, the huge macros, the empty for loops, the goto’s, the ambigious variable naming convention, the huge swathes of commented out but not deleted code segments, the fixme comments, the “should this work?” comments…etc.etc.
Shocking, sort of like catching the pope taking a prozy up the wrong 'un!

yeah, the Q2 code isn’t pretty. Not at all. However, to address something I forgot earlier, vertex buffers WERE included in the later patches of Q2. (The latest patch-version I saw was 20 or 21 or somesuch and there were code for vertex buffers in there, I’m pretty sure…At least for the entity drawing code.

EDITED: Yeah, about the vertex buffers… That’s exactly what the original poster wrote, so Nice Going There…I’m DUMB. :slight_smile:

Oh well… I’m sure hacking around in that codebase cut two years off my life. :slight_smile:

/Henrik

[This message has been edited by CAD_Swede (edited 05-04-2003).]

Allthough I can’t remeber q2 very well any more just judging from all the initialization console messages and available info I’d say that q3 should be a little more organized compared to 2.
But still code organization and design has nothing to do with using a function for calculating the distance between two points or using a class hierarchy instead of structures. That’s why I hate all that OOP hype. If OOP helps someone organize his code then that’s great but C == hack && C++ == well_designed_code is not generally true.

d = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));

should be as clean, readable and well-designed to anyone with really basic algebra knowledge as:

d = dist(x1, x2, y1, y2);
or
d = p1.dist(p2);

or whatever else you can think of. And if it’s not you can use a comment or a #define. Not that the other ways are worse, they just aren’t better.
Not that all this makes q2 code any cleaner, but still I had to say it.

Mmm, yes - I think I know what you’re saying…not sure why you’re saying it though. Nobody’s mentioned OOP.
Seeing as though you bring it up though - I use template classes for my matrices, vectors, and general maths functions. Everything’s inline’d, so it’s basically more elegant than c macros, but equally as fast.
By the way, your example is pretty funny. If you think the first method is just as readable, then you should take a holiday!
Just inline it away, and then you can use it again!

Originally posted by Jan2000:
[b]In some article it was said, that at the beginning of Doom 3 id decided to move on to C++. So Q3 is certainly also coded in C.
I was very surprised about them not using C++ in Q3, but i think it is better to use plain C, instead of a mixture of both.

id´s ftp server? What´s the exact url? ftp.id.com had nothing to offer.

Jan.[/b]

In fact Doom3 renderer is still coded in C, I’ve readen it in an interview a long time ago :

Voodoo Extreme – The game side is C++, why not the rest of the code?

John Carmack – It’s still a possibility, but I am fairly happy with how the internals of the renderer are represented in straight C code.

[This message has been edited by Zeross (edited 05-04-2003).]

It’s not that the core render code is written in plain c that’s the problem (c/c++, don’t care - they both support structs), it’s because it’s so badly written in c that’s the problem, and it’s GL renderer module is very inefficient.
Anyway, as has been said - at least he got it out the door and made lots of money.

should be as clean, readable and well-designed to anyone with really basic algebra knowledge as:

First of all, that’s just bad coding practice. The distance function should be its own function so that, if you made a mistake in typing it, you only have to fix it in one place (rather than having to hunt it down throughout your entire codebase). And this is for any programming, C, C++, Java, Visual Basic, etc. A programmer who didn’t break the distance formula into its own function obviously lacks some sense of code design.

Secondly, there’s no way that “sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));” is a clear as “Distance()”. At the very least, it takes longer to read the first one. Also, unless there is a comment in front of it, you have to take a moment to realize you’re looking at the distance formula (even for the experienced, it takes a moment to recogize it in C). This isn’t even a question; it’s a fact.

The line “sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));” should have a comment. The line “Distance()” doesn’t need one; you know exactly what it does by trivial inspection. A 10-year old understands it as well as an experienced programmer.

[This message has been edited by Korval (edited 05-04-2003).]

On their official E3 movie you can see some lines of code of Doom III…

you ought to see some scary “typedef struct { };” construct!

As far as I can tell Carmack never said he was a good programmers, in fact it’s often said that he is a bad programmer. But he excels at finding solutions for problems.

But anyway I’m often shocked by the code of other people, it’s just that Carmack’s code is below average.
Hell, when I look at some code I wrote 6 months ago I already want to rewrite it again.

I don’t really care how well done are the sources of a program if it works correctly. Unfortunatly you can explain most recurring bugs in Q1/2/3 simply by looking at the quality of the code, it’s a bit unfortunate that most of these bugs could have been easily avoided if properly coded.

[This message has been edited by GPSnoopy (edited 05-04-2003).]

Dist is pretty readable if you write it like this

d = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));

but well most of the time it would be more like

x1 = whatever expression to get you the x coord
x2 = whatever expression to get you the second x coord (involving [] -> or .)

d = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));

I mean’you can’t be serious about this…
(Besides in quake it mostly looks like this)

vec3_t delta;


VectorSubtract(blah, bleh, delta);
d = Length(delta);

More readable but still more typing and an extra variable in the body needs to be added. (damn C needs to have them at the beginning of a block )

Charles

Originally posted by Pentagram:

[quote]

vec3_t delta;


VectorSubtract(blah, bleh, delta);
d = Length(delta);

More readable but still more typing and an extra variable in the body needs to be added. (damn C needs to have them at the beginning of a block )

Charles[/b][/QUOTE]

Yeah, prolly it be much better the C++ compiler to create 7-8 temporaries, eh ?

And before criticizing C, care to learn it ?

~velco

Yup, autos/temps are evil especially in high frequency calls. Making them static is better but they eat up memory. My timings showed 50% speed gain when using statics instead of autos. Anyone else noticed looping in quake1 math functions? Should be unrolled I think.

1st rule: C is generally faster than C++. 2nd rule: OK, OK, the coding style can change a lot, but, look at 1st rule

OK, enough 1st thing about quarks, they have been finished 2nd they were ‘best’ 3D’s of that time. 3rd have you seen Half-Life code?
And finally, syntax could look ugly, but somtimes it just works and you could have supa-dupa structures through 10 classes game->ogl->bsptree->to->left->bottom->prerender->render that’ll have such a hell of overhead that it’ll have -1 fps on R9800. The thing I like about classes is that they make code more readable and you can finish + sell that s**t , though in c you ‘can’ do that faster