Two days lost, but not entirely wasted. I have been trying to figure out how to change the material of a mesh object imported into a Papervision3D scene graph as part of a Collada 4.1.1 scene that I had exported from Maya. No matter what I tried, I could not change the material for an individual mesh object at run time. I was using all the provided methods with no luck. For example, the one that should do the the trick is:
dae.getChildByName("COLLADA_Scene").getChildByName(meshName).replaceMaterialByName(new ColorMaterial, materialName);(dae is a DAE object; meshName is the string name of the mesh in the collada scene whose material you want to change, and materialName is the string name of the material you want to replace)
But no go. The strange thing was that I could print the list of materials that I had imported from the Collada file by using:
for (var name:String in dae.materials.materialsByName){ trace(dae.materials.getMaterialByName(name).toString()); }
Whats more, the materials (BitmapFileMaterials in my case) loaded fine onto the meshes and were visible when the program ran (e.g., see previous post). But there seemed no way to access those materials once the program was running. There seemed to be no accessible references between the material list for the scene and the individual meshes in the scene.
So, I dug into the most recent version of DAE.as class from Papervision3D. And what did I find: The materials are applied to each of the individual triangles in your mesh (I am assuming that your mesh was triangulated during Collada file creation, so lines 1442-1461 in the DAE.as file holds the relevant code) but not to the object as a whole. So, while the mesh object has no record of its material, each of the individual triangles of the mesh do. Still, there seems to be no reference from the main materials list for the DAE object to these triangles; because changing the material in the main materials list has no effect on the rendered scene. So: What to do?
The first solution I thought of was to write a function for swapping the material of a mesh object on a triangle per triangle basis. What follows is a functional but very simple version, without the desirable checks for nulls:
public static function swapObjectMaterials(dae:DAE, objectName:String, material:MaterialObject3D):void{ var length:int = dae.getChildByName("COLLADA_Scene").getChildByName(objectName).geometry.faces.length; for (var i:int = 0; i < length; i++){ Triangle3D(dae.getChildByName("COLLADA_Scene").getChildByName(objectName).geometry.faces[i]).material = material; } }
That is all you need to fix this problem (well, it fixed it for me).
The better solution would be to fix the load of the DAE object so that there remains a reference between the main materials list and the individual triangle meshes, such that changing a member of the materials list changes that material on each of the individual triangles. Time permitting, that should be done within the next couple of weeks.
From a design perspective, it makes perfect sense to apply the materials on a per-triangle-face basis in order to conserve any uv mapping that was done in your modelling program; still, the reference issue needs fixing.
As an endnote: Having fixed the above problem, I ran into another problem. I had been interested in swapping a BitmapFileMaterial with a texture for a MovieMaterial. While the above function swapped them, the uv mapping was conserved such that the new MovieMaterial was applied with the old uv coordinates. I fixed that problem too...stay tuned for when I have some more writing time.












DAE material access...
I struggled with the same problem, found Your blog paralell to an alternative way to run-time access all the "hidden" materials in a loaded DAE attached to a scene.
Without modding DAE.as, You can get a dictionary object of all materials (real ones-pv3d) You simply iterate through the materials.materialsByName property of Your DAE object, for example like this:
Basically You access the base class of the DAE class, witch is DisplayObject3D, where the materials from the XML are "pushed" into. These hold the real reference of the in-scene (rendered) materials.
There is a missing feature of the DAE parser - it won't store the NAME of the materials.
The trace( mat.name ) in the above example will yield in "null" in all cases.
The "implementation" of it is REALLY simple.
In the function DAE.as::buildMaterialInstance(...) just put before the last "return material" (at line 1028)
This way the super class of the DAE will have the MaterialsList elements name property set right. After this You can access the material You want by (for example):
Have a nice day, and good coding!
dbam.
Please help, i need to
Please help, i need to change the dae texture to another, im not a programer and is very dificult to me understand, can you help me please??
this is my code, i have three textures, "textureA, "textureB" and "textureC"
package {
import flash.events.Event;
import org.papervision3d.objects.parsers.DAE;
[SWF(width="640", height="480", backgroundColor="#ffffff", frameRate="30")]
public class AR extends PV3DARApp {
private var frigo:DAE;
public function AR() {
addEventListener(Event.INIT, _onInit);
init('Data/camera_para.dat', 'Data/marker.pat');
}
private function _onInit(e:Event):void {
frigo = new DAE();
frigo.load('model/frigo.dae');
frigo.scale = 20;
frigo.rotationX = 90;
_markerNode.addChild(frigo);
addEventListener(Event.ENTER_FRAME, _update);
}
private function _update(e:Event):void {
frigo.rotationZ -= 0;
}
}
}