Archive for the 'Uncategorized' Category
Working with Away3D
So for the last few weeks I’ve been experimenting with Away3D. Away3D is a free 3D engine for Flash, very similar to Papervision3D. As a previous user of Papervision, I noticed a lot of similarities, but there are a few differences, both good and bad, to take note of. There are different features between the two, though for the most part they’re pretty similar.
The different is mainly in the syntax of how things are set up. As with Papervision, you need to set up a Scene3D, a View3D (Viewport3D), and Camera3D. Papervision requires that a Renderer is set up, where as with Away3D the rendering is done just through the view. The syntax is shorter for this in Away3D, as Papervision requires you to pass multiple objects: renderer.renderScene(scene, camera, viewport), where Away3D you just call view.render().
Another difference is that Away3D uses what they call initObjects, which are objects that contain name-value pairs. So when creating a plane in Papervision, you do so by: myPlane = new Plane(myMaterial,350,350,3,3), where there are explicit arguments for the material, width, height, subdivisions x, and subdivisions y. Away3D, on the other hand, doesn’t require you to pass any arguments when you create your plane: myPlane = new Plane({material:defaultMaterial, width:350, height:350, segmentsW:3, segmentsH:3}). This style has it’s pros and cons, the nice part is that when creating the object, you can set specific properties without having a long list of arguments in the constructor. The downfall is that if you are not carefull, it can fail silently due to typos or by accidently calling a property by a different name, such as something like: myPlane = new Plane({segmentsW:3}) vs. myPlane = new Plane({segmentsX:3}).
I’m not going to go though all the differences I encountered, but there are more, and I think it boils down to personal preference. For example, when creating shaders in Papervision, you need to pass a specific light object to the material in order to make it work. In Away3D, as long as the light is in the scene, the shader will use it. Another nice feature Away3D has, which I’m not sure if Papervision has, is material caching. When you have multiple objects in a scene, if the object doesn’t move and the camera doesn’t move, that object is not updated on render. If there are objects that are behind the still object that are moving, those will be updated, but the still one will still not be. There’s an example of that here.
One of the features that Away3D does have that Papervision3D does not (yet?) support is Normal Maps. Normal mapping, basically, is where you take a high polygon mesh and save out the details as a special material that can then be used on a low poly mesh to make it appear to have the higher count. The normal map is basically like an advanced bump map, but instead it is in color because it takes into account angles for where the light reflects and cast shadows. I’m not going to get into details, so check out wikipedia if yo want some more info. Here is an example I made that shows the difference between regular bitmap material and the normal mapping shader, as well as an example that shows you what the normal map looks like wrapped on the head as a texture. The model was made by my talented 3D coworker Andrew Jerez.
One issue with the normal map shaders in Away3D is that once you have multiple objects together, if those objects intersect, the render engine breaks and causes artifacts. There’s a few solutions to this. In the example above, the eyes are a different object/mesh. By assigning them to their own render session ( eyes.ownSession = new SpriteRenderSession() ) and then offsetting their z-depth ( eyes.screenZOffset = -10 ). This more or less will break the z depth sorting, so it can’t be used for complex geomety that would wrap around the object that uses the normal mapping. The other solution, which is best especially if you want more than one object to have normal mapping shader on it, is that all the objects in the scene need to have the same shader material. So for instance, (not seen in demo) we have the head mesh and a hair mesh. We want both to have normal mapping, so we have to assgin the exact same material to each:
shader = new Dot3BitmapMapterial(textureBitmapData, normalsBitmapData);
headMesh.material = shader;
hairMesh.material = shader;
This technique means that you need to make sure that you set up yout UVs in the 3D editor (in this case Maya) so that each object can share the same texture file. Below are some examples showing the texture image, the normal map image, and the UB layout for the face and hair.
Normal maps also take some time to parse and since this happens in a for loop, if you have a large normal map, Flash can freeze for a few seconds while it runs though and creates the normal map. I broke this part out into an enter frame, which on completion dispatches a MaterialEvent. If you are interested, the source is here. Create the Dot3BitmapMaterial as normal, but pass manual:true in the initObject, add a listener for MaterialEvent.DOT3_MATERIAL_BUILT, and then call myMaterial.buildMaterial().
One last fun little thing. Away3D also supportes enviromental shaders. An enviromental shader is more or less like cheating to do reflection. You have a material on the object of the surrounding enviroment, which acts as the reflection result. An example of that is seen here on the Away3D site. The area being reflected is what is in front of the object, which is out of view of the scene and more or less “behind you” as you look at your screen. So a true reflection would be reflecting what’s really in front of that object, which in this case is you looking at your monitor. So hook up a web cam, capture that feed as a material, and there you have a ‘mirror’ material.
If you have a webcam, take a look.

If your camera doesn’t work, you might have to right click>settings, and on the camera tab change it to use the web cam. I’ve noticed this problem on macbooks. It’s slower, but you can also combine materials, such as the environment shader and Dot3Material.
For help with Away3D, visit the dev group they have set up on Google. The Away3D team regularly checks and provides the most help they can.
3 commentsControlling AS2 swfs within an AS3 application.
Sometimes you’ll need to load an AS2 swf into your AS3 project, and this seems like it can be a nightmare. And it can be, depending on what it is. You loose some functionality, such as loadMovieNum and getURL. On top of that, you can’t control the movie, as in you can’t access any public functions. There can be a workaround, though. The trick is to write an AS2 shell that acts like a bridge. You’ll load the AS2 swf into that shell, and communicate with the swf from that file, then communicate to the AS2 swf bridge from your AS3 project via localConnection. This comes from a problem I recently was required to tackle, so I fiugred I’d share my solutution.
In this example, we need to load an existing game written in AS2 into an AS3 website. We do not have any access to the source files, just the compiled swf, which needs to be properly disposed in order to stop its audio channel. The solution is to create an AS2 shell that can load and unload the game, and then communicate with the shell via localConnection.
Step 1. Setting up the AS2 shell
Make a new AS2 targeted flash file and on the stage create a new empty MovieClip and give it an instance name, in this case container_mc.
Now as much as this hurts, click on the first frame and open the ActionScript panel. Yes, we’re going to add some very simple code to the timeline. First we want to load the game using loadMovie, targeting the container_mc that we created on the stage. This will load our file into this empty MovieClip so we can easily remove it later. Since we’ll be bringing this into and AS3 swf, we cannot use loadMoiveNum. The one line of code should look like this: loadMovie(“game_as2.swf”,this.container_mc) .
Step 2. Setting up the LocalConnection listener
This file is basically going to wait for a command from a localConnection at some point, so we’ll set that up immediately after loading the movie. In this case, we named the connection ‘gameBridge’ and will need to use that string in out AS3 swf in order to sync the two together. The code looks like this:
var lc:LocalConnection = new LocalConnection();
lc.connect(“gameBridge”);
Now we need to set up a method that will be called from AS3. In this case, it’s a dispose method. In order for the method to be called, it needs to be a method of the localConnection, so the full function name is lc.dispose = function():Void. Remember that lc is our localConnection object, and that in AS2 the datatype for void is capitalized. All we want to do in this function is kill the game, so we’re going to unload it and kill the connection. Just two lines of code, which looks like this:
lc.dispose = function():Void {
unloadMovie(container_mc);
lc.close();
}
That’s it for the AS2 side.
Step 3. Setting up the load in the AS3 project
We load in the AS2 swf just like we do an AS3 one, the only difference is that instead of it being of type MovieClip, it will be a special class called AVM1Movie, which stands for ActionScript Virtual Machine 1 MovieClip. Remember, we’re loading our shell we just made, not the game. So my load method looks like this:
private var game:AVM1Movie;
private var loader:Loader;
private function loadGame():void {
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, hndlGameLoad);
loader.load(new URLRequest(“gameshell.swf”));
}
private function hndlGameLoad(e:Event):void {
game = AVM1Movie(loader.contentLoaderInfo.content);
addChild(game);
}
In this case, the game was set to a frame rate of 30fps, and my app is running at 71fps. That means that the loaded game will now run over twice as fast. There’s not much we can do about this, but we can set the overall stage frame rate to match the loaded game, and when the game is unloaded, just remember to set it back. It’s just one line of code: stage.frameRate = 30;
Step 4. Setting up the LocalConnection call method
The last thing to do is call the AS2 swf and tell it to dispose when we need it to. We just set up a new LocalConnection object and pass it the name of the connection we set up in the AS2 swf and the method that we want to call. Looks like this:
lc = new LocalConnection();
lc.send(“gameBridge”, “dispose”);
And that’s about it. Pretty simple and quick way to load and still be able to dispose of an AS2 file.
7 commentsPixel Bender Filters
I started to play around with pixel bender a few weeks ago, but didn’t have much time to really accomplish anything interesting. However, I came across the opportunity (or rather excuse) to use it to whip up a quick filter for my current project. Basically, we have a bunch of transparent png images of people or objects. In the images, the figures or objects cast shadows, but the shadow’s transparency is not taken into account (think of it more like a .gif where transparency is either true or false rather than smooth). So I wanted a way to take a selection of the image, and basically have it translate the brigtness value to alpha. The result would be similiar to using a multiply blend mode, if blend modes could be used with only one layer. Anyways, I couldn’t find a way in Photoshop to accomplish the effect to my liking, so I wrote a super simple pixel bender filter, imported it, and voilà, I had exactly what I needed. Pixel Bender is going to be a great too for player 10, but I think there could be a lot of interesting and practical uses for it even outside of Flash.
Here’s the filter (right/option click and save as, I guess Firefox and the like recognize it as a text file) if you’d like, as well as an image that hopefully clarifies what I was trying to describe above.
1 comment





