Patch #30050 by Juha Mäki-Kanto (kanttori)
authorDomino Marama <domino@dominodesigns.info>
Sun, 5 Feb 2012 16:19:28 +0000 (16:19 +0000)
committerDomino Marama <domino@dominodesigns.info>
Sun, 5 Feb 2012 16:19:28 +0000 (16:19 +0000)
Fixes for Collada exporter.
Adds Second Life compatibility for armatures
Adds objects parentinverse to exported transform if it's non-identity
Fix mismatch between add_inv_bind_mats and add_joints_source accessor counts
Fix bone exports in world space should be local space

source/blender/collada/AnimationExporter.cpp
source/blender/collada/AnimationExporter.h
source/blender/collada/ArmatureExporter.cpp
source/blender/collada/DocumentExporter.cpp
source/blender/collada/ExportSettings.h
source/blender/collada/TransformWriter.cpp
source/blender/collada/collada.cpp
source/blender/collada/collada.h
source/blender/makesrna/intern/rna_scene_api.c
source/blender/windowmanager/intern/wm_operators.c

index 7b57ed2..c2d8c35 100644 (file)
@@ -773,6 +773,27 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames , Ob
                        copy_m4_m4(mat, pchan->pose_mat);
                UnitConverter converter;
 
+               // 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);
+
+                       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;
+
+                               mult_m4_m4m4(mat, temp, mat);
+                       }
+               }
+
                float outmat[4][4];
                converter.mat4_to_dae(outmat,mat);
 
index c3a5c7a..ba7ec68 100644 (file)
@@ -83,7 +83,9 @@ private:
 
 public:
 
-       AnimationExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryAnimations(sw) { this->sw = sw; }
+       AnimationExporter(COLLADASW::StreamWriter *sw, const ExportSettings *export_settings):
+                       COLLADASW::LibraryAnimations(sw), export_settings(export_settings)
+                       { this->sw = sw; }
        
 
        void exportAnimations(Scene *sce);
@@ -92,6 +94,7 @@ public:
        void operator() (Object *ob); 
        
 protected:
+       const ExportSettings *export_settings;
 
        void dae_animation(Object* ob, FCurve *fcu, char* transformName , bool is_param, Material *ma = NULL);
 
index fcfc197..0e89f2d 100644 (file)
@@ -221,8 +221,31 @@ void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW:
                mult_m4_m4m4(mat, invpar, pchan->pose_mat);
        }
        else {
-               // get world-space from armature-space
-               mult_m4_m4m4(mat, ob_arm->obmat, pchan->pose_mat);
+               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);
+       }
+
+       // SECOND_LIFE_COMPATIBILITY
+       if(export_settings->second_life)
+       {
+               // Remove rotations vs armature from transform
+               // parent_rest_rot * mat * irest_rot
+               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);
+
+               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);
+               }
        }
 
        TransformWriter::add_node_transform(node, mat,NULL );
@@ -341,10 +364,16 @@ std::string ArmatureExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase
 {
        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(BLI_countlist(defbase));
+       source.setAccessorCount(totjoint); //BLI_countlist(defbase));
        source.setAccessorStride(16);
        
        source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4);
@@ -366,16 +395,27 @@ std::string ArmatureExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase
 
        for (bDeformGroup *def = (bDeformGroup*)defbase->first; def; def = def->next) {
                if (is_bone_defgroup(ob_arm, def)) {
-
                        bPoseChannel *pchan = get_pose_channel(pose, def->name);
 
                        float mat[4][4];
                        float world[4][4];
                        float inv_bind_mat[4][4];
 
-                       // make world-space matrix, arm_mat is armature-space
-                       mult_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat);
-                       
+                       // 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);
 
index 6e8abc0..6e04a17 100644 (file)
@@ -257,7 +257,7 @@ void DocumentExporter::exportCurrentScene(Scene *sce)
        }
 
        // <library_animations>
-       AnimationExporter ae(&sw);
+       AnimationExporter ae(&sw, this->export_settings);
        ae.exportAnimations(sce);
 
        // <library_controllers>
index 1ad7c8c..80e20ac 100644 (file)
@@ -31,6 +31,7 @@ struct ExportSettings
 {
  public:
  bool selected;
+ bool second_life;
  char *filepath;
 };
 
index 379a061..a2bca67 100644 (file)
@@ -59,6 +59,7 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[][4],
 
 void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob)
 {
+       /*
        float rot[3], loc[3], scale[3];
 
        if (ob->parent) {
@@ -91,6 +92,27 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob)
        }
 
        add_transform(node, loc, rot, scale);
+       */
+
+       /* Using parentinv should allow use of existing curves */
+       // 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 ;
+               if(ob->parentinv[i%4][i/4] != f) add_parinv = true;
+       }
+
+       // Eat this 3ds Max et friends
+       if(add_parinv)
+       {
+               double dmat[4][4];
+               UnitConverter converter;
+               converter.mat4_to_dae_double(dmat, ob->parentinv);
+               node.addMatrix("parentinverse", dmat);
+       }
+
+       add_transform(node, ob->loc, ob->rot, ob->size);
 }
 
 void TransformWriter::add_node_transform_identity(COLLADASW::Node& node)
index 0731fac..39114f6 100644 (file)
@@ -49,11 +49,12 @@ extern "C"
                return 0;
        }
 
-       int collada_export(Scene *sce, const char *filepath, int selected)
+       int collada_export(Scene *sce, const char *filepath, int selected, int second_life)
        {
                ExportSettings export_settings;
                
                export_settings.selected = selected != 0;
+               export_settings.second_life = second_life != 0;
                export_settings.filepath = (char *)filepath;
 
                /* annoying, collada crashes if file cant be created! [#27162] */
index b86f37b..1619773 100644 (file)
@@ -37,7 +37,7 @@ extern "C" {
         * both return 1 on success, 0 on error
         */
        int collada_import(bContext *C, const char *filepath);
-       int collada_export(Scene *sce, const char *filepath, int selected);
+       int collada_export(Scene *sce, const char *filepath, int selected, int second_life);
 #ifdef __cplusplus
 }
 #endif
index 153317f..6d58863 100644 (file)
@@ -84,9 +84,9 @@ static void rna_SceneRender_get_frame_path(RenderData *rd, int frame, char *name
 /* don't remove this, as COLLADA exporting cannot be done through operators in render() callback. */
 #include "../../collada/collada.h"
 
-static void rna_Scene_collada_export(Scene *scene, const char *filepath, int selected)
+static void rna_Scene_collada_export(Scene *scene, const char *filepath, int selected, int second_life)
 {
-       collada_export(scene, filepath, selected);
+       collada_export(scene, filepath, selected, second_life);
 }
 
 #endif
@@ -110,10 +110,11 @@ void RNA_api_scene(StructRNA *srna)
 #ifdef WITH_COLLADA
        /* don't remove this, as COLLADA exporting cannot be done through operators in render() callback. */
        func= RNA_def_function(srna, "collada_export", "rna_Scene_collada_export");
-       RNA_def_string(func, "filepath", "", FILE_MAX, "File Path", "File path to write Collada file");
-       parm= RNA_def_boolean(func, "selected", 0, "Export only selected", "Export only selected elements");
+       parm= RNA_def_string(func, "filepath", "", FILE_MAX, "File Path", "File path to write Collada file");
        RNA_def_property_flag(parm, PROP_REQUIRED);
        RNA_def_property_subtype(parm, PROP_FILEPATH); /* allow non utf8 */
+       parm= RNA_def_boolean(func, "selected", 0, "Export only selected", "Export only selected elements");
+       parm= RNA_def_boolean(func, "second_life", 0, "Export for Second Life", "Compatibility mode for Second Life");
        RNA_def_function_ui_description(func, "Export to collada file");
 #endif
 }
index 3346eda..19c4516 100644 (file)
@@ -2135,7 +2135,7 @@ static int wm_collada_export_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED
 static int wm_collada_export_exec(bContext *C, wmOperator *op)
 {
        char filename[FILE_MAX];
-       int selected;
+       int selected, second_life;
        
        if(!RNA_struct_property_is_set(op->ptr, "filepath")) {
                BKE_report(op->reports, RPT_ERROR, "No filename given");
@@ -2144,7 +2144,8 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op)
 
        RNA_string_get(op->ptr, "filepath", filename);
        selected = RNA_boolean_get(op->ptr, "selected");
-       if(collada_export(CTX_data_scene(C), filename, selected)) {
+       second_life = RNA_boolean_get(op->ptr, "second_life");
+       if(collada_export(CTX_data_scene(C), filename, selected, second_life)) {
                return OPERATOR_FINISHED;
        }
        else {
@@ -2164,6 +2165,8 @@ static void WM_OT_collada_export(wmOperatorType *ot)
        WM_operator_properties_filesel(ot, FOLDERFILE|COLLADAFILE, FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH, FILE_DEFAULTDISPLAY);
        RNA_def_boolean(ot->srna, "selected", 0, "Export only selected",
                "Export only selected elements");
+       RNA_def_boolean(ot->srna, "second_life", 0, "Export for Second Life",
+               "Compatibility mode for Second Life");
 }
 
 /* function used for WM_OT_save_mainfile too */