Changeset 185

Show
Ignore:
Timestamp:
06/01/10 00:03:08 (2 years ago)
Author:
JoeCoder
Message:

Improved collada parsing again. Geometry data referenced by skeleton controllers is also loaded. Fixed parsing number lists with multiple spaces between numbers.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/yage/resource/collada.d

    r184 r185  
    1414import tango.text.xml.DocTester; 
    1515import tango.util.Convert; 
     16 
    1617import yage.core.array; 
    1718import yage.core.color; 
     
    2526import yage.resource.material; 
    2627import yage.resource.manager; 
     28import yage.resource.model; 
    2729import yage.resource.texture; 
    2830import yage.system.log; 
     
    8486        {   throw new XMLException("Could not parse xml document."); 
    8587        } 
     88    } 
     89     
     90    Matrix getBaseTransform() 
     91    {   char[] upAxis = Node(doc.elements).getChild("asset").getChild("up_axis").value(); 
     92        if (upAxis == "X_UP") // Y is already up 
     93            return Vec3f(0, -3.1415/2, 0).toMatrix(); 
     94        if (upAxis == "Z_UP") 
     95            return Vec3f(-3.1415/2, 0, 0).toMatrix(); 
     96        return Matrix.IDENTITY; 
    8697    } 
    8798     
     
    297308            technique = profileCommon.getChild("technique"); 
    298309        } else // Collada 1.3 
    299         {       technique = materialNode.getChild("shader").getChild("technique"); 
    300         } 
     310            technique = materialNode.getChild("shader").getChild("technique");       
    301311         
    302312        Node shadingType = technique.getChild(); // in profile_COMMON, it can be newparam, image, blinn, constant, lambert, phong, or extra. 
     
    308318        // else use blinn (gourard) shading from the fixed function pipeline 
    309319         
     320         
     321        // Helper function for loading material data. 
     322        void getColorOrTexture(Node n, inout Color color, inout GPUTexture texture) 
     323        {   char[] name = n.name(); 
     324            switch (name) 
     325            {   case "param": 
     326                    n = Xml.getNodeById(doc, n.getAttribute("ref"), "sid").getChild("float3");   
     327                    // deliberate fall-through 
     328                case "color": 
     329                    Color temp = Color(Xml.parseNumberList!(float)(n.value)); 
     330                    color = Color(cast(int)temp.r, cast(int)temp.g, cast(int)temp.b, ((color.a*cast(int)temp.a)/255)); 
     331                    break; 
     332                case "texture": 
     333                    texture = getTextureById(n.getAttribute("texture")); // TODO getImageByTexture 
     334                    break; 
     335                default: 
     336                    Log.error("Collada material parameter %s not supported", name); 
     337        }   } 
     338         
    310339        // Loop through and get each material property 
    311340        scope Node[] params = shadingType.getChildren(); 
    312341        foreach (Node param; params) 
    313342        {                
    314             void getColorOrTexture(Node n, inout Color color, inout GPUTexture texture) 
    315             {   char[] name = n.name(); 
    316                 switch (name) 
    317                 {   case "param": 
    318                         n = Xml.getNodeById(doc, n.getAttribute("ref"), "sid").getChild("float3");   
    319                         // deliberate fall-through 
    320                     case "color": 
    321                         Color temp = Color(Xml.parseNumberList!(float)(n.value)); 
    322                         color = Color(cast(int)temp.r, cast(int)temp.g, cast(int)temp.b, ((color.a*cast(int)temp.a)/255)); 
    323                         break; 
    324                     case "texture": 
    325                         texture = getTextureById(n.getAttribute("texture")); // TODO getImageByTexture 
    326                         break; 
    327             }   } 
    328              
    329343            if (!param.getChildren().length) 
    330344                continue; 
     
    369383                    break; 
    370384            } 
    371              
    372             // Enable blending if there's alpha. 
    373             if (pass.blend==MaterialPass.Blend.NONE) 
    374                 if (pass.diffuse.a < 1f || (pass.textures.length && pass.textures[0].texture.getImage().getChannels()==4)) 
    375                     pass.blend = MaterialPass.Blend.AVERAGE; 
    376         } 
    377          
    378         // Create a tecnique that uses no shaders. 
     385        } 
     386         
     387        // Look to see if there's a technique/extra/technique/bump for a bump--fcollada (and maybe also Blender?) puts the bump map here. 
     388        if (technique.hasChild("extra")) 
     389        {   Node extra = technique.getChild("extra"); 
     390            if (extra.hasChild("technique")) 
     391            {   Node extraTechnique = extra.getChild("technique"); 
     392                if (extraTechnique.hasChild("bump")) 
     393                {   GPUTexture texture; 
     394                    getColorOrTexture(extraTechnique.getChild("bump").getChild("texture"), pass.diffuse, texture); 
     395                    pass.setNormalSpecularTexture(Texture(texture)); // may be null 
     396        }   }   } 
     397         
     398        // Enable blending if there's alpha. 
     399        if (pass.blend==MaterialPass.Blend.NONE) 
     400            if (pass.diffuse.a < 1f || (pass.textures.length && pass.textures[0].texture.getImage().getChannels()==4)) 
     401                pass.blend = MaterialPass.Blend.AVERAGE; 
     402         
     403        // Create a fallback technique that uses no shaders. 
    379404        if (result.getPass().autoShader == MaterialPass.AutoShader.PHONG) 
    380405        { 
     
    401426         
    402427        // Get the up direction (unfinished) 
    403         Matrix upTransform; 
    404         char[] upAxis = Node(doc.elements).getChild("asset").getChild("up_axis").value(); 
    405         if (upAxis == "Z_UP") 
    406             upTransform = Vec3f(-3.1415/2, 0, 0).toMatrix(); 
    407          
    408          
    409         // Loop through the scenes and load all the geometry nodes they reference. 
    410         Node[] scenes; 
    411         Node root = Node(doc.elements); 
    412         if (root.hasChild("library_visual_scenes")) 
    413             scenes = root.getChild("library_visual_scenes").getChildren("visual_scene"); 
    414         else // collada 1.3 
    415             scenes = root.getChildren("scene"); 
    416          
    417         foreach (visual_scene; scenes) // loop through scenes 
     428        Matrix upTransform = getBaseTransform(); 
     429         
     430        foreach (visual_scene; getScenes()) // loop through scenes 
    418431        { 
    419             void traverseSceneNodes(Node node) 
     432            // Go through the scene nodes and collect anything that can be used as a model. 
     433            void traverseSceneNodes(Node node, Matrix matrix) 
    420434            { 
    421                 Node instance_geometry
    422                 if (node.hasChild("instance_geometry")) 
    423                     instance_geometry = node.getChild("instance_geometry"); 
     435                char[] geometryId
     436                if (node.hasChild("instance_geometry")) // Collada 1.4+ 
     437                    geometryId = node.getChild("instance_geometry").getAttribute("url"); 
    424438                else if (node.hasChild("instance")) // Collada 1.3 
    425                     instance_geometry = node.getChild("instance"); 
    426                  
    427                 if (instance_geometry.node) 
     439                    geometryId = node.getChild("instance").getAttribute("url"); 
     440                else if (node.hasChild("instance_controller")) // A controller for skeletal animation, which we will follow to get it's geometry 
     441                {   Node controller = Xml.getNodeById(doc, node.getChild("instance_controller").getAttribute("url")); 
     442                    Node skin = controller.getChild("skin"); 
     443                    geometryId = skin.getAttribute("source"); 
     444                } 
     445                 
     446                if (geometryId.length) 
    428447                {                        
    429                     char[] geometryId = instance_geometry.getAttribute("url"); // TODO: Multiple instance geometry? 
    430448                    Geometry geometry = getGeometryById(geometryId, true); 
    431                     if (geometry) 
    432                     { 
    433                        // Get transformation matrix for this instance of the geometry. 
    434                        Matrix matrix; 
    435                         foreach (transform; node.getChildren()) 
    436                         {  if (transform.name=="translate") 
    437                                matrix.move(Vec3f(Xml.parseNumberList!(float)(transform.value))); 
    438                             else if (transform.name=="rotate") 
    439                             {  float[] values = Xml.parseNumberList!(float)(transform.value); 
    440                                assert(values.length==4); 
    441                                matrix = matrix.rotate(Vec3f(values[3]*tango.math.Math.PI/180, values[0], values[1], values[2])); // load from axis-angle                           
    442                             }  
    443                            else if (transform.name=="scale")                        
    444                                matrix.setScalePreservingRotation(Vec3f(Xml.parseNumberList!(float)(transform.value))); 
    445                            else if (transform.name=="matrix") // collada 1.3 
    446                            {   matrix = Matrix(Xml.parseNumberList!(float)(transform.value)); 
    447                                 
    448                            } 
    449                        } 
     449                     
     450                    // Get transformation matrix for this instance of the geometry. 
     451                    foreach (transform; node.getChildren()) 
     452                    {  if (transform.name=="translate") 
     453                           matrix = matrix.move(Vec3f(Xml.parseNumberList!(float)(transform.value))); 
     454                        else if (transform.name=="rotate") 
     455                        {  float[] values = Xml.parseNumberList!(float)(transform.value); 
     456                            assert(values.length==4); 
     457                            matrix = matrix.rotate(Vec3f(values[3]*tango.math.Math.PI/180, values[0], values[1], values[2])); // load from axis-angle                           
     458                        }  
     459                        else if (transform.name=="scale")                      
     460                            matrix.setScalePreservingRotation(Vec3f(Xml.parseNumberList!(float)(transform.value))); 
     461                        else if (transform.name=="matrix") // collada 1.3 
     462                            matrix = Matrix(Xml.parseNumberList!(float)(transform.value));  
     463                         
     464                    } 
     465                     
     466                    if (geometry)  // TODO: Sometimes intance_geometry has xml children specifying a material (or other things as well?) 
     467                    {  geometries~= geometry; 
    450468                        geometryTransforms ~= matrix * upTransform; 
    451                          
    452                         // TODO: Sometimes intance_geometry has xml children specifying a material (or other things as well?) 
    453                          
    454                         geometries~= geometry; 
    455469                    } 
    456470                } 
    457471                 
    458472                foreach (child; node.getChildren("node")) // loop through nodes in a scene 
    459                     traverseSceneNodes(child); 
     473                    traverseSceneNodes(child, matrix); 
    460474            } 
    461475             
    462             traverseSceneNodes(visual_scene); 
     476            traverseSceneNodes(visual_scene, Matrix.IDENTITY); 
    463477        } 
    464478         
     
    499513        return result; 
    500514    } 
     515     
     516    Node[] getScenes() 
     517    { 
     518        Node[] scenes; 
     519        Node root = Node(doc.elements); 
     520        if (root.hasChild("library_visual_scenes")) 
     521            scenes = root.getChild("library_visual_scenes").getChildren("visual_scene"); 
     522        else // collada 1.3 
     523            scenes = root.getChildren("scene"); 
     524        return scenes; 
     525    } 
    501526 
     527    Joint[] getSkeletonById(char[] id) 
     528    { 
     529        // Get the up direction (unfinished) 
     530        Matrix upTransform = getBaseTransform(); 
     531         
     532        // Loop through the scenes and load all the geometry nodes they reference. 
     533         
     534         
     535        foreach (scene; getScenes()) // loop through scenes 
     536        { 
     537             
     538             
     539        } 
     540        return null; 
     541    } 
     542     
    502543    /** 
    503544     * Get a yage GPUTexture from the Collada file by its id. 
     
    548589    private float[] getDataFromSourceId(char[] id, out ushort components) 
    549590    {    
    550          
    551          
    552591        Node source = Xml.getNodeById(doc, id);      
    553592        Node sourceAccessor; 
     
    661700            try { 
    662701                foreach(i, piece; pieces)            
    663                     result[i] = to!(T)(piece); 
     702                    if (piece.length) 
     703                        result[i] = to!(T)(piece); 
    664704            } catch (ConversionException e) 
    665705            {   throw new XmlException(e.toString()); 
  • trunk/src/yage/resource/model.d

    r175 r185  
    1414import yage.core.math.vector; 
    1515import yage.core.object2; 
     16import yage.core.tree; 
    1617import yage.resource.collada; 
    1718import yage.resource.geometry; 
     
    2021import yage.system.log; 
    2122 
     23/* 
    2224/// 
    2325struct KeyFrame 
     
    3941    KeyFrame[] rotations; 
    4042}; 
    41  
     43*/ 
     44 
     45class Joint : Tree!(Joint) 
     46
     47    Matrix relative; 
     48    Matrix absolute; 
     49
    4250 
    4351/** 
     
    5159    private char[] source; 
    5260 
     61    // Old: 
    5362    protected float fps=24; 
    5463    protected bool animated = false; 
    5564    protected double animation_time=-1; 
    56     protected double animation_max_time=0; 
    57     protected Joint[] joints; // used for skeletal animation 
    58     protected int[] joint_indices; 
     65    protected double animation_max_time=0;   
     66    //protected int[] joint_indices; 
     67         
     68    protected Joint[] skeleton; // All of the joints that makeup the skeleton.  The first Joint is the root. 
    5969 
    6070    /// Instantiate an empty model. 
     
    7585    } 
    7686 
    77     /** 
     87    /* 
    7888     * Advance this Model's animation to time. 
    7989     * This still has bugs somehow. 
    8090     * Params: 
    8191     *     time = 
    82      */ 
    8392    void animateTo(double time) 
    8493    { 
     
    179188            setAttribute(Geometry.NORMALS, normals); 
    180189    }    
    181  
    182     /** 
    183      * Get an array of all of the Model's Joints, which are used for skeletal animation. 
    184      * This can be traversed as an array, or as a tree since each Joint references its parent and children. */ 
    185     Joint[] getJoints() 
    186     {   return joints;       
    187     } 
     190     */ 
    188191     
    189192    /**