I use ‘fprintf’.
If there is one thing I’ve learned about web-based game development, it’s to put as much flexibility as possible into these kinds of process. I’ve spent a LOT of effort getting model exporters and converters working as smoothly and painlessly as possible.
The first step is that we export models from either ‘blender’ or Maya into our own XML format (which is used in projects other than WebGL - Windows and Linux-based games, stuff I’ve been playing with on Nintendo-DS, etc). I wrote plugins for those two tools to do that. I’d like to get a working exporter for 3DStudio as well…but I don’t have the time/need right now.
(I dislike Collada because its importers and exporters don’t hold up to it’s original promise as a universal 3D format…it’s full of junk that I don’t need - and it’s missing robust exporters for stuff like skeletal mesh animation and shader parameterization.)
For WebGL I wrote a C++ program that uses TinyXML to load the XML file. We don’t mess with JSON - it’s just as easy to write JavaScript data structures directly and for this kind of data (98% of which is dense arrays of floating point vertex data), any ASCII format is as good as any other…so why bother with JSON? It’s just more stuff to go wrong.
This tool knows what kind of model it is (furniture, a human, a vehicle, etc) - and which of our games it’s going to be use in. I use this opportunity to aggressively trim the precision of the numbers in a way that depends on “game knowledge”. (eg, in “BarFight” where we’re talking about a ‘human-scale’ world no more than 40 meters across, positions are stored accurately to 1mm, normals to 1%, texture coordinates to the resolution of the texture maps, etc. In our upcoming “Ships of Oak” sailing ship combat game, precisions for things like islands are only accurate to the nearest meter, for ships, accurate to a centimeter, etc). I also trim leading and trailing zeroes and decimal points from the numbers and use exponential notation (eg 1e3 instead of 1000.0) whenever it’s more compact. This dramatically reduces the file size and the load times compared to JSON.
This XML-to-JS tool has a command-line option to emit nicely laid out JavaScript with neatly aligned columns of numbers, indentation and comments - so I can more easily debug art problems if I have to. I can also convert our XML format to JavaScript on-the-fly using a PHP program on the server that runs the XML-to-JS program and writes the results to HTTP. This allows the artist to simply dump his exported blender files onto the server and use his browser to start either the game, our model viewer, our animation viewer or our “DNA viewer” and get instant results - albeit with slightly slower download times.
We have two websites - one “live” site (tubagames.net) and one development site which is heavily password-protected and kept strictly “private” - we don’t even let the search engines “spider” it! The live site has only compressed JS files on it - the dev site lets you choose the uncompressed form from a preferences panel. The client code that runs in the browser can’t tell the difference. To “release” a game, we just run a batch file to bulk-convert all of the models - then copy all of the files on the dev site over to the live site. This is also automated to eliminate human error.
Since we use the “Unison” program to synchronize data between our computers and the dev site server (and also between the dev site and the live site) - it takes about 10 seconds (three mouse-clicks!) to sync the artists machine to the dev site - which sends .xml, .glsl and .png files from PC to server. When he hits “reload” on the model viewer, PHP converts models to JS as necessary and sends them back into his browser. That painless/rapid turnaround REALLY helps when you’re in the heat of art development.
As our games get more complex, with more art assets, I plan to have the PHP model “loader” check the timestamps on the .xml and .js files and only convert the ones that are outdated…but right now, for the two games we have in progress, the process is fast enough to be bearable.