diff options
Diffstat (limited to 'source/blender/blenkernel/intern/curve.c')
-rw-r--r-- | source/blender/blenkernel/intern/curve.c | 357 |
1 files changed, 256 insertions, 101 deletions
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 4b4ca1cb32b..5fba308e3df 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -36,7 +36,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_bpath.h" #include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -168,11 +167,11 @@ void BKE_curve_free(Curve *cu) MEM_freeN(cu->tb); } -Curve *BKE_curve_add(const char *name, int type) +Curve *BKE_curve_add(Main *bmain, const char *name, int type) { Curve *cu; - cu = BKE_libblock_alloc(&G.main->curve, ID_CU, name); + cu = BKE_libblock_alloc(&bmain->curve, ID_CU, name); copy_v3_fl(cu->size, 1.0f); cu->flag = CU_FRONT | CU_BACK | CU_DEFORM_BOUNDS_OFF | CU_PATH_RADIUS; cu->pathlen = 100; @@ -794,7 +793,9 @@ static void makeknots(Nurb *nu, short uv) calcknots(nu->knotsv, nu->pntsv, nu->orderv, nu->flagv); } } - else nu->knotsv = NULL; + else { + nu->knotsv = NULL; + } } } } @@ -876,7 +877,7 @@ static void basisNurb(float t, short order, short pnts, float *knots, float *bas void BKE_nurb_makeFaces(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 */ +/* coord_array has to be (3 * 4 * resolu * resolv) in size, and zero-ed */ { BPoint *bp; float *basisu, *basis, *basisv, *sum, *fp, *in; @@ -1747,7 +1748,7 @@ static void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *si else t02 = (saacos(t02)) / 2.0f; - t02 = (float)sin(t02); + t02 = sinf(t02); if (t02 == 0.0f) t02 = 1.0f; @@ -2203,6 +2204,70 @@ static void make_bevel_list_segment_3D(BevList *bl) copy_qt_qt(bevp2->quat, bevp1->quat); } +/* only for 2 points */ +static void make_bevel_list_segment_2D(BevList *bl) +{ + BevPoint *bevp2 = (BevPoint *)(bl + 1); + BevPoint *bevp1 = bevp2 + 1; + + const float x1 = bevp1->vec[0] - bevp2->vec[0]; + const float y1 = bevp1->vec[1] - bevp2->vec[1]; + + 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); +} + +static void make_bevel_list_2D(BevList *bl) +{ + /* 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 */ + + BevPoint *bevp2 = (BevPoint *)(bl + 1); + BevPoint *bevp1 = bevp2 + (bl->nr - 1); + BevPoint *bevp0 = bevp1 - 1; + int nr; + + nr = bl->nr; + while (nr--) { + const float x1 = bevp1->vec[0] - bevp0->vec[0]; + const float x2 = bevp1->vec[0] - bevp2->vec[0]; + const float y1 = bevp1->vec[1] - bevp0->vec[1]; + const float 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++; + } + + /* correct non-cyclic cases */ + if (bl->poly == -1) { + BevPoint *bevp = (BevPoint *)(bl + 1); + bevp1 = bevp + 1; + bevp->sina = bevp1->sina; + bevp->cosa = bevp1->cosa; + bevp = (BevPoint *)(bl + 1); + bevp += (bl->nr - 1); + bevp1 = bevp - 1; + bevp->sina = bevp1->sina; + bevp->cosa = bevp1->cosa; + + /* correct for the dir/quat, see above why its needed */ + bevel_list_cyclic_fix_3D(bl); + } +} + void BKE_curve_bevelList_make(Object *ob) { /* @@ -2217,10 +2282,11 @@ void BKE_curve_bevelList_make(Object *ob) BPoint *bp; BevList *bl, *blnew, *blnext; BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0; - float min, inp, x1, x2, y1, y2; + float min, inp; struct bevelsort *sortdata, *sd, *sd1; int a, b, nr, poly, resolu = 0, len = 0; int do_tilt, do_radius, do_weight; + int is_editmode = 0; /* this function needs an object, because of tflag and upflag */ cu = ob->data; @@ -2234,12 +2300,17 @@ void BKE_curve_bevelList_make(Object *ob) if (cu->editnurb && ob->type != OB_FONT) { ListBase *nurbs = BKE_curve_editNurbs_get(cu); nu = nurbs->first; + is_editmode = 1; } else { nu = cu->nurb.first; } - while (nu) { + for (; nu; nu = nu->next) { + + if (nu->hide && is_editmode) + continue; + /* 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 */ @@ -2385,7 +2456,6 @@ void BKE_curve_bevelList_make(Object *ob) } } } - nu = nu->next; } /* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */ @@ -2530,76 +2600,22 @@ void BKE_curve_bevelList_make(Object *ob) /* 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) { - + /* 2D Curves */ + for (bl = cu->bev.first; bl; bl = bl->next) { if (bl->nr < 2) { /* do nothing */ } else if (bl->nr == 2) { /* 2 pnt, treat separate */ - bevp2 = (BevPoint *)(bl + 1); - bevp1 = bevp2 + 1; - - x1 = bevp1->vec[0] - bevp2->vec[0]; - y1 = bevp1->vec[1] - bevp2->vec[1]; - - 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); + make_bevel_list_segment_2D(bl); } else { - bevp2 = (BevPoint *)(bl + 1); - bevp1 = bevp2 + (bl->nr - 1); - bevp0 = bevp1 - 1; - - nr = bl->nr; - while (nr--) { - 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++; - } - - /* correct non-cyclic cases */ - if (bl->poly == -1) { - bevp = (BevPoint *)(bl + 1); - bevp1 = bevp + 1; - bevp->sina = bevp1->sina; - bevp->cosa = bevp1->cosa; - bevp = (BevPoint *)(bl + 1); - bevp += (bl->nr - 1); - bevp1 = bevp - 1; - bevp->sina = bevp1->sina; - bevp->cosa = bevp1->cosa; - - /* correct for the dir/quat, see above why its needed */ - bevel_list_cyclic_fix_3D(bl); - } + make_bevel_list_2D(bl); } - bl = bl->next; } } - else { /* 3D Curves */ - bl = cu->bev.first; - while (bl) { - + else { + /* 3D Curves */ + for (bl = cu->bev.first; bl; bl = bl->next) { if (bl->nr < 2) { /* do nothing */ } @@ -2609,7 +2625,6 @@ void BKE_curve_bevelList_make(Object *ob) else { make_bevel_list_3D(bl, (int)(resolu * cu->twist_smooth), cu->twist_mode); } - bl = bl->next; } } } @@ -3304,80 +3319,218 @@ void BKE_curve_keyVertexTilts_apply(Curve *UNUSED(cu), ListBase *lb, float *key) } } -int BKE_nurb_check_valid_u(struct Nurb *nu) +bool BKE_nurb_check_valid_u(struct Nurb *nu) { if (nu == NULL) - return 0; + return false; if (nu->pntsu <= 1) - return 0; + return false; if (nu->type != CU_NURBS) - return 1; /* not a nurb, lets assume its valid */ + return true; /* not a nurb, lets assume its valid */ - if (nu->pntsu < nu->orderu) return 0; + if (nu->pntsu < nu->orderu) return false; 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 */ + return false; /* bezier with 4 orderu needs 5 points */ } else { if (nu->orderu != 3) - return 0; /* order must be 3 or 4 */ + return false; /* order must be 3 or 4 */ } } - return 1; + return true; } -int BKE_nurb_check_valid_v(struct Nurb *nu) +bool BKE_nurb_check_valid_v(struct Nurb *nu) { if (nu == NULL) - return 0; + return false; if (nu->pntsv <= 1) - return 0; + return false; if (nu->type != CU_NURBS) - return 1; /* not a nurb, lets assume its valid */ + return true; /* not a nurb, lets assume its valid */ if (nu->pntsv < nu->orderv) - return 0; + return false; 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 */ + return false; /* bezier with 4 orderu needs 5 points */ } else { if (nu->orderv != 3) - return 0; /* order must be 3 or 4 */ + return false; /* order must be 3 or 4 */ } } - return 1; + return true; } -int BKE_nurb_order_clamp_u(struct Nurb *nu) +bool BKE_nurb_order_clamp_u(struct Nurb *nu) { - int change = 0; + bool change = false; if (nu->pntsu < nu->orderu) { nu->orderu = nu->pntsu; - change = 1; + change = true; } if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) { CLAMP(nu->orderu, 3, 4); - change = 1; + change = true; } return change; } -int BKE_nurb_order_clamp_v(struct Nurb *nu) +bool BKE_nurb_order_clamp_v(struct Nurb *nu) { - int change = 0; + bool change = false; if (nu->pntsv < nu->orderv) { nu->orderv = nu->pntsv; - change = 1; + change = true; } if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) { CLAMP(nu->orderv, 3, 4); - change = 1; + change = true; } return change; } +bool BKE_nurb_type_convert(Nurb *nu, const short type, const bool use_handles) +{ + BezTriple *bezt; + BPoint *bp; + int a, c, nr; + + if (nu->type == CU_POLY) { + if (type == CU_BEZIER) { /* to Bezier with vecthandles */ + nr = nu->pntsu; + bezt = (BezTriple *)MEM_callocN(nr * sizeof(BezTriple), "setsplinetype2"); + nu->bezt = bezt; + a = nr; + bp = nu->bp; + while (a--) { + copy_v3_v3(bezt->vec[1], bp->vec); + bezt->f1 = bezt->f2 = bezt->f3 = bp->f1; + bezt->h1 = bezt->h2 = HD_VECT; + bezt->weight = bp->weight; + bezt->radius = bp->radius; + bp++; + bezt++; + } + MEM_freeN(nu->bp); + nu->bp = NULL; + nu->pntsu = nr; + nu->type = CU_BEZIER; + BKE_nurb_handles_calc(nu); + } + else if (type == CU_NURBS) { + nu->type = CU_NURBS; + nu->orderu = 4; + nu->flagu &= CU_NURB_CYCLIC; /* disable all flags except for cyclic */ + BKE_nurb_knot_calc_u(nu); + a = nu->pntsu * nu->pntsv; + bp = nu->bp; + while (a--) { + bp->vec[3] = 1.0; + bp++; + } + } + } + else if (nu->type == CU_BEZIER) { /* Bezier */ + if (type == CU_POLY || type == CU_NURBS) { + nr = use_handles ? (3 * nu->pntsu) : nu->pntsu; + nu->bp = MEM_callocN(nr * sizeof(BPoint), "setsplinetype"); + a = nu->pntsu; + bezt = nu->bezt; + bp = nu->bp; + while (a--) { + if ((type == CU_POLY && bezt->h1 == HD_VECT && bezt->h2 == HD_VECT) || (use_handles == false)) { + /* vector handle becomes 1 poly vertice */ + copy_v3_v3(bp->vec, bezt->vec[1]); + bp->vec[3] = 1.0; + bp->f1 = bezt->f2; + if (use_handles) nr -= 2; + bp->radius = bezt->radius; + bp->weight = bezt->weight; + bp++; + } + else { + char *f = &bezt->f1; + for (c = 0; c < 3; c++, f++) { + copy_v3_v3(bp->vec, bezt->vec[c]); + bp->vec[3] = 1.0; + bp->f1 = *f; + bp->radius = bezt->radius; + bp->weight = bezt->weight; + bp++; + } + } + bezt++; + } + MEM_freeN(nu->bezt); + nu->bezt = NULL; + nu->pntsu = nr; + nu->pntsv = 1; + nu->orderu = 4; + nu->orderv = 1; + nu->type = type; + +#if 0 /* UNUSED */ + if (nu->flagu & CU_NURB_CYCLIC) c = nu->orderu - 1; + else c = 0; +#endif + + if (type == CU_NURBS) { + nu->flagu &= CU_NURB_CYCLIC; /* disable all flags except for cyclic */ + nu->flagu |= CU_NURB_BEZIER; + BKE_nurb_knot_calc_u(nu); + } + } + } + else if (nu->type == CU_NURBS) { + if (type == CU_POLY) { + nu->type = CU_POLY; + if (nu->knotsu) MEM_freeN(nu->knotsu); /* python created nurbs have a knotsu of zero */ + nu->knotsu = NULL; + if (nu->knotsv) MEM_freeN(nu->knotsv); + nu->knotsv = NULL; + } + else if (type == CU_BEZIER) { /* to Bezier */ + nr = nu->pntsu / 3; + + if (nr < 2) { + return false; /* conversion impossible */ + } + else { + bezt = MEM_callocN(nr * sizeof(BezTriple), "setsplinetype2"); + nu->bezt = bezt; + a = nr; + bp = nu->bp; + while (a--) { + copy_v3_v3(bezt->vec[0], bp->vec); + bezt->f1 = bp->f1; + bp++; + copy_v3_v3(bezt->vec[1], bp->vec); + bezt->f2 = bp->f1; + bp++; + copy_v3_v3(bezt->vec[2], bp->vec); + bezt->f3 = bp->f1; + bezt->radius = bp->radius; + bezt->weight = bp->weight; + bp++; + bezt++; + } + MEM_freeN(nu->bp); + nu->bp = NULL; + MEM_freeN(nu->knotsu); + nu->knotsu = NULL; + nu->pntsu = nr; + nu->type = CU_BEZIER; + } + } + } + + return true; +} + /* Get edit nurbs or normal nurbs list */ ListBase *BKE_curve_nurbs_get(Curve *cu) { @@ -3390,7 +3543,7 @@ ListBase *BKE_curve_nurbs_get(Curve *cu) /* basic vertex data functions */ -int BKE_curve_minmax(Curve *cu, float min[3], float max[3]) +bool BKE_curve_minmax(Curve *cu, float min[3], float max[3]) { ListBase *nurb_lb = BKE_curve_nurbs_get(cu); Nurb *nu; @@ -3401,7 +3554,7 @@ int BKE_curve_minmax(Curve *cu, float min[3], float max[3]) return (nurb_lb->first != NULL); } -int BKE_curve_center_median(Curve *cu, float cent[3]) +bool BKE_curve_center_median(Curve *cu, float cent[3]) { ListBase *nurb_lb = BKE_curve_nurbs_get(cu); Nurb *nu; @@ -3432,21 +3585,23 @@ int BKE_curve_center_median(Curve *cu, float cent[3]) } } - mul_v3_fl(cent, 1.0f / (float)total); + if (total) { + mul_v3_fl(cent, 1.0f / (float)total); + } return (total != 0); } -int BKE_curve_center_bounds(Curve *cu, float cent[3]) +bool BKE_curve_center_bounds(Curve *cu, float cent[3]) { float min[3], max[3]; INIT_MINMAX(min, max); if (BKE_curve_minmax(cu, min, max)) { mid_v3_v3v3(cent, min, max); - return 1; + return true; } - return 0; + return false; } void BKE_curve_translate(Curve *cu, float offset[3], int do_keys) |