Ruckus design files start with a lang line:
|#lang ruckus||package: ruckus|
Ruckus is based on Racket. You don’t need to know Racket to do basic work in Ruckus, but as designs become more complicated, Racket’s features can be a huge help.
All coordinates in Ruckus are relative.
Primitive objects (see below) are always created at the origin of their local coordinate frame. The relationship between an object’s local coordinates and world coordinates can be controlled by transforms, such as at and rotate.
For example, this sphere sits at the origin:
We can make two spheres, separated by 200 units, using at to shift them in space:
The coordinates are relative, not absolute; they measure distance from the local origin. We can shift the local origin by wrapping the whole shebang in more at. The coordinates get added together. Thus, here we define two spheres, at locations '(100 55 0) and '(-100 55 0). They are still 200 units apart, just shifted by 55 units in one direction.
This might seem a little pathological, but if we wrap the inside in a function, we have a reusable chunk we can place wherever we want:
#lang ruckus (define (spheres-200-units-apart) (at '(100 0 0) (sphere 100)) (at '(-100 0 0) (sphere 100))) (at '(0 55 0) (spheres-200-units-apart)) (at '(0 110 0) (spheres-200-units-apart)) ; ... and so on
This reusability is the real strength of using relative coordinates.
Ruckus distinguishes between 2D and 3D contexts.
Any function called from a 3D context is also in a 3D context:
#lang ruckus (define (my-sphere) ; Because this is called from a 3D context, its contents are ; also in a 3D context. (sphere 100)) (my-sphere) ; called here
You can switch into a 2D context by using a projection transform, which specifies how to project flat 2D objects into 3D space. Currently, only one projection transform is available: extrude.
#lang ruckus ; 3D context on the outside... (extrude 100 ; ...but 2D context on the inside. (circle 100))
To complete the circle, you can also use 3D shapes in a 2D context by using a slicing transform, which specifies how to smash a 3D object into a flat 2D shape. Currently, only one slicing transform is available: slice, which produces a cross-section.
#lang ruckus ; 3D context on the outside... (extrude 100 ; ...2D context on the inside... (circle 100) (slice ; ...and a chewy 3D center. (cube 170)))
(coord? v) → boolean?
v : any?
A coordinate is a list of real numbers, where the length of the list corresponds to the current context: three numbers in 3D, two in 2D.
(color? v) → boolean?
v : any?
A color literal may be:
A list of three real numbers, representing red, green, and blue, where 1.0 is full intensity and 0 is nothing.
A symbolic color name taken from the X11 color names, lower-cased and with dashes in place of spaces, e.g. 'light-goldenrod-yellow.
These primitives can be employed in any 3D context.
Radius is the default way of specifying a sphere. We provide the #:diameter keyword as an option, because otherwise some designs wind up littered with divide-by-twos to convert specified diameters to radii. The #:radius keyword can help contrast with #:diameter in designs where both are used.
(rects size-x size-y size-z)
size-x : real?
size-y : real?
size-z : real?
size : real?
This is exactly equivalent to the following definition:
(capsule height radius)
height : real?
radius : real?
The capsule form generates a capsule, centered around the origin, and extending along the Z axis. height gives the distance between the center points of the two ending spheres, and radius gives the radius of the capsule and the ending spheres.
Note that the actual length of a capsule along Z is given by (+ height (* 2 radius)).
The plane’s normal is given by normal, and its distance from the origin along the normal is distance. Positive distances include the origin in the "inside" part of space; negative distances exclude it.
The normal will be normalized internally by Ruckus, so you can use any vector.
constraints must be a list. Each item in the list can be one of two kinds, basic points and points with normal vectors.
Basic points (as lists of three reals) are points in space that are on the surface of the object.
Points with normals are given as a list of two points. The first is a basic point on the surface, and the second is taken as a normal vector pointing out of the surface at that point.
At least one point in the constraints list must have a normal.
This is still under development and is pretty hairy.
radius is the default way of specifying a circle. We provide the #:diameter keyword as an alternative for designs that prefer to specify dimensions that way, and #:radius for contrast in designs that mix both styles.
(rect size-x size-y)
size-x : real?
size-y : real?
(union form ...)
Most combinators implicitly union their children, so an explicit union is rarely necessary.
(intersection form ...)
(intersection (cube 330) (sphere 200))
(difference first-form other-forms ...)
Unlike intersection, difference is sensitive to the order of its child forms. The first-form is treated specially. As a result, using difference is the main case where you may want to use an explicit union to group several objects together into a single form.
(difference (cube 330) (sphere 200))
(smooth-union radius form ...)
radius : real?
(smooth-union 10 (cube 330) (sphere 200))
vector should be a valid vector in the current context: in 3D, a list of three real numbers; in 2D, a list of two. vector may be written in place as a literal, or taken from a variable.
When called with ratio, the single ratio is applied equally to all axes.
When called with vector, separate ratios are applied to each axis: in 3D contexts, three ratios are required, and in 2D, two are required.
In 2D contexts, the first version must be used, and the rotation is always counter-clockwise by angle degrees around the Z axis.
In 3D contexts, the second version must be used, and the axis must be provided.
axis can be one of the literal symbols 'x, 'y, or 'z, designating the X, Y, or Z axes, respectively.
axis can also be a literal vector, given as a list of three numbers. In this case the vector will be normalized internally.
The color col is represented as a list of real numbers, giving the fraction of red, green, and blue as a number between 0 and 1.
Color is currently only significant in the Ruckus visualizer.
(iso shift forms ...)
shift : real?
(extrude height forms ...)
height : real?
(slice forms ...)
(mirror-x forms ...)
(mirror-y forms ...)
(mirror-z forms ...)
This version is illegal in 2D contexts, since there is no Z axis.
(repeat-x period forms ...)
period : real?
(radial-repeat count forms ...)
count : integer?
(reflect-distance forms ...)