Wavefront OBJ file to Javascript arrays
Andor Salga | 19 August, 2008 | 16:15
To place a model into a scene, the model must first be created in a modeling application such as 3D Studio Max, Blender or softImage. Once it has been created, the vertices, normals, etc. must be exported to a file. Since JavaScript can’t natively read files, we have decided to create a conversion tool to convert the exported file into a set of javascript arrays within a .js file which can then easily be used. We decided on using the Wavefront obj specification as many modeling applications can export obj files, it is simple, human readable and easy to convert into other formats. The workflow to get a model into a scene, such as a car would be:
1 - Create the car in a modeling tool.
2 - Export to the obj file standard, let’s say car.obj.
3 - Use our tool to convert car.obj into car.js, where car.js will contain a set of JavaScript arrays for the vertices, normals, texture coordinates and faces.
4 - Somewhere in a script, include the lines:
Model car = new Model();
car.init(carVertices, carUVs, carNormals, carFaces);
Then the car can be translated, scaled and rotated into the scene.
The converter
Here is the current interface of the converter:
objconverter objFile [jsFile] [prefix]
objFile - The file to convert.
jsFile - An optional argument which is the path where to place the converted data, if omitted, it will default using the first part of the objFile, in this case “car” with an appended “.js”.
prefix - An optional argument. If ther user wants, they can choose the prefix of their variables. If omitted, the arrays will be carVerts, carUVs, carNormals and carFaces. If they provide an argument, it will be used instead of “car”. This is simply made as a convenience. Users can just as easily open the file and rename the variables on their own.
Limitations
Currently, the tool has some limitations. The first is trying to convert an obj file which contains a model which has not been triangulated and another is converting a model which does not have texture coordinates or normals.
Typically, triangles are used to approximate a model, but quadrilaterals can also be used. Currently, the our Model ‘class’ only accepts triangles, so this creates a problem. I have found Blender to be notorious for exporting quads instead of triangles. So a face in an .obj file may look like this:
f 1/1/1 2/2/2 3/3/3 4/4/4
instead of this:
f 1/1/1 2/2/2 3/3/3
(Check out the File Format section in tutorial 4 for an explanation of vertex, normal and face arrays)
If a face with 4 parts is found, the converter rejects it and informs the user the model has not been triangulated. However, correcting this is not difficult, Blender does provide a means to triangulate the model with a click of a button during exporting.
Models must always have vertices, but normals and texture coordinates may not always be present. This creates a small problem when trying to place a model into a scene since the init() method of a Model requires the normals and texture coordinate arrays. I have decided to address the problem by issuing a warning to the user. The warning simple states that since some data was not found in the .obj file, the exported data may not work with older versions of the library. I am presuming in some future release the normals and texture coordinates will be optional (currently they are required).
Annoyances and amends
One annoying thing I found when working with a .js file is that the array variables in the file were tricky to find and copy to place in the Model.init() call. So, I made the converter place a list of the arrays at the top of the file in a comment, so copying is easy. So, if the Blender monkey was converted, the comment would be:
/*
monkey has…
507 vertices
2904 texture coords
946 normals
968 faces
monkeyVertices, monkeyNormals, monkeyUVs, monkeyFaces
*/
Another small annoyance was having to open a command line window just to convert the file. To fix this, I tweaked the code to properly accept files dropped onto the converter. However I haven’t tried this on my mac yet.
Now what’s left to do is more testing and porting over to Mac.
