|Michigan Tech's Open Sustainability Technology Lab.|
Introduction[edit | edit source]
This page describes the script to produce an animation based on a textual description document and uses Blender, which is a free and open-source software package for animation.
Method[edit | edit source]
The program handles a list of objects, which can be translated and rotated arbitrarily. Each object definition includes zero or more reference points, which can be used in the animation specification for position and displacement computations.
The script first defines all the objects and then the animation.
Types and expressions[edit | edit source]
Within the script, there are many places where expressions may be used. Expressions contain values of several types:
- Numbers (always stored as floating point).
- Points: a position in 3D space.
- Vectors: a displacement in 3D space.
All logical operations are possible:
- number + number = number
- number - number = number
- number * number = number
- number / number = number
- Point + Vector = Point
- Point - Vector = Point
- Point - Point = Vector
- Vector + Vector = Vector
- Vector + Point = Point
- Vector - Vector = Vector
- Vector * number = Vector
- Vector / number = Vector
- number * Vector = Vector
- number, number, number = Vector
- -Vector = Vector
- -number = number
Note that a Vector and a Point are not interchangeable. If you want a vector from the origin to be used as a point, you have to be explicit about it. Same thing about a displacement from the origin to a point. This is intentional; it may catch mistakes.
Indentation[edit | edit source]
As in python, indentation matters. It is only allowed where it is expected. It is used to define blocks of lines; ending the indentation ends the block. Any command which expects an indented block after it ends in a colon. Every new indentation level must be exactly one byte more than the previous. This may be either a space or a tab, but it must not be more than one byte. It is strongly suggested to use either spaces or tabs throughout the file and not mix them.
Comments[edit | edit source]
Lines starting with # are ignored. Lines starting with ! are also ignored, but they are printed to the terminal when the script runs, along with the time and frame number when they appear.
File format[edit | edit source]
The first part of the file defines the objects. There are two main things that are described: objects and markers. Objects have a corresponding blender source file to describe their model. They can be rotated and translated. Markers are identical to objects, except that they don't have a model; they are only a location which can be manipulated. This can be used to help describing the movements of the objects, by providing reference points.
The objects and markers can be grouped by placing their definition inside a block that starts with group followed by the name of the group and a colon. This name can be used in the animation instructions to move all objects in the group simultaneously.
There are two predefined special objects: one named Camera, which is the position of the camera, and one named Target, which is the position the camera is pointing at. This means that rotating the camera object has no effect (other than the translation that may be part of the rotation); it will always be rotated such that it is looking at Target.
Example object definition section[edit | edit source]
# A group for all objects is useful. group all: # Some spheres in different colors; they use the same blender model. group spheres: object red_sphere sphere f000 object blue_sphere sphere 00f0 group cylinders: object yellow_cylinder cylinder ff00 marker cylinder_helper
As can be seen, object colors are specified using 4 hexadecimal digits, like rgb color codes in html. However, the 4th digit is not the transparency, but the amount of specular reflection. Setting it to zero makes the object matte, setting it to f makes it shiny.
Animation section[edit | edit source]
The rest of the file describes the animation. It normally starts with moving all objects to their starting locations, but that is not a requirement. Any object that is not moved will be at the origin.
The main movement commands are translate and rotate. They both take the number of seconds that the operation should take as their first argument, and the object or group that is to be moved as the second. After that, translate requires a displacement vector (not a position!) and rotate needs an angle in degrees and a rotation vector, which is described as a base position and a direction.
For translations, you normally want to move an object such that a reference point A moves to be on top of another reference point B ("move the base of the cylinder to the top of the cube"). The displacement vector for this operation is simply B - A. A is a point on the object that moves; B is a point that doesn't move. But this is not a requirement; any displacement vector is allowed.
If the Blender file that contains the model also contains Empty objects, their positions relative to the object can be used as locations in the expressions. For example, if a blender file of a cylinder contained an empty named top, and that blender file is used to define an object called cylinder, the origin of an object named cube can be moved on top of the cylinder using:
translate 2 cube cylinder.top - cube
These reference markers automatically update their position when their parent object is translated or rotated, so they always reference the spot on the object.
Complex movements[edit | edit source]
Using the above approach, it is possible to create animations of things move in sequence. First one thing moves, then the next. Also, a thing can rotate first and then translate, but not simultaneously. For this, some extra commands are available.
Movement instructions can be grouped into blocks titled parallel or serial. All items in a block titled parallel will happen simultaneously; items in a block titled serial will happen sequencially. Instructions at the outermost level are implictly in a single serial block.
Doing things in parallel leads to a new problem: if an object which is in the process of being rotated is referenced, which position will the expression use? To make things easy, the program considers any movement to have completed immediately. So these instructions:
parallel: rotate 2 cube 90 cube.top 1,0,0 translate 2 cube marker - cube
will result in the cube being at the position of marker after the 2 seconds. On the other hand, these instructions:
parallel: translate 2 cube marker - cube rotate 2 cube 90 cube.top 1,0,0
will result in the cube being somewhere else (unless the marker is at the origin): the final position will the the same no matter if the block is parallel or serial, so here the rotation makes it move away from the marker.
Finally, to get the timing perfect, there is a wait instruction, which only takes a number of seconds as an argument. To make things easier in parallel blocks, an other instruction may be specified on the same line as the wait instruction; the two are then implicitly interpreted as being in a serial block. For example:
parallel: wait 1 rotate 1 360 cube 0,0,1 translate 2 cube 0,0,10
will move the cube up by 10, and in the second half of that movement, it will also rotate it a full circle around its vertical axis.
Variables[edit | edit source]
When making animations, some values, which can be the result of computations, are repeatedly needed. Such values can be stored in variables. Variables can have any of the types supported by the system. For example, these two things are identical:
set d cube.right - cube.left translate 1 cube 3 * d
translate 1 cube 3 * (cube.right - cube.left)
Note however, that the value of a variable is stored at the time the set instruction is executed. So these two are different things:
set d cube.right - cube.left rotate 1 cube 90 cube 0,1,0 translate 1 cube 3 * d
rotate 1 cube 90 cube 0,1,0 translate 1 cube 3 * (cube.right - cube.left)