During the development of the Realized Visions section of In an ABSOLUT World, we faced creative and technical challenges in bringing the cubes to life on screen.
Our solutions included some clever 3D math, the usual Flash trickery and help from the Open Source community, but mostly lateral thinking.
3D + 2D
The idea of mixing 3D graphics with 2D physics comes from this early trailer of Little Big Planet. The game not only looks amazing, but for an interactive designer, even the preview videos are an excellent source of inspiration.
To calculate the physics between the cubes, we chose Box2DFlashAS3, a port of Box2D v1.4.3 to AS3 made by Matt Bush aka skatehead.
Box2D is an Open Source 2D rigid body physics engine for games, written in C++ by Erin Catto, a very talented physics programmer at Blizzard Entertainment. Other Box2D based engines for Flash worth checking out are motor2 and Physaxe for haXe.
Version 1.9 of Papervision3D handles the 3D rendering, while our application takes care of updating the 3D objects according to their 2D counterparts in the physics engine.
Scene depth is achieved by combining separate layers of 2D physics. The cubes still live in a 2D world that’s placed at a specific depth. To avoid the overhead of running multiple instances of the physics engine, we create our layers from horizontal segments of the 2D world. Sometimes, this might produce poltergeist phenomena between layers.
Geometry

Our cubes are actually a group of separate planes. This allows for great flexibility in working with individual cube faces and the entire cube at the same time.
To be able to open the box, we also added a hinge node to those faces that rotate around their edge. To open a face we rotate it’s hinge.
The outline shows the final hierarchy, with a root cube node, four hinge nodes and six face planes.
Working with planes and 2D interaction, let us apply simple 2D logic to some 3D problems. Our application implements custom shading and sorting optimized for our scene setup.
Shading
To maximize performance, we render each face plane on a separate container, and choose between two shading modes depending on the cube’s behaviour.
When the cube is awake, under the control of the physics engine, we dynamically shade the container of each plane on every frame. Since the rendered output is much smaller than the original material texture, this approach is much faster than shading the material directly.
But for still cubes, with physics disabled or asleep, we only need to update the shading once. Baking the dynamic shading into the material isn’t particularly fast, but if done once, instead of on every frame, distributed among frames, it produces a faster to render scene.
Reflections
Cube reflections are mirrored versions of the original objects. The shading is darker and they are rendered on a layer with Add blend mode.
To mirror the textures without creating a new material, we invert the UV mapping of the faces of the object. This is the actual code used, were you specify the axis to rotate as ‘u’ or ‘v’.
function flipTexture( obj:DisplayObject3D, axis:String='v' ):void
{
var faces:Array = obj.geometry.faces;
for each( var face:Face3D in faces )
{
face.uv[0][axis] = 1 - face.uv[0][axis];
face.uv[1][axis] = 1 - face.uv[1][axis];
face.uv[2][axis] = 1 - face.uv[2][axis];
}
}
Camera
The movement of the camera is calculated by combining the result of different functions.
We start with Tweener for the transitions, then we add user interaction so the point of view follows the mouse and the camera rolls accordingly.
A steadicam function keeps the scene alive even when still. The camera also follows and zooms in a box when it’s being dragged.
Optimization
In low poly PV3D pieces most of the performance is taken by the Flash Player screen rendering. In our case, making extensive use of colour transformations, the situation is even more delicate.
We constantly adjust stage quality and material smooth settings to achieve the best balance between performance and image quality.
The application switches between MEDIUM and LOW stage quality settings as needed. Falling back to the faster mode if frame time drops. You can disable this by selecting the corresponding quality mode in the RMB context menu. We use readability antialias to avoid text pixelation.
Intro and video player default to H.264 MPEG if supported by the player, else plays an FLV version.
At the end of the day, extensive experimentation and tweaking is always needed to achieve the effects you have in mind. Sometimes it means rewriting it all, but it’s definitely worth it.

April 24, 2008 at 11:24 am |
[...] Check it out here. [...]
April 24, 2008 at 1:28 pm |
Thanks for the insight
April 24, 2008 at 2:17 pm |
Nice!
Who did the music?
April 24, 2008 at 8:24 pm |
Impressive, how long did this take to develop?
April 24, 2008 at 10:05 pm |
Thanks for sharing. I really enjoyed the site.
April 24, 2008 at 10:27 pm |
Oh man, killer work! Can’t imagine the amount of sweat and tears behind this one.
April 27, 2008 at 5:23 pm |
Music is from Jonas Quant (quantastical.com), and the whole thing took around 4 months.
Glad you liked it.
April 15, 2009 at 10:50 pm |
this is some addicting stuff to play around with.
one question… did you place the separate planes inside of a Cube with transparent materials or just a DisplayObject3D.