Previously, I went over the process of writing an Away3D parser but skipped how to actually interpret the data in a file. In this post, I’m going to talk about the structure of an OBJ file (less complicated than SOUR), how it’s typical of all 3D files, and how in Away3D or any 3D engine one would turn its data into a usable 3D object.

First, let’s actually look at a 3D file, a simple cube saved by Blender. This cube has sides 2 Blender units long and is centered perfectly. (Hence all the 1’s and -1’s.) It has a material file and is UV-mapped. Unlike SOUR, it uses quads (four-pointed faces like rectangles, diamonds, or squares).

Alright, let’s go through it.

The lines that begin with a pound sign (#) are comments. They can be deleted and it will have no effect on the file.

The lines that begin with “mtllib” refer to the MTL material files exported alongside the OBJ file. In my experience, MTL files are fairly useless, so I’m not going to cover how they work here except to say that they do not contain the PNG or JPG file used for the texture, and that you can delete that line with little effect. Same for “useMtl” lines.

The lines that begin with “v” are vertices. You can see that each has an X, Y, and Z value. Furthermore, they are “indexed”. More on that later.


The lines that begin with “vt” are texture vertices. They’re in 2D space, so they only have X and Y coordinates. They will for the rest of this post be called “UVs”, since that’s more common.


useMtl, s
Next are a few more useless lines. The line with “useMtl” was discussed above. The one with “s” has to do with smoothing groups, which applies to 3DS Max only.

Next up are the lines starting with “f”. F is for face. This is where it gets interesting. Remember how I said the vertices were indexed? Each face has two numbers. One refers to a vertex, a “v”, and the second refers to a UV, a “vt” from the above lists of vertices and UVs. You’ll see that there are eight vertices and each of the face number-sets’ first numbers is in the range 1-8. See where this is going? The first face is a quad with the vertices 1,2,3, and 4, or:

By plotting those four points in 3D space, we reconstruct the first of the six quad faces of a cube. “Indexing” means listing each of the eight vertices only once and then referring to that vertex by its “index” number in the face information. This saves space and bandwidth. The alternative would be listing the actual “v” vertex information per face. The UVs are also indexed.

So, in a custom parser, if you were parsing line by line like the OBJ and SOUR parsers do, you’d read a line, separate the bits by the spaces in the line via something like AS3’s String.split() function, throw out the first one, and use the rest to form a vertex or UV. Once you had a list of vertices, UVs, and whatever other data was relevant, you’d use your 3D engine’s methods/functions to construct the Mesh object and put it onscreen. In Away3D, that looks like:

And that’s really it. Parsing is just taking data in one form, and making it readable to whatever needs to use it.

A big part of creating the SOUR format was writing a parser to get the models into Away3D. (A parser is a part of a program which reads data in a storage format and changes it into a usable format.) In this article, I’m going to go through the basics of writing an Away3D parser.

The Parts

An Away3D parser has six fundamental functions you need to use:

  • the constructor and super() in it
  • proceedParsing()
  • hasTime()
  • supportsType()
  • supportsData()
  • finalizeAsset()

The Parent Class: ParserBase

You’ll need to extend Away3D’s ParserBase class to get access to the functions mentioned above, and to make your parser compatible with the AssetLibrary.

The Constructor

Like any AS3 constructor, the constructor function will have the same name as a parser class. So for our parser, SOURParser, the constructor is SOURParser(). The only thing you need to worry about doing in the constructor (though you can do more if you so choose) is using the super() function. ParserBase, the parent class, takes a single argument, either ParserDataFormat.PLAIN_TEXT or ParserDataFormat.BINARY, depending on what kind of 3D file is being parsed.

Compatibility Checking

Away3D parsers attempt to determine whether the data being fed to them is compatible in two ways: by examining the file extension and by checking the contents of the file for certain strings which are a part of the file’s formatting. supportsType() does the former and supportsData() the latter. Both return a boolean. Override them and modify them as is appropriate for your 3D file format.

The Actual Parsing

How a parser reads your data is really up to you. For SOUR, I chose to do a line-by-line approach in a while loop, much like the OBJ parser does. All the parsing gets done in proceedParsing().

One nice feature of Away3D’s ParserBase though, is that it has the hasTime() function, which allows you to do the parsing over the course of several frames rather than all at once. Why does that make a difference? If you’re attempting to read a file all at once and the file is too large to be processed in the time in between frame renders, the parsing will continue until it’s done and THEN the next frame will get rendered, causing frame loss. Using hasTime(), you can determine if you’ve exceeded the time limit between frames yet, in order to break the job of parsing down into smaller pieces, and not lose frames. If everything gets preloaded, it won’t make a difference, but if some assets are loaded on the fly, it’s rather important.

When you finish reading data from your 3D file and reconstructing it as a Mesh, Geometry, Animation, Texture, etc., you’ll want to pass that 3D-formatted data back to your application. You do that with finalizeAsset(), which takes the data itself, automatically figures out the AssetType, and delivers it back to your application via an AssetEvent. The process of turning a 3D file into Mesh data is the subject of another article.

Note: SOUR was created during my time with Kumoshi.

Our custom 3D format, SOUR, has gotten an upgrade. SOUR now has the capability to include “attachment points”, which will allow us to put things in avatars’ hands, things on their heads, etc. Behold:


The mechanism is pretty simple. See the red and blue dots? Their positions get saved alongside the animation keyframes. Moving the attached objects with them is as simple as telling the attached object to “go” to the red one and “look” at the blue one. Of course, the red and blue dots needn’t actually be shown.

Working on a game or 3D project that could use this sort of functionality? Check out SOUR’s Github page.

SOUR is a custom 3D file format designed to bridge the gap between Blender and Away3D. Aren’t there other formats which Blender exports and Away3D reads? Yes there are: OBJ, 3DS, MD2, MD5, AC3D, DAE. However, none of these formats except for DAE can save vertex tangents, and the DAE export script for Blender doesn’t save them.

What are vertex tangents, and why do they matter? Let me break it down.

What’s a Vertex Tangent?

You may know that 3D models are made of triangles. Each triangle has three points, called vertices. A vertex is a point in 3D space. Like a point in 2D space, a vertex has an X and a Y coordinate, but for 3D space, a vertex also needs a Z coordinate. There is other information related to each of a triangle’s three vertices too. I won’t go too deep into it except to say that the other information is used to light the 3D shapes correctly, and that part of that information about each vertex includes a second set of three numbers called a “vertex tangent”.

Vertex tangents are very important for “normal mapping”, a technique used to make a low-detail version of a 3D model look like it’s a high-detail version. Using normal mapping reduces the amount of power your graphics card needs to render a given 3D model, and thus increases performance without sacrificing much quality.

Back to Away3D and SOUR

Since none of the currently existing Blender export formats save vertex tangents, when Away3D reads the models, it realizes that there are no vertex tangents and attempts to figure them out itself. This is all well and good if the program used to create the 3D model’s normal map and Away3D are using the same vertex tangent generation math. Blender and Away3D don’t. The result is ugly seams on models using normal maps.


SOUR solves this problem by saving vertex tangent information into the 3D file. Away3D never gets a chance to generate (not incorrect but) mismatching vertex tangents, and the models look spiffy.


SOUR has a few other features too:

  • indexed & compressed to save space
  • bone or keyshape-based vertex animation
  • also exports vertex normals
  • has a Blender export script, an Away3D parser, and a Github page

If you do a Google search for “normal map seams”, you’ll find that Away3D isn’t even remotely the only engine which suffers from the nonstandard normal map generation problem. JMonkey, OGRE, XNA, and others all have this issue. I would love to see SOUR used more widely. If you have any suggestions for the format, leave them in the comments.