3DS model, Why can I not change material TYPE?

Software: Away3D 4.x

Mike Samuel, Newbie
Posted: 25 June 2012 07:05 AM   Total Posts: 30

Hello,

I’m loading a 3ds model, (created / exported from Blender 2.6x) using Loader3D.
This is all working, I can see the model in flash as expected. Shapes, Colors, A-OK.
However if I try to change a mesh’s material from ColorMaterial into TextureMaterial the movie stops working.
The default material type is always ColorMaterial when I check on import, even if I assign a Texture in Blender.

here is the relevant LoadComplete handler I use (important parts only)

private function onModelCompleted(event:LoaderEvent):void
{
  var mesh1:Mesh;
  trace(“model loaded”+_loader.numChildren);
  for (var n:int = 0; n < _loader.numChildren;n++ )
  {
  mesh1 = _loader.getChildAt(n) as Mesh;
  //This is always working, I can assign color material at will!!
  mesh1.material = new ColorMaterial(0xFF0000);

  //This will not work, WHY?
  mesh1.material = new TextureMaterial(new BitmapTexture((new texCaRed()).bitmapData));
  }
}

The TextureMaterial itself is working fine, I can assign it to a simple Plane or Sphere just fine.

Am I missing something or is it not possible to change the the TYPE of a material once set? If so, how can I tell the 3ds file to use TextureMaterial up front?

Anyone any ideas what I am doing wrong?

Regards

Andreas

 

 

   

Ivan Moreno, Newbie
Posted: 25 June 2012 10:56 AM   Total Posts: 22   [ # 1 ]

Hello,

Storing multiple materials inside the meshes I found it complicated and not performance friendly, it is better for me to store them in a vector or an array and interact with them in runtime. Something like this:

private var colorMaterial:ColorMaterial = new ColorMaterial(0xff0000);
private var textureMaterial:TextureMaterial = new TextureMaterial(new BitmapTexture(new mytexture().bitmapData));//create the materials in the initialize method…

private var myMaterials = [colorMaterial, textureMaterial];//store them in the initialize method…

private var myMesh:Mesh;

after loading your mesh you can select the material by index:

private function meshComplete(e:LoaderEvent):void{
  for (var n:int = 0; n < _loader.numChildren;n++ )
  {
  myMesh = _loader.getChildAt(n) as Mesh;
  myMesh.material = myMaterials[0];
  myScene.addChild(myMesh);
  }
}

then in the update method you can just toggle them as you want:

private function update(e:Event):void{//==> EnterFrame event
  if(foo){
    myMesh.material = myMaterials[0];
  }else{
    myMesh.material = myMaterials[1];
  }
}

It is good for performance reasons that you use at minimum the amount of materials, lights, filters, shaders, etc. and if it’s possible reuse them when you can. If what you want to do is replace the textures of the mesh, in that case the procedures would be similar but you will modify the textures on the texture material instead of the material of the mesh.

I don’t know how it works the exporter in Blender, but I had experienced some path issues/errors with most of the parsers especially with the Max3DS one. So, I like to export the model without any material or texture information and then apply them inside Away3D. The important thing is how you unwrap your UVWs inside the modeling software.

I’m planing to make some small tuts about this in the upcoming days/weeks. I hope this is what you need.

Best.

   

Mike Samuel, Newbie
Posted: 25 June 2012 03:12 PM   Total Posts: 30   [ # 2 ]

Thank you for your lengthy reply Ivan.
I’m afraid in my attempt to simplify/shorten my example code I made things worse. Sorry about that. I meant to state ..if I assign a colorMat, it works, if I assign a textureMat, it does NOT work.
You are correct, I should (and I do) create my materials once in init().

Let me try again.
materials are stored in:  _colorMatDic and _texMatDic.
3ds model loaded into:  _loader
and a plain sphere mesh : _mSphere

The sphere is created like this
SphereGeometry sg = new SphereGeometry(64,12,12, false);
_mSphere = new Mesh(sg, _colorMatDic[“red”]);
_mSphere.geometry.scaleUV(32, 32);

Lets say I have an update method similar to your example

private function updateMaterials(var foo:Boolean, var name:String):void{
  
if(foo){// use colormaterials
    
_mSphere.material _colorMatDic[name];
    for (var 
n:int 0_loader.numChildren;n++ )
    
{
      
var modelMesh _loader.getChildAt(n) as Mesh;
      
modelMesh.material _colorMatDic[name];
    
}
  }else{
// use TextureMaterials
    
_mSphere.material _texMatDic[name];
    for (var 
n:int 0_loader.numChildren;n++ )
    
{
      
var modelMesh _loader.getChildAt(n) as Mesh;
      
modelMesh.material _texMatDic[name];
    
}
  }

Lets also assume, all the color and texture materials are created, the model is loaded, all A-OK, I see the model and the sphere on stage.

In code, I can now do:

updateMaterials(true,"green");   //Sphere and model turn green
updateMaterials(true,"blue");     //you get the idea 

but if I do this

updateMaterials(false,"lines"); 

only the sphere shows up in lines, the 3DS model does not.

Disregard any performance issues for now, all I am try’n to do is change the models materials on user interaction.

The sphere is just there to experiment / show the texture materials are working. However I can not assign the Texture Materials to the 3ds model. Only the ColorMaterials are working @the 3ds model. Why?

I’m sorry for the lengthy post, I don’t know how to explain this differently.

Regards,

Andreas

 

   

Ivan Moreno, Newbie
Posted: 25 June 2012 03:44 PM   Total Posts: 22   [ # 3 ]

I think the problem is related with the texture path of your 3DS file. When you compile your app the console doesn’t throw any error? Have you tried to use AssetEvent instead of LoaderEvent? If you have no chance to modify your own models settings then you can use the AssetLoaderContext, which will pass the texture path of the material into the loader to prevent stream errors. Something like this:

var assetLoaderContext:AssetLoaderContext = new AssetLoaderContext();
assetLoaderContext.mapUrlToData("path/to/myTexture.jpg", new myTexture());
_loader.loadData(new myModel(), assetLoaderContext); 

If this doesn’t work then would be better to have more details of your code. I’m 100% sure that you can replace materials and textures in 3DS files.

   

Richard Olsson, Administrator
Posted: 25 June 2012 03:53 PM   Total Posts: 1192   [ # 4 ]

Does the model have UV coordinates? You say it “doesn’t work”, but are you getting any error messages? Do you have the debug version of Flash Player?

Try setting Debug.active = true somewhere early in your code. That will, among other things, activate Stage3D error-checking, which should definitely throw errors if there are any render problems.

   

Mike Samuel, Newbie
Posted: 26 June 2012 04:56 AM   Total Posts: 30   [ # 5 ]

Thank you Ivan and Richard for all the help / tips.

I finally got it.
So yes, I was missing the “AssetLoaderContext” part.

And, I did not create a UVMap. In my blender model, I did assign a Material and a Texture. But only the build in marble, wood textures stuff

Once I loaded my image texture into Blender, created the UV map for each individual mesh. Voila, Export -> loading .. and the material type in away3d is now textureMaterial and I can assign different textures within flash.

So I guess there was never something wrong with my code, I was missing the fact that I must create a UV map / Texture.

Lesson learned.

Yet, I do not completely understand why.
If I create a simple PlaneGeometry or Sphere in code , I can assign a TextureMaterial without any extra work

Is there a fundamental difference between meshes created in code vs. loaded from 3ds file?

Thanks again

Andreas

 

 

   

Richard Olsson, Administrator
Posted: 26 June 2012 07:37 AM   Total Posts: 1192   [ # 6 ]

You don’t need AssetLoaderContext unless you want to replace textures at load-time with other textures. You also don’t need to assign a texture in Blender, all you need to do is make sure the object has UV coordinates. And even that isn’t necessary if you’re using the release branch of Away3D (which will become the final stable 4.0 release.) In that version dummy UV coordinates are created automatically if they were missing. However, dummy UVs will likely not result in the textured output you want.

The reason the model needs UVs is that otherwise the shader running on the GPU can have no idea of what pixel from the texture goes where on the surface.

Primitives (planes et c) already have UVs. These are defined procedurally, according to the same algorithm that the defines their geometric shape. When you load models however, it is extremely difficult for the engine to “unwrap” the model procedurally, and even if it did it wouldn’t match the texture so such functionality makes little sense. Instead, you have to explicitly define UV coordinates (by making sure you include it in your export from Blender or whatever editor you use) or, in the release branch, the engine will assign dummy UVs.

   

Mike Samuel, Newbie
Posted: 26 June 2012 04:20 PM   Total Posts: 30   [ # 7 ]

ic, very informative, thank you.

Regards

Andreas

   

fmax, Newbie
Posted: 20 October 2013 03:38 PM   Total Posts: 10   [ # 8 ]

Try it:

var mesh:Mesh [the mesh for changing]
for each (var item:SubMesh in mesh.subMeshes{
item
.material null;
}
mesh
.material = new ColorMaterial(0xFF00FF); 
// or another material... 
   
   

X

Away3D Forum

Member Login

Username

Password

Remember_me



X