diff options
author | Gaia Clary <gaia.clary@machinimatrix.org> | 2012-08-06 01:35:09 +0400 |
---|---|---|
committer | Gaia Clary <gaia.clary@machinimatrix.org> | 2012-08-06 01:35:09 +0400 |
commit | f8a68d50f7f5c53e0d8f16e0f5553a8e5b5b9c6c (patch) | |
tree | 0f0f12dbad18498c8849c67a8388c76c67c935d0 /source/blender/collada | |
parent | 7d2190b79bf1f57cfc5f9ab9bd51a8660c6ae909 (diff) |
COLLADA: report #32237 fixed Camera exporter and Importer to use correct camera animation data
Diffstat (limited to 'source/blender/collada')
-rw-r--r-- | source/blender/collada/AnimationExporter.cpp | 65 | ||||
-rw-r--r-- | source/blender/collada/AnimationExporter.h | 2 | ||||
-rw-r--r-- | source/blender/collada/AnimationImporter.cpp | 93 | ||||
-rw-r--r-- | source/blender/collada/AnimationImporter.h | 1 |
4 files changed, 146 insertions, 15 deletions
diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index 57829f777c5..0e8ead61437 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -106,7 +106,8 @@ void AnimationExporter::operator()(Object *ob) if ((!strcmp(transformName, "lens")) || (!strcmp(transformName, "ortho_scale")) || - (!strcmp(transformName, "clip_end")) || (!strcmp(transformName, "clip_start"))) + (!strcmp(transformName, "clip_end")) || + (!strcmp(transformName, "clip_start"))) { dae_animation(ob, fcu, transformName, true); } @@ -203,8 +204,10 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa } //axis names for colors - else if (!strcmp(transformName, "color") || !strcmp(transformName, "specular_color") || !strcmp(transformName, "diffuse_color") || - (!strcmp(transformName, "alpha"))) + else if (!strcmp(transformName, "color") || + !strcmp(transformName, "specular_color") || + !strcmp(transformName, "diffuse_color") || + !strcmp(transformName, "alpha")) { const char *axis_names[] = {"R", "G", "B"}; if (fcu->array_index < 3) @@ -212,8 +215,10 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa } //axis names for transforms - else if ((!strcmp(transformName, "location") || !strcmp(transformName, "scale")) || - (!strcmp(transformName, "rotation_euler")) || (!strcmp(transformName, "rotation_quaternion"))) + else if (!strcmp(transformName, "location") || + !strcmp(transformName, "scale") || + !strcmp(transformName, "rotation_euler") || + !strcmp(transformName, "rotation_quaternion")) { const char *axis_names[] = {"X", "Y", "Z"}; if (fcu->array_index < 3) @@ -260,9 +265,13 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa MEM_freeN(eul); MEM_freeN(eul_axis); } + else if(!strcmp(transformName, "lens") && (ob->type == OB_CAMERA)) { + output_id = create_lens_source_from_fcurve((Camera *) ob->data, COLLADASW::InputSemantic::OUTPUT, fcu, anim_id); + } else { output_id = create_source_from_fcurve(COLLADASW::InputSemantic::OUTPUT, fcu, anim_id, axis_name); } + // create interpolations source std::string interpolation_id = create_interpolation_source(fcu, anim_id, axis_name, &has_tangents); @@ -553,7 +562,7 @@ void AnimationExporter::add_source_parameters(COLLADASW::SourceBase::ParameterNa } } -void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length) +void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool is_rotation, float *values, int *length) { switch (semantic) { case COLLADASW::InputSemantic::INPUT: @@ -562,7 +571,7 @@ void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSeman break; case COLLADASW::InputSemantic::OUTPUT: *length = 1; - if (rotation) { + if (is_rotation) { values[0] = RAD2DEGF(bezt->vec[1][1]); } else { @@ -578,7 +587,7 @@ void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSeman values[0] = 0; values[1] = 0; } - else if (rotation) { + else if (is_rotation) { values[1] = RAD2DEGF(bezt->vec[0][1]); } else { @@ -594,7 +603,7 @@ void AnimationExporter::get_source_values(BezTriple *bezt, COLLADASW::InputSeman values[0] = 0; values[1] = 0; } - else if (rotation) { + else if (is_rotation) { values[1] = RAD2DEGF(bezt->vec[2][1]); } else { @@ -654,6 +663,44 @@ std::string AnimationExporter::create_source_from_fcurve(COLLADASW::InputSemanti return source_id; } +/* + * Similar to create_source_from_fcurve, but adds conversion of lens + * animation data from focal length to FOV. + */ +std::string AnimationExporter::create_lens_source_from_fcurve(Camera *cam, COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id) +{ + std::string source_id = anim_id + get_semantic_suffix(semantic); + + COLLADASW::FloatSourceF source(mSW); + source.setId(source_id); + source.setArrayId(source_id + ARRAY_ID_SUFFIX); + source.setAccessorCount(fcu->totvert); + + source.setAccessorStride(1); + + COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); + add_source_parameters(param, semantic, false, "", false); + + source.prepareToAppendValues(); + + for (unsigned int i = 0; i < fcu->totvert; i++) { + float values[3]; // be careful! + int length = 0; + get_source_values(&fcu->bezt[i], semantic, false, values, &length); + for (int j = 0; j < length; j++) + { + float val = RAD2DEGF(focallength_to_fov(values[j], cam->sensor_x)); + source.appendValues(val); + } + } + + source.finish(); + + return source_id; +} + + + //Currently called only to get OUTPUT source values ( if rotation and hence the axis is also specified ) std::string AnimationExporter::create_source_from_array(COLLADASW::InputSemantic::Semantics semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name) { diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h index 1313687db28..0a7832e9d64 100644 --- a/source/blender/collada/AnimationExporter.h +++ b/source/blender/collada/AnimationExporter.h @@ -133,6 +133,8 @@ protected: std::string create_source_from_fcurve(COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id, const char *axis_name); + std::string create_lens_source_from_fcurve(Camera *cam, COLLADASW::InputSemantic::Semantics semantic, FCurve *fcu, const std::string& anim_id); + std::string create_source_from_array(COLLADASW::InputSemantic::Semantics semantic, float *v, int tot, bool is_rot, const std::string& anim_id, const char *axis_name); std::string create_source_from_vector(COLLADASW::InputSemantic::Semantics semantic, std::vector<float> &fra, bool is_rot, const std::string& anim_id, const char *axis_name); diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp index af6d70ecca0..a237222774d 100644 --- a/source/blender/collada/AnimationImporter.cpp +++ b/source/blender/collada/AnimationImporter.cpp @@ -652,6 +652,51 @@ void AnimationImporter:: Assign_float_animations(const COLLADAFW::UniqueId& list } +/* + * Lens animations must be stored in COLLADA by using FOV, + * while blender internally uses focal length. + * The imported animation curves must be converted appropriately. + */ +void AnimationImporter::Assign_lens_animations(const COLLADAFW::UniqueId& listid, ListBase *AnimCurves, const double aspect, Camera *cam, const char *anim_type, int fov_type) +{ + char rna_path[100]; + if (animlist_map.find(listid) == animlist_map.end()) { + return; + } + else { + //anim_type has animations + const COLLADAFW::AnimationList *animlist = animlist_map[listid]; + const COLLADAFW::AnimationList::AnimationBindings& bindings = animlist->getAnimationBindings(); + //all the curves belonging to the current binding + std::vector<FCurve *> animcurves; + for (unsigned int j = 0; j < bindings.getCount(); j++) { + animcurves = curve_map[bindings[j].animation]; + + BLI_strncpy(rna_path, anim_type, sizeof(rna_path)); + + modify_fcurve(&animcurves, rna_path, 0); + std::vector<FCurve *>::iterator iter; + //Add the curves of the current animation to the object + for (iter = animcurves.begin(); iter != animcurves.end(); iter++) { + FCurve *fcu = *iter; + + for (unsigned int i = 0; i < fcu->totvert; i++) { + + double input_fov = fcu->bezt[i].vec[1][1]; + double xfov = (fov_type == CAMERA_YFOV) ? aspect * input_fov : input_fov; + + // fov is in degrees, cam->lens is in millimiters + double fov = fov_to_focallength(DEG2RADF(input_fov), cam->sensor_x); + + fcu->bezt[i].vec[1][1] = fov; + } + + BLI_addtail(AnimCurves, fcu); + } + } + } +} + void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& animcurves, COLLADAFW::Node *root, COLLADAFW::Node *node, COLLADAFW::Transformation *tm) { @@ -796,6 +841,39 @@ void AnimationImporter::apply_matrix_curves(Object *ob, std::vector<FCurve *>& a } +/* + * This function returns the aspet ration from the Collada camera. + * + * Note:COLLADA allows to specify either XFov, or YFov alone. + * In tghat case the aspect ratio can be determined from + * the viewport aspect ratio (which is 1:1 ?) + * XXX: check this: its probably wrong! + * If both values are specified, then the aspect ration is simply xfov/yfov + * and if aspect ratio is efined, then .. well then its that one. + */ +static const double get_aspect_ratio(const COLLADAFW::Camera *camera) +{ + double aspect = camera->getAspectRatio().getValue(); + + if(aspect == 0) + { + const double yfov = camera->getYFov().getValue(); + + if(yfov == 0) + aspect=1; // assume yfov and xfov are equal + else + { + const double xfov = camera->getXFov().getValue(); + if (xfov==0) + aspect = 1; + else + aspect = xfov / yfov; + } + } + return aspect; +} + + void AnimationImporter::translate_Animations(COLLADAFW::Node *node, std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& root_map, std::multimap<COLLADAFW::UniqueId, Object *>& object_map, @@ -924,10 +1002,11 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node, } if (animType->camera != 0) { - Camera *camera = (Camera *) ob->data; - - if (!camera->adt || !camera->adt->action) act = verify_adt_action((ID *)&camera->id, 1); - else act = camera->adt->action; + Camera *cam = (Camera *) ob->data; + if (!cam->adt || !cam->adt->action) + act = verify_adt_action((ID *)&cam->id, 1); + else + act = cam->adt->action; ListBase *AnimCurves = &(act->curves); const COLLADAFW::InstanceCameraPointerArray& nodeCameras = node->getInstanceCameras(); @@ -938,13 +1017,15 @@ void AnimationImporter::translate_Animations(COLLADAFW::Node *node, if ((animType->camera & CAMERA_XFOV) != 0) { const COLLADAFW::AnimatableFloat *xfov = &(camera->getXFov()); const COLLADAFW::UniqueId& listid = xfov->getAnimationList(); - Assign_float_animations(listid, AnimCurves, "lens"); + double aspect = get_aspect_ratio(camera); + Assign_lens_animations(listid, AnimCurves, aspect, cam, "lens", CAMERA_XFOV); } else if ((animType->camera & CAMERA_YFOV) != 0) { const COLLADAFW::AnimatableFloat *yfov = &(camera->getYFov()); const COLLADAFW::UniqueId& listid = yfov->getAnimationList(); - Assign_float_animations(listid, AnimCurves, "lens"); + double aspect = get_aspect_ratio(camera); + Assign_lens_animations(listid, AnimCurves, aspect, cam, "lens", CAMERA_YFOV); } else if ((animType->camera & CAMERA_XMAG) != 0) { diff --git a/source/blender/collada/AnimationImporter.h b/source/blender/collada/AnimationImporter.h index 32af2b5b78b..db61692484b 100644 --- a/source/blender/collada/AnimationImporter.h +++ b/source/blender/collada/AnimationImporter.h @@ -165,6 +165,7 @@ public: void Assign_color_animations(const COLLADAFW::UniqueId& listid, ListBase *AnimCurves, const char * anim_type); void Assign_float_animations(const COLLADAFW::UniqueId& listid, ListBase *AnimCurves, const char * anim_type); + void Assign_lens_animations(const COLLADAFW::UniqueId& listid, ListBase *AnimCurves, const double aspect, Camera *cam, const char *anim_type, int fov_type); int setAnimType ( const COLLADAFW::Animatable * prop, int type, int addition); |