merge with/from trunk at r35190
[blender.git] / source / blender / blenkernel / intern / curve.c
index 58ff601e7f7e920eb82a6ec813809a42283c688e..67e988249f599a8356cd765e95cb9bb5452f99eb 100644 (file)
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
 #include <string.h>
 #include <stdlib.h>  
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #include "MEM_guardedalloc.h"
+
 #include "BLI_blenlib.h"  
-#include "BLI_arithb.h"  
+#include "BLI_math.h"  
+#include "BLI_utildefines.h"
 
-#include "DNA_object_types.h"  
 #include "DNA_curve_types.h"  
 #include "DNA_material_types.h"  
 
 /* for dereferencing pointers */
-#include "DNA_ID.h"  
 #include "DNA_key_types.h"  
 #include "DNA_scene_types.h"  
 #include "DNA_vfont_types.h"  
+#include "DNA_meshdata_types.h"  
+#include "DNA_object_types.h"
 
 #include "BKE_animsys.h"
 #include "BKE_anim.h"  
 #include "BKE_key.h"  
 #include "BKE_library.h"  
 #include "BKE_main.h"  
-#include "BKE_mesh.h" 
 #include "BKE_object.h"  
-#include "BKE_utildefines.h"  // VECCOPY
 
 
+#include "ED_curve.h"
+
 /* globals */
 
 /* local */
-int cu_isectLL(float *v1, float *v2, float *v3, float *v4, 
+static int cu_isectLL(float *v1, float *v2, float *v3, float *v4, 
                           short cox, short coy, 
                           float *labda, float *mu, float *vec);
 
@@ -79,12 +77,22 @@ void unlink_curve(Curve *cu)
        
        for(a=0; a<cu->totcol; a++) {
                if(cu->mat[a]) cu->mat[a]->id.us--;
-               cu->mat[a]= 0;
+               cu->mat[a]= NULL;
        }
        if(cu->vfont) cu->vfont->id.us--; 
-       cu->vfont= 0;
+       cu->vfont= NULL;
+
+       if(cu->vfontb) cu->vfontb->id.us--; 
+       cu->vfontb= NULL;
+
+       if(cu->vfonti) cu->vfonti->id.us--; 
+       cu->vfonti= NULL;
+
+       if(cu->vfontbi) cu->vfontbi->id.us--; 
+       cu->vfontbi= NULL;
+       
        if(cu->key) cu->key->id.us--;
-       cu->key= 0;
+       cu->key= NULL;
 }
 
 /* frees editcurve entirely */
@@ -112,13 +120,8 @@ void free_curve(Curve *cu)
        BLI_freelistN(&cu->bev);
        freedisplist(&cu->disp);
        BKE_free_editfont(cu);
-       
-       if(cu->editnurb) {
-               freeNurblist(cu->editnurb);
-               MEM_freeN(cu->editnurb);
-               cu->editnurb= NULL;
-       }
 
+       free_curve_editNurb(cu);
        unlink_curve(cu);
        BKE_free_animdata((ID *)cu);
        
@@ -130,22 +133,24 @@ void free_curve(Curve *cu)
        if(cu->tb) MEM_freeN(cu->tb);
 }
 
-Curve *add_curve(char *name, int type)
+Curve *add_curve(const char *name, int type)
 {
        Curve *cu;
 
        cu= alloc_libblock(&G.main->curve, ID_CU, name);
        
        cu->size[0]= cu->size[1]= cu->size[2]= 1.0;
-       cu->flag= CU_FRONT+CU_BACK;
+       cu->flag= CU_FRONT|CU_BACK|CU_DEFORM_BOUNDS_OFF|CU_PATH_RADIUS;
        cu->pathlen= 100;
-       cu->resolu= cu->resolv= 12;
+       cu->resolu= cu->resolv= (type == OB_SURF) ? 4 : 12;
        cu->width= 1.0;
        cu->wordspace = 1.0;
        cu->spacing= cu->linedist= 1.0;
        cu->fsize= 1.0;
        cu->ulheight = 0.05;    
        cu->texflag= CU_AUTOSPACE;
+       cu->smallcaps_scale= 0.75f;
+       cu->twist_mode= CU_TWIST_MINIMUM;       // XXX: this one seems to be the best one in most cases, at least for curve deform...
        
        cu->bb= unit_boundbox();
        
@@ -153,8 +158,8 @@ Curve *add_curve(char *name, int type)
                cu->vfont= cu->vfontb= cu->vfonti= cu->vfontbi= get_builtin_font();
                cu->vfont->id.us+=4;
                cu->str= MEM_mallocN(12, "str");
-               strcpy(cu->str, "Text");
-               cu->pos= 4;
+               BLI_strncpy(cu->str, "Text", 12);
+               cu->len= cu->pos= 4;
                cu->strinfo= MEM_callocN(12*sizeof(CharInfo), "strinfo new");
                cu->totbox= cu->actbox= 1;
                cu->tb= MEM_callocN(MAXTEXTBOX*sizeof(TextBox), "textbox");
@@ -170,7 +175,7 @@ Curve *copy_curve(Curve *cu)
        int a;
        
        cun= copy_libblock(cu);
-       cun->nurb.first= cun->nurb.last= 0;
+       cun->nurb.first= cun->nurb.last= NULL;
        duplicateNurblist( &(cun->nurb), &(cu->nurb));
 
        cun->mat= MEM_dupallocN(cu->mat);
@@ -186,11 +191,12 @@ Curve *copy_curve(Curve *cu)
        cun->key= copy_key(cu->key);
        if(cun->key) cun->key->from= (ID *)cun;
        
-       cun->disp.first= cun->disp.last= 0;
-       cun->bev.first= cun->bev.last= 0;
-       cun->path= 0;
+       cun->disp.first= cun->disp.last= NULL;
+       cun->bev.first= cun->bev.last= NULL;
+       cun->path= NULL;
 
        cun->editnurb= NULL;
+       cun->editfont= NULL;
 
 #if 0  // XXX old animation system
        /* single user ipo too */
@@ -207,7 +213,7 @@ Curve *copy_curve(Curve *cu)
 
 void make_local_curve(Curve *cu)
 {
-       Object *ob = 0;
+       Object *ob = NULL;
        Curve *cun;
        int local=0, lib=0;
        
@@ -216,14 +222,17 @@ void make_local_curve(Curve *cu)
         * - mixed: do a copy
         */
        
-       if(cu->id.lib==0) return;
-       
-       if(cu->vfont) cu->vfont->id.lib= 0;
-       
+       if(cu->id.lib==NULL) return;
+
+       if(cu->vfont) cu->vfont->id.lib= NULL;
+       if(cu->vfontb) cu->vfontb->id.lib= NULL;
+       if(cu->vfonti) cu->vfonti->id.lib= NULL;
+       if(cu->vfontbi) cu->vfontbi->id.lib= NULL;
+
        if(cu->id.us==1) {
-               cu->id.lib= 0;
+               cu->id.lib= NULL;
                cu->id.flag= LIB_LOCAL;
-               new_id(0, (ID *)cu, 0);
+               new_id(NULL, (ID *)cu, NULL);
                return;
        }
        
@@ -237,9 +246,9 @@ void make_local_curve(Curve *cu)
        }
        
        if(local && lib==0) {
-               cu->id.lib= 0;
+               cu->id.lib= NULL;
                cu->id.flag= LIB_LOCAL;
-               new_id(0, (ID *)cu, 0);
+               new_id(NULL, (ID *)cu, NULL);
        }
        else if(local && lib) {
                cun= copy_curve(cu);
@@ -249,7 +258,7 @@ void make_local_curve(Curve *cu)
                while(ob) {
                        if(ob->data==cu) {
                                
-                               if(ob->id.lib==0) {
+                               if(ob->id.lib==NULL) {
                                        ob->data= cun;
                                        cun->id.us++;
                                        cu->id.us--;
@@ -284,7 +293,7 @@ void tex_space_curve(Curve *cu)
 {
        DispList *dl;
        BoundBox *bb;
-       float *fp, min[3], max[3], loc[3], size[3];
+       float *fp, min[3], max[3];
        int tot, doit= 0;
        
        if(cu->bb==NULL) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox");
@@ -311,20 +320,15 @@ void tex_space_curve(Curve *cu)
                min[0] = min[1] = min[2] = -1.0f;
                max[0] = max[1] = max[2] = 1.0f;
        }
-       
-       loc[0]= (min[0]+max[0])/2.0f;
-       loc[1]= (min[1]+max[1])/2.0f;
-       loc[2]= (min[2]+max[2])/2.0f;
-       
-       size[0]= (max[0]-min[0])/2.0f;
-       size[1]= (max[1]-min[1])/2.0f;
-       size[2]= (max[2]-min[2])/2.0f;
 
        boundbox_set_from_min_max(bb, min, max);
 
        if(cu->texflag & CU_AUTOSPACE) {
-               VECCOPY(cu->loc, loc);
-               VECCOPY(cu->size, size);
+               mid_v3_v3v3(cu->loc, min, max);
+               cu->size[0]= (max[0]-min[0])/2.0f;
+               cu->size[1]= (max[1]-min[1])/2.0f;
+               cu->size[2]= (max[2]-min[2])/2.0f;
+
                cu->rot[0]= cu->rot[1]= cu->rot[2]= 0.0;
 
                if(cu->size[0]==0.0) cu->size[0]= 1.0;
@@ -378,12 +382,12 @@ int count_curveverts_without_handles(ListBase *nurb)
 void freeNurb(Nurb *nu)
 {
 
-       if(nu==0) return;
+       if(nu==NULL) return;
 
        if(nu->bezt) MEM_freeN(nu->bezt);
-       nu->bezt= 0;
+       nu->bezt= NULL;
        if(nu->bp) MEM_freeN(nu->bp);
-       nu->bp= 0;
+       nu->bp= NULL;
        if(nu->knotsu) MEM_freeN(nu->knotsu);
        nu->knotsu= NULL;
        if(nu->knotsv) MEM_freeN(nu->knotsv);
@@ -399,7 +403,7 @@ void freeNurblist(ListBase *lb)
 {
        Nurb *nu, *next;
 
-       if(lb==0) return;
+       if(lb==NULL) return;
 
        nu= lb->first;
        while(nu) {
@@ -407,7 +411,7 @@ void freeNurblist(ListBase *lb)
                freeNurb(nu);
                nu= next;
        }
-       lb->first= lb->last= 0;
+       lb->first= lb->last= NULL;
 }
 
 Nurb *duplicateNurb(Nurb *nu)
@@ -416,7 +420,7 @@ Nurb *duplicateNurb(Nurb *nu)
        int len;
 
        newnu= (Nurb*)MEM_mallocN(sizeof(Nurb),"duplicateNurb");
-       if(newnu==0) return 0;
+       if(newnu==NULL) return NULL;
        memcpy(newnu, nu, sizeof(Nurb));
 
        if(nu->bezt) {
@@ -518,7 +522,47 @@ void minmaxNurb(Nurb *nu, float *min, float *max)
                        bp++;
                }
        }
+}
+
+/* be sure to call makeknots after this */
+void addNurbPoints(Nurb *nu, int number)
+{
+       BPoint *tmp= nu->bp;
+       int i;
+       nu->bp= (BPoint *)MEM_mallocN((nu->pntsu + number) * sizeof(BPoint), "rna_Curve_spline_points_add");
+
+       if(tmp) {
+               memmove(nu->bp, tmp, nu->pntsu * sizeof(BPoint));
+               MEM_freeN(tmp);
+       }
+
+       memset(nu->bp + nu->pntsu, 0, number * sizeof(BPoint));
+
+       for(i=0, tmp= nu->bp + nu->pntsu; i < number; i++, tmp++) {
+               tmp->radius= 1.0f;
+       }
+
+       nu->pntsu += number;
+}
+
+void addNurbPointsBezier(Nurb *nu, int number)
+{
+       BezTriple *tmp= nu->bezt;
+       int i;
+       nu->bezt= (BezTriple *)MEM_mallocN((nu->pntsu + number) * sizeof(BezTriple), "rna_Curve_spline_points_add");
+
+       if(tmp) {
+               memmove(nu->bezt, tmp, nu->pntsu * sizeof(BezTriple));
+               MEM_freeN(tmp);
+       }
+
+       memset(nu->bezt + nu->pntsu, 0, number * sizeof(BezTriple));
+
+       for(i=0, tmp= nu->bezt + nu->pntsu; i < number; i++, tmp++) {
+               tmp->radius= 1.0f;
+       }
 
+       nu->pntsu += number;
 }
 
 /* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline calculations ~~~~~~~~~~~ */
@@ -531,7 +575,7 @@ static void calcknots(float *knots, short aantal, short order, short type)
        float k;
        int a, t;
 
-        t = aantal+order;
+               t = aantal+order;
        if(type==0) {
 
                for(a=0;a<t;a++) {
@@ -572,7 +616,7 @@ static void makecyclicknots(float *knots, short pnts, short order)
 {
        int a, b, order2, c;
 
-       if(knots==0) return;
+       if(knots==NULL) return;
 
        order2=order-1;
 
@@ -586,7 +630,7 @@ static void makecyclicknots(float *knots, short pnts, short order)
        }
 
        b= order;
-        c=pnts + order + order2;
+               c=pnts + order + order2;
        for(a=pnts+order2; a<c; a++) {
                knots[a]= knots[a-1]+ (knots[b]-knots[b-1]);
                b--;
@@ -595,14 +639,14 @@ static void makecyclicknots(float *knots, short pnts, short order)
 
 
 
-void makeknots(Nurb *nu, short uv)
+static void makeknots(Nurb *nu, short uv)
 {
        if(nu->type == CU_NURBS) {
                if(uv == 1) {
                        if(nu->knotsu) MEM_freeN(nu->knotsu);
                        if(check_valid_nurb_u(nu)) {
                                nu->knotsu= MEM_callocN(4+sizeof(float)*KNOTSU(nu), "makeknots");
-                               if(nu->flagu & CU_CYCLIC) {
+                               if(nu->flagu & CU_NURB_CYCLIC) {
                                        calcknots(nu->knotsu, nu->pntsu, nu->orderu, 0);  /* cyclic should be uniform */
                                        makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu);
                                } else {
@@ -615,7 +659,7 @@ void makeknots(Nurb *nu, short uv)
                        if(nu->knotsv) MEM_freeN(nu->knotsv);
                        if(check_valid_nurb_v(nu)) {
                                nu->knotsv= MEM_callocN(4+sizeof(float)*KNOTSV(nu), "makeknots");
-                               if(nu->flagv & CU_CYCLIC) {
+                               if(nu->flagv & CU_NURB_CYCLIC) {
                                        calcknots(nu->knotsv, nu->pntsv, nu->orderv, 0);  /* cyclic should be uniform */
                                        makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv);
                                } else {
@@ -627,20 +671,30 @@ void makeknots(Nurb *nu, short uv)
        }
 }
 
+void nurbs_knot_calc_u(Nurb *nu)
+{
+       makeknots(nu, 1);
+}
+
+void nurbs_knot_calc_v(Nurb *nu)
+{
+       makeknots(nu, 2);
+}
+
 static void basisNurb(float t, short order, short pnts, float *knots, float *basis, int *start, int *end)
 {
        float d, e;
        int i, i1 = 0, i2 = 0 ,j, orderpluspnts, opp2, o2;
 
        orderpluspnts= order+pnts;
-        opp2 = orderpluspnts-1;
+               opp2 = orderpluspnts-1;
 
        /* this is for float inaccuracy */
        if(t < knots[0]) t= knots[0];
        else if(t > knots[opp2]) t= knots[opp2];
 
        /* this part is order '1' */
-        o2 = order + 1;
+               o2 = order + 1;
        for(i=0;i<opp2;i++) {
                if(knots[i]!=knots[i+1] && t>= knots[i] && t<=knots[i+1]) {
                        basis[i]= 1.0;
@@ -690,16 +744,16 @@ static void basisNurb(float t, short order, short pnts, float *knots, float *bas
 }
 
 
-void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride
+void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride, int resolu, int resolv)
 /* coord_array  has to be 3*4*resolu*resolv in size, and zero-ed */
 {
        BPoint *bp;
        float *basisu, *basis, *basisv, *sum, *fp, *in;
        float u, v, ustart, uend, ustep, vstart, vend, vstep, sumdiv;
-       int i, j, iofs, jofs, cycl, len, resolu, resolv;
+       int i, j, iofs, jofs, cycl, len, curu, curv;
        int istart, iend, jsta, jen, *jstart, *jend, ratcomp;
        
-       int totu = nu->pntsu*nu->resolu, totv = nu->pntsv*nu->resolv;
+       int totu = nu->pntsu*resolu, totv = nu->pntsv*resolv;
        
        if(nu->knotsu==NULL || nu->knotsv==NULL) return;
        if(nu->orderu>nu->pntsu) return;
@@ -733,18 +787,18 @@ void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride)
        
        fp= nu->knotsu;
        ustart= fp[nu->orderu-1];
-       if(nu->flagu & CU_CYCLIC) uend= fp[nu->pntsu+nu->orderu-1];
+       if(nu->flagu & CU_NURB_CYCLIC) uend= fp[nu->pntsu+nu->orderu-1];
        else uend= fp[nu->pntsu];
-       ustep= (uend-ustart)/((nu->flagu & CU_CYCLIC) ? totu : totu - 1);
+       ustep= (uend-ustart)/((nu->flagu & CU_NURB_CYCLIC) ? totu : totu - 1);
        
        basisu= (float *)MEM_mallocN(sizeof(float)*KNOTSU(nu), "makeNurbfaces3");
 
        fp= nu->knotsv;
        vstart= fp[nu->orderv-1];
        
-       if(nu->flagv & CU_CYCLIC) vend= fp[nu->pntsv+nu->orderv-1];
+       if(nu->flagv & CU_NURB_CYCLIC) vend= fp[nu->pntsv+nu->orderv-1];
        else vend= fp[nu->pntsv];
-       vstep= (vend-vstart)/((nu->flagv & CU_CYCLIC) ? totv : totv - 1);
+       vstep= (vend-vstart)/((nu->flagv & CU_NURB_CYCLIC) ? totv : totv - 1);
        
        len= KNOTSV(nu);
        basisv= (float *)MEM_mallocN(sizeof(float)*len*totv, "makeNurbfaces3");
@@ -752,32 +806,32 @@ void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride)
        jend= (int *)MEM_mallocN(sizeof(float)*totv, "makeNurbfaces5");
 
        /* precalculation of basisv and jstart,jend */
-       if(nu->flagv & CU_CYCLIC) cycl= nu->orderv-1; 
+       if(nu->flagv & CU_NURB_CYCLIC) cycl= nu->orderv-1; 
        else cycl= 0;
        v= vstart;
        basis= basisv;
-       resolv= totv;
-       while(resolv--) {
-               basisNurb(v, nu->orderv, (short)(nu->pntsv+cycl), nu->knotsv, basis, jstart+resolv, jend+resolv);
+       curv= totv;
+       while(curv--) {
+               basisNurb(v, nu->orderv, (short)(nu->pntsv+cycl), nu->knotsv, basis, jstart+curv, jend+curv);
                basis+= KNOTSV(nu);
                v+= vstep;
        }
 
-       if(nu->flagu & CU_CYCLIC) cycl= nu->orderu-1; 
+       if(nu->flagu & CU_NURB_CYCLIC) cycl= nu->orderu-1; 
        else cycl= 0;
        in= coord_array;
        u= ustart;
-       resolu= totu;
-       while(resolu--) {
+       curu= totu;
+       while(curu--) {
 
                basisNurb(u, nu->orderu, (short)(nu->pntsu+cycl), nu->knotsu, basisu, &istart, &iend);
 
                basis= basisv;
-               resolv= totv;
-               while(resolv--) {
+               curv= totv;
+               while(curv--) {
 
-                       jsta= jstart[resolv];
-                       jen= jend[resolv];
+                       jsta= jstart[curv];
+                       jen= jend[curv];
 
                        /* calculate sum */
                        sumdiv= 0.0;
@@ -853,19 +907,19 @@ void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride)
        MEM_freeN(jend);
 }
 
-void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, int resolu)
+void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, float *weight_array, int resolu, int stride)
 /* coord_array has to be 3*4*pntsu*resolu in size and zero-ed
  * tilt_array and radius_array will be written to if valid */
 {
        BPoint *bp;
        float u, ustart, uend, ustep, sumdiv;
        float *basisu, *sum, *fp;
-       float *coord_fp= coord_array, *tilt_fp= tilt_array, *radius_fp= radius_array;
+       float *coord_fp= coord_array, *tilt_fp= tilt_array, *radius_fp= radius_array, *weight_fp= weight_array;
        int i, len, istart, iend, cycl;
 
        if(nu->knotsu==NULL) return;
        if(nu->orderu>nu->pntsu) return;
-       if(coord_array==0) return;
+       if(coord_array==NULL) return;
 
        /* allocate and initialize */
        len= nu->pntsu;
@@ -881,13 +935,13 @@ void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radiu
 
        fp= nu->knotsu;
        ustart= fp[nu->orderu-1];
-       if(nu->flagu & CU_CYCLIC) uend= fp[nu->pntsu+nu->orderu-1];
+       if(nu->flagu & CU_NURB_CYCLIC) uend= fp[nu->pntsu+nu->orderu-1];
        else uend= fp[nu->pntsu];
-       ustep= (uend-ustart)/(resolu - ((nu->flagu & CU_CYCLIC) ? 0 : 1));
+       ustep= (uend-ustart)/(resolu - ((nu->flagu & CU_NURB_CYCLIC) ? 0 : 1));
        
        basisu= (float *)MEM_mallocN(sizeof(float)*KNOTSU(nu), "makeNurbcurve3");
 
-       if(nu->flagu & CU_CYCLIC) cycl= nu->orderu-1; 
+       if(nu->flagu & CU_NURB_CYCLIC) cycl= nu->orderu-1; 
        else cycl= 0;
 
        u= ustart;
@@ -933,14 +987,18 @@ void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radiu
                                
                                if (radius_fp)
                                        (*radius_fp) += (*fp) * bp->radius;
+
+                               if (weight_fp)
+                                       (*weight_fp) += (*fp) * bp->weight;
                                
                        }
                }
 
-               coord_fp+= 3;
+               coord_fp = (float *)(((char *)coord_fp) + stride);
                
-               if (tilt_fp) tilt_fp++;
-               if (radius_fp) radius_fp++;
+               if (tilt_fp)    tilt_fp = (float *)(((char *)tilt_fp) + stride);
+               if (radius_fp)  radius_fp = (float *)(((char *)radius_fp) + stride);
+               if (weight_fp)  weight_fp = (float *)(((char *)weight_fp) + stride);
                
                u+= ustep;
        }
@@ -964,28 +1022,50 @@ void forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int i
        f*= it;
        rt3= (q3-q0+3.0f*(q1-q2))/f;
        
-       q0= rt0;
+         q0= rt0;
        q1= rt1+rt2+rt3;
        q2= 2*rt2+6*rt3;
        q3= 6*rt3;
   
-       for(a=0; a<=it; a++) {
+         for(a=0; a<=it; a++) {
                *p= q0;
-               p+= stride;
+               p = (float *)(((char *)p)+stride);
                q0+= q1;
-               q1+= q2;
-               q2+= q3;
-       }
-}      
+                q1+= q2;
+                q2+= q3;
+        }
+}
+
+static void forward_diff_bezier_cotangent(float *p0, float *p1, float *p2, float *p3, float *p, int it, int stride)
+{
+       /* note that these are not purpendicular to the curve
+        * they need to be rotated for this,
+        *
+        * This could also be optimized like forward_diff_bezier */
+       int a;
+         for(a=0; a<=it; a++) {
+               float t = (float)a / (float)it;
+
+               int i;
+               for(i=0; i<3; i++) {
+                       p[i]= (-6*t + 6)*p0[i] + (18*t - 12)*p1[i] + (-18*t + 6)*p2[i] + (6*t)*p3[i];
+               }
+               normalize_v3(p);
+               p = (float *)(((char *)p)+stride);
+        }
+}
 
 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
 
 float *make_orco_surf(Object *ob)
 {
+       /* Note: this function is used in convertblender only atm, so
+        * suppose nonzero curve's render resolution should always be used */
        Curve *cu= ob->data;
        Nurb *nu;
        int a, b, tot=0;
        int sizeu, sizev;
+       int resolu, resolv;
        float *fp, *coord_array;
        
        /* first calculate the size of the datablock */
@@ -999,12 +1079,15 @@ float *make_orco_surf(Object *ob)
                
                See also convertblender.c: init_render_surf()
                */
+
+               resolu= cu->resolu_ren ? cu->resolu_ren : nu->resolu;
+               resolv= cu->resolv_ren ? cu->resolv_ren : nu->resolv;
                
-               sizeu = nu->pntsu*nu->resolu; 
-               sizev = nu->pntsv*nu->resolv;
-               if (nu->flagu & CU_CYCLIC) sizeu++;
-               if (nu->flagv & CU_CYCLIC) sizev++;
-               if(nu->pntsv>1) tot+= sizeu * sizev;
+               sizeu = nu->pntsu*resolu;
+               sizev = nu->pntsv*resolv;
+               if (nu->flagu & CU_NURB_CYCLIC) sizeu++;
+               if (nu->flagv & CU_NURB_CYCLIC) sizev++;
+                if(nu->pntsv>1) tot+= sizeu * sizev;
                
                nu= nu->next;
        }
@@ -1013,11 +1096,14 @@ float *make_orco_surf(Object *ob)
        
        nu= cu->nurb.first;
        while(nu) {
+               resolu= cu->resolu_ren ? cu->resolu_ren : nu->resolu;
+               resolv= cu->resolv_ren ? cu->resolv_ren : nu->resolv;
+
                if(nu->pntsv>1) {
-                       sizeu = nu->pntsu*nu->resolu; 
-                       sizev = nu->pntsv*nu->resolv;
-                       if (nu->flagu & CU_CYCLIC) sizeu++;
-                       if (nu->flagv & CU_CYCLIC) sizev++;
+                       sizeu = nu->pntsu*resolu;
+                       sizev = nu->pntsv*resolv;
+                       if (nu->flagu & CU_NURB_CYCLIC) sizeu++;
+                       if (nu->flagv & CU_NURB_CYCLIC) sizev++;
                        
                        if(cu->flag & CU_UV_ORCO) {
                                for(b=0; b< sizeu; b++) {
@@ -1036,22 +1122,22 @@ float *make_orco_surf(Object *ob)
                                }
                        }
                        else {
-                               float *_tdata= MEM_callocN((nu->pntsu*nu->resolu) * (nu->pntsv*nu->resolv) *3*sizeof(float), "temp data");
+                               float *_tdata= MEM_callocN((nu->pntsu*resolu) * (nu->pntsv*resolv) *3*sizeof(float), "temp data");
                                float *tdata= _tdata;
                                
-                               makeNurbfaces(nu, tdata, 0);
+                               makeNurbfaces(nu, tdata, 0, resolu, resolv);
                                
                                for(b=0; b<sizeu; b++) {
                                        int use_b= b;
-                                       if (b==sizeu-1 && (nu->flagu & CU_CYCLIC))
+                                       if (b==sizeu-1 && (nu->flagu & CU_NURB_CYCLIC))
                                                use_b= 0;
                                        
                                        for(a=0; a<sizev; a++) {
                                                int use_a= a;
-                                               if (a==sizev-1 && (nu->flagv & CU_CYCLIC))
+                                               if (a==sizev-1 && (nu->flagv & CU_NURB_CYCLIC))
                                                        use_a= 0;
                                                
-                                               tdata = _tdata + 3 * (use_b * (nu->pntsv*nu->resolv) + use_a);
+                                               tdata = _tdata + 3 * (use_b * (nu->pntsv*resolv) + use_a);
                                                
                                                fp[0]= (tdata[0]-cu->loc[0])/cu->size[0];
                                                fp[1]= (tdata[1]-cu->loc[1])/cu->size[1];
@@ -1079,18 +1165,12 @@ float *make_orco_curve(Scene *scene, Object *ob)
        DispList *dl;
        int u, v, numVerts;
        float *fp, *coord_array;
-       int remakeDisp = 0;
-
-       if (!(cu->flag&CU_UV_ORCO) && cu->key && cu->key->refkey) {
-               cp_cu_key(cu, cu->key->refkey, 0, count_curveverts(&cu->nurb));
-               makeDispListCurveTypes(scene, ob, 1);
-               remakeDisp = 1;
-       }
+       ListBase disp = {NULL, NULL};
 
-       /* Assumes displist has been built */
+       makeDispListCurveTypes_forOrco(scene, ob, &disp);
 
        numVerts = 0;
-       for (dl=cu->disp.first; dl; dl=dl->next) {
+       for (dl=disp.first; dl; dl=dl->next) {
                if (dl->type==DL_INDEX3) {
                        numVerts += dl->nr;
                } else if (dl->type==DL_SURF) {
@@ -1107,7 +1187,7 @@ float *make_orco_curve(Scene *scene, Object *ob)
        }
 
        fp= coord_array= MEM_mallocN(3*sizeof(float)*numVerts, "cu_orco");
-       for (dl=cu->disp.first; dl; dl=dl->next) {
+       for (dl=disp.first; dl; dl=dl->next) {
                if (dl->type==DL_INDEX3) {
                        for (u=0; u<dl->nr; u++, fp+=3) {
                                if (cu->flag & CU_UV_ORCO) {
@@ -1135,8 +1215,8 @@ float *make_orco_curve(Scene *scene, Object *ob)
                        for (u=0; u<sizev; u++) {
                                for (v=0; v<sizeu; v++,fp+=3) {
                                        if (cu->flag & CU_UV_ORCO) {
-                                               fp[0]= 2.0f*u/(dl->parts-1) - 1.0f;
-                                               fp[1]= 2.0f*v/(dl->nr-1) - 1.0f;
+                                               fp[0]= 2.0f*u/(sizev - 1) - 1.0f;
+                                               fp[1]= 2.0f*v/(sizeu - 1) - 1.0f;
                                                fp[2]= 0.0;
                                        } else {
                                                float *vert;
@@ -1155,9 +1235,7 @@ float *make_orco_curve(Scene *scene, Object *ob)
                }
        }
 
-       if (remakeDisp) {
-               makeDispListCurveTypes(scene, ob, 0);
-       }
+       freedisplist(&disp);
 
        return coord_array;
 }
@@ -1165,7 +1243,7 @@ float *make_orco_curve(Scene *scene, Object *ob)
 
 /* ***************** BEVEL ****************** */
 
-void makebevelcurve(Scene *scene, Object *ob, ListBase *disp)
+void makebevelcurve(Scene *scene, Object *ob, ListBase *disp, int forRender)
 {
        DispList *dl, *dlnew;
        Curve *bevcu, *cu;
@@ -1178,40 +1256,49 @@ void makebevelcurve(Scene *scene, Object *ob, ListBase *disp)
        /* if a font object is being edited, then do nothing */
 // XXX if( ob == obedit && ob->type == OB_FONT ) return;
 
-       if(cu->bevobj && cu->bevobj!=ob) {
-               if(cu->bevobj->type==OB_CURVE) {
-                       bevcu= cu->bevobj->data;
-                       if(bevcu->ext1==0.0 && bevcu->ext2==0.0) {
-                               facx= cu->bevobj->size[0];
-                               facy= cu->bevobj->size[1];
+       if(cu->bevobj) {
+               if (cu->bevobj->type!=OB_CURVE) return;
+
+               bevcu= cu->bevobj->data;
+               if(bevcu->ext1==0.0 && bevcu->ext2==0.0) {
+                       ListBase bevdisp= {NULL, NULL};
+                       facx= cu->bevobj->size[0];
+                       facy= cu->bevobj->size[1];
 
-                               dl= bevcu->disp.first;
-                               if(dl==0) {
+                       if (forRender) {
+                               makeDispListCurveTypes_forRender(scene, cu->bevobj, &bevdisp, NULL, 0);
+                               dl= bevdisp.first;
+                       } else {
+                               dl= cu->bevobj->disp.first;
+                               if(dl==NULL) {
                                        makeDispListCurveTypes(scene, cu->bevobj, 0);
-                                       dl= bevcu->disp.first;
+                                       dl= cu->bevobj->disp.first;
                                }
-                               while(dl) {
-                                       if ELEM(dl->type, DL_POLY, DL_SEGM) {
-                                               dlnew= MEM_mallocN(sizeof(DispList), "makebevelcurve1");                                        
-                                               *dlnew= *dl;
-                                               dlnew->verts= MEM_mallocN(3*sizeof(float)*dl->parts*dl->nr, "makebevelcurve1");
-                                               memcpy(dlnew->verts, dl->verts, 3*sizeof(float)*dl->parts*dl->nr);
-                                               
-                                               if(dlnew->type==DL_SEGM) dlnew->flag |= (DL_FRONT_CURVE|DL_BACK_CURVE);
-                                               
-                                               BLI_addtail(disp, dlnew);
-                                               fp= dlnew->verts;
-                                               nr= dlnew->parts*dlnew->nr;
-                                               while(nr--) {
-                                                       fp[2]= fp[1]*facy;
-                                                       fp[1]= -fp[0]*facx;
-                                                       fp[0]= 0.0;
-                                                       fp+= 3;
-                                               }
+                       }
+
+                       while(dl) {
+                               if ELEM(dl->type, DL_POLY, DL_SEGM) {
+                                       dlnew= MEM_mallocN(sizeof(DispList), "makebevelcurve1");
+                                       *dlnew= *dl;
+                                       dlnew->verts= MEM_mallocN(3*sizeof(float)*dl->parts*dl->nr, "makebevelcurve1");
+                                       memcpy(dlnew->verts, dl->verts, 3*sizeof(float)*dl->parts*dl->nr);
+
+                                       if(dlnew->type==DL_SEGM) dlnew->flag |= (DL_FRONT_CURVE|DL_BACK_CURVE);
+
+                                       BLI_addtail(disp, dlnew);
+                                       fp= dlnew->verts;
+                                       nr= dlnew->parts*dlnew->nr;
+                                       while(nr--) {
+                                               fp[2]= fp[1]*facy;
+                                               fp[1]= -fp[0]*facx;
+                                               fp[0]= 0.0;
+                                               fp+= 3;
                                        }
-                                       dl= dl->next;
                                }
+                               dl= dl->next;
                        }
+
+                       freedisplist(&bevdisp);
                }
        }
        else if(cu->ext1==0.0 && cu->ext2==0.0) {
@@ -1261,30 +1348,33 @@ void makebevelcurve(Scene *scene, Object *ob, ListBase *disp)
                short dnr;
                
                /* bevel now in three parts, for proper vertex normals */
-               /* part 1 */
-               dnr= nr= 2+ cu->bevresol;
-               if( (cu->flag & (CU_FRONT|CU_BACK))==0)
-                       nr= 3+ 2*cu->bevresol;
-                  
-               dl= MEM_callocN(sizeof(DispList), "makebevelcurve p1");
-               dl->verts= MEM_mallocN(nr*3*sizeof(float), "makebevelcurve p1");
-               BLI_addtail(disp, dl);
-               dl->type= DL_SEGM;
-               dl->parts= 1;
-               dl->flag= DL_BACK_CURVE;
-               dl->nr= nr;
+               /* part 1, back */
 
-               /* half a circle */
-               fp= dl->verts;
-               dangle= (0.5*M_PI/(dnr-1));
-               angle= -(nr-1)*dangle;
-               
-               for(a=0; a<nr; a++) {
-                       fp[0]= 0.0;
-                       fp[1]= (float)(cos(angle)*(cu->ext2));
-                       fp[2]= (float)(sin(angle)*(cu->ext2)) - cu->ext1;
-                       angle+= dangle;
-                       fp+= 3;
+               if((cu->flag & CU_BACK) || !(cu->flag & CU_FRONT)) {
+                       dnr= nr= 2+ cu->bevresol;
+                       if( (cu->flag & (CU_FRONT|CU_BACK))==0)
+                               nr= 3+ 2*cu->bevresol;
+
+                       dl= MEM_callocN(sizeof(DispList), "makebevelcurve p1");
+                       dl->verts= MEM_mallocN(nr*3*sizeof(float), "makebevelcurve p1");
+                       BLI_addtail(disp, dl);
+                       dl->type= DL_SEGM;
+                       dl->parts= 1;
+                       dl->flag= DL_BACK_CURVE;
+                       dl->nr= nr;
+
+                       /* half a circle */
+                       fp= dl->verts;
+                       dangle= (0.5*M_PI/(dnr-1));
+                       angle= -(nr-1)*dangle;
+
+                       for(a=0; a<nr; a++) {
+                               fp[0]= 0.0;
+                               fp[1]= (float)(cos(angle)*(cu->ext2));
+                               fp[2]= (float)(sin(angle)*(cu->ext2)) - cu->ext1;
+                               angle+= dangle;
+                               fp+= 3;
+                       }
                }
                
                /* part 2, sidefaces */
@@ -1317,35 +1407,37 @@ void makebevelcurve(Scene *scene, Object *ob, ListBase *disp)
                        }
                }
                
-               /* part 3 */
-               dnr= nr= 2+ cu->bevresol;
-               if( (cu->flag & (CU_FRONT|CU_BACK))==0)
-                       nr= 3+ 2*cu->bevresol;
-               
-               dl= MEM_callocN(sizeof(DispList), "makebevelcurve p3");
-               dl->verts= MEM_mallocN(nr*3*sizeof(float), "makebevelcurve p3");
-               BLI_addtail(disp, dl);
-               dl->type= DL_SEGM;
-               dl->flag= DL_FRONT_CURVE;
-               dl->parts= 1;
-               dl->nr= nr;
-               
-               /* half a circle */
-               fp= dl->verts;
-               angle= 0.0;
-               dangle= (0.5*M_PI/(dnr-1));
-               
-               for(a=0; a<nr; a++) {
-                       fp[0]= 0.0;
-                       fp[1]= (float)(cos(angle)*(cu->ext2));
-                       fp[2]= (float)(sin(angle)*(cu->ext2)) + cu->ext1;
-                       angle+= dangle;
-                       fp+= 3;
+               /* part 3, front */
+               if((cu->flag & CU_FRONT) || !(cu->flag & CU_BACK)) {
+                       dnr= nr= 2+ cu->bevresol;
+                       if( (cu->flag & (CU_FRONT|CU_BACK))==0)
+                               nr= 3+ 2*cu->bevresol;
+
+                       dl= MEM_callocN(sizeof(DispList), "makebevelcurve p3");
+                       dl->verts= MEM_mallocN(nr*3*sizeof(float), "makebevelcurve p3");
+                       BLI_addtail(disp, dl);
+                       dl->type= DL_SEGM;
+                       dl->flag= DL_FRONT_CURVE;
+                       dl->parts= 1;
+                       dl->nr= nr;
+
+                       /* half a circle */
+                       fp= dl->verts;
+                       angle= 0.0;
+                       dangle= (0.5*M_PI/(dnr-1));
+
+                       for(a=0; a<nr; a++) {
+                               fp[0]= 0.0;
+                               fp[1]= (float)(cos(angle)*(cu->ext2));
+                               fp[2]= (float)(sin(angle)*(cu->ext2)) + cu->ext1;
+                               angle+= dangle;
+                               fp+= 3;
+                       }
                }
        }
 }
 
-int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec)
+static int cu_isectLL(float *v1, float *v2, float *v3, float *v4, short cox, short coy, float *labda, float *mu, float *vec)
 {
        /* return:
                -1: colliniar
@@ -1390,8 +1482,8 @@ static short bevelinside(BevList *bl1,BevList *bl2)
        /* take first vertex of possible hole */
 
        bevp= (BevPoint *)(bl2+1);
-       hvec1[0]= bevp->x
-       hvec1[1]= bevp->y
+       hvec1[0]= bevp->vec[0]
+       hvec1[1]= bevp->vec[1]
        hvec1[2]= 0.0;
        VECCOPY(hvec2,hvec1);
        hvec2[0]+=1000;
@@ -1404,18 +1496,18 @@ static short bevelinside(BevList *bl1,BevList *bl2)
        prevbevp= bevp+(nr-1);
 
        while(nr--) {
-               min= prevbevp->y;
-               max= bevp->y;
+               min= prevbevp->vec[1];
+               max= bevp->vec[1];
                if(max<min) {
                        min= max;
-                       max= prevbevp->y;
+                       max= prevbevp->vec[1];
                }
                if(min!=max) {
                        if(min<=hvec1[1] && max>=hvec1[1]) {
                                /* there's a transition, calc intersection point */
-                               mode= cu_isectLL(&(prevbevp->x),&(bevp->x),hvec1,hvec2,0,1,&lab,&mu,vec);
+                               mode= cu_isectLL(prevbevp->vec, bevp->vec, hvec1, hvec2, 0, 1, &lab, &mu, vec);
                                /* if lab==0.0 or lab==1.0 then the edge intersects exactly a transition
-                                  only allow for one situation: we choose lab= 1.0
+                                          only allow for one situation: we choose lab= 1.0
                                 */
                                if(mode>=0 && lab!=0.0) {
                                        if(vec[0]<hvec1[0]) links++;
@@ -1486,24 +1578,27 @@ static void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *si
 
 }
 
-static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *tilt_array, float *radius_array, int resolu)
+static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *tilt_array, float *radius_array, float *weight_array, int resolu, int stride)
 {
        BezTriple *pprev, *next, *last;
        float fac, dfac, t[4];
        int a;
        
+       if(tilt_array==NULL && radius_array==NULL)
+               return;
+       
        last= nu->bezt+(nu->pntsu-1);
        
        /* returns a point */
        if(prevbezt==nu->bezt) {
-               if(nu->flagu & CU_CYCLIC) pprev= last;
+               if(nu->flagu & CU_NURB_CYCLIC) pprev= last;
                else pprev= prevbezt;
        }
        else pprev= prevbezt-1;
        
        /* next point */
        if(bezt==last) {
-               if(nu->flagu & CU_CYCLIC) next= nu->bezt;
+               if(nu->flagu & CU_NURB_CYCLIC) next= nu->bezt;
                else next= bezt;
        }
        else next= bezt+1;
@@ -1513,32 +1608,407 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *
        
        for(a=0; a<resolu; a++, fac+= dfac) {
                if (tilt_array) {
-                       if (nu->tilt_interp==3) { /* May as well support for tilt also 2.47 ease interp */
-                               tilt_array[a] = prevbezt->alfa + (bezt->alfa - prevbezt->alfa)*(3.0f*fac*fac - 2.0f*fac*fac*fac);
+                       if (nu->tilt_interp==KEY_CU_EASE) { /* May as well support for tilt also 2.47 ease interp */
+                               *tilt_array = prevbezt->alfa + (bezt->alfa - prevbezt->alfa)*(3.0f*fac*fac - 2.0f*fac*fac*fac);
                        } else {
-                               set_four_ipo(fac, t, nu->tilt_interp);
-                               tilt_array[a]= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa;
+                               key_curve_position_weights(fac, t, nu->tilt_interp);
+                               *tilt_array= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa;
                        }
+                       
+                       tilt_array = (float *)(((char *)tilt_array) + stride); 
                }
                
                if (radius_array) {
-                       if (nu->radius_interp==3) {
+                       if (nu->radius_interp==KEY_CU_EASE) {
                                /* Support 2.47 ease interp
                                 * Note! - this only takes the 2 points into account,
                                 * giving much more localized results to changes in radius, sometimes you want that */
-                               radius_array[a] = prevbezt->radius + (bezt->radius - prevbezt->radius)*(3.0f*fac*fac - 2.0f*fac*fac*fac);
+                               *radius_array = prevbezt->radius + (bezt->radius - prevbezt->radius)*(3.0f*fac*fac - 2.0f*fac*fac*fac);
                        } else {
                                
                                /* reuse interpolation from tilt if we can */
                                if (tilt_array==NULL || nu->tilt_interp != nu->radius_interp) {
-                                       set_four_ipo(fac, t, nu->radius_interp);
+                                       key_curve_position_weights(fac, t, nu->radius_interp);
                                }
-                               radius_array[a]= t[0]*pprev->radius + t[1]*prevbezt->radius + t[2]*bezt->radius + t[3]*next->radius;
+                               *radius_array= t[0]*pprev->radius + t[1]*prevbezt->radius + t[2]*bezt->radius + t[3]*next->radius;
                        }
+                       
+                       radius_array = (float *)(((char *)radius_array) + stride); 
+               }
+
+               if(weight_array) {
+                       /* basic interpolation for now, could copy tilt interp too  */
+                       *weight_array = prevbezt->weight + (bezt->weight - prevbezt->weight)*(3.0f*fac*fac - 2.0f*fac*fac*fac);
+
+                       weight_array = (float *)(((char *)weight_array) + stride);
+               }
+       }
+}
+
+/* make_bevel_list_3D_* funcs, at a minimum these must
+ * fill in the bezp->quat and bezp->dir values */
+
+/* correct non-cyclic cases by copying direction and rotation
+ * values onto the first & last end-points */
+static void bevel_list_cyclic_fix_3D(BevList *bl)
+{
+       BevPoint *bevp, *bevp1;
+
+       bevp= (BevPoint *)(bl+1);
+       bevp1= bevp+1;
+       QUATCOPY(bevp->quat, bevp1->quat);
+       VECCOPY(bevp->dir, bevp1->dir);
+       VECCOPY(bevp->tan, bevp1->tan);
+       bevp= (BevPoint *)(bl+1);
+       bevp+= (bl->nr-1);
+       bevp1= bevp-1;
+       QUATCOPY(bevp->quat, bevp1->quat);
+       VECCOPY(bevp->dir, bevp1->dir);
+       VECCOPY(bevp->tan, bevp1->tan);
+}
+/* utility for make_bevel_list_3D_* funcs */
+static void bevel_list_calc_bisect(BevList *bl)
+{
+       BevPoint *bevp2, *bevp1, *bevp0;
+       int nr;
+
+       bevp2= (BevPoint *)(bl+1);
+       bevp1= bevp2+(bl->nr-1);
+       bevp0= bevp1-1;
+
+       nr= bl->nr;
+       while(nr--) {
+               /* totally simple */
+               bisect_v3_v3v3v3(bevp1->dir, bevp0->vec, bevp1->vec, bevp2->vec);
+
+               bevp0= bevp1;
+               bevp1= bevp2;
+               bevp2++;
+       }
+}
+static void bevel_list_flip_tangents(BevList *bl)
+{
+       BevPoint *bevp2, *bevp1, *bevp0;
+       int nr;
+
+       bevp2= (BevPoint *)(bl+1);
+       bevp1= bevp2+(bl->nr-1);
+       bevp0= bevp1-1;
+
+       nr= bl->nr;
+       while(nr--) {
+               if(RAD2DEG(angle_v2v2(bevp0->tan, bevp1->tan)) > 90)
+                       negate_v3(bevp1->tan);
+
+               bevp0= bevp1;
+               bevp1= bevp2;
+               bevp2++;
+       }
+}
+/* apply user tilt */
+static void bevel_list_apply_tilt(BevList *bl)
+{
+       BevPoint *bevp2, *bevp1, *bevp0;
+       int nr;
+       float q[4];
+
+       bevp2= (BevPoint *)(bl+1);
+       bevp1= bevp2+(bl->nr-1);
+       bevp0= bevp1-1;
+
+       nr= bl->nr;
+       while(nr--) {
+               axis_angle_to_quat(q, bevp1->dir, bevp1->alfa);
+               mul_qt_qtqt(bevp1->quat, q, bevp1->quat);
+               normalize_qt(bevp1->quat);
+
+               bevp0= bevp1;
+               bevp1= bevp2;
+               bevp2++;
+       }
+}
+/* smooth quats, this function should be optimized, it can get slow with many iterations. */
+static void bevel_list_smooth(BevList *bl, int smooth_iter)
+{
+       BevPoint *bevp2, *bevp1, *bevp0;
+       int nr;
+
+       float q[4];
+       float bevp0_quat[4];
+       int a;
+
+       for(a=0; a < smooth_iter; a++) {
+
+               bevp2= (BevPoint *)(bl+1);
+               bevp1= bevp2+(bl->nr-1);
+               bevp0= bevp1-1;
+
+               nr= bl->nr;
+
+               if(bl->poly== -1) { /* check its not cyclic */
+                       /* skip the first point */
+                       /* bevp0= bevp1; */
+                       bevp1= bevp2;
+                       bevp2++;
+                       nr--;
+
+                       bevp0= bevp1;
+                       bevp1= bevp2;
+                       bevp2++;
+                       nr--;
+
                }
+
+               QUATCOPY(bevp0_quat, bevp0->quat);
+
+               while(nr--) {
+                       /* interpolate quats */
+                       float zaxis[3] = {0,0,1}, cross[3], q2[4];
+                       interp_qt_qtqt(q, bevp0_quat, bevp2->quat, 0.5);
+                       normalize_qt(q);
+
+                       mul_qt_v3(q, zaxis);
+                       cross_v3_v3v3(cross, zaxis, bevp1->dir);
+                       axis_angle_to_quat(q2, cross, angle_normalized_v3v3(zaxis, bevp1->dir));
+                       normalize_qt(q2);
+
+                       QUATCOPY(bevp0_quat, bevp1->quat);
+                       mul_qt_qtqt(q, q2, q);
+                       interp_qt_qtqt(bevp1->quat, bevp1->quat, q, 0.5);
+                       normalize_qt(bevp1->quat);
+
+
+                       /* bevp0= bevp1; */ /* UNUSED */
+                       bevp1= bevp2;
+                       bevp2++;
+               }
+       }
+}
+
+static void make_bevel_list_3D_zup(BevList *bl)
+{
+       BevPoint *bevp2, *bevp1, *bevp0; /* standard for all make_bevel_list_3D_* funcs */
+       int nr;
+
+       bevp2= (BevPoint *)(bl+1);
+       bevp1= bevp2+(bl->nr-1);
+       bevp0= bevp1-1;
+
+       nr= bl->nr;
+       while(nr--) {
+               /* totally simple */
+               bisect_v3_v3v3v3(bevp1->dir, bevp0->vec, bevp1->vec, bevp2->vec);
+               vec_to_quat( bevp1->quat,bevp1->dir, 5, 1);
+
+               bevp0= bevp1;
+               bevp1= bevp2;
+               bevp2++;
+       }
+}
+
+static void make_bevel_list_3D_minimum_twist(BevList *bl)
+{
+       BevPoint *bevp2, *bevp1, *bevp0; /* standard for all make_bevel_list_3D_* funcs */
+       int nr;
+       float q[4];
+
+       bevel_list_calc_bisect(bl);
+
+       bevp2= (BevPoint *)(bl+1);
+       bevp1= bevp2+(bl->nr-1);
+       bevp0= bevp1-1;
+
+       nr= bl->nr;
+       while(nr--) {
+
+               if(nr+4 > bl->nr) { /* first time and second time, otherwise first point adjusts last */
+                       vec_to_quat( bevp1->quat,bevp1->dir, 5, 1);
+               }
+               else {
+                       float angle= angle_normalized_v3v3(bevp0->dir, bevp1->dir);
+
+                       if(angle > 0.0f) { /* otherwise we can keep as is */
+                               float cross_tmp[3];
+                               cross_v3_v3v3(cross_tmp, bevp0->dir, bevp1->dir);
+                               axis_angle_to_quat(q, cross_tmp, angle);
+                               mul_qt_qtqt(bevp1->quat, q, bevp0->quat);
+                       }
+                       else {
+                               QUATCOPY(bevp1->quat, bevp0->quat);
+                       }
+               }
+
+               bevp0= bevp1;
+               bevp1= bevp2;
+               bevp2++;
+       }
+
+       if(bl->poly != -1) { /* check for cyclic */
+
+               /* Need to correct for the start/end points not matching
+                * do this by calculating the tilt angle difference, then apply
+                * the rotation gradually over the entire curve
+                *
+                * note that the split is between last and second last, rather then first/last as youd expect.
+                *
+                * real order is like this
+                * 0,1,2,3,4 --> 1,2,3,4,0
+                *
+                * this is why we compare last with second last
+                * */
+               float vec_1[3]= {0,1,0}, vec_2[3]= {0,1,0}, angle, ang_fac, cross_tmp[3];
+
+               BevPoint *bevp_first;
+               BevPoint *bevp_last;
+
+
+               bevp_first= (BevPoint *)(bl+1);
+               bevp_first+= bl->nr-1;
+               bevp_last = bevp_first;
+               bevp_last--;
+
+               /* quats and vec's are normalized, should not need to re-normalize */
+               mul_qt_v3(bevp_first->quat, vec_1);
+               mul_qt_v3(bevp_last->quat, vec_2);
+               normalize_v3(vec_1);
+               normalize_v3(vec_2);
+
+               /* align the vector, can avoid this and it looks 98% OK but
+                * better to align the angle quat roll's before comparing */
+               {
+                       cross_v3_v3v3(cross_tmp, bevp_last->dir, bevp_first->dir);
+                       angle = angle_normalized_v3v3(bevp_first->dir, bevp_last->dir);
+                       axis_angle_to_quat(q, cross_tmp, angle);
+                       mul_qt_v3(q, vec_2);
+               }
+
+               angle= angle_normalized_v3v3(vec_1, vec_2);
+
+               /* 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/(180.0/M_PI))
+                       angle = -angle;
+
+               bevp2= (BevPoint *)(bl+1);
+               bevp1= bevp2+(bl->nr-1);
+               bevp0= bevp1-1;
+
+               nr= bl->nr;
+               while(nr--) {
+                       ang_fac= angle * (1.0f-((float)nr/bl->nr)); /* also works */
+
+                       axis_angle_to_quat(q, bevp1->dir, ang_fac);
+                       mul_qt_qtqt(bevp1->quat, q, bevp1->quat);
+
+                       bevp0= bevp1;
+                       bevp1= bevp2;
+                       bevp2++;
+               }
+       }
+}
+
+static void make_bevel_list_3D_tangent(BevList *bl)
+{
+       BevPoint *bevp2, *bevp1, *bevp0; /* standard for all make_bevel_list_3D_* funcs */
+       int nr;
+
+       float bevp0_tan[3], cross_tmp[3];
+
+       bevel_list_calc_bisect(bl);
+       if(bl->poly== -1) /* check its not cyclic */
+               bevel_list_cyclic_fix_3D(bl); // XXX - run this now so tangents will be right before doing the flipping
+       bevel_list_flip_tangents(bl);
+
+       /* correct the tangents */
+       bevp2= (BevPoint *)(bl+1);
+       bevp1= bevp2+(bl->nr-1);
+       bevp0= bevp1-1;
+
+       nr= bl->nr;
+       while(nr--) {
+
+               cross_v3_v3v3(cross_tmp, bevp1->tan, bevp1->dir);
+               cross_v3_v3v3(bevp1->tan, cross_tmp, bevp1->dir);
+               normalize_v3(bevp1->tan);
+
+               bevp0= bevp1;
+               bevp1= bevp2;
+               bevp2++;
+       }
+
+
+       /* now for the real twist calc */
+       bevp2= (BevPoint *)(bl+1);
+       bevp1= bevp2+(bl->nr-1);
+       bevp0= bevp1-1;
+
+       VECCOPY(bevp0_tan, bevp0->tan);
+
+       nr= bl->nr;
+       while(nr--) {
+
+               /* make perpendicular, modify tan in place, is ok */
+               float cross_tmp[3];
+               float zero[3] = {0,0,0};
+
+               cross_v3_v3v3(cross_tmp, bevp1->tan, bevp1->dir);
+               normalize_v3(cross_tmp);
+               tri_to_quat( bevp1->quat,zero, cross_tmp, bevp1->tan); /* XXX - could be faster */
+
+               /* bevp0= bevp1; */ /* UNUSED */
+               bevp1= bevp2;
+               bevp2++;
+       }
+}
+
+static void make_bevel_list_3D(BevList *bl, int smooth_iter, int twist_mode)
+{
+       switch(twist_mode) {
+       case CU_TWIST_TANGENT:
+               make_bevel_list_3D_tangent(bl);
+               break;
+       case CU_TWIST_MINIMUM:
+               make_bevel_list_3D_minimum_twist(bl);
+               break;
+       default: /* CU_TWIST_Z_UP default, pre 2.49c */
+               make_bevel_list_3D_zup(bl);
        }
+
+       if(bl->poly== -1) /* check its not cyclic */
+               bevel_list_cyclic_fix_3D(bl);
+
+       if(smooth_iter)
+               bevel_list_smooth(bl, smooth_iter);
+
+       bevel_list_apply_tilt(bl);
 }
 
+
+
+/* only for 2 points */
+static void make_bevel_list_segment_3D(BevList *bl)
+{
+       float q[4];
+
+       BevPoint *bevp2= (BevPoint *)(bl+1);
+       BevPoint *bevp1= bevp2+1;
+
+       /* simple quat/dir */
+       sub_v3_v3v3(bevp1->dir, bevp1->vec, bevp2->vec);
+       normalize_v3(bevp1->dir);
+
+       vec_to_quat( bevp1->quat,bevp1->dir, 5, 1);
+
+       axis_angle_to_quat(q, bevp1->dir, bevp1->alfa);
+       mul_qt_qtqt(bevp1->quat, q, bevp1->quat);
+       normalize_qt(bevp1->quat);
+       VECCOPY(bevp2->dir, bevp1->dir);
+       QUATCOPY(bevp2->quat, bevp1->quat);
+}
+
+
+
 void makeBevelList(Object *ob)
 {
        /*
@@ -1553,12 +2023,10 @@ void makeBevelList(Object *ob)
        BPoint *bp;
        BevList *bl, *blnew, *blnext;
        BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0;
-       float min, inp, x1, x2, y1, y2, vec[3], vec_prev[3], q[4], quat[4], quat_prev[4], cross[3];
-       float *coord_array, *tilt_array=NULL, *radius_array=NULL, *coord_fp, *tilt_fp=NULL, *radius_fp=NULL;
-       float *v1, *v2;
+       float min, inp, x1, x2, y1, y2;
        struct bevelsort *sortdata, *sd, *sd1;
-       int a, b, nr, poly, resolu, len=0;
-       int do_tilt, do_radius;
+       int a, b, nr, poly, resolu = 0, len = 0;
+       int do_tilt, do_radius, do_weight;
        
        /* this function needs an object, because of tflag and upflag */
        cu= ob->data;
@@ -1569,14 +2037,17 @@ void makeBevelList(Object *ob)
        /* STEP 1: MAKE POLYS  */
 
        BLI_freelistN(&(cu->bev));
-       if(cu->editnurb && ob->type!=OB_FONT) nu= cu->editnurb->first;
-       else nu= cu->nurb.first;
+       if(cu->editnurb && ob->type!=OB_FONT) {
+               ListBase *nurbs= ED_curve_editnurbs(cu);
+               nu= nurbs->first;
+       } else nu= cu->nurb.first;
        
        while(nu) {
                
                /* check if we will calculate tilt data */
                do_tilt = CU_DO_TILT(cu, nu);
                do_radius = CU_DO_RADIUS(cu, nu); /* normal display uses the radius, better just to calculate them */
+               do_weight = 1;
                
                /* check we are a single point? also check we are not a surface and that the orderu is sane,
                 * enforced in the UI but can go wrong possibly */
@@ -1595,37 +2066,36 @@ void makeBevelList(Object *ob)
                                bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList2");
                                BLI_addtail(&(cu->bev), bl);
        
-                               if(nu->flagu & CU_CYCLIC) bl->poly= 0;
+                               if(nu->flagu & CU_NURB_CYCLIC) bl->poly= 0;
                                else bl->poly= -1;
                                bl->nr= len;
-                               bl->flag= 0;
+                               bl->dupe_nr= 0;
                                bevp= (BevPoint *)(bl+1);
                                bp= nu->bp;
        
                                while(len--) {
-                                       bevp->x= bp->vec[0];
-                                       bevp->y= bp->vec[1];
-                                       bevp->z= bp->vec[2];
+                                       VECCOPY(bevp->vec, bp->vec);
                                        bevp->alfa= bp->alfa;
                                        bevp->radius= bp->radius;
-                                       bevp->f1= SELECT;
+                                       bevp->weight= bp->weight;
+                                       bevp->split_tag= TRUE;
                                        bevp++;
                                        bp++;
                                }
                        }
                        else if(nu->type == CU_BEZIER) {
        
-                               len= resolu*(nu->pntsu+ (nu->flagu & CU_CYCLIC) -1)+1;  /* in case last point is not cyclic */
+                               len= resolu*(nu->pntsu+ (nu->flagu & CU_NURB_CYCLIC) -1)+1;     /* in case last point is not cyclic */
                                bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelBPoints");
                                BLI_addtail(&(cu->bev), bl);
        
-                               if(nu->flagu & CU_CYCLIC) bl->poly= 0;
+                               if(nu->flagu & CU_NURB_CYCLIC) bl->poly= 0;
                                else bl->poly= -1;
                                bevp= (BevPoint *)(bl+1);
        
                                a= nu->pntsu-1;
                                bezt= nu->bezt;
-                               if(nu->flagu & CU_CYCLIC) {
+                               if(nu->flagu & CU_NURB_CYCLIC) {
                                        a++;
                                        prevbezt= nu->bezt+(nu->pntsu-1);
                                }
@@ -1634,90 +2104,65 @@ void makeBevelList(Object *ob)
                                        bezt++;
                                }
                                
-                               coord_array= coord_fp= MEM_mallocN(3*sizeof(float)*(resolu+1), "makeBevelCoords");
-                               
-                               if(do_tilt)
-                                       tilt_array= tilt_fp= MEM_callocN(sizeof(float)*(resolu+1), "makeBevelTilt");
-                               
-                               if (do_radius)
-                                       radius_array= radius_fp= MEM_callocN(sizeof(float)*(resolu+1), "nakeBevelRadius");
-                               
                                while(a--) {
                                        if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) {
-       
-                                               bevp->x= prevbezt->vec[1][0];
-                                               bevp->y= prevbezt->vec[1][1];
-                                               bevp->z= prevbezt->vec[1][2];
+
+                                               VECCOPY(bevp->vec, prevbezt->vec[1]);
                                                bevp->alfa= prevbezt->alfa;
                                                bevp->radius= prevbezt->radius;
-                                               bevp->f1= SELECT;
-                                               bevp->f2= 0;
+                                               bevp->weight= prevbezt->weight;
+                                               bevp->split_tag= TRUE;
+                                               bevp->dupe_tag= FALSE;
                                                bevp++;
                                                bl->nr++;
-                                               bl->flag= 1;
+                                               bl->dupe_nr= 1;
                                        }
                                        else {
-                                               v1= prevbezt->vec[1];
-                                               v2= bezt->vec[0];
-                                               
                                                /* always do all three, to prevent data hanging around */
-                                               forward_diff_bezier(v1[0], v1[3], v2[0], v2[3], coord_array, resolu, 3);
-                                               forward_diff_bezier(v1[1], v1[4], v2[1], v2[4], coord_array+1, resolu, 3);
-                                               forward_diff_bezier(v1[2], v1[5], v2[2], v2[5], coord_array+2, resolu, 3);
+                                               int j;
+                                               
+                                               /* BevPoint must stay aligned to 4 so sizeof(BevPoint)/sizeof(float) works */
+                                               for(j=0; j<3; j++) {
+                                                       forward_diff_bezier(    prevbezt->vec[1][j],    prevbezt->vec[2][j],
+                                                                                                       bezt->vec[0][j],                bezt->vec[1][j],
+                                                                                                       &(bevp->vec[j]), resolu, sizeof(BevPoint));
+                                               }
                                                
-                                               if (do_tilt || do_radius)
-                                                       alfa_bezpart(prevbezt, bezt, nu, tilt_array, radius_array, resolu);
+                                               /* if both arrays are NULL do nothiong */
+                                               alfa_bezpart(   prevbezt, bezt, nu,
+                                                                                do_tilt        ? &bevp->alfa : NULL,
+                                                                                do_radius      ? &bevp->radius : NULL,
+                                                                                do_weight      ? &bevp->weight : NULL,
+                                                                                resolu, sizeof(BevPoint));
+
                                                
+                                               if(cu->twist_mode==CU_TWIST_TANGENT) {
+                                                       forward_diff_bezier_cotangent(
+                                                                                                       prevbezt->vec[1],       prevbezt->vec[2],
+                                                                                                       bezt->vec[0],           bezt->vec[1],
+                                                                                                       bevp->tan, resolu, sizeof(BevPoint));
+                                               }
+
                                                /* indicate with handlecodes double points */
                                                if(prevbezt->h1==prevbezt->h2) {
-                                                       if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= SELECT;
+                                                       if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->split_tag= TRUE;
                                                }
                                                else {
-                                                       if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->f1= SELECT;
-                                                       else if(prevbezt->h2==0 || prevbezt->h2==HD_VECT) bevp->f1= SELECT;
-                                               }
-                                               
-                                               nr= resolu;
-                                               
-                                               coord_fp = coord_array;
-                                               tilt_fp = tilt_array;
-                                               radius_fp = radius_array;
-                                               
-                                               while(nr--) {
-                                                       bevp->x= coord_fp[0]; 
-                                                       bevp->y= coord_fp[1];
-                                                       bevp->z= coord_fp[2];
-                                                       coord_fp+=3;
-                                                       
-                                                       if (do_tilt) {
-                                                               bevp->alfa= *tilt_fp;
-                                                               tilt_fp++;
-                                                       }
-                                                       
-                                                       if (do_radius) {
-                                                               bevp->radius= *radius_fp;
-                                                               radius_fp++;
-                                                       }
-                                                       bevp++;
+                                                       if(prevbezt->h1==0 || prevbezt->h1==HD_VECT) bevp->split_tag= TRUE;
+                                                       else if(prevbezt->h2==0 || prevbezt->h2==HD_VECT) bevp->split_tag= TRUE;
                                                }
                                                bl->nr+= resolu;
-       
+                                               bevp+= resolu;
                                        }
                                        prevbezt= bezt;
                                        bezt++;
                                }
                                
-                               MEM_freeN(coord_array);
-                               if (do_tilt)    MEM_freeN(tilt_array);
-                               if (do_radius)  MEM_freeN(radius_array);
-                               coord_array = tilt_array = radius_array = NULL;
-                               
-                               if((nu->flagu & CU_CYCLIC)==0) {            /* not cyclic: endpoint */
-                                       bevp->x= prevbezt->vec[1][0];
-                                       bevp->y= prevbezt->vec[1][1];
-                                       bevp->z= prevbezt->vec[1][2];
+                               if((nu->flagu & CU_NURB_CYCLIC)==0) {       /* not cyclic: endpoint */
+                                       VECCOPY(bevp->vec, prevbezt->vec[1]);
                                        bevp->alfa= prevbezt->alfa;
                                        bevp->radius= prevbezt->radius;
+                                       bevp->weight= prevbezt->weight;
                                        bl->nr++;
                                }
                        }
@@ -1728,45 +2173,16 @@ void makeBevelList(Object *ob)
                                        bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList3");
                                        BLI_addtail(&(cu->bev), bl);
                                        bl->nr= len;
-                                       bl->flag= 0;
-                                       if(nu->flagu & CU_CYCLIC) bl->poly= 0;
+                                       bl->dupe_nr= 0;
+                                       if(nu->flagu & CU_NURB_CYCLIC) bl->poly= 0;
                                        else bl->poly= -1;
                                        bevp= (BevPoint *)(bl+1);
-       
-                                       coord_array= coord_fp= MEM_callocN(3*sizeof(float)*len, "makeBevelCoords");    /* has to be zero-ed */
-                                       
-                                       if(do_tilt)
-                                               tilt_array= tilt_fp= MEM_callocN(sizeof(float)*len, "makeBevelTilt");
-                                       
-                                       if (do_radius)
-                                               radius_array= radius_fp= MEM_callocN(sizeof(float)*len, "nakeBevelRadius");
                                        
-                                       makeNurbcurve(nu, coord_array, tilt_array, radius_array, resolu);
-                                       
-                                       while(len--) {
-                                               bevp->x= coord_fp[0]; 
-                                               bevp->y= coord_fp[1];
-                                               bevp->z= coord_fp[2];
-                                               coord_fp+=3;
-                                               
-                                               if (do_tilt) {
-                                                       bevp->alfa= *tilt_fp;
-                                                       tilt_fp++;
-                                               }
-                                               
-                                               if (do_radius) {
-                                                       bevp->radius= *radius_fp;
-                                                       radius_fp++;
-                                               }
-                                               
-                                               
-                                               bevp->f1= bevp->f2= 0;
-                                               bevp++;
-                                       }
-                                       MEM_freeN(coord_array);
-                                       if (do_tilt)    MEM_freeN(tilt_array);
-                                       if (do_radius)  MEM_freeN(radius_array);
-                                       coord_array = tilt_array = radius_array = NULL;
+                                       makeNurbcurve(  nu, &bevp->vec[0],
+                                                                       do_tilt         ? &bevp->alfa : NULL,
+                                                                       do_radius       ? &bevp->radius : NULL,
+                                                                       do_weight       ? &bevp->weight : NULL,
+                                                                       resolu, sizeof(BevPoint));
                                }
                        }
                }
@@ -1782,11 +2198,11 @@ void makeBevelList(Object *ob)
                        bevp0= bevp1+(nr-1);
                        nr--;
                        while(nr--) {
-                               if( fabs(bevp0->x-bevp1->x)<0.00001 ) {
-                                       if( fabs(bevp0->y-bevp1->y)<0.00001 ) {
-                                               if( fabs(bevp0->z-bevp1->z)<0.00001 ) {
-                                                       bevp0->f2= SELECT;
-                                                       bl->flag++;
+                               if( fabs(bevp0->vec[0]-bevp1->vec[0])<0.00001 ) {
+                                       if( fabs(bevp0->vec[1]-bevp1->vec[1])<0.00001 ) {
+                                               if( fabs(bevp0->vec[2]-bevp1->vec[2])<0.00001 ) {
+                                                       bevp0->dupe_tag= TRUE;
+                                                       bl->dupe_nr++;
                                                }
                                        }
                                }
@@ -1799,8 +2215,8 @@ void makeBevelList(Object *ob)
        bl= cu->bev.first;
        while(bl) {
                blnext= bl->next;
-               if(bl->nr && bl->flag) {
-                       nr= bl->nr- bl->flag+1; /* +1 because vectorbezier sets flag too */
+               if(bl->nr && bl->dupe_nr) {
+                       nr= bl->nr- bl->dupe_nr+1;      /* +1 because vectorbezier sets flag too */
                        blnew= MEM_mallocN(sizeof(BevList)+nr*sizeof(BevPoint), "makeBevelList4");
                        memcpy(blnew, bl, sizeof(BevList));
                        blnew->nr= 0;
@@ -1810,7 +2226,7 @@ void makeBevelList(Object *ob)
                        bevp1= (BevPoint *)(blnew+1);
                        nr= bl->nr;
                        while(nr--) {
-                               if(bevp0->f2==0) {
+                               if(bevp0->dupe_tag==0) {
                                        memcpy(bevp1, bevp0, sizeof(BevPoint));
                                        bevp1++;
                                        blnew->nr++;
@@ -1818,7 +2234,7 @@ void makeBevelList(Object *ob)
                                bevp0++;
                        }
                        MEM_freeN(bl);
-                       blnew->flag= 0;
+                       blnew->dupe_nr= 0;
                }
                bl= blnext;
        }
@@ -1847,8 +2263,8 @@ void makeBevelList(Object *ob)
                                bevp= (BevPoint *)(bl+1);
                                nr= bl->nr;
                                while(nr--) {
-                                       if(min>bevp->x) {
-                                               min= bevp->x;
+                                       if(min>bevp->vec[0]) {
+                                               min= bevp->vec[0];
                                                bevp1= bevp;
                                        }
                                        bevp++;
@@ -1863,8 +2279,7 @@ void makeBevelList(Object *ob)
                                if(bevp1== bevp) bevp2= (BevPoint *)(bl+1);
                                else bevp2= bevp1+1;
 
-                               inp= (bevp1->x- bevp0->x)*(bevp0->y- bevp2->y)
-                                   +(bevp0->y- bevp1->y)*(bevp0->x- bevp2->x);
+                               inp= (bevp1->vec[0]- bevp0->vec[0]) * (bevp0->vec[1]- bevp2->vec[1]) + (bevp0->vec[1]- bevp1->vec[1]) * (bevp0->vec[0]- bevp2->vec[0]);
 
                                if(inp>0.0) sd->dir= 1;
                                else sd->dir= 0;
@@ -1908,208 +2323,89 @@ void makeBevelList(Object *ob)
                MEM_freeN(sortdata);
        }
 
-       /* STEP 4: COSINES */
-       bl= cu->bev.first;
-       while(bl) {
-       
-               if(bl->nr < 2) {
-                       /* do nothing */
-               }
-               else if(bl->nr==2) {    /* 2 pnt, treat separate */
-                       bevp2= (BevPoint *)(bl+1);
-                       bevp1= bevp2+1;
-
-                       x1= bevp1->x- bevp2->x;
-                       y1= bevp1->y- bevp2->y;
-
-                       calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa));
-                       bevp2->sina= bevp1->sina;
-                       bevp2->cosa= bevp1->cosa;
+       /* STEP 4: 2D-COSINES or 3D ORIENTATION */
+       if((cu->flag & CU_3D)==0) {
+               /* note: bevp->dir and bevp->quat are not needed for beveling but are
+                * used when making a path from a 2D curve, therefor they need to be set - Campbell */
+               bl= cu->bev.first;
+               while(bl) {
 
-                       if(cu->flag & CU_3D) {  /* 3D */
-                               float quat[4], q[4];
-                       
-                               VecSubf(vec, &bevp1->x, &bevp2->x);
-                               
-                               vectoquat(vec, 5, 1, quat);
-                               
-                               AxisAngleToQuat(q, vec, bevp1->alfa);
-                               QuatMul(quat, q, quat);
-                               
-                               QuatToMat3(quat, bevp1->mat);
-                               Mat3CpyMat3(bevp2->mat, bevp1->mat);
+                       if(bl->nr < 2) {
+                               /* do nothing */
                        }
+                       else if(bl->nr==2) {    /* 2 pnt, treat separate */
+                               bevp2= (BevPoint *)(bl+1);
+                               bevp1= bevp2+1;
 
-               }       /* this has to be >2 points */
-               else if(cu->flag & CU_NO_TWIST && cu->flag & CU_3D && bl->poly != -1) {
-
-                       /* Special case, cyclic curve with no twist. tricky... */
-
-                       float quat[4], q[4], cross[3];
-
-                       /* correcting a cyclic curve is more complicated, need to be corrected from both ends */
-                       float *quat_tmp1, *quat_tmp2; /* store a quat in the matrix temporarily */
-                       int iter_dir;
-                       BevPoint *bevp_start= (BevPoint *)(bl+1);
+                               x1= bevp1->vec[0]- bevp2->vec[0];
+                               y1= bevp1->vec[1]- bevp2->vec[1];
 
-                       /* loop over the points twice, once up, once back, accumulate the quat rotations
-                        * in both directions, then blend them in the 3rd loop and apply the tilt */
-                       for(iter_dir = 0; iter_dir < 2; iter_dir++) {
+                               calc_bevel_sin_cos(x1, y1, -x1, -y1, &(bevp1->sina), &(bevp1->cosa));
+                               bevp2->sina= bevp1->sina;
+                               bevp2->cosa= bevp1->cosa;
 
+                               /* fill in dir & quat */
+                               make_bevel_list_segment_3D(bl);
+                       }
+                       else {
                                bevp2= (BevPoint *)(bl+1);
                                bevp1= bevp2+(bl->nr-1);
                                bevp0= bevp1-1;
 
                                nr= bl->nr;
                                while(nr--) {
-       
-                                       /* Normalizes */
-                                       VecBisect3(vec, &bevp0->x, &bevp1->x, &bevp2->x);
-
-                                       if(bl->nr==nr+1) { /* first time */
-                                               vectoquat(vec, 5, 1, quat);
-                                       }
-                                       else {
-                                               float angle = NormalizedVecAngle2(vec_prev, vec);
-                                       
-                                               if(angle > 0.0f) { /* otherwise we can keep as is */
-                                                       Crossf(cross, vec_prev, vec);
-                                                       AxisAngleToQuat(q, cross, angle);
-                                                       QuatMul(quat, q, quat_prev);
-                                               }
-                                               else {
-                                                       QUATCOPY(quat, quat_prev);
-                                               }
-                                       }
-                                       QUATCOPY(quat_prev, quat); /* quat_prev can't have the tilt applied */
-                                       VECCOPY(vec_prev, vec);
-
-                                       if(iter_dir==0) { /* up, first time */
-                                               quat_tmp1= (float *)bevp1->mat;
-
-                                               bevp0= bevp1;
-                                               bevp1= bevp2;
-                                               bevp2++;
-                                       }
-                                       else { /* down second time */
-                                               quat_tmp1= ((float *)bevp1->mat)+4;
-
-                                               bevp2= bevp1;
-                                               bevp1= bevp0;
-                                               bevp0--;
-
-                                               /* wrap around */
-                                               if (bevp0 < bevp_start)
-                                                       bevp0= bevp_start+(bl->nr-1);
-                                       }
-
-                                       QUATCOPY(quat_tmp1, quat);
+                                       x1= bevp1->vec[0]- bevp0->vec[0];
+                                       x2= bevp1->vec[0]- bevp2->vec[0];
+                                       y1= bevp1->vec[1]- bevp0->vec[1];
+                                       y2= bevp1->vec[1]- bevp2->vec[1];
+
+                                       calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa));
+
+                                       /* from: make_bevel_list_3D_zup, could call but avoid a second loop.
+                                        * no need for tricky tilt calculation as with 3D curves */
+                                       bisect_v3_v3v3v3(bevp1->dir, bevp0->vec, bevp1->vec, bevp2->vec);
+                                       vec_to_quat( bevp1->quat,bevp1->dir, 5, 1);
+                                       /* done with inline make_bevel_list_3D_zup */
+
+                                       bevp0= bevp1;
+                                       bevp1= bevp2;
+                                       bevp2++;
                                }
-                       }
-
-                       /* Now interpolate the 2 quats and apply tilt */
-
-                       bevp2= (BevPoint *)(bl+1);
-                       bevp1= bevp2+(bl->nr-1);
-                       bevp0= bevp1-1;
-
-                       nr= bl->nr;
-                       while(nr--) {
-
-                               VecBisect3(vec, &bevp0->x, &bevp1->x, &bevp2->x);
-
-                               quat_tmp1= (float *)bevp1->mat;
-                               quat_tmp2= quat_tmp1+4;
-
-                               /* blend the 2 rotations gathered from both directions */
-                               QuatInterpol(quat, quat_tmp1, quat_tmp2, 1.0 - (((float)nr)/bl->nr));
-
-                               AxisAngleToQuat(q, vec, bevp1->alfa);
-                               QuatMul(quat, q, quat);
-                               QuatToMat3(quat, bevp1->mat);
-                               
-                               /* generic */
-                               x1= bevp1->x- bevp0->x;
-                               x2= bevp1->x- bevp2->x;
-                               y1= bevp1->y- bevp0->y;
-                               y2= bevp1->y- bevp2->y;
-                       
-                               calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa));
-                               
-                               bevp0= bevp1;
-                               bevp1= bevp2;
-                               bevp2++;
-                       }
-               }
-               else {
-                       /* Any curve with 3 or more points */
-
-                       bevp2= (BevPoint *)(bl+1);
-                       bevp1= bevp2+(bl->nr-1);
-                       bevp0= bevp1-1;
-
-                       nr= bl->nr;
-                       while(nr--) {
-
-                               if(cu->flag & CU_3D) {  /* 3D */
-
-                                       /* Normalizes */
-                                       VecBisect3(vec, &bevp0->x, &bevp1->x, &bevp2->x);
-
-                                       if(bl->nr==nr+1 || !(cu->flag & CU_NO_TWIST)) { /* first time */
-                                               vectoquat(vec, 5, 1, quat);
-                                       }
-                                       else {
-                                               float angle = NormalizedVecAngle2(vec_prev, vec);
-
-                                               if(angle > 0.0f) { /* otherwise we can keep as is */
-                                                       Crossf(cross, vec_prev, vec);
-                                                       AxisAngleToQuat(q, cross, angle);
-                                                       QuatMul(quat, q, quat_prev);
-                                               }
-                                               else {
-                                                       QUATCOPY(quat, quat_prev);
-                                               }
-                                       }
-                                       QUATCOPY(quat_prev, quat); /* quat_prev can't have the tilt applied */
-                                       VECCOPY(vec_prev, vec);
-                                       
-                                       AxisAngleToQuat(q, vec, bevp1->alfa);
-                                       QuatMul(quat, q, quat);
-                                       QuatToMat3(quat, bevp1->mat);
-                               }
-
-                               x1= bevp1->x- bevp0->x;
-                               x2= bevp1->x- bevp2->x;
-                               y1= bevp1->y- bevp0->y;
-                               y2= bevp1->y- bevp2->y;
-
-                               calc_bevel_sin_cos(x1, y1, x2, y2, &(bevp1->sina), &(bevp1->cosa));
 
-
-                               bevp0= bevp1;
-                               bevp1= bevp2;
-                               bevp2++;
-                       }
-
-                       /* correct non-cyclic cases */
-                       if(bl->poly== -1) {
-                               if(bl->nr>2) {
+                               /* correct non-cyclic cases */
+                               if(bl->poly== -1) {
                                        bevp= (BevPoint *)(bl+1);
                                        bevp1= bevp+1;
                                        bevp->sina= bevp1->sina;
                                        bevp->cosa= bevp1->cosa;
-                                       Mat3CpyMat3(bevp->mat, bevp1->mat);
                                        bevp= (BevPoint *)(bl+1);
                                        bevp+= (bl->nr-1);
                                        bevp1= bevp-1;
                                        bevp->sina= bevp1->sina;
                                        bevp->cosa= bevp1->cosa;
-                                       Mat3CpyMat3(bevp->mat, bevp1->mat);
+
+                                       /* correct for the dir/quat, see above why its needed */
+                                       bevel_list_cyclic_fix_3D(bl);
                                }
                        }
+                       bl= bl->next;
+               }
+       }
+       else { /* 3D Curves */
+               bl= cu->bev.first;
+               while(bl) {
+
+                       if(bl->nr < 2) {
+                               /* do nothing */
+                       }
+                       else if(bl->nr==2) {    /* 2 pnt, treat separate */
+                               make_bevel_list_segment_3D(bl);
+                       }
+                       else {
+                               make_bevel_list_3D(bl, (int)(resolu*cu->twist_smooth), cu->twist_mode);
+                       }
+                       bl= bl->next;
                }
-               bl= bl->next;
        }
 }
 
@@ -2117,7 +2413,7 @@ void makeBevelList(Object *ob)
 
 /*
  *   handlecodes:
- *             1: nothing,  1:auto,  2:vector,  3:aligned
+ *             0: nothing,  1:auto,  2:vector,  3:aligned
  */
 
 /* mode: is not zero when FCurve, is 2 when forced horizontal for autohandles */
@@ -2130,7 +2426,7 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
 
        p2= bezt->vec[1];
 
-       if(prev==0) {
+       if(prev==NULL) {
                p3= next->vec[1];
                pt[0]= 2*p2[0]- p3[0];
                pt[1]= 2*p2[1]- p3[1];
@@ -2139,7 +2435,7 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
        }
        else p1= prev->vec[1];
 
-       if(next==0) {
+       if(next==NULL) {
                pt[0]= 2*p2[0]- p1[0];
                pt[1]= 2*p2[1]- p1[1];
                pt[2]= 2*p2[2]- p1[2];
@@ -2235,10 +2531,10 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
                        if(leftviolate || rightviolate) {       /* align left handle */
                                float h1[3], h2[3];
                                
-                               VecSubf(h1, p2-3, p2);
-                               VecSubf(h2, p2, p2+3);
-                               len1= Normalize(h1);
-                               len2= Normalize(h2);
+                               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);
                                
@@ -2274,8 +2570,8 @@ void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
                *(p2+5)= *(p2+2)+dz1;
        }
 
-       len2= VecLenf(p2, p2+3);
-       len1= VecLenf(p2, p2-3);
+       len2= len_v3v3(p2, p2+3);
+       len1= len_v3v3(p2, p2-3);
        if(len1==0.0) len1=1.0;
        if(len2==0.0) len2=1.0;
 
@@ -2319,16 +2615,16 @@ void calchandlesNurb(Nurb *nu) /* first, if needed, set handle flags */
        
        a= nu->pntsu;
        bezt= nu->bezt;
-       if(nu->flagu & CU_CYCLIC) prev= bezt+(a-1);
-       else prev= 0;
+       if(nu->flagu & CU_NURB_CYCLIC) prev= bezt+(a-1);
+       else prev= NULL;
        next= bezt+1;
 
        while(a--) {
                calchandleNurb(bezt, prev, next, 0);
                prev= bezt;
                if(a==1) {
-                       if(nu->flagu & CU_CYCLIC) next= nu->bezt;
-                       else next= 0;
+                       if(nu->flagu & CU_NURB_CYCLIC) next= nu->bezt;
+                       else next= NULL;
                }
                else next++;
 
@@ -2339,13 +2635,13 @@ void calchandlesNurb(Nurb *nu) /* first, if needed, set handle flags */
 
 void testhandlesNurb(Nurb *nu)
 {
-    /* use when something has changed with handles.
-    it treats all BezTriples with the following rules:
-    PHASE 1: do types have to be altered?
-       Auto handles: become aligned when selection status is NOT(000 || 111)
-       Vector handles: become 'nothing' when (one half selected AND other not)
-    PHASE 2: recalculate handles
-    */
+       /* use when something has changed with handles.
+       it treats all BezTriples with the following rules:
+       PHASE 1: do types have to be altered?
+          Auto handles: become aligned when selection status is NOT(000 || 111)
+          Vector handles: become 'nothing' when (one half selected AND other not)
+       PHASE 2: recalculate handles
+       */
        BezTriple *bezt;
        short flag, a;
 
@@ -2387,7 +2683,7 @@ void autocalchandlesNurb(Nurb *nu, int flag)
        BezTriple *bezt2, *bezt1, *bezt0;
        int i, align, leftsmall, rightsmall;
 
-       if(nu==0 || nu->bezt==0) return;
+       if(nu==NULL || nu->bezt==NULL) return;
        
        bezt2 = nu->bezt;
        bezt1 = bezt2 + (nu->pntsu-1);
@@ -2402,18 +2698,18 @@ void autocalchandlesNurb(Nurb *nu, int flag)
                if(flag==0 || (bezt1->f1 & flag) ) {
                        bezt1->h1= 0;
                        /* distance too short: vectorhandle */
-                       if( VecLenf( bezt1->vec[1], bezt0->vec[1] ) < 0.0001) {
+                       if( len_v3v3( bezt1->vec[1], bezt0->vec[1] ) < 0.0001) {
                                bezt1->h1= HD_VECT;
                                leftsmall= 1;
                        }
                        else {
                                /* aligned handle? */
-                               if(DistVL2Dfl(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < 0.0001) {
+                               if(dist_to_line_v2(bezt1->vec[1], bezt1->vec[0], bezt1->vec[2]) < 0.0001) {
                                        align= 1;
                                        bezt1->h1= HD_ALIGN;
                                }
                                /* or vector handle? */
-                               if(DistVL2Dfl(bezt1->vec[0], bezt1->vec[1], bezt0->vec[1]) < 0.0001)
+                               if(dist_to_line_v2(bezt1->vec[0], bezt1->vec[1], bezt0->vec[1]) < 0.0001)
                                        bezt1->h1= HD_VECT;
                                
                        }
@@ -2422,7 +2718,7 @@ void autocalchandlesNurb(Nurb *nu, int flag)
                if(flag==0 || (bezt1->f3 & flag) ) {
                        bezt1->h2= 0;
                        /* distance too short: vectorhandle */
-                       if( VecLenf( bezt1->vec[1], bezt2->vec[1] ) < 0.0001) {
+                       if( len_v3v3( bezt1->vec[1], bezt2->vec[1] ) < 0.0001) {
                                bezt1->h2= HD_VECT;
                                rightsmall= 1;
                        }
@@ -2431,7 +2727,7 @@ void autocalchandlesNurb(Nurb *nu, int flag)
                                if(align) bezt1->h2= HD_ALIGN;
 
                                /* or vector handle? */
-                               if(DistVL2Dfl(bezt1->vec[2], bezt1->vec[1], bezt2->vec[1]) < 0.0001)
+                               if(dist_to_line_v2(bezt1->vec[2], bezt1->vec[1], bezt2->vec[1]) < 0.0001)
                                        bezt1->h2= HD_VECT;
                                
                        }
@@ -2612,38 +2908,41 @@ void switchdirectionNurb(Nurb *nu)
                        bp2--;
                }
                if(nu->type == CU_NURBS) {
-                       /* inverse knots */
-                       a= KNOTSU(nu);
-                       fp1= nu->knotsu;
-                       fp2= fp1+(a-1);
-                       a/= 2;
-                       while(fp1!=fp2 && a>0) {
-                               SWAP(float, *fp1, *fp2);
-                               a--;
-                               fp1++; 
-                               fp2--;
-                       }
-                       /* and make in increasing order again */
-                       a= KNOTSU(nu);
-                       fp1= nu->knotsu;
-                       fp2=tempf= MEM_mallocN(sizeof(float)*a, "switchdirect");
-                       while(a--) {
-                               fp2[0]= fabs(fp1[1]-fp1[0]);
-                               fp1++;
-                               fp2++;
-                       }
-       
-                       a= KNOTSU(nu)-1;
-                       fp1= nu->knotsu;
-                       fp2= tempf;
-                       fp1[0]= 0.0;
-                       fp1++;
-                       while(a--) {
-                               fp1[0]= fp1[-1]+fp2[0];
+                       /* no knots for too short paths */
+                       if(nu->knotsu) {
+                               /* inverse knots */
+                               a= KNOTSU(nu);
+                               fp1= nu->knotsu;
+                               fp2= fp1+(a-1);
+                               a/= 2;
+                               while(fp1!=fp2 && a>0) {
+                                       SWAP(float, *fp1, *fp2);
+                                       a--;
+                                       fp1++; 
+                                       fp2--;
+                               }
+                               /* and make in increasing order again */
+                               a= KNOTSU(nu);
+                               fp1= nu->knotsu;
+                               fp2=tempf= MEM_mallocN(sizeof(float)*a, "switchdirect");
+                               while(a--) {
+                                       fp2[0]= fabs(fp1[1]-fp1[0]);
+                                       fp1++;
+                                       fp2++;
+                               }
+               
+                               a= KNOTSU(nu)-1;
+                               fp1= nu->knotsu;
+                               fp2= tempf;
+                               fp1[0]= 0.0;
                                fp1++;
-                               fp2++;
+                               while(a--) {
+                                       fp1[0]= fp1[-1]+fp2[0];
+                                       fp1++;
+                                       fp2++;
+                               }
+                               MEM_freeN(tempf);
                        }
-                       MEM_freeN(tempf);
                }
        }
        else {
@@ -2666,7 +2965,7 @@ void switchdirectionNurb(Nurb *nu)
 }
 
 
-float (*curve_getVertexCos(Curve *cu, ListBase *lb, int *numVerts_r))[3]
+float (*curve_getVertexCos(Curve *UNUSED(cu), ListBase *lb, int *numVerts_r))[3]
 {
        int i, numVerts = *numVerts_r = count_curveverts(lb);
        float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "cu_vcos");
@@ -2694,7 +2993,7 @@ float (*curve_getVertexCos(Curve *cu, ListBase *lb, int *numVerts_r))[3]
        return cos;
 }
 
-void curve_applyVertexCos(Curve *cu, ListBase *lb, float (*vertexCos)[3])
+void curve_applyVertexCos(Curve *UNUSED(cu), ListBase *lb, float (*vertexCos)[3])
 {
        float *co = vertexCos[0];
        Nurb *nu;
@@ -2719,6 +3018,64 @@ void curve_applyVertexCos(Curve *cu, ListBase *lb, float (*vertexCos)[3])
        }
 }
 
+float (*curve_getKeyVertexCos(Curve *UNUSED(cu), ListBase *lb, float *key))[3]
+{
+       int i, numVerts = count_curveverts(lb);
+       float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "cu_vcos");
+       Nurb *nu;
+
+       co = cos[0];
+       for (nu=lb->first; nu; nu=nu->next) {
+               if (nu->type == CU_BEZIER) {
+                       BezTriple *bezt = nu->bezt;
+
+                       for (i=0; i<nu->pntsu; i++,bezt++) {
+                               VECCOPY(co, key); co+=3; key+=3;
+                               VECCOPY(co, key); co+=3; key+=3;
+                               VECCOPY(co, key); co+=3; key+=3;
+                               key+=3; /* skip tilt */
+                       }
+               }
+               else {
+                       BPoint *bp = nu->bp;
+
+                       for(i=0; i<nu->pntsu*nu->pntsv; i++,bp++) {
+                               VECCOPY(co, key); co+=3; key+=3;
+                               key++; /* skip tilt */
+                       }
+               }
+       }
+
+       return cos;
+}
+
+void curve_applyKeyVertexTilts(Curve *UNUSED(cu), ListBase *lb, float *key)
+{
+       Nurb *nu;
+       int i;
+
+       for(nu=lb->first; nu; nu=nu->next) {
+               if(nu->type == CU_BEZIER) {
+                       BezTriple *bezt = nu->bezt;
+
+                       for(i=0; i<nu->pntsu; i++,bezt++) {
+                               key+=3*3;
+                               bezt->alfa= *key;
+                               key+=3;
+                       }
+               }
+               else {
+                       BPoint *bp = nu->bp;
+
+                       for(i=0; i<nu->pntsu*nu->pntsv; i++,bp++) {
+                               key+=3;
+                               bp->alfa= *key;
+                               key++;
+                       }
+               }
+       }
+}
+
 int check_valid_nurb_u( struct Nurb *nu )
 {
        if (nu==NULL)                                           return 0;
@@ -2726,7 +3083,7 @@ int check_valid_nurb_u( struct Nurb *nu )
        if (nu->type != CU_NURBS)                       return 1; /* not a nurb, lets assume its valid */
        
        if (nu->pntsu < nu->orderu)                     return 0;
-       if (((nu->flag & CU_CYCLIC)==0) && ((nu->flagu>>1) & 2)) { /* Bezier U Endpoints */
+       if (((nu->flag & CU_NURB_CYCLIC)==0) && (nu->flagu & CU_NURB_BEZIER)) { /* Bezier U Endpoints */
                if (nu->orderu==4) {
                        if (nu->pntsu < 5)                      return 0; /* bezier with 4 orderu needs 5 points */
                } else if (nu->orderu != 3)             return 0; /* order must be 3 or 4 */
@@ -2740,7 +3097,7 @@ int check_valid_nurb_v( struct Nurb *nu)
        if (nu->type != CU_NURBS)                       return 1; /* not a nurb, lets assume its valid */
        
        if (nu->pntsv < nu->orderv)                     return 0;
-       if (((nu->flag & CU_CYCLIC)==0) && ((nu->flagv>>1) & 2)) { /* Bezier V Endpoints */
+       if (((nu->flag & CU_NURB_CYCLIC)==0) && (nu->flagv & CU_NURB_BEZIER)) { /* Bezier V Endpoints */
                if (nu->orderv==4) {
                        if (nu->pntsv < 5)                      return 0; /* bezier with 4 orderu needs 5 points */
                } else if (nu->orderv != 3)             return 0; /* order must be 3 or 4 */
@@ -2755,7 +3112,7 @@ int clamp_nurb_order_u( struct Nurb *nu )
                nu->orderu= nu->pntsu;
                change= 1;
        }
-       if(((nu->flag & CU_CYCLIC)==0) && (nu->flagu>>1)&2) {
+       if(((nu->flagu & CU_NURB_CYCLIC)==0) && (nu->flagu & CU_NURB_BEZIER)) {
                CLAMP(nu->orderu, 3,4);
                change= 1;
        }
@@ -2769,12 +3126,117 @@ int clamp_nurb_order_v( struct Nurb *nu)
                nu->orderv= nu->pntsv;
                change= 1;
        }
-       if(((nu->flag & CU_CYCLIC)==0) && (nu->flagv>>1)&2) {
+       if(((nu->flagv & CU_NURB_CYCLIC)==0) && (nu->flagv & CU_NURB_BEZIER)) {
                CLAMP(nu->orderv, 3,4);
                change= 1;
        }
        return change;
 }
 
+/* Get edit nurbs or normal nurbs list */
+ListBase *BKE_curve_nurbs(Curve *cu)
+{
+       if (cu->editnurb) {
+               return ED_curve_editnurbs(cu);
+       }
 
+       return &cu->nurb;
+}
 
+
+/* basic vertex data functions */
+int minmax_curve(Curve *cu, float min[3], float max[3])
+{
+       ListBase *nurb_lb= BKE_curve_nurbs(cu);
+       Nurb *nu;
+
+       for(nu= nurb_lb->first; nu; nu= nu->next)
+               minmaxNurb(nu, min, max);
+
+       return (nurb_lb->first != NULL);
+}
+
+int curve_center_median(Curve *cu, float cent[3])
+{
+       ListBase *nurb_lb= BKE_curve_nurbs(cu);
+       Nurb *nu;
+       int total= 0;
+
+       zero_v3(cent);
+
+       for(nu= nurb_lb->first; nu; nu= nu->next) {
+               int i;
+
+               if(nu->type == CU_BEZIER) {
+                       BezTriple *bezt;
+                       i= nu->pntsu;
+                       total += i * 3;
+                       for(bezt= nu->bezt; i--; bezt++) {
+                               add_v3_v3(cent, bezt->vec[0]);
+                               add_v3_v3(cent, bezt->vec[1]);
+                               add_v3_v3(cent, bezt->vec[2]);
+                       }
+               }
+               else {
+                       BPoint *bp;
+                       i= nu->pntsu*nu->pntsv;
+                       total += i;
+                       for(bp= nu->bp; i--; bp++) {
+                               add_v3_v3(cent, bp->vec);
+                       }
+               }
+       }
+
+       mul_v3_fl(cent, 1.0f/(float)total);
+
+       return (total != 0);
+}
+
+int curve_center_bounds(Curve *cu, float cent[3])
+{
+       float min[3], max[3];
+       INIT_MINMAX(min, max);
+       if(minmax_curve(cu, min, max)) {
+               mid_v3_v3v3(cent, min, max);
+               return 1;
+       }
+
+       return 0;
+}
+
+void curve_translate(Curve *cu, float offset[3], int do_keys)
+{
+       ListBase *nurb_lb= BKE_curve_nurbs(cu);
+       Nurb *nu;
+       int i;
+
+       for(nu= nurb_lb->first; nu; nu= nu->next) {
+               BezTriple *bezt;
+               BPoint *bp;
+
+               if(nu->type == CU_BEZIER) {
+                       i= nu->pntsu;
+                       for(bezt= nu->bezt; i--; bezt++) {
+                               add_v3_v3(bezt->vec[0], offset);
+                               add_v3_v3(bezt->vec[1], offset);
+                               add_v3_v3(bezt->vec[2], offset);
+                       }
+               }
+               else {
+                       i= nu->pntsu*nu->pntsv;
+                       for(bp= nu->bp; i--; bp++) {
+                               add_v3_v3(bp->vec, offset);
+                       }
+               }
+       }
+
+       if (do_keys && cu->key) {
+               KeyBlock *kb;
+               for (kb=cu->key->block.first; kb; kb=kb->next) {
+                       float *fp= kb->data;
+                       for (i= kb->totelem; i--; fp+=3) {
+                               add_v3_v3(fp, offset);
+                       }
+               }
+       }
+}