nomatter
2fév/1011

Cinema4D Collada Corrector for Away3D and Papervision3D

---- EDIT : 15 may 2011
Cinema4D.as has been updated, bug fix : script added material property on objects that doesn't need it, cause Away3d parser to crash
AIR Application : Bug Fix, now REALLY update the file... (thanks to Tobias Richter! )
----

Welcome on my blog! You're reading my first post congratulations!

Well what's the subject? Oh year a "Cinema4D Collada corrector" for Away3D and Papervision3D...

On my last project I've got an issue when I tried to integrate a 3D model with several objects AND textures in Away3D.
It seems that, when coming from C4D, Away3D and P3D parser's take the same texture for all meshes. Even if I'm really not an expert in Collada, I'd searched throw the collada's file and parser what happened.

After some headaches to understand (a bit) how a Collada file is constructed (love the node's node's node's imbrication, and some id that "bind" textures to effects, effects to materials, materials with instances, etc. I'm sure it's possible to make a map with warzone and traps based on the collada structure...), I've found that Cinema4D export always the same material's name (a wonderful "Material 1"...) in several nodes.
I've written a class to correct this problem. Now you have Material 1 AND Material 2, Material 3, etc. Not sexy nor explicit but that's working.

Here the code :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package eu.nomatter.collada
{
    public class Cinema4D
    {
       
        private static var materialCount:int = 0;
       
        public function Cinema4D()
        {
        }
       
        public static function correctMaterial( xml:XML ):XML {
               
            // Fancy namespace remove http://www.stevensacks.net/2008/07/02/parsing-xhtml-with-e4x-in-as3/
            var colladaNamespace:Namespace = xml.namespace();
            xml = new XML( xml.toXMLString().replace(/\s+xmlns(:[^=]+)?="[^"]*"/g, "") );
           
            var idGeom:String;
            Cinema4D.materialCount = 0;
            var newName:String;
            var count:int = 0;
            var nodeGeometry:XMLList;
           
            for each( var geomXML:XML in xml.library_visual_scenes.visual_scene.node ) {
                Cinema4D.correctNode( xml, geomXML );
            }
           
            xml.@xmlns = colladaNamespace.toString();
            return xml;
        }
       
        private static function correctNode( xml:XML, rootNode:XML ):void {
            var materialName:String = "Material";
            if( rootNode.node.length() > 0 ) {
                for each( var node:XML in rootNode.node ) {
                    Cinema4D.correctNode( xml, node );
                }
            } else {
                var idGeom:String = String( rootNode.instance_geometry.@url.toString().split("#")[1] );
                var newName:String = materialName+String( ++Cinema4D.materialCount );
                rootNode.instance_geometry.bind_material.technique_common.instance_material.@symbol = newName;
                var nodeGeometry:XMLList = xml.library_geometries.geometry.(@id == idGeom);
                nodeGeometry.mesh.triangles.@material = newName;
            }
        }

    }
}

You can see a very simple test here

Originally I've made an AIR application to patch the file instead of executing the code at runtime. Now I've extract the code which correct the xml in a separate class. In the Air app you can drag and drop your file on the application to correct it or use the "Select file" button.

Oh and if you're a Cinem4D user, let me know if you had experiment the same problem!

AS Class : Cinema4D Collada Corrector AS
AIR File : C4DColladaCorrector AIR install
AIR Project source : C4DColladaCorrector AIR project