How to find a Model

Tuesday, May 12, 2009 | 5:46 PM

Labels:

No, we're not talking about live models to use in your work, human or otherwise. This is about how to look up a 3D model from a file loaded in O3D.

The first thing that should be made clear is that O3D does not directly support loading models. Instead, it provides a framework for you to build your own model loading and we've provided a sample art path to do that. The sample art path is split into 2 parts. The first part, the o3dConverter takes a collada file and converts it into a gzipped tar file with a JSON file inside describing the scene and other files storing vertices, skinning, animation and textures. The second part is a sample loader in samples/o3djs/serialization.js which loads the JSON file and uses the data inside to recreate the scene in O3D.

The important points about that are:

  1. They are samples. If you don't like them or your application has different needs then change them.

  2. They are not directly part of O3D. There is no fixed file format for O3D. If you want to make better exporters that export to a format that matches your application better, you're free to do that. If you have a solution that solves a problem better than collada and our sample format does and you want to load that format, you have the power to do it. In fact, we are really hoping you will, and if we're lucky, you'll make your solutions available to the community.

  3. There are 4 parts to that entire path: The modeler you use, the exporter you use, the converter you use, the loader you use. You can replace or change any of those 4 parts if they don't meet your needs. It's also important to notice that what you get through our sample art path is dependent on the first 2 parts, the modeler and the exporter. If you have an exporter doing something you'd like done differently you might need to find a new one or write your own. For example, maybe you'd like your exporter to combine hierarchies of models into a single model. Or, maybe you'd like your art path to export things like "shape: {type: 'sphere', radius: '50'}" instead of saving out the mesh for a sphere and you'd like your loader to create spheres at load time when it sees that. More importantly, maybe you'd like to your exporter to export materials as they are in your art tool and then have your loader create materials that match instead of our sample art path which can't do that because it's limited by collada.

With that out of the way, let's talk about the sample art path we have provided and how to find a model. If you are not familar with the O3D API it might be good to review the technical overview doc, especially the part about the scene graph.

Assuming you loaded a scene like this:
 var path = "http://somedomain.com/assets/somescene.o3dtgz";

function loadCallback(pack, parent, exception) {
if (exception) {
alert("Could not load: " + path + "\n" + exception);
} else {
// Scene has been loaded.
}
}

scenePack = client.createPack();
sceneRoot = pack.createObject('Transform');
o3djs.scene.loadScene(client, scenePack, sceneRoot, path, loadCallback);

At this point, you can search for models in several ways. Most modeling packages show the name of the transform above a model instead of the name of the model itself. So, if you want to search by transform name there are 2 easy ways:
 var transforms = scenePack.getObjects("myModel", "o3d.Transform");

This searches the entire pack for transforms with the name "myModel".

another way is with:
 var transforms = sceneRoot.getTransformsFromTreeByName("myModel");

This searches a sub tree of transforms for transforms with the name "myModel". Both functions return an array of results.

Once you have the transforms, you may be able to use them as transforms, or if you want to find the shapes then you can try something like:
 // assuming you found multiple transforms
for (var ii = 0; ii < transforms.length; ++ii) {
var shapes = transforms[ii].shapes;
// now iterate through the shapes.
for (var jj = 0; jj < shapes.length; ++jj) {
var shape = shapes[jj];
}
}

Often, if you are making your own assets, you'll know the exact structure of your scene. For example, if you know there is only 1 transform named "house" and you know there is only one shape under it, you could just do the following:
 // get the 1 transform we expect.
var houseTransform = scenePack.getObjects("house", "o3d.Transform")[0];
// get the single shape we expect.
var houseShape = houseTransform.shapes[0];

On the other hand, if you know the name of the shape itself, you can look for shapes directly. I'm personally more familar with Maya and its default behavior is to automatically name shapes with the suffix "Shape". If you rename a transform to "house", the shape will be renamed "houseShape". In this case, if you know there is only 1 shape named "houseShape" in your scene you can do this:
 // get the 1 shape we expect.
var houseShape = scenePack.getObjects("houseShape", "o3d.Shape")[0];

The next thing to be aware of is that Shapes are made from Primitives. The point of having both Shapes and Primitives is that most modeling packages let you put more than one material on a particular model. For example you could make a house and texture the walls with one material and the roof with a different material. If that was one shape in the modeler, it would load as one shape in O3D with 2 primitives. The sample o3dCoverter takes the names of the materials and appends them to the name of the shape to make the names of the primitives. Assuming the name of the house shape was "houseShape", the primitives will be named "houseShape|roof_material" and "houseShape|wall_material".

Primitives can be found similarly to how we found previous objects.
 // get the 1 primitive we expect.
var housePrimitives =
scenePack.getObjects("houseShape|roof_material", "o3d.Shape")[0];

Or probably more useful, assuming we have already found the shape for the house following the methods above we can use:
 var housePrimitives = houseShape.elements;
for (var ii = 0; ii < housePrimitives.length; ++ii) {
var primitive = housePrimitives[ii];
...
}

I hope this makes things a little clearer. It would be really awesome if some of you will take up the challenge and go off and make some improved exporters, better converters and better loaders that provide even more solutions. We've heard from the community that a custom Blender exporter is being worked on. We'd love to see exporters for other modeling packages that take advantage of the specific strengths and features of those packages.

If there is anything you'd like to us to post about or other questions you have please join us in the o3d discuss group. We really appreciate your ideas and feedback.

2 comments:

Dominiek said...

Hello there,

I'm currently writing my thesis and doing some experiments with O3D. I have to say it looks really promising already. I would however like to see the documentation for the O3D Animation API, does anybody know when this will be available?

Thanks in advance and congrats on your work so far!

Unknown said...

Do you think is so powerful to move FLash developers to O3D?