Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Donut math: how donut.c works (2011) (a1k0n.net)
121 points by shrikant on Jan 23, 2014 | hide | past | favorite | 22 comments


slightly disappointing - the effect is interesting but the implementation and derivation are sloppy.

using a z buffer is a little unexciting i was expecting something raytracy or voxely - maybe even scanliney... but thats too much to explain in this comment.

also using the matrices for deriving the torus equation... its much simpler to create a rotating basis intuitively with cos and sin then apply them again to create a circle going around... then rotate the torus as a separate operation before applying the 3d projection

e.g. start with

  x = R*cos(t);
  y = R*sin(t);
to define the big circle - note that ( cos(t), sin(t), 0 ) is the normal to that circle and use that to create the circles winding around with a second parameter:

  x = r*cos(t)*cos(u) + R*cos(t)
  y = r*sin(t)*cos(u) + R*sin(t)
  z = r*sin(u)
set u = n * t and then you get the torus shape with a single parameter where the spiral around the surface closes up on itself.

the 3d rotation of the whole object can be kept separate and done on a per axis basis (since using only two angle this is actually less operations as well)

you end up with the same result but no need to do any particularly challenging algebra.


Yes, I just collapsed all the rotations because it ended up being smaller code than doing the two separate axis rotations on x,y,z. Clarity and simplicity was the opposite of the goal here, it was an IOCCC entry.

But I think I did pretty much exactly what you said, otherwise.


If learning more about 3D rendering means I'm going to end up being disappointed by donut.c, I think I'm going to put off learning more about 3D rendering.


> If learning more about 3D rendering means I'm going to end up being disappointed by donut.c, I think I'm going to put off learning more about 3D rendering.

A topologist: "You can easily screw yourself up in three dimensions, but you need at least five to unscrew yourself."


i was hoping to find something clever or interesting. thats not a reason to not continue trying to learn


This sounds like your ticket to IOCCC 2014 fame & fortune.


are you saying that using less code, more steps and less maths with a simpler algorithm requiring much less knowledge is going to make more obfuscated code?

any mathsy code is going to be obfuscated without comments explaining the underlying assumptions and for geometric stuff like this what you really want is diagrams...


I may have misread your disappointment. I thought you were critiquing this IOCCC entry on its merits as an IOCCC entry.


> You end up with the same result but no need to do any particularly challenging algebra.

And a larger code which means it's bad for an IOCCC.


Also you can use the sign of a point on the normal for no z-buffer.

edit: removed my needless commentary


That doesn't work -- there are front-facing surfaces behind other front-facing surfaces. You can see an example of this in the point-drawing javascript implementation further down the page, where I do just that.


Doh of course, thanks for the great write-up and the clever original donut.c entry.


And here's the beginning of a1k0n's MSP430 port:

https://gist.github.com/a1k0n/8582230

:)


I read that article awhile ago, used the character brightness representation idea to build a JavaScript image/webcam/video to ascii converter http://dph.am/jscii/ https://github.com/EnotionZ/jscii



When I run this with pypy it is far too fast to see what is going on.


How do I compile this? GCC complains:

    CFLAGS="-g -pipe" make -k donut
    cc -g -pipe    donut.c   -o donut
    donut.c:1:2: warning: data definition has no type or storage class [enabled by default]
    donut.c: In function ‘main’:
    donut.c:4:16: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
    donut.c:5:12: warning: incompatible implicit declaration of built-in function ‘memset’ [enabled by default]
    donut.c:9:63: error: ‘s’ undeclared (first use in this function)
    donut.c:9:63: note: each undeclared identifier is reported only once for each function it appears in
    donut.c:10:18: error: expected ‘,’ or ‘;’ before ‘in’
    donut.c:11:32: error: ‘t’ undeclared (first use in this function)
    make: *** [donut] Errore 1
    
    Compilation exited abnormally with code 2 at Thu Jan 23 16:11:12


I had no problems using: gcc -o donut donut.c -lm

You may also have errors in your version of donut.c, try copying the version from http://www.a1k0n.net/2006/09/15/obfuscated-c-donut.html


Merge lines 9 and 10, so that

s\

in(...

becomes

sin(...


Definitely worth checking out! Some fascinating code and math to create animated ASCII art.


I ported this to Lua as a PNaCl demo: https://gonativeclient.appspot.com/demo/lua

Click the "Donut" button, and press enter.


Replace line printf("\x1b[H") with you system specific screen clearing function if you don't have POSIX.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: