Cadet Editor Launch

After much tinkering, testing, re-factoring and playing, the team at Unwrong are proud to announce the launch of www.cadeteditor.com, the demo site for our new app. Cadet is a general-purpose editor framework for the Flash platform. To demo Cadet we decided to build a Box2D physics editor and an Away3D scene editor, though if an engine has a Scene Graph, we could probably write an editor for it using Cadet. We’ve also published a few videos to help give an idea of the various features in each editor. For instance… This video demonstrates how easy it is to create a simple physics scene in the Box2D editor:

This video introduces Joints, a more advanced Box2D concept:

This video demonstrates the ActionScript and three.js exporters (I mentioned in my previous post) in action in the Away3D editor:

And this video demonstrates importing and texturing a custom model in the 3D editor:

If you feel like watching any more, the rest can be found on our Vimeo page.

If you’d like to keep up-to-date with the latest features and fixes, please subscribe to our Facebook or Twitter.

We hope you enjoy playing with the editors and if you have any feedback, let us know! :-)

Posted in Apps, Away3D, Bones, Editor, Flash | 3 Comments

Away3D 4.0 Gold: AS3 and three.js exporters

Last year I began messing around with the AS3 exporter for Away3D 3.6.0. After writing a few test scenes and resolving a few issues with it, I went on to see whether I could write a three.js exporter, and experienced some positive results.

Lots of things have changed since last September, the biggest of those being the complete rewrite of the Away3D engine to support the Stage3D APIs. One thing that hasn’t changed though is my particular interest in writing exporters for Away3D. The current “Gold” release of Away3D doesn’t yet support serialization; the old code obviously became defunct with the rewrite, and the Away team have no doubt been focused on code which is more pivotal to the engine’s success over recent months.

It just so happened that I needed at least a basic working Away3D exporter for a project I’m working on, so I decided to write a new one. If you’d like to see what I’ve added here are the commit details to my fork of away3d-core-fp11. If you’d like to run the few simple tests I’ve create for yourself, you can download them from my blog repo on github. Note: To run the experiments, you’ll also need a copy of my away3d-core-fp11 fork which contains the Away3D updates. Alternatively, you can view the same examples in your browser here.

As per the Away3D 3.6.0 -> three.js exporter, you’ll notice in the examples that the X-Axis is inverted. Other than this though, the results are pretty similar. I’ve decided not to try and rectify the differences below between the Away3D and three.js scenes, as they are all a result of how the engines “naturally” render their primitives and scene. For instance, I could have flipped the three.js Wireframe Plane and Torus primitives to match their Away3D counterparts, though this added code could cause confusion later if the developer expected the transform of the object to be the same as it was in ActionScript.

Image

I’ve also tried to make the ActionScript and JavaScript outputted by the Serializer as neat and as similar to one another as possible. Here’s an excerpt from the ActionScript and JavaScript output created by the Primitives scene:

Image

As you can see, three.js needs to use a slightly different geometry and material in this instance, but the resultant meshes both access these objects using their position in an array, which contains only that type of object.

Hopefully that gives a reasonable overview of the Serializer code as it stands, I’ll submit it to the Away team and keep my fingers crossed that it’ll be accepted..! :-)

Posted in Away3D, Flash, HTML5, Three JS | Tagged , , , , | 3 Comments

The Future of Flash: Rearranging deckchairs on the Titanic?

We at DotBrighton were fortunate enough on the 24th Feb to have a visit from Flash Platform Evangelist Lee Brimelow.

Lee gave a frank and forward looking presentation regarding the recent upsets with the Flash Platform and Adobe’s roadmap for Flash for the foreseeable future. Predictably enough, for the most part it was a reiteration of the recent Flash Platform Roadmap White Paper. The message essentially being: Future of Flash = Premium Video and Gaming, i.e. Flash is for the stuff you can’t do in HTML. But wasn’t this always the case? The only thing that’s changed is that HTML has caught up on Flash like wildfire in recent years.

Historically speaking, I’ve always thought of Flash as being the platform that’s pushed the boundaries of what was possible in a browser. Thankfully, the browser was listening and can now do many of the same tricks. The question facing Flash developers now then is “does this game/website/X still need to be made in Flash?” (given that support for Flash Player across devices isn’t great…) I’m sure lots of Flash developers like myself are begrudgingly beginning to test the water with HTML5, pushing it to see just how far it can go and gauging where to place their chips.

As mentioned in a previous post, the main thing I didn’t like about the HTML5 world was JavaScript. To a Flash developer (or at least to this one), JavaScript looks a lot like ActionScript 1, and I’d imagine that’s not a place most Flash devs would like to go back to. Thankfully, Google seem to have similar feelings about this and have created Dart to solve our problems. Dart is a optionally typed language that comes with a free Eclipse based editor that supports auto-complete. This was enough to pique my interest, and I have to say that I actually now prefer the language over ActionScript 3.

So it seems HTML5 has it’s new ActionScript and FlashBuilder style code editor (assuming Dart takes off), plus it supports Bitmap and hardware accelerated WebGL rendering, so what is it missing? Well, the Flash IDE. If we’re going to start rendering everything in the browser using Canvas, SVG or WebGL, we’re still going to need a great animation tool to punt out our Bitmap and Vector graphics.

As Lee stated in his talk (paraphrasing here..): “Do I care about SWF? No, not really, I just care about great tools.”

I think that one sentence defines the future for Flash/Adobe in a nutshell. None of us really care about the SWF, it’s just the platform we use to present our nicely animated/coded work. The browser can do it now too you say? Ok, can we still use our favourite tools? Hopefully. If the Flash IDE focuses on exporting animations as SVG or sprite sheets for use with HTML5 projects, then I’m sure it’ll quite quickly become the best HTML5 animation tool around. Hopefully as Adobe Edge progresses, we’ll begin to see much more focused support for HTML5 projects across the entire Creative Suite. We may not generally be coding in ActionScript or FlashBuilder any more, but hopefully we can bring the rest of the Creative Suite with us.

The Flash Player can continue to push the boundaries in terms of what can be achieved online (with specific focus on bringing AAA games to the browser), and hopefully Flash tooling generally can continue to push to set the standard for a “write once, publish anywhere” workflow. Ultimately, the Flash Player will only continue to be relevant if it can prove that it can do something better than it’s alternatives, but even if the Flash Player does eventually disappear, it’s not what Adobe were selling anyway. Adobe sell editing and publishing tools. With their recent efforts to publish for iPhone from the Flash IDE, Adobe have demonstrated that they’re more about the tools than the platforms. This can only be a good thing for devs who don’t want to have to rewrite their software for every conceivable platform they wish to publish to.

In summary: Flash is dead, long live Flash.

Posted in Dart, Flash, HTML5 | 1 Comment

Three.dart: Three.js Dart port

Check out the source code at Three.dart on Github.

Although I’ve been very interested in the recent developments in the HTML5 specification, including bitmap and SVG rendering support, I have to say, the one thing that’s been keeping the wind from my sails is… JavaScript.

To a humble Flash developer, JavaScript -in it’s currently incarnation- looks not unlike ActionScript 1. (This is because both JavaScript and ActionScript are dialects of ECMAScript)

The idea of having to downgrade from ActionScript 3 to ActionScript 1, losing classes, compile-time type checking, an Eclipse based code editor with autocomplete… and instead moving to a text editor like NotePad2, seemed less than appealing.

I was in two minds about it, wondering whether it was perhaps just me being inflexible to a different way of thinking, but I have to say I was bouyed slightly by Google’s seemingly similar thoughts:

http://en.wikipedia.org/wiki/Dart_(programming_language)#Motivation

It turns out that Google’s new language Dart intends to bring exactly all the things I was loathed to leave behind, to the browser. Not only that, you can write your code in Dart and compile to JavaScript, so in principle (assuming the Dart to JS compile is comparable to a JS to JS compile) there are big structural benefits and no drawbacks(?), other than investing in a language that isn’t currently used much…

One of the things that appealed to me about JavaScript is it’s openness; the fact that you can view-source and look through the scripts that are running on the page. The fact is though, this isn’t really the case with more complicated libraries like three.js. Due to various optimisation concerns for live projects, the source code is compiled down to a file that is still readable by a machine, but not by a human.

The thing that makes three.js open is its Github repository, where you can download the source and examples, file bugs and feature requests, etc. The reality is then, that libraries like this currently compile from JavaScript to minified JavaScript, so couldn’t we potentially compile from Dart to minified Javascript instead?

Not being able to resist a challenge, I thought I’d teach myself Dart, three.js, and brush up on my JavaScript by trying to write a three.js Dart port. After a fair amount of head scratching and several days of resolving compile-time and run-time errors, I was fairly jubilant to see this:

I guess that’s not very impressive, in and of itself, to look at… But after several days of seeing nothing and hoping that this wasn’t, in fact, a doomed venture, you can imagine it meant a lot to me…

Just to give you a quick example of why I bothered to do this, take a look at the following code comparison:

This is obviously showing the same function being written in JavaScript and Dart, JavaScript being the top one. When I look at that JavaScript, especially when I’m aware it’s part of a large and complicated system, my heart sinks a bit. 10 variables are being declared, and apart from being able to make a reasonably educated guess based on their names and my patchy understanding of this particular system, I have no idea what they represent. Now look at the Dart version, you know exactly what the variables represent, there’s no ambiguity. You even know that this function doesn’t return a value, all from the first few lines. Also, if for instance you’re not quite sure what a Vector3 is, Control-Click the definition and the Dart Editor opens up the class for you.

Here’s another example, this time demonstrating inheritance:

I personally prefer the Dart code again here, as obviously, the JavaScript is having to do a few clever tricks to support an object-oriented programming style. Anyway, you get the picture.

I hope you like the project, and if you agree or disagree with the comparisons between JavaScript and Dart above, I’d be very interested to hear your comments! :-)

Posted in Dart, Three JS | 15 Comments

2011 in review

The WordPress.com stats helper monkeys prepared a 2011 annual report for this blog.

Here’s an excerpt:

The concert hall at the Syndey Opera House holds 2,700 people. This blog was viewed about 13,000 times in 2011. If it were a concert at Sydney Opera House, it would take about 5 sold-out performances for that many people to see it.

Click here to see the complete report.

Posted in Misc | Leave a comment

Away3D 3.6.0: Three JS exporter WIP

As a follow on to my recent Away3d AS3Exporter update post, I began to wonder whether I could write a similar exporter for Three JS. I’ve managed to make a reasonable amount of progress with this- the current version can export various Away3D primitives to their correct positions, but I’m struggling a little with translating the rotation and scale properties.

Here’s the code for the latest version, and here’s the swf which outputs the Three JS HTML file.

Clicking on the “export to 3JS” button generates the HTML file and copies the code to your clipboard. If you create a new text file in Notepad or similar, call it “exported.html” (the name doesn’t matter as long as the .html extension is there), paste in the code, save and open the html page. Note: this example doesn’t run in IE9 for me, so I’d advise opening it with Google Chrome. Alternatively, you can click here to open the resultant Three JS scene in your browser. The image below describes the problem with the Three JS scene:

As you can see there are a few issues with the exported HTML file.

The first problem is that the red x-axis is inverted in Three JS. This is because Away3D is a left-handed system whereas Three JS is a right-handed system. This means that the positions of the objects are correct asides from the fact they are inverted on the x-axis.

The second problem is that the primitives appear to be rotated +90 degrees around the x-axis. This seems to be due to the fact that the standard behaviour in Three JS is to build them from top to bottom along the z-axis, whereas the standard behaviour in Away3D is to build them from top to bottom along the y-axis.

I’ve attempted to resolve both of these issues in exporters.ThreeJSExporter in the following function:

private function getThreeJSMatrix( object3d:Object3D ):Matrix3D
{
  var m:Matrix3D = object3d.transform.clone();
  m.prependRotation(-90, Vector3D.X_AXIS);
  m.appendScale(-1,1,1);

  return m;
}

The function getThreeJSMatrix() is called just before an object3d is serialised and updates the object’s Matrix3D in an attempt to correct it’s orientation in the resultant Three JS scene. As you can see from the image below, this works to some degree, though the plane primitives are rendered upside down (hence are invisible from this viewing angle) and the primitives which had rotations applied to them are incorrectly rotated in the new coordinate space. Click here to open the resultant Three JS scene in your browser.

I’m hoping someone with a little more 3D knowledge will read this and help me to complete what should be a pretty neat little exporter.

Key questions:

  • Should I rotate the objects through -90 degrees or is there another way in Three JS to alter the rendering orientation (e.g. yUp = true in Away3D)?
  • Can someone provide the necessary matrix transformation code to translate rotation and scale properties from a left-handed to a right-handed system?
Thanks in advance! :-)
Posted in Away3D, Flash, Three JS | 3 Comments

Away3D 3.6.0: AS3Exporter update

View/download the Source files for this post here. The tutorial also assumes you have a working build of Away3D 3.6.0.

I’ve been playing around with the ActionScript exporter for Away3D 3.6.0 a fair bit recently and have found a few scenarios where it didn’t work so well. The upshot of this is that I’ve re-written the AS3Exporter.as file, solving the problems that I was able to identify while hanging onto the clever bits that already worked.

The following slideshow demonstrates a number of tests that I’ve created and included in the source files above. Each of the images represents one of the “TestScene” apps that can be run from the source project. Each of the test scenes has an Export to AS3 button which copies the exported AS3 file to your clipboard and defaults to using the new exporter at exporters.AS3Exporter, if you want to compare the new exporter against the old one, change the import statement for the exporter at the top to import away3d.exporters.AS3Exporter.

For PrimitiveTestScene, MaterialsTestScene, TransformsTestScene,  ContainersTestScene and LoadedMeshTestScene, the class exported.ExportedScene is created. Copy and paste this new code into the class file of the same name and then run the ExportedSceneViewer app to see the results.

For SingleMeshTestScene and SinglePrimitiveTestScene, the class exported.ExportedMesh is created. Copy and paste this new code into the class file of the same name then run the ExporterMeshViewer app to see the results.

As you can see from the pictures, the new exporter succeeds in a number of scenarios where the old exporter failed. I’ll explain what’s happened in each test case briefly below:

1. Primitives Test

In this test, as we are only concerned with the rendering of the primitives’ geometries rather than their materials, the old exporter works as well as the new exporter. Both however exhibit a problem where Cone, WireCone, Cylinder and WireCylinder are re-rendered at half of their previous height. This is actually due to a bug with the primitives rather than the exporters; in the buildPrimitive() function for each of these primitives we find the following line of code:

_height /= 2;

This line means that when you later get the height property for the primitive, it reports that it is half the height that you originally specified.

One difference you might notice in the code outputted by the exporters is that the new exporter omits any properties or functions that aren’t required for this specific scene in order to improve legibility. In this scene the read(), setSource() and buildMaterials() functions are omitted. It’s also worth noting that the cleanUp() function has been dropped altogether in the new version.

Whilst writing the parsers for each Objects3D I noticed that LineSegment currently requires Vector3Ds if passed an initialisation object via the constructor function and Vertexs if setting the same properties via the classes public API, I’m assuming Vertex should now be done away with in favour of Vector3D.

I’ve also added support for ObjectContainer3D primitives, for example Trident. This functionality is currently disabled however, as Trident doesn’t expose the necessary public properties or accept an initialisation object in the same way as the other primitives. I propose the public properties axisLength and showLetters are introduced, which if changed force the Trident to re-render.

2. Materials Test

As you can see from the pictures, materials aren’t really supported in the old exporter, which makes sense as I’m sure the priority was to enable users to export custom meshes into ActionScript code. In the new exporter BitmapMaterial, ColorMaterial, WireColorMaterial and WireframeMaterial are supported. BitmapMaterial support will only work if you have passed a class to it which extends BitmapData. This is the default behaviour if you export a bitmap for ActionScript from within the Flash IDE, you can also look in the assets package in the source code for this project to see how you can achieve the same effect with code.

3. Transforms Test

As you can see from the pic, the new exporter remains faithful to the initial scene, apart from the aforementioned problem with the Cone primitive’s height. The problem with the old exporter is that it fails to register each primitive’s scaleX, scaleY and scaleZ properties. The new exporter will retain this information when using it’s default behaviour, but currently drops it when using object initialisers. What do I mean by that? Well… You may have noticed this line of code in the clickExportBtnHandler() function for each test scene:

exporter.export( view.scene, "ExportedScene", "exported");//, true);

The currently commented out optional extra Boolean value at the end is a flag to tell the exporter whether to use “object initialisers” or not, this is a new feature I’ve introduced. With the flag set to false, your primitive code will look like this:

var sphere1:Sphere = new Sphere();
sphere1.segmentsW = 12;
sphere1.segmentsH = 9;
sphere1.radius = 100*_scale;
sphere1.position = new Vector3D(-500*_scale, 100*_scale, -1500*_scale);
sphere1.rotationX = 153.3;
sphere1.rotationY = 171.19;
sphere1.rotationZ = 201.22;
sphere1.scaleX = 0.87;
sphere1.scaleY = 1.59;
sphere1.scaleZ = 1.48;
sphere1.material = new WireColorMaterial(0x8d9e96, {wireColor:0x0});
_containers[0].addChild(sphere1);
_meshes.push(sphere1);

With the flag set to true, it will look like this:

var sphere1:Sphere = new Sphere({segmentsW:12, segmentsH:9, radius:100*_scale, x:-500*_scale, y:100*_scale, z:-1500*_scale, rotationX:18.54, rotationY:284.45, rotationZ:61.03, scaleX:0.64, scaleY:0.87, scaleZ:0.1, material:new WireColorMaterial(0x530424, {wireColor:0x0})});
_containers[0].addChild(sphere1);
_meshes.push(sphere1);

I personally prefer the former over the latter for a number of reasons. In the battle between clarity and brevity in coding, I generally tend to find myself on the side of clarity. The latter approach relies on the individual to be aware of all of the relevant properties and to type them perfectly into a dynamic object without the benefit of auto-completion.

Also, by using the public API of the class in the former example, we can be more confident in our assumptions of exactly what will happen; by setting the scaleX, scaleY and scaleZ public properties, we can be fairly safe in the assumption that the primitive will be updated unless a reasonably significant bug exists. With the latter example however we are relying on the fact that the developer has written the code to parse these properties out of the object initialiser, and in this instance it appears they haven’t. If you click through to the constructor function for away3d.core.base.Object3D you can find the following line…

scale( ini.getNumber("scale", 1) );

…where support is added for a scale property which isn’t in fact reflected in Object3D‘s public properties.

Finally, what the latter saves in terms of vertical code length it almost equals in horizontal code length, so it sacrifices clarity and predictability without a great improvement in brevity.

I’ve decided not to work around this bug with the new exporter as this is an issue which should be resolved with the Object3D init object parsing. Whilst the team are no doubt feverishly working on the next version of the framework to support Stage3D, I think now could be a good time to question the logic of using object initialisers and the value of supporting the additional parsing code it necessarily creates.

4. Containers Test

The problem with the old exporter in this instance is simply a small error in the ObjectContainer3D exporter code. Here’s the relevant code the old exporter creates:

var cont1:ObjectContainer3D = new ObjectContainer3D();
aC.push(cont1);
addChild(cont1);
var m1:Matrix3D = new Matrix3D();
m1.rawData = Vector.([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);
transform = m1;
cont1.movePivot(0,0,0);

The error is in the line transform = m1, if this is changed to cont1.transform = m1, it works fine.

This brings me neatly onto the topic of the code structure within the old AS3Exporter class. If you look for instance at the code dealing with writing out containers in the old parse() function, it looks like this:

if(containerid != -1){
  containerString += "\n\t\t\tvar cont"+id+":ObjectContainer3D = new ObjectContainer3D();\n";
  containerString += "\t\t\taC.push(cont"+id+");\n";
  if (containerid == 0)
    containerString += "\t\t\taddChild(cont"+id+");\n";
  else
    containerString += "\t\t\tcont"+containerid+".addChild(cont"+id+");\n";

    containerString +="\t\t\tvar m"+id+":Matrix3D = new Matrix3D();\n";
    v = obj.transform.rawData;
    containerString += "\t\t\tm"+id+".rawData = Vector.(["+v[0]+","+v[1]+","+v[2]+","+v[3]+","+v[4]+","+v[5]+","+v[6]+","+v[7]+","+v[8]+","+v[9]+","+v[10]+","+v[11]+","+v[12]+","+v[13]+","+v[14]+","+v[15]+"]);\n"
    containerString += "\t\t\ttransform = m"+id+";\n";

    if(obj.name != null)
      containerString += "\t\t\tcont"+id+".name = \""+obj.name+"\";\n";
    if(obj.pivotPoint.toString() != "x:0 y:0 z:0")
      containerString += "\t\t\tcont"+id+".movePivot("+obj.pivotPoint.x+","+obj.pivotPoint.y+","+obj.pivotPoint.z+");\n";
}else{
  containerString += "\t\t\taC.push(this);\n";
  containerString += "\t\t\tvar m"+id+":Matrix3D = new Matrix3D();\n";
  v = obj.transform.rawData;
  containerString +="\t\t\tm"+id+".rawData = Vector.(["+v[0]+","+v[1]+","+v[2]+","+v[3]+","+v[4]+","+v[5]+","+v[6]+","+v[7]+","+v[8]+","+v[9]+","+v[10]+","+v[11]+","+v[12]+","+v[13]+","+v[14]+","+v[15]+"]);\n"
  containerString += "\t\t\ttransform = m"+id+";\n";

  if (obj.name != null)
    containerString += "\t\t\tname = \""+obj.name+"\";\n";
  if (obj.pivotPoint.toString() != "x:0 y:0 z:0")
    containerString += "\t\t\tmovePivot("+obj.pivotPoint.x+","+obj.pivotPoint.y+","+obj.pivotPoint.z+");\n";
}

The first thing I notice about this is there’s loads of repetition which could (and should) be turned into functions in order to avoid the errors which creep in from typing and retyping code. Here’s the equivalent code in the new version:

if(containerid != -1)
{
  containerString += newLine();
  containerName	= getContainerName(type, id);
  containerString += newLine(getObject3dDefAsString(type, object3d, id, 3));
}
else
{
  containerName = "this";
  var obj2	:Object = getObject3dDataObj( object3d );
  containerString += writeDataObjAsString( obj2, containerName, 3 );
}

containerString += newLine("_containers.push("+containerName+");", 3);

if(containerid != -1)
{
  if (containerid == 0)
    containerString += newLine("addChild("+containerName+");", 3);
  else
    containerString += newLine("_containers["+containerid+"].addChild("+containerName+");", 3);
}

Firstly, all the \ts and \ns have been incorporated into the newLine() function, which creates a new line, inserts your new string and prepends the specified number of tab indents.

Secondly, all Object3D parsing is (as soon as is practicably possible) fed into one central pipeline, rather than being written and re-written for different circumstances. Within getObject3dDefAsString() a data object is created to contain all of the properties for the Object3D which need to be serialised. The first thing this function does is look for a specific parser for the Object3D in question. It does this by looking in the _registeredObject3dTypes and _registeredContainerTypes Dictionaries to see if a parsing function has been associated with it’s type. If the type is Cube for instance, the following parsing function will be found and the relevant properties for the Cube will be added to the data object:

private function getCubeDataObj(object3d:Object3D, obj:Object):Object
{
  var cube:Cube = Cube(object3d);
  obj.props.push(new KVP("width", cube.width+"*_scale"));
  obj.props.push(new KVP("height", cube.height+"*_scale"));
  obj.props.push(new KVP("depth", cube.depth+"*_scale"));

  return obj;
}

Next, getMeshDataObj() is called, which in turn calls getObject3dDataObj(). Between these 3 functions we should be able to glean all necessary information to serialise any Primitive, Mesh or ObjectContainer3D in the scene. Forcing all Object3Ds to be parsed via this one pipeline removes the possibility for errors creeping in from copying and pasting code.

Also, because all Object3Ds are now parsed via the same pipeline, our position code for the ObjectContainer3D now writes out as the much more human readable:

objectcontainer3d2.position = new Vector3D(400*_scale, 0*_scale, 0*_scale);

As opposed to the slightly less intelligible:

var m2:Matrix3D = new Matrix3D();
m2.rawData = Vector.([1,0,0,0,0,1,0,0,0,0,1,0,400,0,0,1]);
cont2.transform = m2;

5. Loaded Mesh Test

The obvious visual difference between the old and the new exported scenes in the accompanying picture is that the old exporter fails to retain the rotation properties and material for the Mesh.

If you look at the code the exporters writes out however, the old version writes quite a long buildMeshes() function where the Mesh is created from an accompanying data object:

private function buildMeshes():void
{
...
  objs.obj0 = {name:"turtle",  transform:m0, pivotPoint:new Vector3D(0,0,0), container:0, bothsides:false, material:null, ownCanvas:false, pushfront:false, pushback:false};
  objs.obj0.geo=geos[0];
...
  for(var i:int = 0;i    ref = objs["obj"+i];
    if(ref != null){
      mesh = new Mesh();
      mesh.type = ".as";
      mesh.bothsides = ref.bothsides;
...
}

In the new version these data objects are done away with and the Meshes are written out as strictly typed objects:

private function buildMeshes():void
{
  _meshes = [];

  var mesh0:Mesh = new Mesh();
  mesh0.name = "turtle";
  mesh0.rotationY = 90;
  mesh0.rotationZ = 180;
  mesh0.material = new BitmapMaterial(new assets.TurtleTexture());
  mesh0.geometry = buildGeometry(_geometries[0], mesh0.material);
  _containers[0].addChild(mesh0);
  _meshes.push(mesh0);
}

The geometry data which still needs to be read in from Strings at runtime still remains in data objects within the setSource() function, and the business of reading it is now delegated to the new buildGeometry() function.

6. Single Mesh Test

This Test Scene targets a single Mesh within the scene for export rather than the scene itself. The old exporter almost works as well as the new exporter in this scenario, except it doesn’t have the benefit of the new Materials support.

Remember that the exported code for tests 6 and 7 needs to be pasted into exported.ExportedMesh rather than exported.ExportedScene as per the previous tests.

7. Single Primitive Test

This Test Scene allows the user to target a single Primitive within the scene for export rather than the scene itself. The new exporter simply extends the relevant primitive and adds the new properties like so:

public class ExportedMesh extends Cylinder
{
  private var _scale:Number;

  public function ExportedMesh(init:Object = null)
  {
    var ini:Init = Init.parse(init);
    _scale = ini.getNumber("scaling", 1);
    buildMeshes();
  }

  private function buildMeshes():void
  {
    segmentsW = 6;
    segmentsH = 4;
    radius = 100*_scale;
    height = 100*_scale;
    openEnded = false;
    position = new Vector3D(-730*_scale, 100*_scale, -200*_scale);
    material = new WireColorMaterial(0x26f40, {wireColor:0x0});
  }
}

The old exporter fails to create valid code in this instance.

So, in summary:

Old Exporter Issues:

  • Fails to read Materials in Materials Test.
  • Fails to retain transform information in Transforms Test and Containers Test.
  • Fails to retain the rotation information for Loaded Mesh Test.
  • Fails the Single Primitive test, exporting code containing errors.

New Exporter Enhancements:

  • Reads BitmapMaterialColorMaterialWireColorMaterialWireframeMaterial.
  • Dynamically imports any classes that extend BitmapData which are being used in BitmapMaterials.
  • All Object3D parsing fed down one central pipeline, removing possibility for copying errors.
  • Support for specific Object3DContainers e.g. Trident.
  • Code only included in exported class if required.
  • Variable names in exported class made more readable, aC = _containers, oList = _meshes, getters wrap properties of the same name with a preceding “_”.
  • objs.obj.. and Mesh parsing code removed from exported class.
  • Strict typing favoured over object initialisers, though both are now supported in exported class.

General Issues: 

  • LineSegment requires Vector3D if dealing with init object and Vertex if using the public properties.
  • Object3D init object doesn’t parse scaleX, scaleY, scaleZ, so this fails when in object initialisers mode.
  • Cone, WireCone, Cylinder and WireCylinder Primitives have _height /= 2 error.
  • Trident primitive should be updated to accept object initialisers and have the public properties axisLength and showLetters.

I hope this helps when writing the new exporter for Away3D 4 and I look forward to playing with it! :-)

Posted in Away3D, Flash | 2 Comments