IOCCC image by Matt Zucker

The International Obfuscated C Code Contest

2024/endoh2 - Prize in solid body physics

rotating rigid body simulation

Author:

To build:

    make all

To use:

    ./prog < body.txt

Try:

    ./try.sh

Judges’ remarks:

Playing with this entry, we were able to experience joy akin to what Niels Bohr and Wolfgang Pauli could have experienced when they played with the Tippe-Top.

We invite you to experiment beyond the try.sh, and test with these “body.txt” files:

For example:

    ./prog < vase.txt

Moreover, you should experiment with various simulation parameters. On the make line you may set:

    | Perameter   | Default  | Meaning
    |-------------|-----------------------------------------------------|
    | WIDTH       |  120     | Screen width                             |
    |             |          |                                          |
    | HEIGHT      |   24     | Screen height                            |
    |             |          |                                          |
    | TIMESTEP    |    0.01  | Simulation time step                     |
    |             |          |     a smaller dt                         |
    |             |          |     increases precision                  |
    |             |          |     down the simulation                  |
    |             |          |                                          |
    | RESTITUTION |    0.5   | Coefficient of restitution               |
    |             |          |                                          |
    | FRICTION    |    0.5   | Coefficient of friction                  |
    |             |          |                                          |
    | RPM         |  750     | Initial rotation speed in RPM            |
    |             |          |                                          |
    | FASTRPM     | 4000     | Tipple top initial rotation speed in RPM |
    |             |          |    used by ./tipple, not ./prog          |
    |             |          |                                          |
    | TILT        |    5     | Initial tilt angle                       |
    |             |          |    in degrees                            |
    |             |          |    0 is upright                          |
    |             |          |    positive values tilt to the right     |

For example, to increase the “Coefficient of friction” to 0.75, the “Initial rotation speed in RPM” to 600, and the “Initial tilt angle” to 15:

    make clobber all FRICTION=0.75 RPM=600 TILT=15

    ./prog < top.txt

Now we would like to see if this entry can be hacked to demonstrate the Dzhanibekov effect.

Author’s remarks:

A Spinning Top Simulator

                                       @@
                                      @@
                             @@@@@@@@@@@@
                         @@ @@@@@@@@@@@@@@@@
                        @@@@  @@@@@@@@@@@@@@@@
                       @@@@@@@    @@@@@@@@@@@  @
                       @@@@@@@@@@@           @@@
                        @@@@@@@@@@@@@@@@@@@@@@@@
                        @@@@@@@@@@@@@@@@@@@@@@@@
                         @@@@@@@@@@@@@@@@@@@@@
                         @@@@@@@@@@@@@@@@@@@@
                          @@@@@@@@@@@@@@@@
                          @@@@@@@@@@@@@
                           @@@@@@@@@
                             @@@@
                             @@
                            @@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

This is a physics engine that simulates the motion of a rotating rigid body, such as a top.

How to run

Compilation requires specifying several -D options:

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=1000 -Dtilt=5 -o prog prog.c

These options define the following parameters:

Then, run the program like this:

$ ./prog < top.txt

Input file format

The input file defines the shape of a rigid body. Here’s an example:

// A typical spinning top

// Use `-Drpm=1000 -Dtilt=5`

.
.
.  // Twirl here
.
.
.
...
   #####
        ##
          #  // Spin!
        ##
   #####
 ..
.
.
.  // Looks painful

This figure is rotated around its left edge to create a 3D object (a solid of revolution). Only solids of revolution are supported by this simulator.

Internally, the rigid body is modeled as a collection of particles (point masses). Each character in the input file has the following meaning:

Algorithm overview

The core algorithm works as follows:

  1. Compute the inertia tensor
  2. Compute an inverse of the tensor
  3. For each particle in contact with the floor: 3-1. Compute the normal force 3-2. Compute friction 3-3. Convert these into the resultant force and torque acting on the body’s center of mass
  4. Update the position, velocity, angular velocity, and orientation of the body

For the detailed theory, refer to a physics textbook.

To keep code size minimal, this simulator uses quaternions to represent 3D vectors and matrices. Quaternion multiplication is powerful, allowing the inertia tensor and its inverse to be calculated concisely, each requiring only about 100 characters of code. Because math.h doesn’t natively support quaternions for these operations, it’s not used at all. This also means linking with -lm is unnecessary.

Motion blur is used in the rendering. You can observe it more clearly by pausing the animation (e.g., with Ctrl+S in some terminals).

Distant points appear as colons (:), while closer ones appear as at-signs (@).

Included data

A few shape files are provided. The top*.txt files are standard spinning top shapes.

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=1000 -Dtilt=5 -o prog prog.c && ./prog < top.txt

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=500 -Dtilt=5 -o prog prog.c && ./prog < top2.txt

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=500 -Dtilt=5 -o prog prog.c && ./prog < top3.txt

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=500 -Dtilt=5 -o prog prog.c && ./prog < top4.txt

The tippe top is a top that flips itself over when spun quickly.

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=2200 -Dtilt=5 -o prog prog.c && ./prog < tippe-top.txt

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=4000 -Dtilt=5 -o prog prog.c && ./prog < tippe-top2.txt

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=4000 -Dtilt=5 -o prog prog.c && ./prog < tippe-top3.txt

Spinning a boiled egg? Try this with -Dtilt=90 to start it from a lying position.

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=1300 -Dtilt=90 -o prog prog.c && ./prog < egg.txt

Spin everyday items – no risk of breaking them:

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=1000 -Dtilt=175 -o prog prog.c && ./prog < bottle.txt

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=1000 -Dtilt=5 -o prog prog.c && ./prog < bottle.txt

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=1000 -Dtilt=5 -o prog prog.c && ./prog < umbrella.txt

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=2000 -Dtilt=5 -o prog prog.c && ./prog < vase.txt

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=2000 -Dtilt=20 -o prog prog.c && ./prog < vase.txt

More shapes: stick.txt, cylinder.txt, halo.txt, and even prog.c.

Yes, prog.c itself can be used as input. Try it:

$ gcc -O3 -DW=120 -DH=24 -Ddt=0.01 -De=0.5 -Du=0.5 -Drpm=1000 -Dtilt=5 -o prog prog.c && ./prog < prog.c

Inventory for 2024/endoh2

Primary files

Secondary files


Jump to: top