I've updated the code to be even more readable, and as an aside, made it more optimal.
sin(A) and sin(B) were being computed repeatedly in the most inner of inner loops, which I pulled out, because A and B don't change in the middle. sin(j) and cos(j) was being computed for every i, even though j wasn't changing. And the intensity was being computed even if the pixel was going to appear beyond the buffer (or wasn't going to appear at all because of a closer pixel in the z buffer).
I also refactored parts of it, and gave names to some constants which you can tweak for fun. DELTA_I can be increased without apparent detriment to image quality. I can't think of good names for the two constants in the middle of the code though: 2 and 5. Are those the minor and major radius of the donut?
Re: repeatedly computing sin(A)/sin(B)/etc: I don't remember why I did that, as it was five years ago, but it was probably intentional just to move code around so it fit within the shape. Or it was an oversight.
IIRC, yes, 5 and 2 are the major and minor radii, meaning 5 is the radius of the ring at the center of the donut (a torus of thickness 0, as it were) and 2 is the thickness -- the radius of the circle extruded around the central ring.
A 3D quine? I've considered it. I have a blog post about something completely unrelated to obfuscated C coming up, but maybe after that I'll make an attempt. If nobody beats me to it.
They're just warnings. I got the same ones but it still created a perfectly good executable. (you kind of have to assume warnings with obfuscated code :)
I had no idea that printing something like "\x1b[2J\x1b[H" can clear the screen - with a bit of googling I found out that this is not that unusual a command, but it still took a little reading to figure it out! [1]
Looks like the rest of the code is for generating the donut. Quite a bit of math involved - too much for a sunday morning to look into and attempt to decipher!
Those are so-called ANSI terminal escape sequences - there is a whole list of them. Hex 1B is the escape character, the characters after that determine the action (clearing the screen, changin text color, moving the cursor etc.) Well, and "[2J" is the sequence for clearing the screen.
<ESC>[H ("home") moves the cursor to the upper-left hand corner, so I initially clear the screen and then use "home" to do the animation.
An alternative method to animate ascii stuff, used in the Yahoo logo, is just to cursor-up 25 lines (or whatever) with <ESC>[25A between frames. That way it doesn't have to clear the screen and you can see your command history, etc.
Very cool - I've never played with sending special terminal characters before to clear the screen and the like; like others, I will definitely add this to my repertoire!
My suggestion for deciphering it - let's not forget about `indent`!
It's really not that hard, once you have some idea of the kind of program you're writing. Write it out normally, and start eliminating everything that can be eliminated (in particular, whitespace, braces, if statements that can be conditionals, subroutines, variables, etc). Takes some ingenuity with loops but it's mostly straightforward.
In this particular example the only really odd thing about it is the lighting calculation, which is an algebraically simplified dot product of the light direction (0, 1, -1) IIRC with the surface normal of a torus (gradient of the equation defining the shape). The derivation of that is long gone but it wasn't hard math.