EZMesh is a plugin and script for 3ds Max that will export models into a very simple format that one can easily load into their 3d application or game. This is intended to be a reference implementation for anyone out there interested in exporting art.
Download ezmesh.zip and install by putting the script ezmesh.ms into $maxroot/scripts/ subdirectory and the plugin ezmesh.dlm into the $maxroot/plugins/ subdirectory. Its compiled for version 7, but should work in later versions. The source for the plugin is also provided in the zip file. To run the script goto the MaxScript Menu and select the "Run Script..." menu item and when the file selector dialog pops up chose the ezmesh.ms file and click Open. Then the exporter becomes available in the utilities panel. If you prefer to run the script automatically then move it to the scripts/startup/ folder.
The exporter supports bones and skinned meshes that use Max's skin modifier. The bones can be any type of node (don't have to be Max bones) and can be animated. During export, the mesh is processed so that it takes into account smoothing groups and does what is needed for those places on the mesh that aren't smooth such as where the same point has different normals depending on which triangle is being drawn. The tangent space basis is also calculated (used by many shaders such as bumpmapping, parallax). If the mesh is manifold, the exporter also generates bevel triangles so the mesh can be extruded in a vertex shader to compute shadow volumes.
The script and code are easily customizable. The format is xml based but could easily be replace with different tokens if there is something which would be easier to parse. In fact, EZMesh is not meant to be any sort of "product". Rather, it is intended to be a good starting point (or just reference code) for game developers, hobbyists, or students who just want to get artwork into their game or 3D application.
Why? - That is a very good question. There are dozens of file formats and exporters out there. Why do we need another one? Personally, I would love to see the industry converge to single set of standards. Not just for file formats but also graphics and physics apis, handedness for coordinate systems, choice of up axis, math library api, file syntax (xml vs curly brackets), string library, etc.. Consequently I've been reluctant to make this exporter public since I don't want to add to problem. However, the file format here seems to fill a niche. It is a simple human-readable xml (ascii) based format that semantically represents meshes the way 3D applications want to see them. It fulfills the most important development objective - getting the job done.
I usually hate it when a technical article takes a long trip down computer science memory lane - it is often the sign of a boring article. So i'll keep the history short - just enough to put things in context and explain where we are today. A long time ago (in the mid 90s) it was easy to load a model and render it with state of the art (opengl 1.0) graphics. All the programmer had to do was read in a simple file format that consisted of vertices and triangles. The file format would typically have been wavefront's obj or some simple variation. Such file formats were easily extended to add color, normal, and texture coordinates as necessary. Because the graphics APIs were functional at the sub vertex component level, it didn't matter much how this data was organized. Triangles could consist of many sets of indices into a number of vector spaces (position, color, uv, normal, etc.). That doesn't work so well today. To accommodate larger models efficiently on current hardware, the preferred runtime format consists of just triangles and vertices where a vertex can be thought of as an element of a higher dimensional space that is the cartesian product of position space, color space, normal space, blend weight space, bone index space, etc.. Consequently, instead of a file format designed around the internals of max or maya or a combination of a number of DCC tools, what the game programmer would love to see is an easy readable file format that is simply a list of these higher order vertices and a list of triangles. Such a data format can be fed directly to anybody's engine. In other words, today's game developers doing next generation rendering (such as weighted boned skinned meshes with parallax occlusion mapping) can have mesh data files that really are just as simple as the .obj files used long ago.
Here's a sample of what the data looks like for an exported box:
<model name="Box01"> <mesh> <material>checker</material> <vertexbuffer count="24" semantic="position blendweights blendindices normal color texcoord tangent binormal"> -2.5 -2.5 0 1 0 0 0 0 0 0 0 0 0 -1 255 255 255 255 1 0 -1 0 0 0 1 0, ... </vertexbuffer> <indexbuffer count="12"> 0 6 9, 9 6 2, ... </indexbuffer> </mesh> </model>
Skeleton and bone animation data can also be exported.
If you are familiar with the d3d function IDirect3DDevice9::DrawIndexedPrimitive or the opengl equivalent, then you can see that the file format is simply a reflection of the data structures you render with. The schema was already defined. So I didn't really invent a new file format. I simply represented this data in ascii by following xml conventions and picking the most appropriate tag names. To have done otherwise would have made me guilty of creating a new file format.
To make use of exported meshes you'll want your application to be able to load vertex and index buffers and pass them to the graphics api. From the format, this should be obvious how it can be done.
Many shaders, Few vertex formats: There are a number of ways to implement this. Generalizing is a good thing to do, but only when it is appropriate. There are many possible shaders that a 3d application may wish to use and even more shaders that haven't been written yet. So any application should support adding shaders later on - preferably without requiring a recompile. However, an application doesn't have to add vertex formats that often. It may even be possible to get by with 1 if there isn't a significant cost in ignoring unused components. Therefore, developing a graphics system that allows for general vertex formats isn't as useful as it may seem, but rather will likely cause more debugging headaches due to the overgeneralization and extra code indirection that the programmer will have to sift through when things go wrong. In other words, in your C/C++ code just implement a class or struct that maps directly to the vertex format(s) instead of implementing a generic system that can represent any vertex class with a void pointer. If you ever need to add another vertex class (to support a 2nd uv channel or something) then just add another struct/class when the time comes. You can still write template based utility functions so, for example, you don't have multiple implementations for determining the bounding box of a mesh. Just my 2c on the subject, feel free to implement your engine how you see fit.
If there is interest, I could provide a reference implementation for importing EZM data and rendering it in a window. Currently, no such SDK is provided. I anticipate that if anybody actually adopts this, then they would prefer to use their own I/O and math routines. Furthermore, they would want to customize it to their needs. For example the exporter could be extended to also output data such as character attributes, jersey number, hit points, mass, inertia or whatever else the developers engine might be able to make use of. In one sense, the point of making EZM public is to provide an alternative starting point to .ase or .asc.
The following pictures show an example of how game art production works. Ok, I admit this is just an excuse to show-off my incredible modeling, animation, and texturing skills by showcasing some of my totally awesome "programmer art".
Its easy to set up the export utility to automatically run a viewer application (or game engine) and provide the newly created file as a command-line argument. Then the artist can test his creation with a single click.
So why 3dsmax? - Artists often use a mix of DCC (digital content creation) tools for the various aspects of production. Perhaps, textures are created in photoshop, the models created in zbrush, rigging is done in 3dsmax, and poser is used to help animate. Thats ok. In this case, 3DSMax often serves as a hub for all these tools to work together and therefore is still a logical place to be exporting content into the game. The exporting code is small and simple because it assumes that its deriving its output from Max's internal trimesh class. These objects use smoothing groups and extra sets of indices for color and texture information. Maxscript isn't the ideal language to implement geometry processing and conversion, so that part was implemented in a dll plugin. Everything else was implemented using maxscript to allow for easy customization.
At a previous game company, we built c++ and maxscript exporters based on similar principles - to get artists content into a form that the game engine could work with. Those implementations stayed with the company. Years ago, I taught a little graphics course at BCIT, and I wanted to introduce the notion of a graphics pipeline to the students. IMHO, the last thing educational institutions need to do is teach computer science students to create content by typing numbers into a cpp file. I supplied a simple maxscript exporter to dump out Max's trimeshes and a utility function to convert the data into a format that could be digested by d3d - i.e. a vertex and indexbuffer.
Later when I was working for Ageia, John, a famous long time game developer, wanted some graphics meshes for Rocket, the company's flagship demo. We had no intention of creating a graphics exporter, but we just wanted something quick while we waited for collada tools to be developed. We looked at what else was available at the time (asc, ase, vrml, etc...) - nothing fit the requirements. So I polished off the bcit exporter and made some minor changes to add functionality that was needed. When John looked at the file format, he said "that's so easy" and named it "Easy Mesh" with extension ezm. The exporter was designed to work alongside (but separate from) a physics exporter that would generate and export convex hulls for the bones and joints with limits for the hierarchy of an articulated model. Other than a few demos I don't think that ezm got used much. Ageia's goal was never to provide graphics pipeline or engine solutions, but rather provide a physics runtime and help developers integrate physics into their existing games and art pipelines.
Fast forward to 2007. For a recent project I just needed to get some skinned meshes up and running. I did look around to try and find an off the shelf standard to use, but ran out of time sifting through all the stuff that is out there and consequently not actually getting anything done in the process. Even if I had adopted something else, I would probably still end up implementing a conversion from that semantic into a vertex and index buffers. The goal is to provide a button in 3dsmax that will export something and have it pop up in a viewer immediately. Consequently, I just updated (and continue to update) the ezm code as needed. Although, I was tempted to rename the extension to .btdt (been there done that) :-)
Personally, I'd prefer for something to come along and replace the need for game developers to implement many of their own systems. Ideally any off-the-shelf solution should not be overwhelming for the developer, force unnecessary systems on him, keep him in the dark, or somehow limit what he can do. Despite years of seeing many standardization initiatives come and go, I still have high hopes that the industry will rally behind a single good solution someday.
why not fbx or collada - First of all I'd like to turn the question around and ask why do both fbx and collada exist? How is a developer supposed to pick the right solution with so many out there. Also, these were primarily designed as interchange formats and they work well in that respect. As for exporting into my application, I've looked at the fbx sdk and I found the viewer application to be rather complicated - sigh. The rendering iterated through elaborate structures and made many opengl calls per vertex. Furthermore, it looked like it was using SDK functions to do the deformations in software. i.e. The sdk and samples simply fell short of going all the way to creating a vertexbuffer and indexbuffer along with a matrix palette. This was rather disappointing since I would assume that every single game developer would want to see just that. I'm sure it could be done by the end developer, but in my case, I don't have time right now. I have higher hopes for Collada. The initial focus of Collada was on the interchange amonst Max, Maya and XSI and the process of turning collada files into game-ready assets was "left as an exercise for the reader". Since then I'm sure the remaining pipeline tools and render libraries are now complete. Hopefully it just a matter of plug-and-play with minimal integration effort required to use Collada. Check out feelingsoftware.com for the latest information on this. The ezm format follows some collada conventions where applicable. Collada doesn't specify a runtime xml schema. If it did then it might look like ezm. Consequently, a better pipeline strategy would be to generate ezm files from collada assets instead of 3dsmax's internal data structures.
But these formats support so much stuff. - But would you use a swiss army knife to open a can of soup if you were in a kitchen that had a regular can-opener handy? Sometimes people just want a simple tool that does the job they need done. The vertex and index buffer format the ezm covers what game developer typically need for rendering the art - even using advanced shaders. I have no desire to convince anybody to adopt any particular mindset. The choice is up to the end developer what he feels most comfortable with.
What about other things like lights in the scene? - Stuff like that is really simple. I believe its easier for a game developer to simply add some code to export lights (or even a custom node type) into a file format that matches the data structures of his engine. The game developer is going to have to do some sort of conversion step at some point anyways.
What about .X? - I believe that .x was initially intended to support the d3d samples that were included with the directx sdk. Because it happened to be included in the d3dx utilities, it was easy for game developers to just use the mesh format, which explains its widespread adoption. It would have been nicer if it was xml based. The comma and semicolon strategy doesn't help this ascii format be human readable. The parsers and exporters for .x should be public source. (actually i don't even know if they are.) .x seems to be more based on fvf and fixed function thinking. I found the d3dx interface to .x data meshes to be too opague. Furthermore microsoft is moving away from .x into something else. That seems to reinforce my earlier decision not to use it.
What about xna's pipeline with .xnb files - Like all the other formats I would have spent days studying it and trying it out but as far as I can tell its only available to xna c# users. I'm a c++ guy and I'm not sure I want to throw everything away and switch to c#. Many years ago I decided not to jump on the java hype bandwagon - a now dead language. More recently, I chose to ignore the (now deprecated) managed directx offerings. I'm not against xna and c#, but I'm going to take a wait-and-see approach before switching languages. Is microsoft going to make the xna pipeline available to C++ developers? I assume this time that they aren't planning to move XNA to the "legacy pile" soon :-)
What about granny - I believe that its probably a great exporter with a good set of easy to use runtime routines. After all, it was designed by seasoned game developers who know what game developers want. Unfortunately, it costs money; so I have not been able to try it.
What about vrml? - Many many years ago, I did take the time to write a parser for vrml files (version 2 at the time). I do recall that it was a huge effort to parse the format and support all the various node types. I did all that despite already having much easier loading and rendering code for lightwave files and the files we then exported from max (which could also do a lot more than vrml could back then). I had thought it was going to be worthwhile to support and promote the "3D standard". I was wrong. VRML didn't really take off. Sure dozens of vrml models were put up on the web. Unfortunately, there was never any consistency on scale and origin placement and axis alignment. This made it impractical to actually use available vrml models even for a hobby project. So if you have to pull it into 3dsmax to fix it anyways, then why not just export to a file format that you can easily work with instead of vrml? Im still hoping for a single 3d standard to emerge. Admittedly, I haven't been keeping myself up to date with what's been happening in the world of vrml (x3d now), nor have I studied their newest schema and ISO standards documents.
What about all the engine exporters out there? - good question, I'm sure there is one out there that already does exactly what is needed. And its probably part of an open source project too. There are over 280 engines in the devmaster.net database. How long would it take to sift through this list, download the promising candidates, and dig into the package in the hopes of finding what you need. BTW, it doesn't take that long to roll your own simple exporter.
page updated: october 2007