Fix for making vectoquat threadsafe, missed a warning.
[blender.git] / source / blender / blenkernel / intern / lattice.c
index 3d8fd7d13112e6c466ae3faf37f618139b217354..47175a789b166ca64dddf9fb4eb2f5805f646d9c 100644 (file)
@@ -44,6 +44,7 @@
 #include "BLI_arithb.h"
 
 #include "DNA_armature_types.h"
+#include "DNA_ipo_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
 #include "DNA_modifier_types.h"
@@ -61,6 +62,7 @@
 #include "BKE_deform.h"
 #include "BKE_displist.h"
 #include "BKE_global.h"
+#include "BKE_ipo.h"
 #include "BKE_key.h"
 #include "BKE_lattice.h"
 #include "BKE_library.h"
@@ -201,11 +203,11 @@ void resizelattice(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
        MEM_freeN(vertexCos);
 }
 
-Lattice *add_lattice()
+Lattice *add_lattice(char *name)
 {
        Lattice *lt;
        
-       lt= alloc_libblock(&G.main->latt, ID_LT, "Lattice");
+       lt= alloc_libblock(&G.main->latt, ID_LT, name);
        
        lt->flag= LT_GRID;
        
@@ -450,19 +452,25 @@ void end_latt_deform()
         */
 typedef struct {
        float dmin[3], dmax[3], dsize, dloc[3];
-       float curvespace[4][4], objectspace[4][4];
+       float curvespace[4][4], objectspace[4][4], objectspace3[3][3];
+       int no_rot_axis;
 } CurveDeform;
 
-static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd)
+static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd, int dloc)
 {
        Mat4Invert(ob->imat, ob->obmat);
        Mat4MulMat4(cd->objectspace, par->obmat, ob->imat);
        Mat4Invert(cd->curvespace, cd->objectspace);
-
+       Mat3CpyMat4(cd->objectspace3, cd->objectspace);
+       
        // offset vector for 'no smear'
-       Mat4Invert(par->imat, par->obmat);
-       VecMat4MulVecfl(cd->dloc, par->imat, ob->obmat[3]);
-
+       if(dloc) {
+               Mat4Invert(par->imat, par->obmat);
+               VecMat4MulVecfl(cd->dloc, par->imat, ob->obmat[3]);
+       }
+       else cd->dloc[0]=cd->dloc[1]=cd->dloc[2]= 0.0f;
+       
+       cd->no_rot_axis= 0;
 }
 
 /* this makes sure we can extend for non-cyclic. *vec needs 4 items! */
@@ -475,6 +483,7 @@ static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir)
        
        /* test for cyclic */
        bl= cu->bev.first;
+       if (!bl->nr) return 0;
        if(bl && bl->poly> -1) cycl= 1;
 
        if(cycl==0) {
@@ -508,10 +517,12 @@ static int where_on_path_deform(Object *ob, float ctime, float *vec, float *dir)
        /* for each point, rotate & translate to curve */
        /* use path, since it has constant distances */
        /* co: local coord, result local too */
-static void calc_curve_deform(Object *par, float *co, short axis, CurveDeform *cd)
+       /* returns quaternion for rotation, using cd->no_rot_axis */
+       /* axis is using another define!!! */
+static int calc_curve_deform(Object *par, float *co, short axis, CurveDeform *cd, float *quatp)
 {
        Curve *cu= par->data;
-       float fac, loc[4], dir[3], *quat, q[4], mat[3][3], cent[3];
+       float fac, loc[4], dir[3], cent[3];
        short upflag, index;
        
        if(axis==MOD_CURVE_POSX || axis==MOD_CURVE_NEGX) {
@@ -538,21 +549,43 @@ static void calc_curve_deform(Object *par, float *co, short axis, CurveDeform *c
        /* to be sure, mostly after file load */
        if(cu->path==NULL) {
                makeDispListCurveTypes(par, 0);
-               if(cu->path==NULL) return;      // happens on append...
+               if(cu->path==NULL) return 0;    // happens on append...
        }
+       
        /* options */
-       if(cu->flag & CU_STRETCH)
-               fac= (co[index]-cd->dmin[index])/(cd->dmax[index] - cd->dmin[index]);
-       else
-               fac= (cd->dloc[index])/(cu->path->totdist) + (co[index]-cd->dmin[index])/(cu->path->totdist);
+       if(ELEM3(axis, OB_NEGX, OB_NEGY, OB_NEGZ)) {
+               if(cu->flag & CU_STRETCH)
+                       fac= (-co[index]-cd->dmax[index])/(cd->dmax[index] - cd->dmin[index]);
+               else
+                       fac= (cd->dloc[index])/(cu->path->totdist) - (co[index]-cd->dmax[index])/(cu->path->totdist);
+       }
+       else {
+               if(cu->flag & CU_STRETCH)
+                       fac= (co[index]-cd->dmin[index])/(cd->dmax[index] - cd->dmin[index]);
+               else
+                       fac= (cd->dloc[index])/(cu->path->totdist) + (co[index]-cd->dmin[index])/(cu->path->totdist);
+       }
+       
+       /* we want the ipo to work on the default 100 frame range, because there's no  
+          actual time involved in path position */
+       if(cu->ipo) {
+               fac*= 100.0f;
+               if(calc_ipo_spec(cu->ipo, CU_SPEED, &fac)==0)
+                       fac/= 100.0;
+       }
        
        if( where_on_path_deform(par, fac, loc, dir)) { /* returns OK */
-
-               quat= vectoquat(dir, axis-1, upflag);   /* -1 for compatibility with old track defines */
+               float q[4], mat[3][3], quat[4];
+               
+               if(cd->no_rot_axis)     /* set by caller */
+                       dir[cd->no_rot_axis-1]= 0.0f;
+               
+               /* -1 for compatibility with old track defines */
+               vectoquat(dir, axis-1, upflag, quat);
                
                /* the tilt */
                if(loc[3]!=0.0) {
-                       Normalise(dir);
+                       Normalize(dir);
                        q[0]= (float)cos(0.5*loc[3]);
                        fac= (float)sin(0.5*loc[3]);
                        q[1]= -fac*dir[0];
@@ -568,8 +601,12 @@ static void calc_curve_deform(Object *par, float *co, short axis, CurveDeform *c
                /* translation */
                VECADD(co, cent, loc);
                
+               if(quatp)
+                       QUATCOPY(quatp, quat);
+               
+               return 1;
        }
-
+       return 0;
 }
 
 void curve_deform_verts(Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], int numVerts, char *vgroup, short defaxis)
@@ -581,7 +618,7 @@ void curve_deform_verts(Object *cuOb, Object *target, DerivedMesh *dm, float (*v
        
        cu->flag |= (CU_PATH|CU_FOLLOW); // needed for path & bevlist
 
-       init_curve_deform(cuOb, target, &cd);
+       init_curve_deform(cuOb, target, &cd, (cu->flag & CU_STRETCH)==0);
                
        /* check whether to use vertex groups (only possible if target is a Mesh)
         * we want either a Mesh with no derived data, or derived data with
@@ -589,7 +626,7 @@ void curve_deform_verts(Object *cuOb, Object *target, DerivedMesh *dm, float (*v
         */
        if(target && target->type==OB_MESH) {
                /* if there's derived data without deformverts, don't use vgroups */
-               if(dm && !dm->getVertData(dm, 0, LAYERTYPE_MDEFORMVERT))
+               if(dm && !dm->getVertData(dm, 0, CD_MDEFORMVERT))
                        use_vgroups = 0;
                else
                        use_vgroups = 1;
@@ -615,7 +652,7 @@ void curve_deform_verts(Object *cuOb, Object *target, DerivedMesh *dm, float (*v
                        INIT_MINMAX(cd.dmin, cd.dmax);
 
                        for(a = 0; a < numVerts; a++, dvert++) {
-                               if(dm) dvert = dm->getVertData(dm, a, LAYERTYPE_MDEFORMVERT);
+                               if(dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
 
                                for(j = 0; j < dvert->totweight; j++) {
                                        if(dvert->dw[j].def_nr == index) {
@@ -628,12 +665,12 @@ void curve_deform_verts(Object *cuOb, Object *target, DerivedMesh *dm, float (*v
 
                        dvert = me->dvert;
                        for(a = 0; a < numVerts; a++, dvert++) {
-                               if(dm) dvert = dm->getVertData(dm, a, LAYERTYPE_MDEFORMVERT);
+                               if(dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
 
                                for(j = 0; j < dvert->totweight; j++) {
                                        if(dvert->dw[j].def_nr == index) {
                                                VECCOPY(vec, vertexCos[a]);
-                                               calc_curve_deform(cuOb, vec, defaxis, &cd);
+                                               calc_curve_deform(cuOb, vec, defaxis, &cd, NULL);
                                                VecLerpf(vertexCos[a], vertexCos[a], vec,
                                                         dvert->dw[j].weight);
                                                Mat4MulVecfl(cd.objectspace, vertexCos[a]);
@@ -651,13 +688,42 @@ void curve_deform_verts(Object *cuOb, Object *target, DerivedMesh *dm, float (*v
                }
 
                for(a = 0; a < numVerts; a++) {
-                       calc_curve_deform(cuOb, vertexCos[a], defaxis, &cd);
+                       calc_curve_deform(cuOb, vertexCos[a], defaxis, &cd, NULL);
                        Mat4MulVecfl(cd.objectspace, vertexCos[a]);
                }
        }
        cu->flag = flag;
 }
 
+/* input vec and orco = local coord in armature space */
+/* orco is original not-animated or deformed reference point */
+/* result written in vec and mat */
+void curve_deform_vector(Object *cuOb, Object *target, float *orco, float *vec, float mat[][3], int no_rot_axis)
+{
+       CurveDeform cd;
+       float quat[4];
+       
+       init_curve_deform(cuOb, target, &cd, 0);        /* 0 no dloc */
+       cd.no_rot_axis= no_rot_axis;                            /* option to only rotate for XY, for example */
+       
+       VECCOPY(cd.dmin, orco);
+       VECCOPY(cd.dmax, orco);
+
+       Mat4MulVecfl(cd.curvespace, vec);
+       
+       if(calc_curve_deform(cuOb, vec, target->trackflag+1, &cd, quat)) {
+               float qmat[3][3];
+               
+               QuatToMat3(quat, qmat);
+               Mat3MulMat3(mat, qmat, cd.objectspace3);
+       }
+       else
+               Mat3One(mat);
+       
+       Mat4MulVecfl(cd.objectspace, vec);
+
+}
+
 void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm,
                           float (*vertexCos)[3], int numVerts, char *vgroup)
 {
@@ -672,7 +738,7 @@ void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm,
         */
        if(target && target->type==OB_MESH) {
                /* if there's derived data without deformverts, don't use vgroups */
-               if(dm && !dm->getVertData(dm, 0, LAYERTYPE_MDEFORMVERT))
+               if(dm && !dm->getVertData(dm, 0, CD_MDEFORMVERT))
                        use_vgroups = 0;
                else
                        use_vgroups = 1;
@@ -694,7 +760,7 @@ void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm,
                        int j;
                        
                        for(a = 0; a < numVerts; a++, dvert++) {
-                               if(dm) dvert = dm->getVertData(dm, a, LAYERTYPE_MDEFORMVERT);
+                               if(dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT);
                                for(j = 0; j < dvert->totweight; j++) {
                                        if (dvert->dw[j].def_nr == index) {
                                                calc_latt_deform(vertexCos[a], dvert->dw[j].weight);