Setting up a Rubik’s Cube in Papervision

December 31, 2008

Intro

Well it’s Christmas, and you’re right, one of the kids got a Rubik’s cube. And we’ve spent the entire break figuring it out – right down to the smallest child, even baby Na. It was a Rubik’s Cube free-for-all. And if that wasn’t enough, we had to make it virtual.

In this post, we’re going to show you a trick you can use to set up a Rubik’s Cube in just 8 lines of code. It uses the same trick that Mr. Doob uses on his blog – geometry.vertices. Below is an image of the cube you will make. Click on it to run the application.

Rubik's Cube (set up in 8 lines of code)

Rubik's Cube (set up in 8 lines of code)

Web Stuff

Demo

Download Source

YouTube Video – Coming!

Discussion

Essentially what you want to do is create a single large cube and use its vertices to anchor the smaller cubes to create the Rubik’s cube .

Using geometry.vertices to add cubes

Using geometry.vertices to add cubes

Large Cube

Segmenting the large cube with 2, 2, 2 (as shown in the image above)creates the coordinates of the Rubik’s cube

cubeGrid = new Cube(myMaterialsList1, mySize, mySize, mySize,2,2,2);

Placing small cubes at each vertex of the large cube is done using the geometry.vertices method.

Small Cubes

The geometry.vertices method gives you the position of each large cube vertex which is stored in the vertices array and accessed using the geometry.vertices method as shown below:

for(var i:int = 0; i<cubeGrid.geometry.vertices.length; i++)
{
var myPart:Cube = new Cube(materialArray[i], mySize/2.1,mySize/2.1,mySize/2.1,2,2,2);

myPart.x=cubeGrid.geometry.vertices[i].x;
myPart.y=cubeGrid.geometry.vertices[i].y;
myPart.z=cubeGrid.geometry.vertices[i].z;

particleArray.push(myPart);
myGraphicsHolder.addChild(myPart);
}

That’s really all there is to it, the only other thing you need to do is to set the faces of the small cubes to the appropriate Rubiks’s Cube colors using a materials list array (materialArray). Just click the more button below to see the complete code listing.

Note: This only sets the cube up. In the book, I show you how to program a fully functioning Rubik’s Cube.

Read the rest of this entry »


Creating an Adjustable Carousel Primitive

November 12, 2008

Intro

Typically carousels are created by assembling single planes in a cylindrical configuration stacking rows as needed. But there is another way to do this. You can create a single primitive which constructs all the planes internally. Handling a single primitive requires fewer calculations to manipulate it than handling multiple planes. And you can do more with it.

To see a demo click on the image below. Try clicking on the images they are interactive.

Single Primitive Carousel

Single Primitive Carousel

Just as in the case of the cube primitive, the carousel primitive can be manipulated as a single primitive. And the number row and column numbers are adjustable.

Web Stuff

Demo: http://professionalpapervision.com/demos/web/carousel/

Download (CarouselPrimitive)
http://code.google.com/p/flex3cookbook2/downloads/list

YouTube How to Video:

How it works

The carousel constructor function shown below gives you the ability to control the horizontal and vertical gap size, number of rows and columns, height and width, segments, and material list.

public function Carousel( materials:MaterialsList, myGap:Number=0, myHGap:Number=0 ,horizNum:int=1, vertiNum:int=1, width:Number=0, height:Number=0, segmentsW:Number=0, segmentsH:Number=0, initObject:Object=null )

Primitive Code

The carousel primitive was created by duplicating the Clickable Button Panel Primitive found in this blog and renaming the class and constructor function to Carousel. Then after adding the appropriate variables, the simple equation for a cylinder was used to place the primitives according to the angle and number created by the horizNum (number of images in a circular row).

var x :Number = myX*Math.cos(myThetaIs)+myZ*Math.sin(myThetaIs);

var z :Number = -myX*Math.sin(myThetaIs)+myZ*Math.cos(myThetaIs);

var y :Number = iy * iH -(textureY+myHGap/2)*(vertiNum/2-n);

var vertex:Vertex3D = new Vertex3D();

vertex[ “x” ] = x;
vertex[ “y” ] = y;
vertex[ “z” ] = z*10;

As the different x, y, and z values are created they are put into the vertex array just as was done in creating the clickable button panel. But notice the term vertex[ “z” ] = z*10; which has a multiplier of 10. This is an issue that must be investigated in the future.

The next issue was changing how the material was named. For the clickable button panel we used a matrix numbering scheme for the material name. We change this scheme when dealing with the carousel primitive to produce a sequential numbering system. This made the images easier to work with and the code is shown below.

var myNumber:Number= horizNum*n+m;
var myMaterial:String = “myMat”+myNumber;

Main Code

Since the carousel contains many images, we do not want to have to list them individually for the material list as we did in the Button Panel case. So we put the image address in a myBitmaps array and iterate through them as shown below to create the materials list.

var materialsList:MaterialsList = new MaterialsList();

for (var i:int = 0; i<myBitmaps.length; i++)
{

var myBitmapFileMaterial:BitmapFileMaterial = new BitmapFileMaterial(myBitmaps[i]);
trace(myBitmaps[i]);
myBitmapFileMaterial.doubleSided = true;

myBitmapFileMaterial.interactive = true;
myBitmapFileMaterial.name=”myMat”+i;

myBitmapFileMaterials.push(myBitmapFileMaterial);
trace(myBitmapFileMaterial.name);

}

for (var ik:int = 0; ik<myBitmaps.length; ik++)
{

materialsList.addMaterial(myBitmapFileMaterials[ik], “myMat” + ik);

}

This is a real time/code saver and can be used to bring in items from an external data base or xml page using HTTP Services.

The Big Problem

In Papervision, pixel measurements lose their meaning due to the 1/z parameter of perspective and as result you end up doing some adjusting. The is true for the carousel. If you change the gap or height components of the Carousel function you must readjust the following parameters to get the carousel to go to the correct image when clicking on it.

var myAdjustLift:Number=35;
var myAdjustHeight:Number=70;
var myLift:Number=myAdjustLift*(plane.vertiNum-1);
var myHeight:Number=myAdjustHeight*(plane.vertiNum);

The myLift parameter adjust the place where you enter the image close up and the myHeight parameter adjusts the individual column spacings entry point. Once you set the parameters above you can change row and column numbers without further adjustments. But if you change vertical gap or image height you need to readjust the parameters above.

There is a nonlinear equation that governs this behavior, but that is the subject of another post…

To see the full Carousel class click the more button below.

Read the rest of this entry »


Follow

Get every new post delivered to your Inbox.