This is documentation of an obsolete version. You should use the newer version instead.

This is a set of scripts used to manage precisely time synchronized motions of objects in club lighting, dynamic art, and other moving displays.

Clockworks units offer sophisticated customization of rotation patterns and a guaranteed perfect synchronization of all units indefinitely over time. Even if a scene server chokes or there is a temporary network disconnect, the units will "catch up" to the current timing and all stay perfectly aligned. DJs and other event managers can look up BPM values for most dance songs and configure their systems in real time during a show.

Clockworks scripts can also be used in other applications that involve simple rotations (e.g., birds flying overhead) and complex, repetitive rotation cycles.

To see the Clockworks system in action, visit the Clockworks Club Demo experience.

Where to get the scripts

Controller settings

There are two essential devices: the controller and the individual units. The controller synchronizes all the units and processes commands from the user. The units are the visibly rotating objects that are synchronized. The two devices are controlled by two corresponding scripts, called "Clockworks - Controller 1.0" and "Clockworks - Rotator 1.0", respectively.

The controller can go in any object. It does not need to be flagged as dynamic. The unit scripts go in objects that must be flagged as dynamic and have rigid bodies, which are what get positioned and rotated by the script. Following are typical settings for the controller script:

The controller script does not need to be configured if you plan to manually start and control the system in person. If you want it to automatically start a control program, you'll need to enter its BPM (beats per minute), program name (blank for default), and auto-start time to 1 or greater.

The BeatsPerMinute (BPM) setting refers to how fast the rotation programs should all run. For example, 60 BPM represents 1 beat per second and 120 BPM represents two beats per second. In typical dance music, a beat is reflected in the time between the individual thump-thump-thumps of bass drums and other heavy percussion instruments that give dancers the sense of rhythm to the music. Most popular dance songs have fixed BPMs that can be found via a Google search or through free BPM lookup sites like Song BPM.

While every unit can hold any number of named programs, the one you configure via the "ProgramScript" setting is the default program, which has no name. Unless you plan to use this advanced feature, it's best to just leave the "ProgramName" setting in the main controller blank.

Rotational unit settings

The rotation script goes in each "unit" that is to be controlled. Following are typical settings for the script:

It is not necessary to set "UnitName" if you do not intend to tinker with programming the individual units at runtime, but it is a good practice. You can even go with "U0", "U1", "U2", etc. if you don't know what to use.

The "Channel" setting is best left at its default value of "0". You can change this if you wish to have multiple separate controller/units systems running on the same experience independently of each other. The default channel value, if you leave it at 0, is 19730001.

The "ProgramScript" setting contains the default program for that unit. A program describes a sequence of rotations the unit undergoes in a continuous loop. More on this in the next section.

By default, the units are updated about 100 times a second. A "SleepMilliseconds" default value of 0 translates to 10ms, or 1/100 of a second. While you can override this value, it's probably best not to in most cases.

The "CenterPoint" setting should be a copy of the "Position" setting for the object or otherwise where you want the rotating object to be placed in the scene. If you don't set this value, it will be gleaned from the object's position when the script is initialized. But keep in mind that, because the object must be dynamic and start out with some mass, it probably will have fallen a little before the script can read its position. So it's best to not rely on automatic detection.

You can think of your object as being rotated on its axis in a perfect circle, as with a wheel. However, you may have reason to "tilt" your object so it rotates more like a wobbly wheel. This is especially valuable with lighting where you want the light to point down with a tilt and rotate in a circle on the ground below. True, you can simply rotate your object with no tilt and orient the spotlight so it is tilted, which is easier, but there may be other scenarios where this is the only way to orient the object you want people to see at an angle other than perfectly along the axis or perpendicular to it.

The "Telescope" setting allows you to have your object projected a distance away from the rotational center point. An example would be a bird flying in a wide circle overhead.

The "Axis" setting is critical. The object rotates around this axis. If you leave this as <0, 0, 0> (default), it will be treated as equivalent to <0, 0, 1>, which points straight up, which is appropriate for, say, a record player. If you want to simulate the hands of a wall clock, you might choose <0, 1, 0> or <1, 0, 0> for rotation around the Y axis or X axis, respectively.

The "Angle" setting adds an initial fixed rotation amount to the starting rotation your program can set. In the clock example, this may be required to align the hour hand up for 12 instead of, say, down or to the right.

Programming a unit

Programming a unit for rotation is, strictly speaking, not like writing code in C# or some other programming language. A "program" describes how a unit should rotate over time. Following is one of the simplest programs possible:

R:1

This can be read as "rotate 1 full turn for each beat". The rotation follows the right-hand rule, so if the axis points up and you look down on it, the object will rotate counter clockwise. We'll call this a "left" turn. Here's a slightly more complex program:

R:-0.25 | R:0.25 | R:0.5

This can be read as "rotate a quarter turn right on the first beat, rotate left a quarter turn, then rotate right a half turn." This cycle continues indefinitely, looping from beat 1 to beat 2 to beat 3 and then back to beat 1 to repeat the loop.

In the above examples, the rotation pattern is "linear", which means it rotates at a constant speed over the whole time period of a single beat. But you can choose other patterns. Here is an example:

Place a pipe (|) symbol between each of the beat definitions.

R:0.1; RP:B

Each beat can have multiple property values like this. Each key:value pair is separated by a semicolon. "R" is the name of the property representing the amount of rotation to undergo during the beat. "RP" is the rotation pattern. In this example, the pattern is not linear, but "back edge". That is, for the first 75% of the beat, the object does rotate. Then it rotates the desired amount linearly during the last 25% of the beat. This gives a "tick" appearance to the rotations and more strongly emphasizes the beat. In this example, the rotation is 10% of a full rotation, so after 10 beats, the object will have rotated back to its starting orientation.

Each beat can have the following property values applied:

R - Rotation

What percentage of a full turn to rotate during the beat. 0 represents no rotation at all. 1 represents a full "left" (counterclockwise) turn. -1 represents a full right turn. You can use larger values like -2 or 5 if you want more rapid rotations. Or you can use fractional values like 0.25 (one quarter) or -0.1 (one tenth).

SR - Start rotation

This is only meaningful on the first beat and only gets applied when the controller sends the start signal to set everything in motion. This can be thought of as a reset and indicates how much rotation to apply at the start. "SR:0" is a good practice to get into for objects that need to visibly line up with other objects in sequence.

FR - Fixed rotation

This wiped out whatever rotation the object had at the end of the prior beat and presets the rotation amount at the start of this beat. Picture a laser sweeping from left to right, always starting at the left side.

IR - Instant rotation

This starts with whatever rotation the object had at the end of the prior beat and adds this much rotation to it. Just as with FR, the R (rotation) property then applies over the rest of this beat's duration.

RP - Rotation pattern

This governs how the rotation takes place over the time of a single beat. Options include:

Live performance commands

You can control the overall performance and that of the individual units without leaving the scene. The system supports a command line syntax right from the public chat window. Here is an example command:

cw start 142

All commands begin with "cw", short for "Clockworks". That is followed by a command. In this example, "Start" tells all the units to begin walking through their programs. And the command may have parameters, like "142" here, which represents the BPM value all the units should run at.

Following are all the commands available. Note that they are all case insensitive, so capitalization is not necessary.

CW Start [BPM] [Program name]

Calling "cw start" by itself simply restarts all the units using the current program and BPM. Calling it with a BPM value resets it using the current program and the desired pace. This is useful during a live dance event for changing the pace with each new song played.

Note that if the named program is missing, the current program loaded into memory is used and restarted, instead.

CW Stop

Stops all units from rotating and resets them to their default orientations. The scripts continue maintaining the objects' positions so they don't float off.

CW DefProg <Program name> <Unit name> <Program script>

Use "*" for the default program's name. Use "*" for all rotational units, though this is usually not desirable. Normally, spaces between arguments in a command signal separate arguments, but with this command, everything on the command line after the unit name argument represents the whole program script to pass along. You can include spaces in your program, which makes it easier to read. Here is an example invocation:

cw defprog * Bird1 sr:0; R:0.1 | r:0.2

There is no practical limit to the number of named programs you can define. These get selected by the UseProg and Start commands.

CW UseProg [Program name] [Unit name]

This tells the given unit to switch to a different named program just after the end of the current beat and maintaining the current BPM rate. This is similar to the Start command, but a finer instrument; and Start interrupts the current beat and resets the loop's start time for all units. But Start is generally preferable during live performances because it is easy.

Note that if the named program is missing, the current program loaded into memory is used and restarted, instead.

CW ClearProg [Unit name]

Clears all programs from one or all units. This is useful in preparation for reloading a whole new set of programs. Note that this will not stop the units from executing the programs they still have in memory indefinitely.

CW MoveTo <Unit name> <Position>

This moves the center point to the given absolute position, which moves the whole object. Position is expressed as "X,Y,Z", where X, Y, and Z are decimal values and there are no spaces at all between tokens. For example, cw moveto U1 10,0,1.5.

CW MoveRel <Unit name> <Position offset>

This relatively moves the center point by the given offset vector, which moves the whole object. Position offset is expressed as "X,Y,Z", where X, Y, and Z are decimal values and there are no spaces at all between tokens. For example, cw moverel U1 0.5,-1,0.

CW RotTo <Unit name> <Orientation>

This rotates the baseline orientation to the given absolute orientation. Orientation is expressed either as a 4-value quaternion ("X,Y,Z,W") or as a 3-value vector ("X,Y,Z") of Euler angles expressed in degrees.

A discussion of quaternions and Euler angles is beyond the scope of this document, but it is generally easier for programmers and nonprogrammers to understand Euler angles as being a series of three rotations. Each of X, Y, and Z represent a separate rotation, with values from -360 to +360. It is just best to experiment with these to see the effects.

CW RotRel <Unit name> <Orientation offset>

This rotates the baseline orientation relative to the current orientation. Orientation offset is expressed either as a 4-value quaternion ("X,Y,Z,W") or as a 3-value vector ("X,Y,Z") of Euler angles expressed in degrees.

A discussion of quaternions and Euler angles is beyond the scope of this document, but it is generally easier for programmers and nonprogrammers to understand Euler angles as being a series of three rotations. Each of X, Y, and Z represent a separate rotation, with values from -360 to +360. It is just best to experiment with these to see the effects.

Making dynamic lights

It's easy enough to make an object, make it dynamic, and dump the "Clockworks - Rotator 1.0" script into it. So long as your 3D object has a rigid body in it, you're good to go from there. But setting up dynamic lighting requires some additional considerations.

You cannot put a script in a light to rotate or move it, but you can embed a light into an object in your scene. To do so, find the object in the "Scene objects" list, right-click on it, and choose Add > Light. Then you can configure it in settings. Later, when you want to change its settings, you have to expand the object in "Scene objects" again and click on the light you added to select it. You can use this technique to add multiple lights to a single object.

Let's start with the directional light. This is what we typically use to simulate sunlight in a scene. You can add one to an object to rotate. Rotating it can create a dramatic and potentially disorienting effect, so use this tactic with care. Also, you currently can only have one directional light in a scene. Directional lights cast shadows.

You can also add point lights to an object. These can be used to create shifting lighting, fireflies, and other interesting effects. But be aware that they cannot currently cast shadows.

Arguably, spotlights are the most generally useful lights to add to rotating objects. They can cast shadows (turned off by default in settings) and have a variety of settings.

Because they can cast shadows, you can create objects that have custom protector masks and have your spotlight behind (or inside) them. Alternatively, you can install fixed spotlights and have rotating objects placed in front of or around them. For example, you can have a rotating sphere with holes poked into it and a white spotlight with a wide angle aiming down inside it to simulate a disco ball.