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).
# Blender v2.64 (sub 2) OBJ File: '' # www.blender.org mtllib cube.mtl o Cube v 1.000000 -1.000000 -1.000000 v 1.000000 -1.000000 1.000000 v -1.000000 -1.000000 1.000000 v -1.000000 -1.000000 -1.000000 v 1.000000 1.000000 -1.000000 v 1.000000 1.000000 1.000000 v -1.000000 1.000000 1.000000 v -1.000000 1.000000 -1.000000 vt 0.250000 0.500000 vt 0.250000 0.250000 vt 0.500000 0.250000 vt 0.500000 0.500000 vt 1.000000 0.500000 vt 0.750000 0.500000 vt 0.750000 0.250000 vt 1.000000 0.250000 vt 0.000000 0.500000 vt 0.000000 0.250000 vt 0.000000 0.000000 vt 0.250000 0.000000 vt 0.250000 0.750000 vt 0.000000 0.750000 usemtl Material s off f 1/1 2/2 3/3 4/4 f 5/5 8/6 7/7 6/8 f 1/1 5/9 6/10 2/2 f 2/2 6/10 7/11 3/12 f 3/3 7/7 8/6 4/4 f 5/9 1/1 4/13 8/14
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.
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:
v 1.000000 -1.000000 -1.000000 v 1.000000 -1.000000 1.000000 v -1.000000 -1.000000 1.000000 v -1.000000 -1.000000 -1.000000
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:
_mesh.geometry.subGeometries.updateIndexData(_indicesArray); _mesh.geometry.subGeometries.updateVertexData(_verticesArray); _mesh.geometry.subGeometries.updateUVData(_uvsArray);
And that’s really it. Parsing is just taking data in one form, and making it readable to whatever needs to use it.