If it works the same way as the Collada parser, you now need to instantiate the parser in order to set the material.

Previously, you could have done something like this:


var model:Object3D = Obj.parse (ModelObjFile, { material: TextureFile } );


Away3D would have then automatically instantiated the mesh class, and turned the bitmap class into a bitmap material. However, the new version doesn't appear to support this from the static function above, which seems to bring it in line with Away3DLite. The new version brought significant performance improvements I hear, which is a great thing, so since we can still accomplish the same thing as above, I won't complain!

Here's how it works now:


var parser:Obj = new Obj ();
var model:Object3D = parser.parseGeometry (ModelObjFile, { material: TextureFile } );



If that doesn't work, you can use Cast.material or something else that's more verbose. I can't remember if I tested the above syntax with only the Class reference for both the mesh and material, but I assume it probably still works. The material property is not a standard Object3D property. It's available for primitives, but not when you load a different model. The materialLibrary allows the model to support multiple textures. The downside is that usually people say that you need to memorize the names of your textures, but not so, fortunately. As I think I mentioned in my past email, you can't set material directly after you've instantiated the model, but I hope the example above will give you what you're looking for. After instantiating, you can swap it out like this:


for each (var materialData:MaterialData in model.materialLibrary) {

materialData.material = Cast.material (TextureFile);

}


Not too hard, right?





On Thu, 19 Aug 2010 03:51:09 -0700, dsirijus <[email protected]> wrote:

I still don't get this one.

Why does simple
var model:Object3D = Obj.parse(new ModelObjFile());
model.material = Cast.material(new TextureFile());
does not work (there's no material property anymore)?

Is there something that does work along these lines? I DO NOT want to
touch materialLibrary.

On Aug 11, 8:55 pm, "Joshua Granick" <[email protected]>
wrote:
Hi everyone,

I recently updated to the latest revisions of Away3D, and I lost the ability to set an object's material at runtime.

This may or may not be obvious to others, but I wanted to share how this works in the latest versions. Many of the examples I've seen are either for loading a mesh (Collada, 3DS, BSP, etc) and relying on Away3D's built in loader for textures, or they use an Away3D primitive (Cube, Plane, Sphere, etc) and set the material property. Personally, I prefer to either load textures myself, or embed them in my classes (the Embed meta tag is blocked in Flash Professional, but should work with FlashDevelop or Flash Builder). Either way, I like to apply textures at runtime myself.

Doing this before was pretty simple. It looked like this:

var object:Object3D = Collada.parse (Mesh, { material: Texture } );

If Mesh and Texture were classes, containing embedded geometry and bitmap data, Away3D would put them together automatically. Of course, if you wanted to use a different material, or customize it a bit more, you could also pass your own material, like these examples:

var object:Object3D = Collada.parse (Mesh, { material: new BitmapMaterial (Cast.bitmap (Texture), { smooth: true } ) } );

var object:Object3D = Collada.parse (Mesh, { material: new WireColorMaterial () } );

However, in the latest versions of Away3D, this no longer works. It will ignore the material property entirely, loading either the default flat texture, or using the built-in loader to try and download and display an image texture. That doesn't work for me, so I went looking around for how I could (again) merge my meshes and textures like I wanted. Here's how:

var parser:Collada = new Collada ( { material: new WireColorMaterial () } );
var object:Object3D = parser.parseGeometry (Mesh);

That will override all the materials defined in the Collada, and replace it with a new material. If you need more control over the process, you can also do something like this:

var parser:Collada = new Collada ();
var object:Object3D = parser.parseGeometry (Mesh);

object.materialLibrary.getMaterial ("lambert1").material = new WireColorMaterial ();

for each (var materialData:MaterialData in object.materialLibrary) {

        if (materialData.name == "lambert1") {

materialData.material = new WireColorMaterial (0xFF0000);

        } else {

materialData.material = new WireColorMaterial (0x00FF00);

        }

}

One of the things I like most about setting either a single material at runtime, or iterating through the material library is that you don't need to remember the names of all your materials. If you have five models which need the same material, you don't need to remember if one was named "lambert1" and the other was named "lambert2".

All in all, I like this way of parsing better than how I did it before. This feels closer to Away3DLite, and it makes it easy to swap out the parser. Since my old approach used the public static method to parse, it meant that I needed to know beforehand which format the mesh was in. However, with the new approach, I could easily create a loader that supports multiple model formats, like this:

public function loadObject (mesh:Class, material:Material, parser:Class):Object3D {

return new parser ( { material: material } ).parseGeometry (mesh);

}

So that's that! I know I was a little stuck figuring out how to do this, both the first time, and the second time. I hope this helps someone!


--
Joshua Granick
Owner / Lead Developer
[ eclecticdesignstudio ]
P: (916) 889-7306

Reply via email to