Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2013-07-08 12:02:37 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2013-07-08 12:02:37 +0400
commit96d78e3de96f876fde8644160dc641ebc7a58e87 (patch)
tree1d9586c55b218a78b4e7f3d064151cf60daafb57 /source/blender
parent8a388a7bef531cfdbf2b33cca233dfeac0b7a211 (diff)
Fix #36042: Subdividing a cyclic spline shifts start/end points
Issue goes back to 2.4x days at least (but very much likely the issue is even older). It's caused by subdivision code was starting to iterate points from previous one, which shifted all the points by one. Reshuffled code so now iteration starts from first spline point. Thanks to Campbell for review and tests! :)
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/editors/curve/editcurve.c165
1 files changed, 94 insertions, 71 deletions
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index 3327d4a07e9..0f96e886ef3 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -2833,6 +2833,44 @@ void CURVE_OT_reveal(wmOperatorType *ot)
/********************** subdivide operator *********************/
+static BezTriple *next_spline_bezier_point_get(Nurb *nu, BezTriple *bezt)
+{
+ BezTriple *nextbezt;
+
+ if (bezt == nu->bezt + nu->pntsu - 1) {
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ nextbezt = nu->bezt;
+ }
+ else {
+ nextbezt = NULL;
+ }
+ }
+ else {
+ nextbezt = bezt + 1;
+ }
+
+ return nextbezt;
+}
+
+static BPoint *next_spline_bpoint_get(Nurb *nu, BPoint *bp)
+{
+ BPoint *nextbp;
+
+ if (bp == nu->bp + nu->pntsu - 1) {
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ nextbp = nu->bp;
+ }
+ else {
+ nextbp = NULL;
+ }
+ }
+ else {
+ nextbp = bp + 1;
+ }
+
+ return nextbp;
+}
+
/** Divide the line segments associated with the currently selected
* curve nodes (Bezier or NURB). If there are no valid segment
* selections within the current selection, nothing happens.
@@ -2842,7 +2880,7 @@ static void subdividenurb(Object *obedit, int number_cuts)
Curve *cu = obedit->data;
EditNurb *editnurb = cu->editnurb;
Nurb *nu;
- BezTriple *prevbezt, *bezt, *beztnew, *beztn;
+ BezTriple *bezt, *beztnew, *beztn;
BPoint *bp, *prevbp, *bpnew, *bpn;
float vec[15];
int a, b, sel, amount, *usel, *vsel, i;
@@ -2853,25 +2891,25 @@ static void subdividenurb(Object *obedit, int number_cuts)
for (nu = editnurb->nurbs.first; nu; nu = nu->next) {
amount = 0;
if (nu->type == CU_BEZIER) {
+ BezTriple *nextbezt;
+
/*
* Insert a point into a 2D Bezier curve.
* Endpoints are preserved. Otherwise, all selected and inserted points are
* newly created. Old points are discarded.
*/
/* count */
- if (nu->flagu & CU_NURB_CYCLIC) {
- a = nu->pntsu;
- bezt = nu->bezt;
- prevbezt = bezt + (a - 1);
- }
- else {
- a = nu->pntsu - 1;
- prevbezt = nu->bezt;
- bezt = prevbezt + 1;
- }
+ a = nu->pntsu;
+ bezt = nu->bezt;
while (a--) {
- if (BEZSELECTED_HIDDENHANDLES(cu, prevbezt) && BEZSELECTED_HIDDENHANDLES(cu, bezt) ) amount += number_cuts;
- prevbezt = bezt;
+ nextbezt = next_spline_bezier_point_get(nu, bezt);
+ if (nextbezt == NULL) {
+ break;
+ }
+
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt) && BEZSELECTED_HIDDENHANDLES(cu, nextbezt)) {
+ amount += number_cuts;
+ }
bezt++;
}
@@ -2879,35 +2917,32 @@ static void subdividenurb(Object *obedit, int number_cuts)
/* insert */
beztnew = (BezTriple *)MEM_mallocN((amount + nu->pntsu) * sizeof(BezTriple), "subdivNurb");
beztn = beztnew;
- if (nu->flagu & CU_NURB_CYCLIC) {
- a = nu->pntsu;
- bezt = nu->bezt;
- prevbezt = bezt + (a - 1);
- }
- else {
- a = nu->pntsu - 1;
- prevbezt = nu->bezt;
- bezt = prevbezt + 1;
- }
+ a = nu->pntsu;
+ bezt = nu->bezt;
while (a--) {
- memcpy(beztn, prevbezt, sizeof(BezTriple));
- keyIndex_updateBezt(editnurb, prevbezt, beztn, 1);
+ memcpy(beztn, bezt, sizeof(BezTriple));
+ keyIndex_updateBezt(editnurb, bezt, beztn, 1);
beztn++;
- if (BEZSELECTED_HIDDENHANDLES(cu, prevbezt) && BEZSELECTED_HIDDENHANDLES(cu, bezt)) {
+ nextbezt = next_spline_bezier_point_get(nu, bezt);
+ if (nextbezt == NULL) {
+ break;
+ }
+
+ if (BEZSELECTED_HIDDENHANDLES(cu, bezt) && BEZSELECTED_HIDDENHANDLES(cu, nextbezt)) {
float prevvec[3][3];
- memcpy(prevvec, prevbezt->vec, sizeof(float) * 9);
+ memcpy(prevvec, bezt->vec, sizeof(float) * 9);
for (i = 0; i < number_cuts; i++) {
factor = 1.0f / (number_cuts + 1 - i);
- memcpy(beztn, bezt, sizeof(BezTriple));
+ memcpy(beztn, nextbezt, sizeof(BezTriple));
/* midpoint subdividing */
interp_v3_v3v3(vec, prevvec[1], prevvec[2], factor);
- interp_v3_v3v3(vec + 3, prevvec[2], bezt->vec[0], factor);
- interp_v3_v3v3(vec + 6, bezt->vec[0], bezt->vec[1], factor);
+ interp_v3_v3v3(vec + 3, prevvec[2], nextbezt->vec[0], factor);
+ interp_v3_v3v3(vec + 6, nextbezt->vec[0], nextbezt->vec[1], factor);
interp_v3_v3v3(vec + 9, vec, vec + 3, factor);
interp_v3_v3v3(vec + 12, vec + 3, vec + 6, factor);
@@ -2920,24 +2955,18 @@ static void subdividenurb(Object *obedit, int number_cuts)
copy_v3_v3(beztn->vec[2], vec + 12);
/* handle of next bezt */
if (a == 0 && i == number_cuts - 1 && (nu->flagu & CU_NURB_CYCLIC)) { copy_v3_v3(beztnew->vec[0], vec + 6); }
- else { copy_v3_v3(bezt->vec[0], vec + 6); }
+ else { copy_v3_v3(nextbezt->vec[0], vec + 6); }
- beztn->radius = (prevbezt->radius + bezt->radius) / 2;
- beztn->weight = (prevbezt->weight + bezt->weight) / 2;
+ beztn->radius = (bezt->radius + nextbezt->radius) / 2;
+ beztn->weight = (bezt->weight + nextbezt->weight) / 2;
memcpy(prevvec, beztn->vec, sizeof(float) * 9);
beztn++;
}
}
- prevbezt = bezt;
bezt++;
}
- /* last point */
- if ((nu->flagu & CU_NURB_CYCLIC) == 0) {
- memcpy(beztn, prevbezt, sizeof(BezTriple));
- keyIndex_updateBezt(editnurb, prevbezt, beztn, 1);
- }
MEM_freeN(nu->bezt);
nu->bezt = beztnew;
@@ -2947,6 +2976,8 @@ static void subdividenurb(Object *obedit, int number_cuts)
}
} /* End of 'if (nu->type == CU_BEZIER)' */
else if (nu->pntsv == 1) {
+ BPoint *nextbp;
+
/*
* All flat lines (ie. co-planar), except flat Nurbs. Flat NURB curves
* are handled together with the regular NURB plane division, as it
@@ -2954,19 +2985,17 @@ static void subdividenurb(Object *obedit, int number_cuts)
* stable... nzc 30-5-'00
*/
/* count */
- if (nu->flagu & CU_NURB_CYCLIC) {
- a = nu->pntsu;
- bp = nu->bp;
- prevbp = bp + (a - 1);
- }
- else {
- a = nu->pntsu - 1;
- prevbp = nu->bp;
- bp = prevbp + 1;
- }
+ a = nu->pntsu;
+ bp = nu->bp;
while (a--) {
- if ( (bp->f1 & SELECT) && (prevbp->f1 & SELECT) ) amount += number_cuts;
- prevbp = bp;
+ nextbp = next_spline_bpoint_get(nu, bp);
+ if (nextbp == NULL) {
+ break;
+ }
+
+ if ((bp->f1 & SELECT) && (nextbp->f1 & SELECT)) {
+ amount += number_cuts;
+ }
bp++;
}
@@ -2975,39 +3004,33 @@ static void subdividenurb(Object *obedit, int number_cuts)
bpnew = (BPoint *)MEM_mallocN((amount + nu->pntsu) * sizeof(BPoint), "subdivNurb2");
bpn = bpnew;
- if (nu->flagu & CU_NURB_CYCLIC) {
- a = nu->pntsu;
- bp = nu->bp;
- prevbp = bp + (a - 1);
- }
- else {
- a = nu->pntsu - 1;
- prevbp = nu->bp;
- bp = prevbp + 1;
- }
+ a = nu->pntsu;
+ bp = nu->bp;
+
while (a--) {
- memcpy(bpn, prevbp, sizeof(BPoint));
- keyIndex_updateBP(editnurb, prevbp, bpn, 1);
+ /* Copy "old" point. */
+ memcpy(bpn, bp, sizeof(BPoint));
+ keyIndex_updateBP(editnurb, bp, bpn, 1);
bpn++;
- if ((bp->f1 & SELECT) && (prevbp->f1 & SELECT)) {
+ nextbp = next_spline_bpoint_get(nu, bp);
+ if (nextbp == NULL) {
+ break;
+ }
+
+ if ((bp->f1 & SELECT) && (nextbp->f1 & SELECT)) {
// printf("*** subdivideNurb: insert 'linear' point\n");
for (i = 0; i < number_cuts; i++) {
factor = (float)(i + 1) / (number_cuts + 1);
- memcpy(bpn, bp, sizeof(BPoint));
- interp_v4_v4v4(bpn->vec, prevbp->vec, bp->vec, factor);
+ memcpy(bpn, nextbp, sizeof(BPoint));
+ interp_v4_v4v4(bpn->vec, bp->vec, nextbp->vec, factor);
bpn++;
}
}
- prevbp = bp;
bp++;
}
- if ((nu->flagu & CU_NURB_CYCLIC) == 0) { /* last point */
- memcpy(bpn, prevbp, sizeof(BPoint));
- keyIndex_updateBP(editnurb, prevbp, bpn, 1);
- }
MEM_freeN(nu->bp);
nu->bp = bpnew;