Merging r39717 through r39983 from trunk into soc-2011-tomato
[blender.git] / source / blender / blenkernel / intern / constraint.c
index 91091d3..5c49723 100644 (file)
@@ -45,6 +45,7 @@
 #include "BLI_utildefines.h"
 
 #include "DNA_armature_types.h"
+#include "DNA_camera_types.h"
 #include "DNA_constraint_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_object_types.h"
 #include "DNA_curve_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
+#include "DNA_lamp_types.h"
 #include "DNA_lattice_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_text_types.h"
+#include "DNA_tracking_types.h"
+#include "DNA_movieclip_types.h"
 
 
 #include "BKE_action.h"
@@ -73,6 +77,8 @@
 #include "BKE_idprop.h"
 #include "BKE_shrinkwrap.h"
 #include "BKE_mesh.h"
+#include "BKE_tracking.h"
+#include "BKE_movieclip.h"
 
 #ifdef WITH_PYTHON
 #include "BPY_extern.h"
@@ -3927,6 +3933,219 @@ static bConstraintTypeInfo CTI_PIVOT = {
        pivotcon_evaluate /* evaluate */
 };
 
+/* ----------- Follow Track ------------- */
+
+static void followtrack_new_data (void *cdata)
+{
+       bFollowTrackConstraint *data= (bFollowTrackConstraint *)cdata;
+
+       data->clip= NULL;
+       data->flag|= FOLLOWTRACK_DEFAULTCLIP;
+       data->reference= FOLLOWTRACK_TRACK;
+}
+
+static void followtrack_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
+{
+       bFollowTrackConstraint *data= con->data;
+
+       func(con, (ID**)&data->clip, userdata);
+}
+
+static void followtrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
+{
+       Scene *scene= cob->scene;
+       bFollowTrackConstraint *data= con->data;
+       MovieClip *clip= data->clip;
+       MovieTrackingTrack *track;
+
+       if(data->flag&FOLLOWTRACK_DEFAULTCLIP)
+               clip= scene->clip;
+
+       if(!clip || !data->track[0])
+               return;
+
+       track= BKE_find_track_by_name(&clip->tracking, data->track);
+
+       if(!track)
+               return;
+
+       if(data->reference==FOLLOWTRACK_BUNDLE) {
+               if(track->flag&TRACK_HAS_BUNDLE) {
+                       float pos[3], mat[4][4], obmat[4][4];
+
+                       copy_m4_m4(obmat, cob->matrix);
+
+                       BKE_get_tracking_mat(cob->scene, mat);
+                       mul_v3_m4v3(pos, mat, track->bundle_pos);
+
+                       cob->matrix[3][0]+= pos[0];
+                       cob->matrix[3][1]+= pos[1];
+                       cob->matrix[3][2]+= pos[2];
+               }
+       } else {
+               Object *camob= cob->scene->camera;
+
+               if(camob) {
+                       MovieClipUser user;
+                       MovieTrackingMarker *marker;
+                       float vec[3], disp[3], axis[3], mat[4][4];
+                       float aspect= (scene->r.xsch*scene->r.xasp) / (scene->r.ysch*scene->r.yasp);
+                       float sensor_x, lens, len, d, ortho_scale;
+
+                       where_is_object_mat(scene, camob, mat);
+
+                       /* camera axis */
+                       vec[0]= 0.f;
+                       vec[1]= 0.f;
+                       vec[2]= 1.f;
+                       mul_v3_m4v3(axis, mat, vec);
+
+                       /* distance to projection plane */
+                       copy_v3_v3(vec, cob->matrix[3]);
+                       sub_v3_v3(vec, mat[3]);
+                       project_v3_v3v3(disp, vec, axis);
+
+                       len= len_v3(disp);
+
+                       if(len>FLT_EPSILON) {
+                               float pos[2], rmat[4][4];
+                               int is_ortho= 0;
+
+                               user.framenr= scene->r.cfra;
+                               marker= BKE_tracking_get_marker(track, user.framenr);
+
+                               add_v2_v2v2(pos, marker->pos, track->offset);
+
+                               /* calculate lens and sensor size depends on object type */
+                               if(camob->type==OB_CAMERA) {
+                                       Camera *camera= (Camera *)camob->data;
+
+                                       sensor_x= camera->sensor_x;
+                                       lens= camera->lens;
+                                       is_ortho= camera->type == CAM_ORTHO;
+                                       ortho_scale= camera->ortho_scale;
+                               } else if (camob->type==OB_LAMP) {
+                                       Lamp *la= camob->data;
+                                       float fac= cosf((float)M_PI*la->spotsize/360.0f);
+                                       float phi= acos(fac);
+
+                                       lens= 16.0f*fac/sinf(phi);
+                                       sensor_x= 32.f;
+                                       ortho_scale= 0.f;
+                               } else {
+                                       lens= 16.f;
+                                       sensor_x= 32.f;
+                                       ortho_scale= 0.f;
+                               }
+
+                               if(is_ortho) {
+                                       vec[0]= ortho_scale * (pos[0]-0.5f);
+                                       vec[1]= ortho_scale * (pos[1]-0.5f);
+                                       vec[2]= -len;
+
+                                       if(aspect>1.f) vec[1]/= aspect;
+                                       else vec[0]*= aspect;
+
+                                       mul_v3_m4v3(disp, camob->obmat, vec);
+
+                                       copy_m4_m4(rmat, camob->obmat);
+                                       zero_v3(rmat[3]);
+                                       mul_m4_m4m4(cob->matrix, rmat, cob->matrix);
+
+                                       copy_v3_v3(cob->matrix[3], disp);
+                               }
+                               else {
+                                       d= (len*sensor_x) / (2.f*lens);
+
+                                       vec[0]= d*(2.f*pos[0]-1.f);
+                                       vec[1]= d*(2.f*pos[1]-1.f);
+                                       vec[2]= -len;
+
+                                       if(aspect>1.f) vec[1]/= aspect;
+                                       else vec[0]*= aspect;
+
+                                       mul_v3_m4v3(disp, camob->obmat, vec);
+
+                                       /* apply camera rotation so Z-axis would be co-linear */
+                                       copy_m4_m4(rmat, camob->obmat);
+                                       zero_v3(rmat[3]);
+                                       mul_m4_m4m4(cob->matrix, rmat, cob->matrix);
+
+                                       copy_v3_v3(cob->matrix[3], disp);
+                               }
+                       }
+               }
+       }
+}
+
+static bConstraintTypeInfo CTI_FOLLOWTRACK = {
+       CONSTRAINT_TYPE_FOLLOWTRACK, /* type */
+       sizeof(bFollowTrackConstraint), /* size */
+       "Follow Track", /* name */
+       "bFollowTrackConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       followtrack_id_looper, /* id looper */
+       NULL, /* copy data */
+       followtrack_new_data, /* new data */
+       NULL, /* get constraint targets */
+       NULL, /* flush constraint targets */
+       NULL, /* get target matrix */
+       followtrack_evaluate /* evaluate */
+};
+
+/* ----------- Camre Solver ------------- */
+
+static void camerasolver_new_data (void *cdata)
+{
+       bCameraSolverConstraint *data= (bCameraSolverConstraint *)cdata;
+
+       data->clip= NULL;
+       data->flag|= CAMERASOLVER_DEFAULTCLIP;
+}
+
+static void camerasolver_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata)
+{
+       bCameraSolverConstraint *data= con->data;
+
+       func(con, (ID**)&data->clip, userdata);
+}
+
+static void camerasolver_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets))
+{
+       Scene *scene= cob->scene;
+       bCameraSolverConstraint *data= con->data;
+       MovieClip *clip= data->clip;
+
+       if(data->flag&CAMERASOLVER_DEFAULTCLIP)
+               clip= scene->clip;
+
+       if(clip) {
+               float mat[4][4], obmat[4][4];
+
+               BKE_tracking_get_interpolated_camera(&clip->tracking, scene->r.cfra, mat);
+
+               copy_m4_m4(obmat, cob->matrix);
+               mul_m4_m4m4(cob->matrix, mat, obmat);
+       }
+}
+
+static bConstraintTypeInfo CTI_CAMERASOLVER = {
+       CONSTRAINT_TYPE_CAMERASOLVER, /* type */
+       sizeof(bCameraSolverConstraint), /* size */
+       "Camera Solver", /* name */
+       "bCameraSolverConstraint", /* struct name */
+       NULL, /* free data */
+       NULL, /* relink data */
+       camerasolver_id_looper, /* id looper */
+       NULL, /* copy data */
+       camerasolver_new_data, /* new data */
+       NULL, /* get constraint targets */
+       NULL, /* flush constraint targets */
+       NULL, /* get target matrix */
+       camerasolver_evaluate /* evaluate */
+};
+
 /* ************************* Constraints Type-Info *************************** */
 /* All of the constraints api functions use bConstraintTypeInfo structs to carry out
  * and operations that involve constraint specific code.
@@ -3964,6 +4183,8 @@ static void constraints_init_typeinfo (void) {
        constraintsTypeInfo[23]= &CTI_TRANSLIKE;                /* Copy Transforms Constraint */
        constraintsTypeInfo[24]= &CTI_SAMEVOL;                  /* Maintain Volume Constraint */
        constraintsTypeInfo[25]= &CTI_PIVOT;                    /* Pivot Constraint */
+       constraintsTypeInfo[26]= &CTI_FOLLOWTRACK;              /* Follow Track Constraint */
+       constraintsTypeInfo[27]= &CTI_CAMERASOLVER;             /* Camera Solver Constraint */
 }
 
 /* This function should be used for getting the appropriate type-info when only