COLLADA: report #32237 fixed Camera exporter and Importer to use correct camera...
authorGaia Clary <gaia.clary@machinimatrix.org>
Sun, 5 Aug 2012 21:35:09 +0000 (21:35 +0000)
committerGaia Clary <gaia.clary@machinimatrix.org>
Sun, 5 Aug 2012 21:35:09 +0000 (21:35 +0000)
source/blender/collada/AnimationExporter.cpp
source/blender/collada/AnimationExporter.h
source/blender/collada/AnimationImporter.cpp
source/blender/collada/AnimationImporter.h

index 57829f777c583885f83030d6b250f318c06363f8..0e8ead61437d667323e3f2dc95559378245cb068 100644 (file)
@@ -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 &param = 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)
 {
index 1313687db28e393c82f85f466f3ac740747bdd8c..0a7832e9d64a209bc2d548452f99ed33a0c432eb 100644 (file)
@@ -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);
index af6d70ecca0858be51f369bd1a5fc6dd1576f89b..a237222774db339027c1563fa332ca10ae3ac924 100644 (file)
@@ -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) {
index 32af2b5b78b2472daad6b3ab188fc01573131c22..db61692484b3b39a9a1dfcb3a161d61c45b69072 100644 (file)
@@ -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);