# How do I make a giant clock made of many small clocks?

I want to recreate this animation I found online, of a giant clock that displays the time using many smaller clocks. The minute and hour hands of the smaller clocks rearrange into symmetry and shows the time. This is the particular image I found:

(The clock showing the time.)

(The video: Giant clock made out of tiny clocks)

For sake of simplicity: I want the needles of those clocks moving and align to show a single digit.

Here is the simple scene that I made using animation nodes:

I made 2 arrows, and duplicated it 5*8 times:

Each arrow is sent to the node program, which determines the position in the space and the rotation:

First, I divided the index by 5 and took the remainder of the division to get the coordinates (x and y index) of the arrow:

Next, I just multiplied it to get the correct scale of the arrow's matrix (x and y coordinates):

How to get the rotation? First, I wrote a map, which determines the rotation of each arrow. I made it using a list of "box symbols" ("┌","─","┐", etc..):

┌───┐
│┌──┘
││
│└──┐
│┌─┐│
││ ││
│└─┘│
└───┘


Then I wrote the script, which converts a correct symbol into 2 angles:

out=[0,0]
if(letter=="┌"):
out=[-90,180]
if(letter=="─"):
out=[-90,90]
if(letter=="│"):
out=[0,180]
if(letter=="┐"):
out=[180,90]
if(letter=="┘"):
out=[0,90]
if(letter=="└"):
out=[0,-90]

rot=out[arrow]


So when I put the correct letter and arrow index (0 or 1 - first or second arrow) it outputs the correct angle:

This script block gets the letter from the text "map":

and finally I used the animate float node to make a transition between a random angle and that angle:

As you see, you need to know a little about Animation nodes and scripting. This is the file (NOTE: it will not work without Animation Nodes!):

• Well done my friend. Understanding Animation nodes (or just math) is my dream. Sorry for the link but I need to: gph.is/2cpbE6Y – cgslav Aug 3 '18 at 21:52

First, the way of representing the digits has to be defined. In this answer, I shall use a low resolution image representing each digit. The image is a $10 \times 12$ binary image like this image representing the digit $4$:

Each $2 \times 2$ pixels represent a clock, so we have $\frac{10}{2}\times \frac{12}{2} = 5\times 6 = 30$ clocks. Each pointer have a limited number of directions it can point at, in particular, it can have an angle $0, \frac{\pi}{2}, \pi, \frac{3}{2}\pi$. By looking at each four pixels of each clock we can determine the orientation of its pointers. Since we have four pixels, then we have $2^4=16$ possible combination, however, if the image is inverted, nothing changes, making the number of possible orientations to be $8$. We can encode the the four pixels in a 4-bit number where each bit represents a pixel. Then one can compute a look up table for each possible 4-bit number that stores the orientation of each pointer. By looking at the reference image, we can find that LUT to be:

p1 = [undetermined, 0   , pi/2, 0 , pi      , undetermined, pi/2  , 0     ]
p2 = [undetermined, pi/2, pi  , pi, 1.5*pi  , undetermined, 1.5*pi, 1.5*pi]


Where p1 and p2 stores the orientation of the first and second pointer such that the index of each orientation is the 4-bit number that characterizes each combination. The undetermined indicates that all pixels are identical or that the first and third or the second and fourth quadrants are similar contrary to the others and thus no orientation can be determined.

In Animation Nodes, I will read the image as a single channel using the expression:

bpy.data.images[imageName].pixels[:][::4]


Where [:] copies the image values and [::4] get us every fourth element because we only need the first channel. (From RGBA we only need R) Then, I am going to get the width and height of the image using the expression:

width = bpy.data.images[imageName].size[0]
height = bpy.data.images[imageName].size[1]


Then, I am going to encode the pixels in the 4-bit number clock by using the following code:

LUT = []
for h in range(height // 2):
for w in range(width // 2):
clock = 0
if pixels[(h * 2 + 1) * width + w * 2 + 1]: clock |= 1
if pixels[(h * 2 + 1) * width + w * 2    ]: clock |= 2
if pixels[h * 2 * width + w * 2          ]: clock |= 4
if pixels[h * 2 * width + w * 2 + 1      ]: clock |= 8
LUT.append(clock)


Since the width and height is double the number of clocks, we loop over only have of them. We initialize the 4-bit number to be zero and for each pixel, check if it is equal to a non zero and if yes, set its corresponding bit to one using the or operator. Then we append the 4-bit number to a list and return it. We only computed $8$ of the combinations, the other $8$ are identical to those computed as we said except their order is reversed, we could either invert the 4-bit number if it surpassed $8$ or combine the list to itself head to head which we shall do because it is easier.

The next step is to evaluate the LUT at the previously computed numbers, forming an Euler from that and constructing a matrix list along the points of a uniform grid. Those matrices represents the orientation of the pointers and their locations and a simple grid mesh can be transformed along them creating the pointers we need.