SQL Data Base in Flash Builder – in 5 lines

December 27, 2009

Intro

If there is one single reason that I’ve stuck with  (Flex 4 now) Flash Builder it’s the ability to auto-generate data base code. In the five part video tutorial series below I demonstrate how to create a complete CRUD SQL database system in Flash Builder…only writing 5 lines of code…the rest is auto-generated.

Of course…why do I care…the goal is to build a 3D learning management system…we’ve got the 3D down…time to bring in the data!!!

Videos

SQL Data Base in Flash Builder – in 5 lines (1 of 5):
http://www.youtube.com/watch?v=x-Da1SD1Ykk

SQL Data Base in Flash Builder – in 5 lines (2 of 5):
http://www.youtube.com/watch?v=1j8A-XxrG8Y

SQL Data Base in Flash Builder – in 5 lines (3 of 5):
http://www.youtube.com/watch?v=TsHdOgxHe2U

SQL Data Base in Flash Builder – in 5 lines (4 of 5):
http://www.youtube.com/watch?v=7jY6rl3rdGk


SQL Data Base in Flash Builder – in 5 lines (5 of 5):
http://www.youtube.com/watch?v=ZJGZFufl4Mk

Source Code

Source Code: http://lv3d.googlecode.com/files/DataBasingFB.zip

Hope this helps someone…it was fun to make…

Best Regards,
Mike


Putting 3D Google Maps on the Web (using Flash 10)

April 18, 2009

Intro

To this point, I’ve been putting Google Maps into Air applications due to the Flash Sandbox issue encountered in PV3D (discussed in a previous post). But in CS4, guess what, it’s not an issue. They go right on the web as you can see from the demo below:

Google Map in 3D on the Web

Google Map in 3D on the Web

Demo

Source

Discussion

Now here is how you do it, and it’s so simple you will not believe it. Use the code below to put your map into a movie where it’s free to move freely in 3D.

movie.addChild(map);

Placing a Google Map on a CS4 Plane is easier in Flex 4 (Gumbo) than it is in PV3D. All you do is throw your map into a movie clip using the code below, and then center it to get your map pivot right. The code snippet below sets your map in a movie clip, centers its pivot, sets map controls, places your movie in a Flex canvas, and centers your movie on the stage.

//Place your map in a movie so you can position its pivot
movie.addChild(map);

//Set your map pivot
map.x=-map.width/2;
map.y=-map.height/2;

//Add Map Controls
map.addControl(new ZoomControl());
map.addControl(new PositionControl());
map.addControl(new MapTypeControl());

//Put your movie in a Flex Canvas
mapHolder.rawChildren.addChild(movie);

//Center your Movie
movie.z=0;
movie.x=450;
movie.y=300;

The map also has two additional Flex components; a button, which stops it from spinning and a slider, which adjusts its speed and direction of rotation.

This is the great power of CS4 over PV3D. You can now bring native Flex components into your 3D environment in conjunction with your 3D objects. Bringing Flex components into PV3D is a difficult task and requires the use of the draw BitmapData feature. But with CS4 it occurs natively, and those components can be manipulated in 3D as well.

Hey that’s it, how crazy can that be! And all the controls and buttons are fully functional and in the right place.

Note: You could have just rotated the map directly, but you put it in a movie to control positioning and its pivot point.

The rest of the code is shown in the link below and discussed in greater detail in Chapter 7 of the book.

Read the rest of this entry »


Animating Multiple Pixel Bender Lights

March 21, 2009

Intro
Having multiple lights in PV3D is a desired effect. But after going through the lightmap classes, let me say that it’s impossible without an major rewrite. But with Pixel Bender all you do is add another term to your pbk filter…let’s do it!

Animating Pixel Bender Lights

Animating Pixel Bender Lights

Demo

Source

Discussion

It’s an amazingly simple process. Just add another term to your pixel bender light equation as shown below:

Adding Multiple Images to PV3D

Adding Multiple Images to PV3D

The example above only shows two lights, but you can have as many lights as you want just by adding additional light terms:

The pixel bender code looks like this

float2 outcoord = outCoord();
float attn = (brightness1/((distance(outcoord, center1)+radius1)))+(brightness2/((distance(outcoord, center2)+radius2)));

dst = attn* sampleNearest(src, outcoord);
dst.a=1.0;

Wow, only five lines of code to have multiple light sources – get out of here!

Animating Your Sources

Once you’ve set your shader up then animating it is pretty easy. If you aren’t sure how to set up your shader for animation, check out Lee Brimlow’s video on animating shaders. I do it a little differently than Lee, but not by much. Here are the steps for animating the lights:

  1. Increment your oscillation parameter osc++
  2. Calculate sine and cosine based upon your incremented osc
  3. Update your light positions
  4. Apply the update to your image

The fully documented code is shown below:

private function loop(e:Event):void{

//Increment your oscillation parameter
osc++;
//Calculate sine and cosine
var cos:Number=150*Math.cos(osc/10);
var sin:Number=150*Math.sin(osc/10);
//Update your light positions
shader.data.center1.value = [sin+400, cos+180];
shader.data.center2.value = [cos+200, sin+180];
//Apply the update to your image
image.filters = [filter];
//Rotating your image holder
holder.rotationY+=.25;
}

If you are aware of how hard this is to do in PV3D, you’re going wow…tell me more…and we will…

For the entire source code download the source above, or check out the link below:

Read the rest of this entry »


Adding Pixel Bender to Papervision3D

March 20, 2009

Intro

One of the things which I abhor about modeling in Papervision3D is texture baking. And if you’ve been in the business as long as I have you know why…it’s a labor intensive nightmare…and you can’t ever get it right. But with pixel bender you don’t have to bake your textures anymore and you can adjust your parameters dynamically using ActionScript.

Dynamic Shading using Pixel Bender

Dynamic Shading using Pixel Bender

Demo

Source

YouTube http://www.youtube.com/watch?v=i8BnSqf0Z_g

Discussion

Adding Pixel Bender to Papervision3D was a three step process:

  • Creation of a Pixel Bender Filter
  • Creation of a Pixel Bender Bitmap File Material Class
  • Creation of a Pixel Bender Bitmap Material Class
Adding Pixel Bender to PV3D

Adding Pixel Bender to PV3D

Before you start coding. Make sure you’ve switched to the Flash 10 player!!!

Step 1: In the previous post several pixel builder filters were presented.

Pixel Bender Filters and Algorithms

To create a dynamic light baker filter the simple light filter was modified by throwing out all the pow and exponent methods. The big trick is that exponential behavior can be mimicked by using inverse of distance –now that’s a processor saver. The final algorithm use is shown below:

lively3d Light Source for Texture Baking

lively3d Light Source for Texture Baking

The pixel bender algorithm is easily implemented using the code below:

float2 outcoord = outCoord();
float attn = (brightness/((distance(outcoord, center)+radius)));

dst = attn* sampleNearest(src, outcoord);
dst.a=1.0

In addition to the modification mentioned above the alpha component is split off and set to one. This keeps the images from losing its alpha as you reduce brightness.

Step 2: Next you must create a Pixel Bender Bitmap File Material Class. This is simply done by making a copy of PV3D’s BitmapFileMaterial class and renaming it BitmapBendMaterial class and after changing the constructor and class names extend this class by the BitmapPixelMaterial class.

BitmapBendMaterial extends BitmapPixelMaterial

You’ll now create the BitmapPixelMaterial class.

Step 3: Make a copy of the PV3D BitmapMaterial class and name it BitmapPixelMaterial. Add the appropriate import statements and the pbj and image embed methods and create a shader as shown below:

[Embed (source=”filters/livelyLight.pbj”,
mimeType=”application/octet-stream”)]
private var ShaderClass:Class;

[Embed (source=”assets/images/gainesHouse512.jpg”)]
private var myImage:Class;

private var shader:Shader

Next incorporate the code to get your shader and image working together:

shader = new Shader(new ShaderClass());
shader.data.center.value = [400, 306];
shader.data.brightness.value = [150];
shader.data.radius.value = [100];

var image:Bitmap = new myImage();
image.filters = [new ShaderFilter(shader)];
shader.data.src.input = image.bitmapData

Finally you must change your fill method to a shader fill method with a matrix method

graphics.beginShaderFill(shader,_localMatrix)

That’s it! To check out the wrapper code download the source or click the more button below:

Read the rest of this entry »


Flex 4 (Gumbo) Fire Video on the Supper Club

March 13, 2009

Intro

Our group just finished the first part of the Beverly Hills Supper Club project. I realize that this is a sensitive area and lives were lost. The completed site will be a memorial to those loved ones that were lost in this tragic fire.

Here I demonstrated playing the Supper Club fire video on the Blender building skin. To see the demo just click the image below (drag the building with the mouse to rotate it and click the play video button to get the video to play):

Supper Club Video on a Blender Model

Supper Club Video on a Blender Model

Demo

Code (Only MXML File – Video too large for Google Code)

UTube

Discussion

It’s pretty easy. Just follow the posts below which explain everything in detail:

1. Learn about netStream and netConnection

Adding Video to a Papervision3D Curved Plan

2. Learn about using video in CS4

Putting Video on a CS4 (Flash 10) Primitive

3. Learn how to build a CS4 shaded model using drawTriangles

CS4 Flat Shaded Tie Fighter with drawTriangles

4. Learn about Light in Papervision3D

Adding Brightness to PV3D Light Source

5. Learn how to model in Blender

3D Modeling

6. Learn how to export your Blender models to Papervision3D and CS4

New Blender XML Exporter/PV3D XML Primitive

The big trick to this is to create a simple parameter that allows you to switch between the shaded model and video within the triangle creation loop.

playMyVideo = false or true;

Run Shade Code if false

….

Run Video Code if true

}else{

var vertices2:Vector.<Number>=new Vector.<Number>();
vertices2.push(dispVec[facesVec[curFace][0]].x, dispVec[facesVec[curFace][0]].y);
vertices2.push(dispVec[facesVec[curFace][1]].x, dispVec[facesVec[curFace][1]].y);
vertices2.push(dispVec[facesVec[curFace][2]].x, dispVec[facesVec[curFace][2]].y);

//Draw Video into Bitmap
bitmapData.draw( this.myVideo);
this.myVideo.attachNetStream ( this.myStream );

spObjImage.graphics.beginBitmapFill(bitmapData,null, false, false);
spObjImage.graphics.drawTriangles(vertices2);
spObjImage.graphics.drawTriangles(vertices2)

}

Another trick is handling rotations correctly. To do this you need to use subtraction of your previous position from you present position (since you are appending rotation in this example). So if you are rotating forward the difference is positive and if backwards the difference is negative.

private function boardMove(e:MouseEvent):void {

var locX:Number=prevX;
var locY:Number=prevY;
if(doRotate){
prevX=spBoard.mouseX;
prevY=spBoard.mouseY;
rotateObj(prevY-locY,-(prevX-locX),0);
e.updateAfterEvent();

}

Once you “get this in your head” you’ll undertstand “append” rotation in CS4 – otherwise it’s uncontrollably wild.

Now there’s on more “Super trick”. This application was originally created for an Adobe Air and was run on the desktop. So when you put it on the web the video will not work since it uses

spObjImage.graphics.drawTriangles(vertices2)

looks like a terrible sandbox issue, but wait a second didn’t we get video on a prim in the previous post on Putting Video on a CS4 (Flash 10) Primitive…

Yes we did???

But this time we don’t have indices and uv data … shouldn’t we just give up or get some expert to tell us what to do…nah, just replace indices and uv data with null and it works…please don’t ask me why. Remember, I said this was a trick.

spObjImage.graphics.drawTriangles(vertices2, null, null,TriangleCulling.NEGATIVE);

And Tada, video on the Supper Club.

Remarks

The full project will allow site visitors to leave messages in supper club rooms…building a flexpress flat-file data base to handle these messages is part of the TEI project… The advantage of the flat-file data base is that you can drop the program onto any server – hassle free and it works – no fancy install!

To see the entire code click the more button below:

Read the rest of this entry »


Flex 4 (Gumbo) Image Ball – Ouchies!

March 12, 2009

Intro

Flash & Math had created a really cool image ball in Flash, but I needed it in Flex 4 (Gumbo) for a project. So I ported it over. The port was non-trivial so I’ve included it here with its source code. The big thing about having it in Flex (MXML & ActionScript) is that I can now drag the Flex components in and use them to harness data. Click the image below to see the demo.

Flex 4 (Gumbo) Image Ball

Flex 4 (Gumbo) Image Ball

Demo

Code (MXML Flex File Only Images too Large and some Copyrighted)

Discussion

Here are the highlights which got me stuck on the port (got an “Ouchie” from each one) .

Note: the code from Flash & Math is thoroughly documented so make sure you download and go through it to follow along).

Ouchie 1: Not so much of an ouchie if you know this one already (and I did), but you can’t use addChild to add a sprite directly to the stage of a Flex MXML project. So create a canvas and add your sprite to that canvas using rawChildren.

cs4Canvas.rawChildren.addChild(board);

You can even use mutliple canvas components (or other containers) – and I did.

Ouchie 2: Flash & Math pulls their thumb nail image assets from the Flash library using linkage. You can’t do that in Flex, so use the embed tag for the thumb nails (all 46 of them – ouchie, ouchie, ouch).

[Embed(source=”thumbs/pic1.jpg”)]
private var Small1:Class;

But now the setUpPics() method won’t work, so use the BitmapAsset class in your thumbnail array.

thumbsArray[0]=[new Small1() as BitmapAsset];

And place your embed class in for their movie class.

Ouchie 3: Rewrite the Vector array declarations using a push method to load the vector arrays-their method of loading these arrays doesn’t work in Flex (and figuring that one out was a big ouchie).

thetaStep.push(0,60,36,30,36,60,0);
jLen.push(1,6,10,12,10,6,1);
phiTilt.push(-90,-60,-30,0,30,60,90)

But fortunately, it’s really easy to implement.

Ouchie 4: Just as with a formal class structure, you must make sure that your variables have the private statement in front of them, and that all declarations are contained in a function (within your script tags). In addition, you must create an init() method and call it from your MXML tags (this acts like a constructor function).

<mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml&#8221; creationComplete=”init()” layout=”absolute”>

Ouchie 5: I added image forward and backwards buttons to the program so once the user double clicks a thumbnail image, he/she can surf the images without going back and forth between image and image thumbnails (this is a big improvement to the code).

This required that I write a small string routine that extracted the numbers from the image name so I could start at that image and go sequentially

var myStringIs:String = picsArray[i][j];
myStringIs=myStringIs.split(“.”).join();
myStringIs=myStringIs.split(“c”).join();
splitArray=myStringIs.split(“,”);
stringNumIs=Number(splitArray[1].toString());

The move forward and backward code for the buttons is given by

private function moveForward(e:MouseEvent):void {
stringNumIs++;
stringNumIs=stringNumIs%47;
if(stringNumIs==0)stringNumIs=1;
loader.load(new URLRequest(“images/pic”+stringNumIs+”.jpg”));
}

private function moveBackwards(e:MouseEvent):void {
stringNumIs–;
if(stringNumIs==0)stringNumIs=46;
loader.load(new URLRequest(“images/pic”+stringNumIs+”.jpg”));
}

This small routine could definitely be improved upon…but it does the job..

Big Problem
Of course the big problem here is that your images have to be sequentially numbered, that’s a big ouchie, and is unacceptable for future projects: I need descriptive names. I can’t remember which image is which, nor can you…

But my timeframe was so short on this project (of which this was a small piece) that I just had to live with it. But a little recoding is needed here to fix this problem…I would treat it as a particle system.

Conclusion
So the port was a little bit “hurtie…ouch, ouch, ouch.”. It took me about 4 hours to complete, but once completed, it worked great and integrated smoothly into the rest of my application.

Hope this saves you some time…or a few ouchies…

Click the more button below to see all the code and a short tutorial on substrings from flepstudio.

Read the rest of this entry »


CS4 Flat Shaded Tie Fighter with drawTriangles

March 1, 2009

Intro

Here’s a CS4 Flat Shaded Tie Fighter. I built the tie fighter in Blender, and used drawTriangles to render the model in CS4. The shaders come directly form Ralph Hauwert’s fast light maps … thanks Ralph. Here I only treat flat shading, but in the book (and its website). I treat the rest of them: cell, gouraud, phong, and envmap.

Since I’ve treated bringing Blender and 3DSMax models into CS4 ad nauseum, I won’t belabor the point. This program culls, has its own light class with brightness (here it alternates in brightness), depth sorts, and displays concavity with no problems.

The perlin noise clouds came from flepstudio … thanks flepstudio!

CS4 Flat Shaded Teifighter drawTriangles

CS4 Flat Shaded Tiefighter using drawTriangles

Source

Demo

YouTube

Discussion

Here’s a brief explanation of flat shading in CS4.

The light class is a point light with brightness (contained in the org/lively3d/lights/ folder of your download). It gives you the position of your light source, brightness, light color, ambient color, and specular level.

Here’s the Hack

The lightColor variable is the color of your light source. The ambientColor variable is not true ambient light. It’s the first and second parameter in a gradient fill (the third one is your light color), and it governs the color that your object will take on. The specularLevel variable adjusts the number of shades between your middle ambient color and light color. And gives the appearance of making your surface shiny at low numbers-hey, it’s a great hack!

Here’s how the gradient fill works:

The beginGradientFill method has several parameters but only the ones used here are listed below: type, color, alphas, ratios, and matrix.
beginGradientFill(type, colors, alphas, ratios, matrix)

They do the following:

  • type-specifies which gradient type to use: linear or radial
  • colors-an array of color values used in the gradient
  • alphas-an array of alpha values corresponding to the colors
  • ratios-defines the percentage of the width where the color is sampled at 100%.
  • matrix- a transformation matrix which controls scale, skewing, and location of your gradient appearance.

Here’s how the light map is implemented:

A bitmapdata object is created named tempmap which is just a simple strip 255 pixels long and 1 pixel wide, the gradient is calculated using the ambient and light colors, and the gradient is drawn into the tempmap and returned.

The process described above is demonstrated in the code below, which comes from Ralph Hauwert’s LightMaps class and is used to create the light maps for flat, cell, phong, and gouraud.

var tempmap:BitmapData = new BitmapData(255,1,false,0);
var s:Sprite = new Sprite();
var m:Matrix = new Matrix();
m.createGradientBox(255,1,0,0,0);
s.graphics.beginGradientFill(GradientType.LINEAR, [ambientColor,ambientColor,lightColor],[1,1,1],[0,255-specularLevel,255],m);
s.graphics.drawRect(0,0,255,1);
s.graphics.endFill();
tempmap.draw(s);
return tempmap;
Now that you understand how a simple light map is created the steps to creating a flat shade are easy:

Step 1: Create your light map

_colors = LightMaps.getFlatMapArray(lightColor, ambientColor, specularLevel );

Step 2: Return a cosine (zd) from the dot product of your light vector with your triangle normal vector. This gives the cosine of the angle of your triangle face normal to your light source. If your light source is at 90 degrees to your object triangle (no light hitting it) then the cosine value (zd) is zero. If your triangle is directly facing the light source then your cosine is 1 (completely lit).

AVect[0]=new Vector3D(dispVec[facesVec[curFace][0]].x,dispVec[facesVec[curFace][0]].y,dispVec[facesVec[curFace][0]].z);
AVect[1]=new Vector3D(dispVec[facesVec[curFace][1]].x,dispVec[facesVec[curFace][1]].y,dispVec[facesVec[curFace][1]].z);
AVect[2]=new Vector3D(dispVec[facesVec[curFace][2]].x,dispVec[facesVec[curFace][2]].y,dispVec[facesVec[curFace][2]].z);

AVect[3]= AVect[0].subtract(AVect[1]);
AVect[4]= AVect[1].subtract(AVect[2]);

AVect[5]=AVect[4].crossProduct(AVect[3]);
AVect[6]=new Vector3D(light.x, light.y, light.z);

var mag1:Number=AVect[5].length;
var mag2:Number=AVect[6].length;

var zd:Number = AVect[6].dotProduct(AVect[5])/(mag1*mag2);

In CS4, you totally eliminate Papervision’s Numbers class since all the calculations provided by that class are now internal to CS4.

So for example a dot product of two matrices in CS4 is given by

var zd:Number = AVect[6].dotProduct(AVect[5])/(mag1*mag2);

Step 3: Calculate the index value from your zd by multiplying it by 255 (hex 0xff) and grab the respective color from your “_colors” array. Essentially as your triangle turns away from your light source the hex value is reduced: effectively darkening your pixels.

zAngle = zd*0xff; //0xff if hex for 255
currentColor = _colors[zAngle];

Step 4: Render your triangle and fill it with your calculated light map color.

spObjImage.graphics.beginFill(currentColor);
spObjImage.graphics.drawTriangles(vertices);

The code above uses drawTriangles exclusively, where PV3D draws individual lines. The big advantage here is that you can make the triangles blow up – can’t wait to show you that!!! And theoretically, it should be faster than PV3D.

Figure 4-4 The Four Steps to Flat Shading

Figure 4-4 The Four Steps to Flat Shading

This probably seems like a lot to absorb, but the good news is that the rest of the shaders follow pretty much of the same process (with the addition of a few matrix methods).

To see the complete code download the source above or click on the more button below:

Read the rest of this entry »


CS4 (Gumbo) Molfile Molecule Viewer Sem#4

February 24, 2009

Intro

This is seminar #4, of a series of free seminars given this semester at NKU on Papervision3D and CS4. It demonstrates how to create a molfile molecule viewer in CS4 (Gumbo). Click the image below to see a demo.

CS4 Molecule for a Molfile

CS4 Molecule from a Molfile

Source

Demo

YouTube

Discussion

This is now my second version of a 3D molecule viewer. The first version was written in Papervision3D and was about 1400 lines of code and required that you rewrite the molfile into xml, and didn’t show bonds. This version is in CS4 (Gumbo or Flex 4) and is only about 350 lines of code, has bonds (single, double, triple, aromatic) and parses the molfile directly.

It took me a day to write this application(from 4 to 11), and that was with breaks: playing with the kids, gym, Shakespeare club, an ice cream float party, and several episodes of Hawaii-5-0 and Enterprise. Yeah, this is the life!

Molfile Parser

Parsing the Molefile was much easier than I thought it was going to be. Here is how you do it:

  • You just bring the molfile into Flex 4 using http services command (just as you would an XML file but with no e4x format)

<mx:HTTPService id=”molService” url=”assets/0420.mol”
result=”initMoleFile(event)” />

  • Then you convert it to a string, take out the special characters, split the contents, stuff it into an array, and remove all empty array elements.

// Convert to string
myString=molService.lastResult.toString();

//Remove special characters
myString = myString.split(“\n”).join(” “);
myString = myString.split(“\r”).join(” “);

//Stuff into an Array
myArray = myString.split(/ /);

//Filter out bland array elements
myArray = myArray.filter(filterMe);
function filterMe(element:String, index:int, array:Array):Boolean{
return (element != “” ); }

  • After you’ve stuffed your molefile into an array, you need to know where to go in that array so you can start counting off the data elements.Where do you go? Go to the version number of the molfile. So run a forEach and grab it’s index value.

myArray.forEach(myStart);

function myStart(element:String, index:int, array:Array):void{
if(element == “V2000″||element == “V3000”){
myStartVert=index;}

The index value of the version number is the heart of your molfile parser. Above we allow for versions V2000 or V3000. This index value will take you to any piece of data that you need in order to display your molecule. From this point on, its just a big counting game, everything is referenced to your version index value.

Atom File

To display your model you need an atom shape that can change size, color, and fill based upon the atom type.

The atom color, type, and radius were previously handled in an earlier version of the molecule viewer, created in Papervision3D (video, source).

And the atom shape and fill were handled in a previous post in this blog on 3D Lines in CS4 using drawPath.

By combining these two programs you can come up with a suitable atom. To do this:

  • Place the atom switch case from the PV3D Viewer into the Ball class created in the 3D Lines post, then change the ball class to Atom along with its constructor and class names.
  • In the switch case change the myColor value from grabbing a jpg to equaling a color value for all possible atoms:

case “H”:
//myColor = “colors/white.jpg”;
myColor = 0xffffff;
radius = 25;

  • In the Constructor function change it to receive only one parameter type, which is the letter of your atom: H, C, O…

public function init(type:String):void{…

  • Finally, change the fill method to gradient fill so your atoms looks cool.

graphics.beginGradientFill(myType, [myColor, 0x000022],[1,1], [1, 40]);

Now that your atom subclass is completed, it’s time to start building molecules.

Creating Molecules and Bonds

There are two parts to creating molecules: placing atoms in 3D, and creating their bonds. The first part of a molfile gives you the atom position values, and the second part give the bond relationships (which atoms are connected to which) and types.

Placing Atoms

Essentially all you have to do is replace the random placement of circles from the post on drawPaths to the atomic positions found in your molfile.

atom.xpos = myArray[myStartVert+1 +j*16] * myScale – offsetx;
atom.ypos = myArray[myStartVert+2 +j*16] * myScale – offsety;
atom.zpos = myArray[myStartVert+3 +j*16] * myScale – offsetz;

myHolder.addChild(atom);

You get to those positions by counting 1 position forward for x, 2 for y, and 3 for z, from the version number index, as shown above.

The offset is just an average of the molecular positions and gives you the ability to spin your molecule around its center. Everything else pretty much follows what was done in the drawPaths post.

Creating Bonds

Creating bonds is easy as well, with one big conceptual change from the drawPaths post. Double processing is eliminated by just duplicating the atom and placing it into a marks array. The lines follow the duplicated atom in the marks array and the other atom which exist in the atoms array are used for sorting.

atoms.push(atom);
marks.push(atom);

The big problem (in creating bonds) was figuring out how to create double, triple, and aromatic bonds. And it turns out to be just a big counting game, coupled with offsetting lines. It starts with figuring out what type of bond you have and using that information in a switch case.

The information for what type of bond you have is carried in the second part of your molfile which starts at

startBondArray=myStartVert+myNumAtoms*16+1

Adding 2 to this number gives you the bond type location (OK once again it’s a big counting game – check out the molfile description under the read more button to see the molfile structure – I know it well).

So, each time you create a double, triple, or aromatic bond you have to keep track of where all the data is in your array. This was accomplished by adding the following counting tracker to your command and data arrays:

commands[2*k+2*dB+4*tB+2*aB]

mydata[4*k+4*dB+8*tB+4*aB]

which are needed to for the drawPath command shown below

myHolder.graphics.drawPath(commands, mydata);

The variables dB, tB, and aB are iterated (by one) each time you create a double, triple, or aromatic bond respectively. These values are then zeroed after each molecular drawing iteration and the process is restarted on each onEnterFrame tick.

Creating the bond offsets was not very sophisticated as shown below:

mydata[4*k+4*dB+8*tB+4*aB] = marks[myArray[startBondArray+7*k]-1].x-bond2Sep;
mydata[4*k+1+4*dB+8*tB+4*aB] = marks[myArray[startBondArray+7*k]-1].y-bond2Sep;

mydata[4*k+4+4*dB+8*tB+4*aB] = marks[myArray[startBondArray+7*k]-1].x+bond2Sep;
mydata[4*k+5+4*dB+8*tB+4*aB] = marks[myArray[startBondArray+7*k]-1].y+bond2Sep;

You just subtract or add an offset value (bond2Sep) as shown above for the double bond case.

Which Way Should We Go!

In going through this, I found some molfiles on the web that were not well formed and would not work with this parser. That’s always the problem with parsers. The errors were easy to fix and many times just meant adding or subtracting an extra zero. But your end user can’t do that…

I really think XML is the best way to go. That way you can target nodes and forget about counting. You can go even a step farther with XML and include chemical bonding information which would enable you to run chemical simulations. Wouldn’t that be cool!

To see all the code, download it from the source link above or click the button below:

Read the rest of this entry »


Google Map Wormhole in Gumbo Air (Flex 4)

January 26, 2009

Intro

I’m working on a huge Google map project for a seminar I’m doing next Tuesday, (and given that I have much time on my hands – right!), I could not resist creating this Google Map wormhole. The animation is created by iterating the map coordinates (longitude and latitude forward), and uses the Tunnel class developed by Petri Leskinen on Pixelero http://pixelero.wordpress.com/.

I don’t iterate uvtData as is done on Pixelero, but longitude and latitude coordinates of the Google map. The change is picked up by drawing the iterated movie into a bitmapdata object and throwing that on to the Tunnel class.

It’s actually map data coming at you (not just a jpeg being recycled).

googlewormhole

Google Wormhole in Gumbo

YouTube

Air Source Files Click Here

Discussion

Bringing Google map data into CS4 or Papervision3D is really easy, as discussed in an earlier post (Google Map on a Papervision Primitive) . In this case, I use Gumbo (Flex 4) not Papervision3D. Gumbo performs better than Papervision3D and does not distort button positions on standard Google control buttons (as Papervision3D does) – hurray!!!

Here are the steps required to get your Google map Wormhole working!

Step 1: Create a movie clip to add your Google map to

movie.graphics.beginFill(0xFFFFFF);
movie.graphics.drawRect(0,0,300,300);

Step 2: Add the Google map to your movie

movie.addChild(Application.application.map);
movie.graphics.endFill();

Step 3: Create a bitmapdata and draw your movie into it

_bmpd=new BitmapData(300,300, false);
_bmpd.draw(movie);

Step 4: Instantiate the Tunnel class (adding in the bitmapdata material) and add the tunnel to a canvas container on your Flex stage.

tunnel = new Tunnel(_bmpd, 800.0, 600.0, 32, 32);
mapHolder.rawChildren.addChild(tunnel);

Step 5: Redraw the movie and iterate Latitude and Longitude coordinates in the onEnterFrame animation loop.

_bmpd.draw(movie);

myLat=myLat-.0002*sin;
myLng=myLng-.0002;

To see the complete code click the more button 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 »