2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory, Sukhitha Jayathilake.
20 * ***** END GPL LICENSE BLOCK *****
23 /** \file blender/collada/AnimationImporter.cpp
29 /* COLLADABU_ASSERT, may be able to remove later */
30 #include "COLLADABUPlatform.h"
32 #include "DNA_armature_types.h"
34 #include "ED_keyframing.h"
36 #include "BLI_listbase.h"
38 #include "BLI_string.h"
39 #include "BLI_string_utils.h"
41 #include "BLT_translation.h"
43 #include "BKE_action.h"
44 #include "BKE_armature.h"
45 #include "BKE_fcurve.h"
46 #include "BKE_object.h"
48 #include "MEM_guardedalloc.h"
50 #include "collada_utils.h"
51 #include "AnimationImporter.h"
52 #include "ArmatureImporter.h"
53 #include "MaterialExporter.h"
57 // first try node name, if not available (since is optional), fall back to original id
59 static const char *bc_get_joint_name(T *node)
61 const std::string& id = node->getName();
62 return id.size() ? id.c_str() : node->getOriginalId().c_str();
65 FCurve *AnimationImporter::create_fcurve(int array_index, const char *rna_path)
67 FCurve *fcu = (FCurve *)MEM_callocN(sizeof(FCurve), "FCurve");
68 fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED);
69 fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
70 fcu->array_index = array_index;
74 void AnimationImporter::create_bezt(FCurve *fcu, float frame, float output)
77 memset(&bez, 0, sizeof(BezTriple));
78 bez.vec[1][0] = frame;
79 bez.vec[1][1] = output;
80 bez.ipo = U.ipo_new; /* use default interpolation mode here... */
81 bez.f1 = bez.f2 = bez.f3 = SELECT;
82 bez.h1 = bez.h2 = HD_AUTO;
83 insert_bezt_fcurve(fcu, &bez, 0);
84 calchandles_fcurve(fcu);
87 // create one or several fcurves depending on the number of parameters being animated
88 void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
90 COLLADAFW::FloatOrDoubleArray& input = curve->getInputValues();
91 COLLADAFW::FloatOrDoubleArray& output = curve->getOutputValues();
93 float fps = (float)FPS;
94 size_t dim = curve->getOutDimension();
97 std::vector<FCurve *>& fcurves = curve_map[curve->getUniqueId()];
100 case 1: // X, Y, Z or angle
105 for (i = 0; i < dim; i++) {
106 FCurve *fcu = (FCurve *)MEM_callocN(sizeof(FCurve), "FCurve");
108 fcu->flag = (FCURVE_VISIBLE | FCURVE_AUTO_HANDLES | FCURVE_SELECTED);
109 // fcu->rna_path = BLI_strdupn(path, strlen(path));
110 fcu->array_index = 0;
111 fcu->totvert = curve->getKeyCount();
113 // create beztriple for each key
114 for (unsigned int j = 0; j < curve->getKeyCount(); j++) {
116 memset(&bez, 0, sizeof(BezTriple));
120 bez.vec[1][0] = bc_get_float_value(input, j) * fps;
121 bez.vec[1][1] = bc_get_float_value(output, j * dim + i);
124 if (curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER ||
125 curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_STEP)
127 COLLADAFW::FloatOrDoubleArray& intan = curve->getInTangentValues();
128 COLLADAFW::FloatOrDoubleArray& outtan = curve->getOutTangentValues();
131 bez.vec[0][0] = bc_get_float_value(intan, (j * 2 * dim) + (2 * i)) * fps;
132 bez.vec[0][1] = bc_get_float_value(intan, (j * 2 * dim) + (2 * i) + 1);
135 bez.vec[2][0] = bc_get_float_value(outtan, (j * 2 * dim) + (2 * i)) * fps;
136 bez.vec[2][1] = bc_get_float_value(outtan, (j * 2 * dim) + (2 * i) + 1);
137 if (curve->getInterpolationType() == COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER)
138 bez.ipo = BEZT_IPO_BEZ;
140 bez.ipo = BEZT_IPO_CONST;
141 //bez.h1 = bez.h2 = HD_AUTO;
144 bez.h1 = bez.h2 = HD_AUTO;
145 bez.ipo = BEZT_IPO_LIN;
147 // bez.ipo = U.ipo_new; /* use default interpolation mode here... */
148 bez.f1 = bez.f2 = bez.f3 = SELECT;
150 insert_bezt_fcurve(fcu, &bez, 0);
153 calchandles_fcurve(fcu);
155 fcurves.push_back(fcu);
156 unused_curves.push_back(fcu);
161 fprintf(stderr, "Output dimension of %d is not yet supported (animation id = %s)\n", (int)dim, curve->getOriginalId().c_str());
166 void AnimationImporter::fcurve_deg_to_rad(FCurve *cu)
168 for (unsigned int i = 0; i < cu->totvert; i++) {
169 // TODO convert handles too
170 cu->bezt[i].vec[1][1] *= DEG2RADF(1.0f);
171 cu->bezt[i].vec[0][1] *= DEG2RADF(1.0f);
172 cu->bezt[i].vec[2][1] *= DEG2RADF(1.0f);
176 void AnimationImporter::fcurve_is_used(FCurve *fcu)
178 unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end());
182 void AnimationImporter::add_fcurves_to_object(Object *ob, std::vector<FCurve *>& curves, char *rna_path, int array_index, Animation *animated)
186 if (!ob->adt || !ob->adt->action) act = verify_adt_action((ID *)&ob->id, 1);
187 else act = ob->adt->action;
189 std::vector<FCurve *>::iterator it;
193 char *p = strstr(rna_path, "rotation_euler");
194 bool is_rotation = p && *(p + strlen("rotation_euler")) == '\0';
196 // convert degrees to radians for rotation
198 fcurve_deg_to_rad(fcu);
201 for (it = curves.begin(), i = 0; it != curves.end(); it++, i++) {
203 fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path));
205 if (array_index == -1) fcu->array_index = i;
206 else fcu->array_index = array_index;
208 if (ob->type == OB_ARMATURE) {
209 bActionGroup *grp = NULL;
210 const char *bone_name = bc_get_joint_name(animated->node);
213 /* try to find group */
214 grp = BKE_action_group_find_name(act, bone_name);
216 /* no matching groups, so add one */
218 /* Add a new group, and make it active */
219 grp = (bActionGroup *)MEM_callocN(sizeof(bActionGroup), "bActionGroup");
221 grp->flag = AGRP_SELECTED;
222 BLI_strncpy(grp->name, bone_name, sizeof(grp->name));
224 BLI_addtail(&act->groups, grp);
225 BLI_uniquename(&act->groups, grp, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "Group"), '.',
226 offsetof(bActionGroup, name), 64);
229 /* add F-Curve to group */
230 action_groups_add_channel(act, grp, fcu);
236 fcurves_actionGroup_map[grp].push_back(fcu);
241 BLI_addtail(&act->curves, fcu);
247 AnimationImporter::AnimationImporter(UnitConverter *conv, ArmatureImporter *arm, Scene *scene) :
248 TransformReader(conv), armature_importer(arm), scene(scene) {
251 AnimationImporter::~AnimationImporter()
253 // free unused FCurves
254 for (std::vector<FCurve *>::iterator it = unused_curves.begin(); it != unused_curves.end(); it++)
257 if (unused_curves.size())
258 fprintf(stderr, "removed %d unused curves\n", (int)unused_curves.size());
261 bool AnimationImporter::write_animation(const COLLADAFW::Animation *anim)
263 if (anim->getAnimationType() == COLLADAFW::Animation::ANIMATION_CURVE) {
264 COLLADAFW::AnimationCurve *curve = (COLLADAFW::AnimationCurve *)anim;
266 // XXX Don't know if it's necessary
267 // Should we check outPhysicalDimension?
268 if (curve->getInPhysicalDimension() != COLLADAFW::PHYSICAL_DIMENSION_TIME) {
269 fprintf(stderr, "Inputs physical dimension is not time.\n");
273 // a curve can have mixed interpolation type,
274 // in this case curve->getInterpolationTypes returns a list of interpolation types per key
275 COLLADAFW::AnimationCurve::InterpolationType interp = curve->getInterpolationType();
277 if (interp != COLLADAFW::AnimationCurve::INTERPOLATION_MIXED) {
279 case COLLADAFW::AnimationCurve::INTERPOLATION_LINEAR:
280 case COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER:
281 case COLLADAFW::AnimationCurve::INTERPOLATION_STEP:
282 animation_to_fcurves(curve);
285 // TODO there're also CARDINAL, HERMITE, BSPLINE and STEP types
286 fprintf(stderr, "CARDINAL, HERMITE and BSPLINE anim interpolation types not supported yet.\n");
292 fprintf(stderr, "MIXED anim interpolation type is not supported yet.\n");
296 fprintf(stderr, "FORMULA animation type is not supported yet.\n");
302 // called on post-process stage after writeVisualScenes
303 bool AnimationImporter::write_animation_list(const COLLADAFW::AnimationList *animlist)
305 const COLLADAFW::UniqueId& animlist_id = animlist->getUniqueId();
307 animlist_map[animlist_id] = animlist;
312 if (uid_animated_map.find(animlist_id) == uid_animated_map.end()) {
316 // for bones rna_path is like: pose.bones["bone-name"].rotation
324 // \todo refactor read_node_transform to not automatically apply anything,
325 // but rather return the transform matrix, so caller can do with it what is
326 // necessary. Same for \ref get_node_mat
327 void AnimationImporter::read_node_transform(COLLADAFW::Node *node, Object *ob)
330 TransformReader::get_node_mat(mat, node, &uid_animated_map, ob);
332 copy_m4_m4(ob->obmat, mat);
333 BKE_object_apply_mat4(ob, ob->obmat, 0, 0);
338 virtual void AnimationImporter::change_eul_to_quat(Object *ob, bAction *act)
343 for (grp = (bActionGroup *)act->groups.first; grp; grp = grp->next) {
345 FCurve *eulcu[3] = {NULL, NULL, NULL};
347 if (fcurves_actionGroup_map.find(grp) == fcurves_actionGroup_map.end())
350 std::vector<FCurve *> &rot_fcurves = fcurves_actionGroup_map[grp];
352 if (rot_fcurves.size() > 3) continue;
354 for (i = 0; i < rot_fcurves.size(); i++)
355 eulcu[rot_fcurves[i]->array_index] = rot_fcurves[i];
357 char joint_path[100];
360 BLI_snprintf(joint_path, sizeof(joint_path), "pose.bones[\"%s\"]", grp->name);
361 BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_quaternion", joint_path);
363 FCurve *quatcu[4] = {
364 create_fcurve(0, rna_path),
365 create_fcurve(1, rna_path),
366 create_fcurve(2, rna_path),
367 create_fcurve(3, rna_path)
370 bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, grp->name);
372 float m4[4][4], irest[3][3];
373 invert_m4_m4(m4, chan->bone->arm_mat);
374 copy_m3_m4(irest, m4);
376 for (i = 0; i < 3; i++) {
378 FCurve *cu = eulcu[i];
382 for (int j = 0; j < cu->totvert; j++) {
383 float frame = cu->bezt[j].vec[1][0];
386 eulcu[0] ? evaluate_fcurve(eulcu[0], frame) : 0.0f,
387 eulcu[1] ? evaluate_fcurve(eulcu[1], frame) : 0.0f,
388 eulcu[2] ? evaluate_fcurve(eulcu[2], frame) : 0.0f
391 // make eul relative to bone rest pose
392 float rot[3][3], rel[3][3], quat[4];
394 /*eul_to_mat3(rot, eul);
396 mul_m3_m3m3(rel, irest, rot);
398 mat3_to_quat(quat, rel);
401 eul_to_quat(quat, eul);
403 for (int k = 0; k < 4; k++)
404 create_bezt(quatcu[k], frame, quat[k]);
408 // now replace old Euler curves
410 for (i = 0; i < 3; i++) {
411 if (!eulcu[i]) continue;
413 action_groups_remove_channel(act, eulcu[i]);
414 free_fcurve(eulcu[i]);
417 chan->rotmode = ROT_MODE_QUAT;
419 for (i = 0; i < 4; i++)
420 action_groups_add_channel(act, grp, quatcu[i]);
424 for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = pchan->next) {
425 pchan->rotmode = ROT_MODE_QUAT;
431 //sets the rna_path and array index to curve
432 void AnimationImporter::modify_fcurve(std::vector<FCurve *> *curves, const char *rna_path, int array_index)
434 std::vector<FCurve *>::iterator it;
436 for (it = curves->begin(), i = 0; it != curves->end(); it++, i++) {
438 fcu->rna_path = BLI_strdup(rna_path);
440 if (array_index == -1) fcu->array_index = i;
441 else fcu->array_index = array_index;
447 void AnimationImporter::unused_fcurve(std::vector<FCurve *> *curves)
449 // when an error happens and we can't actually use curve remove it from unused_curves
450 std::vector<FCurve *>::iterator it;
451 for (it = curves->begin(); it != curves->end(); it++) {
457 void AnimationImporter::find_frames(std::vector<float> *frames, std::vector<FCurve *> *curves)
459 std::vector<FCurve *>::iterator iter;
460 for (iter = curves->begin(); iter != curves->end(); iter++) {
463 for (unsigned int k = 0; k < fcu->totvert; k++) {
464 //get frame value from bezTriple
465 float fra = fcu->bezt[k].vec[1][0];
466 //if frame already not added add frame to frames
467 if (std::find(frames->begin(), frames->end(), fra) == frames->end())
468 frames->push_back(fra);
474 //creates the rna_paths and array indices of fcurves from animations using transformation and bound animation class of each animation.
475 void AnimationImporter:: Assign_transform_animations(COLLADAFW::Transformation *transform,
476 const COLLADAFW::AnimationList::AnimationBinding *binding,
477 std::vector<FCurve *> *curves, bool is_joint, char *joint_path)
479 COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType();
480 bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
481 bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
483 //to check if the no of curves are valid
484 bool xyz = ((tm_type == COLLADAFW::Transformation::TRANSLATE || tm_type == COLLADAFW::Transformation::SCALE) && binding->animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
487 if (!((!xyz && curves->size() == 1) || (xyz && curves->size() == 3) || is_matrix)) {
488 fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves->size());
495 case COLLADAFW::Transformation::TRANSLATE:
496 case COLLADAFW::Transformation::SCALE:
498 bool loc = tm_type == COLLADAFW::Transformation::TRANSLATE;
500 BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, loc ? "location" : "scale");
502 BLI_strncpy(rna_path, loc ? "location" : "scale", sizeof(rna_path));
504 switch (binding->animationClass) {
505 case COLLADAFW::AnimationList::POSITION_X:
506 modify_fcurve(curves, rna_path, 0);
508 case COLLADAFW::AnimationList::POSITION_Y:
509 modify_fcurve(curves, rna_path, 1);
511 case COLLADAFW::AnimationList::POSITION_Z:
512 modify_fcurve(curves, rna_path, 2);
514 case COLLADAFW::AnimationList::POSITION_XYZ:
515 modify_fcurve(curves, rna_path, -1);
518 unused_fcurve(curves);
519 fprintf(stderr, "AnimationClass %d is not supported for %s.\n",
520 binding->animationClass, loc ? "TRANSLATE" : "SCALE");
526 case COLLADAFW::Transformation::ROTATE:
529 BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_euler", joint_path);
531 BLI_strncpy(rna_path, "rotation_euler", sizeof(rna_path));
532 std::vector<FCurve *>::iterator iter;
533 for (iter = curves->begin(); iter != curves->end(); iter++) {
536 //if transform is rotation the fcurves values must be turned in to radian.
538 fcurve_deg_to_rad(fcu);
540 COLLADAFW::Rotate *rot = (COLLADAFW::Rotate *)transform;
541 COLLADABU::Math::Vector3& axis = rot->getRotationAxis();
543 switch (binding->animationClass) {
544 case COLLADAFW::AnimationList::ANGLE:
545 if (COLLADABU::Math::Vector3::UNIT_X == axis) {
546 modify_fcurve(curves, rna_path, 0);
548 else if (COLLADABU::Math::Vector3::UNIT_Y == axis) {
549 modify_fcurve(curves, rna_path, 1);
551 else if (COLLADABU::Math::Vector3::UNIT_Z == axis) {
552 modify_fcurve(curves, rna_path, 2);
555 unused_fcurve(curves);
557 case COLLADAFW::AnimationList::AXISANGLE:
558 // TODO convert axis-angle to quat? or XYZ?
560 unused_fcurve(curves);
561 fprintf(stderr, "AnimationClass %d is not supported for ROTATE transformation.\n",
562 binding->animationClass);
567 case COLLADAFW::Transformation::MATRIX:
569 COLLADAFW::Matrix *mat = (COLLADAFW::Matrix*)transform;
570 COLLADABU::Math::Matrix4 mat4 = mat->getMatrix();
571 switch (binding->animationClass) {
572 case COLLADAFW::AnimationList::TRANSFORM:
576 unused_fcurve(curves);
578 case COLLADAFW::Transformation::SKEW:
579 case COLLADAFW::Transformation::LOOKAT:
580 unused_fcurve(curves);
581 fprintf(stderr, "Animation of SKEW and LOOKAT transformations is not supported yet.\n");
587 //creates the rna_paths and array indices of fcurves from animations using color and bound animation class of each animation.
588 void AnimationImporter:: Assign_color_animations(const COLLADAFW::UniqueId& listid, ListBase *AnimCurves, const char *anim_type)
591 BLI_strncpy(rna_path, anim_type, sizeof(rna_path));
593 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
594 const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
595 //all the curves belonging to the current binding
596 std::vector<FCurve *> animcurves;
597 for (unsigned int j = 0; j < bindings.getCount(); j++) {
598 animcurves = curve_map[bindings[j].animation];
600 switch (bindings[j].animationClass) {
601 case COLLADAFW::AnimationList::COLOR_R:
602 modify_fcurve(&animcurves, rna_path, 0);
604 case COLLADAFW::AnimationList::COLOR_G:
605 modify_fcurve(&animcurves, rna_path, 1);
607 case COLLADAFW::AnimationList::COLOR_B:
608 modify_fcurve(&animcurves, rna_path, 2);
610 case COLLADAFW::AnimationList::COLOR_RGB:
611 case COLLADAFW::AnimationList::COLOR_RGBA: // to do-> set intensity
612 modify_fcurve(&animcurves, rna_path, -1);
616 unused_fcurve(&animcurves);
617 fprintf(stderr, "AnimationClass %d is not supported for %s.\n",
618 bindings[j].animationClass, "COLOR");
621 std::vector<FCurve *>::iterator iter;
622 //Add the curves of the current animation to the object
623 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
625 BLI_addtail(AnimCurves, fcu);
631 void AnimationImporter:: Assign_float_animations(const COLLADAFW::UniqueId& listid, ListBase *AnimCurves, const char *anim_type)
634 if (animlist_map.find(listid) == animlist_map.end()) {
638 //anim_type has animations
639 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
640 const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
641 //all the curves belonging to the current binding
642 std::vector<FCurve *> animcurves;
643 for (unsigned int j = 0; j < bindings.getCount(); j++) {
644 animcurves = curve_map[bindings[j].animation];
646 BLI_strncpy(rna_path, anim_type, sizeof(rna_path));
647 modify_fcurve(&animcurves, rna_path, 0);
648 std::vector<FCurve *>::iterator iter;
649 //Add the curves of the current animation to the object
650 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
652 /* All anim_types whose values are to be converted from Degree to Radians can be ORed here */
653 if (STREQ("spot_size", anim_type)) {
654 /* NOTE: Do NOT convert if imported file was made by blender <= 2.69.10
655 * Reason: old blender versions stored spot_size in radians (was a bug)
657 if (this->import_from_version == "" || BLI_natstrcmp(this->import_from_version.c_str(), "2.69.10") != -1) {
658 fcurve_deg_to_rad(fcu);
661 /** XXX What About animtype "rotation" ? */
663 BLI_addtail(AnimCurves, fcu);
672 * Lens animations must be stored in COLLADA by using FOV,
673 * while blender internally uses focal length.
674 * The imported animation curves must be converted appropriately.
676 void AnimationImporter::Assign_lens_animations(const COLLADAFW::UniqueId& listid, ListBase *AnimCurves, const double aspect, Camera *cam, const char *anim_type, int fov_type)
679 if (animlist_map.find(listid) == animlist_map.end()) {
683 //anim_type has animations
684 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
685 const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
686 //all the curves belonging to the current binding
687 std::vector<FCurve *> animcurves;
688 for (unsigned int j = 0; j < bindings.getCount(); j++) {
689 animcurves = curve_map[bindings[j].animation];
691 BLI_strncpy(rna_path, anim_type, sizeof(rna_path));
693 modify_fcurve(&animcurves, rna_path, 0);
694 std::vector<FCurve *>::iterator iter;
695 //Add the curves of the current animation to the object
696 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
699 for (unsigned int i = 0; i < fcu->totvert; i++) {
701 double input_fov = fcu->bezt[i].vec[1][1];
703 // NOTE: Needs more testing (As we curretnly have no official test data for this)
704 double xfov = (fov_type == CAMERA_YFOV) ? (2.0f * atanf(aspect * tanf(DEG2RADF(input_fov) * 0.5f))) : DEG2RADF(input_fov);
706 fcu->bezt[i].vec[1][1] = fov_to_focallength(xfov, cam->sensor_x);
709 BLI_addtail(AnimCurves, fcu);
716 void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& animcurves, COLLADAFW::Node *root, COLLADAFW::Node *node,
717 COLLADAFW::Transformation *tm)
719 bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
720 const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL;
721 char joint_path[200];
723 armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
725 std::vector<float> frames;
726 find_frames(&frames, &animcurves);
728 float irest_dae[4][4];
729 float rest[4][4], irest[4][4];
732 get_joint_rest_mat(irest_dae, root, node);
733 invert_m4(irest_dae);
735 Bone *bone = BKE_armature_find_bone_name((bArmature *)ob->data, bone_name);
737 fprintf(stderr, "cannot find bone \"%s\"\n", bone_name);
742 copy_m4_m4(rest, bone->arm_mat);
743 invert_m4_m4(irest, rest);
745 // new curves to assign matrix transform animation
746 FCurve *newcu[10]; // if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale
747 unsigned int totcu = 10;
748 const char *tm_str = NULL;
750 for (int i = 0; i < totcu; i++) {
755 tm_str = "rotation_quaternion";
768 BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str);
770 BLI_strncpy(rna_path, tm_str, sizeof(rna_path));
771 newcu[i] = create_fcurve(axis, rna_path);
772 newcu[i]->totvert = frames.size();
775 if (frames.size() == 0)
778 std::sort(frames.begin(), frames.end());
780 std::vector<float>::iterator it;
785 // sample values at each frame
786 for (it = frames.begin(); it != frames.end(); it++) {
794 // calc object-space mat
795 evaluate_transform_at_frame(matfra, node, fra);
798 // for joints, we need a special matrix
800 // special matrix: iR * M * iR_dae * R
801 // where R, iR are bone rest and inverse rest mats in world space (Blender bones),
802 // iR_dae is joint inverse rest matrix (DAE) and M is an evaluated joint world-space matrix (DAE)
803 float temp[4][4], par[4][4];
806 calc_joint_parent_mat_rest(par, NULL, root, node);
807 mul_m4_m4m4(temp, par, matfra);
809 // evaluate_joint_world_transform_at_frame(temp, NULL, node, fra);
811 // calc special matrix
812 mul_m4_series(mat, irest, temp, irest_dae, rest);
815 copy_m4_m4(mat, matfra);
818 float rot[4], loc[3], scale[3];
819 mat4_decompose(loc, rot, scale, mat);
822 for (int i = 0; i < totcu; i++) {
824 add_bezt(newcu[i], fra, rot[i]);
826 add_bezt(newcu[i], fra, loc[i - 4]);
828 add_bezt(newcu[i], fra, scale[i - 7]);
831 verify_adt_action((ID *)&ob->id, 1);
833 ListBase *curves = &ob->adt->action->curves;
836 for (int i = 0; i < totcu; i++) {
838 add_bone_fcurve(ob, node, newcu[i]);
840 BLI_addtail(curves, newcu[i]);
841 // fcurve_is_used(newcu[i]); // never added to unused
846 bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name);
847 chan->rotmode = ROT_MODE_QUAT;
850 ob->rotmode = ROT_MODE_QUAT;
858 * This function returns the aspet ration from the Collada camera.
860 * Note:COLLADA allows to specify either XFov, or YFov alone.
861 * In that case the aspect ratio can be determined from
862 * the viewport aspect ratio (which is 1:1 ?)
863 * XXX: check this: its probably wrong!
864 * If both values are specified, then the aspect ration is simply xfov/yfov
865 * and if aspect ratio is efined, then .. well then its that one.
867 static const double get_aspect_ratio(const COLLADAFW::Camera *camera)
869 double aspect = camera->getAspectRatio().getValue();
872 const double yfov = camera->getYFov().getValue();
875 aspect = 1; // assume yfov and xfov are equal
878 const double xfov = camera->getXFov().getValue();
882 aspect = xfov / yfov;
889 void AnimationImporter::translate_Animations(COLLADAFW::Node *node,
890 std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& root_map,
891 std::multimap<COLLADAFW::UniqueId, Object *>& object_map,
892 std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map)
894 bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
895 COLLADAFW::UniqueId uid = node->getUniqueId();
896 COLLADAFW::Node *root = root_map.find(uid) == root_map.end() ? node : root_map[uid];
900 ob = armature_importer->get_armature_for_joint(root);
902 ob = object_map.find(uid) == object_map.end() ? NULL : object_map.find(uid)->second;
905 fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str());
910 AnimationImporter::AnimMix *animType = get_animation_type(node, FW_object_map);
913 if ( (animType->transform) != 0) {
914 /* const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL; */ /* UNUSED */
915 char joint_path[200];
918 armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
921 if (!ob->adt || !ob->adt->action) act = verify_adt_action((ID *)&ob->id, 1);
922 else act = ob->adt->action;
924 //Get the list of animation curves of the object
925 ListBase *AnimCurves = &(act->curves);
927 const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations();
929 //for each transformation in node
930 for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) {
931 COLLADAFW::Transformation *transform = nodeTransforms[i];
932 COLLADAFW::Transformation::TransformationType tm_type = transform->getTransformationType();
934 bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
935 bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
937 const COLLADAFW::UniqueId& listid = transform->getAnimationList();
939 //check if transformation has animations
940 if (animlist_map.find(listid) == animlist_map.end()) {
944 //transformation has animations
945 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
946 const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
947 //all the curves belonging to the current binding
948 std::vector<FCurve *> animcurves;
949 for (unsigned int j = 0; j < bindings.getCount(); j++) {
950 animcurves = curve_map[bindings[j].animation];
952 apply_matrix_curves(ob, animcurves, root, node, transform);
957 add_bone_animation_sampled(ob, animcurves, root, node, transform);
960 //calculate rnapaths and array index of fcurves according to transformation and animation class
961 Assign_transform_animations(transform, &bindings[j], &animcurves, is_joint, joint_path);
963 std::vector<FCurve *>::iterator iter;
964 //Add the curves of the current animation to the object
965 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
968 BLI_addtail(AnimCurves, fcu);
976 if (is_rotation && !is_joint) {
977 ob->rotmode = ROT_MODE_EUL;
982 if ((animType->light) != 0) {
983 Lamp *lamp = (Lamp *) ob->data;
985 if (!lamp->adt || !lamp->adt->action) act = verify_adt_action((ID *)&lamp->id, 1);
986 else act = lamp->adt->action;
988 ListBase *AnimCurves = &(act->curves);
989 const COLLADAFW::InstanceLightPointerArray& nodeLights = node->getInstanceLights();
991 for (unsigned int i = 0; i < nodeLights.getCount(); i++) {
992 const COLLADAFW::Light *light = (COLLADAFW::Light *) FW_object_map[nodeLights[i]->getInstanciatedObjectId()];
994 if ((animType->light & LIGHT_COLOR) != 0) {
995 const COLLADAFW::Color *col = &(light->getColor());
996 const COLLADAFW::UniqueId& listid = col->getAnimationList();
998 Assign_color_animations(listid, AnimCurves, "color");
1000 if ((animType->light & LIGHT_FOA) != 0) {
1001 const COLLADAFW::AnimatableFloat *foa = &(light->getFallOffAngle());
1002 const COLLADAFW::UniqueId& listid = foa->getAnimationList();
1004 Assign_float_animations(listid, AnimCurves, "spot_size");
1006 if ( (animType->light & LIGHT_FOE) != 0) {
1007 const COLLADAFW::AnimatableFloat *foe = &(light->getFallOffExponent());
1008 const COLLADAFW::UniqueId& listid = foe->getAnimationList();
1010 Assign_float_animations(listid, AnimCurves, "spot_blend");
1016 if (animType->camera != 0) {
1017 Camera *cam = (Camera *) ob->data;
1018 if (!cam->adt || !cam->adt->action)
1019 act = verify_adt_action((ID *)&cam->id, 1);
1021 act = cam->adt->action;
1023 ListBase *AnimCurves = &(act->curves);
1024 const COLLADAFW::InstanceCameraPointerArray& nodeCameras = node->getInstanceCameras();
1026 for (unsigned int i = 0; i < nodeCameras.getCount(); i++) {
1027 const COLLADAFW::Camera *camera = (COLLADAFW::Camera *) FW_object_map[nodeCameras[i]->getInstanciatedObjectId()];
1029 if ((animType->camera & CAMERA_XFOV) != 0) {
1030 const COLLADAFW::AnimatableFloat *xfov = &(camera->getXFov());
1031 const COLLADAFW::UniqueId& listid = xfov->getAnimationList();
1032 double aspect = get_aspect_ratio(camera);
1033 Assign_lens_animations(listid, AnimCurves, aspect, cam, "lens", CAMERA_XFOV);
1036 else if ((animType->camera & CAMERA_YFOV) != 0) {
1037 const COLLADAFW::AnimatableFloat *yfov = &(camera->getYFov());
1038 const COLLADAFW::UniqueId& listid = yfov->getAnimationList();
1039 double aspect = get_aspect_ratio(camera);
1040 Assign_lens_animations(listid, AnimCurves, aspect, cam, "lens", CAMERA_YFOV);
1043 else if ((animType->camera & CAMERA_XMAG) != 0) {
1044 const COLLADAFW::AnimatableFloat *xmag = &(camera->getXMag());
1045 const COLLADAFW::UniqueId& listid = xmag->getAnimationList();
1046 Assign_float_animations(listid, AnimCurves, "ortho_scale");
1049 else if ((animType->camera & CAMERA_YMAG) != 0) {
1050 const COLLADAFW::AnimatableFloat *ymag = &(camera->getYMag());
1051 const COLLADAFW::UniqueId& listid = ymag->getAnimationList();
1052 Assign_float_animations(listid, AnimCurves, "ortho_scale");
1055 if ((animType->camera & CAMERA_ZFAR) != 0) {
1056 const COLLADAFW::AnimatableFloat *zfar = &(camera->getFarClippingPlane());
1057 const COLLADAFW::UniqueId& listid = zfar->getAnimationList();
1058 Assign_float_animations(listid, AnimCurves, "clip_end");
1061 if ((animType->camera & CAMERA_ZNEAR) != 0) {
1062 const COLLADAFW::AnimatableFloat *znear = &(camera->getNearClippingPlane());
1063 const COLLADAFW::UniqueId& listid = znear->getAnimationList();
1064 Assign_float_animations(listid, AnimCurves, "clip_start");
1069 if (animType->material != 0) {
1070 Material *ma = give_current_material(ob, 1);
1071 if (!ma->adt || !ma->adt->action) act = verify_adt_action((ID *)&ma->id, 1);
1072 else act = ma->adt->action;
1074 ListBase *AnimCurves = &(act->curves);
1076 const COLLADAFW::InstanceGeometryPointerArray& nodeGeoms = node->getInstanceGeometries();
1077 for (unsigned int i = 0; i < nodeGeoms.getCount(); i++) {
1078 const COLLADAFW::MaterialBindingArray& matBinds = nodeGeoms[i]->getMaterialBindings();
1079 for (unsigned int j = 0; j < matBinds.getCount(); j++) {
1080 const COLLADAFW::UniqueId & matuid = matBinds[j].getReferencedMaterial();
1081 const COLLADAFW::Effect *ef = (COLLADAFW::Effect *) (FW_object_map[matuid]);
1082 if (ef != NULL) { /* can be NULL [#28909] */
1083 const COLLADAFW::CommonEffectPointerArray& commonEffects = ef->getCommonEffects();
1084 COLLADAFW::EffectCommon *efc = commonEffects[0];
1085 if ((animType->material & MATERIAL_SHININESS) != 0) {
1086 const COLLADAFW::FloatOrParam *shin = &(efc->getShininess());
1087 const COLLADAFW::UniqueId& listid = shin->getAnimationList();
1088 Assign_float_animations(listid, AnimCurves, "specular_hardness");
1091 if ((animType->material & MATERIAL_IOR) != 0) {
1092 const COLLADAFW::FloatOrParam *ior = &(efc->getIndexOfRefraction());
1093 const COLLADAFW::UniqueId& listid = ior->getAnimationList();
1094 Assign_float_animations(listid, AnimCurves, "raytrace_transparency.ior");
1097 if ((animType->material & MATERIAL_SPEC_COLOR) != 0) {
1098 const COLLADAFW::ColorOrTexture *cot = &(efc->getSpecular());
1099 const COLLADAFW::UniqueId& listid = cot->getColor().getAnimationList();
1100 Assign_color_animations(listid, AnimCurves, "specular_color");
1103 if ((animType->material & MATERIAL_DIFF_COLOR) != 0) {
1104 const COLLADAFW::ColorOrTexture *cot = &(efc->getDiffuse());
1105 const COLLADAFW::UniqueId& listid = cot->getColor().getAnimationList();
1106 Assign_color_animations(listid, AnimCurves, "diffuse_color");
1116 void AnimationImporter::add_bone_animation_sampled(Object *ob, std::vector<FCurve *>& animcurves, COLLADAFW::Node *root, COLLADAFW::Node *node, COLLADAFW::Transformation *tm)
1118 const char *bone_name = bc_get_joint_name(node);
1119 char joint_path[200];
1120 armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
1122 std::vector<float> frames;
1123 find_frames(&frames, &animcurves);
1125 // convert degrees to radians
1126 if (tm->getTransformationType() == COLLADAFW::Transformation::ROTATE) {
1128 std::vector<FCurve *>::iterator iter;
1129 for (iter = animcurves.begin(); iter != animcurves.end(); iter++) {
1130 FCurve *fcu = *iter;
1132 fcurve_deg_to_rad(fcu);
1137 float irest_dae[4][4];
1138 float rest[4][4], irest[4][4];
1140 get_joint_rest_mat(irest_dae, root, node);
1141 invert_m4(irest_dae);
1143 Bone *bone = BKE_armature_find_bone_name((bArmature *)ob->data, bone_name);
1145 fprintf(stderr, "cannot find bone \"%s\"\n", bone_name);
1150 copy_m4_m4(rest, bone->arm_mat);
1151 invert_m4_m4(irest, rest);
1153 // new curves to assign matrix transform animation
1154 FCurve *newcu[10]; // if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale
1155 unsigned int totcu = 10;
1156 const char *tm_str = NULL;
1158 for (int i = 0; i < totcu; i++) {
1163 tm_str = "rotation_quaternion";
1167 tm_str = "location";
1176 BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str);
1178 newcu[i] = create_fcurve(axis, rna_path);
1179 newcu[i]->totvert = frames.size();
1182 if (frames.size() == 0)
1185 std::sort(frames.begin(), frames.end());
1190 std::vector<float>::iterator it;
1192 // sample values at each frame
1193 for (it = frames.begin(); it != frames.end(); it++) {
1201 // calc object-space mat
1202 evaluate_transform_at_frame(matfra, node, fra);
1205 // for joints, we need a special matrix
1206 // special matrix: iR * M * iR_dae * R
1207 // where R, iR are bone rest and inverse rest mats in world space (Blender bones),
1208 // iR_dae is joint inverse rest matrix (DAE) and M is an evaluated joint world-space matrix (DAE)
1209 float temp[4][4], par[4][4];
1213 calc_joint_parent_mat_rest(par, NULL, root, node);
1214 mul_m4_m4m4(temp, par, matfra);
1216 // evaluate_joint_world_transform_at_frame(temp, NULL, node, fra);
1218 // calc special matrix
1219 mul_m4_series(mat, irest, temp, irest_dae, rest);
1221 float rot[4], loc[3], scale[3];
1223 bc_rotate_from_reference_quat(rot, qref, mat);
1224 copy_qt_qt(qref, rot);
1226 copy_v3_v3(loc, mat[3]);
1227 mat4_to_size(scale, mat);
1230 for (int i = 0; i < totcu; i++) {
1232 add_bezt(newcu[i], fra, rot[i]);
1234 add_bezt(newcu[i], fra, loc[i - 4]);
1236 add_bezt(newcu[i], fra, scale[i - 7]);
1239 verify_adt_action((ID *)&ob->id, 1);
1242 for (int i = 0; i < totcu; i++) {
1243 add_bone_fcurve(ob, node, newcu[i]);
1244 // fcurve_is_used(newcu[i]); // never added to unused
1247 bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name);
1248 chan->rotmode = ROT_MODE_QUAT;
1253 //Check if object is animated by checking if animlist_map holds the animlist_id of node transforms
1254 AnimationImporter::AnimMix *AnimationImporter::get_animation_type(const COLLADAFW::Node *node,
1255 std::map<COLLADAFW::UniqueId, const COLLADAFW::Object *> FW_object_map)
1257 AnimMix *types = new AnimMix();
1259 const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations();
1261 //for each transformation in node
1262 for (unsigned int i = 0; i < nodeTransforms.getCount(); i++) {
1263 COLLADAFW::Transformation *transform = nodeTransforms[i];
1264 const COLLADAFW::UniqueId& listid = transform->getAnimationList();
1266 //check if transformation has animations
1267 if (animlist_map.find(listid) == animlist_map.end()) {
1271 types->transform = types->transform | NODE_TRANSFORM;
1275 const COLLADAFW::InstanceLightPointerArray& nodeLights = node->getInstanceLights();
1277 for (unsigned int i = 0; i < nodeLights.getCount(); i++) {
1278 const COLLADAFW::Light *light = (COLLADAFW::Light *) FW_object_map[nodeLights[i]->getInstanciatedObjectId()];
1279 types->light = setAnimType(&(light->getColor()), (types->light), LIGHT_COLOR);
1280 types->light = setAnimType(&(light->getFallOffAngle()), (types->light), LIGHT_FOA);
1281 types->light = setAnimType(&(light->getFallOffExponent()), (types->light), LIGHT_FOE);
1283 if (types->light != 0) break;
1287 const COLLADAFW::InstanceCameraPointerArray& nodeCameras = node->getInstanceCameras();
1288 for (unsigned int i = 0; i < nodeCameras.getCount(); i++) {
1289 const COLLADAFW::Camera *camera = (COLLADAFW::Camera *) FW_object_map[nodeCameras[i]->getInstanciatedObjectId()];
1290 if ( camera == NULL ) {
1291 // Can happen if the node refers to an unknown camera.
1295 const bool is_perspective_type = camera->getCameraType() == COLLADAFW::Camera::PERSPECTIVE;
1298 const COLLADAFW::Animatable *mag;
1299 const COLLADAFW::UniqueId listid = camera->getYMag().getAnimationList();
1300 if (animlist_map.find(listid) != animlist_map.end()) {
1301 mag = &(camera->getYMag());
1302 addition = (is_perspective_type) ? CAMERA_YFOV: CAMERA_YMAG;
1305 mag = &(camera->getXMag());
1306 addition = (is_perspective_type) ? CAMERA_XFOV: CAMERA_XMAG;
1308 types->camera = setAnimType(mag, (types->camera), addition);
1310 types->camera = setAnimType(&(camera->getFarClippingPlane()), (types->camera), CAMERA_ZFAR);
1311 types->camera = setAnimType(&(camera->getNearClippingPlane()), (types->camera), CAMERA_ZNEAR);
1313 if (types->camera != 0) break;
1317 const COLLADAFW::InstanceGeometryPointerArray& nodeGeoms = node->getInstanceGeometries();
1318 for (unsigned int i = 0; i < nodeGeoms.getCount(); i++) {
1319 const COLLADAFW::MaterialBindingArray& matBinds = nodeGeoms[i]->getMaterialBindings();
1320 for (unsigned int j = 0; j < matBinds.getCount(); j++) {
1321 const COLLADAFW::UniqueId & matuid = matBinds[j].getReferencedMaterial();
1322 const COLLADAFW::Effect *ef = (COLLADAFW::Effect *) (FW_object_map[matuid]);
1323 if (ef != NULL) { /* can be NULL [#28909] */
1324 const COLLADAFW::CommonEffectPointerArray& commonEffects = ef->getCommonEffects();
1325 if (!commonEffects.empty()) {
1326 COLLADAFW::EffectCommon *efc = commonEffects[0];
1327 types->material = setAnimType(&(efc->getShininess()), (types->material), MATERIAL_SHININESS);
1328 types->material = setAnimType(&(efc->getSpecular().getColor()), (types->material), MATERIAL_SPEC_COLOR);
1329 types->material = setAnimType(&(efc->getDiffuse().getColor()), (types->material), MATERIAL_DIFF_COLOR);
1330 // types->material = setAnimType(&(efc->get()), (types->material), MATERIAL_TRANSPARENCY);
1331 types->material = setAnimType(&(efc->getIndexOfRefraction()), (types->material), MATERIAL_IOR);
1339 int AnimationImporter::setAnimType(const COLLADAFW::Animatable *prop, int types, int addition)
1342 const COLLADAFW::UniqueId& listid = prop->getAnimationList();
1343 if (animlist_map.find(listid) != animlist_map.end())
1344 anim_type = types | addition;
1351 // Is not used anymore.
1352 void AnimationImporter::find_frames_old(std::vector<float> *frames, COLLADAFW::Node *node, COLLADAFW::Transformation::TransformationType tm_type)
1354 bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
1355 bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
1356 // for each <rotate>, <translate>, etc. there is a separate Transformation
1357 const COLLADAFW::TransformationPointerArray& nodeTransforms = node->getTransformations();
1360 // find frames at which to sample plus convert all rotation keys to radians
1361 for (i = 0; i < nodeTransforms.getCount(); i++) {
1362 COLLADAFW::Transformation *transform = nodeTransforms[i];
1363 COLLADAFW::Transformation::TransformationType nodeTmType = transform->getTransformationType();
1366 if (nodeTmType == tm_type) {
1367 //get animation bindings for the current transformation
1368 const COLLADAFW::UniqueId& listid = transform->getAnimationList();
1369 //if transform is animated its animlist must exist.
1370 if (animlist_map.find(listid) != animlist_map.end()) {
1372 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
1373 const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
1375 if (bindings.getCount()) {
1376 //for each AnimationBinding get the fcurves which animate the transform
1377 for (unsigned int j = 0; j < bindings.getCount(); j++) {
1378 std::vector<FCurve *>& curves = curve_map[bindings[j].animation];
1379 bool xyz = ((nodeTmType == COLLADAFW::Transformation::TRANSLATE || nodeTmType == COLLADAFW::Transformation::SCALE) && bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ);
1381 if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3) || is_matrix) {
1382 std::vector<FCurve *>::iterator iter;
1384 for (iter = curves.begin(); iter != curves.end(); iter++) {
1385 FCurve *fcu = *iter;
1387 //if transform is rotation the fcurves values must be turned in to radian.
1389 fcurve_deg_to_rad(fcu);
1391 for (unsigned int k = 0; k < fcu->totvert; k++) {
1392 //get frame value from bezTriple
1393 float fra = fcu->bezt[k].vec[1][0];
1394 //if frame already not added add frame to frames
1395 if (std::find(frames->begin(), frames->end(), fra) == frames->end())
1396 frames->push_back(fra);
1401 fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves.size());
1413 // animlist_map - map animlist id -> animlist
1414 // curve_map - map anim id -> curve(s)
1415 Object *AnimationImporter::translate_animation_OLD(COLLADAFW::Node *node,
1416 std::map<COLLADAFW::UniqueId, Object *>& object_map,
1417 std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& root_map,
1418 COLLADAFW::Transformation::TransformationType tm_type,
1422 bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE;
1423 bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX;
1424 bool is_joint = node->getType() == COLLADAFW::Node::JOINT;
1426 COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ? node : root_map[node->getUniqueId()];
1427 Object *ob = is_joint ? armature_importer->get_armature_for_joint(node) : object_map[node->getUniqueId()];
1428 const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL;
1430 fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str());
1434 // frames at which to sample
1435 std::vector<float> frames;
1437 find_frames_old(&frames, node, tm_type);
1441 float irest_dae[4][4];
1442 float rest[4][4], irest[4][4];
1445 get_joint_rest_mat(irest_dae, root, node);
1446 invert_m4(irest_dae);
1448 Bone *bone = BKE_armature_find_bone_name((bArmature *)ob->data, bone_name);
1450 fprintf(stderr, "cannot find bone \"%s\"\n", bone_name);
1455 copy_m4_m4(rest, bone->arm_mat);
1456 invert_m4_m4(irest, rest);
1461 #ifdef ARMATURE_TEST
1462 FCurve *job_curves[10];
1463 job = get_joint_object(root, node, par_job);
1466 if (frames.size() == 0)
1469 std::sort(frames.begin(), frames.end());
1471 const char *tm_str = NULL;
1473 case COLLADAFW::Transformation::ROTATE:
1474 tm_str = "rotation_quaternion";
1476 case COLLADAFW::Transformation::SCALE:
1479 case COLLADAFW::Transformation::TRANSLATE:
1480 tm_str = "location";
1482 case COLLADAFW::Transformation::MATRIX:
1489 char joint_path[200];
1492 armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path));
1495 FCurve *newcu[10]; // if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale
1496 unsigned int totcu = is_matrix ? 10 : (is_rotation ? 4 : 3);
1498 for (i = 0; i < totcu; i++) {
1504 tm_str = "rotation_quaternion";
1508 tm_str = "location";
1518 BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str);
1520 BLI_strncpy(rna_path, tm_str, sizeof(rna_path));
1521 newcu[i] = create_fcurve(axis, rna_path);
1523 #ifdef ARMATURE_TEST
1525 job_curves[i] = create_fcurve(axis, tm_str);
1529 std::vector<float>::iterator it;
1531 // sample values at each frame
1532 for (it = frames.begin(); it != frames.end(); it++) {
1540 // calc object-space mat
1541 evaluate_transform_at_frame(matfra, node, fra);
1543 // for joints, we need a special matrix
1545 // special matrix: iR * M * iR_dae * R
1546 // where R, iR are bone rest and inverse rest mats in world space (Blender bones),
1547 // iR_dae is joint inverse rest matrix (DAE) and M is an evaluated joint world-space matrix (DAE)
1548 float temp[4][4], par[4][4];
1551 calc_joint_parent_mat_rest(par, NULL, root, node);
1552 mul_m4_m4m4(temp, par, matfra);
1554 // evaluate_joint_world_transform_at_frame(temp, NULL, node, fra);
1556 // calc special matrix
1557 mul_m4_series(mat, irest, temp, irest_dae, rest);
1560 copy_m4_m4(mat, matfra);
1563 float val[4], rot[4], loc[3], scale[3];
1566 case COLLADAFW::Transformation::ROTATE:
1567 mat4_to_quat(val, mat);
1569 case COLLADAFW::Transformation::SCALE:
1570 mat4_to_size(val, mat);
1572 case COLLADAFW::Transformation::TRANSLATE:
1573 copy_v3_v3(val, mat[3]);
1575 case COLLADAFW::Transformation::MATRIX:
1576 mat4_to_quat(rot, mat);
1577 copy_v3_v3(loc, mat[3]);
1578 mat4_to_size(scale, mat);
1585 for (i = 0; i < totcu; i++) {
1588 add_bezt(newcu[i], fra, rot[i]);
1590 add_bezt(newcu[i], fra, loc[i - 4]);
1592 add_bezt(newcu[i], fra, scale[i - 7]);
1595 add_bezt(newcu[i], fra, val[i]);
1599 #ifdef ARMATURE_TEST
1602 case COLLADAFW::Transformation::ROTATE:
1603 mat4_to_quat(val, matfra);
1605 case COLLADAFW::Transformation::SCALE:
1606 mat4_to_size(val, matfra);
1608 case COLLADAFW::Transformation::TRANSLATE:
1609 copy_v3_v3(val, matfra[3]);
1612 mat4_to_quat(rot, matfra);
1613 copy_v3_v3(loc, matfra[3]);
1614 mat4_to_size(scale, matfra);
1620 for (i = 0; i < totcu; i++) {
1623 add_bezt(job_curves[i], fra, rot[i]);
1625 add_bezt(job_curves[i], fra, loc[i - 4]);
1627 add_bezt(job_curves[i], fra, scale[i - 7]);
1630 add_bezt(job_curves[i], fra, val[i]);
1637 verify_adt_action((ID *)&ob->id, 1);
1639 ListBase *curves = &ob->adt->action->curves;
1642 for (i = 0; i < totcu; i++) {
1644 add_bone_fcurve(ob, node, newcu[i]);
1646 BLI_addtail(curves, newcu[i]);
1648 #ifdef ARMATURE_TEST
1650 BLI_addtail(&job->adt->action->curves, job_curves[i]);
1654 if (is_rotation || is_matrix) {
1656 bPoseChannel *chan = BKE_pose_channel_find_name(ob->pose, bone_name);
1657 chan->rotmode = ROT_MODE_QUAT;
1660 ob->rotmode = ROT_MODE_QUAT;
1667 // internal, better make it private
1668 // warning: evaluates only rotation and only assigns matrix transforms now
1669 // prerequisites: animlist_map, curve_map
1670 void AnimationImporter::evaluate_transform_at_frame(float mat[4][4], COLLADAFW::Node *node, float fra)
1672 const COLLADAFW::TransformationPointerArray& tms = node->getTransformations();
1676 for (unsigned int i = 0; i < tms.getCount(); i++) {
1677 COLLADAFW::Transformation *tm = tms[i];
1678 COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
1683 std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId();
1684 if (!evaluate_animation(tm, m, fra, nodename.c_str())) {
1686 case COLLADAFW::Transformation::ROTATE:
1687 dae_rotate_to_mat4(tm, m);
1689 case COLLADAFW::Transformation::TRANSLATE:
1690 dae_translate_to_mat4(tm, m);
1692 case COLLADAFW::Transformation::SCALE:
1693 dae_scale_to_mat4(tm, m);
1695 case COLLADAFW::Transformation::MATRIX:
1696 dae_matrix_to_mat4(tm, m);
1699 fprintf(stderr, "unsupported transformation type %d\n", type);
1704 copy_m4_m4(temp, mat);
1706 mul_m4_m4m4(mat, temp, m);
1710 static void report_class_type_unsupported(const char *path,
1711 const COLLADAFW::AnimationList::AnimationClass animclass,
1712 const COLLADAFW::Transformation::TransformationType type)
1714 if (animclass == COLLADAFW::AnimationList::UNKNOWN_CLASS) {
1715 fprintf(stderr, "%s: UNKNOWN animation class\n", path);
1718 fprintf(stderr, "%s: animation class %d is not supported yet for transformation type %d\n", path, animclass, type);
1722 // return true to indicate that mat contains a sane value
1723 bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, float mat[4][4], float fra, const char *node_id)
1725 const COLLADAFW::UniqueId& listid = tm->getAnimationList();
1726 COLLADAFW::Transformation::TransformationType type = tm->getTransformationType();
1728 if (type != COLLADAFW::Transformation::ROTATE &&
1729 type != COLLADAFW::Transformation::SCALE &&
1730 type != COLLADAFW::Transformation::TRANSLATE &&
1731 type != COLLADAFW::Transformation::MATRIX) {
1732 fprintf(stderr, "animation of transformation %d is not supported yet\n", type);
1736 if (animlist_map.find(listid) == animlist_map.end())
1739 const COLLADAFW::AnimationList *animlist = animlist_map[listid];
1740 const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings();
1742 if (bindings.getCount()) {
1745 bool is_scale = (type == COLLADAFW::Transformation::SCALE);
1746 bool is_translate = (type == COLLADAFW::Transformation::TRANSLATE);
1749 dae_scale_to_v3(tm, vec);
1750 else if (is_translate)
1751 dae_translate_to_v3(tm, vec);
1753 for (unsigned int j = 0; j < bindings.getCount(); j++) {
1754 const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[j];
1755 std::vector<FCurve *>& curves = curve_map[binding.animation];
1756 COLLADAFW::AnimationList::AnimationClass animclass = binding.animationClass;
1760 case COLLADAFW::Transformation::ROTATE:
1761 BLI_snprintf(path, sizeof(path), "%s.rotate (binding %u)", node_id, j);
1763 case COLLADAFW::Transformation::SCALE:
1764 BLI_snprintf(path, sizeof(path), "%s.scale (binding %u)", node_id, j);
1766 case COLLADAFW::Transformation::TRANSLATE:
1767 BLI_snprintf(path, sizeof(path), "%s.translate (binding %u)", node_id, j);
1769 case COLLADAFW::Transformation::MATRIX:
1770 BLI_snprintf(path, sizeof(path), "%s.matrix (binding %u)", node_id, j);
1776 if (type == COLLADAFW::Transformation::ROTATE) {
1777 if (curves.size() != 1) {
1778 fprintf(stderr, "expected 1 curve, got %d\n", (int)curves.size());
1782 // TODO support other animclasses
1783 if (animclass != COLLADAFW::AnimationList::ANGLE) {
1784 report_class_type_unsupported(path, animclass, type);
1788 COLLADABU::Math::Vector3& axis = ((COLLADAFW::Rotate *)tm)->getRotationAxis();
1790 float ax[3] = {(float)axis[0], (float)axis[1], (float)axis[2]};
1791 float angle = evaluate_fcurve(curves[0], fra);
1792 axis_angle_to_mat4(mat, ax, angle);
1796 else if (is_scale || is_translate) {
1797 bool is_xyz = animclass == COLLADAFW::AnimationList::POSITION_XYZ;
1799 if ((!is_xyz && curves.size() != 1) || (is_xyz && curves.size() != 3)) {
1801 fprintf(stderr, "%s: expected 3 curves, got %d\n", path, (int)curves.size());
1803 fprintf(stderr, "%s: expected 1 curve, got %d\n", path, (int)curves.size());
1807 switch (animclass) {
1808 case COLLADAFW::AnimationList::POSITION_X:
1809 vec[0] = evaluate_fcurve(curves[0], fra);
1811 case COLLADAFW::AnimationList::POSITION_Y:
1812 vec[1] = evaluate_fcurve(curves[0], fra);
1814 case COLLADAFW::AnimationList::POSITION_Z:
1815 vec[2] = evaluate_fcurve(curves[0], fra);
1817 case COLLADAFW::AnimationList::POSITION_XYZ:
1818 vec[0] = evaluate_fcurve(curves[0], fra);
1819 vec[1] = evaluate_fcurve(curves[1], fra);
1820 vec[2] = evaluate_fcurve(curves[2], fra);
1823 report_class_type_unsupported(path, animclass, type);
1827 else if (type == COLLADAFW::Transformation::MATRIX) {
1828 // for now, of matrix animation, support only the case when all values are packed into one animation
1829 if (curves.size() != 16) {
1830 fprintf(stderr, "%s: expected 16 curves, got %d\n", path, (int)curves.size());
1834 COLLADABU::Math::Matrix4 matrix;
1837 for (std::vector<FCurve *>::iterator it = curves.begin(); it != curves.end(); it++) {
1838 matrix.setElement(i, j, evaluate_fcurve(*it, fra));
1844 fcurve_is_used(*it);
1846 unit_converter->dae_matrix_to_mat4_(mat, matrix);
1852 size_to_mat4(mat, vec);
1854 copy_v3_v3(mat[3], vec);
1856 return is_scale || is_translate;
1862 // gives a world-space mat of joint at rest position
1863 void AnimationImporter::get_joint_rest_mat(float mat[4][4], COLLADAFW::Node *root, COLLADAFW::Node *node)
1865 // if bind mat is not available,
1866 // use "current" node transform, i.e. all those tms listed inside <node>
1867 if (!armature_importer->get_joint_bind_mat(mat, node)) {
1868 float par[4][4], m[4][4];
1870 calc_joint_parent_mat_rest(par, NULL, root, node);
1871 get_node_mat(m, node, NULL, NULL);
1872 mul_m4_m4m4(mat, par, m);
1876 // gives a world-space mat, end's mat not included
1877 bool AnimationImporter::calc_joint_parent_mat_rest(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end)
1882 par ? copy_m4_m4(mat, par) : unit_m4(mat);
1886 // use bind matrix if available or calc "current" world mat
1887 if (!armature_importer->get_joint_bind_mat(m, node)) {
1890 get_node_mat(temp, node, NULL, NULL);
1891 mul_m4_m4m4(m, par, temp);
1894 get_node_mat(m, node, NULL, NULL);
1898 COLLADAFW::NodePointerArray& children = node->getChildNodes();
1899 for (unsigned int i = 0; i < children.getCount(); i++) {
1900 if (calc_joint_parent_mat_rest(mat, m, children[i], end))
1907 #ifdef ARMATURE_TEST
1908 Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::Node *node, Object *par_job)
1910 if (joint_objects.find(node->getUniqueId()) == joint_objects.end()) {
1911 Object *job = bc_add_object(scene, OB_EMPTY, (char *)get_joint_name(node));
1913 job->lay = BKE_scene_base_find(scene, job)->lay = 2;
1915 mul_v3_fl(job->size, 0.5f);
1916 DAG_id_tag_update(&job->id, OB_RECALC_OB);
1918 verify_adt_action((ID *)&job->id, 1);
1920 job->rotmode = ROT_MODE_QUAT;
1923 get_joint_rest_mat(mat, root, node);
1926 float temp[4][4], ipar[4][4];
1927 invert_m4_m4(ipar, par_job->obmat);
1928 copy_m4_m4(temp, mat);
1929 mul_m4_m4m4(mat, ipar, temp);
1932 bc_decompose(mat, job->loc, NULL, job->quat, job->size);
1935 job->parent = par_job;
1937 DAG_id_tag_update(&par_job->id, OB_RECALC_OB);
1938 job->parsubstr[0] = 0;
1941 BKE_object_where_is_calc(scene, job);
1943 // after parenting and layer change
1944 DAG_relations_tag_update(CTX_data_main(C));
1946 joint_objects[node->getUniqueId()] = job;
1949 return joint_objects[node->getUniqueId()];
1954 // recursively evaluates joint tree until end is found, mat then is world-space matrix of end
1955 // mat must be identity on enter, node must be root
1956 bool AnimationImporter::evaluate_joint_world_transform_at_frame(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end, float fra)
1961 evaluate_transform_at_frame(temp, node, node == end ? fra : 0.0f);
1962 mul_m4_m4m4(m, par, temp);
1965 evaluate_transform_at_frame(m, node, node == end ? fra : 0.0f);
1973 COLLADAFW::NodePointerArray& children = node->getChildNodes();
1974 for (int i = 0; i < children.getCount(); i++) {
1975 if (evaluate_joint_world_transform_at_frame(mat, m, children[i], end, fra))
1984 void AnimationImporter::add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurve *fcu)
1986 const char *bone_name = bc_get_joint_name(node);
1987 bAction *act = ob->adt->action;
1989 /* try to find group */
1990 bActionGroup *grp = BKE_action_group_find_name(act, bone_name);
1992 /* no matching groups, so add one */
1994 /* Add a new group, and make it active */
1995 grp = (bActionGroup *)MEM_callocN(sizeof(bActionGroup), "bActionGroup");
1997 grp->flag = AGRP_SELECTED;
1998 BLI_strncpy(grp->name, bone_name, sizeof(grp->name));
2000 BLI_addtail(&act->groups, grp);
2001 BLI_uniquename(&act->groups, grp, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "Group"), '.',
2002 offsetof(bActionGroup, name), 64);
2005 /* add F-Curve to group */
2006 action_groups_add_channel(act, grp, fcu);
2009 void AnimationImporter::add_bezt(FCurve *fcu, float fra, float value)
2011 //float fps = (float)FPS;
2013 memset(&bez, 0, sizeof(BezTriple));
2014 bez.vec[1][0] = fra;
2015 bez.vec[1][1] = value;
2016 bez.ipo = BEZT_IPO_LIN; /* use default interpolation mode here... */
2017 bez.f1 = bez.f2 = bez.f3 = SELECT;
2018 bez.h1 = bez.h2 = HD_AUTO;
2019 insert_bezt_fcurve(fcu, &bez, 0);
2020 calchandles_fcurve(fcu);
2023 void AnimationImporter::set_import_from_version(std::string import_from_version)
2025 this->import_from_version = import_from_version;