diff options
author | Arystanbek Dyussenov <arystan.d@gmail.com> | 2010-01-05 20:42:01 +0300 |
---|---|---|
committer | Arystanbek Dyussenov <arystan.d@gmail.com> | 2010-01-05 20:42:01 +0300 |
commit | 0a0d43a926c487ea01761e6e4a98af811fc3c619 (patch) | |
tree | 70b0033bafedaeeb0591f1b199c870df7f77a60b /source/blender/collada | |
parent | 73f84b24fca541caa4aaec02d946b887ddfb216b (diff) | |
parent | 06d548bd6fdb9d3e4fc99ecf3b26617648e6b73c (diff) |
Merge -c 25001,25310,25311,25638,25746 from COLLADA branch into trunk.
Diffstat (limited to 'source/blender/collada')
-rw-r--r-- | source/blender/collada/DocumentExporter.cpp | 686 | ||||
-rw-r--r-- | source/blender/collada/DocumentImporter.cpp | 39 |
2 files changed, 470 insertions, 255 deletions
diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index d2543423097..ef36a2eea9a 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -21,6 +21,7 @@ extern "C" { #include "BKE_DerivedMesh.h" #include "BKE_fcurve.h" +#include "BKE_animsys.h" #include "BLI_path_util.h" #include "BLI_fileops.h" #include "ED_keyframing.h" @@ -36,6 +37,7 @@ extern "C" #include "BKE_armature.h" #include "BKE_image.h" #include "BKE_utildefines.h" +#include "BKE_object.h" #include "BLI_math.h" #include "BLI_string.h" @@ -198,6 +200,12 @@ static std::string get_camera_id(Object *ob) return translate_id(id_name(ob)) + "-camera"; } +std::string get_joint_id(Bone *bone, Object *ob_arm) +{ + return translate_id(id_name(ob_arm) + "_" + bone->name); +} + + /* Utilities to avoid code duplication. Definition can take some time to understand, but they should be useful. @@ -851,11 +859,6 @@ private: return ob_arm; } - std::string get_joint_id(Bone *bone, Object *ob_arm) - { - return translate_id(id_name(ob_arm) + "_" + bone->name); - } - std::string get_joint_sid(Bone *bone) { char name[100]; @@ -1538,9 +1541,23 @@ public: if (t->mapto & MAP_REF) { ep.setReflective(createTexture(ima, uvname, sampler)); } + // alpha if (t->mapto & MAP_ALPHA) { ep.setTransparent(createTexture(ima, uvname, sampler)); } + // extension: + // Normal map --> Must be stored with <extra> tag as different technique, + // since COLLADA doesn't support normal maps, even in current COLLADA 1.5. + if (t->mapto & MAP_NORM) { + COLLADASW::Texture texture(key); + texture.setTexcoord(uvname); + texture.setSampler(*sampler); + // technique FCOLLADA, with the <bump> tag, is most likely the best understood, + // most widespread de-facto standard. + texture.setProfileName("FCOLLADA"); + texture.setChildElementName("bump"); + ep.setExtraTechniqueColorOrTexture(COLLADASW::ColorOrTexture(texture)); + } } // performs the actual writing ep.addProfileElements(); @@ -1720,9 +1737,9 @@ public: class AnimationExporter: COLLADASW::LibraryAnimations { Scene *scene; - std::map<bActionGroup*, std::vector<FCurve*> > fcurves_actionGroup_map; - std::map<bActionGroup*, std::vector<FCurve*> > rotfcurves_actionGroup_map; + public: + AnimationExporter(COLLADASW::StreamWriter *sw): COLLADASW::LibraryAnimations(sw) {} void exportAnimations(Scene *sce) @@ -1736,17 +1753,278 @@ public: closeLibrary(); } - // create <animation> for each transform axis + // called for each exported object + void operator() (Object *ob) + { + if (!ob->adt || !ob->adt->action) return; + + FCurve *fcu = (FCurve*)ob->adt->action->curves.first; + + if (ob->type == OB_ARMATURE) { + if (!ob->data) return; + + bArmature *arm = (bArmature*)ob->data; + for (Bone *bone = (Bone*)arm->bonebase.first; bone; bone = bone->next) + write_bone_animation(ob, bone); + } + else { + while (fcu) { + // TODO "rotation_quaternion" is also possible for objects (although euler is default) + if ((!strcmp(fcu->rna_path, "location") || !strcmp(fcu->rna_path, "scale")) || + (!strcmp(fcu->rna_path, "rotation_euler") && ob->rotmode == ROT_MODE_EUL)) + dae_animation(fcu, id_name(ob)); + + fcu = fcu->next; + } + } + } + +protected: + + void dae_animation(FCurve *fcu, std::string ob_name) + { + const char *axis_names[] = {"X", "Y", "Z"}; + const char *axis_name = NULL; + char anim_id[200]; + char anim_name[200]; + + if (fcu->array_index < 3) + axis_name = axis_names[fcu->array_index]; + + BLI_snprintf(anim_id, sizeof(anim_id), "%s.%s.%s", (char*)translate_id(ob_name).c_str(), + fcu->rna_path, axis_names[fcu->array_index]); + BLI_snprintf(anim_name, sizeof(anim_name), "%s.%s.%s", + (char*)ob_name.c_str(), fcu->rna_path, axis_names[fcu->array_index]); + + // check rna_path is one of: rotation, scale, location + + openAnimation(anim_id, anim_name); + + // create input source + std::string input_id = create_source_from_fcurve(Sampler::INPUT, fcu, anim_id, axis_name); + + // create output source + std::string output_id = create_source_from_fcurve(Sampler::OUTPUT, fcu, anim_id, axis_name); + + // create interpolations source + std::string interpolation_id = create_interpolation_source(fcu->totvert, anim_id, axis_name); + + std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX; + COLLADASW::LibraryAnimations::Sampler sampler(sampler_id); + std::string empty; + sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id)); + sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id)); + + // this input is required + sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); + + addSampler(sampler); + + std::string target = translate_id(ob_name) + + "/" + get_transform_sid(fcu->rna_path, -1, axis_name); + addChannel(COLLADABU::URI(empty, sampler_id), target); + + closeAnimation(); + } + + void write_bone_animation(Object *ob_arm, Bone *bone) + { + if (!ob_arm->adt) + return; + + for (int i = 0; i < 3; i++) + sample_and_write_bone_animation(ob_arm, bone, i); + + for (Bone *child = (Bone*)bone->childbase.first; child; child = child->next) + write_bone_animation(ob_arm, child); + } + + void sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type) + { + bArmature *arm = (bArmature*)ob_arm->data; + int flag = arm->flag; + std::vector<float> fra; + char prefix[256]; + + BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name); + + bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name); + if (!pchan) + return; + + switch (transform_type) { + case 0: + find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode); + break; + case 1: + find_frames(ob_arm, fra, prefix, "scale"); + break; + case 2: + find_frames(ob_arm, fra, prefix, "location"); + break; + default: + return; + } - float convert_time(float frame) { + // exit rest position + if (flag & ARM_RESTPOS) { + arm->flag &= ~ARM_RESTPOS; + where_is_pose(scene, ob_arm); + } + + if (fra.size()) { + float *v = (float*)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames"); + sample_animation(v, fra, transform_type, bone, ob_arm); + + if (transform_type == 0) { + // write x, y, z curves separately if it is rotation + float *c = (float*)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames"); + for (int i = 0; i < 3; i++) { + for (int j = 0; j < fra.size(); j++) + c[j] = v[j * 3 + i]; + + dae_bone_animation(fra, c, transform_type, i, id_name(ob_arm), bone->name); + } + MEM_freeN(c); + } + else { + // write xyz at once if it is location or scale + dae_bone_animation(fra, v, transform_type, -1, id_name(ob_arm), bone->name); + } + + MEM_freeN(v); + } + + // restore restpos + if (flag & ARM_RESTPOS) + arm->flag = flag; + where_is_pose(scene, ob_arm); + } + + void sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm) + { + bPoseChannel *pchan, *parchan = NULL; + bPose *pose = ob_arm->pose; + + pchan = get_pose_channel(pose, bone->name); + + if (!pchan) + return; + + parchan = pchan->parent; + + enable_fcurves(ob_arm->adt->action, bone->name); + + std::vector<float>::iterator it; + for (it = frames.begin(); it != frames.end(); it++) { + float mat[4][4], ipar[4][4]; + + float ctime = bsystem_time(scene, ob_arm, *it, 0.0f); + + BKE_animsys_evaluate_animdata(&ob_arm->id, ob_arm->adt, *it, ADT_RECALC_ANIM); + where_is_pose_bone(scene, ob_arm, pchan, ctime); + + // compute bone local mat + if (bone->parent) { + invert_m4_m4(ipar, parchan->pose_mat); + mul_m4_m4m4(mat, pchan->pose_mat, ipar); + } + else + copy_m4_m4(mat, pchan->pose_mat); + + switch (type) { + case 0: + mat4_to_eul(v, mat); + break; + case 1: + mat4_to_size(v, mat); + break; + case 2: + copy_v3_v3(v, mat[3]); + break; + } + + v += 3; + } + + enable_fcurves(ob_arm->adt->action, NULL); + } + + // dae_bone_animation -> add_bone_animation + // (blend this into dae_bone_animation) + void dae_bone_animation(std::vector<float> &fra, float *v, int tm_type, int axis, std::string ob_name, std::string bone_name) + { + const char *axis_names[] = {"X", "Y", "Z"}; + const char *axis_name = NULL; + char anim_id[200]; + char anim_name[200]; + bool is_rot = tm_type == 0; + + if (!fra.size()) + return; + + char rna_path[200]; + BLI_snprintf(rna_path, sizeof(rna_path), "pose.bones[\"%s\"].%s", bone_name.c_str(), + tm_type == 0 ? "rotation_quaternion" : (tm_type == 1 ? "scale" : "location")); + + if (axis > -1) + axis_name = axis_names[axis]; + + std::string transform_sid = get_transform_sid(NULL, tm_type, axis_name); + + BLI_snprintf(anim_id, sizeof(anim_id), "%s.%s.%s", (char*)translate_id(ob_name).c_str(), + (char*)translate_id(bone_name).c_str(), (char*)transform_sid.c_str()); + BLI_snprintf(anim_name, sizeof(anim_name), "%s.%s.%s", + (char*)ob_name.c_str(), (char*)bone_name.c_str(), (char*)transform_sid.c_str()); + + // TODO check rna_path is one of: rotation, scale, location + + openAnimation(anim_id, anim_name); + + // create input source + std::string input_id = create_source_from_vector(Sampler::INPUT, fra, is_rot, anim_id, axis_name); + + // create output source + std::string output_id; + if (axis == -1) + output_id = create_xyz_source(v, fra.size(), anim_id); + else + output_id = create_source_from_array(Sampler::OUTPUT, v, fra.size(), is_rot, anim_id, axis_name); + + // create interpolations source + std::string interpolation_id = create_interpolation_source(fra.size(), anim_id, axis_name); + + std::string sampler_id = std::string(anim_id) + SAMPLER_ID_SUFFIX; + COLLADASW::LibraryAnimations::Sampler sampler(sampler_id); + std::string empty; + sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id)); + sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id)); + + // TODO create in/out tangents source + + // this input is required + sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); + + addSampler(sampler); + + std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid; + addChannel(COLLADABU::URI(empty, sampler_id), target); + + closeAnimation(); + } + + float convert_time(float frame) + { return FRA2TIME(frame); } - float convert_angle(float angle) { + float convert_angle(float angle) + { return COLLADABU::Math::Utils::radToDegF(angle); } - std::string get_semantic_suffix(Sampler::Semantic semantic) { + std::string get_semantic_suffix(Sampler::Semantic semantic) + { switch(semantic) { case Sampler::INPUT: return INPUT_SOURCE_ID_SUFFIX; @@ -1763,17 +2041,25 @@ public: } void add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param, - Sampler::Semantic semantic, bool rotation, const char *axis) { + Sampler::Semantic semantic, bool is_rot, const char *axis) + { switch(semantic) { case Sampler::INPUT: param.push_back("TIME"); break; case Sampler::OUTPUT: - if (rotation) { + if (is_rot) { param.push_back("ANGLE"); } else { - param.push_back(axis); + if (axis) { + param.push_back(axis); + } + else { + param.push_back("X"); + param.push_back("Y"); + param.push_back("Z"); + } } break; case Sampler::IN_TANGENT: @@ -1808,7 +2094,7 @@ public: } } - std::string create_source(Sampler::Semantic semantic, FCurve *fcu, std::string& anim_id, const char *axis_name) + std::string create_source_from_fcurve(Sampler::Semantic semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name) { std::string source_id = anim_id + get_semantic_suffix(semantic); @@ -1842,26 +2128,28 @@ public: return source_id; } - std::string create_interpolation_source(FCurve *fcu, std::string& anim_id, const char *axis_name) + std::string create_source_from_array(Sampler::Semantic semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name) { - std::string source_id = anim_id + get_semantic_suffix(Sampler::INTERPOLATION); - - //bool is_rotation = !strcmp(fcu->rna_path, "rotation"); + std::string source_id = anim_id + get_semantic_suffix(semantic); - COLLADASW::NameSource source(mSW); + COLLADASW::FloatSourceF source(mSW); source.setId(source_id); source.setArrayId(source_id + ARRAY_ID_SUFFIX); - source.setAccessorCount(fcu->totvert); + source.setAccessorCount(tot); source.setAccessorStride(1); COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); - param.push_back("INTERPOLATION"); + add_source_parameters(param, semantic, is_rot, axis_name); source.prepareToAppendValues(); - for (int i = 0; i < fcu->totvert; i++) { - // XXX - source.appendValues(LINEAR_NAME); + for (int i = 0; i < tot; i++) { + float val = v[i]; + if (semantic == Sampler::INPUT) + val = convert_time(val); + else if (is_rot) + val = convert_angle(val); + source.appendValues(val); } source.finish(); @@ -1869,258 +2157,161 @@ public: return source_id; } - std::string get_transform_sid(char *rna_path, const char *axis_name) + std::string create_source_from_vector(Sampler::Semantic semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name) { - // if (!strcmp(rna_path, "rotation")) -// return std::string(rna_path) + axis_name; - -// return std::string(rna_path) + "." + axis_name; - std::string new_rna_path; - - if (strstr(rna_path, "rotation")) { - new_rna_path = "rotation"; - return new_rna_path + axis_name; - } - else if (strstr(rna_path, "location")) { - new_rna_path = strstr(rna_path, "location"); - return new_rna_path + "." + axis_name; - } - else if (strstr(rna_path, "scale")) { - new_rna_path = strstr(rna_path, "scale"); - return new_rna_path + "." + axis_name; - } - return NULL; - } + std::string source_id = anim_id + get_semantic_suffix(semantic); - void add_animation(FCurve *fcu, std::string ob_name) - { - const char *axis_names[] = {"X", "Y", "Z"}; - const char *axis_name = NULL; - char c_anim_id[100]; // careful! - char c_anim_name[100]; // careful! + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(fra.size()); + source.setAccessorStride(1); - if (fcu->array_index < 3) - axis_name = axis_names[fcu->array_index]; - - BLI_snprintf(c_anim_id, sizeof(c_anim_id), "%s.%s.%s", (char*)translate_id(ob_name).c_str(), - fcu->rna_path, axis_names[fcu->array_index]); - std::string anim_id(c_anim_id); - BLI_snprintf(c_anim_name, sizeof(c_anim_name), "%s.%s.%s", - (char*)ob_name.c_str(), fcu->rna_path, axis_names[fcu->array_index]); - std::string anim_name = c_anim_name; + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + add_source_parameters(param, semantic, is_rot, axis_name); - // check rna_path is one of: rotation, scale, location + source.prepareToAppendValues(); - openAnimation(anim_id, anim_name); + std::vector<float>::iterator it; + for (it = fra.begin(); it != fra.end(); it++) { + float val = *it; + if (semantic == Sampler::INPUT) + val = convert_time(val); + else if (is_rot) + val = convert_angle(val); + source.appendValues(val); + } - // create input source - std::string input_id = create_source(Sampler::INPUT, fcu, anim_id, axis_name); + source.finish(); - // create output source - std::string output_id = create_source(Sampler::OUTPUT, fcu, anim_id, axis_name); + return source_id; + } - // create interpolations source - std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name); + // only used for sources with OUTPUT semantic + std::string create_xyz_source(float *v, int tot, const std::string& anim_id) + { + Sampler::Semantic semantic = Sampler::OUTPUT; + std::string source_id = anim_id + get_semantic_suffix(semantic); - std::string sampler_id = anim_id + SAMPLER_ID_SUFFIX; - COLLADASW::LibraryAnimations::Sampler sampler(sampler_id); - std::string empty; - sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id)); - sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id)); + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(tot); + source.setAccessorStride(3); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + add_source_parameters(param, semantic, false, NULL); - // this input is required - sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); + source.prepareToAppendValues(); - addSampler(sampler); + for (int i = 0; i < tot; i++) { + source.appendValues(*v, *(v + 1), *(v + 2)); + v += 3; + } - std::string target = translate_id(ob_name) - + "/" + get_transform_sid(fcu->rna_path, axis_name); - addChannel(COLLADABU::URI(empty, sampler_id), target); + source.finish(); - closeAnimation(); + return source_id; } - - void add_bone_animation(FCurve *fcu, std::string ob_name, std::string bone_name) + + std::string create_interpolation_source(int tot, const std::string& anim_id, const char *axis_name) { - const char *axis_names[] = {"X", "Y", "Z"}; - const char *axis_name = NULL; - char c_anim_id[100]; // careful! - char c_anim_name[100]; // careful! + std::string source_id = anim_id + get_semantic_suffix(Sampler::INTERPOLATION); - if (fcu->array_index < 3) - axis_name = axis_names[fcu->array_index]; - - std::string transform_sid = get_transform_sid(fcu->rna_path, axis_name); + COLLADASW::NameSource source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(tot); + source.setAccessorStride(1); - BLI_snprintf(c_anim_id, sizeof(c_anim_id), "%s.%s.%s", (char*)translate_id(ob_name).c_str(), - (char*)translate_id(bone_name).c_str(), (char*)transform_sid.c_str()); - std::string anim_id(c_anim_id); - BLI_snprintf(c_anim_name, sizeof(c_anim_name), "%s.%s.%s", - (char*)ob_name.c_str(), (char*)bone_name.c_str(), (char*)transform_sid.c_str()); - std::string anim_name(c_anim_name); - - // check rna_path is one of: rotation, scale, location - - openAnimation(anim_id, anim_name); - - // create input source - std::string input_id = create_source(Sampler::INPUT, fcu, anim_id, axis_name); + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + param.push_back("INTERPOLATION"); - // create output source - std::string output_id = create_source(Sampler::OUTPUT, fcu, anim_id, axis_name); + source.prepareToAppendValues(); - // create interpolations source - std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name); + for (int i = 0; i < tot; i++) { + source.appendValues(LINEAR_NAME); + } - std::string sampler_id = anim_id + SAMPLER_ID_SUFFIX; - COLLADASW::LibraryAnimations::Sampler sampler(sampler_id); - std::string empty; - sampler.addInput(Sampler::INPUT, COLLADABU::URI(empty, input_id)); - sampler.addInput(Sampler::OUTPUT, COLLADABU::URI(empty, output_id)); + source.finish(); - // this input is required - sampler.addInput(Sampler::INTERPOLATION, COLLADABU::URI(empty, interpolation_id)); + return source_id; + } - addSampler(sampler); + std::string get_transform_sid(char *rna_path, int tm_type, const char *axis_name) + { + if (rna_path) { + char *name = extract_transform_name(rna_path); - std::string target = translate_id(ob_name + "_" + bone_name) + "/" + transform_sid; - addChannel(COLLADABU::URI(empty, sampler_id), target); + if (strstr(name, "rotation")) + return std::string("rotation") + axis_name; + else if (!strcmp(name, "location") || !strcmp(name, "scale")) + return std::string(name); + } + else { + if (tm_type == 0) + return std::string("rotation") + axis_name; + else + return tm_type == 1 ? "scale" : "location"; + } - closeAnimation(); + return NULL; } - - FCurve *create_fcurve(int array_index, char *rna_path) + + char *extract_transform_name(char *rna_path) { - FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve"); - - fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED); - fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path)); - fcu->array_index = array_index; - return fcu; - } - - void create_bezt(FCurve *fcu, float frame, float output) - { - BezTriple bez; - memset(&bez, 0, sizeof(BezTriple)); - bez.vec[1][0] = frame; - bez.vec[1][1] = output; - bez.ipo = U.ipo_new; /* use default interpolation mode here... */ - bez.f1 = bez.f2 = bez.f3 = SELECT; - bez.h1 = bez.h2 = HD_AUTO; - insert_bezt_fcurve(fcu, &bez, 0); - calchandles_fcurve(fcu); + char *dot = strrchr(rna_path, '.'); + return dot ? (dot + 1) : rna_path; } - - void change_quat_to_eul(Object *ob, bActionGroup *grp, char *grpname) + + void find_frames(Object *ob, std::vector<float> &fra, const char *prefix, const char *tm_name) { - std::vector<FCurve*> &rot_fcurves = rotfcurves_actionGroup_map[grp]; - - FCurve *quatcu[4] = {NULL, NULL, NULL, NULL}; - int i; - - for (i = 0; i < rot_fcurves.size(); i++) - quatcu[rot_fcurves[i]->array_index] = rot_fcurves[i]; - - char *rna_path = rot_fcurves[0]->rna_path; - - FCurve *eulcu[3] = { - create_fcurve(0, rna_path), - create_fcurve(1, rna_path), - create_fcurve(2, rna_path) - }; - - for (i = 0; i < 4; i++) { - - FCurve *cu = quatcu[i]; - - if (!cu) continue; - - for (int j = 0; j < cu->totvert; j++) { - float frame = cu->bezt[j].vec[1][0]; - - float quat[4] = { - quatcu[0] ? evaluate_fcurve(quatcu[0], frame) : 0.0f, - quatcu[1] ? evaluate_fcurve(quatcu[1], frame) : 0.0f, - quatcu[2] ? evaluate_fcurve(quatcu[2], frame) : 0.0f, - quatcu[3] ? evaluate_fcurve(quatcu[3], frame) : 0.0f - }; - - float eul[3]; - - quat_to_eul( eul,quat); - - for (int k = 0; k < 3; k++) - create_bezt(eulcu[k], frame, eul[k]); + FCurve *fcu= (FCurve*)ob->adt->action->curves.first; + + for (; fcu; fcu = fcu->next) { + if (prefix && strncmp(prefix, fcu->rna_path, strlen(prefix))) + continue; + + char *name = extract_transform_name(fcu->rna_path); + if (!strcmp(name, tm_name)) { + for (int i = 0; i < fcu->totvert; i++) { + float f = fcu->bezt[i].vec[1][0]; + if (std::find(fra.begin(), fra.end(), f) == fra.end()) + fra.push_back(f); + } } } - - for (i = 0; i < 3; i++) { - add_bone_animation(eulcu[i], id_name(ob), std::string(grpname)); - free_fcurve(eulcu[i]); - } } - // called for each exported object - void operator() (Object *ob) + void find_rotation_frames(Object *ob, std::vector<float> &fra, const char *prefix, int rotmode) { - if (!ob->adt || !ob->adt->action) return; - - FCurve *fcu = (FCurve*)ob->adt->action->curves.first; - - if (ob->type == OB_ARMATURE) { - - while (fcu) { - - if (strstr(fcu->rna_path, ".rotation")) - rotfcurves_actionGroup_map[fcu->grp].push_back(fcu); - else fcurves_actionGroup_map[fcu->grp].push_back(fcu); - - fcu = fcu->next; - } - - for (bPoseChannel *pchan = (bPoseChannel*)ob->pose->chanbase.first; pchan; pchan = pchan->next) { - int i; - char *grpname = pchan->name; - bActionGroup *grp = action_groups_find_named(ob->adt->action, grpname); - - if (!grp) continue; - - // write animation for location & scaling - if (fcurves_actionGroup_map.find(grp) == fcurves_actionGroup_map.end()) continue; - - std::vector<FCurve*> &fcurves = fcurves_actionGroup_map[grp]; - for (i = 0; i < fcurves.size(); i++) - add_bone_animation(fcurves[i], id_name(ob), std::string(grpname)); - - // ... for rotation - if (rotfcurves_actionGroup_map.find(grp) == rotfcurves_actionGroup_map.end()) - continue; - - // if rotation mode is euler - no need to convert it - if (pchan->rotmode == ROT_MODE_EUL) { - - std::vector<FCurve*> &rotfcurves = rotfcurves_actionGroup_map[grp]; - - for (i = 0; i < rotfcurves.size(); i++) - add_bone_animation(rotfcurves[i], id_name(ob), std::string(grpname)); - } - - // convert rotation to euler & write animation - else change_quat_to_eul(ob, grp, grpname); + if (rotmode > 0) + find_frames(ob, fra, prefix, "rotation_euler"); + else if (rotmode == ROT_MODE_QUAT) + find_frames(ob, fra, prefix, "rotation_quaternion"); + else if (rotmode == ROT_MODE_AXISANGLE) + ; + } + + // enable fcurves driving a specific bone, disable all the rest + // if bone_name = NULL enable all fcurves + void enable_fcurves(bAction *act, char *bone_name) + { + FCurve *fcu; + char prefix[200]; + + if (bone_name) + BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone_name); + + for (fcu = (FCurve*)act->curves.first; fcu; fcu = fcu->next) { + if (bone_name) { + if (!strncmp(fcu->rna_path, prefix, strlen(prefix))) + fcu->flag &= ~FCURVE_DISABLED; + else + fcu->flag |= FCURVE_DISABLED; } - } - else { - while (fcu) { - - if (!strcmp(fcu->rna_path, "location") || - !strcmp(fcu->rna_path, "scale") || - !strcmp(fcu->rna_path, "rotation_euler")) { - - add_animation(fcu, id_name(ob)); - } - - fcu = fcu->next; + else { + fcu->flag &= ~FCURVE_DISABLED; } } } @@ -2192,3 +2383,12 @@ void DocumentExporter::exportCurrentScene(Scene *sce, const char* filename) void DocumentExporter::exportScenes(const char* filename) { } + +/* + +NOTES: + +* AnimationExporter::sample_animation enables all curves on armature, this is undesirable for a user + + */ + diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 575160ff84e..26e95c378a6 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -43,6 +43,8 @@ extern "C" #include "ED_armature.h" #include "ED_mesh.h" // ED_vgroup_vert_add, ... #include "ED_anim_api.h" +#include "ED_object.h" + #include "WM_types.h" #include "WM_api.h" @@ -82,6 +84,7 @@ extern "C" #include "DNA_mesh_types.h" #include "DNA_material_types.h" #include "DNA_scene_types.h" +#include "DNA_modifier_types.h" #include "MEM_guardedalloc.h" @@ -497,20 +500,24 @@ private: void link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& joint_by_uid, TransformReader *tm) { + Object workob; + Scene *scene = CTX_data_scene(C); + + ModifierData *md = ED_object_modifier_add(NULL, scene, ob, NULL, eModifierType_Armature); + ((ArmatureModifierData *)md)->object = ob_arm; + tm->decompose(bind_shape_matrix, ob->loc, ob->rot, NULL, ob->size); ob->parent = ob_arm; - ob->partype = PARSKEL; + ob->partype = PAROBJECT; + + what_does_parent(scene, ob, &workob); + invert_m4_m4(ob->parentinv, workob.obmat); + ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA; ((bArmature*)ob_arm->data)->deformflag = ARM_DEF_VGROUP; - // we need armature matrix here... where do we get it from I wonder... - // root node/joint? or node with <instance_controller>? - float parmat[4][4]; - unit_m4(parmat); - invert_m4_m4(ob->parentinv, parmat); - // create all vertex groups std::vector<JointData>::iterator it; int joint_index; @@ -551,7 +558,7 @@ private: } } - DAG_scene_sort(CTX_data_scene(C)); + DAG_scene_sort(scene); DAG_ids_flush_update(0); WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); } @@ -624,6 +631,9 @@ private: 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; @@ -2430,7 +2440,7 @@ public: Bone *bone = get_named_bone((bArmature*)ob->data, bone_name); if (!bone) { - fprintf(stderr, "cannot find bone \"%s\"", bone_name); + fprintf(stderr, "cannot find bone \"%s\"\n", bone_name); #ifdef ARMATURE_TEST return NULL; #else @@ -2773,9 +2783,14 @@ public: // use bind matrix if available or calc "current" world mat if (!armature_importer->get_joint_bind_mat(m, node)) { - float temp[4][4]; - get_node_mat(temp, node, NULL, NULL); - mul_m4_m4m4(m, temp, par); + if (par) { + float temp[4][4]; + get_node_mat(temp, node, NULL, NULL); + mul_m4_m4m4(m, temp, par); + } + else { + get_node_mat(m, node, NULL, NULL); + } } COLLADAFW::NodePointerArray& children = node->getChildNodes(); |