|
Blender
V2.59
|
00001 /* 00002 * $Id: AnimationImporter.cpp 37664 2011-06-20 12:43:10Z jesterking $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * Contributor(s): Chingiz Dyussenov, Arystanbek Dyussenov, Nathan Letwory. 00021 * 00022 * ***** END GPL LICENSE BLOCK ***** 00023 */ 00024 00029 #include <stddef.h> 00030 00031 /* COLLADABU_ASSERT, may be able to remove later */ 00032 #include "COLLADABUPlatform.h" 00033 00034 #include "DNA_armature_types.h" 00035 00036 #include "ED_keyframing.h" 00037 00038 #include "BLI_listbase.h" 00039 #include "BLI_math.h" 00040 #include "BLI_path_util.h" 00041 #include "BLI_string.h" 00042 00043 #include "BKE_action.h" 00044 #include "BKE_armature.h" 00045 #include "BKE_fcurve.h" 00046 #include "BKE_object.h" 00047 00048 #include "MEM_guardedalloc.h" 00049 00050 #include "collada_utils.h" 00051 #include "AnimationImporter.h" 00052 #include "ArmatureImporter.h" 00053 00054 #include <algorithm> 00055 #include <cstddef> 00056 00057 // first try node name, if not available (since is optional), fall back to original id 00058 template<class T> 00059 static const char *bc_get_joint_name(T *node) 00060 { 00061 const std::string& id = node->getName(); 00062 return id.size() ? id.c_str() : node->getOriginalId().c_str(); 00063 } 00064 00065 FCurve *AnimationImporter::create_fcurve(int array_index, const char *rna_path) 00066 { 00067 FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve"); 00068 00069 fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED); 00070 fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path)); 00071 fcu->array_index = array_index; 00072 return fcu; 00073 } 00074 00075 void AnimationImporter::create_bezt(FCurve *fcu, float frame, float output) 00076 { 00077 BezTriple bez; 00078 memset(&bez, 0, sizeof(BezTriple)); 00079 bez.vec[1][0] = frame; 00080 bez.vec[1][1] = output; 00081 bez.ipo = U.ipo_new; /* use default interpolation mode here... */ 00082 bez.f1 = bez.f2 = bez.f3 = SELECT; 00083 bez.h1 = bez.h2 = HD_AUTO; 00084 insert_bezt_fcurve(fcu, &bez, 0); 00085 calchandles_fcurve(fcu); 00086 } 00087 00088 // create one or several fcurves depending on the number of parameters being animated 00089 void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve) 00090 { 00091 COLLADAFW::FloatOrDoubleArray& input = curve->getInputValues(); 00092 COLLADAFW::FloatOrDoubleArray& output = curve->getOutputValues(); 00093 // COLLADAFW::FloatOrDoubleArray& intan = curve->getInTangentValues(); 00094 // COLLADAFW::FloatOrDoubleArray& outtan = curve->getOutTangentValues(); 00095 float fps = (float)FPS; 00096 size_t dim = curve->getOutDimension(); 00097 unsigned int i; 00098 00099 std::vector<FCurve*>& fcurves = curve_map[curve->getUniqueId()]; 00100 00101 switch (dim) { 00102 case 1: // X, Y, Z or angle 00103 case 3: // XYZ 00104 case 16: // matrix 00105 { 00106 for (i = 0; i < dim; i++ ) { 00107 FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve"); 00108 00109 fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED); 00110 // fcu->rna_path = BLI_strdupn(path, strlen(path)); 00111 fcu->array_index = 0; 00112 //fcu->totvert = curve->getKeyCount(); 00113 00114 // create beztriple for each key 00115 for (unsigned int j = 0; j < curve->getKeyCount(); j++) { 00116 BezTriple bez; 00117 memset(&bez, 0, sizeof(BezTriple)); 00118 00119 // intangent 00120 // bez.vec[0][0] = get_float_value(intan, j * 6 + i + i) * fps; 00121 // bez.vec[0][1] = get_float_value(intan, j * 6 + i + i + 1); 00122 00123 // input, output 00124 bez.vec[1][0] = bc_get_float_value(input, j) * fps; 00125 bez.vec[1][1] = bc_get_float_value(output, j * dim + i); 00126 00127 // outtangent 00128 // bez.vec[2][0] = get_float_value(outtan, j * 6 + i + i) * fps; 00129 // bez.vec[2][1] = get_float_value(outtan, j * 6 + i + i + 1); 00130 00131 bez.ipo = U.ipo_new; /* use default interpolation mode here... */ 00132 bez.f1 = bez.f2 = bez.f3 = SELECT; 00133 bez.h1 = bez.h2 = HD_AUTO; 00134 insert_bezt_fcurve(fcu, &bez, 0); 00135 } 00136 00137 calchandles_fcurve(fcu); 00138 00139 fcurves.push_back(fcu); 00140 } 00141 } 00142 break; 00143 default: 00144 fprintf(stderr, "Output dimension of %d is not yet supported (animation id = %s)\n", (int)dim, curve->getOriginalId().c_str()); 00145 } 00146 00147 for (std::vector<FCurve*>::iterator it = fcurves.begin(); it != fcurves.end(); it++) 00148 unused_curves.push_back(*it); 00149 } 00150 00151 void AnimationImporter::fcurve_deg_to_rad(FCurve *cu) 00152 { 00153 for (unsigned int i = 0; i < cu->totvert; i++) { 00154 // TODO convert handles too 00155 cu->bezt[i].vec[1][1] *= M_PI / 180.0f; 00156 } 00157 } 00158 00159 void AnimationImporter::add_fcurves_to_object(Object *ob, std::vector<FCurve*>& curves, char *rna_path, int array_index, Animation *animated) 00160 { 00161 bAction *act; 00162 00163 if (!ob->adt || !ob->adt->action) act = verify_adt_action((ID*)&ob->id, 1); 00164 else act = ob->adt->action; 00165 00166 std::vector<FCurve*>::iterator it; 00167 int i; 00168 00169 #if 0 00170 char *p = strstr(rna_path, "rotation_euler"); 00171 bool is_rotation = p && *(p + strlen("rotation_euler")) == '\0'; 00172 00173 // convert degrees to radians for rotation 00174 if (is_rotation) 00175 fcurve_deg_to_rad(fcu); 00176 #endif 00177 00178 for (it = curves.begin(), i = 0; it != curves.end(); it++, i++) { 00179 FCurve *fcu = *it; 00180 fcu->rna_path = BLI_strdupn(rna_path, strlen(rna_path)); 00181 00182 if (array_index == -1) fcu->array_index = i; 00183 else fcu->array_index = array_index; 00184 00185 if (ob->type == OB_ARMATURE) { 00186 bActionGroup *grp = NULL; 00187 const char *bone_name = bc_get_joint_name(animated->node); 00188 00189 if (bone_name) { 00190 /* try to find group */ 00191 grp = action_groups_find_named(act, bone_name); 00192 00193 /* no matching groups, so add one */ 00194 if (grp == NULL) { 00195 /* Add a new group, and make it active */ 00196 grp = (bActionGroup*)MEM_callocN(sizeof(bActionGroup), "bActionGroup"); 00197 00198 grp->flag = AGRP_SELECTED; 00199 BLI_strncpy(grp->name, bone_name, sizeof(grp->name)); 00200 00201 BLI_addtail(&act->groups, grp); 00202 BLI_uniquename(&act->groups, grp, "Group", '.', offsetof(bActionGroup, name), 64); 00203 } 00204 00205 /* add F-Curve to group */ 00206 action_groups_add_channel(act, grp, fcu); 00207 00208 } 00209 #if 0 00210 if (is_rotation) { 00211 fcurves_actionGroup_map[grp].push_back(fcu); 00212 } 00213 #endif 00214 } 00215 else { 00216 BLI_addtail(&act->curves, fcu); 00217 } 00218 00219 // curve is used, so remove it from unused_curves 00220 unused_curves.erase(std::remove(unused_curves.begin(), unused_curves.end(), fcu), unused_curves.end()); 00221 } 00222 } 00223 00224 AnimationImporter::AnimationImporter(UnitConverter *conv, ArmatureImporter *arm, Scene *scene) : 00225 TransformReader(conv), armature_importer(arm), scene(scene) { } 00226 00227 AnimationImporter::~AnimationImporter() 00228 { 00229 // free unused FCurves 00230 for (std::vector<FCurve*>::iterator it = unused_curves.begin(); it != unused_curves.end(); it++) 00231 free_fcurve(*it); 00232 00233 if (unused_curves.size()) 00234 fprintf(stderr, "removed %d unused curves\n", (int)unused_curves.size()); 00235 } 00236 00237 bool AnimationImporter::write_animation(const COLLADAFW::Animation* anim) 00238 { 00239 if (anim->getAnimationType() == COLLADAFW::Animation::ANIMATION_CURVE) { 00240 COLLADAFW::AnimationCurve *curve = (COLLADAFW::AnimationCurve*)anim; 00241 00242 // XXX Don't know if it's necessary 00243 // Should we check outPhysicalDimension? 00244 if (curve->getInPhysicalDimension() != COLLADAFW::PHYSICAL_DIMENSION_TIME) { 00245 fprintf(stderr, "Inputs physical dimension is not time. \n"); 00246 return true; 00247 } 00248 00249 // a curve can have mixed interpolation type, 00250 // in this case curve->getInterpolationTypes returns a list of interpolation types per key 00251 COLLADAFW::AnimationCurve::InterpolationType interp = curve->getInterpolationType(); 00252 00253 if (interp != COLLADAFW::AnimationCurve::INTERPOLATION_MIXED) { 00254 switch (interp) { 00255 case COLLADAFW::AnimationCurve::INTERPOLATION_LINEAR: 00256 case COLLADAFW::AnimationCurve::INTERPOLATION_BEZIER: 00257 animation_to_fcurves(curve); 00258 break; 00259 default: 00260 // TODO there're also CARDINAL, HERMITE, BSPLINE and STEP types 00261 fprintf(stderr, "CARDINAL, HERMITE, BSPLINE and STEP anim interpolation types not supported yet.\n"); 00262 break; 00263 } 00264 } 00265 else { 00266 // not supported yet 00267 fprintf(stderr, "MIXED anim interpolation type is not supported yet.\n"); 00268 } 00269 } 00270 else { 00271 fprintf(stderr, "FORMULA animation type is not supported yet.\n"); 00272 } 00273 00274 return true; 00275 } 00276 00277 // called on post-process stage after writeVisualScenes 00278 bool AnimationImporter::write_animation_list(const COLLADAFW::AnimationList* animlist) 00279 { 00280 const COLLADAFW::UniqueId& animlist_id = animlist->getUniqueId(); 00281 00282 animlist_map[animlist_id] = animlist; 00283 00284 #if 0 00285 // should not happen 00286 if (uid_animated_map.find(animlist_id) == uid_animated_map.end()) { 00287 return true; 00288 } 00289 00290 // for bones rna_path is like: pose.bones["bone-name"].rotation 00291 00292 // what does this AnimationList animate? 00293 Animation& animated = uid_animated_map[animlist_id]; 00294 Object *ob = animated.ob; 00295 00296 char rna_path[100]; 00297 char joint_path[100]; 00298 bool is_joint = false; 00299 00300 // if ob is NULL, it should be a JOINT 00301 if (!ob) { 00302 ob = armature_importer->get_armature_for_joint(animated.node); 00303 00304 if (!ob) { 00305 fprintf(stderr, "Cannot find armature for node %s\n", get_joint_name(animated.node)); 00306 return true; 00307 } 00308 00309 armature_importer->get_rna_path_for_joint(animated.node, joint_path, sizeof(joint_path)); 00310 00311 is_joint = true; 00312 } 00313 00314 const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings(); 00315 00316 switch (animated.tm->getTransformationType()) { 00317 case COLLADAFW::Transformation::TRANSLATE: 00318 case COLLADAFW::Transformation::SCALE: 00319 { 00320 bool loc = animated.tm->getTransformationType() == COLLADAFW::Transformation::TRANSLATE; 00321 if (is_joint) 00322 BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, loc ? "location" : "scale"); 00323 else 00324 BLI_strncpy(rna_path, loc ? "location" : "scale", sizeof(rna_path)); 00325 00326 for (int i = 0; i < bindings.getCount(); i++) { 00327 const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[i]; 00328 COLLADAFW::UniqueId anim_uid = binding.animation; 00329 00330 if (curve_map.find(anim_uid) == curve_map.end()) { 00331 fprintf(stderr, "Cannot find FCurve by animation UID.\n"); 00332 continue; 00333 } 00334 00335 std::vector<FCurve*>& fcurves = curve_map[anim_uid]; 00336 00337 switch (binding.animationClass) { 00338 case COLLADAFW::AnimationList::POSITION_X: 00339 add_fcurves_to_object(ob, fcurves, rna_path, 0, &animated); 00340 break; 00341 case COLLADAFW::AnimationList::POSITION_Y: 00342 add_fcurves_to_object(ob, fcurves, rna_path, 1, &animated); 00343 break; 00344 case COLLADAFW::AnimationList::POSITION_Z: 00345 add_fcurves_to_object(ob, fcurves, rna_path, 2, &animated); 00346 break; 00347 case COLLADAFW::AnimationList::POSITION_XYZ: 00348 add_fcurves_to_object(ob, fcurves, rna_path, -1, &animated); 00349 break; 00350 default: 00351 fprintf(stderr, "AnimationClass %d is not supported for %s.\n", 00352 binding.animationClass, loc ? "TRANSLATE" : "SCALE"); 00353 } 00354 } 00355 } 00356 break; 00357 case COLLADAFW::Transformation::ROTATE: 00358 { 00359 if (is_joint) 00360 BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_euler", joint_path); 00361 else 00362 BLI_strncpy(rna_path, "rotation_euler", sizeof(rna_path)); 00363 00364 COLLADAFW::Rotate* rot = (COLLADAFW::Rotate*)animated.tm; 00365 COLLADABU::Math::Vector3& axis = rot->getRotationAxis(); 00366 00367 for (int i = 0; i < bindings.getCount(); i++) { 00368 const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[i]; 00369 COLLADAFW::UniqueId anim_uid = binding.animation; 00370 00371 if (curve_map.find(anim_uid) == curve_map.end()) { 00372 fprintf(stderr, "Cannot find FCurve by animation UID.\n"); 00373 continue; 00374 } 00375 00376 std::vector<FCurve*>& fcurves = curve_map[anim_uid]; 00377 00378 switch (binding.animationClass) { 00379 case COLLADAFW::AnimationList::ANGLE: 00380 if (COLLADABU::Math::Vector3::UNIT_X == axis) { 00381 add_fcurves_to_object(ob, fcurves, rna_path, 0, &animated); 00382 } 00383 else if (COLLADABU::Math::Vector3::UNIT_Y == axis) { 00384 add_fcurves_to_object(ob, fcurves, rna_path, 1, &animated); 00385 } 00386 else if (COLLADABU::Math::Vector3::UNIT_Z == axis) { 00387 add_fcurves_to_object(ob, fcurves, rna_path, 2, &animated); 00388 } 00389 break; 00390 case COLLADAFW::AnimationList::AXISANGLE: 00391 // TODO convert axis-angle to quat? or XYZ? 00392 default: 00393 fprintf(stderr, "AnimationClass %d is not supported for ROTATE transformation.\n", 00394 binding.animationClass); 00395 } 00396 } 00397 } 00398 break; 00399 case COLLADAFW::Transformation::MATRIX: 00400 case COLLADAFW::Transformation::SKEW: 00401 case COLLADAFW::Transformation::LOOKAT: 00402 fprintf(stderr, "Animation of MATRIX, SKEW and LOOKAT transformations is not supported yet.\n"); 00403 break; 00404 } 00405 #endif 00406 00407 return true; 00408 } 00409 00410 // \todo refactor read_node_transform to not automatically apply anything, 00411 // but rather return the transform matrix, so caller can do with it what is 00412 // necessary. Same for \ref get_node_mat 00413 void AnimationImporter::read_node_transform(COLLADAFW::Node *node, Object *ob) 00414 { 00415 float mat[4][4]; 00416 TransformReader::get_node_mat(mat, node, &uid_animated_map, ob); 00417 if (ob) { 00418 copy_m4_m4(ob->obmat, mat); 00419 object_apply_mat4(ob, ob->obmat, 0, 0); 00420 } 00421 } 00422 00423 #if 0 00424 virtual void AnimationImporter::change_eul_to_quat(Object *ob, bAction *act) 00425 { 00426 bActionGroup *grp; 00427 int i; 00428 00429 for (grp = (bActionGroup*)act->groups.first; grp; grp = grp->next) { 00430 00431 FCurve *eulcu[3] = {NULL, NULL, NULL}; 00432 00433 if (fcurves_actionGroup_map.find(grp) == fcurves_actionGroup_map.end()) 00434 continue; 00435 00436 std::vector<FCurve*> &rot_fcurves = fcurves_actionGroup_map[grp]; 00437 00438 if (rot_fcurves.size() > 3) continue; 00439 00440 for (i = 0; i < rot_fcurves.size(); i++) 00441 eulcu[rot_fcurves[i]->array_index] = rot_fcurves[i]; 00442 00443 char joint_path[100]; 00444 char rna_path[100]; 00445 00446 BLI_snprintf(joint_path, sizeof(joint_path), "pose.bones[\"%s\"]", grp->name); 00447 BLI_snprintf(rna_path, sizeof(rna_path), "%s.rotation_quaternion", joint_path); 00448 00449 FCurve *quatcu[4] = { 00450 create_fcurve(0, rna_path), 00451 create_fcurve(1, rna_path), 00452 create_fcurve(2, rna_path), 00453 create_fcurve(3, rna_path) 00454 }; 00455 00456 bPoseChannel *chan = get_pose_channel(ob->pose, grp->name); 00457 00458 float m4[4][4], irest[3][3]; 00459 invert_m4_m4(m4, chan->bone->arm_mat); 00460 copy_m3_m4(irest, m4); 00461 00462 for (i = 0; i < 3; i++) { 00463 00464 FCurve *cu = eulcu[i]; 00465 00466 if (!cu) continue; 00467 00468 for (int j = 0; j < cu->totvert; j++) { 00469 float frame = cu->bezt[j].vec[1][0]; 00470 00471 float eul[3] = { 00472 eulcu[0] ? evaluate_fcurve(eulcu[0], frame) : 0.0f, 00473 eulcu[1] ? evaluate_fcurve(eulcu[1], frame) : 0.0f, 00474 eulcu[2] ? evaluate_fcurve(eulcu[2], frame) : 0.0f 00475 }; 00476 00477 // make eul relative to bone rest pose 00478 float rot[3][3], rel[3][3], quat[4]; 00479 00480 /*eul_to_mat3(rot, eul); 00481 00482 mul_m3_m3m3(rel, irest, rot); 00483 00484 mat3_to_quat(quat, rel); 00485 */ 00486 00487 eul_to_quat(quat, eul); 00488 00489 for (int k = 0; k < 4; k++) 00490 create_bezt(quatcu[k], frame, quat[k]); 00491 } 00492 } 00493 00494 // now replace old Euler curves 00495 00496 for (i = 0; i < 3; i++) { 00497 if (!eulcu[i]) continue; 00498 00499 action_groups_remove_channel(act, eulcu[i]); 00500 free_fcurve(eulcu[i]); 00501 } 00502 00503 chan->rotmode = ROT_MODE_QUAT; 00504 00505 for (i = 0; i < 4; i++) 00506 action_groups_add_channel(act, grp, quatcu[i]); 00507 } 00508 00509 bPoseChannel *pchan; 00510 for (pchan = (bPoseChannel*)ob->pose->chanbase.first; pchan; pchan = pchan->next) { 00511 pchan->rotmode = ROT_MODE_QUAT; 00512 } 00513 } 00514 #endif 00515 00516 // prerequisites: 00517 // animlist_map - map animlist id -> animlist 00518 // curve_map - map anim id -> curve(s) 00519 Object *AnimationImporter::translate_animation(COLLADAFW::Node *node, 00520 std::map<COLLADAFW::UniqueId, Object*>& object_map, 00521 std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& root_map, 00522 COLLADAFW::Transformation::TransformationType tm_type, 00523 Object *par_job) 00524 { 00525 bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE; 00526 bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX; 00527 bool is_joint = node->getType() == COLLADAFW::Node::JOINT; 00528 00529 COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ? node : root_map[node->getUniqueId()]; 00530 Object *ob = is_joint ? armature_importer->get_armature_for_joint(node) : object_map[node->getUniqueId()]; 00531 const char *bone_name = is_joint ? bc_get_joint_name(node) : NULL; 00532 00533 if (!ob) { 00534 fprintf(stderr, "cannot find Object for Node with id=\"%s\"\n", node->getOriginalId().c_str()); 00535 return NULL; 00536 } 00537 00538 // frames at which to sample 00539 std::vector<float> frames; 00540 00541 // for each <rotate>, <translate>, etc. there is a separate Transformation 00542 const COLLADAFW::TransformationPointerArray& tms = node->getTransformations(); 00543 00544 unsigned int i; 00545 00546 // find frames at which to sample plus convert all rotation keys to radians 00547 for (i = 0; i < tms.getCount(); i++) { 00548 COLLADAFW::Transformation *tm = tms[i]; 00549 COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); 00550 00551 if (type == tm_type) { 00552 const COLLADAFW::UniqueId& listid = tm->getAnimationList(); 00553 00554 if (animlist_map.find(listid) != animlist_map.end()) { 00555 const COLLADAFW::AnimationList *animlist = animlist_map[listid]; 00556 const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings(); 00557 00558 if (bindings.getCount()) { 00559 for (unsigned int j = 0; j < bindings.getCount(); j++) { 00560 std::vector<FCurve*>& curves = curve_map[bindings[j].animation]; 00561 bool xyz = ((type == COLLADAFW::Transformation::TRANSLATE || type == COLLADAFW::Transformation::SCALE) && bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ); 00562 00563 if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3) || is_matrix) { 00564 std::vector<FCurve*>::iterator iter; 00565 00566 for (iter = curves.begin(); iter != curves.end(); iter++) { 00567 FCurve *fcu = *iter; 00568 00569 if (is_rotation) 00570 fcurve_deg_to_rad(fcu); 00571 00572 for (unsigned int k = 0; k < fcu->totvert; k++) { 00573 float fra = fcu->bezt[k].vec[1][0]; 00574 if (std::find(frames.begin(), frames.end(), fra) == frames.end()) 00575 frames.push_back(fra); 00576 } 00577 } 00578 } 00579 else { 00580 fprintf(stderr, "expected %d curves, got %d\n", xyz ? 3 : 1, (int)curves.size()); 00581 } 00582 } 00583 } 00584 } 00585 } 00586 } 00587 00588 float irest_dae[4][4]; 00589 float rest[4][4], irest[4][4]; 00590 00591 if (is_joint) { 00592 get_joint_rest_mat(irest_dae, root, node); 00593 invert_m4(irest_dae); 00594 00595 Bone *bone = get_named_bone((bArmature*)ob->data, bone_name); 00596 if (!bone) { 00597 fprintf(stderr, "cannot find bone \"%s\"\n", bone_name); 00598 return NULL; 00599 } 00600 00601 unit_m4(rest); 00602 copy_m4_m4(rest, bone->arm_mat); 00603 invert_m4_m4(irest, rest); 00604 } 00605 00606 Object *job = NULL; 00607 00608 #ifdef ARMATURE_TEST 00609 FCurve *job_curves[10]; 00610 job = get_joint_object(root, node, par_job); 00611 #endif 00612 00613 if (frames.size() == 0) 00614 return job; 00615 00616 std::sort(frames.begin(), frames.end()); 00617 00618 const char *tm_str = NULL; 00619 switch (tm_type) { 00620 case COLLADAFW::Transformation::ROTATE: 00621 tm_str = "rotation_quaternion"; 00622 break; 00623 case COLLADAFW::Transformation::SCALE: 00624 tm_str = "scale"; 00625 break; 00626 case COLLADAFW::Transformation::TRANSLATE: 00627 tm_str = "location"; 00628 break; 00629 case COLLADAFW::Transformation::MATRIX: 00630 break; 00631 default: 00632 return job; 00633 } 00634 00635 char rna_path[200]; 00636 char joint_path[200]; 00637 00638 if (is_joint) 00639 armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path)); 00640 00641 // new curves 00642 FCurve *newcu[10]; // if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale 00643 unsigned int totcu = is_matrix ? 10 : (is_rotation ? 4 : 3); 00644 00645 for (i = 0; i < totcu; i++) { 00646 00647 int axis = i; 00648 00649 if (is_matrix) { 00650 if (i < 4) { 00651 tm_str = "rotation_quaternion"; 00652 axis = i; 00653 } 00654 else if (i < 7) { 00655 tm_str = "location"; 00656 axis = i - 4; 00657 } 00658 else { 00659 tm_str = "scale"; 00660 axis = i - 7; 00661 } 00662 } 00663 00664 if (is_joint) 00665 BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str); 00666 else 00667 strcpy(rna_path, tm_str); 00668 00669 newcu[i] = create_fcurve(axis, rna_path); 00670 00671 #ifdef ARMATURE_TEST 00672 if (is_joint) 00673 job_curves[i] = create_fcurve(axis, tm_str); 00674 #endif 00675 } 00676 00677 std::vector<float>::iterator it; 00678 00679 // sample values at each frame 00680 for (it = frames.begin(); it != frames.end(); it++) { 00681 float fra = *it; 00682 00683 float mat[4][4]; 00684 float matfra[4][4]; 00685 00686 unit_m4(matfra); 00687 00688 // calc object-space mat 00689 evaluate_transform_at_frame(matfra, node, fra); 00690 00691 // for joints, we need a special matrix 00692 if (is_joint) { 00693 // special matrix: iR * M * iR_dae * R 00694 // where R, iR are bone rest and inverse rest mats in world space (Blender bones), 00695 // iR_dae is joint inverse rest matrix (DAE) and M is an evaluated joint world-space matrix (DAE) 00696 float temp[4][4], par[4][4]; 00697 00698 // calc M 00699 calc_joint_parent_mat_rest(par, NULL, root, node); 00700 mul_m4_m4m4(temp, matfra, par); 00701 00702 // evaluate_joint_world_transform_at_frame(temp, NULL, , node, fra); 00703 00704 // calc special matrix 00705 mul_serie_m4(mat, irest, temp, irest_dae, rest, NULL, NULL, NULL, NULL); 00706 } 00707 else { 00708 copy_m4_m4(mat, matfra); 00709 } 00710 00711 float val[4], rot[4], loc[3], scale[3]; 00712 00713 switch (tm_type) { 00714 case COLLADAFW::Transformation::ROTATE: 00715 mat4_to_quat(val, mat); 00716 break; 00717 case COLLADAFW::Transformation::SCALE: 00718 mat4_to_size(val, mat); 00719 break; 00720 case COLLADAFW::Transformation::TRANSLATE: 00721 copy_v3_v3(val, mat[3]); 00722 break; 00723 case COLLADAFW::Transformation::MATRIX: 00724 mat4_to_quat(rot, mat); 00725 copy_v3_v3(loc, mat[3]); 00726 mat4_to_size(scale, mat); 00727 break; 00728 default: 00729 break; 00730 } 00731 00732 // add keys 00733 for (i = 0; i < totcu; i++) { 00734 if (is_matrix) { 00735 if (i < 4) 00736 add_bezt(newcu[i], fra, rot[i]); 00737 else if (i < 7) 00738 add_bezt(newcu[i], fra, loc[i - 4]); 00739 else 00740 add_bezt(newcu[i], fra, scale[i - 7]); 00741 } 00742 else { 00743 add_bezt(newcu[i], fra, val[i]); 00744 } 00745 } 00746 00747 #ifdef ARMATURE_TEST 00748 if (is_joint) { 00749 switch (tm_type) { 00750 case COLLADAFW::Transformation::ROTATE: 00751 mat4_to_quat(val, matfra); 00752 break; 00753 case COLLADAFW::Transformation::SCALE: 00754 mat4_to_size(val, matfra); 00755 break; 00756 case COLLADAFW::Transformation::TRANSLATE: 00757 copy_v3_v3(val, matfra[3]); 00758 break; 00759 case MATRIX: 00760 mat4_to_quat(rot, matfra); 00761 copy_v3_v3(loc, matfra[3]); 00762 mat4_to_size(scale, matfra); 00763 break; 00764 default: 00765 break; 00766 } 00767 00768 for (i = 0; i < totcu; i++) { 00769 if (is_matrix) { 00770 if (i < 4) 00771 add_bezt(job_curves[i], fra, rot[i]); 00772 else if (i < 7) 00773 add_bezt(job_curves[i], fra, loc[i - 4]); 00774 else 00775 add_bezt(job_curves[i], fra, scale[i - 7]); 00776 } 00777 else { 00778 add_bezt(job_curves[i], fra, val[i]); 00779 } 00780 } 00781 } 00782 #endif 00783 } 00784 00785 verify_adt_action((ID*)&ob->id, 1); 00786 00787 ListBase *curves = &ob->adt->action->curves; 00788 00789 // add curves 00790 for (i = 0; i < totcu; i++) { 00791 if (is_joint) 00792 add_bone_fcurve(ob, node, newcu[i]); 00793 else 00794 BLI_addtail(curves, newcu[i]); 00795 00796 #ifdef ARMATURE_TEST 00797 if (is_joint) 00798 BLI_addtail(&job->adt->action->curves, job_curves[i]); 00799 #endif 00800 } 00801 00802 if (is_rotation || is_matrix) { 00803 if (is_joint) { 00804 bPoseChannel *chan = get_pose_channel(ob->pose, bone_name); 00805 chan->rotmode = ROT_MODE_QUAT; 00806 } 00807 else { 00808 ob->rotmode = ROT_MODE_QUAT; 00809 } 00810 } 00811 00812 return job; 00813 } 00814 00815 // internal, better make it private 00816 // warning: evaluates only rotation 00817 // prerequisites: animlist_map, curve_map 00818 void AnimationImporter::evaluate_transform_at_frame(float mat[4][4], COLLADAFW::Node *node, float fra) 00819 { 00820 const COLLADAFW::TransformationPointerArray& tms = node->getTransformations(); 00821 00822 unit_m4(mat); 00823 00824 for (unsigned int i = 0; i < tms.getCount(); i++) { 00825 COLLADAFW::Transformation *tm = tms[i]; 00826 COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); 00827 float m[4][4]; 00828 00829 unit_m4(m); 00830 00831 std::string nodename = node->getName().size() ? node->getName() : node->getOriginalId(); 00832 if (!evaluate_animation(tm, m, fra, nodename.c_str())) { 00833 switch (type) { 00834 case COLLADAFW::Transformation::ROTATE: 00835 dae_rotate_to_mat4(tm, m); 00836 break; 00837 case COLLADAFW::Transformation::TRANSLATE: 00838 dae_translate_to_mat4(tm, m); 00839 break; 00840 case COLLADAFW::Transformation::SCALE: 00841 dae_scale_to_mat4(tm, m); 00842 break; 00843 case COLLADAFW::Transformation::MATRIX: 00844 dae_matrix_to_mat4(tm, m); 00845 break; 00846 default: 00847 fprintf(stderr, "unsupported transformation type %d\n", type); 00848 } 00849 } 00850 00851 float temp[4][4]; 00852 copy_m4_m4(temp, mat); 00853 00854 mul_m4_m4m4(mat, m, temp); 00855 } 00856 } 00857 00858 // return true to indicate that mat contains a sane value 00859 bool AnimationImporter::evaluate_animation(COLLADAFW::Transformation *tm, float mat[4][4], float fra, const char *node_id) 00860 { 00861 const COLLADAFW::UniqueId& listid = tm->getAnimationList(); 00862 COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); 00863 00864 if (type != COLLADAFW::Transformation::ROTATE && 00865 type != COLLADAFW::Transformation::SCALE && 00866 type != COLLADAFW::Transformation::TRANSLATE && 00867 type != COLLADAFW::Transformation::MATRIX) { 00868 fprintf(stderr, "animation of transformation %d is not supported yet\n", type); 00869 return false; 00870 } 00871 00872 if (animlist_map.find(listid) == animlist_map.end()) 00873 return false; 00874 00875 const COLLADAFW::AnimationList *animlist = animlist_map[listid]; 00876 const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings(); 00877 00878 if (bindings.getCount()) { 00879 float vec[3]; 00880 00881 bool is_scale = (type == COLLADAFW::Transformation::SCALE); 00882 bool is_translate = (type == COLLADAFW::Transformation::TRANSLATE); 00883 00884 if (type == COLLADAFW::Transformation::SCALE) 00885 dae_scale_to_v3(tm, vec); 00886 else if (type == COLLADAFW::Transformation::TRANSLATE) 00887 dae_translate_to_v3(tm, vec); 00888 00889 for (unsigned int j = 0; j < bindings.getCount(); j++) { 00890 const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[j]; 00891 std::vector<FCurve*>& curves = curve_map[binding.animation]; 00892 COLLADAFW::AnimationList::AnimationClass animclass = binding.animationClass; 00893 char path[100]; 00894 00895 switch (type) { 00896 case COLLADAFW::Transformation::ROTATE: 00897 BLI_snprintf(path, sizeof(path), "%s.rotate (binding %u)", node_id, j); 00898 break; 00899 case COLLADAFW::Transformation::SCALE: 00900 BLI_snprintf(path, sizeof(path), "%s.scale (binding %u)", node_id, j); 00901 break; 00902 case COLLADAFW::Transformation::TRANSLATE: 00903 BLI_snprintf(path, sizeof(path), "%s.translate (binding %u)", node_id, j); 00904 break; 00905 case COLLADAFW::Transformation::MATRIX: 00906 BLI_snprintf(path, sizeof(path), "%s.matrix (binding %u)", node_id, j); 00907 break; 00908 default: 00909 break; 00910 } 00911 00912 if (animclass == COLLADAFW::AnimationList::UNKNOWN_CLASS) { 00913 fprintf(stderr, "%s: UNKNOWN animation class\n", path); 00914 continue; 00915 } 00916 00917 if (type == COLLADAFW::Transformation::ROTATE) { 00918 if (curves.size() != 1) { 00919 fprintf(stderr, "expected 1 curve, got %d\n", (int)curves.size()); 00920 return false; 00921 } 00922 00923 // TODO support other animclasses 00924 if (animclass != COLLADAFW::AnimationList::ANGLE) { 00925 fprintf(stderr, "%s: animation class %d is not supported yet\n", path, animclass); 00926 return false; 00927 } 00928 00929 COLLADABU::Math::Vector3& axis = ((COLLADAFW::Rotate*)tm)->getRotationAxis(); 00930 float ax[3] = {axis[0], axis[1], axis[2]}; 00931 float angle = evaluate_fcurve(curves[0], fra); 00932 axis_angle_to_mat4(mat, ax, angle); 00933 00934 return true; 00935 } 00936 else if (is_scale || is_translate) { 00937 bool is_xyz = animclass == COLLADAFW::AnimationList::POSITION_XYZ; 00938 00939 if ((!is_xyz && curves.size() != 1) || (is_xyz && curves.size() != 3)) { 00940 if (is_xyz) 00941 fprintf(stderr, "%s: expected 3 curves, got %d\n", path, (int)curves.size()); 00942 else 00943 fprintf(stderr, "%s: expected 1 curve, got %d\n", path, (int)curves.size()); 00944 return false; 00945 } 00946 00947 switch (animclass) { 00948 case COLLADAFW::AnimationList::POSITION_X: 00949 vec[0] = evaluate_fcurve(curves[0], fra); 00950 break; 00951 case COLLADAFW::AnimationList::POSITION_Y: 00952 vec[1] = evaluate_fcurve(curves[0], fra); 00953 break; 00954 case COLLADAFW::AnimationList::POSITION_Z: 00955 vec[2] = evaluate_fcurve(curves[0], fra); 00956 break; 00957 case COLLADAFW::AnimationList::POSITION_XYZ: 00958 vec[0] = evaluate_fcurve(curves[0], fra); 00959 vec[1] = evaluate_fcurve(curves[1], fra); 00960 vec[2] = evaluate_fcurve(curves[2], fra); 00961 break; 00962 default: 00963 fprintf(stderr, "%s: animation class %d is not supported yet\n", path, animclass); 00964 break; 00965 } 00966 } 00967 else if (type == COLLADAFW::Transformation::MATRIX) { 00968 // for now, of matrix animation, support only the case when all values are packed into one animation 00969 if (curves.size() != 16) { 00970 fprintf(stderr, "%s: expected 16 curves, got %d\n", path, (int)curves.size()); 00971 return false; 00972 } 00973 00974 COLLADABU::Math::Matrix4 matrix; 00975 int i = 0, j = 0; 00976 00977 for (std::vector<FCurve*>::iterator it = curves.begin(); it != curves.end(); it++) { 00978 matrix.setElement(i, j, evaluate_fcurve(*it, fra)); 00979 j++; 00980 if (j == 4) { 00981 i++; 00982 j = 0; 00983 } 00984 } 00985 00986 COLLADAFW::Matrix tm(matrix); 00987 dae_matrix_to_mat4(&tm, mat); 00988 00989 return true; 00990 } 00991 } 00992 00993 if (is_scale) 00994 size_to_mat4(mat, vec); 00995 else 00996 copy_v3_v3(mat[3], vec); 00997 00998 return is_scale || is_translate; 00999 } 01000 01001 return false; 01002 } 01003 01004 // gives a world-space mat of joint at rest position 01005 void AnimationImporter::get_joint_rest_mat(float mat[4][4], COLLADAFW::Node *root, COLLADAFW::Node *node) 01006 { 01007 // if bind mat is not available, 01008 // use "current" node transform, i.e. all those tms listed inside <node> 01009 if (!armature_importer->get_joint_bind_mat(mat, node)) { 01010 float par[4][4], m[4][4]; 01011 01012 calc_joint_parent_mat_rest(par, NULL, root, node); 01013 get_node_mat(m, node, NULL, NULL); 01014 mul_m4_m4m4(mat, m, par); 01015 } 01016 } 01017 01018 // gives a world-space mat, end's mat not included 01019 bool AnimationImporter::calc_joint_parent_mat_rest(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end) 01020 { 01021 float m[4][4]; 01022 01023 if (node == end) { 01024 par ? copy_m4_m4(mat, par) : unit_m4(mat); 01025 return true; 01026 } 01027 01028 // use bind matrix if available or calc "current" world mat 01029 if (!armature_importer->get_joint_bind_mat(m, node)) { 01030 if (par) { 01031 float temp[4][4]; 01032 get_node_mat(temp, node, NULL, NULL); 01033 mul_m4_m4m4(m, temp, par); 01034 } 01035 else { 01036 get_node_mat(m, node, NULL, NULL); 01037 } 01038 } 01039 01040 COLLADAFW::NodePointerArray& children = node->getChildNodes(); 01041 for (unsigned int i = 0; i < children.getCount(); i++) { 01042 if (calc_joint_parent_mat_rest(mat, m, children[i], end)) 01043 return true; 01044 } 01045 01046 return false; 01047 } 01048 01049 #ifdef ARMATURE_TEST 01050 Object *AnimationImporter::get_joint_object(COLLADAFW::Node *root, COLLADAFW::Node *node, Object *par_job) 01051 { 01052 if (joint_objects.find(node->getUniqueId()) == joint_objects.end()) { 01053 Object *job = add_object(scene, OB_EMPTY); 01054 01055 rename_id((ID*)&job->id, (char*)get_joint_name(node)); 01056 01057 job->lay = object_in_scene(job, scene)->lay = 2; 01058 01059 mul_v3_fl(job->size, 0.5f); 01060 job->recalc |= OB_RECALC_OB; 01061 01062 verify_adt_action((ID*)&job->id, 1); 01063 01064 job->rotmode = ROT_MODE_QUAT; 01065 01066 float mat[4][4]; 01067 get_joint_rest_mat(mat, root, node); 01068 01069 if (par_job) { 01070 float temp[4][4], ipar[4][4]; 01071 invert_m4_m4(ipar, par_job->obmat); 01072 copy_m4_m4(temp, mat); 01073 mul_m4_m4m4(mat, temp, ipar); 01074 } 01075 01076 TransformBase::decompose(mat, job->loc, NULL, job->quat, job->size); 01077 01078 if (par_job) { 01079 job->parent = par_job; 01080 01081 par_job->recalc |= OB_RECALC_OB; 01082 job->parsubstr[0] = 0; 01083 } 01084 01085 where_is_object(scene, job); 01086 01087 // after parenting and layer change 01088 DAG_scene_sort(CTX_data_main(C), scene); 01089 01090 joint_objects[node->getUniqueId()] = job; 01091 } 01092 01093 return joint_objects[node->getUniqueId()]; 01094 } 01095 #endif 01096 01097 #if 0 01098 // recursively evaluates joint tree until end is found, mat then is world-space matrix of end 01099 // mat must be identity on enter, node must be root 01100 bool AnimationImporter::evaluate_joint_world_transform_at_frame(float mat[4][4], float par[4][4], COLLADAFW::Node *node, COLLADAFW::Node *end, float fra) 01101 { 01102 float m[4][4]; 01103 if (par) { 01104 float temp[4][4]; 01105 evaluate_transform_at_frame(temp, node, node == end ? fra : 0.0f); 01106 mul_m4_m4m4(m, temp, par); 01107 } 01108 else { 01109 evaluate_transform_at_frame(m, node, node == end ? fra : 0.0f); 01110 } 01111 01112 if (node == end) { 01113 copy_m4_m4(mat, m); 01114 return true; 01115 } 01116 else { 01117 COLLADAFW::NodePointerArray& children = node->getChildNodes(); 01118 for (int i = 0; i < children.getCount(); i++) { 01119 if (evaluate_joint_world_transform_at_frame(mat, m, children[i], end, fra)) 01120 return true; 01121 } 01122 } 01123 01124 return false; 01125 } 01126 #endif 01127 01128 void AnimationImporter::add_bone_fcurve(Object *ob, COLLADAFW::Node *node, FCurve *fcu) 01129 { 01130 const char *bone_name = bc_get_joint_name(node); 01131 bAction *act = ob->adt->action; 01132 01133 /* try to find group */ 01134 bActionGroup *grp = action_groups_find_named(act, bone_name); 01135 01136 /* no matching groups, so add one */ 01137 if (grp == NULL) { 01138 /* Add a new group, and make it active */ 01139 grp = (bActionGroup*)MEM_callocN(sizeof(bActionGroup), "bActionGroup"); 01140 01141 grp->flag = AGRP_SELECTED; 01142 BLI_strncpy(grp->name, bone_name, sizeof(grp->name)); 01143 01144 BLI_addtail(&act->groups, grp); 01145 BLI_uniquename(&act->groups, grp, "Group", '.', offsetof(bActionGroup, name), 64); 01146 } 01147 01148 /* add F-Curve to group */ 01149 action_groups_add_channel(act, grp, fcu); 01150 } 01151 01152 void AnimationImporter::add_bezt(FCurve *fcu, float fra, float value) 01153 { 01154 BezTriple bez; 01155 memset(&bez, 0, sizeof(BezTriple)); 01156 bez.vec[1][0] = fra; 01157 bez.vec[1][1] = value; 01158 bez.ipo = U.ipo_new; /* use default interpolation mode here... */ 01159 bez.f1 = bez.f2 = bez.f3 = SELECT; 01160 bez.h1 = bez.h2 = HD_AUTO; 01161 insert_bezt_fcurve(fcu, &bez, 0); 01162 calchandles_fcurve(fcu); 01163 }