Added gsoc-2012 collada improvements from bratwurst branch
authorGaia Clary <gaia.clary@machinimatrix.org>
Mon, 21 Jan 2013 13:45:49 +0000 (13:45 +0000)
committerGaia Clary <gaia.clary@machinimatrix.org>
Mon, 21 Jan 2013 13:45:49 +0000 (13:45 +0000)
31 files changed:
release/scripts/presets/operator/wm.collada_export/second_life_rigged.py
release/scripts/presets/operator/wm.collada_export/second_life_static.py
source/blender/collada/AnimationExporter.cpp
source/blender/collada/AnimationExporter.h
source/blender/collada/AnimationImporter.cpp
source/blender/collada/ArmatureExporter.cpp
source/blender/collada/ArmatureExporter.h
source/blender/collada/ArmatureImporter.cpp
source/blender/collada/ArmatureImporter.h
source/blender/collada/CMakeLists.txt
source/blender/collada/ControllerExporter.cpp [new file with mode: 0644]
source/blender/collada/ControllerExporter.h [new file with mode: 0644]
source/blender/collada/DocumentExporter.cpp
source/blender/collada/DocumentImporter.cpp
source/blender/collada/DocumentImporter.h
source/blender/collada/ExportSettings.h
source/blender/collada/ExtraHandler.cpp
source/blender/collada/GeometryExporter.cpp
source/blender/collada/GeometryExporter.h
source/blender/collada/MeshImporter.cpp
source/blender/collada/MeshImporter.h
source/blender/collada/SceneExporter.cpp
source/blender/collada/SceneExporter.h
source/blender/collada/TransformReader.cpp
source/blender/collada/TransformWriter.cpp
source/blender/collada/collada.cpp
source/blender/collada/collada.h
source/blender/collada/collada_internal.cpp
source/blender/collada/collada_internal.h
source/blender/editors/io/io_collada.c
source/blender/makesrna/intern/rna_scene_api.c

index 2c695a2..81769a8 100644 (file)
@@ -7,6 +7,7 @@ op.export_mesh_type_selection = 'view'
 op.selected = True
 op.include_children = False
 op.include_armatures = True
+op.include_shapekeys = False
 op.deform_bones_only = True
 op.active_uv_only = True
 op.include_uv_textures = True
index 081788b..ad06909 100644 (file)
@@ -7,6 +7,7 @@ op.export_mesh_type_selection = 'view'
 op.selected = True
 op.include_children = False
 op.include_armatures = False
+op.include_shapekeys = False
 op.deform_bones_only = False
 op.active_uv_only = True
 op.include_uv_textures = True
index 26b5edf..493d151 100644 (file)
@@ -24,6 +24,8 @@
 #include "AnimationExporter.h"
 #include "MaterialExporter.h"
 
+Global G;
+
 template<class Functor>
 void forEachObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set)
 {
@@ -82,7 +84,12 @@ void AnimationExporter::operator()(Object *ob)
                }
 
        }
-
+    
+    export_object_constraint_animation(ob);
+    
+       //This needs to be handled by extra profiles, so postponed for now
+       //export_morph_animation(ob);
+               
        //Export Lamp parameter animations
        if ( (ob->type == OB_LAMP) && ((Lamp *)ob->data)->adt && ((Lamp *)ob->data)->adt->action) {
                fcu = (FCurve *)(((Lamp *)ob->data)->adt->action->curves.first);
@@ -134,7 +141,69 @@ void AnimationExporter::operator()(Object *ob)
                                fcu = fcu->next;
                        }
                }
+       }
+
+
+}
+
+void AnimationExporter::export_object_constraint_animation(Object *ob)
+{
+       std::vector<float> fra;
+    //Takes frames of target animations
+       make_anim_frames_from_targets(ob, fra);
+    
+       if (fra.size())
+       dae_baked_object_animation(fra, ob);
+}
+
+void AnimationExporter::export_morph_animation(Object *ob)
+{ 
+       FCurve *fcu;
+       char *transformName;
+       Key *key = BKE_key_from_object(ob);
+       if(!key) return;
+
+       if(key->adt && key->adt->action){
+               fcu = (FCurve *)key->adt->action->curves.first;
+               
+               while (fcu) {
+                       transformName = extract_transform_name(fcu->rna_path);
+
+                       dae_animation(ob, fcu, transformName, true);
+                       
+                       fcu = fcu->next;
+               }
+       }
+
+}
 
+void AnimationExporter::make_anim_frames_from_targets(Object *ob, std::vector<float> &frames ){
+       
+       ListBase *conlist = get_active_constraints(ob);
+       if(conlist == NULL) return;
+       bConstraint *con;
+       for (con = (bConstraint*)conlist->first; con; con = con->next) {
+               ListBase targets = {NULL, NULL};
+               
+               bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
+               
+               if(!validateConstraints(con)) continue;
+
+               if (cti && cti->get_constraint_targets) {
+                       bConstraintTarget *ct;
+                       Object *obtar;
+                       /* get targets 
+                        *  - constraints should use ct->matrix, not directly accessing values
+                        *      - ct->matrix members have not yet been calculated here! 
+                        */
+                       cti->get_constraint_targets(con, &targets);
+                       if(cti){
+                               for (ct = (bConstraintTarget*)targets.first; ct; ct = ct->next){
+                                       obtar = ct->tar;
+                                       find_frames(obtar, frames);
+                               }
+                       }
+               }
        }
 }
 
@@ -320,6 +389,9 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa
                if (ma)
                        target = translate_id(id_name(ma)) + "-effect" +
                                 "/common/" /*profile common is only supported */ + get_transform_sid(fcu->rna_path, -1, axis_name, true);
+               //if shape key animation, this is the main problem, how to define the channel targets.
+               /*target = get_morph_id(ob) +
+                                "/value" +*/ 
        }
        addChannel(COLLADABU::URI(empty, sampler_id), target);
 
@@ -368,18 +440,23 @@ void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, B
        //char prefix[256];
 
        FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first;
-       while (fcu) {
+
+       //Check if there is a fcurve in the armature for the bone in param
+       //when baking this check is not needed, solve every bone for every frame.
+       /*while (fcu) {
                std::string bone_name = getObjectBoneName(ob_arm, fcu);
                int val = BLI_strcasecmp((char *)bone_name.c_str(), bone->name);
                if (val == 0) break;
                fcu = fcu->next;
        }
 
-       if (!(fcu)) return; 
+       if (!(fcu)) return;*/ 
+
        bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name);
        if (!pchan)
                return;
 
+       //every inserted keyframe of bones.     
        find_frames(ob_arm, fra);
 
        if (flag & ARM_RESTPOS) {
@@ -415,7 +492,8 @@ void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_
 
        // create output source
        std::string output_id;
-       output_id = create_4x4_source(fra, ob_arm, bone,  anim_id);
+
+       output_id = create_4x4_source(fra, ob_arm, bone, anim_id);
 
        // create interpolations source
        std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
@@ -439,6 +517,48 @@ void AnimationExporter::dae_baked_animation(std::vector<float> &fra, Object *ob_
        closeAnimation();
 }
 
+void AnimationExporter::dae_baked_object_animation(std::vector<float> &fra, Object *ob)
+{
+       std::string ob_name = id_name(ob);
+       char anim_id[200];
+
+       if (!fra.size())
+               return;
+
+       BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s", (char*)translate_id(ob_name).c_str(),
+                "object_matrix");
+
+       openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING);
+
+       // create input source
+       std::string input_id = create_source_from_vector(COLLADASW::InputSemantic::INPUT, fra, false, anim_id, "");
+
+       // create output source
+       std::string output_id;
+       output_id = create_4x4_source( fra, ob, NULL, anim_id);
+
+       // create interpolations source
+       std::string interpolation_id = fake_interpolation_source(fra.size(), anim_id, "");
+
+       std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX;
+       COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id);
+       std::string empty;
+       sampler.addInput(COLLADASW::InputSemantic::INPUT, COLLADABU::URI(empty, input_id));
+       sampler.addInput(COLLADASW::InputSemantic::OUTPUT, COLLADABU::URI(empty, output_id));
+
+       // TODO create in/out tangents source
+
+       // this input is required
+       sampler.addInput(COLLADASW::InputSemantic::INTERPOLATION, COLLADABU::URI(empty, interpolation_id));
+
+       addSampler(sampler);
+
+       std::string target = translate_id(ob_name) + "/transform";
+       addChannel(COLLADABU::URI(empty, sampler_id), target);
+
+       closeAnimation();
+}
+
 // dae_bone_animation -> add_bone_animation
 // (blend this into dae_bone_animation)
 void AnimationExporter::dae_bone_animation(std::vector<float> &fra, float *values, int tm_type, int axis, std::string ob_name, std::string bone_name)
@@ -762,7 +882,8 @@ std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemanti
        return source_id;
 }
 
-std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob_arm, Bone *bone, const std::string& anim_id)
+
+std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object * ob, Bone *bone, const std::string& anim_id)
 {
        COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT;
        std::string source_id = anim_id + get_semantic_suffix(semantic);
@@ -777,74 +898,94 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj
        add_source_parameters(param, semantic, false, NULL, true);
 
        source.prepareToAppendValues();
-
+    
        bPoseChannel *parchan = NULL;
        bPoseChannel *pchan = NULL;
-       bPose *pose = ob_arm->pose;
+       bPoseChannel *rootchan = NULL;
+               
+       if (ob->type == OB_ARMATURE ){
+               bPose *pose = ob->pose;
+               pchan = BKE_pose_channel_find_name(pose, bone->name);
+               if (!pchan)
+                       return "";
 
-       pchan = BKE_pose_channel_find_name(pose, bone->name);
-
-       if (!pchan)
-               return "";
-
-       parchan = pchan->parent;
-
-       enable_fcurves(ob_arm->adt->action, bone->name);
+               parchan = pchan->parent;
 
+               enable_fcurves(ob->adt->action, bone->name);
+       }
+       
        std::vector<float>::iterator it;
        int j = 0;
        for (it = frames.begin(); it != frames.end(); it++) {
                float mat[4][4], ipar[4][4];
-
+        
                float ctime = BKE_scene_frame_get_from_ctime(scene, *it);
-
-               BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM);
-               BKE_pose_where_is_bone(scene, ob_arm, pchan, ctime, 1);
-
-               // compute bone local mat
-               if (bone->parent) {
-                       invert_m4_m4(ipar, parchan->pose_mat);
-                       mult_m4_m4m4(mat, ipar, pchan->pose_mat);
-               }
-               else
-                       copy_m4_m4(mat, pchan->pose_mat);
-               UnitConverter converter;
-
+               CFRA = BKE_scene_frame_get_from_ctime(scene, *it);
+               //BKE_scene_update_for_newframe(G.main,scene,scene->lay);
+               BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
+                               
+               if (bone){
+                       if( pchan->flag & POSE_CHAIN)
+                       {
+                               enable_fcurves(ob->adt->action, NULL);
+                               BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL);
+                               BKE_pose_where_is(scene, ob);
+                       }
+                       else
+                       BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
+                       
+                       // compute bone local mat
+                       if (bone->parent) {
+                               invert_m4_m4(ipar, parchan->pose_mat);
+                               mult_m4_m4m4(mat, ipar, pchan->pose_mat);
+                       }
+                       else
+                               copy_m4_m4(mat, pchan->pose_mat);
+                       
                // SECOND_LIFE_COMPATIBILITY
                // AFAIK animation to second life is via BVH, but no
                // reason to not have the collada-animation be correct
-               if (export_settings->second_life) {
-                       float temp[4][4];
-                       copy_m4_m4(temp, bone->arm_mat);
-                       temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
-                       invert_m4(temp);
+                       if (export_settings->second_life) {
+                               float temp[4][4];
+                               copy_m4_m4(temp, bone->arm_mat);
+                               temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+                               invert_m4(temp);
 
-                       mult_m4_m4m4(mat, mat, temp);
+                               mult_m4_m4m4(mat, mat, temp);
 
-                       if (bone->parent) {
-                               copy_m4_m4(temp, bone->parent->arm_mat);
-                               temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+                               if (bone->parent) {
+                                       copy_m4_m4(temp, bone->parent->arm_mat);
+                                       temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
 
-                               mult_m4_m4m4(mat, temp, mat);
+                                       mult_m4_m4m4(mat, temp, mat);
+                               }
                        }
-               }
 
-               float outmat[4][4];
-               converter.mat4_to_dae(outmat, mat);
+               }
+               else {
+                       calc_ob_mat_at_time(ob, ctime, mat);
+               }
+               
+               UnitConverter converter;
 
+               double outmat[4][4];
+               converter.mat4_to_dae_double(outmat, mat);
 
                source.appendValues(outmat);
 
-
                j++;
+
+               BIK_release_tree(scene, ob, ctime);
        }
 
-       enable_fcurves(ob_arm->adt->action, NULL);
+       enable_fcurves(ob->adt->action, NULL);
 
        source.finish();
 
        return source_id;
 }
+
+
 // only used for sources with OUTPUT semantic ( locations and scale)
 std::string AnimationExporter::create_xyz_source(float *v, int tot, const std::string& anim_id)
 {
@@ -1184,6 +1325,12 @@ bool AnimationExporter::hasAnimations(Scene *sce)
                        }
                }
 
+               //check shape key animation
+               if(!fcu){
+                       Key *key = BKE_key_from_object(ob);
+                       if(key && key->adt && key->adt->action)
+                               fcu = (FCurve *)key->adt->action->curves.first;
+               }
                if (fcu)
                        return true;
        }
@@ -1351,3 +1498,42 @@ void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, i
 
        enable_fcurves(ob_arm->adt->action, NULL);
 }
+
+bool AnimationExporter::validateConstraints(bConstraint *con){
+       
+       bool valid = true;
+       bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
+       /* these we can skip completely (invalid constraints...) */
+       if (cti == NULL) valid = false;
+       if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) valid = false;
+       /* these constraints can't be evaluated anyway */
+       if (cti->evaluate_constraint == NULL) valid = false;
+       /* influence == 0 should be ignored */
+       if (con->enforce == 0.0f) valid = false;
+
+       return valid;
+}
+
+void AnimationExporter::calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4]){ 
+       ListBase *conlist = get_active_constraints(ob);
+       bConstraint *con;
+       for (con = (bConstraint*)conlist->first; con; con = con->next) {
+               ListBase targets = {NULL, NULL};
+               
+               bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
+               
+               if (cti && cti->get_constraint_targets) {
+                       bConstraintTarget *ct;
+                       Object *obtar;
+                       cti->get_constraint_targets(con, &targets);
+                       for (ct = (bConstraintTarget*)targets.first; ct; ct = ct->next){
+                               obtar = ct->tar;
+                               BKE_animsys_evaluate_animdata(scene, &obtar->id, obtar->adt, ctime, ADT_RECALC_ANIM);
+                               BKE_object_where_is_calc_time(scene, obtar, ctime);
+                       }
+               }
+       }
+       BKE_object_where_is_calc_time(scene, ob, ctime);
+       copy_m4_m4(mat, ob->obmat);
+}
+
index 349930d..d2f50b2 100644 (file)
@@ -34,6 +34,7 @@ extern "C"
 #include "DNA_camera_types.h"
 #include "DNA_armature_types.h"
 #include "DNA_material_types.h"
+#include "DNA_constraint_types.h"
 
 #include "BLI_math.h"
 #include "BLI_string.h"
@@ -47,6 +48,10 @@ extern "C"
 #include "BKE_action.h" // pose functions
 #include "BKE_armature.h"
 #include "BKE_object.h"
+#include "BKE_constraint.h"
+#include "BIK_api.h"
+#include "BKE_global.h"
+#include "ED_object.h"
 
 #ifdef NAN_BUILDINFO
 extern char build_rev[];
@@ -73,9 +78,13 @@ extern char build_rev[];
 
 #include "collada_internal.h"
 
+#include "IK_solver.h"
+
 #include <vector>
 #include <algorithm> // std::find
 
+
+
 class AnimationExporter: COLLADASW::LibraryAnimations
 {
 private:
@@ -98,6 +107,10 @@ protected:
        const ExportSettings *export_settings;
 
        void dae_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma = NULL);
+    
+       void export_object_constraint_animation(Object *ob);
+
+       void export_morph_animation(Object *ob);
 
        void write_bone_animation_matrix(Object *ob_arm, Bone *bone);
 
@@ -119,6 +132,8 @@ protected:
        
        void dae_baked_animation(std::vector<float> &fra, Object *ob_arm, Bone *bone);
 
+       void dae_baked_object_animation(std::vector<float> &fra, Object *ob);
+
        float convert_time(float frame);
 
        float convert_angle(float angle);
@@ -130,7 +145,7 @@ protected:
        
        void get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length);
        
-       float * get_eul_source_for_quat(Object *ob );
+       float* get_eul_source_for_quat(Object *ob );
 
        std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name);
 
@@ -143,17 +158,21 @@ protected:
        std::string create_xyz_source(float *v, int tot, const std::string& anim_id);
 
        std::string create_4x4_source(std::vector<float> &frames, Object * ob_arm, Bone *bone, const std::string& anim_id);
-
+    
        std::string create_interpolation_source(FCurve *fcu, const std::string& anim_id, const char *axis_name, bool *has_tangents);
 
        std::string fake_interpolation_source(int tot, const std::string& anim_id, const char *axis_name);
+       
        // for rotation, axis name is always appended and the value of append_axis is ignored
        std::string get_transform_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis);
        std::string get_light_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis);
        std::string get_camera_param_sid(char *rna_path, int tm_type, const char *axis_name, bool append_axis);
+       
        void find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name);
        void find_frames(Object *ob, std::vector<float> &fra);
 
+       void make_anim_frames_from_targets(Object *ob, std::vector<float> &frames );
+
        void find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode);
        
        // enable fcurves driving a specific bone, disable all the rest
@@ -165,4 +184,11 @@ protected:
        char *extract_transform_name(char *rna_path);
 
        std::string getObjectBoneName(Object *ob, const FCurve * fcu);
+
+       void getBakedPoseData(Object *obarm, int startFrame, int endFrame, bool ActionBake, bool ActionBakeFirstFrame);
+
+       bool validateConstraints(bConstraint *con);
+
+       void calc_ob_mat_at_time(Object *ob, float ctime , float mat[][4]);
+
 };
index 3d0ceb5..943c4fb 100644 (file)
@@ -937,10 +937,9 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
                                        if (is_matrix) {
                                                apply_matrix_curves(ob, animcurves, root, node,  transform);
                                        }
-                                       else {
+                                       else {                          
 
                                                if (is_joint) {
-
                                                        add_bone_animation_sampled(ob, animcurves, root, node, transform);
                                                }
                                                else {
@@ -1676,8 +1675,6 @@ void AnimationImporter::evaluate_transform_at_frame(float mat[4][4], COLLADAFW::
                                default:
                                        fprintf(stderr, "unsupported transformation type %d\n", type);
                        }
-                       // dae_matrix_to_mat4(tm, m);
-                       
                }
 
                float temp[4][4];
index 134fd63..36993ea 100644 (file)
@@ -75,12 +75,6 @@ void ArmatureExporter::add_armature_bones(Object *ob_arm, Scene *sce,
        }
 }
 
-bool ArmatureExporter::is_skinned_mesh(Object *ob)
-{
-       return bc_get_assigned_armature(ob) != NULL;
-}
-
-
 void ArmatureExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone)
 {
        if (bc_is_root_bone(bone, this->export_settings->deform_bones_only))
@@ -110,31 +104,17 @@ bool ArmatureExporter::add_instance_controller(Object *ob)
        for (bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) {
                write_bone_URLs(ins, ob_arm, bone);
        }
-
+    
        InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
                
        ins.add();
        return true;
 }
 
-void ArmatureExporter::export_controllers(Scene *sce)
-{
-       scene = sce;
-
-       openLibrary();
-
-       GeometryFunctor gf;
-       gf.forEachMeshObjectInExportSet<ArmatureExporter>(sce, *this, this->export_settings->export_set);
-
-       closeLibrary();
-}
-
 void ArmatureExporter::operator()(Object *ob)
 {
        Object *ob_arm = bc_get_assigned_armature(ob);
 
-       if (ob_arm /*&& !already_written(ob_arm)*/)
-               export_controller(ob, ob_arm);
 }
 #if 0
 
@@ -187,67 +167,67 @@ void ArmatureExporter::add_bone_node(Bone *bone, Object *ob_arm, Scene *sce,
                node.setNodeName(node_name);
                node.setNodeSid(node_sid);
 
-#if 0
+#if 0 
                if (bone->childbase.first == NULL || BLI_countlist(&(bone->childbase)) >= 2) {
                        add_blender_leaf_bone( bone, ob_arm, node);
                }
-               else {
+               else{
 #endif
-               node.start();
+                       node.start();
 
-               add_bone_transform(ob_arm, bone, node);
+                       add_bone_transform(ob_arm, bone, node);
 
-               // Write nodes of childobjects, remove written objects from list
-               std::list<Object *>::iterator i = child_objects.begin();
+                       // Write nodes of childobjects, remove written objects from list
+                       std::list<Object *>::iterator i = child_objects.begin();
 
-               while (i != child_objects.end()) {
-                       if ((*i)->partype == PARBONE && (0 == strcmp((*i)->parsubstr, bone->name))) {
-                               float backup_parinv[4][4];
-                               copy_m4_m4(backup_parinv, (*i)->parentinv);
+                       while (i != child_objects.end()) {
+                               if ((*i)->partype == PARBONE && (0 == strcmp((*i)->parsubstr, bone->name))) {
+                                       float backup_parinv[4][4];
+                                       copy_m4_m4(backup_parinv, (*i)->parentinv);
 
-                               // crude, temporary change to parentinv
-                               // so transform gets exported correctly.
+                                       // crude, temporary change to parentinv
+                                       // so transform gets exported correctly.
 
-                               // Add bone tail- translation... don't know why
-                               // bone parenting is against the tail of a bone
-                               // and not it's head, seems arbitrary.
-                               (*i)->parentinv[3][1] += bone->length;
+                                       // Add bone tail- translation... don't know why
+                                       // bone parenting is against the tail of a bone
+                                       // and not it's head, seems arbitrary.
+                                       (*i)->parentinv[3][1] += bone->length;
 
-                               // SECOND_LIFE_COMPATIBILITY
-                               // TODO: when such objects are animated as
-                               // single matrix the tweak must be applied
-                               // to the result.
-                               if (export_settings->second_life) {
-                                       // tweak objects parentinverse to match compatibility
-                                       float temp[4][4];
+                                       // SECOND_LIFE_COMPATIBILITY
+                                       // TODO: when such objects are animated as
+                                       // single matrix the tweak must be applied
+                                       // to the result.
+                                       if (export_settings->second_life) {
+                                               // tweak objects parentinverse to match compatibility
+                                               float temp[4][4];
 
-                                       copy_m4_m4(temp, bone->arm_mat);
-                                       temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
+                                               copy_m4_m4(temp, bone->arm_mat);
+                                               temp[3][0] = temp[3][1] = temp[3][2] = 0.0f;
 
-                                       mult_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv);
-                               }
+                                               mult_m4_m4m4((*i)->parentinv, temp, (*i)->parentinv);
+                                       }
 
-                               se->writeNodes(*i, sce);
+                                       se->writeNodes(*i, sce);
 
-                               copy_m4_m4((*i)->parentinv, backup_parinv);
-                               child_objects.erase(i++);
+                                       copy_m4_m4((*i)->parentinv, backup_parinv);
+                                       child_objects.erase(i++);
+                               }
+                               else i++;
                        }
-                       else i++;
-               }
 
-               for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
-                       add_bone_node(child, ob_arm, sce, se, child_objects);
+                       for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+                               add_bone_node(child, ob_arm, sce, se, child_objects);
+                       }
+                       node.end();
                }
-               node.end();
-       }
-       else {
-               for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
-                       add_bone_node(child, ob_arm, sce, se, child_objects);
+               else {
+                       for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+                               add_bone_node(child, ob_arm, sce, se, child_objects);
+                       }
                }
-       }
 }
 
-#if 0
+//#if 1
 void ArmatureExporter::add_blender_leaf_bone(Bone *bone, Object *ob_arm, COLLADASW::Node& node)
 {
        node.start();
@@ -258,13 +238,13 @@ void ArmatureExporter::add_blender_leaf_bone(Bone *bone, Object *ob_arm, COLLADA
        node.addExtraTechniqueParameter("blender", "tip_y", bone->tail[1]);
        node.addExtraTechniqueParameter("blender", "tip_z", bone->tail[2]);
        
-       for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+       /*for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
                add_bone_node(child, ob_arm, sce, se, child_objects);
-       }
+       }*/
        node.end();
        
 }
-#endif
+//#endif
 
 void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node)
 {
@@ -273,22 +253,27 @@ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW:
        float mat[4][4];
 
        if (bone->parent) {
-               // get bone-space matrix from armature-space
-               bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name);
-
+               // get bone-space matrix from parent pose
+               /*bPoseChannel *parchan = BKE_pose_channel_find_name(ob_arm->pose, bone->parent->name);
                float invpar[4][4];
                invert_m4_m4(invpar, parchan->pose_mat);
-               mult_m4_m4m4(mat, invpar, pchan->pose_mat);
+               mult_m4_m4m4(mat, invpar, pchan->pose_mat);*/
+               
+               float invpar[4][4];
+               invert_m4_m4(invpar, bone->parent->arm_mat);
+               mult_m4_m4m4(mat, invpar, bone->arm_mat);
+
        }
        else {
-               copy_m4_m4(mat, pchan->pose_mat);
-               // Why? Joint's localspace is still it's parent node
-               //get world-space from armature-space
-               //mult_m4_m4m4(mat, ob_arm->obmat, pchan->pose_mat);
+               
+               //copy_m4_m4(mat, pchan->pose_mat);
+               //pose mat is object space
+               //New change: export bone->arm_mat
+               copy_m4_m4(mat, bone->arm_mat);
        }
 
        // SECOND_LIFE_COMPATIBILITY
-       if (export_settings->second_life) {
+    if (export_settings->second_life) {
                // Remove rotations vs armature from transform
                // parent_rest_rot * mat * irest_rot
                float temp[4][4];
@@ -313,315 +298,3 @@ std::string ArmatureExporter::get_controller_id(Object *ob_arm, Object *ob)
 {
        return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX;
 }
-
-// ob should be of type OB_MESH
-// both args are required
-void ArmatureExporter::export_controller(Object *ob, Object *ob_arm)
-{
-       // joint names
-       // joint inverse bind matrices
-       // vertex weights
-
-       // input:
-       // joint names: ob -> vertex group names
-       // vertex group weights: me->dvert -> groups -> index, weight
-
-#if 0
-       me->dvert :
-
-       typedef struct MDeformVert {
-               struct MDeformWeight *dw;
-               int totweight;
-               int flag;   // flag only in use for weightpaint now
-       } MDeformVert;
-
-       typedef struct MDeformWeight {
-               int def_nr;
-               float weight;
-       } MDeformWeight;
-#endif
-
-       bool use_instantiation = this->export_settings->use_object_instantiation;
-       Mesh *me;
-
-       if (this->export_settings->apply_modifiers) {
-               me = bc_to_mesh_apply_modifiers(scene, ob, this->export_settings->export_mesh_type);
-       }
-       else {
-               me = (Mesh *)ob->data;
-       }
-       BKE_mesh_tessface_ensure(me);
-
-       if (!me->dvert) return;
-
-       std::string controller_name = id_name(ob_arm);
-       std::string controller_id = get_controller_id(ob_arm, ob);
-
-       openSkin(controller_id, controller_name,
-                COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation)));
-
-       add_bind_shape_mat(ob);
-
-       std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id);
-       std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, &ob->defbase, controller_id);
-
-       std::list<int> vcounts;
-       std::list<int> joints;
-       std::list<float> weights;
-
-       {
-               int i, j;
-
-               // def group index -> joint index
-               std::vector<int> joint_index_by_def_index;
-               bDeformGroup *def;
-
-               for (def = (bDeformGroup *)ob->defbase.first, i = 0, j = 0; def; def = def->next, i++) {
-                       if (is_bone_defgroup(ob_arm, def))
-                               joint_index_by_def_index.push_back(j++);
-                       else
-                               joint_index_by_def_index.push_back(-1);
-               }
-
-               for (i = 0; i < me->totvert; i++) {
-                       MDeformVert *vert = &me->dvert[i];
-                       std::map<int, float> jw;
-
-                       // We're normalizing the weights later
-                       float sumw = 0.0f;
-
-                       for (j = 0; j < vert->totweight; j++) {
-                               int joint_index = joint_index_by_def_index[vert->dw[j].def_nr];
-                               if (joint_index != -1 && vert->dw[j].weight > 0.0f) {
-                                       jw[joint_index] += vert->dw[j].weight;
-                                       sumw += vert->dw[j].weight;
-                               }
-                       }
-
-                       if (sumw > 0.0f) {
-                               float invsumw = 1.0f / sumw;
-                               vcounts.push_back(jw.size());
-                               for (std::map<int, float>::iterator m = jw.begin(); m != jw.end(); ++m) {
-                                       joints.push_back((*m).first);
-                                       weights.push_back(invsumw * (*m).second);
-                               }
-                       }
-                       else {
-                               vcounts.push_back(0);
-#if 0
-                               vcounts.push_back(1);
-                               joints.push_back(-1);
-                               weights.push_back(1.0f);
-#endif
-                       }
-               }
-       }
-
-       std::string weights_source_id = add_weights_source(me, controller_id, weights);
-       add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id);
-       add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints);
-
-       if (this->export_settings->apply_modifiers)
-       {
-               BKE_libblock_free_us(&(G.main->mesh), me);
-       }
-       closeSkin();
-       closeController();
-}
-
-void ArmatureExporter::add_joints_element(ListBase *defbase,
-                                          const std::string& joints_source_id, const std::string& inv_bind_mat_source_id)
-{
-       COLLADASW::JointsElement joints(mSW);
-       COLLADASW::InputList &input = joints.getInputList();
-
-       input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h
-                                        COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id)));
-       input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::BINDMATRIX,
-                                        COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id)));
-       joints.add();
-}
-
-void ArmatureExporter::add_bind_shape_mat(Object *ob)
-{
-       double bind_mat[4][4];
-
-       converter.mat4_to_dae_double(bind_mat, ob->obmat);
-
-       addBindShapeTransform(bind_mat);
-}
-
-std::string ArmatureExporter::add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
-{
-       std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX;
-
-       int totjoint = 0;
-       bDeformGroup *def;
-       for (def = (bDeformGroup *)defbase->first; def; def = def->next) {
-               if (is_bone_defgroup(ob_arm, def))
-                       totjoint++;
-       }
-
-       COLLADASW::NameSource source(mSW);
-       source.setId(source_id);
-       source.setArrayId(source_id + ARRAY_ID_SUFFIX);
-       source.setAccessorCount(totjoint);
-       source.setAccessorStride(1);
-       
-       COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
-       param.push_back("JOINT");
-
-       source.prepareToAppendValues();
-
-       for (def = (bDeformGroup *)defbase->first; def; def = def->next) {
-               Bone *bone = get_bone_from_defgroup(ob_arm, def);
-               if (bone)
-                       source.appendValues(get_joint_sid(bone, ob_arm));
-       }
-
-       source.finish();
-
-       return source_id;
-}
-
-std::string ArmatureExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
-{
-       std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX;
-
-       int totjoint = 0;
-       for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
-               if (is_bone_defgroup(ob_arm, def))
-                       totjoint++;
-       }
-
-       COLLADASW::FloatSourceF source(mSW);
-       source.setId(source_id);
-       source.setArrayId(source_id + ARRAY_ID_SUFFIX);
-       source.setAccessorCount(totjoint); //BLI_countlist(defbase));
-       source.setAccessorStride(16);
-       
-       source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4);
-       COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
-       param.push_back("TRANSFORM");
-
-       source.prepareToAppendValues();
-
-       bPose *pose = ob_arm->pose;
-       bArmature *arm = (bArmature *)ob_arm->data;
-
-       int flag = arm->flag;
-
-       // put armature in rest position
-       if (!(arm->flag & ARM_RESTPOS)) {
-               arm->flag |= ARM_RESTPOS;
-               BKE_pose_where_is(scene, ob_arm);
-       }
-
-       for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
-               if (is_bone_defgroup(ob_arm, def)) {
-                       bPoseChannel *pchan = BKE_pose_channel_find_name(pose, def->name);
-
-                       float mat[4][4];
-                       float world[4][4];
-                       float inv_bind_mat[4][4];
-
-                       // SECOND_LIFE_COMPATIBILITY
-                       if (export_settings->second_life) {
-                               // Only translations, no rotation vs armature
-                               float temp[4][4];
-                               unit_m4(temp);
-                               copy_v3_v3(temp[3], pchan->bone->arm_mat[3]);
-                               mult_m4_m4m4(world, ob_arm->obmat, temp);
-                       }
-                       else {
-                               // make world-space matrix, arm_mat is armature-space
-                               mult_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat);
-                       }
-
-                       invert_m4_m4(mat, world);
-                       converter.mat4_to_dae(inv_bind_mat, mat);
-
-                       source.appendValues(inv_bind_mat);
-               }
-       }
-
-       // back from rest positon
-       if (!(flag & ARM_RESTPOS)) {
-               arm->flag = flag;
-               BKE_pose_where_is(scene, ob_arm);
-       }
-
-       source.finish();
-
-       return source_id;
-}
-
-Bone *ArmatureExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def)
-{
-       bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, def->name);
-       return pchan ? pchan->bone : NULL;
-}
-
-bool ArmatureExporter::is_bone_defgroup(Object *ob_arm, bDeformGroup *def)
-{
-       return get_bone_from_defgroup(ob_arm, def) != NULL;
-}
-
-std::string ArmatureExporter::add_weights_source(Mesh *me, const std::string& controller_id, const std::list<float>& weights)
-{
-       std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX;
-
-       COLLADASW::FloatSourceF source(mSW);
-       source.setId(source_id);
-       source.setArrayId(source_id + ARRAY_ID_SUFFIX);
-       source.setAccessorCount(weights.size());
-       source.setAccessorStride(1);
-       
-       COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
-       param.push_back("WEIGHT");
-
-       source.prepareToAppendValues();
-
-       for (std::list<float>::const_iterator i = weights.begin(); i != weights.end(); ++i) {
-               source.appendValues(*i);
-       }
-
-       source.finish();
-
-       return source_id;
-}
-
-void ArmatureExporter::add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id,
-                                                  const std::list<int>& vcounts,
-                                                  const std::list<int>& joints)
-{
-       COLLADASW::VertexWeightsElement weightselem(mSW);
-       COLLADASW::InputList &input = weightselem.getInputList();
-
-       int offset = 0;
-       input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h
-                                        COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id), offset++));
-       input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT,
-                                        COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), offset++));
-
-       weightselem.setCount(vcounts.size());
-
-       // write number of deformers per vertex
-       COLLADASW::PrimitivesBase::VCountList vcountlist;
-
-       vcountlist.resize(vcounts.size());
-       std::copy(vcounts.begin(), vcounts.end(), vcountlist.begin());
-
-       weightselem.prepareToAppendVCountValues();
-       weightselem.appendVertexCount(vcountlist);
-
-       weightselem.CloseVCountAndOpenVElement();
-
-       // write deformer index - weight index pairs
-       int weight_index = 0;
-       for (std::list<int>::const_iterator i = joints.begin(); i != joints.end(); ++i) {
-               weightselem.appendValues(*i, weight_index++);
-       }
-
-       weightselem.finish();
-}
index 086c16f..e2496a4 100644 (file)
@@ -41,6 +41,7 @@
 #include "DNA_listBase.h"
 #include "DNA_mesh_types.h"
 #include "DNA_object_types.h"
+#include "DNA_constraint_types.h"
 #include "DNA_scene_types.h"
 
 #include "TransformWriter.h"
@@ -62,11 +63,9 @@ public:
        void add_armature_bones(Object *ob_arm, Scene *sce, SceneExporter *se,
                                std::list<Object *>& child_objects);
 
-       bool is_skinned_mesh(Object *ob);
-
        bool add_instance_controller(Object *ob);
 
-       void export_controllers(Scene *sce);
+       //void export_controllers(Scene *sce);*/
 
        void operator()(Object *ob);
 
@@ -98,29 +97,6 @@ private:
 
        std::string get_controller_id(Object *ob_arm, Object *ob);
 
-       // ob should be of type OB_MESH
-       // both args are required
-       void export_controller(Object *ob, Object *ob_arm);
-
-       void add_joints_element(ListBase *defbase,
-                               const std::string& joints_source_id, const std::string& inv_bind_mat_source_id);
-
-       void add_bind_shape_mat(Object *ob);
-
-       std::string add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id);
-
-       std::string add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id);
-
-       Bone *get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def);
-
-       bool is_bone_defgroup(Object *ob_arm, bDeformGroup *def);
-
-       std::string add_weights_source(Mesh *me, const std::string& controller_id,
-                                      const std::list<float>& weights);
-
-       void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id,
-                                       const std::list<int>& vcount, const std::list<int>& joints);
-
        void write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone);
 };
 
index f1cf732..58c3f34 100644 (file)
@@ -78,84 +78,8 @@ JointData *ArmatureImporter::get_joint_data(COLLADAFW::Node *node);
        return &joint_index_to_joint_info_map[joint_index];
 }
 #endif
-void ArmatureImporter::create_unskinned_bone(COLLADAFW::Node *node, EditBone *parent, int totchild,
-                                             float parent_mat[4][4], Object *ob_arm)
-{
-       std::vector<COLLADAFW::Node *>::iterator it;
-       it = std::find(finished_joints.begin(), finished_joints.end(), node);
-       if (it != finished_joints.end()) return;
-
-       float mat[4][4];
-       float obmat[4][4];
-
-       // object-space
-       get_node_mat(obmat, node, NULL, NULL);
-
-       EditBone *bone = ED_armature_edit_bone_add((bArmature *)ob_arm->data, (char *)bc_get_joint_name(node));
-       totbone++;
-       
-       if (parent) bone->parent = parent;
-
-       float angle = 0;
 
-       // get world-space
-       if (parent) {
-               mult_m4_m4m4(mat, parent_mat, obmat);
-
-       }
-       else {
-               copy_m4_m4(mat, obmat);
-
-       }
-       float loc[3], size[3], rot[3][3];
-       mat4_to_loc_rot_size(loc, rot, size, obmat);
-       mat3_to_vec_roll(rot, NULL, &angle);
-       bone->roll = angle;
-       // set head
-       copy_v3_v3(bone->head, mat[3]);
-
-       // set tail, don't set it to head because 0-length bones are not allowed
-       float vec[3] = {0.0f, 0.5f, 0.0f};
-       add_v3_v3v3(bone->tail, bone->head, vec);
-
-       // set parent tail
-       if (parent && totchild == 1) {
-               copy_v3_v3(parent->tail, bone->head);
-               
-               // not setting BONE_CONNECTED because this would lock child bone location with respect to parent
-               // bone->flag |= BONE_CONNECTED;
-       
-               // XXX increase this to prevent "very" small bones?
-               const float epsilon = 0.000001f;
-
-               // derive leaf bone length
-               float length = len_v3v3(parent->head, parent->tail);
-               if ((length < leaf_bone_length || totbone == 0) && length > epsilon) {
-                       leaf_bone_length = length;
-               }
-
-               // treat zero-sized bone like a leaf bone
-               if (length <= epsilon) {
-                       add_leaf_bone(parent_mat, parent, node);
-               }
-
-       }
-
-       COLLADAFW::NodePointerArray& children = node->getChildNodes();
-       for (unsigned int i = 0; i < children.getCount(); i++) {
-               create_unskinned_bone(children[i], bone, children.getCount(), mat, ob_arm);
-       }
-
-       // in second case it's not a leaf bone, but we handle it the same way
-       if (!children.getCount() || children.getCount() > 1) {
-               add_leaf_bone(mat, bone, node);
-       }
-
-       finished_joints.push_back(node);
-
-}
-
-void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
+void ArmatureImporter::create_bone(SkinInfo* skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
                                    float parent_mat[4][4], bArmature *arm)
 {
        //Checking if bone is already made.
@@ -168,50 +92,51 @@ void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBo
        // JointData* jd = get_joint_data(node);
 
        float mat[4][4];
-
+       float obmat[4][4];
+       
        // TODO rename from Node "name" attrs later
        EditBone *bone = ED_armature_edit_bone_add(arm, (char *)bc_get_joint_name(node));
        totbone++;
 
-       if (skin.get_joint_inv_bind_matrix(joint_inv_bind_mat, node)) {
+       if (skin && skin->get_joint_inv_bind_matrix(joint_inv_bind_mat, node)) {
                // get original world-space matrix
                invert_m4_m4(mat, joint_inv_bind_mat);
        }
        // create a bone even if there's no joint data for it (i.e. it has no influence)
        else {
-               float obmat[4][4];
-
-               // object-space
+               // bone-space
                get_node_mat(obmat, node, NULL, NULL);
-
+                       
                // get world-space
-               if (parent)
+               if (parent){
                        mult_m4_m4m4(mat, parent_mat, obmat);
+               }
                else
                        copy_m4_m4(mat, obmat);
-
-               float loc[3], size[3], rot[3][3], angle;
-               mat4_to_loc_rot_size(loc, rot, size, obmat);
-               mat3_to_vec_roll(rot, NULL, &angle);
-               bone->roll = angle;
        }
 
-       
        if (parent) bone->parent = parent;
 
+       float loc[3], size[3], rot[3][3]; 
+       float angle;
+       float vec[3] = {0.0f, 0.5f, 0.0f};
+       mat4_to_loc_rot_size(loc, rot, size, mat);
+       //copy_m3_m4(bonemat,mat);
+       mat3_to_vec_roll(rot, vec, &angle);
+
+       bone->roll = angle;
        // set head
        copy_v3_v3(bone->head, mat[3]);
 
        // set tail, don't set it to head because 0-length bones are not allowed
-       float vec[3] = {0.0f, 0.5f, 0.0f};
        add_v3_v3v3(bone->tail, bone->head, vec);
 
        // set parent tail
        if (parent && totchild == 1) {
-               copy_v3_v3(parent->tail, bone->head);
+          copy_v3_v3(parent->tail, bone->head);
 
                // not setting BONE_CONNECTED because this would lock child bone location with respect to parent
-               // bone->flag |= BONE_CONNECTED;
+                bone->flag |= BONE_CONNECTED;
 
                // XXX increase this to prevent "very" small bones?
                const float epsilon = 0.000001f;
@@ -227,32 +152,6 @@ void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBo
                        add_leaf_bone(parent_mat, parent, node);
                }
 
-               /*
-#if 0
-               // and which row in mat is bone direction
-               float vec[3];
-               sub_v3_v3v3(vec, parent->tail, parent->head);
-#ifdef COLLADA_DEBUG
-               print_v3("tail - head", vec);
-               print_m4("matrix", parent_mat);
-#endif
-               for (int i = 0; i < 3; i++) {
-#ifdef COLLADA_DEBUG
-                       char *axis_names[] = {"X", "Y", "Z"};
-                       printf("%s-axis length is %f\n", axis_names[i], len_v3(parent_mat[i]));
-#endif
-                       float angle = angle_v2v2(vec, parent_mat[i]);
-                       if (angle < min_angle) {
-#ifdef COLLADA_DEBUG
-                               print_v3("picking", parent_mat[i]);
-                               printf("^ %s axis of %s's matrix\n", axis_names[i], get_dae_name(node));
-#endif
-                               bone_direction_row = i;
-                               min_angle = angle;
-                       }
-               }
-#endif
-               */
        }
 
        COLLADAFW::NodePointerArray& children = node->getChildNodes();
@@ -265,6 +164,8 @@ void ArmatureImporter::create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBo
                add_leaf_bone(mat, bone, node);
        }
 
+       bone->length = len_v3v3(bone->head, bone->tail);
+
        finished_joints.push_back(node);
 }
 
@@ -299,7 +200,7 @@ void ArmatureImporter::add_leaf_bone(float mat[4][4], EditBone *bone,  COLLADAFW
 void ArmatureImporter::fix_leaf_bones( )
 {
        // just setting tail for leaf bones here
-
+    float correctionMin = 1.0f;
        std::vector<LeafBone>::iterator it;
        for (it = leaf_bones.begin(); it != leaf_bones.end(); it++) {
                LeafBone& leaf = *it;
@@ -307,12 +208,11 @@ void ArmatureImporter::fix_leaf_bones( )
                // pointing up
                float vec[3] = {0.0f, 0.0f, 0.1f};
                
-               // if parent: take parent length and direction
-               if (leaf.bone->parent) sub_v3_v3v3(vec, leaf.bone->parent->tail, leaf.bone->parent->head);
+               sub_v3_v3v3(vec, leaf.bone->tail , leaf.bone->head);
+               mul_v3_fl(vec, leaf_bone_length);
+               add_v3_v3v3(leaf.bone->tail, leaf.bone->head , vec);
 
-               copy_v3_v3(leaf.bone->tail, leaf.bone->head);
-               add_v3_v3v3(leaf.bone->tail, leaf.bone->head, vec);
-       }
+               }
 }
 
 #if 0
@@ -410,40 +310,36 @@ ArmatureJoints& ArmatureImporter::get_armature_joints(Object *ob_arm)
 void ArmatureImporter::create_armature_bones( )
 {
        std::vector<COLLADAFW::Node *>::iterator ri;
+
+       leaf_bone_length = FLT_MAX;
        //if there is an armature created for root_joint next root_joint
        for (ri = root_joints.begin(); ri != root_joints.end(); ri++) {
                if (get_armature_for_joint(*ri) != NULL) continue;
                
-               //add armature object for current joint
-               //Object *ob_arm = bc_add_object(scene, OB_ARMATURE, NULL);
-
                Object *ob_arm = joint_parent_map[(*ri)->getUniqueId()];
 
                if (!ob_arm)
                        continue;
-
-               //ob_arm->type = OB_ARMATURE;
+        
                ED_armature_to_edit(ob_arm);
 
-               // min_angle = 360.0f;          // minimum angle between bone head-tail and a row of bone matrix
-
-               // create unskinned bones
                /*
                 * TODO:
                 * check if bones have already been created for a given joint
                 */
-               leaf_bone_length = FLT_MAX;
-               create_unskinned_bone(*ri, NULL, (*ri)->getChildNodes().getCount(), NULL, ob_arm);
 
+        create_bone(NULL, *ri , NULL, (*ri)->getChildNodes().getCount(), NULL, (bArmature *)ob_arm->data);
+        
+               //leaf bone tails are derived from the matrix, so no need of this.
                fix_leaf_bones();
 
                // exit armature edit mode
-       
                unskinned_armature_map[(*ri)->getUniqueId()] = ob_arm;
 
                ED_armature_from_edit(ob_arm);
-
-               set_pose(ob_arm, *ri, NULL, NULL);
+        
+               //This serves no purpose, as pose is automatically reset later, in BKE_where_is_bone()
+               //set_pose(ob_arm, *ri, NULL, NULL);
 
                ED_armature_edit_free(ob_arm);
                DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
@@ -533,7 +429,6 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
        totbone = 0;
        // bone_direction_row = 1; // TODO: don't default to Y but use asset and based on it decide on default row
        leaf_bone_length = FLT_MAX;
-       // min_angle = 360.0f;          // minimum angle between bone head-tail and a row of bone matrix
 
        // create bones
        /*
@@ -549,7 +444,7 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
 
                // since root_joints may contain joints for multiple controllers, we need to filter
                if (skin.uses_joint_or_descendant(*ri)) {
-                       create_bone(skin, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, (bArmature *)ob_arm->data);
+                       create_bone(&skin, *ri, NULL, (*ri)->getChildNodes().getCount(), NULL, (bArmature *)ob_arm->data);
 
                        if (joint_parent_map.find((*ri)->getUniqueId()) != joint_parent_map.end() && !skin.get_parent())
                                skin.set_parent(joint_parent_map[(*ri)->getUniqueId()]);
@@ -563,22 +458,14 @@ void ArmatureImporter::create_armature_bones(SkinInfo& skin)
        ED_armature_edit_free(ob_arm);
        DAG_id_tag_update(&ob_arm->id, OB_RECALC_OB | OB_RECALC_DATA);
 
-       // set_leaf_bone_shapes(ob_arm);
-       // set_euler_rotmode();
 }
 
-
-// root - if this joint is the top joint in hierarchy, if a joint
-// is a child of a node (not joint), root should be true since
-// this is where we build armature bones from
-
 void ArmatureImporter::set_pose(Object *ob_arm,  COLLADAFW::Node *root_node, const char *parentname, float parent_mat[4][4])
 { 
        char *bone_name = (char *) bc_get_joint_name(root_node);
        float mat[4][4];
        float obmat[4][4];
 
-       float ax[3];
        float angle = 0.0f;
        
        // object-space
@@ -597,14 +484,16 @@ void ArmatureImporter::set_pose(Object *ob_arm,  COLLADAFW::Node *root_node, con
 
        }
        else {
+               
                copy_m4_m4(mat, obmat);
                float invObmat[4][4];
                invert_m4_m4(invObmat, ob_arm->obmat);
                mult_m4_m4m4(pchan->pose_mat, invObmat, mat);
+               
        }
 
-       mat4_to_axis_angle(ax, &angle, mat);
-       pchan->bone->roll = angle;
+       ///*mat4_to_axis_angle(ax, &angle, mat);
+       //pchan->bone->roll = angle;*/
 
 
        COLLADAFW::NodePointerArray& children = root_node->getChildNodes();
@@ -614,6 +503,10 @@ void ArmatureImporter::set_pose(Object *ob_arm,  COLLADAFW::Node *root_node, con
 
 }
 
+
+// root - if this joint is the top joint in hierarchy, if a joint
+// is a child of a node (not joint), root should be true since
+// this is where we build armature bones from
 void ArmatureImporter::add_joint(COLLADAFW::Node *node, bool root, Object *parent, Scene *sce)
 {
        joint_by_uid[node->getUniqueId()] = node;
@@ -729,13 +622,12 @@ bool ArmatureImporter::write_skin_controller_data(const COLLADAFW::SkinControlle
 bool ArmatureImporter::write_controller(const COLLADAFW::Controller *controller)
 {
        // - create and store armature object
-
-       const COLLADAFW::UniqueId& skin_id = controller->getUniqueId();
+       const COLLADAFW::UniqueId& con_id = controller->getUniqueId();
 
        if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_SKIN) {
                COLLADAFW::SkinController *co = (COLLADAFW::SkinController *)controller;
                // to be able to find geom id by controller id
-               geom_uid_by_controller_uid[skin_id] = co->getSource();
+               geom_uid_by_controller_uid[con_id] = co->getSource();
 
                const COLLADAFW::UniqueId& data_uid = co->getSkinControllerData();
                if (skin_by_data_uid.find(data_uid) == skin_by_data_uid.end()) {
@@ -746,14 +638,60 @@ bool ArmatureImporter::write_controller(const COLLADAFW::Controller *controller)
                skin_by_data_uid[data_uid].set_controller(co);
        }
        // morph controller
-       else {
-               // shape keys? :)
-               fprintf(stderr, "Morph controller is not supported yet.\n");
+       else if (controller->getControllerType() == COLLADAFW::Controller::CONTROLLER_TYPE_MORPH) {
+               COLLADAFW::MorphController *co = (COLLADAFW::MorphController *)controller;
+               // to be able to find geom id by controller id
+               geom_uid_by_controller_uid[con_id] = co->getSource();
+               //Shape keys are applied in DocumentImporter->finish()
+               morph_controllers.push_back(co);
        }
 
        return true;
 }
 
+void ArmatureImporter::make_shape_keys(){
+       std::vector<COLLADAFW::MorphController *>::iterator mc;
+       float weight;
+        
+       for (mc = morph_controllers.begin(); mc != morph_controllers.end(); mc++) {
+               //Controller data
+               COLLADAFW::UniqueIdArray& morphTargetIds = (*mc)->getMorphTargets();
+               COLLADAFW::FloatOrDoubleArray& morphWeights = (*mc)->getMorphWeights();
+        
+               //Prereq: all the geometries must be imported and mesh objects must be made
+               Object *source_ob = this->mesh_importer->get_object_by_geom_uid((*mc)->getSource());
+               
+               Mesh *source_me = (Mesh*) source_ob->data;
+               //insert key to source mesh
+               Key *key = source_me->key = BKE_key_add((ID *)source_me);
+               key->type = KEY_RELATIVE;
+               KeyBlock *kb;
+               
+               //insert basis key
+               kb = BKE_keyblock_add_ctime(key, "Basis", FALSE);
+               BKE_key_convert_from_mesh(source_me, kb);
+
+               //insert other shape keys
+               for ( int i = 0 ; i < morphTargetIds.getCount() ; i++ ){
+                       //better to have a seperate map of morph objects, 
+                       //This'll do for now since only mesh morphing is imported
+                       Mesh *me = this->mesh_importer->get_mesh_by_geom_uid(morphTargetIds[i]);
+                       
+                       if(me){
+                               me->key = key;
+                               kb = BKE_keyblock_add_ctime(key, me->id.name, FALSE);
+                               BKE_key_convert_from_mesh(me, kb);
+                               
+                               //apply weights
+                               weight =  morphWeights.getFloatValues()->getData()[i];
+                               kb->curval = weight;
+                       }
+                       else 
+                               fprintf(stderr, "Morph target geometry not found.\n");
+               }
+       }
+}
+
 
 COLLADAFW::UniqueId *ArmatureImporter::get_geometry_uid(const COLLADAFW::UniqueId& controller_uid)
 {
index bb710f0..b07edfb 100644 (file)
 
 #include "COLLADAFWNode.h"
 #include "COLLADAFWUniqueId.h"
+#include "COLLADAFWMorphController.h"
 
 extern "C" {
 #include "BKE_context.h"
+#include "BKE_key.h"
 
 #include "DNA_armature_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_key_types.h"
 
 #include "ED_armature.h"
 }
@@ -88,6 +91,7 @@ private:
        std::map<COLLADAFW::UniqueId, COLLADAFW::Node*> joint_by_uid; // contains all joints
        std::vector<COLLADAFW::Node*> root_joints;
        std::vector<COLLADAFW::Node*> finished_joints;
+       std::vector<COLLADAFW::MorphController*> morph_controllers;
        std::map<COLLADAFW::UniqueId, Object*> joint_parent_map;
        std::map<COLLADAFW::UniqueId, Object*> unskinned_armature_map;
 
@@ -103,12 +107,9 @@ private:
        JointData *get_joint_data(COLLADAFW::Node *node);
 #endif
 
-       void create_bone(SkinInfo& skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
+       void create_bone(SkinInfo* skin, COLLADAFW::Node *node, EditBone *parent, int totchild,
                         float parent_mat[4][4], bArmature *arm);
 
-       void create_unskinned_bone(COLLADAFW::Node *node, EditBone *parent, int totchild,
-                                  float parent_mat[4][4], Object * ob_arm);
-
        void add_leaf_bone(float mat[4][4], EditBone *bone, COLLADAFW::Node * node);
 
        void fix_leaf_bones();
@@ -140,9 +141,6 @@ public:
        ArmatureImporter(UnitConverter *conv, MeshImporterBase *mesh, AnimationImporterBase *anim, Scene *sce);
        ~ArmatureImporter();
 
-       // root - if this joint is the top joint in hierarchy, if a joint
-       // is a child of a node (not joint), root should be true since
-       // this is where we build armature bones from
        void add_joint(COLLADAFW::Node *node, bool root, Object *parent, Scene *sce);
 
 #if 0
@@ -152,6 +150,8 @@ public:
        // here we add bones to armatures, having armatures previously created in write_controller
        void make_armatures(bContext *C);
 
+       void make_shape_keys();
+
 #if 0
        // link with meshes, create vertex groups, assign weights
        void link_armature(Object *ob_arm, const COLLADAFW::UniqueId& geom_id, const COLLADAFW::UniqueId& controller_data_id);
index 0091df3..7f38934 100644 (file)
@@ -36,6 +36,9 @@ set(INC
        ../windowmanager
        ../imbuf
        ../../../intern/guardedalloc
+       ../ikplugin
+       ../../../intern/iksolver/extern
+       
 )
 
 set(INC_SYS
@@ -48,6 +51,7 @@ set(SRC
        ArmatureExporter.cpp
        ArmatureImporter.cpp
        CameraExporter.cpp
+       ControllerExporter.cpp
        DocumentExporter.cpp
        DocumentImporter.cpp
        EffectExporter.cpp
@@ -74,6 +78,7 @@ set(SRC
        ArmatureExporter.h
        ArmatureImporter.h
        CameraExporter.h
+       ControllerExporter.h
        DocumentExporter.h
        DocumentImporter.h
        EffectExporter.h
diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp
new file mode 100644 (file)
index 0000000..d41c907
--- /dev/null
@@ -0,0 +1,598 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed,
+ *                 Nathan Letwory, Sukhitha Jayathilake
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/collada/ControllerExporter.cpp
+ *  \ingroup collada
+ */
+
+#include "COLLADASWBaseInputElement.h"
+#include "COLLADASWInstanceController.h"
+#include "COLLADASWPrimitves.h"
+#include "COLLADASWSource.h"
+
+#include "DNA_action_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+
+#include "BKE_action.h"
+#include "BKE_armature.h"
+
+extern "C" {
+#include "BKE_main.h"
+#include "BKE_mesh.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+}
+
+#include "ED_armature.h"
+
+#include "BLI_listbase.h"
+
+#include "GeometryExporter.h"
+#include "ArmatureExporter.h"
+#include "ControllerExporter.h"
+#include "SceneExporter.h"
+
+#include "collada_utils.h"
+
+// XXX exporter writes wrong data for shared armatures.  A separate
+// controller should be written for each armature-mesh binding how do
+// we make controller ids then?
+ControllerExporter::ControllerExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings) : COLLADASW::LibraryControllers(sw), export_settings(export_settings) {
+}
+
+bool ControllerExporter::is_skinned_mesh(Object *ob)
+{
+       return bc_get_assigned_armature(ob) != NULL;
+}
+
+
+void ControllerExporter::write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone)
+{
+       if (bc_is_root_bone(bone, this->export_settings->deform_bones_only))
+               ins.addSkeleton(COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_joint_id(bone, ob_arm)));
+       else {
+               for (Bone *child = (Bone *)bone->childbase.first; child; child = child->next) {
+                       write_bone_URLs(ins, ob_arm, child);
+               }
+       }
+}
+
+bool ControllerExporter::add_instance_controller(Object *ob)
+{
+       Object *ob_arm = bc_get_assigned_armature(ob);
+       bArmature *arm = (bArmature *)ob_arm->data;
+
+       const std::string& controller_id = get_controller_id(ob_arm, ob);
+
+       COLLADASW::InstanceController ins(mSW);
+       ins.setUrl(COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, controller_id));
+
+       Mesh *me = (Mesh *)ob->data;
+       if (!me->dvert) return false;
+
+       // write root bone URLs
+       Bone *bone;
+       for (bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) {
+               write_bone_URLs(ins, ob_arm, bone);
+       }
+    
+       InstanceWriter::add_material_bindings(ins.getBindMaterial(), ob, this->export_settings->active_uv_only);
+               
+       ins.add();
+       return true;
+}
+
+void ControllerExporter::export_controllers(Scene *sce)
+{
+       scene = sce;
+
+       openLibrary();
+
+       GeometryFunctor gf;
+       gf.forEachMeshObjectInExportSet<ControllerExporter>(sce, *this, this->export_settings->export_set);
+
+       closeLibrary();
+}
+
+void ControllerExporter::operator()(Object *ob)
+{
+       Object *ob_arm = bc_get_assigned_armature(ob);
+       Key *key = BKE_key_from_object(ob);
+
+       if (ob_arm)
+               export_skin_controller(ob, ob_arm);
+       if(key){
+               export_morph_controller(ob, key);
+       }
+}
+#if 0
+
+bool ArmatureExporter::already_written(Object *ob_arm)
+{
+       return std::find(written_armatures.begin(), written_armatures.end(), ob_arm) != written_armatures.end();
+}
+
+void ArmatureExporter::wrote(Object *ob_arm)
+{
+       written_armatures.push_back(ob_arm);
+}
+
+void ArmatureExporter::find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce)
+{
+       objects.clear();
+
+       Base *base = (Base *) sce->base.first;
+       while (base) {
+               Object *ob = base->object;
+               
+               if (ob->type == OB_MESH && get_assigned_armature(ob) == ob_arm) {
+                       objects.push_back(ob);
+               }
+
+               base = base->next;
+       }
+}
+#endif
+
+std::string ControllerExporter::get_joint_sid(Bone *bone, Object *ob_arm)
+{
+       return get_joint_id(bone, ob_arm);
+}
+
+std::string ControllerExporter::get_controller_id(Object *ob_arm, Object *ob)
+{
+       return translate_id(id_name(ob_arm)) + "_" + translate_id(id_name(ob)) + SKIN_CONTROLLER_ID_SUFFIX;
+}
+
+std::string ControllerExporter::get_controller_id(Key *key, Object *ob)
+{
+       return translate_id(id_name(ob)) + MORPH_CONTROLLER_ID_SUFFIX;
+}
+
+// ob should be of type OB_MESH
+// both args are required
+void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm)
+{
+       // joint names
+       // joint inverse bind matrices
+       // vertex weights
+
+       // input:
+       // joint names: ob -> vertex group names
+       // vertex group weights: me->dvert -> groups -> index, weight
+
+#if 0
+       me->dvert :
+
+       typedef struct MDeformVert {
+               struct MDeformWeight *dw;
+               int totweight;
+               int flag;   // flag only in use for weightpaint now
+       } MDeformVert;
+
+       typedef struct MDeformWeight {
+               int def_nr;
+               float weight;
+       } MDeformWeight;
+#endif
+
+       bool use_instantiation = this->export_settings->use_object_instantiation;
+       Mesh *me;
+
+       if (this->export_settings->apply_modifiers) 
+               me = bc_to_mesh_apply_modifiers(scene, ob, this->export_settings->export_mesh_type);
+       else 
+               me = (Mesh *)ob->data;
+       
+       BKE_mesh_tessface_ensure(me);
+
+       if (!me->dvert) return;
+
+       std::string controller_name = id_name(ob_arm);
+       std::string controller_id = get_controller_id(ob_arm, ob);
+
+       openSkin(controller_id, controller_name,
+                COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation)));
+
+       add_bind_shape_mat(ob);
+
+       std::string joints_source_id = add_joints_source(ob_arm, &ob->defbase, controller_id);
+       std::string inv_bind_mat_source_id = add_inv_bind_mats_source(ob_arm, &ob->defbase, controller_id);
+
+       std::list<int> vcounts;
+       std::list<int> joints;
+       std::list<float> weights;
+
+       {
+               int i, j;
+
+               // def group index -> joint index
+               std::vector<int> joint_index_by_def_index;
+               bDeformGroup *def;
+
+               for (def = (bDeformGroup *)ob->defbase.first, i = 0, j = 0; def; def = def->next, i++) {
+                       if (is_bone_defgroup(ob_arm, def))
+                               joint_index_by_def_index.push_back(j++);
+                       else
+                               joint_index_by_def_index.push_back(-1);
+               }
+
+               for (i = 0; i < me->totvert; i++) {
+                       MDeformVert *vert = &me->dvert[i];
+                       std::map<int, float> jw;
+
+                       // We're normalizing the weights later
+                       float sumw = 0.0f;
+
+                       for (j = 0; j < vert->totweight; j++) {
+                               int joint_index = joint_index_by_def_index[vert->dw[j].def_nr];
+                               if (joint_index != -1 && vert->dw[j].weight > 0.0f) {
+                                       jw[joint_index] += vert->dw[j].weight;
+                                       sumw += vert->dw[j].weight;
+                               }
+                       }
+
+                       if (sumw > 0.0f) {
+                               float invsumw = 1.0f / sumw;
+                               vcounts.push_back(jw.size());
+                               for (std::map<int, float>::iterator m = jw.begin(); m != jw.end(); ++m) {
+                                       joints.push_back((*m).first);
+                                       weights.push_back(invsumw * (*m).second);
+                               }
+                       }
+                       else {
+                               vcounts.push_back(0);
+#if 0
+                               vcounts.push_back(1);
+                               joints.push_back(-1);
+                               weights.push_back(1.0f);
+#endif
+                       }
+               }
+       }
+
+       std::string weights_source_id = add_weights_source(me, controller_id, weights);
+       add_joints_element(&ob->defbase, joints_source_id, inv_bind_mat_source_id);
+       add_vertex_weights_element(weights_source_id, joints_source_id, vcounts, joints);
+
+       if (this->export_settings->apply_modifiers)
+       {
+               BKE_libblock_free_us(&(G.main->mesh), me);
+       }
+       closeSkin();
+       closeController();
+}
+
+void ControllerExporter::export_morph_controller(Object *ob, Key *key)
+{
+       bool use_instantiation = this->export_settings->use_object_instantiation;
+       Mesh *me;
+
+       if (this->export_settings->apply_modifiers) {
+               me = bc_to_mesh_apply_modifiers(scene, ob, this->export_settings->export_mesh_type);
+       } 
+       else {
+               me = (Mesh *)ob->data;
+       }
+       BKE_mesh_tessface_ensure(me);
+
+       std::string controller_name = id_name(ob) + "-morph";
+       std::string controller_id = get_controller_id(key, ob);
+
+       openMorph(controller_id, controller_name,
+                COLLADABU::URI(COLLADABU::Utils::EMPTY_STRING, get_geometry_id(ob, use_instantiation)));
+    
+       std::string targets_id = add_morph_targets(key, ob);
+       std::string morph_weights_id = add_morph_weights(key, ob);
+       
+       COLLADASW::TargetsElement targets(mSW);
+
+       COLLADASW::InputList &input = targets.getInputList();
+
+       input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::MORPH_TARGET, // constant declared in COLLADASWInputList.h
+                                        COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, targets_id)));
+       input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::MORPH_WEIGHT,
+                                        COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, morph_weights_id)));
+       targets.add();
+
+       if (this->export_settings->apply_modifiers)
+       {
+               BKE_libblock_free_us(&(G.main->mesh), me);
+       }
+    
+       //support for animations
+       //can also try the base element and param alternative
+       add_weight_extras(key);
+       closeMorph();
+       closeController();
+}
+
+std::string ControllerExporter::add_morph_targets(Key *key, Object *ob)
+{
+       std::string source_id = translate_id(id_name(ob)) + TARGETS_SOURCE_ID_SUFFIX;
+
+       COLLADASW::IdRefSource source(mSW);
+       source.setId(source_id);
+       source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+       source.setAccessorCount(key->totkey - 1);
+       source.setAccessorStride(1);
+    
+       COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+       param.push_back("IDREF");
+
+       source.prepareToAppendValues();
+
+       KeyBlock * kb = (KeyBlock*)key->block.first;
+       //skip the basis
+       kb = kb->next;
+       for (; kb; kb = kb->next) {
+               std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name);
+               source.appendValues(geom_id);
+
+       }
+
+       source.finish();
+
+       return source_id;
+}
+
+std::string ControllerExporter::add_morph_weights(Key *key, Object *ob)
+{
+       std::string source_id = translate_id(id_name(ob)) + WEIGHTS_SOURCE_ID_SUFFIX;
+
+       COLLADASW::FloatSourceF source(mSW);
+       source.setId(source_id);
+       source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+       source.setAccessorCount(key->totkey - 1);
+       source.setAccessorStride(1);
+    
+       COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+       param.push_back("MORPH_WEIGHT");
+       
+       source.prepareToAppendValues();
+
+       KeyBlock * kb = (KeyBlock*)key->block.first;
+       //skip the basis
+       kb = kb->next;
+       for (; kb; kb = kb->next) {
+               float weight = kb->curval;
+               source.appendValues(weight);
+       }
+       source.finish();
+
+       return source_id;
+}
+
+//Added to implemente support for animations.
+void ControllerExporter::add_weight_extras(Key *key){
+       // can also try the base element and param alternative
+       COLLADASW::BaseExtraTechnique extra;
+       
+       KeyBlock * kb = (KeyBlock*)key->block.first;
+       //skip the basis
+       kb = kb->next;
+       for (; kb; kb = kb->next) {
+               float weight = kb->curval;
+               extra.addExtraTechniqueParameter ("KHR", "morph_weights" , 0.000, "MORPH_WEIGHT_TO_TARGET");
+       }
+}
+
+
+
+void ControllerExporter::add_joints_element(ListBase *defbase,
+                                          const std::string& joints_source_id, const std::string& inv_bind_mat_source_id)
+{
+       COLLADASW::JointsElement joints(mSW);
+       COLLADASW::InputList &input = joints.getInputList();
+
+       input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h
+                                        COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id)));
+       input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::BINDMATRIX,
+                                        COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, inv_bind_mat_source_id)));
+       joints.add();
+}
+
+void ControllerExporter::add_bind_shape_mat(Object *ob)
+{
+       double bind_mat[4][4];
+
+       converter.mat4_to_dae_double(bind_mat, ob->obmat);
+
+       addBindShapeTransform(bind_mat);
+}
+
+std::string ControllerExporter::add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
+{
+       std::string source_id = controller_id + JOINTS_SOURCE_ID_SUFFIX;
+
+       int totjoint = 0;
+       bDeformGroup *def;
+       for (def = (bDeformGroup *)defbase->first; def; def = def->next) {
+               if (is_bone_defgroup(ob_arm, def))
+                       totjoint++;
+       }
+
+       COLLADASW::NameSource source(mSW);
+       source.setId(source_id);
+       source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+       source.setAccessorCount(totjoint);
+       source.setAccessorStride(1);
+       
+       COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+       param.push_back("JOINT");
+
+       source.prepareToAppendValues();
+
+       for (def = (bDeformGroup *)defbase->first; def; def = def->next) {
+               Bone *bone = get_bone_from_defgroup(ob_arm, def);
+               if (bone)
+                       source.appendValues(get_joint_sid(bone, ob_arm));
+       }
+
+       source.finish();
+
+       return source_id;
+}
+
+std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id)
+{
+       std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX;
+
+       int totjoint = 0;
+       for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
+               if (is_bone_defgroup(ob_arm, def))
+                       totjoint++;
+       }
+
+       COLLADASW::FloatSourceF source(mSW);
+       source.setId(source_id);
+       source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+       source.setAccessorCount(totjoint); //BLI_countlist(defbase));
+       source.setAccessorStride(16);
+       
+       source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4);
+       COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+       param.push_back("TRANSFORM");
+
+       source.prepareToAppendValues();
+
+       bPose *pose = ob_arm->pose;
+       bArmature *arm = (bArmature *)ob_arm->data;
+
+       int flag = arm->flag;
+
+       // put armature in rest position
+       if (!(arm->flag & ARM_RESTPOS)) {
+               arm->flag |= ARM_RESTPOS;
+               BKE_pose_where_is(scene, ob_arm);
+       }
+
+       for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) {
+               if (is_bone_defgroup(ob_arm, def)) {
+                       bPoseChannel *pchan = BKE_pose_channel_find_name(pose, def->name);
+
+                       float mat[4][4];
+                       float world[4][4];
+                       float inv_bind_mat[4][4];
+
+                       // SECOND_LIFE_COMPATIBILITY
+                       if (export_settings->second_life) {
+                               // Only translations, no rotation vs armature
+                               float temp[4][4];
+                               unit_m4(temp);
+                               copy_v3_v3(temp[3], pchan->bone->arm_mat[3]);
+                               mult_m4_m4m4(world, ob_arm->obmat, temp);
+                       }
+                       else {
+                               // make world-space matrix, arm_mat is armature-space
+                               mult_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat);
+                       }
+
+                       invert_m4_m4(mat, world);
+                       converter.mat4_to_dae(inv_bind_mat, mat);
+
+                       source.appendValues(inv_bind_mat);
+               }
+       }
+
+       // back from rest positon
+       if (!(flag & ARM_RESTPOS)) {
+               arm->flag = flag;
+               BKE_pose_where_is(scene, ob_arm);
+       }
+
+       source.finish();
+
+       return source_id;
+}
+
+Bone *ControllerExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def)
+{
+       bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, def->name);
+       return pchan ? pchan->bone : NULL;
+}
+
+bool ControllerExporter::is_bone_defgroup(Object *ob_arm, bDeformGroup *def)
+{
+       return get_bone_from_defgroup(ob_arm, def) != NULL;
+}
+
+std::string ControllerExporter::add_weights_source(Mesh *me, const std::string& controller_id, const std::list<float>& weights)
+{
+       std::string source_id = controller_id + WEIGHTS_SOURCE_ID_SUFFIX;
+
+       COLLADASW::FloatSourceF source(mSW);
+       source.setId(source_id);
+       source.setArrayId(source_id + ARRAY_ID_SUFFIX);
+       source.setAccessorCount(weights.size());
+       source.setAccessorStride(1);
+       
+       COLLADASW::SourceBase::ParameterNameList &param = source.getParameterNameList();
+       param.push_back("WEIGHT");
+
+       source.prepareToAppendValues();
+
+       for (std::list<float>::const_iterator i = weights.begin(); i != weights.end(); ++i) {
+               source.appendValues(*i);
+       }
+
+       source.finish();
+
+       return source_id;
+}
+
+void ControllerExporter::add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id,
+                                                  const std::list<int>& vcounts,
+                                                  const std::list<int>& joints)
+{
+       COLLADASW::VertexWeightsElement weightselem(mSW);
+       COLLADASW::InputList &input = weightselem.getInputList();
+
+       int offset = 0;
+       input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::JOINT, // constant declared in COLLADASWInputList.h
+                                        COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, joints_source_id), offset++));
+       input.push_back(COLLADASW::Input(COLLADASW::InputSemantic::WEIGHT,
+                                        COLLADASW::URI(COLLADABU::Utils::EMPTY_STRING, weights_source_id), offset++));
+
+       weightselem.setCount(vcounts.size());
+
+       // write number of deformers per vertex
+       COLLADASW::PrimitivesBase::VCountList vcountlist;
+
+       vcountlist.resize(vcounts.size());
+       std::copy(vcounts.begin(), vcounts.end(), vcountlist.begin());
+
+       weightselem.prepareToAppendVCountValues();
+       weightselem.appendVertexCount(vcountlist);
+
+       weightselem.CloseVCountAndOpenVElement();
+
+       // write deformer index - weight index pairs
+       int weight_index = 0;
+       for (std::list<int>::const_iterator i = joints.begin(); i != joints.end(); ++i) {
+               weightselem.appendValues(*i, weight_index++);
+       }
+
+       weightselem.finish();
+}
diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h
new file mode 100644 (file)
index 0000000..4355fb6
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Jan Diederich, Tod Liverseed,
+ *                 Nathan Letwory, Sukhitha Jayathilake
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file ControllerExporter.h
+ *  \ingroup collada
+ */
+
+#ifndef __CONTROLLEREXPORTER_H__
+#define __CONTROLLEREXPORTER_H__
+
+#include <list>
+#include <string>
+//#include <vector>
+
+#include "COLLADASWStreamWriter.h"
+#include "COLLADASWLibraryControllers.h"
+#include "COLLADASWInputList.h"
+#include "COLLADASWNode.h"
+#include "COLLADASWExtraTechnique.h"
+
+#include "DNA_armature_types.h"
+#include "DNA_listBase.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_key_types.h"
+
+#include "TransformWriter.h"
+#include "InstanceWriter.h"
+
+#include "ExportSettings.h"
+
+#include "BKE_key.h"
+
+class SceneExporter;
+
+class ControllerExporter : public COLLADASW::LibraryControllers, protected TransformWriter, protected InstanceWriter
+{
+public:
+       ControllerExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings);
+
+       bool is_skinned_mesh(Object *ob);
+
+       bool add_instance_controller(Object *ob);
+
+       void export_controllers(Scene *sce);
+
+       void operator()(Object *ob);
+
+private:
+       Scene *scene;
+       UnitConverter converter;
+       const ExportSettings *export_settings;
+
+#if 0
+       std::vector<Object *> written_armatures;
+
+       bool already_written(Object *ob_arm);
+
+       void wrote(Object *ob_arm);
+
+       void find_objects_using_armature(Object *ob_arm, std::vector<Object *>& objects, Scene *sce);
+#endif
+
+       std::string get_joint_sid(Bone *bone, Object *ob_arm);
+
+       std::string get_controller_id(Object *ob_arm, Object *ob);
+
+       std::string get_controller_id(Key *key, Object *ob);
+
+       // ob should be of type OB_MESH
+       // both args are required
+       void export_skin_controller(Object *ob, Object *ob_arm);
+
+       void export_morph_controller(Object *ob, Key *key);
+
+       void add_joints_element(ListBase *defbase,
+                               const std::string& joints_source_id, const std::string& inv_bind_mat_source_id);
+
+       void add_bind_shape_mat(Object *ob);
+
+       std::string add_morph_targets(Key *key, Object *ob);
+
+       std::string add_morph_weights(Key *key, Object *ob);
+
+       void add_weight_extras(Key *key);
+
+       std::string add_joints_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id);
+
+       std::string add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id);
+
+       Bone *get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def);
+
+       bool is_bone_defgroup(Object *ob_arm, bDeformGroup *def);
+
+       std::string add_weights_source(Mesh *me, const std::string& controller_id,
+                                      const std::list<float>& weights);
+
+       void add_vertex_weights_element(const std::string& weights_source_id, const std::string& joints_source_id,
+                                       const std::list<int>& vcount, const std::list<int>& joints);
+
+       void write_bone_URLs(COLLADASW::InstanceController &ins, Object *ob_arm, Bone *bone);
+};
+
+#endif
index c491326..71909b3 100644 (file)
@@ -123,6 +123,7 @@ extern bool bc_has_object_type(LinkNode *export_set, short obtype);
 #include "ArmatureExporter.h"
 #include "AnimationExporter.h"
 #include "CameraExporter.h"
+#include "ControllerExporter.h"
 #include "EffectExporter.h"
 #include "GeometryExporter.h"
 #include "ImageExporter.h"
@@ -269,11 +270,15 @@ void DocumentExporter::exportCurrentScene(Scene *sce)
 
        // <library_controllers>
        ArmatureExporter arm_exporter(&sw, this->export_settings);
-       if (bc_has_object_type(export_set, OB_ARMATURE)) {
-               arm_exporter.export_controllers(sce);
-       }
+       ControllerExporter controller_exporter(&sw , this->export_settings);
+       //for Morph controller export, removing the check
+       /*if (bc_has_object_type(export_set, OB_ARMATURE)) 
+       {*/
+       controller_exporter.export_controllers(sce);
+       //}
 
        // <library_visual_scenes>
+
        SceneExporter se(&sw, &arm_exporter, this->export_settings);
        se.exportScene(sce);
        
index b7797b5..1d8be59 100644 (file)
@@ -210,10 +210,11 @@ void DocumentImporter::finish()
        }
 
 
-       mesh_importer.optimize_material_assignments();
+       mesh_importer.optimize_material_assignements();
 
        armature_importer.set_tags_map(this->uid_tags_map);
        armature_importer.make_armatures(mContext);
+       armature_importer.make_shape_keys();
 
 #if 0
        armature_importer.fix_animation();
@@ -256,7 +257,7 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW
 {
 
        // The split in #29246, rootmap must point at actual root when
-       // calculating bones in apply_curves_as_matrix.
+       // calculating bones in apply_curves_as_matrix. - actual root is the root node.
        // This has to do with inverse bind poses being world space
        // (the sources for skinned bones' restposes) and the way
        // non-skinning nodes have their "restpose" recursively calculated.
@@ -265,7 +266,7 @@ void DocumentImporter::translate_anim_recursive(COLLADAFW::Node *node, COLLADAFW
        if (par) { // && par->getType() == COLLADAFW::Node::JOINT) {
                // par is root if there's no corresp. key in root_map
                if (root_map.find(par->getUniqueId()) == root_map.end())
-                       root_map[node->getUniqueId()] = par;
+                       root_map[node->getUniqueId()] = node;
                else
                        root_map[node->getUniqueId()] = root_map[par->getUniqueId()];
        }
@@ -376,8 +377,8 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod
                anim_importer.read_node_transform(source_node, obn);
        }
 
-       DAG_scene_sort(CTX_data_main(mContext), sce);
-       DAG_ids_flush_update(CTX_data_main(mContext), 0);
+       /*DAG_scene_sort(CTX_data_main(mContext), sce);
+       DAG_ids_flush_update(CTX_data_main(mContext), 0);*/
 
        COLLADAFW::NodePointerArray &children = source_node->getChildNodes();
        if (children.getCount()) {
@@ -406,22 +407,29 @@ Object *DocumentImporter::create_instance_node(Object *source_ob, COLLADAFW::Nod
        return obn;
 }
 
+// to create constraints off node <extra> tags. Assumes only constraint data in
+// current <extra> with blender profile.
+void DocumentImporter::create_constraints(ExtraTags *et, Object *ob){
+       if ( et && et->isProfile("blender")){
+               std::string name;
+               short* type = 0;
+               et->setData("type", type);
+               bConstraint * con = BKE_add_ob_constraint(ob, "Test_con", *type);
+               
+       }
+}
+
 void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par, bool is_library_node)
 {
        Object *ob = NULL;
        bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
        bool read_transform = true;
 
-       std::vector<Object *> *objects_done = new std::vector<Object *>();
+       ExtraTags *et = getExtraTags(node->getUniqueId());
 
+       std::vector<Object *> *objects_done = new std::vector<Object *>();
+    
        if (is_joint) {
-               if (par) {
-                       Object *empty = par;
-                       par = bc_add_object(sce, OB_ARMATURE, NULL);
-                       bc_set_parent(par, empty->parent, mContext);
-                       //remove empty : todo
-                       object_map.insert(std::make_pair<COLLADAFW::UniqueId, Object *>(parent_node->getUniqueId(), par));
-               }
                armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par, sce);
        }
        else {
@@ -487,10 +495,15 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent
 
                        read_transform = false;
                }
+
                // if node is empty - create empty object
                // XXX empty node may not mean it is empty object, not sure about this
                if ( (geom_done + camera_done + lamp_done + controller_done + inst_done) < 1) {
-                       ob = bc_add_object(sce, OB_EMPTY, NULL);
+                       //Check if Object is armature, by checking if immediate child is a JOINT node.
+                       if(is_armature(node))
+                               ob = bc_add_object(sce, OB_ARMATURE, NULL);
+                       else ob = bc_add_object(sce, OB_EMPTY, NULL);
+
                        objects_done->push_back(ob);
                }
                
@@ -508,6 +521,8 @@ void DocumentImporter::write_node(COLLADAFW::Node *node, COLLADAFW::Node *parent
                                libnode_ob.push_back(ob);
                }
 
+               //create_constraints(et,ob);
+
        }
 
        for (std::vector<Object *>::iterator it = objects_done->begin(); it != objects_done->end(); ++it) {
@@ -959,11 +974,12 @@ bool DocumentImporter::writeLight(const COLLADAFW::Light *light)
        Lamp *lamp = NULL;
        std::string la_id, la_name;
 
-       TagsMap::iterator etit;
+       ExtraTags *et = getExtraTags(light->getUniqueId());
+       /*TagsMap::iterator etit;
        ExtraTags *et = 0;
        etit = uid_tags_map.find(light->getUniqueId().toAscii());
        if (etit != uid_tags_map.end())
-               et = etit->second;
+               et = etit->second;*/
 
        la_id = light->getOriginalId();
        la_name = light->getName();
@@ -1183,3 +1199,14 @@ bool DocumentImporter::addExtraTags(const COLLADAFW::UniqueId &uid, ExtraTags *e
        return true;
 }
 
+bool DocumentImporter::is_armature(COLLADAFW::Node *node){
+       COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes();
+       for (unsigned int i = 0; i < child_nodes.getCount(); i++) {     
+               if(child_nodes[i]->getType() == COLLADAFW::Node::JOINT) return true;
+               else continue;
+       }
+    
+       //no child is JOINT
+       return false;
+
+}
index d54b8db..7e3476f 100644 (file)
 
 
 #include "BKE_object.h"
+#include "BKE_constraint.h"
 
 #include "TransformReader.h"
 #include "AnimationImporter.h"
 #include "ArmatureImporter.h"
+#include "ControllerExporter.h"
 #include "MeshImporter.h"
 
 
@@ -73,9 +75,11 @@ public:
        Object* create_camera_object(COLLADAFW::InstanceCamera*, Scene*);
        Object* create_lamp_object(COLLADAFW::InstanceLight*, Scene*);
        Object* create_instance_node(Object*, COLLADAFW::Node*, COLLADAFW::Node*, Scene*, bool);
+       void create_constraints(ExtraTags *et, Object *ob);
        void write_node(COLLADAFW::Node*, COLLADAFW::Node*, Scene*, Object*, bool);
        MTex* create_texture(COLLADAFW::EffectCommon*, COLLADAFW::Texture&, Material*, int, TexIndexTextureArrayMap&);
        void write_profile_COMMON(COLLADAFW::EffectCommon*, Material*);
+       
        void translate_anim_recursive(COLLADAFW::Node*, COLLADAFW::Node*, Object*);
 
        /**
@@ -128,6 +132,10 @@ public:
        /** Get an extisting ExtraTags for uid */
        ExtraTags* getExtraTags(const COLLADAFW::UniqueId &uid);
 
+       bool is_armature(COLLADAFW::Node * node);
+
+
+
 private:
 
        /** Current import stage we're in. */
index 2504c27..cf45b9b 100644 (file)
@@ -37,6 +37,7 @@ public:
        bool selected;
        bool include_children;
        bool include_armatures;
+       bool include_shapekeys;
        bool deform_bones_only;
 
        bool active_uv_only;
index df49b4f..bcf7e57 100644 (file)
@@ -74,6 +74,7 @@ bool ExtraHandler::parseElement(
                if (!et) {
                        et = new ExtraTags(std::string(profileName));
                        dimp->addExtraTags(uniqueId, et);
+
                }
                currentExtraTags = et;
                return true;
index f33f0fa..6673e1d 100644 (file)
@@ -69,9 +69,8 @@ void GeometryExporter::exportGeom(Scene *sce)
 }
 
 void GeometryExporter::operator()(Object *ob)
-{
+{ 
        // XXX don't use DerivedMesh, Mesh instead?
-
 #if 0          
        DerivedMesh *dm = mesh_get_derived_final(mScene, ob, CD_MASK_BAREMESH);
 #endif
@@ -155,17 +154,92 @@ void GeometryExporter::operator()(Object *ob)
 
        closeGeometry();
 
-       if (this->export_settings->apply_modifiers)
-       {
+       if (this->export_settings->apply_modifiers) {
                BKE_libblock_free_us(&(G.main->mesh), me);
        }
-
-
+    
+       if (this->export_settings->include_shapekeys) {
+               Key * key = BKE_key_from_object(ob);
+               if(key) {
+                       KeyBlock * kb = (KeyBlock*)key->block.first;
+                       //skip the basis
+                       kb = kb->next;
+                       for (; kb; kb = kb->next) {
+                               BKE_key_convert_to_mesh(kb, me);
+                               export_key_mesh(ob, me, kb);
+                       }
+               }
+       }
 #if 0
        dm->release(dm);
 #endif
 }
 
+void GeometryExporter::export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb){
+       std::string geom_id = get_geometry_id(ob, false) + "_morph_" + translate_id(kb->name);
+       std::vector<Normal> nor;
+       std::vector<Face> norind;
+       
+       if (exportedGeometry.find(geom_id) != exportedGeometry.end())
+       {
+               return;
+       }
+
+       std::string geom_name =  id_name(ob) + "_morph_" + kb->name;
+
+       exportedGeometry.insert(geom_id);
+
+       bool has_color = (bool)CustomData_has_layer(&me->fdata, CD_MCOL);
+
+       create_normals(nor, norind, me);
+
+       // openMesh(geoId, geoName, meshId)
+       openMesh(geom_id, geom_name);
+       
+       // writes <source> for vertex coords
+       createVertsSource(geom_id, me);
+       
+       // writes <source> for normal coords
+       createNormalsSource(geom_id, me, nor);
+
+       bool has_uvs = (bool)CustomData_has_layer(&me->fdata, CD_MTFACE);
+       
+       // writes <source> for uv coords if mesh has uv coords
+       if (has_uvs)
+               createTexcoordsSource(geom_id, me);
+
+       if (has_color)
+               createVertexColorSource(geom_id, me);
+
+       // <vertices>
+
+       COLLADASW::Vertices verts(mSW);
+       verts.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::VERTEX));
+       COLLADASW::InputList &input_list = verts.getInputList();
+       COLLADASW::Input input(COLLADASW::InputSemantic::POSITION, getUrlBySemantics(geom_id, COLLADASW::InputSemantic::POSITION));
+       input_list.push_back(input);
+       verts.add();
+
+       //createLooseEdgeList(ob, me, geom_id, norind);
+
+       // XXX slow             
+       if (ob->totcol) {
+               for (int a = 0; a < ob->totcol; a++) {
+                       createPolylist(a, has_uvs, has_color, ob, me, geom_id, norind);
+               }
+       }
+       else {
+               createPolylist(0, has_uvs, has_color, ob, me, geom_id, norind);
+       }
+       
+       closeMesh();
+       
+       if (me->flag & ME_TWOSIDED) {
+               mSW->appendTextBlock("<extra><technique profile=\"MAYA\"><double_sided>1</double_sided></technique></extra>");
+       }
+
+       closeGeometry();
+}
 
 void GeometryExporter::createLooseEdgeList(Object *ob,
                                            Mesh   *me,
index 7161bb7..7cbbf0d 100644 (file)
 #include "DNA_mesh_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_key_types.h"
 
 #include "ExportSettings.h"
 
+#include "BKE_key.h"
+
 extern Object *bc_get_highest_selected_ancestor_or_self(Object *ob);
 
 // TODO: optimize UV sets by making indexed list with duplicates removed
@@ -100,6 +103,8 @@ public:
        COLLADASW::URI getUrlBySemantics(std::string geom_id, COLLADASW::InputSemantic::Semantics type, std::string other_suffix = "");
 
        COLLADASW::URI makeUrl(std::string id);
+
+       void export_key_mesh(Object *ob, Mesh *me, KeyBlock *kb);
        
        /* int getTriCount(MFace *faces, int totface);*/
 private:
index 8256618..febfb77 100644 (file)
@@ -946,6 +946,13 @@ Object *MeshImporter::get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid
        return NULL;
 }
 
+Mesh *MeshImporter::get_mesh_by_geom_uid(const COLLADAFW::UniqueId& mesh_uid)
+{
+       if (uid_mesh_map.find(mesh_uid) != uid_mesh_map.end())
+               return uid_mesh_map[mesh_uid];
+       return NULL;
+}
+
 MTex *MeshImporter::assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture,
                                                Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map,
                                                MTex *color_texture)
@@ -1061,7 +1068,7 @@ std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh)
  *
  * During import all materials have been assigned to Object.
  * Now we iterate over the imported objects and optimize
- * the assignments as follows:
+ * the assignements as follows:
  *
  * for each imported geometry:
  *     if number of users is 1:
@@ -1075,7 +1082,7 @@ std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh)
  *             adjust all other users accordingly.
  *
  **/
-void MeshImporter::optimize_material_assignments()
+void MeshImporter::optimize_material_assignements()
 {
        for (std::vector<Object *>::iterator it = imported_objects.begin();
             it != imported_objects.end(); ++it)
@@ -1119,7 +1126,7 @@ void MeshImporter::optimize_material_assignments()
  * come along with different materials. So we first create the objects
  * and assign the materials to Object, then in a later cleanup we decide
  * which materials shall be moved to the created geometries. Also see
- * optimize_material_assignments() above.
+ * optimize_material_assignements() above.
  */
 MTFace *MeshImporter::assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial,
                                               std::map<COLLADAFW::UniqueId, Material *>& uid_material_map,
index 746b073..946f9ff 100644 (file)
@@ -59,6 +59,7 @@ class MeshImporterBase
 {
 public:
        virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid) = 0;
+       virtual Mesh *get_mesh_by_geom_uid(const COLLADAFW::UniqueId& mesh_uid) = 0;
 };
 
 class UVDataWrapper
@@ -106,10 +107,10 @@ private:
 #endif
        
        void set_face_uv(MTFace *mtface, UVDataWrapper &uvs,
-                        COLLADAFW::IndexList& index_list, unsigned int *tris_indices);
+                                        COLLADAFW::IndexList& index_list, unsigned int *tris_indices);
 
        void set_face_uv(MTFace *mtface, UVDataWrapper &uvs,
-                        COLLADAFW::IndexList& index_list, int index, bool quad);
+                                       COLLADAFW::IndexList& index_list, int index, bool quad);
 
 #ifdef COLLADA_DEBUG
        void print_index_list(COLLADAFW::IndexList& index_list);
@@ -132,7 +133,7 @@ private:
 
        CustomData create_edge_custom_data(EdgeHash *eh);
 
-       void allocate_face_data(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris);
+    void allocate_face_data(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris);
 
        // TODO: import uv set names
        void read_faces(COLLADAFW::Mesh *mesh, Mesh *me, int new_tris);
@@ -151,24 +152,26 @@ public:
        void bmeshConversion();
 
        virtual Object *get_object_by_geom_uid(const COLLADAFW::UniqueId& geom_uid);
+
+       virtual Mesh *get_mesh_by_geom_uid(const COLLADAFW::UniqueId& geom_uid);
        
        MTex *assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture,
-                                        Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map,
-                                        MTex *color_texture);
+                                                                        Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map,
+                                                                        MTex *color_texture);
 
-       void optimize_material_assignments();
+       void optimize_material_assignements();
 
        MTFace *assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial,
-                                       std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
-                                       Object *ob, const COLLADAFW::UniqueId *geom_uid,
-                                       MTex **color_texture, char *layername, MTFace *texture_face,
-                                       std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index);
+                                                                       std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
+                                                                       Object *ob, const COLLADAFW::UniqueId *geom_uid, 
+                                                                       MTex **color_texture, char *layername, MTFace *texture_face,
+                                                                       std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index);
        
        
        Object *create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom,
-                                  bool isController,
-                                  std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
-                                  std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map);
+                                                          bool isController,
+                                                          std::map<COLLADAFW::UniqueId, Material*>& uid_material_map,
+                                                          std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map);
 
        // create a mesh storing a pointer in a map so it can be retrieved later by geometry UID
        bool write_geometry(const COLLADAFW::Geometry* geom);
index 6d239ae..bb33e40 100644 (file)
@@ -182,6 +182,46 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
                colladaNode.end();
        }
 
+       if (ob->constraints.first != NULL ){
+               bConstraint *con = (bConstraint*) ob->constraints.first;
+               while(con){
+                       std::string con_name(id_name(con));
+                       std::string con_tag = con_name + "_constraint";
+                       colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"type",con->type);
+                       colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"enforce",con->enforce);
+                       colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"flag",con->flag);
+                       colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"headtail",con->headtail);
+                       colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"lin_error",con->lin_error);
+                       colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"own_space",con->ownspace);
+                       colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"rot_error",con->rot_error);
+                       colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"tar_space",con->tarspace);
+                       colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"lin_error",con->lin_error);
+                       
+                       //not ideal: add the target object name as another parameter. 
+                       //No real mapping in the .dae
+                       //Need support for multiple target objects also.
+                       bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
+                       ListBase targets = {NULL, NULL};
+                       if (cti && cti->get_constraint_targets) {
+                       
+                               bConstraintTarget *ct;
+                               Object *obtar;
+                       
+                               cti->get_constraint_targets(con, &targets);
+                               if(cti){
+                                       int i = 1;
+                                       for (ct = (bConstraintTarget*)targets.first; ct; ct = ct->next){
+                                               obtar = ct->tar;
+                                               std::string tar_id(id_name(obtar));
+                                               colladaNode.addExtraTechniqueChildParameter("blender",con_tag,"target_id",tar_id);
+                                       }
+                               }
+                       }
+            
+                       con = con->next;
+               }
+       }
+
        for (std::list<Object *>::iterator i = child_objects.begin(); i != child_objects.end(); ++i) {
                if (bc_is_marked(*i)) {
                        bc_remove_mark(*i);
@@ -189,8 +229,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce)
                }
        }
 
-       if (ob->type != OB_ARMATURE) {
+       if (ob->type != OB_ARMATURE)
                colladaNode.end();
-       }
 }
 
index 31b471a..f438c00 100644 (file)
@@ -43,6 +43,7 @@ extern "C" {
 #include "DNA_anim_types.h"
 #include "DNA_action_types.h"
 #include "DNA_curve_types.h"
+#include "DNA_constraint_types.h"
 #include "DNA_armature_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_userdef_types.h"
@@ -51,6 +52,7 @@ extern "C" {
 #include "BKE_fcurve.h"
 #include "BKE_animsys.h"
 #include "BLI_path_util.h"
+#include "BKE_constraint.h"
 #include "BLI_fileops.h"
 #include "ED_keyframing.h"
 }
index 5bc135e..24124c7 100644 (file)
@@ -45,29 +45,31 @@ void TransformReader::get_node_mat(float mat[4][4], COLLADAFW::Node *node, std::
 
                COLLADAFW::Transformation *tm = node->getTransformations()[i];
                COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
-
-               switch (type) {
-                       case COLLADAFW::Transformation::TRANSLATE:
-                               dae_translate_to_mat4(tm, cur);
-                               break;
-                       case COLLADAFW::Transformation::ROTATE:
-                               dae_rotate_to_mat4(tm, cur);
-                               break;
-                       case COLLADAFW::Transformation::SCALE:
-                               dae_scale_to_mat4(tm, cur);
-                               break;
-                       case COLLADAFW::Transformation::MATRIX:
-                               dae_matrix_to_mat4(tm, cur);
-                               break;
-                       case COLLADAFW::Transformation::LOOKAT:
-                       case COLLADAFW::Transformation::SKEW:
-                               fprintf(stderr, "LOOKAT and SKEW transformations are not supported yet.\n");
-                               break;
+        
+               if(type == COLLADAFW::Transformation::MATRIX){
+                       dae_matrix_to_mat4(tm, mat);
+                       return;
                }
-
-               copy_m4_m4(copy, mat);
-               mult_m4_m4m4(mat, copy, cur);
-
+               else{                   
+                       switch (type) {
+                               case COLLADAFW::Transformation::TRANSLATE:
+                                       dae_translate_to_mat4(tm, cur);
+                                       break;
+                               case COLLADAFW::Transformation::ROTATE:
+                                       dae_rotate_to_mat4(tm, cur);
+                                       break;
+                               case COLLADAFW::Transformation::SCALE:
+                                       dae_scale_to_mat4(tm, cur);
+                                       break;
+                               case COLLADAFW::Transformation::LOOKAT:
+                               case COLLADAFW::Transformation::SKEW:
+                                       fprintf(stderr, "LOOKAT and SKEW transformations are not supported yet.\n");
+                                       break;
+                       }
+                       copy_m4_m4(copy, mat);
+                       mult_m4_m4m4(mat, copy, cur);
+               }
+               
                if (animation_map) {
                        // AnimationList that drives this Transformation
                        const COLLADAFW::UniqueId& anim_list_id = tm->getAnimationList();
index 3fe3f62..f06c8cb 100644 (file)
@@ -52,9 +52,9 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4],
 
        TransformBase::decompose(local, loc, rot, NULL, scale);
        if (node.getType() == COLLADASW::Node::JOINT)
-               node.addMatrix("transform", dmat);
+       node.addMatrix("transform", dmat);
        else
-               add_transform(node, loc, rot, scale);
+       add_transform(node, loc, rot, scale);
 }
 
 void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob)
@@ -93,12 +93,13 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob)
 
        add_transform(node, loc, rot, scale);
 #endif
-
+       UnitConverter converter;
+       
        /* Using parentinv should allow use of existing curves */
        if (ob->parent) {
                // If parentinv is identity don't add it.
                bool add_parinv = false;
-
+               
                for (int i = 0; i < 16; ++i) {
                        float f = (i % 4 == i / 4) ? 1.0f : 0.0f;
                        add_parinv |= (ob->parentinv[i % 4][i / 4] != f);
@@ -106,12 +107,14 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob)
 
                if (add_parinv) {
                        double dmat[4][4];
-                       UnitConverter converter;
                        converter.mat4_to_dae_double(dmat, ob->parentinv);
                        node.addMatrix("parentinverse", dmat);
                }
        }
-
+    
+       double d_obmat[4][4];   
+       converter.mat4_to_dae_double(d_obmat, ob->obmat);
+       node.addMatrix("transform",d_obmat);
        add_transform(node, ob->loc, ob->rot, ob->size);
 }
 
@@ -123,7 +126,6 @@ void TransformWriter::add_node_transform_identity(COLLADASW::Node& node)
 
 void TransformWriter::add_transform(COLLADASW::Node& node, float loc[3], float rot[3], float scale[3])
 {
-       node.addTranslate("location", loc[0], loc[1], loc[2]);
 #if 0
        node.addRotateZ("rotationZ", COLLADABU::Math::Utils::radToDegF(rot[2]));
        node.addRotateY("rotationY", COLLADABU::Math::Utils::radToDegF(rot[1]));
@@ -132,6 +134,7 @@ void TransformWriter::add_transform(COLLADASW::Node& node, float loc[3], float r
        node.addRotateZ("rotationZ", RAD2DEGF(rot[2]));
        node.addRotateY("rotationY", RAD2DEGF(rot[1]));
        node.addRotateX("rotationX", RAD2DEGF(rot[0]));
-
        node.addScale("scale", scale[0], scale[1], scale[2]);
+       node.addTranslate("location", loc[0], loc[1], loc[2]);
+
 }
index fbb1888..ef34c55 100644 (file)
@@ -59,6 +59,7 @@ int collada_export(Scene *sce,
                    int selected,
                    int include_children,
                    int include_armatures,
+                                  int include_shapekeys,
                    int deform_bones_only,
 
                                   int active_uv_only,
@@ -89,6 +90,7 @@ int collada_export(Scene *sce,
        export_settings.selected                 = selected          != 0;
        export_settings.include_children         = include_children  != 0;
        export_settings.include_armatures        = include_armatures != 0;
+       export_settings.include_shapekeys        = include_shapekeys != 0;
        export_settings.deform_bones_only        = deform_bones_only != 0;
 
        export_settings.active_uv_only           = active_uv_only != 0;
index 13f8151..a02e3e0 100644 (file)
@@ -55,6 +55,7 @@ int collada_export(Scene *sce,
                    int selected,
                    int include_children,
                    int include_armatures,
+                   int include_shapekeys,
                    int deform_bones_only,
 
                                   int active_uv_only,
index 51d81dc..64c5673 100644 (file)
@@ -283,3 +283,9 @@ std::string get_material_id(Material *mat)
 {
        return translate_id(id_name(mat)) + "-material";
 }
+
+std::string get_morph_id(Object *ob)
+{
+       return translate_id(id_name(ob)) + "-morph";
+}
+
index d92f53f..ba07762 100644 (file)
@@ -99,4 +99,6 @@ extern std::string get_camera_id(Object *ob);
 
 extern std::string get_material_id(Material *mat);
 
+extern std::string get_morph_id(Object *ob);
+
 #endif /* __COLLADA_INTERNAL_H__ */
index ba93206..f53672b 100644 (file)
@@ -84,6 +84,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
        int selected;
        int include_children;
        int include_armatures;
+       int include_shapekeys;
        int deform_bones_only;
 
        int include_uv_textures;
@@ -109,6 +110,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
        selected                 = RNA_boolean_get(op->ptr, "selected");
        include_children         = RNA_boolean_get(op->ptr, "include_children");
        include_armatures        = RNA_boolean_get(op->ptr, "include_armatures");
+       include_shapekeys        = RNA_boolean_get(op->ptr, "include_shapekeys");
        deform_bones_only        = RNA_boolean_get(op->ptr, "deform_bones_only");
 
        include_uv_textures      = RNA_boolean_get(op->ptr, "include_uv_textures");
@@ -130,6 +132,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
                           selected,
                           include_children,
                           include_armatures,
+                          include_shapekeys,
                           deform_bones_only,
 
                           active_uv_only,
@@ -176,6 +179,10 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr)
        uiItemR(row, imfptr, "include_armatures", 0, NULL, ICON_NONE);
        uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
 
+       row = uiLayoutRow(box, FALSE);
+       uiItemR(row, imfptr, "include_shapekeys", 0, NULL, ICON_NONE);
+       uiLayoutSetEnabled(row, RNA_boolean_get(imfptr, "selected"));
+
        /* Texture options */
        box = uiLayoutBox(layout);
        row = uiLayoutRow(box, FALSE);
@@ -266,6 +273,9 @@ void WM_OT_collada_export(wmOperatorType *ot)
        RNA_def_boolean(ot->srna, "include_armatures", 0, "Include Armatures",
                        "Export related armatures (even if not selected)");
 
+       RNA_def_boolean(ot->srna, "include_shapekeys", 1, "Include Shape Keys",
+                       "Export all Shape Keys from Mesh Objects");
+
        RNA_def_boolean(ot->srna, "deform_bones_only", 0, "Deform Bones only",
                        "Only export deforming bones with armatures");
 
index 9b5a858..e877367 100644 (file)
@@ -101,6 +101,7 @@ static void rna_Scene_collada_export(
         int selected,
         int include_children,
         int include_armatures,
+        int include_shapekeys,
         int deform_bones_only,
 
         int active_uv_only,
@@ -113,7 +114,7 @@ static void rna_Scene_collada_export(
         int second_life)
 {
        collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected,
-                      include_children, include_armatures, deform_bones_only,
+                      include_children, include_armatures, include_shapekeys, deform_bones_only,
                       active_uv_only, include_uv_textures, include_material_textures,
                       use_texture_copies, use_object_instantiation, sort_by_name, second_life);
 }
@@ -149,6 +150,7 @@ void RNA_api_scene(StructRNA *srna)
        parm = RNA_def_boolean(func, "selected", 0, "Selection Only", "Export only selected elements");
        parm = RNA_def_boolean(func, "include_children", 0, "Include Children", "Export all children of selected objects (even if not selected)");
        parm = RNA_def_boolean(func, "include_armatures", 0, "Include Armatures", "Export related armatures (even if not selected)");
+       parm = RNA_def_boolean(func, "include_shapekeys", 0, "Include Shape Keys", "Export all Shape Keys from Mesh Objects");
        parm = RNA_def_boolean(func, "deform_bones_only", 0, "Deform Bones only", "Only export deforming bones with armatures");
 
        parm = RNA_def_boolean(func, "active_uv_only", 0, "Active UV Layer only", "Export only the active UV Layer");