Loading OBJ file - assetType - Geometry - how to set texture?

Software: Away3D 4.x

Avatar
Darcey, Moderator
Posted: 06 September 2012 02:14 PM   Total Posts: 209

Hi,

I have a simple AssetLoader - Loader3D loading a Blender object I created (single mesh).

The loader returns:
evt.asset.assetType = geometry
evt.asset = object geometry

If this was like “PlaneGeometry” I would be able to set via:
myMesh = new Mesh(geometry,texture);

However, this doesn’t work and the examples are all looping via AssetType.MESH.

This I thought would work but doesnt (no error returned)
//evt = AssetEvent from Loader3D
myMesh = new Mesh(evt.asset as Geometry,myColourMaterial);
away3DScene.scene.addChild(arrowMesh);

Anyone know how to set the texture on a lader geometry mesh?
or
How to load an OBJ model and set the textures manually?

Thanks

D

 

   

John Wilson, Member
Posted: 06 September 2012 04:22 PM   Total Posts: 62   [ # 1 ]

I import my Blender .obj files into Prefab3D and then export them as awd2 files - they are much smaller than .obj files.  If I don’t want to export a texture I switch off the “Save dependencies” button in Prefab.  If I do want to export the texture I switch on Save Dependencies and “Embed dependencies” options.

I then process the .awd file in as3 using something like:

private var loaderCutter Loader3D;

.
.
.

loaderObject = new Loader3D(falsenull);
loaderObject.addEventListener(LoaderEvent.RESOURCE_COMPLETEonObjectComplete);
loaderObject.addEventListener(LoaderEvent.LOAD_ERRORonResourceLoadingError);
loaderObject.load(new URLRequest('surprise_assets/Object/Object.awd'));


private function 
onObjectComplete(event:LoaderEvent):void
{
 
var m:Mesh loader.getChildAt(0).getChildAt(0) as Mesh;
 if (
m.material != null{
  
//The loader contains a texture image 
  
var t:TextureMaterial m.material as TextureMaterial;
  
//Assign lightPicker etc
 
}else{
  
//The loader does not contains a texture image 
  
var matTexture:TextureMaterial = new TextureMaterial(new BitmapTexture(bitmap.bitmapData));
  
//Assign lightPicker etc
 
}

Hope this helps.

 

   

Avatar
Darcey, Moderator
Posted: 06 September 2012 04:40 PM   Total Posts: 209   [ # 2 ]

Thanks for the idea, I will do a conversion and access it’s material that way via a prefab conversion, but only as a last resort…

I optimise my obj files considerably. The obj file I am loading is only 2kb.

If I have to convert an OBJ file to another format to be able to set it’s material, may as well remove OBJ support from Away3D.

I’m not a fan of this:
var m:Mesh = loader.getChildAt(0).getChildAt(0) as Mesh;
or
m:Mesh = loader.getChildAt(0)

Which are used in many examples, even on my site. Not an ideal way of returning data or to access a loaded object (max,obj,awd etc).

So, same question:

Does anyone know how to load an OBJ file and set it’s texture manually? This will allow for dynamic changing of textures also. An essential function I would assume.

I pref’ to manage the preloading and the application of textures myself.

If I get the answer this will also become an article on my website for everyone whom runs into the same situation.

Thanks

D

 

   

Avatar
Fabrice Closier, Administrator
Posted: 06 September 2012 07:01 PM   Total Posts: 1265   [ # 3 ]

The loaded Meshes are registered to the Assetlibrary. So any model generated by parsers, unless you have said otherwize, is accessible from a simple AssetLibrary.getAsset(“theNameOfMyMesh”);
From the above post I see that you embed. In this case, I would preffer to export as as3 as you do not require any loaders. You can then simply intanciate the AS3 and addChild it. If you need to access the meshes, each class export has a meshes and containers public that you could loop as well and for instance check on name. As its AS3, you can also directly add your props/lights by hand into the exported classes.
(an optional register to assetLibrary and better support of lights is on the todo). You have atm support for methods, normalmaps and specular map. So you can test your materials settinsg into prefab. No compile required.

However If your project is ment to use variable content, I would indeed go for awd2, as its fast, low kb and obvioulsy its only a start. The format, exporters and parser will be improved/dev sync with the engine. 

As I see that you guys want to access the meshes simply to assign the lightpickers to materials, you could add a simgle line after either your complete event or class declaration.
LightsHelper.addStaticLightsToMaterials(e.asset/mesh/container, lights:Vector.<LightBase> ); or without “s” to pass one single light.

Of course these are all personal prefs. You are free to pick the method you and project are most comfortable with.

 

   

Avatar
Darcey, Moderator
Posted: 06 September 2012 08:10 PM   Total Posts: 209   [ # 4 ]

Hi Fabrice,

There are no embedded models in the project. I was preloading them via Greensock’s LoaderMax api. The models I am using are all below 5kb.

So I guess I will have to: Blender > OBJ > Prefab > AWD2 > XML preloader list for (LoaderMax) > Away3D 4 > Dynamically assign textures to mesh by name.

I’m pretty sure Blender exports names of it’s meshes in OBJ?

But if I do adopt this new process flow it will put me in the position of how to get the model into Away3D 4 from LoaderMax?

Is there a Blender plugin available to bypass prefab? or is Prefab fine for Away3D 4 AWD2 exporting?

Relating to my OBJ issue.

As I am not embedding models, I’m using LoaderMax from greensock which preloads in lots and lots of stuff, I was then obtaining a string of the 3D model from it and placing that into the loader3D (which displays the model) eg:

preloader class

public var loader:LoaderMax;
loader = new LoaderMax(settings);
loader.append( new DataLoader(path to model.obj and item name) ); 

Which is then retrieved like so:

Model1View class

var modelString:String preloader.loader.getContent("item name");
var 
loader3D:Loader3D = new Loader3D();
loader3D.scale(900);
loader3D.addEventListener(AssetEvent.ASSET_COMPLETE,assetCompleteHandler);
loader3D.loadData(modelString);
// Normally I see view.scene.addChild(loader3D); here which works and displays a checkerboard model 


assetCompleteHandler” function

private function assetCompleteHandler(e:AssetEvent):void
{
    trace
("e.asset.assetType = " e.asset.assetType);
    
//traceoutput: Geometry

    // Examples I see here put getChild at index as loader is extending ObjectContainer3D but this will error

    // Examples I find also show how to handle material for type MESH
    // which is no good as the type returned in Geometry

    // And why wouldn't this work?
    //e = AssetEvent from Loader3D on this function params
    
myMesh = new Mesh(e.asset as Geometry,myColourMaterial);
    
away3DScene.scene.addChild(arrowMesh);

 

Some of my questions are:

1. Why addChild the loader? I know it’s extended from ObjectContainer3D wouldn’t it be better to take this from the loader in the complete handler?

2. If I can access geometry from the AssetEvent, how come that last bit of code doesnt work?

3. How does the AssetLibrary work? Is this automatically instantiated when Away3D is instantiated a view or scene? Do we have to set it up? How do we get it’s length? How do we iterate through it? How do we set a models name? What happens on conflicing names? How do I list all the Assets in the AssetLibrary? for a:* in AssetLibrary lists nothing and describeType doesn’t help either.

and most imporantly
4. Do you have any working code which can dynamically change the texture on a plane, cube, triangle,anything simple created in Blender exported as an OBJ and loaded into Away3D 4? Is this functionality available? Is just OBJ restrcited? Can AWD2 have it’s textures dynamically altered easier?


Thanks

Darcey

 

   

Avatar
Fabrice Closier, Administrator
Posted: 06 September 2012 08:57 PM   Total Posts: 1265   [ # 5 ]

1: sure, actually we builded it this way to allow quick dev and it was of course inspired by legacy. You should allways addChild on LoaderEvent.RESOURCE_COMPLETE. Then you are sure all is there (at least all is parsed), and of course add an error listener in case of. The term loader was there in my reply missleading, the context was either if you use loaders or a class.

2: That depends of what your model is composed of and how the exporter saves this information. In case of obj, there are many exporters outthere and many variations in their ouputs for the same model. So some exporter would for instance export an o tag, that we can use to read to set a mesh name, others will keep it to faces information only. Check if your obj exporter does set the o tag.

3/ via loaders meshes are registered to the library, you can define how it handles the names. You can add for instance a line like these before load anything.
new name overwrites old one or not,
AssetLibrary.conflictPrecedence = ConflictPrecedence.FAVOR_OLD;/New
or do as you please
AssetLibrary.conflictStrategy = new IgnoreConflictStrategy();
So duplicated names may at times give issues like now if you don’t do anything. (Prefab handles this for you).
If you generate by code however, you have to register the mesh to the asset library yourself.
Take a look at the assetLibrary doc and its package

4/you can change the material of any mesh exactly the same way that is a primitive, an extrusion, loaded mesh etc.. Once serialized as mesh they are all equal.

there are 3 ways to do so in speudocode:
- mesh.material = otherMaterial. To be used for material type changes or to toggle
- mesh.material.texture = otherBitmaptexture (in case of diffusemap only, but same for normalMap or specularMap)

- mesh.material.texture.bitmapdata
Sometimes you would want to do this, its actually changing the aspect of the material yet it’s just the BitmapTexture bitmapdata being updated. The material instance and its BitmapTexture(s) remains unchanged.

One case “help code doesn’t work” I often see is that (usually 3ds and collada) a default material is set on the mesh and then per subgeometry. Thats defined into the file. So if you change via code the mesh material only but let the subMesh material, you will not have the expected result as the subgeometry will be the one displayed.
There again, Prefab has a detailed mesh option to inspect your model subgeometry before using them in production.

As about bypassing Prefab, sure. You can export, compile get an eventual error and restart from your editor, Blender in this case or you see Prefab for what it is made for: help you and ease your work. Plus its not Photoshop, you drop a file on the icon or double click it and your model is on screen in matter of seconds. Yes Prefab awd2 are perfectly valid awd2 files. You could also load an awd2 from another awd2 exporter and reexport instead of using obj. You can download exporters installer here http://code.google.com/p/awd/

You have many choices, just pick the one that fits best your flow.

 

   

Avatar
Darcey, Moderator
Posted: 06 September 2012 09:14 PM   Total Posts: 209   [ # 6 ]

ok cool.
I’ve had a quick look at:
http://away3d.com/livedocs/away3d/4.0/away3d/library/AssetLibrary.html

If I was to take the example on github:
https://github.com/away3d/away3d-examples-fp11/blob/master/src/Basic_Load3DS.as

If this was just switched to using no assetLoaderContext and using an OBJ file like I have in my code in previous post. How do I get access to the mesh to change the texture via mesh.material.texture.bitmapdata?

Note:
var loader3D:Loader3D = new Loader3D();
//etc

Doesn’t return a type of MESH, for me it returns Geometry.
So I can’t use:

var myMesh:Mesh loader3D.getChildAt(0); // Which will error as it's returning geometry. 


Does Loader3D automatically put the asset into the AssetLibrary?

If I test this with:

trace"[" AssetLibrary.getAsset("Curve.001_Mesh") + "]" );
// TRACES: [NULL] 

Data for my OBJ model reads:

# Blender v2.63 (sub 0) OBJ File: ‘Arrow.blend’
# http://www.blender.org
o Curve.001_Mesh
v 1.466773 0.000000 -1.086387
v 1.473586 0.000000 -1.070784
v 1.488168 0.000000 -1.030132
etc

 

   

Avatar
Fabrice Closier, Administrator
Posted: 06 September 2012 09:21 PM   Total Posts: 1265   [ # 7 ]

what is the name displayed on your mesh in Prefab?

 

   

Avatar
Darcey, Moderator
Posted: 06 September 2012 09:24 PM   Total Posts: 209   [ # 8 ]

I just renamed the model in blender to “ArrowMesh” and re-exported obj, checked OBJ file and it now reads:

o ArrowMesh
v 1.466773 0.000000 
-1.086387
v 1.473586 0.000000 
-1.070784 

Which is correct.

Prefab shows the models name as “ArrowMesh”;

So I also tried in AS3:

AssetLibrary.loadData(modelString);
trace"[" AssetLibrary.getAsset("ArrowMesh") + "]" ); 

Result = null

 

   

Avatar
Darcey, Moderator
Posted: 06 September 2012 09:29 PM   Total Posts: 209   [ # 9 ]

Here’s the OBJ file.

 

File Attachments
DArrow.obj  (File Size: 9KB - Downloads: 154)
   

Avatar
Darcey, Moderator
Posted: 06 September 2012 09:36 PM   Total Posts: 209   [ # 10 ]

Just done a clean re-write:

loadObject()

AssetLibrary.loadData(modelString);  AssetLibrary.addEventListener(AssetEvent.ASSET_COMPLETE,onModelParseComplete); 

onModelParseComplete()

t.ttrace("e.asset.assetType = " e.asset.assetType); // geometry
t.ttrace("e.asset = " e.asset); // [Object Geometry]
t.ttrace"[" AssetLibrary.getAsset("ArrowMesh") + "]" ); // NULL

var myMesh:Mesh AssetLibrary.getAsset("ArrowMesh") as Mesh// ERROR
away3dScene.scene.addChild(myMesh); 

 

   

Avatar
Darcey, Moderator
Posted: 06 September 2012 09:47 PM   Total Posts: 209   [ # 11 ]

Just noticed I made a typo… Prefab name is “ArrowMesh1”.

I adjusted the code and result was the same….... However….. I accidentally removed the event listener clean up line in a test compile.

//AssetLibrary.removeEventListener(AssetEvent.ASSET_COMPLETE,onModelParseComplete);

And found that the function is being called twice?

1st run gives: Geometry
and
2nd run gives: Mesh

I’ve tested both executions of the function and both times:

trace"[" AssetLibrary.getAsset("ArrowMesh1") + "]" ); 

Result with: [NULL]

Any ideas?

 

 

   

Avatar
Darcey, Moderator
Posted: 06 September 2012 10:03 PM   Total Posts: 209   [ # 12 ]

Just tried an AWD2 version of my model, added it to my preloader and dumped it as a string to both Loader3D and AssetLibrary.loadData for test and both result in:

Errors with:

TypeErrorError #1009: Cannot access a property or method of a null object reference.
 
at away3d.loaders.parsers::AWD2Parser/proceedParsing()[L:\wamp\www\workspace\Presentation\libs\away3d\loaders\parsers\AWD2Parser.as:189]
 at away3d
.loaders.parsers::ParserBase/onInterval()[L:\wamp\www\workspace\Presentation\libs\away3d\loaders\parsers\ParserBase.as:420]
 at flash
.utils::Timer/_timerDispatch()
 
at flash.utils::Timer/tick() 


I’ve checked the data string being used and it’s dumping out gobldy gook characters for AWD2 but there is data going into it.

 

   

Avatar
Darcey, Moderator
Posted: 06 September 2012 10:23 PM   Total Posts: 209   [ # 13 ]

ok… 1 step closer…

Something wrong with the OBJ files coming from Blender for loading with Away3D 4’s OBJ Parser, I guess everything is different eh.

With AWD2 parser throwing an error, I decided to see if exporting as OBJ from Prefab would work… And guess what… It did, it increased the file size from 9kb to 133kb but it worked. I’m thinking that loading this into blender and decimating it may help.

The objects lighting is a mess (seems to be affected by vertices on a flat surface?) but I guess I will have to go for solid colour materials created in blender or something. Over to the blender forums I go lol

I guess I will have to make multiple faces/meshes and apply colour materials to them to get the lighting effect I need. I’m after a 3D button esque look just on a 3D curved arrow. Where the whole side darkens or lightens depending on position.

I will post links to tutorials in the forum once I get this sorted to a clean working process flow.

Thanks for the pointers Fabrice smile Love the new prefab by the way wink

 

   

Avatar
Darcey, Moderator
Posted: 06 September 2012 10:44 PM   Total Posts: 209   [ # 14 ]

Ok for blender OBJ export to work correctly:

1. Name your mesh, lets say for example “bob” in blender
2. Export your OBJ
3. Open your OBJ file in notepad++ or notepad etc
4. Find the line that starts with o (usually line 3 or 4)
5. Adjust the name of your mesh to “o bob”
6. You can now get the asset in AS3 via its name bob
7. On your modelComplete function, check for assetType == mesh before you remove/clean up the event listener or you wont get access to the mesh via AssetLibrary.getAsset(“bob”)


Fabrice or anyone… Any ideas on how to make the light solid on 1 surface instead of fracture on vertices? EG:
http://www.allforthecode.co.uk/dev/away3d/Away3D_4/TexturesLightsAndModels/

Thanks

Darcey

 

   
   

X

Away3D Forum

Member Login

Username

Password

Remember_me



X