diff options
author | Gaia Clary <gaia.clary@machinimatrix.org> | 2018-02-26 18:34:45 +0300 |
---|---|---|
committer | Gaia Clary <gaia.clary@machinimatrix.org> | 2018-02-26 19:16:56 +0300 |
commit | a024da55af09fb75e3b72489a8696878909bf676 (patch) | |
tree | cf9cfcccbba2323816a19647770e07d6b5d3c6e7 /source/blender/collada | |
parent | 5f9657316e4e53594643cf1bb128135a593bcae5 (diff) |
Adding support for Matrix Transformation export
The exporter does export matrix data (4*4 Transformation matrix) only for Skeletal animation. For object animation only exporting to trans/rot/loc is implemented.
This task implements Matrix export also for simple Object animation.
Differential Revision: https://developer.blender.org/D3082
Diffstat (limited to 'source/blender/collada')
-rw-r--r-- | source/blender/collada/AnimationExporter.cpp | 191 | ||||
-rw-r--r-- | source/blender/collada/AnimationExporter.h | 5 | ||||
-rw-r--r-- | source/blender/collada/ControllerExporter.cpp | 2 | ||||
-rw-r--r-- | source/blender/collada/DocumentExporter.cpp | 26 | ||||
-rw-r--r-- | source/blender/collada/ExportSettings.h | 1 | ||||
-rw-r--r-- | source/blender/collada/SceneExporter.cpp | 7 | ||||
-rw-r--r-- | source/blender/collada/SceneExporter.h | 3 | ||||
-rw-r--r-- | source/blender/collada/collada.cpp | 4 | ||||
-rw-r--r-- | source/blender/collada/collada.h | 1 | ||||
-rw-r--r-- | source/blender/collada/collada_utils.cpp | 23 | ||||
-rw-r--r-- | source/blender/collada/collada_utils.h | 8 |
11 files changed, 188 insertions, 83 deletions
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index cf689a4a3eb..8c0733374a1 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -49,7 +49,16 @@ bool AnimationExporter::exportAnimations(Scene *sce) return has_animations; } - +bool AnimationExporter::is_flat_line(std::vector<float> &values, int channel_count) +{ + for (int i = 0; i < values.size(); i += channel_count) { + for (int j = 0; j < channel_count; j++) { + if (!bc_in_range(values[j], values[i+j], 0.000001)) + return false; + } + } + return true; +} /* * This function creates a complete LINEAR Collada <Animation> Entry with all needed * <source>, <sampler>, and <channel> entries. @@ -83,9 +92,11 @@ void AnimationExporter::create_sampled_animation(int channel_count, std::string axis_name, bool is_rot) { - char anim_id[200]; + if (is_flat_line(values, channel_count)) + return; + BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(), label.c_str(), axis_name.c_str()); openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING); @@ -97,8 +108,10 @@ void AnimationExporter::create_sampled_animation(int channel_count, std::string output_id; if (channel_count == 1) output_id = create_source_from_array(COLLADASW::InputSemantic::OUTPUT, &values[0], values.size(), is_rot, anim_id, axis_name.c_str()); - else if(channel_count == 3) + else if (channel_count == 3) output_id = create_xyz_source(&values[0], times.size(), anim_id); + else if (channel_count == 16) + output_id = create_4x4_source(times, values, anim_id); std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX; COLLADASW::LibraryAnimations::Sampler sampler(sw, sampler_id); @@ -135,26 +148,38 @@ void AnimationExporter::create_sampled_animation(int channel_count, void AnimationExporter::export_keyframed_animation_set(Object *ob) { FCurve *fcu = (FCurve *)ob->adt->action->curves.first; + if (!fcu) { + return; /* object has no animation */ + } - char *transformName; - while (fcu) { - //for armature animations as objects - if (ob->type == OB_ARMATURE) - transformName = fcu->rna_path; - else - transformName = extract_transform_name(fcu->rna_path); + if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) { - if ( - STREQ(transformName, "location") || - STREQ(transformName, "scale") || - (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) || - STREQ(transformName, "rotation_quaternion")) - { - create_keyframed_animation(ob, fcu, transformName, false); - } - fcu = fcu->next; + std::vector<float> ctimes; + std::vector<float[4][4]> values; + find_keyframes(ob, ctimes); + if (ctimes.size() > 0) + export_sampled_matrix_animation(ob, ctimes); } + else { + char *transformName; + while (fcu) { + //for armature animations as objects + if (ob->type == OB_ARMATURE) + transformName = fcu->rna_path; + else + transformName = extract_transform_name(fcu->rna_path); + if ( + STREQ(transformName, "location") || + STREQ(transformName, "scale") || + (STREQ(transformName, "rotation_euler") && ob->rotmode == ROT_MODE_EUL) || + STREQ(transformName, "rotation_quaternion")) + { + create_keyframed_animation(ob, fcu, transformName, false); + } + fcu = fcu->next; + } + } } /* @@ -171,19 +196,52 @@ void AnimationExporter::export_keyframed_animation_set(Object *ob) */ void AnimationExporter::export_sampled_animation_set(Object *ob) { + std::vector<float>ctimes; + find_sampleframes(ob, ctimes); + if (ctimes.size() > 0) { + if (this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) + export_sampled_matrix_animation(ob, ctimes); + else + export_sampled_transrotloc_animation(ob, ctimes); + } +} + +void AnimationExporter::export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes) +{ + UnitConverter converter; + + std::vector<float> values; + + for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime) { + float fmat[4][4]; + float outmat[4][4]; + + bc_update_scene(scene, *ctime); + BKE_object_matrix_local_get(ob, fmat); + converter.mat4_to_dae(outmat, fmat); + + if (this->export_settings->limit_precision) + bc_sanitize_mat(outmat, 6); + + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + values.push_back(outmat[j][i]); + } + + std::string ob_name = id_name(ob); + + create_sampled_animation(16, ctimes, values, ob_name, "transform", "", false); +} + +void AnimationExporter::export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes) +{ static int LOC = 0; static int EULX = 1; static int EULY = 2; static int EULZ = 3; static int SCALE = 4; - static int TIME = 5; - - if (this->export_settings->sampling_rate < 1) - return; // to avoid infinite loop - std::vector<float> baked_curves[6]; - std::vector<float> &ctimes = baked_curves[TIME]; - find_sampleframes(ob, ctimes); + std::vector<float> baked_curves[5]; for (std::vector<float>::iterator ctime = ctimes.begin(); ctime != ctimes.end(); ++ctime ) { float fmat[4][4]; @@ -192,7 +250,7 @@ void AnimationExporter::export_sampled_animation_set(Object *ob) float fsize[3]; float feul[3]; - evaluate_anim_with_constraints(ob, *ctime); // set object transforms to the frame + bc_update_scene(scene, *ctime); BKE_object_matrix_local_get(ob, fmat); mat4_decompose(floc, fquat, fsize, fmat); @@ -214,16 +272,16 @@ void AnimationExporter::export_sampled_animation_set(Object *ob) std::string ob_name = id_name(ob); - create_sampled_animation(3, baked_curves[TIME], baked_curves[SCALE], ob_name, "scale", "", false); - create_sampled_animation(3, baked_curves[TIME], baked_curves[LOC], ob_name, "location", "", false); + create_sampled_animation(3, ctimes, baked_curves[SCALE], ob_name, "scale", "", false); + create_sampled_animation(3, ctimes, baked_curves[LOC], ob_name, "location", "", false); /* Not sure how to export rotation as a 3channel animation, * so separate into 3 single animations for now: */ - create_sampled_animation(1, baked_curves[TIME], baked_curves[EULX], ob_name, "rotation", "X", true); - create_sampled_animation(1, baked_curves[TIME], baked_curves[EULY], ob_name, "rotation", "Y", true); - create_sampled_animation(1, baked_curves[TIME], baked_curves[EULZ], ob_name, "rotation", "Z", true); + create_sampled_animation(1, ctimes, baked_curves[EULX], ob_name, "rotation", "X", true); + create_sampled_animation(1, ctimes, baked_curves[EULY], ob_name, "rotation", "Y", true); + create_sampled_animation(1, ctimes, baked_curves[EULZ], ob_name, "rotation", "Z", true); fprintf(stdout, "Animation Export: Baked %zd frames for %s (sampling rate: %d)\n", baked_curves[0].size(), @@ -242,19 +300,19 @@ void AnimationExporter::operator()(Object *ob) if (ob->adt && ob->adt->action) { if (ob->type == OB_ARMATURE) { + /* Export skeletal animation (if any)*/ bArmature *arm = (bArmature *)ob->data; for (Bone *bone = (Bone *)arm->bonebase.first; bone; bone = bone->next) write_bone_animation_matrix(ob, bone); } + + /* Armatures can have object animation and skeletal animation*/ + if (this->export_settings->sampling_rate < 1) { + export_keyframed_animation_set(ob); + } else { - if (this->export_settings->sampling_rate == -1) { - export_keyframed_animation_set(ob); - } - else { - export_sampled_animation_set(ob); - } + export_sampled_animation_set(ob); } - } export_object_constraint_animation(ob); @@ -1186,9 +1244,51 @@ std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemanti return source_id; } +std::string AnimationExporter::create_4x4_source(std::vector<float> &ctimes, std::vector<float> &values , const std::string &anim_id) +{ + COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; + std::string source_id = anim_id + get_semantic_suffix(semantic); + + COLLADASW::Float4x4Source source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(ctimes.size()); + source.setAccessorStride(16); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + add_source_parameters(param, semantic, false, NULL, true); + + source.prepareToAppendValues(); + + bPoseChannel *parchan = NULL; + bPoseChannel *pchan = NULL; + + + std::vector<float>::iterator it; + + for (it = values.begin(); it != values.end(); it+=16) { + float mat[4][4]; + + bc_copy_m4_farray(mat, &*it); + + UnitConverter converter; + double outmat[4][4]; + converter.mat4_to_dae_double(outmat, mat); + + if (this->export_settings->limit_precision) + bc_sanitize_mat(outmat, 6); + + source.appendValues(outmat); + } + + source.finish(); + return source_id; +} std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob, Bone *bone, const std::string &anim_id) { + bool is_bone_animation = ob->type == OB_ARMATURE && bone; + COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; std::string source_id = anim_id + get_semantic_suffix(semantic); @@ -1206,7 +1306,7 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj bPoseChannel *parchan = NULL; bPoseChannel *pchan = NULL; - if (ob->type == OB_ARMATURE && bone) { + if (is_bone_animation) { bPose *pose = ob->pose; pchan = BKE_pose_channel_find_name(pose, bone->name); if (!pchan) @@ -1224,11 +1324,8 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj float frame = *it; float ctime = BKE_scene_frame_get_from_ctime(scene, frame); - CFRA = BKE_scene_frame_get_from_ctime(scene, frame); - //BKE_scene_update_for_newframe(G.main->eval_ctx, G.main,scene,scene->lay); - BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL); - - if (bone) { + bc_update_scene(scene, ctime); + if (is_bone_animation) { if (pchan->flag & POSE_CHAIN) { enable_fcurves(ob->adt->action, NULL); BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL); @@ -1268,10 +1365,6 @@ std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Obj } else { - BKE_scene_frame_set(scene, ctime); - Main *bmain = bc_get_main(); - EvaluationContext *ev_context = bc_get_evaluation_context(); - BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay); copy_m4_m4(mat, ob->obmat); } diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h index b26b0427f33..52b46353528 100644 --- a/source/blender/collada/AnimationExporter.h +++ b/source/blender/collada/AnimationExporter.h @@ -144,9 +144,12 @@ protected: float* get_eul_source_for_quat(Object *ob ); + bool is_flat_line(std::vector<float> &values, int channel_count); void export_keyframed_animation_set(Object *ob); void create_keyframed_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma = NULL); void export_sampled_animation_set(Object *ob); + void export_sampled_transrotloc_animation(Object *ob, std::vector<float> &ctimes); + void export_sampled_matrix_animation(Object *ob, std::vector<float> &ctimes); void create_sampled_animation(int channel_count, std::vector<float> ×, std::vector<float> &values, std::string, std::string label, std::string axis_name, bool is_rot); void evaluate_anim_with_constraints(Object *ob, float ctime); @@ -161,7 +164,7 @@ protected: std::string create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name); std::string create_xyz_source(float *v, int tot, const std::string& anim_id); - + std::string create_4x4_source(std::vector<float> ×, std::vector<float> &values, 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); diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp index 5cd5e6d271a..4afe71f47ba 100644 --- a/source/blender/collada/ControllerExporter.cpp +++ b/source/blender/collada/ControllerExporter.cpp @@ -282,7 +282,7 @@ void ControllerExporter::export_skin_controller(Object *ob, Object *ob_arm) } if (oob_counter > 0) { - fprintf(stderr, "Ignored %d Vertex weights which use index to non existing VGroup %lu.\n", + fprintf(stderr, "Ignored %d Vertex weights which use index to non existing VGroup %zu.\n", oob_counter, joint_index_by_def_index.size()); } } diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index 957fec50e4b..7ed5d8ff693 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -302,29 +302,11 @@ int DocumentExporter::exportCurrentScene(Scene *sce) SceneExporter se(writer, &arm_exporter, this->export_settings); - // <library_animations> - AnimationExporter ae(writer, this->export_settings); - -#if 0 - bool has_animations = ae.exportAnimations(sce); - /* The following code seems to be an obsolete workaround - Comment out until it proofs correct that we no longer need it. - */ - if (has_animations && this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) { - // channels adressing <matrix> objects is not (yet) supported - // So we force usage of <location>, <translation> and <scale> - fprintf(stdout, - "For animated Ojects we must use decomposed <matrix> elements,\n" \ - "Forcing usage of TransLocRot transformation type."); - se.setExportTransformationType(BC_TRANSFORMATION_TYPE_TRANSROTLOC); + if (this->export_settings->include_animations) { + // <library_animations> + AnimationExporter ae(writer, this->export_settings); + ae.exportAnimations(sce); } - else { - se.setExportTransformationType(this->export_settings->export_transformation_type); - } -#else - ae.exportAnimations(sce); - se.setExportTransformationType(this->export_settings->export_transformation_type); -#endif se.exportScene(sce); // <scene> diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h index 3b0b5708c7c..73a101108a9 100644 --- a/source/blender/collada/ExportSettings.h +++ b/source/blender/collada/ExportSettings.h @@ -39,6 +39,7 @@ public: bool include_armatures; bool include_shapekeys; bool deform_bones_only; + bool include_animations; int sampling_rate; bool active_uv_only; diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index 73945539931..5a0badf8d3a 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -38,11 +38,6 @@ SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, { } -void SceneExporter::setExportTransformationType(BC_export_transformation_type transformation_type) -{ - this->transformation_type = transformation_type; -} - void SceneExporter::exportScene(Scene *sce) { // <library_visual_scenes> <visual_scene> @@ -138,7 +133,7 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) // for skinned mesh we write obmat in <bind_shape_matrix> TransformWriter::add_node_transform_identity(colladaNode); else { - TransformWriter::add_node_transform_ob(colladaNode, ob, this->transformation_type); + TransformWriter::add_node_transform_ob(colladaNode, ob, this->export_settings->export_transformation_type); } // <instance_geometry> diff --git a/source/blender/collada/SceneExporter.h b/source/blender/collada/SceneExporter.h index c7c15dba2cb..b896b9abd8d 100644 --- a/source/blender/collada/SceneExporter.h +++ b/source/blender/collada/SceneExporter.h @@ -97,11 +97,8 @@ class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter, public: SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings); void exportScene(Scene *sce); - void setExportTransformationType(BC_export_transformation_type transformation_type); private: - BC_export_transformation_type transformation_type; - // required for writeNodes() for bone-parented objects friend class ArmatureExporter; void exportHierarchy(Scene *sce); void writeNodes(Object *ob, Scene *sce); diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index 79f50888150..9605dae275b 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -78,6 +78,7 @@ int collada_export(Scene *sce, int include_armatures, int include_shapekeys, int deform_bones_only, + int include_animations, int sampling_rate, int active_uv_only, @@ -104,7 +105,8 @@ int collada_export(Scene *sce, 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.sampling_rate = sampling_rate; + export_settings.include_animations = include_animations; + export_settings.sampling_rate = sampling_rate; export_settings.active_uv_only = active_uv_only != 0; export_settings.export_texture_type = export_texture_type; diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h index a8f082f630c..99f601b7db7 100644 --- a/source/blender/collada/collada.h +++ b/source/blender/collada/collada.h @@ -77,6 +77,7 @@ int collada_export(struct Scene *sce, int include_armatures, int include_shapekeys, int deform_bones_only, + int include_animations, int sampling_rate, int active_uv_only, diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 9f984a33ed1..fcd92e220c0 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -144,6 +144,14 @@ EvaluationContext *bc_get_evaluation_context() return bmain->eval_ctx; } +void bc_update_scene(Scene *scene, float ctime) +{ + BKE_scene_frame_set(scene, ctime); + Main *bmain = bc_get_main(); + EvaluationContext *ev_context = bc_get_evaluation_context(); + BKE_scene_update_for_newframe(ev_context, bmain, scene, scene->lay); +} + Object *bc_add_object(Scene *scene, int type, const char *name) { Object *ob = BKE_object_add_only_object(G.main, type, name); @@ -883,6 +891,21 @@ void bc_sanitize_mat(double mat[4][4], int precision) mat[i][j] = double_round(mat[i][j], precision); } +void bc_copy_m4_farray(float r[4][4], float *a) +{ + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + r[i][j] = *a++; +} + +void bc_copy_farray_m4(float *r, float a[4][4]) +{ + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + *r++ = a[i][j]; + +} + /* * Returns name of Active UV Layer or empty String if no active UV Layer defined. * Assuming the Object is of type MESH diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h index 8b5903b9746..bbe36f2999c 100644 --- a/source/blender/collada/collada_utils.h +++ b/source/blender/collada/collada_utils.h @@ -65,6 +65,7 @@ typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex *> > TexIndexTextureA extern Main *bc_get_main(); extern EvaluationContext *bc_get_evaluation_context(); +extern void bc_update_scene(Scene *scene, float ctime); extern float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index); extern int bc_test_parent_loop(Object *par, Object *ob); @@ -102,6 +103,13 @@ extern bool bc_is_leaf_bone(Bone *bone); extern EditBone *bc_get_edit_bone(bArmature * armature, char *name); extern int bc_set_layer(int bitfield, int layer, bool enable); extern int bc_set_layer(int bitfield, int layer); + +inline bool bc_in_range(float a, float b, float range) { + return abs(a - b) < range; +} +void bc_copy_m4_farray(float r[4][4], float *a); +void bc_copy_farray_m4(float *r, float a[4][4]); + extern void bc_sanitize_mat(float mat[4][4], int precision); extern void bc_sanitize_mat(double mat[4][4], int precision); |