svn merge ^/trunk/blender -r40644:40720
[blender-staging.git] / source / blender / blenkernel / intern / curve.c
index d3c47a5e66b557905403da93a892bd355fd4b11b..3bf3c0f9ed8e85faebc40d3653a5db0ecefacdf1 100644 (file)
 
 #include "MEM_guardedalloc.h"
 
-#include "BLI_blenlib.h"  
-#include "BLI_math.h"  
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
 #include "BLI_utildefines.h"
+#include "BLI_ghash.h"
 
 #include "DNA_curve_types.h"  
 #include "DNA_material_types.h"  
@@ -67,9 +68,6 @@
 #include "BKE_object.h"
 #include "BKE_material.h"
 
-
-#include "ED_curve.h"
-
 /* globals */
 
 /* local */
@@ -119,6 +117,25 @@ void BKE_free_editfont(Curve *cu)
        }
 }
 
+void free_curve_editNurb_keyIndex(EditNurb *editnurb)
+{
+       if (!editnurb->keyindex) {
+               return;
+       }
+       BLI_ghash_free(editnurb->keyindex, NULL, (GHashValFreeFP)MEM_freeN);
+       editnurb->keyindex= NULL;
+}
+
+void free_curve_editNurb (Curve *cu)
+{
+       if(cu->editnurb) {
+               freeNurblist(&cu->editnurb->nurbs);
+               free_curve_editNurb_keyIndex(cu->editnurb);
+               MEM_freeN(cu->editnurb);
+               cu->editnurb= NULL;
+       }
+}
+
 /* don't free curve itself */
 void free_curve(Curve *cu)
 {
@@ -282,6 +299,16 @@ void make_local_curve(Curve *cu)
        }
 }
 
+/* Get list of nurbs from editnurbs structure */
+ListBase *curve_editnurbs(Curve *cu)
+{
+       if (cu->editnurb) {
+               return &cu->editnurb->nurbs;
+       }
+
+       return NULL;
+}
+
 short curve_type(Curve *cu)
 {
        Nurb *nu;
@@ -359,7 +386,6 @@ void tex_space_curve(Curve *cu)
        }
 }
 
-
 int count_curveverts(ListBase *nurb)
 {
        Nurb *nu;
@@ -581,46 +607,47 @@ void addNurbPointsBezier(Nurb *nu, int number)
 /* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline calculations ~~~~~~~~~~~ */
 
 
-static void calcknots(float *knots, short aantal, short order, short type)
-/* knots: number of pnts NOT corrected for cyclic */
-/* type;        0: uniform, 1: endpoints, 2: bezier */
+static void calcknots(float *knots, const short pnts, const short order, const short flag)
 {
+       /* knots: number of pnts NOT corrected for cyclic */
+       const int pnts_order= pnts + order;
        float k;
-       int a, t;
-
-               t = aantal+order;
-       if(type==0) {
+       int a;
 
-               for(a=0;a<t;a++) {
-                       knots[a]= (float)a;
-               }
-       }
-       else if(type==1) {
+       switch(flag & (CU_NURB_ENDPOINT|CU_NURB_BEZIER)) {
+       case CU_NURB_ENDPOINT:
                k= 0.0;
-               for(a=1;a<=t;a++) {
+               for(a=1; a <= pnts_order; a++) {
                        knots[a-1]= k;
-                       if(a>=order && a<=aantal) k+= 1.0f;
+                       if(a >= order && a <= pnts) k+= 1.0f;
                }
-       }
-       else if(type==2) {
-               /* Warning, the order MUST be 2 or 4, if this is not enforced, the displist will be corrupt */
+               break;
+       case CU_NURB_BEZIER:
+               /* Warning, the order MUST be 2 or 4,
+                * if this is not enforced, the displist will be corrupt */
                if(order==4) {
                        k= 0.34;
-                       for(a=0;a<t;a++) {
+                       for(a=0; a < pnts_order; a++) {
                                knots[a]= floorf(k);
                                k+= (1.0f/3.0f);
                        }
                }
                else if(order==3) {
                        k= 0.6f;
-                       for(a=0;a<t;a++) {
-                               if(a>=order && a<=aantal) k+= 0.5f;
+                       for(a=0; a < pnts_order; a++) {
+                               if(a >= order && a <= pnts) k+= 0.5f;
                                knots[a]= floorf(k);
                        }
                }
                else {
                        printf("bez nurb curve order is not 3 or 4, should never happen\n");
                }
+               break;
+       default:
+               for(a=0; a < pnts_order; a++) {
+                       knots[a]= (float)a;
+               }
+               break;
        }
 }
 
@@ -663,7 +690,7 @@ static void makeknots(Nurb *nu, short uv)
                                        calcknots(nu->knotsu, nu->pntsu, nu->orderu, 0);  /* cyclic should be uniform */
                                        makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu);
                                } else {
-                                       calcknots(nu->knotsu, nu->pntsu, nu->orderu, nu->flagu>>1);
+                                       calcknots(nu->knotsu, nu->pntsu, nu->orderu, nu->flagu);
                                }
                        }
                        else nu->knotsu= NULL;
@@ -676,7 +703,7 @@ static void makeknots(Nurb *nu, short uv)
                                        calcknots(nu->knotsv, nu->pntsv, nu->orderv, 0);  /* cyclic should be uniform */
                                        makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv);
                                } else {
-                                       calcknots(nu->knotsv, nu->pntsv, nu->orderv, nu->flagv>>1);
+                                       calcknots(nu->knotsv, nu->pntsv, nu->orderv, nu->flagv);
                                }
                        }
                        else nu->knotsv= NULL;
@@ -1898,7 +1925,7 @@ static void make_bevel_list_3D_minimum_twist(BevList *bl)
                /* flip rotation if needs be */
                cross_v3_v3v3(cross_tmp, vec_1, vec_2);
                normalize_v3(cross_tmp);
-               if(angle_normalized_v3v3(bevp_first->dir, cross_tmp) < 90.0f/(float)(180.0/M_PI))
+               if(angle_normalized_v3v3(bevp_first->dir, cross_tmp) < DEG2RADF(90.0f))
                        angle = -angle;
 
                bevp2= (BevPoint *)(bl+1);
@@ -2049,7 +2076,7 @@ void makeBevelList(Object *ob)
 
        BLI_freelistN(&(cu->bev));
        if(cu->editnurb && ob->type!=OB_FONT) {
-               ListBase *nurbs= ED_curve_editnurbs(cu);
+               ListBase *nurbs= curve_editnurbs(cu);
                nu= nurbs->first;
        } else nu= cu->nurb.first;
        
@@ -2431,72 +2458,77 @@ void makeBevelList(Object *ob)
 void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
 {
        float *p1,*p2,*p3, pt[3];
-       float dx1,dy1,dz1,dx,dy,dz,vx,vy,vz,len,len1,len2;
+       float dvec_a[3], dvec_b[3];
+       float len, len_a, len_b;
        const float eps= 1e-5;
 
-       if(bezt->h1==0 && bezt->h2==0) return;
+       if(bezt->h1==0 && bezt->h2==0) {
+               return;
+       }
 
        p2= bezt->vec[1];
 
        if(prev==NULL) {
                p3= next->vec[1];
-               pt[0]= 2*p2[0]- p3[0];
-               pt[1]= 2*p2[1]- p3[1];
-               pt[2]= 2*p2[2]- p3[2];
+               pt[0]= 2.0f*p2[0] - p3[0];
+               pt[1]= 2.0f*p2[1] - p3[1];
+               pt[2]= 2.0f*p2[2] - p3[2];
                p1= pt;
        }
-       else p1= prev->vec[1];
+       else {
+               p1= prev->vec[1];
+       }
 
        if(next==NULL) {
-               pt[0]= 2*p2[0]- p1[0];
-               pt[1]= 2*p2[1]- p1[1];
-               pt[2]= 2*p2[2]- p1[2];
+               pt[0]= 2.0f*p2[0] - p1[0];
+               pt[1]= 2.0f*p2[1] - p1[1];
+               pt[2]= 2.0f*p2[2] - p1[2];
                p3= pt;
        }
-       else p3= next->vec[1];
+       else {
+               p3= next->vec[1];
+       }
 
-       dx= p2[0]- p1[0];
-       dy= p2[1]- p1[1];
-       dz= p2[2]- p1[2];
-       
-       if(mode) len1= dx;
-       else len1= (float)sqrt(dx*dx+dy*dy+dz*dz);
-       
-       dx1= p3[0]- p2[0];
-       dy1= p3[1]- p2[1];
-       dz1= p3[2]- p2[2];
-       
-       if(mode) len2= dx1;
-       else len2= (float)sqrt(dx1*dx1+dy1*dy1+dz1*dz1);
+       sub_v3_v3v3(dvec_a, p2, p1);
+       sub_v3_v3v3(dvec_b, p3, p2);
+
+       if (mode != 0) {
+               len_a= dvec_a[0];
+               len_b= dvec_b[0];
+       }
+       else {
+               len_a= len_v3(dvec_a);
+               len_b= len_v3(dvec_b);
+       }
+
+       if(len_a==0.0f) len_a=1.0f;
+       if(len_b==0.0f) len_b=1.0f;
 
-       if(len1==0.0f) len1=1.0f;
-       if(len2==0.0f) len2=1.0f;
 
+       if(ELEM(bezt->h1,HD_AUTO,HD_AUTO_ANIM) || ELEM(bezt->h2,HD_AUTO,HD_AUTO_ANIM)) {    /* auto */
+               float tvec[3];
+               tvec[0]= dvec_b[0]/len_b + dvec_a[0]/len_a;
+               tvec[1]= dvec_b[1]/len_b + dvec_a[1]/len_a;
+               tvec[2]= dvec_b[2]/len_b + dvec_a[2]/len_a;
+               len= len_v3(tvec) * 2.5614f;
 
-       if(bezt->h1==HD_AUTO || bezt->h2==HD_AUTO) {    /* auto */
-               vx= dx1/len2 + dx/len1;
-               vy= dy1/len2 + dy/len1;
-               vz= dz1/len2 + dz/len1;
-               len= 2.5614f*(float)sqrt(vx*vx + vy*vy + vz*vz);
                if(len!=0.0f) {
                        int leftviolate=0, rightviolate=0;      /* for mode==2 */
                        
-                       if(len1>5.0f*len2) len1= 5.0f*len2;     
-                       if(len2>5.0f*len1) len2= 5.0f*len1;
+                       if(len_a>5.0f*len_b) len_a= 5.0f*len_b;
+                       if(len_b>5.0f*len_a) len_b= 5.0f*len_a;
                        
-                       if(bezt->h1==HD_AUTO) {
-                               len1/=len;
-                               *(p2-3)= *p2-vx*len1;
-                               *(p2-2)= *(p2+1)-vy*len1;
-                               *(p2-1)= *(p2+2)-vz*len1;
+                       if(ELEM(bezt->h1,HD_AUTO,HD_AUTO_ANIM)) {
+                               len_a/=len;
+                               madd_v3_v3v3fl(p2-3, p2, tvec, -len_a);
                                
-                               if(mode==2 && next && prev) {   // keep horizontal if extrema
+                               if((bezt->h1==HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */
                                        float ydiff1= prev->vec[1][1] - bezt->vec[1][1];
                                        float ydiff2= next->vec[1][1] - bezt->vec[1][1];
                                        if( (ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f) ) {
                                                bezt->vec[0][1]= bezt->vec[1][1];
                                        }
-                                       else {                                          // handles should not be beyond y coord of two others
+                                       else { /* handles should not be beyond y coord of two others */
                                                if(ydiff1 <= 0.0f) {
                                                        if(prev->vec[1][1] > bezt->vec[0][1]) {
                                                                bezt->vec[0][1]= prev->vec[1][1]; 
@@ -2512,19 +2544,17 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
                                        }
                                }
                        }
-                       if(bezt->h2==HD_AUTO) {
-                               len2/=len;
-                               *(p2+3)= *p2+vx*len2;
-                               *(p2+4)= *(p2+1)+vy*len2;
-                               *(p2+5)= *(p2+2)+vz*len2;
+                       if(ELEM(bezt->h2,HD_AUTO,HD_AUTO_ANIM)) {
+                               len_b/=len;
+                               madd_v3_v3v3fl(p2+3, p2, tvec,  len_b);
                                
-                               if(mode==2 && next && prev) {   // keep horizontal if extrema
+                               if((bezt->h2==HD_AUTO_ANIM) && next && prev) { /* keep horizontal if extrema */
                                        float ydiff1= prev->vec[1][1] - bezt->vec[1][1];
                                        float ydiff2= next->vec[1][1] - bezt->vec[1][1];
                                        if( (ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f) ) {
                                                bezt->vec[2][1]= bezt->vec[1][1];
                                        }
-                                       else {                                          // handles should not be beyond y coord of two others
+                                       else { /* andles should not be beyond y coord of two others */
                                                if(ydiff1 <= 0.0f) {
                                                        if(next->vec[1][1] < bezt->vec[2][1]) {
                                                                bezt->vec[2][1]= next->vec[1][1]; 
@@ -2540,25 +2570,25 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
                                        }
                                }
                        }
-                       if(leftviolate || rightviolate) {       /* align left handle */
+                       if(leftviolate || rightviolate) { /* align left handle */
                                float h1[3], h2[3];
+                               float dot;
                                
                                sub_v3_v3v3(h1, p2-3, p2);
                                sub_v3_v3v3(h2, p2, p2+3);
-                               len1= normalize_v3(h1);
-                               len2= normalize_v3(h2);
-                               
-                               vz= INPR(h1, h2);
-                               
+
+                               len_a= normalize_v3(h1);
+                               len_b= normalize_v3(h2);
+
+                               dot= dot_v3v3(h1, h2);
+
                                if(leftviolate) {
-                                       *(p2+3)= *(p2)   - vz*len2*h1[0];
-                                       *(p2+4)= *(p2+1) - vz*len2*h1[1];
-                                       *(p2+5)= *(p2+2) - vz*len2*h1[2];
+                                       mul_v3_fl(h1, dot * len_b);
+                                       sub_v3_v3v3(p2+3, p2, h1);
                                }
                                else {
-                                       *(p2-3)= *(p2)   + vz*len1*h2[0];
-                                       *(p2-2)= *(p2+1) + vz*len1*h2[1];
-                                       *(p2-1)= *(p2+2) + vz*len1*h2[2];
+                                       mul_v3_fl(h2, dot * len_a);
+                                       add_v3_v3v3(p2-3, p2, h2);
                                }
                        }
                        
@@ -2566,60 +2596,52 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
        }
 
        if(bezt->h1==HD_VECT) { /* vector */
-               dx/=3.0f;
-               dy/=3.0f;
-               dz/=3.0f;
-               *(p2-3)= *p2-dx;
-               *(p2-2)= *(p2+1)-dy;
-               *(p2-1)= *(p2+2)-dz;
+               mul_v3_fl(dvec_a, 1.0f/3.0f);
+               sub_v3_v3v3(p2-3, p2, dvec_a);
        }
        if(bezt->h2==HD_VECT) {
-               dx1/=3.0f;
-               dy1/=3.0f;
-               dz1/=3.0f;
-               *(p2+3)= *p2+dx1;
-               *(p2+4)= *(p2+1)+dy1;
-               *(p2+5)= *(p2+2)+dz1;
+               mul_v3_fl(dvec_b, 1.0f/3.0f);
+               sub_v3_v3v3(p2+3, p2, dvec_b);
        }
 
-       len2= len_v3v3(p2, p2+3);
-       len1= len_v3v3(p2, p2-3);
-       if(len1==0.0f) len1= 1.0f;
-       if(len2==0.0f) len2= 1.0f;
+       len_b= len_v3v3(p2, p2+3);
+       len_a= len_v3v3(p2, p2-3);
+       if(len_a==0.0f) len_a= 1.0f;
+       if(len_b==0.0f) len_b= 1.0f;
 
        if(bezt->f1 & SELECT) { /* order of calculation */
-               if(bezt->h2==HD_ALIGN) {        /* aligned */
-                       if(len1>eps) {
-                               len= len2/len1;
-                               p2[3]= p2[0]+len*(p2[0]-p2[-3]);
-                               p2[4]= p2[1]+len*(p2[1]-p2[-2]);
-                               p2[5]= p2[2]+len*(p2[2]-p2[-1]);
+               if(bezt->h2==HD_ALIGN) { /* aligned */
+                       if(len_a>eps) {
+                               len= len_b/len_a;
+                               p2[3]= p2[0]+len*(p2[0] - p2[-3]);
+                               p2[4]= p2[1]+len*(p2[1] - p2[-2]);
+                               p2[5]= p2[2]+len*(p2[2] - p2[-1]);
                        }
                }
                if(bezt->h1==HD_ALIGN) {
-                       if(len2>eps) {
-                               len= len1/len2;
-                               p2[-3]= p2[0]+len*(p2[0]-p2[3]);
-                               p2[-2]= p2[1]+len*(p2[1]-p2[4]);
-                               p2[-1]= p2[2]+len*(p2[2]-p2[5]);
+                       if(len_b>eps) {
+                               len= len_a/len_b;
+                               p2[-3]= p2[0]+len*(p2[0] - p2[3]);
+                               p2[-2]= p2[1]+len*(p2[1] - p2[4]);
+                               p2[-1]= p2[2]+len*(p2[2] - p2[5]);
                        }
                }
        }
        else {
                if(bezt->h1==HD_ALIGN) {
-                       if(len2>eps) {
-                               len= len1/len2;
-                               p2[-3]= p2[0]+len*(p2[0]-p2[3]);
-                               p2[-2]= p2[1]+len*(p2[1]-p2[4]);
-                               p2[-1]= p2[2]+len*(p2[2]-p2[5]);
+                       if(len_b>eps) {
+                               len= len_a/len_b;
+                               p2[-3]= p2[0]+len*(p2[0] - p2[3]);
+                               p2[-2]= p2[1]+len*(p2[1] - p2[4]);
+                               p2[-1]= p2[2]+len*(p2[2] - p2[5]);
                        }
                }
                if(bezt->h2==HD_ALIGN) {        /* aligned */
-                       if(len1>eps) {
-                               len= len2/len1;
-                               p2[3]= p2[0]+len*(p2[0]-p2[-3]);
-                               p2[4]= p2[1]+len*(p2[1]-p2[-2]);
-                               p2[5]= p2[2]+len*(p2[2]-p2[-1]);
+                       if(len_a>eps) {
+                               len= len_b/len_a;
+                               p2[3]= p2[0]+len*(p2[0] - p2[-3]);
+                               p2[4]= p2[1]+len*(p2[1] - p2[-2]);
+                               p2[5]= p2[2]+len*(p2[2] - p2[-1]);
                        }
                }
        }
@@ -2674,15 +2696,15 @@ void testhandlesNurb(Nurb *nu)
                if(bezt->f1 & SELECT) flag++;
                if(bezt->f2 & SELECT) flag += 2;
                if(bezt->f3 & SELECT) flag += 4;
-
+               
                if( !(flag==0 || flag==7) ) {
-                       if(bezt->h1==HD_AUTO) {   /* auto */
+                       if(ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) {   /* auto */
                                bezt->h1= HD_ALIGN;
                        }
-                       if(bezt->h2==HD_AUTO) {   /* auto */
+                       if(ELEM(bezt->h2, HD_AUTO, HD_AUTO_ANIM)) {   /* auto */
                                bezt->h2= HD_ALIGN;
                        }
-
+                       
                        if(bezt->h1==HD_VECT) {   /* vector */
                                if(flag < 4) bezt->h1= 0;
                        }
@@ -2692,7 +2714,7 @@ void testhandlesNurb(Nurb *nu)
                }
                bezt++;
        }
-
+       
        calchandlesNurb(nu);
 }
 
@@ -3157,7 +3179,7 @@ int clamp_nurb_order_v( struct Nurb *nu)
 ListBase *BKE_curve_nurbs(Curve *cu)
 {
        if (cu->editnurb) {
-               return ED_curve_editnurbs(cu);
+               return curve_editnurbs(cu);
        }
 
        return &cu->nurb;
@@ -3260,3 +3282,28 @@ void curve_translate(Curve *cu, float offset[3], int do_keys)
                }
        }
 }
+
+void curve_delete_material_index(Curve *cu, int index)
+{
+       const int curvetype= curve_type(cu);
+
+       if(curvetype == OB_FONT) {
+               struct CharInfo *info= cu->strinfo;
+               int i;
+               for(i= cu->len-1; i >= 0; i--, info++) {
+                       if (info->mat_nr && info->mat_nr>=index) {
+                               info->mat_nr--;
+                       }
+               }
+       }
+       else {
+               Nurb *nu;
+
+               for (nu= cu->nurb.first; nu; nu= nu->next) {
+                       if(nu->mat_nr && nu->mat_nr>=index) {
+                               nu->mat_nr--;
+                               if (curvetype == OB_CURVE) nu->charidx--;
+                       }
+               }
+       }
+}