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 »


Adding Simple Blender Models to CS4

December 27, 2008

Intro

One of my colleagues, Barbara Kaskosz just released a series of CS4 examples which I have been modifying to accept xml and blender models. Her examples can be found at

http://www.flashandmath.com/

Barbara is a gifted coder, great person, and real honor to know – adding to her work is a head-rush for me! Click on the image below to run the CS4 Blender example.

Extending Barbara's Simple 3D Draw

Extending Barbara's Simple 3D Draw

Above is an example of a Blender model created in my Blender XML exporter brought into Barbara’s 3D Draw program.

Web Stuff

Demo

Download Source Code

Discussion

Here are the steps I followed to enhance Barbara’s Simple 3D draw to accept Blender objects (this example does not included textured models I will be releasing that in an upcoming post).

  • I downloaded her code example Simple 3D Dynamic Drawing in Flash CS4 (use her Icosahedron example) and removed all the comments. The comments were great but they got in the way when I started to recode the example.
  • I then converted her timeline ActionScript code into a class package and ran it in Flex as an ActionScript Package. I’ve included that package in my download files.
  • Then I created a (non-textured) model in Blender and exported it using my XML Blender Exporter. I then placed that XML model file in Flex. (To learn how to model in Blender just click on my 3D modeling link in this blog. There are tons of getting started in Blender tutorials.)
  • Then I add the AS3 code needed to import the Blender XML model into Barbara’s Simple 3D program .

var externalXML:XML;
var loader:URLLoader = new URLLoader();
var request:URLRequest = new URLRequest(“testShip2.xml”);
loader.load(request);
loader.addEventListener(Event.COMPLETE, onComplete);

function onComplete(event:Event):void
{
var loader:URLLoader = event.target as URLLoader;
if (loader != null)
{
externalXML = new XML(loader.data);
setVertices(externalXML);
}else{

trace(“loader is not a URLLoader!”);

}
}

  • I then combined her setVertices() and setFaces() functions and placed an externalXML argument in the new combined setVertices(myData_xml:XML) function to bring in the XML data. I then split the CVS XML data into arrays and loaded the vertices and face indices XML data into Barbara’s vertsVec[i] and faceVec[i] vector arrays. In addition a scale factor was added to scale the Blender model.

private function setVertices(myData_xml:XML):void {
var mySlitVert:Array=
myData_xml.myPrimSet[0].myVertices.split(“,”);
var mySlitFace:Array=
myData_xml.myPrimSet[0].myFaces.split(“,”);

numVertices=(mySlitVert.length-1)/3;
var myScale:Number=40;
var i:int;
for(i=0;i<=numVertices;i++){
vertsVec[i]= new Vector3D(mySlitVert[i*3]*myScale,mySlitVert[i*3+1]*myScale,
mySlitVert[i*3+2]*myScale); }

numFaces = (mySlitFace.length-1)/3;
var j:int;
for(j=0;j<=numFaces;j++){
facesVec[j]=
[mySlitFace[j*3],mySlitFace[j*3+1],mySlitFace[j*3+2]];
facesColors[j]=Math.random()*0xffffff;
}
}

  • Finally, I added a color vector array and randomly populated it . The colors were then applied to the Blender model faces. Everything else was the same as Barbara’s code.

facesColors[j]=Math.random()*0xffffff;

Click the more button below to see the entire code and the Icosahedron class package.

Read the rest of this entry »


Google Map on a Papervision Primitive (in 6 lines of code)

December 16, 2008

Intro

Putting a Google map on a Papervision Primitive is extremely easy. All you need to do is to turn the map into a Movie (using the MovieMaterial class) and then place it on a primitive. It’s really that easy! You can do it in only six lines of code given below;

1. Turn Google Maps into a Movie

movie.graphics.beginFill(0xFFFFFF);
movie.graphics.drawRect(0,0,800,600)
movie.addChild(Application.application.map);
movie.graphics.endFill();
mat = new MovieMaterial(movie, false, true,true,new Rectangle(0,0,800,600));

2. Place that movie onto a primitive

sphere = new Sphere(mat, 600, 32, 32);

In this case, we use a sphere, but you can use any primitive you want. The results are shown in the image below;

Google Map on a Primitive

Google Map on a Primitive

Discussion

Open source is a counter-intuitive concept. The success of Google maps illustrates the point. After developing a robust interface which parsed terabytes of satellite imagery and road data – they just gave it all away. And what a success and what a great resource that helps so many.

About a year ago our group decided to enter this global freeway as well by giving all our development work away – everything we do of consequence goes up on Google code and Youtube. At first, it was just an experiment. We were small and had nothing to lose. What a surprise?

As a result, we gained more global advertisement than we could ever pay for. And the job offers started pouring in. But then something happened – we found that we loved doing it. Our hearts were blessed. We didn’t care about the money or notoriety. Jesus had it right … it was better to give than receive, and man doesn’t live by bread alone …

Open source is just great fun…which makes me think…

There must be a human mechanism in the brain that equates creativity (accelerated brain chemistry) and giving (or letting go). It makes sense, letting go allows the brain to free fall up. The brain knows it’s only temporary and will die (and most likely when) – it just wants to fly (I guess that’s why we like roller coasters – it’s a brain ride). Well anyway, it works for us – we’re tripping over ourselves trying to get the next innovation out the door – who would know.

Enough of my open source propaganda (just think about it) – let’s take a look at how this puppy was made.

Procedure

I think the most important blog you could look at on this subject is Path Finder Development by Sasha Dzeletovic. They did a Papervision Yahoo maps which is actually much more complicated than what you’ll see here. I had worked quite a bit with the Yahoo Flash API last year and was delighted when Google created one. The Google API seemed to have solved many of the problems that I was having using the Yahoo API.

The only code I really needed from Path Finder was the first six lines at the beginning of this post. Everything else was just simple Papervision and the Google Flash API. Many of the complications I had with the Yahoo API just went away using Google. The real key was just converting the Map into a movie using the MovieMaterial class and placing it on a primitive. Also, handling the map display container similarly to the Path Finder article gave me full interactivity with the map – double click zoom – mouse panning – maker interactivity – and that’s really cool!

The only issue I had was that for more advanced applications I had to reprogram the Google control interfaces. Which I had to do for my Wii controlled applications anyway … more on that in upcoming posts.

YouTube – How it was made


Download (Air Application)

http://flex3cookbook2.googlecode.com/files/googlemaps.zip

Click the more button below to see the full code listing of the Google Map Air Application.

Read the rest of this entry »


Creating a Simple Flash Particle Emitter

December 14, 2008

Intro

Particles are essential in 3D. They can be used to represent fire, smoke, water, a swarm of bees, or a flock of birds. But presently Papervision doesn’t have a well-developed particle system. In the book, we develop a number of classes to enhance Papervision’s particle framework.

Particles systems typically have the following properties;

  • New particles are generated from an emitter
  • Each particle has unique attributes
  • Particles have a life time (or designated space) and afterwards are removed or reused
  • Particles are governed by scripts (classes that determine their behavior)
  • Particles are rendered

But in Flash the best way to handle particle lifetime is to regenerate them when their life time is over.

Click the image below to see the program in action. The particle emitter will follow your mouse, respond to gravity, bounce off a floor 3 times and then be regenerated back to the mouse pointer.

There are a number of key concepts here and particles are discussed in detail in the book. In this post, we shall lightly touch on the important concepts and provide you with all the code.

Particle Emitter
Particle Emitter

Demo

http://www.professionalpapervision.com/demos/web/pemitter/

Download

http://flex3cookbook2.googlecode.com/files/particleEmitter.zip

Discussion

Here are the key concepts:

Emitter

Creating an emitter is simple – you just tell the particles where to be created. In the code, we generate them at the mouse pointer with a small variation on velocity.

myParticle.ypos = mouseY-vpY;
myParticle.xpos = mouseX-vpX;

 

myParticle.vx = Math.random() * 6 – 3;
myParticle.vy = Math.random() * 6 – 6;
myParticle.vz = Math.random() * 6 – 3;

Regenerator

When a particle has outlived its lifetime we regenerate it by sending it back to the source. As discussed in previous posts regenerating particles is preferable based on how Flash handles memory resources.

myParticle.ypos = mouseY-vpY;
myParticle.xpos = mouseX-vpX;

 

z-Sorter

Since we are dealing with multiple particles we must sort them based on z-position.

private function sortZ():void
{
myParticles.sortOn(“zpos”, Array.DESCENDING | Array.NUMERIC);
for(var i:uint = 0; i < nummyParticles; i++)
{
var myParticle:ParticleEmitter = myParticles[i];
setChildIndex(myParticle, i);
}

Velocity

Velocity was added by incrementing it in the onEnterFrame loop.

myParticle.xpos += myParticle.vx;
myParticle.ypos += myParticle.vy;
myParticle.zpos += myParticle.vz;

Gravity

Gravity is created by iterating the y-velocity. To get smoke you would just change the sign of the gravity term and iterate upwards.

 

myParticle.vy += gravity;

 

Bounce

When the particle exceeds the floor then bounce is created by reversing velocity and doing an decimal multiplication on velocity.

 

myParticle.bounceNum++;
myParticle.vy *= bounce;

In the example above, bounce is equal to -.6 which reverses the velocity and reduces it exponentially.

Perspective Scaling

Thales theorem is used for perspective scaling in the z-coordinates.

var scale:Number = fl / (fl + myParticle.zpos);
myParticle.scaleX = myParticle.scaleY = scale;
myParticle.x = vpX + myParticle.xpos * scale;
myParticle.y = vpY + myParticle.ypos * scale;

Primitive

Even though this is not Papervision, it demonstrates how a primitive is set up. But the physics is in the primitive but Papervision does not have a physics engine. So the big questions is where should the physics go. Should it go on the primitive or on the DisplayObject3D. In this case, it is on the primitive, but putting it on the DisplayObject3D gives you the advantage of have the physics on all objects …not just primitives … more on this later.

In our primitive we have four possible shapes and they are selected randomly and thrown onto the stage using the switch case.

The random selector is on the main program side given by

var myParticle:ParticleEmitter= new ParticleEmitter(10, Math.random() * 0xffffff, Math.round(Math.random()*3));

where Math.round(Math.random()*3 selects from four possible particles found in the switch case from 0 to 3 on the primitive side.

switch(switchNum)

{

case 0:

graphics.lineStyle(0);
graphics.beginFill(color);
graphics.drawRect(0,0,2*radius,2*radius);
graphics.endFill();

break;

case 1:

graphics.lineStyle(0);
graphics.beginFill(color);
graphics.drawCircle(0, 0, radius);
graphics.endFill();

break;

case 2:

graphics.lineStyle(0);
graphics.beginFill(color);
graphics.drawEllipse(0, 0, 2*radius, radius);
graphics.endFill();

break;

case 3:
graphics.lineStyle(0);
graphics.beginFill(color);
graphics.drawEllipse(0, 0, radius, 2*radius);
graphics.endFill();

break;

default:

trace(“warning – Particle material has no valid shape.”);

break;

}

}

To see the full source code click the more link below.

 

 

 

 

 

Read the rest of this entry »


Building a 3D Flash Engine in 19 Lines of Code

December 11, 2008

Intro

In this example, you’re going to build a 3D engine based on perspective scaling in 19 lines of code. Before Flash 10 there was no native support for 3D and all you had were x and y coordinates to play around with. So you needed to add another dimension to get 3D – a z-axis. So the trick to creating a z-axis was to use perspective scaling. Which means that as an object moves away from you it gets small and as it moves towards you it get larger. But we need to quantify this idea (make some math out of it) so we can program it. And that comes from Thales Theorem.

Thales Theorem

Imagine that you are in your home looking out the window. As you approach the window objects outside look larger and as you get farther away from the window objects outside look smaller. Your distance from the window is called your focal length (fl), the window is your projection plane (or viewport), and your eye is the vanishing point.

Now don’t move – this fixes your focal length – and watch outside as objects move closer to and farther away from your window. As a bird flies closer to the window it looks larger and as it flies away it looks smaller. This is your z-axis – the distance between the outside object and your window pane. And the equation that governs the behavior that you see is given below;

sizeRatio = size/SIZE = fl/(fl + z)

where your sizeRatio equals “one” when your outside object is at the window and “zero” when your object (bird) flies far away (off to infinity). This equation works and is illustrated in the graphic below as a Blender monkey peering at a projection plane.

Application of Thales Theorem

Application of Thales Theorem

Z-Sorting

When dealing with multiple objects that overlap, perspective scaling alone is not enough. In the Flash Player you need to z-sort. This is even an issue with Gumbo (Flex 4). When creating a 3D carousel for example you need to z-sort the objects as they spin to put the closest one on top of the stack. The technical name is transposition and in AS2 it was easily accomplished using the swapDepths method. But in AS3 it is a little more complicated.

In AS3, the display list functions as an array and each display object has an index. The index start at zero and goes up to the number of objects on your stage where index zero is the bottom object. So since the display object is a child you can change its position using the setChildIndex method.

Since all your objects are in an array, you can sort that array by z and then set the indices of your array objects based on z. And that’s how it is presently done! Here’s a sort code snippet that illustrates the concept

private function sortmyZ():void
{

myObjects.sortOn(“myZvalue”, Array.DESCENDING|Array.NUMERIC)
for(var i:uint =0; i<numObjects; i++)

{

var myObject:MYObject3D = myObjects[i];
setChildIndex(myObject, i);

}

}

The code snippet sorts the objects in reverse numerical order from high to low based on the myZvalue of your objects. Thus, the objects further away from your projection plane get a lower index value placing them on the bottom of the stack.

This method will need to be called each time your 3D engine iterates the position of your objects. Typically this occurs on an onEnterFrame event.

With that said, you’re now ready to build your3D engine.

3D Flash Engine in 19 Lines of Code

Here is the Demo, Download, Youtube, and Discussion.

Demo

http://www.professionalpapervision.com/demos/web/flash19engine/

Download

http://flex3cookbook2.googlecode.com/files/engine3D19lines.zip

Youtube: How it was made


Discussion

Here are the steps for creating the program:

1. Start by importing the Sprite class; this is where you are going to draw a ball that you will animate in 3D.

import flash.display.Sprite;//imports sprite class

2. Next declare your variables zposition, Angle, and focal length.

var zposition:Number = 0;//z postion
var myAngle:Number =0;//Angle of myBall
var fl:Number = 250; //focal length

3. Next create your ball and add it to the stage.

var myBall:Sprite = new Sprite();//instantiates myBall sprite
myBall.graphics.beginFill(0xFF0000);//Assigns a ball color
myBall.graphics.drawCircle(0, 0, 40);//draws your ball at (0,0)
myBall.graphics.endFill();//ends the fill
addChild(myBall);//adds the ball to the stage

4. Next create your onEnterFrame listener which loops through your equations of motion. This is the heart of all 3D engines.

addEventListener(Event.ENTER_FRAME, onEnterFrame);//loops equations

5. Finally, create the function that will be looped. These are your equations of motion which govern the perspective as it is changed and converts 3D to 2D (or projects onto the viewport).

function onEnterFrame(event:Event):void{
var scale:Number = fl / (fl + zposition);//scale perspective
myAngle=myAngle+.1;//iterates angle
if(Math.abs(myAngle)>=20) myAngle=-myAngle;//change sign
myBall.x = 300*Math.sin(myAngle)*scale+300; //ball orbit x
myBall.y = 300*Math.cos(myAngle)*scale; //ball orbit y
myBall.scaleX = scale;//scales perspective in x
myBall.scaleY = scale;//scales perspective in y
zposition = myAngle*100;} //increments z

Though this is not Papervision it illustrates a number of elements that every 3D engine possesses;

  • a frame looper/renderer
  • perspective (z-coordinate)
  • projection onto a viewport
  • primitive or basic shape
  • addition of a color (or material)

And all of this in just 19 line of code. If only it would have stayed this simple. Papervision started off with only 20 classes, now it is in the hundreds and growing. But as they say, no pain no gain.

Click more below to see the paste-able code. Just cut and past the code below into flash and watch the magic of perspective occur.

Read the rest of this entry »


34 Papervision Legacy Examples

December 10, 2008

A while ago 34 Papervision examples were moved from the AS3  examples folder of Papervision (they were moved to as3 > tags > 1_7 > examples – see villmer’s comment below). I’m assuming this was done to  remove legacy code. Some of the examples are dated and need to be streamlined, but many are still somewhat instructive. So I’ve zipped them and put them on my book’s site for you to download. The image below names the available examples.

34 Papervision Legacy Examples

34 Papervision Legacy Examples

To download the 34 Papervision Legacy Examples click here or try the direct link below;

Direct Link

http://www.professionalpapervision.com/demos/code/legacyexamples/legacy34examples.zip

The swfs in the individual folders are functional. So if you click on them they should run (given that you have flash installed). Also, I have included the src folder which contains the legacy version of Papervision used to create these examples. It amazing how much Papervision has changed over the past year. But more change is on the way.

The Papervision team is in the process of writing PapervisionX (the Flash 10 compatible version of Papervision). Once that is completed the examples above will be totally obsolete, but for now you might find them useful.


New Blender XML Exporter/PV3D XML Primitive

December 9, 2008

Thanks to Dennis Ippel

Many thanks to Dennis Ippel whose creation of the AS3 Blender exporter made my creation of the XML Exporter and XML Papervision Primitive possible (or at least infinitely easier). This is an iteration of his work. Essentially, I rewrote his Python AS3 Exporter to export XML from Blender and then created a Papervision XML Primitive which uses that XML. Links for the XML Exporter and Primitive are given in this article.

Intro

At first glimpse you might be wondering, why would you need an XML exporter for Blender and Papervision XML Primitive?

And there are actually two answers to this question. First, Blender doesn’t have a handy exporter for Papervision. It presently exports to Actionscript (to find out more check it out here ) So, creating an exporter that exports to XML gives you the ability to pick that XML up into an XML primitive. Presently, primitives are created mathematically in Papervision. By using an XML Primitive you can make any object in Blender and use it like a primitive in Papervision. Just by dropping its XML file (and image if textured) into Papervision.

The XML Primitive is simple; it just references the XML file and color or image (if textured) as shown below. All the properties of Papervision primitives apply to it such as translation, rotation, and scaling.

myWidget = new XMLPrimitive(“Widget.xml”, color or bitmap asset);

The second purpose is to create a mechanism for saving and using box models created in Papervision. That’s right you’re going to box model in Papervision.

Click on the image below to see the physics roller in action.

String Roller for Physics Lab

String Roller for Virtual Physics Lab

In the YouTube below, I demonstrate how to use the exporter and xml primitive and discuss how they were made.

YouTube Video – Development and How to Use

How it was made

How to use it

Demos

Demo 1 Widget with Color (no Texture)

Demo 2 Ship with Texture

Downloads

Demo 1 Widget with Blender File (Flex and Flash Code)

Demo 2 Ship with Blender File (Flex and Flash Code)

XMLExporter/XMLPrimitive

Discussion

This xml exporter/primitive was originally made to create widgets for a series of virtual physics experiments at NKU. Creating the widget above using the xml exporter has streamlined the process of making these widgets. There are two ways to create these primtives – textured and untextured.

Two Ways (Textured and Untextured)

Note: Presently the XML Primitive does not except shaded materials. Only untextured and textured primitives created in Blender are allowed.

There are two ways to get a XML primitives out of Blender – textured and untextured. Demo 1 above is the untextured way (but you can still give it a color using the color material) and demo 2 is the textured primitive. An example of a texture object is given below. And if you want to learn how to texture an object in Blender watch the following two videos.

UV Mapping (Texturing an object in Blender)

Part 1 – UV Mapping
http://www.youtube.com/watch?v=gxSXp-vGyV8

Part 2 – UV Mapping
http://www.youtube.com/watch?v=gCNJtSNWXgM

Following the procedure above you can create an object and put a texture on it for XMLExport. You can click the image below to see an animated example of and XML exported primitive. The image below shows a textured ship on the left and its texture map on the right.

Putting a Texture on a Ship

Putting a Texture on a Ship

Important: But regardless of which XML primitive you use (textured or untextured) you must triangulate your object in edit model by pressing Ctrl+t or your objects will have triangular holes in them. An example of the XML generated by the XMLExporter is given below

Installing the Exporter/Primitve

Unzip the exporter/primitive found here

and place the XMLExport python file in the following scripts directory

  • Windows: /Blender Foundation/Blender/.blender/scripts/ (Blender .2.46: C:\Documents and Settings\<username>\Application Data\Blender Foundation\Blender\.blender\scripts)
  • Mac: /Applications/blender/blender.app/Contents/MacOS/.blender/scripts/

then place the XMLPrimitive in the primitive Papervision folder found in the following directory

org/papervision3d/objects/primitives

and that’s it. You are now ready to make an XML Primitive in Blender. Just reference this exported file in your XMLPrimitive as show below and add a color or bitmap depending on if your Primitive is textured or not.

//Use a color for an untextured primitive
var paper2:ColorMaterial = new ColorMaterial(0xFFFF00,1,false);
paper2.doubleSided = true;

//Use a bitmap for an textured primitive
bitmap=new BitmapFileMaterial(“crusor_Cylinder.jpg”);

//Reference the XML generated file and your texture or color
mcylinder = new XMLPrimitive(“Widget.xml”,paper2);

An example of the type of export code you will be seeing is given below.

XMLExporter Code

The XML generated for this primitive is shown below;

<?xml version=’1.0′ encoding=’utf-8’?>
<myData>
<myPrimSet>
<myVertices>
0.707107,-0.280624,0.707107,0.965926,…
</myVertices>
<myFaces>
24,0,1,24,1,2,24,2,3,24,3,4,…
</myFaces>
<myParams>
0.000000,0.000000,0.000000,…
</myParams>

</myData>

To see the code for the Python exporter or XML Primitive click the more button below;

Read the rest of this entry »


Follow

Get every new post delivered to your Inbox.