diff options
Diffstat (limited to 'source/blender/collada/DocumentImporter.cpp')
-rw-r--r-- | source/blender/collada/DocumentImporter.cpp | 524 |
1 files changed, 344 insertions, 180 deletions
diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 495b600f9ae..fd4c31621c8 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -174,6 +174,59 @@ static float get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigne return array.getDoubleValues()->getData()[index]; } +// copied from /editors/object/object_relations.c +static int test_parent_loop(Object *par, Object *ob) +{ + /* test if 'ob' is a parent somewhere in par's parents */ + + if(par == NULL) return 0; + if(ob == par) return 1; + + return test_parent_loop(par->parent, ob); +} + +// a shortened version of parent_set_exec() +// if is_parent_space is true then ob->obmat will be multiplied by par->obmat before parenting +static int set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space=true) +{ + if (!par || test_parent_loop(par, ob)) + return false; + + Object workob; + Scene *sce = CTX_data_scene(C); + + ob->parent = par; + ob->partype = PAROBJECT; + + ob->parsubstr[0] = 0; + + if (is_parent_space) { + // calc par->obmat + where_is_object(sce, par); + + // move child obmat into world space + float mat[4][4]; + mul_m4_m4m4(mat, ob->obmat, par->obmat); + copy_m4_m4(ob->obmat, mat); + } + + // apply child obmat (i.e. decompose it into rot/loc/size) + object_apply_mat4(ob, ob->obmat); + + // compute parentinv + what_does_parent(sce, ob, &workob); + invert_m4_m4(ob->parentinv, workob.obmat); + + ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA; + par->recalc |= OB_RECALC_OB; + + DAG_scene_sort(sce); + DAG_ids_flush_update(0); + WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); + + return true; +} + typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex*> > TexIndexTextureArrayMap; class TransformReader : public TransformBase @@ -341,6 +394,7 @@ private: std::map<COLLADAFW::UniqueId, COLLADAFW::UniqueId> geom_uid_by_controller_uid; std::map<COLLADAFW::UniqueId, COLLADAFW::Node*> joint_by_uid; // contains all joints std::vector<COLLADAFW::Node*> root_joints; + std::map<COLLADAFW::UniqueId, Object*> joint_parent_map; std::vector<Object*> armature_objects; @@ -375,6 +429,7 @@ private: Object *ob_arm; COLLADAFW::UniqueId controller_uid; + Object *parent; public: @@ -384,7 +439,8 @@ private: joint_data(skin.joint_data), unit_converter(skin.unit_converter), ob_arm(skin.ob_arm), - controller_uid(skin.controller_uid) + controller_uid(skin.controller_uid), + parent(skin.parent) { copy_m4_m4(bind_shape_matrix, (float (*)[4])skin.bind_shape_matrix); @@ -393,7 +449,7 @@ private: transfer_int_array_data_const(skin.joint_indices, joint_indices); } - SkinInfo(UnitConverter *conv) : unit_converter(conv), ob_arm(NULL) {} + SkinInfo(UnitConverter *conv) : unit_converter(conv), ob_arm(NULL), parent(NULL) {} // nobody owns the data after this, so it should be freed manually with releaseMemory template <class T> @@ -520,14 +576,17 @@ private: void link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node*>& joint_by_uid, TransformReader *tm) { - Object workob; Scene *scene = CTX_data_scene(C); ModifierData *md = ED_object_modifier_add(NULL, scene, ob, NULL, eModifierType_Armature); ((ArmatureModifierData *)md)->object = ob_arm; - tm->decompose(bind_shape_matrix, ob->loc, ob->rot, NULL, ob->size); - + copy_m4_m4(ob->obmat, bind_shape_matrix); + object_apply_mat4(ob, ob->obmat); +#if 1 + ::set_parent(ob, ob_arm, C); +#else + Object workob; ob->parent = ob_arm; ob->partype = PAROBJECT; @@ -536,6 +595,11 @@ private: ob->recalc |= OB_RECALC_OB|OB_RECALC_DATA; + DAG_scene_sort(scene); + DAG_ids_flush_update(0); + WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); +#endif + ((bArmature*)ob_arm->data)->deformflag = ARM_DEF_VGROUP; // create all vertex groups @@ -577,16 +641,23 @@ private: } } } - - DAG_scene_sort(scene); - DAG_ids_flush_update(0); - WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, NULL); } bPoseChannel *get_pose_channel_from_node(COLLADAFW::Node *node) { return get_pose_channel(ob_arm->pose, get_joint_name(node)); } + + void set_parent(Object *_parent) + { + parent = _parent; + } + + Object* get_parent() + { + return parent; + } + }; std::map<COLLADAFW::UniqueId, SkinInfo> skin_by_data_uid; // data UID = skin controller data UID @@ -856,6 +927,9 @@ private: // since root_joints may contain joints for multiple controllers, we need to filter if (skin.uses_joint(*it)) { create_bone(skin, *it, NULL, (*it)->getChildNodes().getCount(), NULL, (bArmature*)ob_arm->data); + + if (joint_parent_map.find((*it)->getUniqueId()) != joint_parent_map.end() && !skin.get_parent()) + skin.set_parent(joint_parent_map[(*it)->getUniqueId()]); } } @@ -889,10 +963,15 @@ public: // root - if this joint is the top joint in hierarchy, if a joint // is a child of a node (not joint), root should be true since // this is where we build armature bones from - void add_joint(COLLADAFW::Node *node, bool root) + void add_joint(COLLADAFW::Node *node, bool root, Object *parent) { joint_by_uid[node->getUniqueId()] = node; - if (root) root_joints.push_back(node); + if (root) { + root_joints.push_back(node); + + if (parent) + joint_parent_map[node->getUniqueId()] = parent; + } } #if 0 @@ -921,14 +1000,17 @@ public: create_armature_bones(skin); - // link armature with an object + // link armature with a mesh object Object *ob = mesh_importer->get_object_by_geom_uid(*get_geometry_uid(skin.get_controller_uid())); - if (ob) { + if (ob) skin.link_armature(C, ob, joint_by_uid, this); - } - else { + else fprintf(stderr, "Cannot find object to link armature with.\n"); - } + + // set armature parent if any + Object *par = skin.get_parent(); + if (par) + set_parent(skin.get_armature(), par, C, false); // free memory stolen from SkinControllerData skin.free(); @@ -1416,6 +1498,13 @@ private: unsigned int totuvset = mesh->getUVCoords().getInputInfosArray().getCount(); for (i = 0; i < totuvset; i++) { + if (mesh->getUVCoords().getLength(i) == 0) { + totuvset = 0; + break; + } + } + + for (i = 0; i < totuvset; i++) { CustomData_add_layer(&me->fdata, CD_MTFACE, CD_CALLOC, NULL, me->totface); //this->set_layername_map[i] = CustomData_get_layer_name(&me->fdata, CD_MTFACE, i); } @@ -1472,9 +1561,11 @@ private: indices += 3; for (k = 0; k < totuvset; k++) { - // get mtface by face index and uv set index - MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k); - set_face_uv(&mtface[face_index], uvs, k, *index_list_array[k], index, false); + if (!index_list_array.empty() && index_list_array[k]) { + // get mtface by face index and uv set index + MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k); + set_face_uv(&mtface[face_index], uvs, k, *index_list_array[k], index, false); + } } test_index_face(mface, &me->fdata, face_index, 3); @@ -1508,9 +1599,11 @@ private: // it is assumed that all primitives have equal number of UV sets for (k = 0; k < totuvset; k++) { - // get mtface by face index and uv set index - MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k); - set_face_uv(&mtface[face_index], uvs, k, *index_list_array[k], index, mface->v4 != 0); + if (!index_list_array.empty() && index_list_array[k]) { + // get mtface by face index and uv set index + MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, k); + set_face_uv(&mtface[face_index], uvs, k, *index_list_array[k], index, mface->v4 != 0); + } } test_index_face(mface, &me->fdata, face_index, vcount); @@ -1548,9 +1641,11 @@ private: set_face_indices(mface, tri_indices, false); for (unsigned int l = 0; l < totuvset; l++) { - // get mtface by face index and uv set index - MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, l); - set_face_uv(&mtface[face_index], uvs, l, *index_list_array[l], uv_indices); + if (!index_list_array.empty() && index_list_array[l]) { + // get mtface by face index and uv set index + MTFace *mtface = (MTFace*)CustomData_get_layer_n(&me->fdata, CD_MTFACE, l); + set_face_uv(&mtface[face_index], uvs, l, *index_list_array[l], uv_indices); + } } test_index_face(mface, &me->fdata, face_index, 3); @@ -1901,77 +1996,50 @@ private: std::vector<FCurve*>& fcurves = curve_map[curve->getUniqueId()]; - if (dim == 1) { - FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve"); - - fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED); - // fcu->rna_path = BLI_strdupn(path, strlen(path)); - fcu->array_index = 0; - //fcu->totvert = curve->getKeyCount(); - - // create beztriple for each key - for (i = 0; i < curve->getKeyCount(); i++) { - BezTriple bez; - memset(&bez, 0, sizeof(BezTriple)); - - // intangent - // bez.vec[0][0] = get_float_value(intan, i + i) * fps; - // bez.vec[0][1] = get_float_value(intan, i + i + 1); - - // input, output - bez.vec[1][0] = get_float_value(input, i) * fps; - bez.vec[1][1] = get_float_value(output, i); - - // outtangent - // bez.vec[2][0] = get_float_value(outtan, i + i) * fps; - // bez.vec[2][1] = get_float_value(outtan, i + i + 1); - - bez.ipo = U.ipo_new; /* use default interpolation mode here... */ - bez.f1 = bez.f2 = bez.f3 = SELECT; - bez.h1 = bez.h2 = HD_AUTO; - insert_bezt_fcurve(fcu, &bez, 0); - } - - calchandles_fcurve(fcu); - - fcurves.push_back(fcu); - } - else if(dim == 3) { - for (i = 0; i < dim; i++ ) { - FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve"); + switch (dim) { + case 1: // X, Y, Z or angle + case 3: // XYZ + case 16: // matrix + { + for (i = 0; i < dim; i++ ) { + FCurve *fcu = (FCurve*)MEM_callocN(sizeof(FCurve), "FCurve"); - fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED); - // fcu->rna_path = BLI_strdupn(path, strlen(path)); - fcu->array_index = 0; - //fcu->totvert = curve->getKeyCount(); + fcu->flag = (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES|FCURVE_SELECTED); + // fcu->rna_path = BLI_strdupn(path, strlen(path)); + fcu->array_index = 0; + //fcu->totvert = curve->getKeyCount(); - // create beztriple for each key - for (unsigned int j = 0; j < curve->getKeyCount(); j++) { - BezTriple bez; - memset(&bez, 0, sizeof(BezTriple)); - - // intangent - // bez.vec[0][0] = get_float_value(intan, j * 6 + i + i) * fps; - // bez.vec[0][1] = get_float_value(intan, j * 6 + i + i + 1); - - // input, output - bez.vec[1][0] = get_float_value(input, j) * fps; - bez.vec[1][1] = get_float_value(output, j * 3 + i); - - // outtangent - // bez.vec[2][0] = get_float_value(outtan, j * 6 + i + i) * fps; - // bez.vec[2][1] = get_float_value(outtan, j * 6 + i + i + 1); - - bez.ipo = U.ipo_new; /* use default interpolation mode here... */ - bez.f1 = bez.f2 = bez.f3 = SELECT; - bez.h1 = bez.h2 = HD_AUTO; - insert_bezt_fcurve(fcu, &bez, 0); - } + // create beztriple for each key + for (unsigned int j = 0; j < curve->getKeyCount(); j++) { + BezTriple bez; + memset(&bez, 0, sizeof(BezTriple)); + + // intangent + // bez.vec[0][0] = get_float_value(intan, j * 6 + i + i) * fps; + // bez.vec[0][1] = get_float_value(intan, j * 6 + i + i + 1); + + // input, output + bez.vec[1][0] = get_float_value(input, j) * fps; + bez.vec[1][1] = get_float_value(output, j * dim + i); + + // outtangent + // bez.vec[2][0] = get_float_value(outtan, j * 6 + i + i) * fps; + // bez.vec[2][1] = get_float_value(outtan, j * 6 + i + i + 1); + + bez.ipo = U.ipo_new; /* use default interpolation mode here... */ + bez.f1 = bez.f2 = bez.f3 = SELECT; + bez.h1 = bez.h2 = HD_AUTO; + insert_bezt_fcurve(fcu, &bez, 0); + } - calchandles_fcurve(fcu); + calchandles_fcurve(fcu); - fcurves.push_back(fcu); + fcurves.push_back(fcu); + } } + break; + default: + fprintf(stderr, "Output dimension of %d is not yet supported (animation id = %s)\n", dim, curve->getOriginalId().c_str()); } for (std::vector<FCurve*>::iterator it = fcurves.begin(); it != fcurves.end(); it++) @@ -2242,8 +2310,10 @@ public: { float mat[4][4]; TransformReader::get_node_mat(mat, node, &uid_animated_map, ob); - if (ob) - TransformReader::decompose(mat, ob->loc, ob->rot, NULL, ob->size); + if (ob) { + copy_m4_m4(ob->obmat, mat); + object_apply_mat4(ob, ob->obmat); + } } #if 0 @@ -2349,7 +2419,9 @@ public: Object *par_job = NULL) { bool is_rotation = tm_type == COLLADAFW::Transformation::ROTATE; + bool is_matrix = tm_type == COLLADAFW::Transformation::MATRIX; bool is_joint = node->getType() == COLLADAFW::Node::JOINT; + COLLADAFW::Node *root = root_map.find(node->getUniqueId()) == root_map.end() ? node : root_map[node->getUniqueId()]; Object *ob = is_joint ? armature_importer->get_armature_for_joint(node) : object_map[node->getUniqueId()]; const char *bone_name = is_joint ? get_joint_name(node) : NULL; @@ -2367,7 +2439,7 @@ public: unsigned int i; - // find frames at which to sample plus convert all keys to radians + // find frames at which to sample plus convert all rotation keys to radians for (i = 0; i < tms.getCount(); i++) { COLLADAFW::Transformation *tm = tms[i]; COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); @@ -2384,7 +2456,7 @@ public: std::vector<FCurve*>& curves = curve_map[bindings[j].animation]; bool xyz = ((type == COLLADAFW::Transformation::TRANSLATE || type == COLLADAFW::Transformation::SCALE) && bindings[j].animationClass == COLLADAFW::AnimationList::POSITION_XYZ); - if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3)) { + if ((!xyz && curves.size() == 1) || (xyz && curves.size() == 3) || is_matrix) { std::vector<FCurve*>::iterator iter; for (iter = curves.begin(); iter != curves.end(); iter++) { @@ -2409,8 +2481,6 @@ public: } } - sort(frames.begin(), frames.end()); - float irest_dae[4][4]; float rest[4][4], irest[4][4]; @@ -2429,18 +2499,18 @@ public: invert_m4_m4(irest, rest); } - char rna_path[200]; - Object *job = NULL; #ifdef ARMATURE_TEST - FCurve *job_curves[4]; + FCurve *job_curves[10]; job = get_joint_object(root, node, par_job); #endif if (frames.size() == 0) return job; + std::sort(frames.begin(), frames.end()); + const char *tm_str = NULL; switch (tm_type) { case COLLADAFW::Transformation::ROTATE: @@ -2452,29 +2522,51 @@ public: case COLLADAFW::Transformation::TRANSLATE: tm_str = "location"; break; + case COLLADAFW::Transformation::MATRIX: + break; default: return job; } - if (is_joint) { - char joint_path[200]; + char rna_path[200]; + char joint_path[200]; + + if (is_joint) armature_importer->get_rna_path_for_joint(node, joint_path, sizeof(joint_path)); - BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str); - } - else { - strcpy(rna_path, tm_str); - } // new curves - FCurve *newcu[4]; - unsigned int totcu = is_rotation ? 4 : 3; + FCurve *newcu[10]; // if tm_type is matrix, then create 10 curves: 4 rot, 3 loc, 3 scale + unsigned int totcu = is_matrix ? 10 : (is_rotation ? 4 : 3); for (i = 0; i < totcu; i++) { - newcu[i] = create_fcurve(i, rna_path); + + int axis = i; + + if (is_matrix) { + if (i < 4) { + tm_str = "rotation_quaternion"; + axis = i; + } + else if (i < 7) { + tm_str = "location"; + axis = i - 4; + } + else { + tm_str = "scale"; + axis = i - 7; + } + } + + if (is_joint) + BLI_snprintf(rna_path, sizeof(rna_path), "%s.%s", joint_path, tm_str); + else + strcpy(rna_path, tm_str); + + newcu[i] = create_fcurve(axis, rna_path); #ifdef ARMATURE_TEST if (is_joint) - job_curves[i] = create_fcurve(i, tm_str); + job_curves[i] = create_fcurve(axis, tm_str); #endif } @@ -2512,7 +2604,7 @@ public: copy_m4_m4(mat, matfra); } - float val[4]; + float val[4], rot[4], loc[3], scale[3]; switch (tm_type) { case COLLADAFW::Transformation::ROTATE: @@ -2524,13 +2616,28 @@ public: case COLLADAFW::Transformation::TRANSLATE: copy_v3_v3(val, mat[3]); break; + case COLLADAFW::Transformation::MATRIX: + mat4_to_quat(rot, mat); + copy_v3_v3(loc, mat[3]); + mat4_to_size(scale, mat); + break; default: break; } - // add 4 or 3 keys + // add keys for (i = 0; i < totcu; i++) { - add_bezt(newcu[i], fra, val[i]); + if (is_matrix) { + if (i < 4) + add_bezt(newcu[i], fra, rot[i]); + else if (i < 7) + add_bezt(newcu[i], fra, loc[i - 4]); + else + add_bezt(newcu[i], fra, scale[i - 7]); + } + else { + add_bezt(newcu[i], fra, val[i]); + } } #ifdef ARMATURE_TEST @@ -2545,12 +2652,28 @@ public: case COLLADAFW::Transformation::TRANSLATE: copy_v3_v3(val, matfra[3]); break; + case MATRIX: + mat4_to_quat(rot, matfra); + copy_v3_v3(loc, matfra[3]); + mat4_to_size(scale, matfra); + break; default: break; } - for (i = 0; i < totcu; i++) - add_bezt(job_curves[i], fra, val[i]); + for (i = 0; i < totcu; i++) { + if (is_matrix) { + if (i < 4) + add_bezt(job_curves[i], fra, rot[i]); + else if (i < 7) + add_bezt(job_curves[i], fra, loc[i - 4]); + else + add_bezt(job_curves[i], fra, scale[i - 7]); + } + else { + add_bezt(job_curves[i], fra, val[i]); + } + } } #endif } @@ -2572,7 +2695,7 @@ public: #endif } - if (is_rotation) { + if (is_rotation || is_matrix) { if (is_joint) { bPoseChannel *chan = get_pose_channel(ob->pose, bone_name); chan->rotmode = ROT_MODE_QUAT; @@ -2601,7 +2724,7 @@ public: unit_m4(m); - if (!evaluate_animation(tm, m, fra)) { + if (!evaluate_animation(tm, m, fra, node->getOriginalId().c_str())) { switch (type) { case COLLADAFW::Transformation::ROTATE: dae_rotate_to_mat4(tm, m); @@ -2628,13 +2751,15 @@ public: } // return true to indicate that mat contains a sane value - bool evaluate_animation(COLLADAFW::Transformation *tm, float mat[4][4], float fra) + bool evaluate_animation(COLLADAFW::Transformation *tm, float mat[4][4], float fra, const char *node_id) { const COLLADAFW::UniqueId& listid = tm->getAnimationList(); COLLADAFW::Transformation::TransformationType type = tm->getTransformationType(); - if (type != COLLADAFW::Transformation::ROTATE && type != COLLADAFW::Transformation::SCALE && - type != COLLADAFW::Transformation::TRANSLATE) { + if (type != COLLADAFW::Transformation::ROTATE && + type != COLLADAFW::Transformation::SCALE && + type != COLLADAFW::Transformation::TRANSLATE && + type != COLLADAFW::Transformation::MATRIX) { fprintf(stderr, "animation of transformation %d is not supported yet\n", type); return false; } @@ -2649,6 +2774,7 @@ public: float vec[3]; bool is_scale = (type == COLLADAFW::Transformation::SCALE); + bool is_translate = (type == COLLADAFW::Transformation::TRANSLATE); if (type == COLLADAFW::Transformation::SCALE) dae_scale_to_v3(tm, vec); @@ -2659,59 +2785,103 @@ public: const COLLADAFW::AnimationList::AnimationBinding& binding = bindings[j]; std::vector<FCurve*>& curves = curve_map[binding.animation]; COLLADAFW::AnimationList::AnimationClass animclass = binding.animationClass; + char path[100]; + + switch (type) { + case COLLADAFW::Transformation::ROTATE: + BLI_snprintf(path, sizeof(path), "%s.rotate (binding %u)", node_id, j); + break; + case COLLADAFW::Transformation::SCALE: + BLI_snprintf(path, sizeof(path), "%s.scale (binding %u)", node_id, j); + break; + case COLLADAFW::Transformation::TRANSLATE: + BLI_snprintf(path, sizeof(path), "%s.translate (binding %u)", node_id, j); + break; + case COLLADAFW::Transformation::MATRIX: + BLI_snprintf(path, sizeof(path), "%s.matrix (binding %u)", node_id, j); + break; + default: + break; + } + + if (animclass == COLLADAFW::AnimationList::UNKNOWN_CLASS) { + fprintf(stderr, "%s: UNKNOWN animation class\n", path); + continue; + } if (type == COLLADAFW::Transformation::ROTATE) { if (curves.size() != 1) { fprintf(stderr, "expected 1 curve, got %u\n", curves.size()); return false; } - else { - if (animclass == COLLADAFW::AnimationList::ANGLE) { - COLLADABU::Math::Vector3& axis = ((COLLADAFW::Rotate*)tm)->getRotationAxis(); - float ax[3] = {axis[0], axis[1], axis[2]}; - float angle = evaluate_fcurve(curves[0], fra); - axis_angle_to_mat4(mat, ax, angle); - return true; - } - else { - // TODO support other animclasses - fprintf(stderr, "<rotate> animclass %d is not supported yet\n", animclass); - return false; - } + // TODO support other animclasses + if (animclass != COLLADAFW::AnimationList::ANGLE) { + fprintf(stderr, "%s: animation class %d is not supported yet\n", path, animclass); + return false; } + + COLLADABU::Math::Vector3& axis = ((COLLADAFW::Rotate*)tm)->getRotationAxis(); + float ax[3] = {axis[0], axis[1], axis[2]}; + float angle = evaluate_fcurve(curves[0], fra); + axis_angle_to_mat4(mat, ax, angle); + + return true; } - else { + else if (is_scale || is_translate) { bool is_xyz = animclass == COLLADAFW::AnimationList::POSITION_XYZ; - if ((!is_xyz && curves.size() == 1) || (is_xyz && curves.size() == 3)) { - switch (animclass) { - case COLLADAFW::AnimationList::POSITION_X: - vec[0] = evaluate_fcurve(curves[0], fra); - break; - case COLLADAFW::AnimationList::POSITION_Y: - vec[1] = evaluate_fcurve(curves[0], fra); - break; - case COLLADAFW::AnimationList::POSITION_Z: - vec[2] = evaluate_fcurve(curves[0], fra); - break; - case COLLADAFW::AnimationList::POSITION_XYZ: - vec[0] = evaluate_fcurve(curves[0], fra); - vec[1] = evaluate_fcurve(curves[1], fra); - vec[2] = evaluate_fcurve(curves[2], fra); - break; - default: - fprintf(stderr, "<%s> animclass %d is not supported yet\n", is_scale ? "scale" : "translate", animclass); - break; - } - } - else { + if ((!is_xyz && curves.size() != 1) || (is_xyz && curves.size() != 3)) { if (is_xyz) - fprintf(stderr, "expected 3 curves, got %u, animclass=%d\n", curves.size(), animclass); + fprintf(stderr, "%s: expected 3 curves, got %u\n", path, curves.size()); else - fprintf(stderr, "expected 1 curve, got %u, animclass=%d\n", curves.size(), animclass); + fprintf(stderr, "%s: expected 1 curve, got %u\n", path, curves.size()); return false; } + + switch (animclass) { + case COLLADAFW::AnimationList::POSITION_X: + vec[0] = evaluate_fcurve(curves[0], fra); + break; + case COLLADAFW::AnimationList::POSITION_Y: + vec[1] = evaluate_fcurve(curves[0], fra); + break; + case COLLADAFW::AnimationList::POSITION_Z: + vec[2] = evaluate_fcurve(curves[0], fra); + break; + case COLLADAFW::AnimationList::POSITION_XYZ: + vec[0] = evaluate_fcurve(curves[0], fra); + vec[1] = evaluate_fcurve(curves[1], fra); + vec[2] = evaluate_fcurve(curves[2], fra); + break; + default: + fprintf(stderr, "%s: animation class %d is not supported yet\n", path, animclass); + break; + } + } + else if (type == COLLADAFW::Transformation::MATRIX) { + // for now, of matrix animation, support only the case when all values are packed into one animation + if (curves.size() != 16) { + fprintf(stderr, "%s: expected 16 curves, got %u\n", path, curves.size()); + return false; + } + + COLLADABU::Math::Matrix4 matrix; + int i = 0, j = 0; + + for (std::vector<FCurve*>::iterator it = curves.begin(); it != curves.end(); it++) { + matrix.setElement(i, j, evaluate_fcurve(*it, fra)); + j++; + if (j == 4) { + i++; + j = 0; + } + } + + COLLADAFW::Matrix tm(matrix); + dae_matrix_to_mat4(&tm, mat); + + return true; } } @@ -2720,7 +2890,7 @@ public: else copy_v3_v3(mat[3], vec); - return true; + return is_scale || is_translate; } return false; @@ -2997,13 +3167,14 @@ public: COLLADAFW::Transformation::TransformationType types[] = { COLLADAFW::Transformation::ROTATE, COLLADAFW::Transformation::SCALE, - COLLADAFW::Transformation::TRANSLATE + COLLADAFW::Transformation::TRANSLATE, + COLLADAFW::Transformation::MATRIX }; unsigned int i; Object *ob; - for (i = 0; i < 3; i++) + for (i = 0; i < 4; i++) ob = anim_importer.translate_animation(node, object_map, root_map, types[i]); COLLADAFW::NodePointerArray &children = node->getChildNodes(); @@ -3066,13 +3237,10 @@ public: void write_node (COLLADAFW::Node *node, COLLADAFW::Node *parent_node, Scene *sce, Object *par) { Object *ob = NULL; + bool is_joint = node->getType() == COLLADAFW::Node::JOINT; - if (node->getType() == COLLADAFW::Node::JOINT) { - - if (node->getType() == COLLADAFW::Node::JOINT) { - armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT); - } - + if (is_joint) { + armature_importer.add_joint(node, parent_node == NULL || parent_node->getType() != COLLADAFW::Node::JOINT, par); } else { COLLADAFW::InstanceGeometryPointerArray &geom = node->getInstanceGeometries(); @@ -3106,27 +3274,23 @@ public: // XXX empty node may not mean it is empty object, not sure about this else { ob = add_object(sce, OB_EMPTY); + rename_id(&ob->id, (char*)node->getOriginalId().c_str()); } // check if object is not NULL if (!ob) return; - object_map[node->getUniqueId()] = ob; - - // if par was given make this object child of the previous - if (par && ob) { - ob->parent = par; - - // doing what 'set parent' operator does - par->recalc |= OB_RECALC_OB; - ob->parsubstr[0] = 0; - - DAG_scene_sort(sce); - } + object_map[node->getUniqueId()] = ob; } anim_importer.read_node_transform(node, ob); + if (!is_joint) { + // if par was given make this object child of the previous + if (par && ob) + set_parent(ob, par, mContext); + } + // if node has child nodes write them COLLADAFW::NodePointerArray &child_nodes = node->getChildNodes(); for (unsigned int i = 0; i < child_nodes.getCount(); i++) { |