Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArystanbek Dyussenov <arystan.d@gmail.com>2010-01-05 20:42:01 +0300
committerArystanbek Dyussenov <arystan.d@gmail.com>2010-01-05 20:42:01 +0300
commit0a0d43a926c487ea01761e6e4a98af811fc3c619 (patch)
tree70b0033bafedaeeb0591f1b199c870df7f77a60b /source/blender/collada
parent73f84b24fca541caa4aaec02d946b887ddfb216b (diff)
parent06d548bd6fdb9d3e4fc99ecf3b26617648e6b73c (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.cpp686
-rw-r--r--source/blender/collada/DocumentImporter.cpp39
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 &param = 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 &param = 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 &param = 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 &param = 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();