Welcome to TiddlyWiki created by Jeremy Ruston; Copyright © 2004-2007 Jeremy Ruston, Copyright © 2007-2011 UnaMesa Association

Man - this blog isn't even a day old and I'm already getting shit about the information overload caused by using sophisticated new Wiki technology. One doesn't like that he can't read it on his Lunix box, another moans that there's too much stuff they can click on and can't I just use a text file? No dammit! I like snazzy new gratuitous tech. This blog is going to be mainly about snazzy new gratuitous tech (with the occasional UphillBothWays nostalgia moan added for good measure). And since this is a thing as totally meaningless and self-centered as a blog, I'm going to use it like I stole it. Er... which I did (thanks [[Jeremy|http://www.tiddlywiki.com/]]). It's not like I'm demanding you use MS tech or anything hentai like that. Er... news? No, I have none of that. Except that I went to see my accountant today and he said I owed The Man five digits. OK, so as an immigrant Brit living in the US seeking asylum from crappy pay and on a "you can stay if you don't cast nasturtiums on Mr. POTUS" visa making money for US companies and spending all my hard-earned cash on other US companies, would it be slightly impolitic to utter the phrase "No taxation without representation?" Yeah, thought not. Even after I get my green card, I have to tell HRH Brenda to shove it before I get to cast a pointless vote in my local United Franchise of America. Gonna book me a plane ticket to Boston, gonna tip a crate of your shitty bourbon into the harbour. Yes, "harbour". It's got a "u" in it. Blow me. Where's my Laphroaig, [[wench|TheWife]]? To be fair, it's all because I got a mildly obscene Christmas bonus on account of the SuperSecretProject. You so want my boss. But you can't have him. He's mine. All mine!

Double precision - it's not magic. But people keep invoking it like it is. ''The problem with floats'' Floating-point numbers are brilliant - they have decent precision and a large range. But they still only have 32 bits, so there's still only 4billion different ones (actually there's fewer than that if you ignore all the varieties of ~NANs, assume infs are basically bugs, and turn off denormals because they're agonisingly slow). So they have tradeoffs and weaknesses just like everything else. You need to know what they are, and what happens for example when you subtract one small number from another - you get imprecision. Ideally every programmer should know the basics of floating-point numerical precision. Any time you do a subtract (or an add, implicitly), consider what happens when the two numbers are very close together, e.g. 1.0000011 - 1.0. The result of this is going to be roughly 0.0000011 of course, but the "roughly" is going to be pretty rough. In general you only get about six-and-a-bit decimal digits of precision from floats (2^23 is 8388608), so the problem is that 1.0000011 isn't very precise - it could be anywhere between 1.0000012 or 1.0000010. So the result of the subtraction is anywhere between 1.2*10^-6 and 1.0*10^-6. That's not very impressive precision, having the second digit be wrong! So you need to refactor your algorithms to fix this. The most obvious place this happens in games is when you're storing world coodinates in standard float32s, and two objects get a decent way from the origin. The first thing you do in rendering is to subtract the camera's position from each object's position, and then send that all the way down the rendering pipeline. The rest all works fine, because everything is relative to the camera, it's that first subtraction that is the problem. For example, getting only six decimal digits of precision, if you're 10km from the origin (London is easily over 20km across), you'll only get about 1cm accuracy. Which doesn't sound that bad in a static screenshot, but as soon as things start moving, you can easily see this horrible jerkiness and quantisation. ''Double trouble'' The solution is "obvious" - if single precision isn't enough, switch to storing your positions in double precision! Unfortunately there's some practical problems. The most obvious is that some machines simply don't do doubles (~PS2, some mobile devices), and on machines that do support doubles, there's usually speed penalties. Even on nice modern ~PCs, actually getting double-precision can be tricky - it's not enough to just write "double" in C - that would be far too simple! Bruce Dawson has a nice round-up of the (extensive) problems - this article is guaranteed to surprise even very experienced coders, so you should read it: https://randomascii.wordpress.com/2012/03/21/intermediate-floating-point-precision/ But let's say you went through all that build agony to get them working, and accepted the speed hit. Really you haven't solved the problem, you've just brushed it under the carpet. Doubles have exactly the same weaknesses as any floating-point representation - variable precision and catastrophic cancellation. All you've done is shuffle the problems into a corner, stuck your fingers in your ears and yelled "lalalalalala". They'll still come back to bite you, and because it's double precision, it'll be even rarer and even harder to track down. And in exchange you've hurt your execution speed and caused build problems. ''Fix it!'' So what's the alternative? Good old fixed-point numbers. They're an old-school technique from before the days of 68881 and 80x87 coprocessors. They're simply integers that you treat as if at some defined place in them is a decimal point - usually expressed as something like "24.8" - which means a 32-bit integer that represents a real-world value with 24 bits of whole value and 8 bits of fraction. So for example the real number X would be represented as the integer (int)(X*256) with appropriate rounding. For general maths, fixed point sounds like a real pain - and I'm not going to lie, it is. I've written raytracers in fixed-point maths, and the constant management of precision really sucks - even with good macro libraries. Float32 is a huge improvement in usability for 99% of maths code. But for absolute position and absolute time, fixed-point works really well. All you ever do with these is subtract one position from another (to produce a float32 delta), or add a (float32) delta to a position. You almost never need to do maths like multiply two positions together - that doesn't even "mean" anything. 64-bit fixed-point integers are supported on pretty much every platform. Even if they're not natively supported, they're easily emulated with things like add-with-carry instructions (and those platforms will have awful float64 support anyway). And fixed-point representations have completely reliable precision. They're just integers - there's no scariness there, they're completely portable, easy to debug, and you know exactly what you're getting in terms of precision. This has huge implications for robustness and testability. ''Works on my machine'' If you're like me, when you develop code, you do so in a tiny sandbox game level so you don't have to spend five minutes loading the assets for a full level. And yay - everything works fine. The physics works, the gameplay movement works, there's no falling-out-of-maps stuff, everything is smooth. So you check it in and then several weeks later someone says there's some bad stuff happening in level X - objects falling through the floor, or moving erratically, or the physics is bouncing oddly. So you test level X and it seems fine, and then you have the "works on my machine" argument with the tester, and it takes you several days to figure out that it only happens in one part of level X, and wouldn't you know it - that's the part where you're a long way from the origin and some part of the physics code is subtracting two large numbers and getting an imprecise result. The nice thing about fixed point is it's consistent. You get the same precision everywhere. If your time step and physics epsilons work at the origin, they work everywhere. And before you moan that fixed-point doesn't have the range - 32 bits of fixed-point gets you anywhere on Earth to about 3mm. Not enough? Well 64 bits of precision gets you to the furthest distance of Pluto from the Sun (7.4 billion km) with sub-micrometer precision. And it's all consistent precision - no lumpy parts or fine parts or places where you suddenly get denormals creeping in and your performance goes through the floor for no well-identifiable reason. ''About time'' That's position, but let's talk about time. Time is where it can really fall over, and it's the place that will most often bite people. If you are doing any sort of precise timing - physics, animation, sound playback - you need not just good precision, but totally reliable precision, because there tend to be a bunch of epsilons that need tuning. You're almost always taking deltas between absolute times, e.g. the current time and the time an animation started, or when a sound was triggered. Everything works fine in your game for the first five minutes, because absolute time probably started at zero, so you're getting lots of precision. But play it for four hours, and now everything's really jinky and jittery. The reason is that four hours is right about 2^24 milliseconds, so you're running out of float precision for anything measured in milliseconds, which is why physics and sound are particularly susceptible - but almost any motion in a game will show this jittering. For added hilarity, if a tester does run across a problem with timing precision, they save the game, send it to a coder, and the coder loads it and... it doesn't happen - because time got reset to zero! This is a very effective way to drive QA completely insane. Again, fixed-point gives you completely reliable precision, no matter how long the game has been running. It's interesting to note that fixed-point time has an easy precedent to follow - [[Network Time Protocol|http://en.wikipedia.org/wiki/Network_Time_Protocol#Timestamps]]. They use a "32.32" format in seconds, meaning there's 32 bits measuring whole seconds, and 32 bits measuring fractions of a second. This has a precision of 233 picoseconds and rolls over every 136 years, both of which should be good enough for most games. In addition, it's very easy for humans to read and use - the top 32 bits is just the time in seconds. (as an side - they are considering extending it to a 64.64 format to fix the rollover in 2036 - this gives them completely gratuitous range and precision - to quote: "the 64 bit value for the fraction is enough to resolve the amount of time it takes a photon to pass an electron (at the speed of light). The 64 bit second value is enough to provide unambiguous time representation until the universe goes dim.") ''Protect yourself'' Even if you don't believe anything else in this post, even if you absolutely insist that floating point will be just fine for everything - please at the very least understand that setting your time to zero at the start of your app is a terrible thing to do. You will fool yourself. If there is any chance at all that someone might play your game for four hours, or leave it on the main menu for four hours, or leave it paused mid-game for four hours, initialize your clock at much much more than four hours! At least that way you'll find the problems sooner. ''Implementation tips'' I think the easiest way to encapsulate this (if you're an OOP fan) is to make a "position" class that holds your chosen representation, and the only operations you can perform on that class (aside from copies and the usual) are subtracting one from another to give a standard float32 vec3, and adding a float32 vec3 to a position to get another position. So it means you can't accidentally use a position without doing calculations relative to another position. The same goes for time - internally you might use a 32.32 number, but all the outside world needs to know is what ~TimeA-~TimeB is, and that can be a float32 quite happily. Similarly, the only operation you need to do on a time is adjust it forwards or backwards by a timestep, and it's fine to have the timestep as a float32. You should find that those operations are all you actually need. If not, then it's probably time to refactor some code, because you're likely to have problems when doing things at different distances from the origin, or at different times. The one thing I have seen is people making BSP trees out of the entire world, and then storing the planes as A,B,C,D where: Ax+By+Cz+D>0. Which is fine, except that's also going to have precision problems. And it's going to have precision problems far earlier, because x,y,z are another object's position. And now you're multiplying two positions together and subtracting a bunch of them and asking if they're positive or negative and the problem with that is that you will halve your available precision. So even doubles will only get you 52/2 = 26 bits of precision, which is rubbish. And experience with BSP trees has shown that they're extremely intolerant of precision errors. The solution for this case is to store a point on the plane and the plane's normal. Otherwise even decently-size levels are going to end up in agony (Michael Abrash has a story exactly like this about Quake 1 - they had tiny tiny levels and they had problems!). Restricting yourself to just taking deltas between two positions will highlight problems like this and allow you to rethink them before they happen. ''TLDR'' * Don't start your times at zero. Start them at something big. Ideally do the same with position - by default set your origin a long way away. * float32 has precision problems even in normal circumstances - you only get about seven digits of precision. * float64 is a tricky beast to use in practice - writing "double" in C is not sufficient. * Variable precision is a nightmare for reproducibility and testability - even float64. * Fixed-point may be old, but it works well for absolute time and position. * Help yourself guard against precision-cancellation problems by not exposing absolute time and position to most parts of your app. Any time you think you need them, you're almost certainly going about the problem wrong. * New OffendOMatic rule: any time you want to use doubles in a game, you probably haven't understood the algorithm.

I've always hated two things about sprintf. The main annoyance is that you have to have the format string, and then after that comes all the arguments. It really doesn't read well, and it's too easy to get the arguments the wrong way round or add or forget one. Related to this is the fact that there's no type-safety, so when you do screw up, it can lead to silent and/or really obscure memory-scribbler bugs. One alternative is the cout/iostream style format with a lot of << stuff everywhere. That makes my eyeballs itch with the amount of C++ involved, and it's ugly to use with string destinations. A third option is smart strings, but the complexity and constant alloc/dealloc behaviour also offends me. I'll be honest - I worry a lot of that magic allocation stuff is just far too complex for mortals to debug or profile. It's far too easy to write a line of simple-looking code and destroy performance. I was hoping not to reinvent the wheel, and a few people pointed me at [[FastFormat|http://www.fastformat.org]]. It has a mode that seems to sort-of do what I want, but the documentation is a disaster and the scope of the thing is clearly huge and way beyond what I need, so rather than wade through it for two hours, I thought I'd see if I could write something simple in two hours that does what I want. Turns out, the answer is "yes". So, the goals are: * No dynamic allocation. * Easier to read and control than sprintf() * Type-safe (in as much as C can ever be type-safe - bloody auto-converts). * Overflow-safe (i.e. it will refuse to scribble, and will assert in debug mode). The thing I'm happy to give up is extendable-length strings, i.e. I don't mind pre-declaring the max length of any string. That's kinda obvious since I don't want dynamic allocation, but it's worth stating explicitly. So the very first thing I wrote almost worked. The first bit was easy - it's this: {{{ struct StaticStr { unsigned int MaxLen; char *pStr; StaticStr ( char *pStrIn, int MaxLengthIn ) { MaxLen = MaxLengthIn; pStr = pStrIn; } ~StaticStr() { // Nothing! } // Cast to a normal string. It's deliberate that it's not a const (but be careful with it). char *Cstr() { return pStr; } // Assignment. StaticStr & operator= ( const StaticStr &other ) { ASSERT ( strlen ( other.pStr ) < this->MaxLen ); strncpy ( this->pStr, other.pStr, this->MaxLen ); this->pStr[this->MaxLen-1] = '\0'; return *this; } // Assignment from a C string. StaticStr & operator= ( const char *pOther ) { ASSERT ( strlen ( pOther ) < this->MaxLen ); strncpy ( this->pStr, pOther, this->MaxLen ); this->pStr[this->MaxLen-1] = '\0'; return *this; } StaticStr & operator+= ( const StaticStr &other ) { int ThisLength = strlen ( this->pStr ); ASSERT ( ( ThisLength + strlen ( other.pStr ) ) < this->MaxLen ); strncat ( this->pStr, other.pStr, this->MaxLen - ThisLength - 1 ); return *this; } // This is actualy an append - it's really += rather than + but the typing gets tedious. StaticStr & operator+ ( const StaticStr &other ) { return *this += other; } // Append of a C string. StaticStr & operator+= ( const char *pOther ) { int ThisLength = strlen ( this->pStr ); ASSERT ( ( ThisLength + strlen ( pOther ) ) < this->MaxLen ); strncat ( this->pStr, pOther, this->MaxLen - ThisLength - 1 ); return *this; } StaticStr & operator+ ( const char *pOther ) { return *this += pOther; } }; // Slightly ugly... // Used like: // StaticStrDecl ( sstemp1, 1024 ); #define StaticStrDecl(name,length) char StaticStringCalled ## name[length]; StaticStr name ( StaticStringCalled ## name, length ) // char *pTemp[1024]; // StaticStrWrap ( sstemp1, pTemp ); #define StaticStrWrap(name,strname) StaticStr name ( strname, sizeof(strname)/sizeof(strname[0]) ) }}} And that works fine for sticking strings together, so you can do code like this: {{{ StaticStrDecl(string1, 1024); char TempString[100]; StaticStrWrap(string2, TempString); string1 = "Hello"; string2 = " world"; string1 += string2; string1 += " again"; }}} ...or more obviously usefully, code like this: {{{ string2 = " world"; (string1 = "Hello") + string2 + " again"; }}} Note the annoying braces. If you just do this: {{{ string1 = "Hello" + string2 + " again"; }}} ...the way you'd like to, it fails to compile because there's no + operator that takes a left hand of a char*, and it doesn't figure out that a different precedence would fix things. It's a pretty minor annoyance. I'm sure somebody with more C++ operator overloading experience can tell me how to fix it, but honestly I'm not sure I want to know. Technically I shouldn't have allowed the + operator, because it's an append, and you should have to write this: {{{ (string1 = "Hello") += string2 += " again"; }}} ...but I hate the typing. Part of the impetus is to make things easier to read, not harder. Also, for reasons I really don't want to pollute my brain with ''(so don't email me)'' the operator precedence changes, so you actually get: {{{ (string1 = "Hello") += (string2 += " again"); }}} ...which means although string1 is correct, string2 now contains " world again", which is not really want I wanted. Of course you can still get strange things happening in some cases if you forget the braces: {{{ string2 = "Hello"; string1 = string2 + " world"; // I forgot the braces, but this still compiles & runs. }}} Now both of them contain "Hello world". Maybe with some sort of gratuitous const gymnastics I could fix it, but right now I'm going to ignore it and hope it doesn't bite me in the arse later. Yeah, right. Ugh. Anyway, so what about actual number printing? Well, my first attempt was to use some temp strings and some functions to wrap sprintf, such as {{{ StaticStr & Int ( int i ) { int written = _snprintf ( pStr, MaxLen, "%i", i ); ASSERT ( ( written >= 0 ) && ( (unsigned)written < MaxLen ) ); return *this; } }}} The way you use it is like this: {{{ (string1 = "Hello ") + string2.Int(1) + " world"; }}} ...and this works. string2 is "1" and string1 is "Hello 1 world". The problem comes when you want to print multiple numbers using the same temp: {{{ (string1 = "Hello ") + string2.Int(1) + " world " + string2.Int(2); }}} The problem is the two Int() functions get called before any concatenation happens, so what you get is "Hello 1 world 1". Why they're called last first is also a mystery - I was at least expecting to get "Hello 2 world 2". It's probably poorly defined anyway. Note that this isn't an operator precedence problem - adding lots of braces doesn't fix the problem. Nuts. I had a cup of tea and a sit-down and a think and then an alternative came to me. It turns out it's much nicer to type, completely avoids the temporary problem, and is faster (not that speed is exactly a priority, especially when printing floats, but it's never a bad thing). First step, add a seemingly pointless helper class: {{{ struct StStInt { int mValue; StStInt ( int Value ) { mValue = Value; } }; }}} That's it - that's all it does - no other methods. There's also ~StStFloat. "~StSt" is just an abbreviation for "~StaticStr." You'll see why I want to shorten it in a bit. Then I add this method to ~StaticStr: {{{ StaticStr & operator+ ( const StStInt &Other ) { int StrLen = strlen ( pStr ); int written = _snprintf ( pStr+StrLen, MaxLen-StrLen, "%i", Other.mValue ); ASSERT ( ( written >= 0 ) && ( (unsigned)written < MaxLen ) ); pStr[MaxLen-1] = '\0'; return *this; } }}} Most of the complexity here is dealing with the completely bonkers behaviour of _snprintf and various overflow checking - the actual conversion stuff is simple. Now you can write fairly elegant stuff like: {{{ string2 = " world "; (string1 = "Hello ") + StStInt(1) + string2 + StStInt(2); }}} You still need the extra braces, annoyingly, but it works just fine. There's no temporaries either - the values are just _snprintf'ed right onto the end of the existing string. The fact that string2 doesn't get modified is nice as well, though I worry that might be undefined behaviour, so maybe don't push it. The next step was to handle formatting, because sometimes you do want it. The routines get only slightly more complex: {{{ struct StStFloat { float mValue; int mPrecision; int mMinWidth; StStFloat ( float Value, int Precision = -1, int MinWidth = -1 ) { mValue = Value; mPrecision = Precision; mMinWidth = MinWidth; } }; }}} ...and... {{{ StaticStr & operator+ ( const StStFloat &Other ) { int StrLen = strlen ( pStr ); int written = -1; if ( Other.mMinWidth < 0 ) { if ( Other.mPrecision < 0 ) { written = _snprintf ( pStr+StrLen, MaxLen-StrLen, "%f", Other.mValue ); } else { written = _snprintf ( pStr+StrLen, MaxLen-StrLen, "%.*f", Other.mPrecision, Other.mValue ); } } else { if ( Other.mPrecision < 0 ) { written = _snprintf ( pStr+StrLen, MaxLen-StrLen, "%*f", Other.mMinWidth, Other.mValue ); } else { written = _snprintf ( pStr+StrLen, MaxLen-StrLen, "%*.*f", Other.mMinWidth, Other.mPrecision, Other.mValue ); } } pStr[MaxLen-1] = '\0'; ASSERT ( ( written >= 0 ) && ( (unsigned)written < MaxLen ) ); return *this; } }}} And that means you can do elegant things like: {{{ (string1 = "Hello ") + StStFloat(1.0f) + ":" + StStFloat(2.0f, 2) + ":" + StStFloat(3.0f, -1, 15) + ":" + StStFloat(4.0f, 3, 10); }}} Which produces string1="Hello 1.000000:2.00: 3.000000: 4.000". Don't ask me why the default precision for _snprintf likes so many decimal points. Anyway, so I got my wish - I got a zero-dynamic-allocation, typesafe, format-free and fairly readable version of sprintf. Happy coder joy joy! Your mission, should you choose to accept it, is to go out and find the wheel that I just reinvented, thus saving me the hassle and embarrassment of using this library evermore. This blog will self-destruct when I get around to it.

Someone prodded me about this the other day, so I thought I should get on and do it. I gave a GDC 2003 talk about SH, but I was never really happy with it - half an hour isn't really enough to cover it well. I haven't changed the slides, but now I have some notes for it. I corrected an error, finally wrote those elusive fConstX values down, but mainly I talk about some surrounding details about the console implementation I actually used it in - what is probably the coolest bit of all - or at least it's the bit the artists really liked about the new system. [[Spherical Harmonics in Actual Games notes]]

The rest have been removed from the front page to save space. Here are all my blog entries in chronological order: [[VR optics and why IPD means too many things]] [[Why didn't Larrabee fail?]] [[The sRGB learning curve]] [[NaNs cause the craziest bugs]] [[Memory stacks and more resizable arrays]] [[Premultiplied alpha part 2]] [[Texture coordinate origin]] [[Elite Dangerous on the Rift]] [[Display rate, rendering rate, and persistence]] [[Wrangling enums]] [[Simple Perforce setup for the solo coder]] [[Even more precision]] [[Resizable arrays without using STL]] [[Polynomial interpolation]] [[How not to interview]] [[Sparse-world storage formats]] [[Matrix maths and names]] [[New Job]] [[A sprintf that isn't as ugly]] [[Saving, loading, replaying and debugging]] [[StarTopia love]] [[Logging, asserts and unit tests]] [[Data Oriented Luddites]] [[Moore's Law vs Duck Typing]] [[Platform-agnostic types]] [[Texture streaming systems with two levels of cache]] [[Visibility and priority tests for streaming assets]] [[Squares or hexes]] [[Dwarf Minecart Tycoon]] [[Larrabee talk roundup and media attention]] [[GDC 09]] [[How to walk better]] [[Larrabee ISA unveiled at GDC 2009]] [[CAs in cloud formation]] [[Regular mesh vertex cache ordering]] [[Siggraph Asia 2008]] [[Plague]] [[Siggraph 2008]] [[ShaderX2 available for free]] [[Larrabee and raytracing]] [[Renderstate change costs]] [[Larrabee decloak]] [[Blog linkage]] [[Smart coder priorities]] [[Rasteriser vs Raytracer]] [[Texture formats for faster compression]] [[Knowing which mipmap levels are needed]] [[SSE]] [[Patently evil]] [[Trilights]] [[Bitangents]] [[More vertex cache optimisation]] [[Reinventing the wheel - again!]] [[Shadowbuffers and shaders]] [[Utah Teapot]] [[GDC survival guide]] [[Pixomatic slides]] [[Notepad++]] [[More on SH]] [[Licenses]] [[Added some hindsights and notes on Spherical Harmonics]] [[Cellular Automata article added]] [[Impostor article added]] [[Shadowmap vs shadowbuffer]] [[Vertex Cache Optimisation]] [[Strippers]] [[Scene Graphs - just say no]] [[Dodgy demos]] [[Premultiplied alpha]] [[Babbage was a true genius]] [[Someone cited my VIPM article]] [[VIPM article in HTML]] [[RSS part 3]] [[VGA was good enough for my grandfather]] [[RSS part 2]] [[A matter of precision]] [[Game Middleware list]] [[RSS banditry]] [[...there was a load of words]] [[In the beginning...]]

A set of articles set up by Mike Action and friends: http://altdevblogaday.com/

I've just been reading up on the Analytical Engine. I've known the background to Babbage's life and works for ages, and I knew he was incredibly clever - the Difference Engine is an amazing feat when you consider it's made of mechanical gears and powered by a human cranking on a lever. But fundamentally all it does is a bunch of parallel additions. For the time, it would have done them extremely fast and have had awesome reliability, but the actual computations were perfectly well-understood. By the way, if you're ever in London, you have to go visit the Science Museum in South Kensington and see the [[Difference Engine Mk2|http://en.wikipedia.org/wiki/Difference_engine]] that they built. It's truly fascinating watching it work, and work well. The thing I didn't realise until I read a bit more about it is that it's actually built to achievable 19th-century tolerances, which means Babbage actually could have built the whole thing, and it would have worked convincingly and usefully. His problems were political and financial rather than mechanical, and it didn't help that he was a pompous jerk (like many geniuses). But again, perfectly well-understood maths in the Difference Engine. Couldn't do anything revolutionary, just would have done it far better than the existing mechanisms (a room full of people adding stuff manually). No, the real genius came with the Analytical Engine. Again, I've always known it was the first programmable computer, but when people say that - you always imagine that well yes, it was slightly smarter than a [[Jacquard Loom|http://en.wikipedia.org/wiki/Jacquard_loom]], and maybe if you squinted a bit and jumped through many flaming hoops you might see it was getting close to Turing-capable, and if you examined manuals a lot and were cunning you could get it to do something kinda like a proper algorithm. Certainly when I've looked at the functionality of some of the 1940s and 50s computers, that's what they always looked like. No, that's not the Analytical Engine at all. It's not a bag of bolts that some mathematician can show in 200 pages of jargon can be made to be Turing-complete. It's much better than that - it's basically a 6502 with bells on (literally). [[Here are lots of details|http://www.fourmilab.ch/babbage/cards.html]] (including an emulator!), but basically it has a fairly straightforwards machine language - it does addition, subtraction, multiplication and division. It has two input registers and an output register. You can do loads from a store (memory) with 1000 entries, to the input registers, and when you load the second register, it does the operation you ask, and puts the result in the output register, which you can move to the store. You can also do shifts left and right to move the decimal point around in fixed-point maths. If the result of a computation has a different sign to the first input, or overflows, it makes a "run-up lever" move upwards. One could imagine tying a small bit of cloth to this lever, and then one might term this "raising a flag". You can issue commands that say to move backwards or forwards by a set number of commands, and you can tell it to do this all the time, or only if the run-up level is raised. Hey - unconditional and conditional branches. I mean that's it - it's so absurdly simple. It has load, store, the basic six arithmetic operations, and conditional branches. Right there in front of you. It's a processor. You could code on it. Look, here's some code (with my comments): {{{ N0 6 ;; preload memory location 0 with the number 6 N1 1 ;; preload memory location 1 with the number 1 N2 1 ;; preload memory location 2 with the number 1 x ;; set the operation to multiply L1 ;; load memory location 1 into the ALU L0 ;; load memory location 0 into the ALU - second load causes the multiply operation to happen S1 ;; store the result in location 1. - ;; set the operation to subtract L0 ;; load location 0 L2 ;; load location 2 - causes subtraction to happen. S0 ;; store to location 0 L2 ;; load location 2 L0 ;; load location 0 - causes subtraction to happen. ;; If the result sign is different to the first argument, the run-up-lever is raised CB?11 ;; if the run-up-lever is raised, move back 11 instructions. ;; Like today's CPUs, the location of the "instruction pointer" has already moved past this instruction, ;; so back 11 means the next instruction is the "x" above. }}} The result of this function is in location 1. Notice that location 2 never gets stored to - it's the constant value 1. Still having a bit of trouble - let me translate it to C: {{{ int mystery_function ( int loc0 ) { int loc1 = 1; const int loc2 = 1; keep_looping: loc1 = loc1 * loc0; loc0 = loc0 - loc2; if ( sgn(loc2 - loc0) != sgn(loc2) ) { goto keep_looping; } return loc1; } }}} ...and now change "loc2" to be "1" and massage the "if" conditional appropriately: {{{ int mystery_function ( int loc0 ) { int loc1 = 1; keep_looping: loc1 *= loc0; --loc0; if ( loc0 > 1 ) { goto keep_looping; } return loc1; } }}} You can't still be having trouble. It's a factorial function! Apart from the slight wackiness of the loop counter, which is an idiom just like any other language, it's all absurdly simple and powerful. The only big thing he was missing from the ALU was direct boolean logic for doing complex control logic. But it's not a huge lack - first, it can all be emulated without too much pain with decimal logic (OR is an add, AND is a multiply, etc), and secondly after about five minutes playing with the thing he would have realised that he needed something like that, and the mechanicals for boolean logic are trivial compared to decimal multiplication and division. Just to gild the lilly, Babbage wanted to attach a plotter to it. You could send the most recent computed result to the X-coordinate or Y-coordinate of the plotter, and you could raise or lower the pen. He could have coded up Tron light-cycles on the damn thing. The one thing he missed (and to be fair so did half the computer pioneers of the 1940s) is the ability to compute addresses, i.e. instead of always looking up the data in location N where N is punched into the card itself, the ability to calculate N with maths. However, he did think of precomputed lookup-tables, which is one form of this, but only loading from it, not storing to it. Amusingly, he then decided that actually, since the table - e.g. of logarithms - had been generated by the AE in an earlier run, and that doing the lookup involved the AE displaying a number and then ringing a bell and getting a man to go rummage through a stack of punched-cards for the right one, which would take time and be error-prone (he also had a primitive error-checking system!), it might just be better if the machine recomputed the desired value there and then, rather than using a LUT at all. Which is almost exactly where we are in computing now, where LUTs are frequently slower and less accurate than just re-doing the computation! And he did all of this in a total vacuum. He had nothing but paper and pen and brass and plans and his brains, and he invented a frighteningly useful, powerful and easy-to-program processor. Including comments and debugging support. They didn't even have a machine as powerful as a cash-register at the time - nothing! So when I say Babbage was a genius - he's one of the greats. If he'd succeeded even slightly, if the Difference Engine had got half-finished and produced useful results and people had taken him seriously - all that Turing and von Neumann stuff that we think of as the birth of modern computing - obsolete before they even thought of it, because Babbage got there nearly a century before. Put it like this - if he had been born almost exactly 100 years //later// and instead of brass and steam had worked in relays and electrickery in the 1950s, he would have made almost exactly the same breakthroughs and probably built almost exactly the same machine - it just would have been a bit faster (but less reliable - bloody valves!). It's almost shameful that in those 100 years, nobody advanced the art of computing in the slightest. And yet think of all the things that have happened in the 50 years since then. I read Sterling and Gibson's book "The Difference Engine" ages ago, and thought it was all a bit of a flight of fancy - pushing the probability curve to breaking-point - the way SF authors should. Now - I'm not sure it was at all fanciful. Imagine if we were living in a world that had had computers for three times as long. Gordon Moore's famous law would have gone totally ballistic by now. Microsoft's motto would have been "a computer in every can of coke", because we'd have had a computer on every desk since about 1910, and the big thing that helped the Allies beat the Nazis wouldn't have been radar, it would have been the Web. There's just one bizarre thing I can't figure out. Babbage initially specified the Analytical Engine to 40 //decimal// digits. Later, he upped it to 50. 50 decimal digits is about 166 bits. That's gigantic, even for fixed-point arithmetic. These days we find 32 bits just fine (9-and-a-bit decimal digits) - 64 in some specialised places (19 digits). But 166 bits is nuts - that is collossal over-engineering. And it's not because he didn't understand the maths - it's extremely clear from his writings that he understood fixed-point math perfectly well - shifting stuff up and down after multiplication and division, etc. In two separate places he explained how to do arbitrary-precision arithmetic using the "run-up lever" (i.e. the AE version of "add-with-carry") in case people needed 100 or 200 digit numbers. To put this in perspective, the universe is at least 156 billion light-years wide - that's 1.5 x 10^27 meters. A single proton is 10^-15 meters across. So the universe is roughly 1.5 x 10^42 protons in size - which only takes 43 decimal digits to represent. Babbage decided that wasn't enough - he needed the full 50 digits. Also, he specified a memory of 1000 entries of these 50-digit numbers, and that didn't include the code, just data - that's 20kbytes of random-access data. For a smart guy whose major problems were finding good enough large-scale manufacturing technologies and finding the cash to build his gigantic room-sized engine, that seems pretty dumb. If he'd built a 3-digit AE, his instruction set would have exceeded the computing capabilities of every 8-bit machine in the home microcomputer revoloution of the 1980s. 5 digits and he'd have beaten the 16-bit PDP11, ST, Amiga and 8086 for per-instruction computing power. If he'd only aimed a little lower, he could almost have built the thing in his own workshop (his son constructed a three-digit Difference Engine from parts found in his house after his death!), instead of spending half his time arguing with his fabrication engineers and begging parliament and the Royal Society for ever-increasing sums of money. What a waste. But still - a genius of the finest calibre. My theory is, Babbage was actually given a Speak-and-Spell by Dr. Who. Or maybe Sarah Connors. It's the only rational explanation.

I heard an eye-opening rant by Chris Hecker the other day. No, not //that// rant - I already knew the Wii was one and a half GameCubes stuck together with duct tape. No, the one about bitangents. "The what?" I hear you ask. "You mean binormals?" As it turns out - no. The rule about what "bi" means is that some objects have an arbitrary set of properties, and you need two of them. It doesn't matter which two - you just need them to be two different examples. So a curve in 3D space has not just one normal, but loads of normals - a whole plane of them in fact. But you only need two of them - pretty much any two. You call one the "normal" and you call the other the "binormal". The standard classical-language hijack of "biX" just means "two X" or "the second X". And that's where binormal comes from - curves. Note that a curve only has a single tangent vector (well, OK, it has two, but one is the negative of the other). OK, so now on surfaces, you have a single normal. There really is only one normal. But there's loads of tangents - an entire plane of them - the plane of the surface. And so you need to pick two of them (typically if the surface is textured we're concerned with the lines of constant V and the lines of constant U). So one is called the tangent, and logically the other one should be called the "bitangent". Yes, you heard me - not "binormal". And that's the rant. When doing bumpmapping on a surface, you should talk about the normal, tangent and //bitangent//. Nobody's quite sure why people cottoned on to the word "binormal", and I've certainly spent the last ten years talking about binormals, but you know what - it's still wrong. From now on, I will speak only of bitangents (though that's going to cause chaos with Granny3D's nice backwards-compatible file format). Here endeth the lesson.

The game of the film, made by [[MuckyFoot]]. Except it had almost nothing to do with the film because we were making it at the same time as the film, didn't know much about their plot, so we just used the same characters in a different story. It had some neat features. The 360-degree fighting was kinda nifty - it used dual-stick "Robotron melee" controls - left one moved Blade, right one would attack in the direction pushed, and the exact attacks used were all down to timing and which weapon you had out. It came out on Xbox and ~PS2, and I wrote the Xbox rendering engine and all the other platform-specific stuff (sound, controllers, save/load, etc). From the start we decided the two platforms were too different to share much code, and we were mostly proved right, though in the end we did share more than we thought - mainly the streaming code and some of the lighting stuff. Originally the ~PS2 wasn't going to try to stream data, because we assumed the DVD seek times would kill us, but it worked much better than we thought, and the extra memory really helped. I'm fairly proud of the graphics engine - got a lot of good tech in it such as streaming almost all rendering resources, some neat code to deal with multiple dynamic light sources, compile-on-demand shaders, and some really good VIPM stuff. Other Xbox-only features were some nice self-shadowing with my first experiments with shadowbuffers, a cool-looking cloth simulation for Blade's cloak. Incidentally, the lighting was a huge pain. You see, Blade is this black guy who wears black leather and black shades, and he hunts vampires, so we're not going to have any bright sunlit levels - we're pretty much always in sewers at night. Result - he's basically invisible. It's fine to show him as a lurking shadow for a film, but in a game you kinda have to be able to see what's going on. Pretty much the only reason you could see him at all was because we cranked up the specular highlights like crazy, and made everything else in the scene fairly bright colours, so at least he's silhouetted. Despite being happy with it on a technical level, it was still a rather rushed game, and had some pretty rough edges. Some of the levels were rather dull - it would have been better if it had been a shorter game, but back then it wasn't acceptable to ship anything less than 20 hours of play, even if a lot of that play was a bit dull. C'est la vie.

If you're going to add this blog to your blogroll, and thanks very much for doing so, please use http://www.eelpi.gotdns.org/blog.wiki.html, and not the address you actually see in your browser - that one will change if/when I move ~ISPs. Thanks.

Pascal Sahuc emailed me a link to a neat paper on cloud simulation with a cheap CA. [["A Simple, Efficient Method for Realistic Animation of Clouds"|http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.1.4850]] by Dobashi and Kaneda. In fact it's absurdly cheap - each cell has only three bits, and it's all boolean tests. I'm amazed that such wonderful results come out of such simple rules and three bits of state. They do smooth the field before rendering, but it still [[looks really good|http://video.google.com/videoplay?docid=3133893853954925559]].

Another article got converted to HTML, and some hindsights. I wish I'd found a fun game to put the code in - it seemed to work really well, but I couldn't think of anything really cool to do with it. [[Papers and articles section|http://www.eelpi.gotdns.org/papers/papers.html]]

My hobby game [[Dwarf Minecart Tycoon]].

I went over some of the fundamentals behind the Data Oriented Design movement in [[Moore's Law vs Duck Typing]]. I'm not going to actually cover what DOD is because I honestly don't (yet) know, and I'm not sure even the main proponents do either. We understand the problem, and we have some examples of solving specific cases, but I'm not sure there's yet a good framework of rules or (wouldn't it be nice) set of libraries to make sure you don't have the problem in the first place while also keeping code readable and flexible. I've also not been paying //that// much attention since I'm no longer a full-time games coder - although I still write plenty of code, the complex stuff doesn't have to be super fast, and the stuff that has to be fast isn't very complex. So I'll leave it to others to explain DOD since I'll just screw it up. But what I do want to make is a meta-comment. The DOD folk are widely seen as a bunch of ninja curmudgeon bit-heads. Although I think they'd probably be quite proud of that label, the image it conveys is of folks who can hand-tune any assembly routine known to man but loathe anything higher-level than C99. They can argue about set associativity, DTLB walking and tell you how many clock cycles it is to main memory. Which is all very clever, but if //you// don't know that stuff they think you're Not A Well Rounded Programmer, and if you use the word "virtual" they'll commence much wailing and gnashing of teeth. In the other corner we have hipsters coming out of university courses with heads full of Java and Python and looking blankly at you when you talk about bitfield manipulation and the justifiable use of "goto". When you say "compile" they think you mean "tokenize", and they regard exception-handling as part of standard control flow rather than an admission of failure in code design. So unfortunately, the DOD message gets conflated with the other two big language flame-wars that have been going on for a while. So let me clearly enumerate them all: 1. Object Oriented Programming is not the answer to everything. 2. C++ is a terrible implementation of an OOP language. 3. Using lots of indirections can trash your caches, destroy performance, and you'll never be able to find it again. .#3 is the big new DOD thing we're all ranting about. .#2 is really difficult to argue too hard against. There's so many examples of better languages out there, and so many examples of dumb bugs caused by C++ implementation decisions. And amusingly it's one thing the hipsters and the 8-bitters can completely agree on. But it's also difficult to do anything about it. It's a practical reality that nobody is going to switch to another language any time soon, and the current leading contenders (Java, Python) smack into problem #3 pretty hard. Of course we should all switch to LISP - let me know when that happens and I'll join you dancing around the bonfires of our editions of K&R, but until then I need it by my side to debug some muppet's lack of parentheses or to look up for the zillionth time how to declare a function returning a pointer to an array of const function pointers. I put bitching about C++ in the same bucket as complaining about the frailties of the human spine and why Macs only have one mouse button - there's nothing you can do about it, so just shut up and deal with it. .#1 is really the only interesting discussion. It's certainly not new and the DOD folk didn't start it, but for most games coders the DOD context may be the first place they've seen people being quite so brazenly ~OOP-phobic. Even then it's not //that// interesting a discussion, because the answer is clearly not "OOP has no uses", nor is it "OOP is the answer to everything", but somewhere in the middle, so it's the position of that line that matters. I happen to think that OOP is overused. In particular I think OOP is used when the thing you want is not //objects// but //abstractions//. Unfortunately the major way C++ knows how to do abstractions is with objects. Thus, any time you want an abstraction (e.g. a cache of previous results) the path you end up getting pushed down by C++ is OOP ("make an object that represents the cache, and now make it inherit from..." aaaarg''gghhh!''), and so what we have is a bunch of ~OOPy shitty unreadable code. But it's shitty because it's ~OOPy and it shouldn't be, not because OOP is inherently a bad design paradigm (when it's appropriate). The other thing I see is people thinking DOD and OOP are opposite ends of the spectrum. This is C++'s fault again, though to be fair a bunch of other ~OOPy languages screw it up as well. In C++ when you have an object (a real game object that is - like a tank or a person) with a bunch of member values such as (position, orientation, health, ammo), it puts all those values contiguous in memory. But DOD says that the rendering only cares about the first two items, so why are you polluting your caches with the other two when rendering? You should have two separate arrays (pos+orient) and (health+ammo) and have one object reference separate items in each array. That's actually totally fine by OOP - all it says is that you want to be able to type obj->pos and obj->ammo, you want to be able to call obj1->~ShootAt(obj2) and so on - it doesn't say anything at all about how the data structures should be laid out. So in theory DOD and OOP should be completely compatible - OOP is a design and syntax philosophy, while DOD cares about data layout and traversal order. An example of a language where these two concepts are kept separate are databases - how you access the data (i.e. views/queries) is decoupled from how the data is stored. Unfortunately, C++ makes it really difficult to separate data layout from syntax. I suspect you can do it with gratuitous overloading and/or templating, or you can force everything to use accessor functions, but then the maintainability of the code plummets rapidly. So yes, //in C++// DOD and OOP tend to tug in different directions. But again, that's just K&R&S kicking you in the nuts. You really should be used to it by now.

[[HelloThere]] [[VR optics and why IPD means too many things]] [[Why didn't Larrabee fail?]] [[The sRGB learning curve]] [[NaNs cause the craziest bugs]] [[Memory stacks and more resizable arrays]] [[Premultiplied alpha part 2]] [[Texture coordinate origin]] [[All blog entries]]

...in progress... FP precision problems between machines. Compiler optimizations. Changing "constants". Recording & holding RNGs Player input record (now need to append to a savegame?) and playback.

A way of compressing vertex data using the principles of displacement mapping, but without needing complex hardware support. The idea is to encode the vertex as three indices to other vertices, plus two barycentric coordinates, plus a displacement along the interpolated normal. This gives you a vertex that is about 8 bytes in size, which is far smaller than most representations, reducing memory footprint and bandwidth requirements. This stream can be easily decoded by ~VS1.1 shader hardware, which is now ubiquitous. For more details see: * Dean Calver's article in ~ShaderX2 "Using Vertex Shaders For Geometry Compression" [[(available for free now)|http://www.realtimerendering.com/blog/shaderx2-books-available-for-free-download/]] * [[My GDC2003 paper on Displacement Mapping|http://www.eelpi.gotdns.org/papers/papers.html]]

I originally wrote this as a response to [[a blog post by Eric Haines|http://www.realtimerendering.com/blog/60-hz-120-hz-240-hz/]], but it turned into a bit of an essay along the way. I thought I'd repost it here and also add some clarifications. There's two separate concepts that people frequently conflate - flicker fusion and motion fusion. They're sort-of similar, but they're absolutely not the same, and they occur at different frequencies. At time of writing, [[the Wikipedia article on flicker fusion|http://en.wikipedia.org/wiki/Flicker_fusion_threshold]] is a mess, constantly switching between the two without warning. It's also misleading - there are plenty of people that can see flicker well above 60Hz (and I am one of them), and the variance is large in humans. In this post I'll try my best to be clear - I'll use "Hz" when talking about flicker, and "fps" when talking about motion. Although this is something we study a huge amount in VR ~HMDs, I'm not going to say too much about them in this post, because any stuff I post about VR goes on the work blog site, not here! So most of this is centered around ~TVs, monitors and cinema. ''Flicker fusion'' Flicker fusion is simple - the lowest speed at which a flickering light stops flickering. It varies between about 40Hz and 90Hz for most people. There is also a distinction between conscious flicker and perceptible flicker. Using myself as an example, I cannot consciously see flicker above about 75Hz. However, if I look at a 75Hz flicker for more than about an hour, I'll get a headache - which is certainly "perceptible". The flicker needs to be above 85Hz to not hurt. This 10Hz gap is not uncommon, though it's largely driven by anecdotal evidence from ~CRTs, as setting people in front of flickering displays for hours on end is not something we do much any more. In my case, this is all experience gained from my youth in the early 90s. High-speed ~CRTs were expensive - but I finally found a nice second-hand iiyama monitor that would consistently give me 1600x1200 pixels of text and also run at more than 75Hz. We believe that a display running at 90Hz is "fast enough" to make everyone happy, though it's possible there's a few rare exceptions out there (and if you know you are one, email me - we'd love to use you as a guinea-pig!) People are significantly more sensitive to flicker in their peripheral vision than in the middle (also about 10Hz-15Hz difference). This may be why some people can tolerate 60Hz CRT ~TVs and monitors, but fewer can tolerate 60Hz flourescent lighting flicker. A lower duty cycle raises the threshold of flicker fusion. I don't have good data on this, but from memory going from 50% duty-cycle to 25% needs about another 10Hz to reach flicker fusion. But the curve on this is funky and non-linear (fairly obviously, 100% duty cycle = zero flicker at any frequency), so don't try to extrapolate too much - just know that duty cycle is important. ''Motion fusion'' Motion fusion is the rate at which successive images appear to start moving smoothly. Note that unlike flicker, "moving smoothly" is a continuum, and higher framerates absolutely do improve the sense of motion. For most people, smooth motion starts at around 20fps (which is why most film is still at 24fps), but it consciously increases in "quality" to 120fps and possibly beyond. ''Combining the two'' So how do these interact? Well, cinema typically has 24 frames per second, which is usually enough for motion, but typically has a 50% duty cycle, and so would flicker like crazy if simply displayed one frame every 24Hz. So cinemas flash each frame two (48Hz), three (72Hz) or four (96Hz) times to reduce the flicker. I don't have great data on this - so projectionists let me know if I'm wrong here - but I believe in the past most cinemas used 48Hz, but modern cinemas mostly use 72Hz, as 48Hz is too low for a "surround" experience - it causes too much flicker in most peoples peripheral vision. The choice of 50/60Hz for CRT ~TVs was driven by flicker fusion limits, and with no frame-storage ability in early ~TVs, they were forced to actually display that many frames. They have a lower duty cycle than cinema - usually around 25% (and it's an exponential drop-off rather than a square wave, so even that number is handy-wavy), which may explain why they needed a higher frequency than cinema. However they cheated with resolution and interlaced to get 30 frames per second. However, it's not a true 30fps in the cinema sense, because even with interlacing you can get 60 "motions" a second - though this does depend on the camera and the recording equipment. I'm not that well-versed in TV tech though - don't know how often you get 60fps of half-frame motion, and how often it gets squashed down to 30fps of full-frame motion. We know from video games that 60fps looks visibly better than 30fps for most people on fast-moving content. Whether they care enough is a different question, and one that continues to rage. For myself, I can easily see the difference, but one doesn't really look "better" than the other to me on a monitor. However, in a VR HMD it's a very different matter for a variety of reasons! ''What about 120 and 240?'' Many modern LCD ~TVs advertise that they have 120fps and 240fps modes, even with regular 60fps inputs. How do they do that, and why? 120fps is fairly obvious - it just looks smoother. Just like 60fps looks smoother than 30fps, 120fps looks smoother than 60fps for most people. It's a more subtle effect than 30fps->60fps, but it's certainly there - I see the difference mainly in smooth pans. Of course the TV has to get that extra frame data from somewhere, and they do it by extracting motion vectors between successive 60fps frames and then inventing new frames by tweening. This causes some odd artifacts sometimes, and although the algorithms are much better these days I still prefer to have them off and just watch 60fps data. The tweening also adds latency - fine for a film, bad for interactive content. OK, so what's the deal with "240fps"? Well, first up, it ain't 240fps - that's marketing bullshit. It's 120 frames of data, interleaved with 120 frames of black. Or, as an engineer might put it - 120fps with a 50% duty cycle on illumination. But that doesn't look as good on a billboard. LCD screens do this by turning the (usually LED) backlight off for those black frames, which also gives the LCD pixels a chance to switch states while they're not being illuminated. So why do this? Why turn the display off for half the time? Normally, LCD displays are full-persistence - the pixels are lit all the time by a backlight. They take a while to switch between colours, but they're always lit - they're always showing something. That means that in things like smooth pans, your eyes are following the pan across the screen, but the pixels are of course moving in discrete 120fps jumps, not continuously. This "smears" the image across your retina and results in blur. We get this really badly in VR - for more details see [[Michael Abrash's great post on the subject|http://blogs.valvesoftware.com/abrash/why-virtual-isnt-real-to-your-brain-judder/]] - but it also happens on ~TVs when your eyes are following moving objects. The solution is the same - low-persistence, otherwise known as "turning the pixels off between frames". If you turn the pixels off, they won't smear. So a 50% duty cycle is good for sharp images, so why hasn't this been done before on LCD screens? The problem is if you do a 50% duty cycle at 60Hz, it will cause flicker (at least with the widescreen TV monstrosities we have these days). That's why LCD ~TVs had to get to 120Hz before going low-persistence. And it really does look better for a lot of content - the edges get sharper even though you can sometimes lose some brightness. But this prompts a question - why not just show 60fps data at 120Hz with low persistence? Just show each frame twice, like cinema does. Why do you need the motion-interpolation tech? Well, coz otherwise the pixels don't smear, they double-image. Think of the same smearing effect, but with the middle of the smear missing - just the two ends. So now any time something moves, you get a double image. This is a very visible effect - even people who are perfectly happy with 30fps rendering and can't see flicker over 50Hz can still see this double-edge effect at 120fps low-persistence! Cinema works around this by adding masses of blur - gigantic gobs of it any time anything moves. But existing TV content isn't authored with this much motion-blur, so it would double-image. And that's why the tweening is generally forced on if you go 120Hz low-persistence. (it's an interesting historical question why ~CRTs - which were inherently low-persistence, with about a 25% duty cycle depending on the phosphors - why did they not look terrible? My theory is that we just didn't know any better - the competition was 24fps/48Hz cinema, and that sucked even more!)

If you're going to release a demo, try and minimally playtest it first on some people who (a) have not already played your game and (b) have $50 they can spend on anything they like. If for some bizarre reason they fail to immediately hand over the $50 in exchange for a full copy of the game, you might want to think about tweaking your demo. Here's the checklist. It's not exactly rocket-science, but it's truly astounding how many manage to violate not one point on it, but every single one. It's even more astounding how random downloads from thid- and fourth-tier publishers on Fileplanet or whereever manage to consistently score several bazillion points above the first-tier publishers parading their stupidity on the heavily-controlled and scruitinised Xbox Live. Maybe that's because those lowlier publishers have to work for their money - who knows? (1) To paraphrase Miyamoto - a late demo can eventually be good, while a rushed demo is bad forever. To put it another way - the demo isn't for the fanbois who read the gaming press and would buy a turd-in-a-box from comapny X. The demo is for the non-hardcore looking for something new. If you release the demo early and it sucks, you will turn away everyone, including the fanbois. If you ship it after the game goes to master and make sure it's not horrible, it will have the most glaring bugs fixed, be more balanced, and you might pull in some longer-term interest and keep yourself from being hurled into the bargain-bin two weeks after release. (2) If at all possible, include the tutorial. I know you think your precious snowflake is so intuitive it's just pick-up-and-play. But again remember - your demo is NOT for the fanboy who bought the first eight episodes of your game series. It's to find the people who don't have preorders. They may not know how to play your game. They may have never played a game like yours. They may have never played any game. That is probably why they have a surplus of $50 bills. One of them could be yours. (3) If you really can't be bothered with a tutorial, at least have some help screens that tell people what the buttons on the controller do. Maybe even what the strange bars on the screen do, or what the icons on the mini-map do, and what to do about each of them. Especially when they flash - flashing says "I'm important". Not explaing what important stuff is shows disdain for the player. And don't make those screens be the loading screens because guess what - they vanish while the player is reading them. Nothing shows a new player the middle finger quite so directly as a screen full of important text that you then don't let them read properly. They haven't even pressed a button and already they hate you! (4) Make the demo nice and easy. Demos are not there to present a challenge to the player, they're there to demonstrate the full set of features to them. So for example in a certain fighting game renowed for its boob physics, you might want to slow everything down a bit and make the computer opponents not quite so ... well ... ninja. Then the player will actually be able to experiment with all the cool throws you spent so long doing the game code and animation for, instead of being mid-air juggled for 75% of the health bar the instant they do anything but madly bash the uppercut button. (5) What is your Unique Selling Point? Why is your game teh ace and all others teh suk? After all, that is why you spent 500 man-years on this product, and that is why your publisher is beating you over the head about deadlines. I may be talking crazy here, but I'm thinking you may wish to explain it to the player. If you don't, the player will be looking at your product and thinking deep philosophical questions such as "why would I spend $50 on this?" You do not want them thinking those sort of questions - you want them thinking "wow - I'm glad I spent $50 on this brilliant game." If you can't manage that, at least go for "shame I spent $50 on this game - the USP sounded cool but it wasn't that much fun after level 8". Your bank manger is equally happy with either. This is your first contact with a large chunk of your potential audience. They have $50, and they are deciding whether to give it to you, so you can feed your wife/husband/kids/cat/llama/habit. Marketing has done its job, and the punter is finally devoting their full and undivided attention to your game and playing your demo. Now it's all up to you - this is your fifteen minutes of fame. If that person doesn't like your demo, it doesn't matter how hard you crunched to get the game out the door.

As a side hobby from the SuperSecretProject, I've been tinkering with writing a game. When I was writing games professionally I really didn't feel like doing more games at home, but now it's a refreshing change from designing instruction sets. However, the question was - what game to do? I didn't want to try to think up something new (dammit Jim, I'm a programmer not a game designer!), so I just blatantly stole concepts from two of my favourite games - [[Dwarf Fortress|http://www.bay12games.com/dwarves/]] and [[Transport Tycoon|http://en.wikipedia.org/wiki/Transport_Tycoon]]. I like them for very similar reasons - you set up a system, and little autonomous agents run around in that system. That sort of indirect influence is really appealing to me as a programmer as well as a game-player. So starting with the high-level concept of "Dwarf Fortress with trains", it could go pretty much any place really. The point of this is to do things I've not really done before, such as writing map structures, managing inventory, path-finding, simple UI, load/save. Whereas I have already done tons of graphics and sound stuff, so for this project I literally don't care about graphics. I literally have a bunch of teapots running around in a gouraud-shaded fixed-function-vertex-shader environment. I'm just using the ~D3DXCreate* functions and abusing my poor graphics card with the number of draw calls, and I refuse to care! This is very much in the spirit of Dwarf Fortress, which uses a full ~OpenGL pipeline to emulate a 16-colour ASCII terminal - though I do at least have a proper 3D camera for the sake of playability. Much as I love DF, the 2D-only interface is a huge barrier to gameplay. I have no pretensions to ever ship the game - it may not even ever be fun to play (since my goal is far more that it should be fun to program!). It's certainly not playable now. But as a programmer there's lots of interesting little things that have kept me intrigued that have never really come up in my life as a graphics coder before. So I thought I'd write about some of them.

''[Edit - this was all good info at the time, but now everything Just Works so most of this post is obsolete. But I don't like to remove stuff from the web, so it remains here for posterity.]'' I've been waiting for this a long time. Elite on the BBC Model B (at school) and the Speccy (my home machine) was the game that made me sit up and realise that 3D rendering was a thing, and it was awesome, and I had to figure it out. I also rapidly discovered that it was a thing that is very difficult, but it inspired me to keep pushing my coding knowledge from BASIC to FORTH to assembly and learning all sorts of tricks. It was only years later on the Atari ST that I felt I actually knew what I was doing and was finally a competent graphics coder, and that moment came when I had a Viper rotating on my screen as fast as the ST version of Elite. It was only much later when I went back and learned some of the details of the 8-bit versions that I realized just how many tricks had had to be played, and why the Amiga/ST versions were comparatively straightforward by comparison. Later at university I met David Braben a few times, and despite my rampant fanboyism, he helped me get my start into the industry. And I've always been a graphics programmer at heart through my various jobs, and on almost every project I have ever worked on, the very first thing I get running is a rotating Viper - I can type the coordinates and faces in from memory (which isn't actually that difficult, but it's a neat party trick). And now I find myself at Oculus working on VR. And lo - the streams have crossed, and two awesome things are coming together very nicely. The ~DK2 version of Elite is still a work in progress, but it's already mighty impressive. I thought I'd write a guide to getting it working. I did this on my "virgin" home machine rather than my work one, using only the public resources, so hopefully you should not have have too many surprises replicating it. These instructions are for ~DK2 on a Win7 machine - I haven't tried Elite on ~DK1, or on any other versions of Windows yet. * I recommend a reasonably fast desktop machine for VR. In general, very few laptops give a good VR experience. I have a machine with a ~GeForce 670 and a machine with a Radeon 7870 - neither are bleeding edge, but both work very well. * Install the latest public Rift runtime or SDK. At the time of writing this is SDK v0.4.4, display driver v1.2.2.0, camera driver v0.0.1.7, but later versions should also work. * A common mistake is to forget to plug in the sync cable between the camera and the junction box on the HMD's cable. The junction box end can be a little stiff at first, so make sure it's pushed all the way in. * Also remember to remove the sticky plastic shipping cover on the camera's lens. In a stroke of genius on our part, it's transparent to visible light which makes it easy to miss, but completely opaque to IR. Do NOT remove the silver-coloured cover - that is meant to be there (it reflects visible light, but it's transparent to IR). * Make sure the Rift is turned on. The button on the top right is the power button - press it so the light is yellow or blue (not off). Be careful when putting the Rift on - it's easy to press this button again and turn the Rift off just as you put it on your head. I do this at least once a week. * If all is ready, the light on the Rift should be blue, and the light on the camera should be blue, and both serial numbers should be displayed in the Oculus Config Util. If not, check your cables! * Open the Oculus Configuration Utility, set up a user profile, enter your details, and calibrate it to your head shape using the "Advanced..." button. It is important you follow the instructions about the side adjustment dials correctly - set them all the way out while actually doing the calibration, and then set them back to where they are comfortable, and set the slider in the Config Util to match the dial setting you chose (note the picture in the Config Util is of the dial on the right side of the HMD). * Check everything is working by clicking "Show Demo Scene" in the Oculus Config Util. It should track your head rotation and translation smoothly, and the desk and objects on it should seem to be a realistic size. OK, now you have the Rift set up in the default "Direct" mode. However, at the time of writing Elite is still using the older "Extended" mode like a lot of other apps, which can be a little fiddly to set up. The Elite chaps say they're working on the Direct-mode support, but right now it's experimental, and I haven't tried it yet. * In the Oculus Config Util, in the Tools menu, select Rift Display Mode and select "Extend Desktop to the HMD" and hit Accept. This will make the Rift show up as a monitor in Windows. * Make sure the Rift is turned on (blue light) when doing this next bit and hasn't gone to sleep. * Right-click on your desktop, select Screen Resolution, and you should see at least two monitors are connected, one of which will be a monitor called "Rift ~DK2" * This will be a monitor that is 1080x1920 in size, and the orientation will say "Landscape" even though it's clearly taller than it is wide. This is normal. * Change the orientation to "Portrait" (not "Portrait (Flipped)"), which confusingly will change it to a 1920x1080 monitor. All apps use it in this mode, not just Elite - you'll only need to do this once. * Make the "Multiple Displays" setting say "Extend these displays" (this is why we call this "Extended" mode - because you're extending your desktop onto the Rift. Don't try to actually use it as a desktop though!) * Don't worry if the Rift shows up as monitor 1 or monitor 2 - either is fine. Your Windows desktop will still be on your primary monitor either way. * Do NOT click "Make this my main display" for the Rift ~DK2 monitor otherwise all your icons and start bars will move to the Rift in horrible ways. Seriously, don't try this. * Re-run the Oculus Config Util demo scene (the desk with the cards on it) - it should work correctly in Extended mode the way it in Direct. Now the Rift is set up for Extended mode, which is a handy thing to know as lots of apps still use it. You can flip it back to Direct mode by using the Oculus Config Util app as before. Now let's get Elite working. * Install and start Elite. * On the main menu, select Options, then Graphics. * Scroll down to the "Quality" section and put "Preset" to "Low". You can fiddle with the various settings later, but Elite looks gorgeous even in low, and it will give you the best possible VR experience. Remember - in VR, framerate is king. The most gorgeous shaders in the world are no good if it's not making framerate. On my machines framerate still drops below 75fps inside the really pretty spaceports (you will see this as a double-image "judder"), but during combat where it matters it's mostly smooth as silk. * Hit "Apply". Coz this is the tricky bit. * Go into Options, Graphics again. * Find the heading called "3D" and select one of the "Oculus Rift" modes. I highly recommend using headphones rather than speakers for the full awesomeness. * Do NOT hit apply yet (if you do, make sure the HMD is sitting horizontal, e.g. put it on your lap, or you won't be able to see anything!) * Now go to the heading called "Monitor" (3rd from top) and select the other one - usually called "Secondary". If you have more than two options, I'm not sure what to pick, sorry. * If you did it right, the "Fullscreen", "Refresh Rate", "Vertical Sync" and "Frame Rate Limit" lines should be redded out, and the resolution should be 1920x1080. This means Elite correctly detected the Rift as being a special display. * OK, now read the next few lines of directions before hitting "Apply". * The screen will go black - quickly put on the Rift! * Waggle the mouse until you get a cursor. You may need to waggle it a long way left or right to get it to appear. * It is asking you "are you sure you want to keep these changes", click "yes". * If you don't do it in ten seconds, which is a surprisingly short time if you're not expecting it, it will drop back to the normal monitor and you have to do it all again. * OK, you're wearing the Rift, and hopefully you see a menu screen in the top left of your view! Yes, it's difficult to read. Welcome to experimental software, test pilot! * Now play the game. * It at any time you want to switch back to the desktop, remember to select "3D" to "Off" AND "Monitor" to "Primary" both together before hitting "Accept", otherwise things get difficult. If you do cock things up - don't panic, just wait 10 seconds, it will revert to previous settings, and you can try again. * At any time you can press F12 to reset the Rift orientation - this includes in menu screens. Very useful if you switched to the Rift when it was pointing in a strange direction. Some things to help quality of life with a Rift in Elite: * If like me you're playing with a mouse (my ~X52Pro is on backorder), I would remap some keys: ** "Set speed to 50%" to "C" (and remember "X" is 0% by default) ** "Cycle next fire group" to "Caps Lock" ** "UI Back" to "Left Shift" ** Remember that most keyboards have a knobble or blob on the F and J keys, so whenever you need keys on that row like "G"="Next Target" or "J"="Jump", they're pretty easy to find. ** Most other functions are non-time-critical (landing gear, cargo scoops, etc) and so can be accessed by going through the right-hand panel. * The default colour of the HUD is quite reddish. The ~DK2 gives optimal resolution in colours with more green or white in them. Elite has some limited control over the colour palette. If you find the file {{{GraphicsConfiguration.xml}}} (in a folder such as {{{C:\Users\YourUserName\AppData\Local\Frontier_Developments\Products\FORC-FDEV-D-1003\}}}) and open it in a text editor, you can tweak it a bit. A really handy interactive page for choosing your own set is at [[Elite: Dangerous HUD colour theme editor|http://arkku.com/elite/hud_editor/]] and they have more instructions. However, many of the possible colour choices leave you with problems such as: ** Can't tell in-station menus items that are redded out from ones that are not. ** Can't tell red, blue and yellow dots on the ~Friend-or-Foe tracker. * My own colour palette is a fairly modest change, but it does turn the text a bit more yellow (i.e. it adds some green), which helps readability without breaking those other things too much: {{{ <GUIColour> <Default> <LocalisationName>Standard</LocalisationName> <MatrixRed> 1, 0.4, 0 </MatrixRed> <MatrixGreen> 0, 1, 0.4 </MatrixGreen> <MatrixBlue> 0, 0, 1 </MatrixBlue> </Default> }}} Elite is already an amazing experience in the Rift, if a little klunky at times. I'm sure with some tweaking it will become even more amazing. Happy flying, remember to look up, and see you out there. Regards, CMDR FOURSYTH

With the usual anti-bot obfuscations, my address is: tom ~~dot~~ forsyth ~~at~~ eelpi ~~dot~~ gotdns ~~dot~~ org.

Bonus karma points to Ben Garney of Garage Games who spotted a silly math error of mine in [[Knowing which mipmap levels are needed]]. Now corrected.

In 2006 when starting this blog, I wrote a moan about double precision and why storing absolute time and position should be done with fixed point instead. Re-reading it, there were a bunch of shorthands and bits I skipped, and it was unstructured and hard to read - like most rants. Also, it talked about the ~PS2 and early ~DX9-class ~GPUs, and nobody really cares about them any more. And somehow I managed to only talk about positions, and completely forgot about time. And the typos - so many typos! So I thought it could do with a cleanup, and here it is: [[A matter of precision]]

Lots of fun. Slightly quieter than last year, but according to many it was because companies are only sending the key people, rather than the massed hordes. Also seemed like a lot fewer of the random mousemat manufacturers, DVD duplicators and the like. Michael Abrash and I gave our talks. He almost filled his gigantic 1000-person room, and my little 300-person room was totally full - not even standing room available. I made sure I left 10 minutes at the end of my talk for questions, but we ended up with half an hour of questions and they had to kick us out of the room for the next session. So I call that a success. A general site for all your Larrabee needs is: http://www.intel.com/software/larrabee/ Our slides are available here (scroll down near the bottom): http://intel.com/software/gdc Michael Abrash's article in Dr. Dobbs Journal is now live: http://www.ddj.com/architect/216402188 The "C++ Larrabee Prototype Primitives" available from here: http://software.intel.com/en-us/articles/prototype-primitives-guide/ These allow you to write Larrabee intrinsics code, but then compile and run it on pretty much anything just by adding a #include into the file. The intent was to make it as easy as possible to prototype some code in any existing project without changing the build. I went to see [[Rune|http://runevision.com/blog/]]'s talk on locomotion (see [[How to walk better]]), and it was really superb. Great tech, great (interactive!) slides, and he's a really good presenter. If you've read his stuff before, go see it again as there's a bunch of stuff I hadn't seen before - tricks like how to stop the ankle flexing bizarrely as people step down from high places.

I was asked recently what the best way to approach [[http://www.gdconf.com/|GDC]] was for the newbie. GDC is a big busy place, and it's easy for people to get a bit lost. Here's a few handy hints: * Take an hour beforehand to sit down and go through the entire timetable. In each timeslot, mark the top three things you'd like to see, and give them a score from "might be interesting" to "must see". Remember to at least look at the tracks that aren't your main discipline - they sometimes have interesting or crossover stuff. Write these scores down, and when you actually get to GDC, transfer them onto the at-a-glance schedule thingie you get in the welcome pack, then you can refer to it quickly during the day. * Prioritise sessions you don't know much about but sound interesting over things that are right in the middle of your primary field. For example, I'm a graphics programmer who's already worked a lot with DX10, so there's probably not a great deal of point going to a talk called "D3D10 Unleashed: New Features and Effects" - it's not going to teach me much new stuff. But I've not all that done much general-purpose multi-processor work, so the talk called "Dragged Kicking and Screaming: Source Multicore" sounds fascinating and will probably give me some new insight when I do start doing multi-processor work. * Be prepared to miss a lot of the lectures - GDC is pretty chaotic. Allow it to be chaotic - don't try to control it too much. If you're talking to someone interesting, and they're not rushing off to something, keep talking to them. You can always go into the lecture for the second half, or at worst you can pick up the lecture notes later. But you might never meet that interesting person again. * Don't spend too long on familiar stuff. GDC's meant to be about new stuff, so don't just hang out at a bar and gossip with your friends all day. Hang out at a bar and gossip with //new// people instead. * Don't spend too long in the expo. Have a quick walk around fairly early on and check the place out, see what might be interesting, but don't hang around or play with stuff. There's two halls this year, and with E3 gone it's even bigger and probably noisier than previous GDCs. If you do find something interesting, note it down for later so when you do find yourself with a spare half hour, or during lunch, you can go back and have a better look. Similarly, if the expo is crowded, go do something else. It's probably lunch-time or something. Come back in an hour and it will be quieter. The booths and the people on them will still be there, and you'll actually be able to see something and talk without shouting. Also don't do the expo on the first day or the last day - that's what everyone else does. * Remember that there's two expo halls this year. * If after five minutes of a lecture you find the lecturer is dull, or presents badly, or is just reading off the slides, leave. It's obvious you're going to get just as much from reading the slides later as you will from seeing the talk in person, and it'll be quicker. Your time is valuable - go to the next-best-rated lecture on your list. Some lectures are 10x better in person - those are the ones you should be watching. If you feel too embarrassed to just walk out, take your phone out as if you had it on vibrate and just got a call or a text message, and walk out glaring at it. * During the lectures, have a notepad and pen out. When you have a question, scribble it down. At the end of the lecture, the presenter will ask for questions, and there's always a deafening silence for a few minutes while everyone remembers what their questions were. That's when you can stick your hand up or go to the microphone and ask your question. * Fill in those feedback forms. The GDC committee do collate them and do take them pretty seriously when considering who to invite back to speak next year. The authors do also get the feedback and some of the comments, so if they have good info but are a terrible speaker, say so. And use the whole scale. I forget what it's out of, but if it's 1-10, 1 = bad, 5 = good, 10 = excellent. No point in messing around with 6, 7, 8 as scores - your voice will be lost in the statistical noise. * Everyone always asks me about the parties and which ones to go to. I'm not a party animal, so I don't enjoy them for what they are. And as far as socialising, they're terrible. Talking is almost impossible and unless you're very wealthy or persistent, you'll be hungry and thirsty. Much better to hang out in a hotel bar or lobby with some friends. You'll still see plenty of game geeks doing the same, but you'll be able to talk and eat. And it's far more relaxing, which means you can gossip til the early hours and still be reasonably awake for the first lecture next day. * Don't worry if you think you're missing all the cool stuff. Everybody always misses all the cool stuff. This year they're in SF rather than San Jose, so nobody knows where anything is, so even old pros will be confused. * Go to the Indie Game Festival if you can. Definitely visit the IGF pavillion to check out the games and chat to the developers. The standard is awesomely high every year. * Play the meatspace MMO game - this year it's "Gangs of GDC". Doesn't usually take up a significant amount of time. It's a good excuse to be silly and talk to people. * The Programmers Challenge is back! Always amusing for the uber-geek. * The Developer's Choice Awards are worthwhile and not as bogus as most of the other awards. Go to them and cheer for people that don't suck.

''WORK IN PROGRESS'' - which is why it's not on the main page yet. A topic guaranteed to cause an argument amongst the shipping veterans is where you should do editing of levels, scripts, shaders, etc. There's three obvious options, although different aspects may use different ones, e.g. shader editing may be done in one place while level editing done in another: -A plugin for your DCC tool of choice (Max, Maya, XSI, etc) -A standalone editor. -A part of your game. The second two are obviously close - the difference being whether you have to do a save/convert/reload cycle every time you want to test something in the actual game. For some console developers, this is a more obvious distinction as it means they don't have to make a PC version of their game simply to test & edit it. To simplify the argument, I'm going to lump the second two together and say there's two choices - embedded in your DCC tool, or as a fully-custom editor that shares as much as possible with your game engine. The advantages of making your game be the editor are obvious. You get to see things as they really are, almost instantly. You're using the real rendering engine, you're using the real asset-management system, and you're using the real physics engine. If some cunning design or model won't work inside your engine, you'll know about it immediately, not three months later when you've already authored a bunch of content. Your artists and designers can experiment however they like, because they see the results immediately and know if they look good or play well. The biggest advantage, if you make it right, is that level designers can set up objects and scripts, hit a button, and they're instantly playing the game. Keeping that design/test/tweak iteration cycle as fast and tight as possible is the key to excellent gameplay. The same is true of lighting (whether realtime or lightmap-driven) and sound environments - both of which rely on having large chunks of the environment around to see whether they work or not, and are almost impossible to do in small unconnected pieces, or without very fast previews. The disadvantages are that it's more complex to make an engine that can run in two different modes - editing, and playing. The editing mode will be running on a powerful PC, often with unoptimised assets (optimising takes time and leads to longer turnaround cycles - you don't want that). The argument for putting the editing tools inside the DCC tool are obvious - your artists already know how to use the tool, and it's a bunch of editing & rendering code that's already been written. Why reinvent the wheel? Ordinarily I'd agree - wheel reinvention is a plague, and burns far too much programmer time in our industry. But hang on a bit - is that really true? Fundamentally, there's a few big problems we have to deal with: *Previewing assets in the actual game environment. That means shaders, textures, lighting models, shadows, lightmaps. If the artists can't see all that as a fast preview while they're building the model, they're going to be doing a lot of guesswork. *Level design. Placeholder artwork, hacked-in control schemes, pre-scripted actor movement - doesn't matter - you need to give the designers tools to work with so they can start getting the broad-strokes design stuff up and running so that everyone can get a feel for what the game is going to be about. *Sound & animation design. Seems odd to put these two together? Not really. Both have a time component to them, and they need smooth blending. This makes them fundamentally different things to rendering and lighting. But you still need to be able to easily preview them in the real game. Also, animations frequently have sound triggers on them - footsteps, equipment sounds, etc. For bonus annoyance, typically the animator and the sound guy aren't the same person, don't know how to use each other's tools, and will want to edit the files independently. *Keep iteration times down. And by "down" I mean less than 15 seconds from tweaking a model/texture/light/object placement/trigger/script to trying it out in the game. We all know that iteration and evolution is at the heart of a good game, so we need to keep the dead time in that iteration loop to the lowest possible. My preferences: Make your engine able to reload assets at the press of a button. Having to shut it down and start it up wastes time, especially as those are the areas you tend to optimise last in a game. You need your artists to be able to edit something in the DCC tool, hit a button, and have the results visible right then. This requires a decent amount of infrastructure, though a lot of that is shared with things like streaming systems (which are really good things to have), and stuff like dealing with Alt+Tab on ~PCs. Even if all you can do is reload existing assets, that's a big time-saver. If you can further and import new models with new texture names, etc. that's even better. Make sure your engine can read assets directly from the exported data, or do so with minimal and fully-automated processing. It doesn't have to render them quickly, and you obviously need another optimised format that you will actually ship data in, but you also need something with a very quick turnaround time. It doesn't matter if the model the artists is currently editing is loading all its textures from raw ~TGAs - we all have big video cards these days. Once they're happy with the textures, a batch script or tool can compress them down to your preferred format. This can either be done overnight, or on another preview button so the artist can see what the compressed version actually looks like. Ditto with things like vertex cache reordering and optimal animation-bone partitioning - none of that stuff matters while the artist is actually editing the model - do it in a batch process overnight. One of the really nice things about Granny3D that we've focussed on a fair bit over the years is the forward and backward compatibility of the file format - you can store all sorts of data in a .~GR2 file, both raw and compressed, and they should all be loadable by anything at any time. One subtlety here is that a processor should never modify original data. The stuff that comes of out the DCC tool should be minimally processed during the export process - convert it to a standard format, but leave as much data in there as you can. Later processing steps can strip that data out, but they will do so with a different file as a target, not an in-place modification. That way when the optimised format changes, you don't need to fire up the DCC tool and do a while bunch of re-exporting - you can just run a batch file on all the raw exported data and have it in the new and improved format. The level & lighting editor should be the game. Using Max/Maya/XSI/Lightwave as a level editor never works well. I've tried it both ways, and I've discussed this with others. Think about it - all you're getting out of your DCC tool is a camera movement model (easily replicated), a bad renderer (you already have a good renderer), some raycast mouse-hit checking (every game has these already) and a bad button UI that I guarantee you will annoy the snot out of you when you actually go to use it. Trying to use the DCC tool's interface to do any serious previewing is horrible - just think about trying to implement some sort of shadowbuffer rendering, or implementing the movement logic of the character inside inside a DCC tool - it's pretty absurd. This is not reinventing the wheel - there's just so little of a DCC tool you actually need or want in something of the scope of a level editor. The animation & sound editor should absolutely be the game. There's just no doubt here - DCC tools don't help at all. Because you need to be able to see the blending and transitions between different animations, and the 3D sound environment as it really will be, a DCC tool doesn't bring anything to the table. The way I've seen animation editors done really well in the past is that the game is playable (ideally with control over any character) and the last thirty seconds are continuously recorded. At any time the animator/sound guy can pause and scrub through that time window, tweaking blends and when sound events happen. So that's my rant - the smartest coders should be tools coders, and they need to write level editors and makefile-driven processing chains. DCC tools are for Digital Content Creation on a micro scale - individual characters, individual animation sets. They're not for entire levels, and they're really bad at previewing.

This is pretty handy - [[GameMiddleware|http://www.gamemiddleware.org/middleware/]] - a website that is just a big list of games middleware. I'm so tired of people reinventing perfectly good wheels. Unless your game is going to focus on having the best system X in the world, why not go and look if someone's already got a perfectly good X you can just buy? Then you can spend your time solving some more interesting problems. Also tinkered with the titles. Not much point having the titles just be the date when the date's written just below them. And the RSS looks more sensible that way.

Granny3D is a big bag of goodness from [[RadGameTools]]. It's an exporter of all sorts of data from Max, Maya and XSI, it's an asset pipeline manipulation and conversion tool, it's a normal-map generator, it's a really cool file system that copes with endianness, 32 or 64 bit pointers, and versioning, it ships on 11 different platforms, and above all it's the world's most superlative runtime animation system. Granny was written by [[Casey Muratori|http://www.mollyrocket.com/]] originally, handed over to me for two exciting years, and then taken over by [[Dave Moore|http://onepartcode.com/]]. Even though I haven't worked on Granny in a while, I still pimp it like crazy to anyone within earshot. Seriously - it's a bunch of really cool tech, a bunch of rather tedious tech, a bunch of gnarly problems solved by the brightest minds in the business (and me), and it's all wrapped up into a lovely little bundle that if you were to replicate yourself would make you officially insane. Pay the money and get on with something more interesting! When I think of all the man-years it would have saved me when working at MuckyFoot, ooh it makes me mad. As Dave said once "we can't replace your existing animation coder, but we can paint a [[big red S|http://en.wikipedia.org/wiki/Superman]] on his chest". As time goes on, Granny becomes more and more about the entire toolchain - taking your mesh, texture, tangent space, animation and annotation data from the various DCC tools, exporting it in a reliable robust cross-platform format, processing that data in a large variety of ways, and then finally delivering the data in optimised form to your game engine. This is an under-appreciated area of games programming. It's not viewed as a sexy job for coders, and it tends to be done hastily, often by junior programmers. As a result, it is usually a source of much pain, not least by the artists and designers who have to use it. Don't let this happen to you - start your toolchain on a solid foundation.

Hello and welcome to my blog. Always fresh, always technobabble. Read the chronological blog that is usually listed below, or use some of the links to the left. Or EmailMe. Although this is technically a wiki, you'll just be editing your own personal copy, not the public one.

I have just finished a round of interviewing with various companies, and for the most part it was a pretty positive experience. However, last time I did this in 2004, it was not so pleasant, and I wrote up a bunch of moans for my dev friends, and we had a good natter and a laugh about them. It may have have been nine years ago, but they're all still very relevant, and if you interview people at your company, it would be worth a look. So here's the list: Interviews go two ways. In many cases, I'm interviewing you more than you're interviewing me. The quality and pertinence of questions you ask reflects very strongly on you and your company. This is sort of the "meta message" to apply to all the following. Simply asking "any questions for me" at the end of the interview does not cover your arse. There's a big difference between interviewing a newbie out of college and an experienced veteran - try to adapt your style. Read my CV/resume. Dammit, this could be the start of a long and lasting relationship, at least do me the courtesy of reading my CV. Asking me about A* algos when it's blindingly obvious I've been a graphics coder all my life says you really haven't paid attention. So why should I work for you? If I list various papers/articles I've written, at least skim-read some of them. They'll give you stuff to talk to me about, and stop you asking questions to which the answer is "read my paper" - that's just embarrassing for all concerned. Do not ask me arbitrary logic questions, especially ones with "tricks" in them. You know - crossing rivers with various objects and animals. Or reversing linked lists in-place - things like that. There's three options. First, I've heard the question before, know the answer, and admit it, and so what does that prove, except that I've done a lot of interviews recently? Second, I've heard the question before and pretend I don't know it and fake working it out so I look like a genius. So now I'm a devious arsehole - cool! Third, I don't know the question and I flounder away trying to spot the trick under time pressure - it is random how long this takes. Logic puzzles are good for testing how good you are at logic puzzles. But like IQ tests and cryptic crosswords, they are only loosely related to how good you are at practical problems. The fact that I've shipped games and designed large systems should tell you more than these tests. Don't ask me maths degree questions when you can see that I did a ~CompSci degree. My answer is (and was) "I don't know, I didn't do a maths degree, but I know where to find the a