flipCode - Tech File - Nicholas Vining [an error occurred while processing this directive]
Nicholas Vining
Click the name for some bio info

E-Mail: vining@pacificcoast.net



   06/19/2000, Tech File Update


OK. I'm writing this from a self-driven hacking session which should last for as long as it can without interruption. I've got nothing better to do, and it's good practice for my Math 12 exam. I'm taking a break because my head hurts. So I thought I'd tell a little story which happened three hours ago, about how something went from crap to really good.

Anyways, I'm working on a 3D engine, and one of the bits are the vector typedefs. Formerly, they were defined as:

typedef float vec4[4];
typedef float mat4[16];
etc.

Well, there were a variety of fascinating problems that came out of that approach, mainly to do with the fact that I'm working in pure C, and C doesn't have a & operator for referential parameters or whatever they're called. So, I'm sitting on my chair, staring at my monitor, drinking "Tension Tamer" herbal tea, (Tranquilitea!), and thinking, "Holy smokes, what a pile of creepy crawlies I've created. How the heck do I deal with that?" In particular, there's a truly impressive phenomenon which will go down in history as "The 64 cell 4x4 matrix bug". I've got pointers flying all over the place, my code's a mess, my SDL Parachute has three big gashes in it, and I've spent two hours in GDB laying breakpoints and trying to figure out if I'd be better off developing a career as a screenwriter.

So, I log onto IRC while thinking about it, and a character by the name of Yorick suggests that I just use structs instead. You get better typecasting and functions can return them.

That would be nice, I think, except that I don't want to do something like:

typedef struct
{
    float x,y,z,w;
} vec4;
because that way I have to access everything individually instead of being able to do a memory copy.

So, I think... and I decide, "Why not do it this way?"

typedef struct
{
    float v[4];
} vec4;

typedef struct
{
    float m[16];
} mat4;
30 minutes later, I discover that this must be the way all really good programmers have been doing it all along. A bit more hacking, and discovering that in my matrix generation code I put the translation bits in _exactly_ the wrong place, and WHAM! Everything suddenly starts working, and I have a screaming zombie spinning on my screen. Woo-hoo!

Then I start thinking again. A neat secondary advantage is that you can easily recognize which terms are matrix components and which terms are vector components in an equation. So if you've got something like this:

product.v[0] = (a.v[0] * b.m[0]) + (a.v[1] * b.m[5]) + (a.v[2] * b.m[9]) + a.v[3];
and you can instantly tell which bits are matrix and which bits are vectors, as if you couldn't already... but it's good if you're busy scaling stuff, translating stuff, or busy dumping data into a rendering pipeline. It also gives you automatic type reference and means you can pass results back directly.

Now, at first I thought, "OK.... well, that'll fix THAT batch of problems... but how sucky!" Then I see how much easier everything gets. Sweet! No more worrying about pointers not typecasting correctly, stupid errors, and the amazing 64 cell 4x4 matrix bug. Then I see the fact that I can now easily recognize vectors, and that everything will become so much nicer from here-on in.

Now, that seems like a _REALLY_ little thing, right? So bloody trivial, you're asking "well, why bother?" Little details like this are important. I think this is easier to use -- it certainly let me clean up my own code and get it all working -- so it may even speed up productivity. It's nice to find the better way occasionally... especially for something trivial, like redefining a few simple typedefs. My thanks to Yorick for the excellent suggestion. (FWIW, he suggested that I go with v[4] about thirty seconds after I thought "my what a good idea"!)

Don't even ask about the amazing 64 cell 4x4 matrix bug. I can only assume that it was a sign of the second coming.

Cheers,

Nicholas





  • 06/19/2000 - Tech File Update
  • 06/04/2000 - Being John Carmack
  • 05/08/2000 - Tech File Update
  • 04/11/2000 - Tech File Update
  • 03/07/2000 - Introduction

  • This document may not be reproduced in any way without explicit permission from the author and flipCode. All Rights Reserved. Best viewed at a high resolution. The views expressed in this document are the views of the author and NOT neccesarily of anyone else associated with flipCode.

    [an error occurred while processing this directive]