diff options
-rw-r--r-- | source/blender/blenkernel/BKE_curve.h | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/curve.c | 137 | ||||
-rw-r--r-- | source/blender/editors/curve/editcurve.c | 46 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 4 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.h | 2 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 26 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_orientations.c | 113 |
7 files changed, 263 insertions, 73 deletions
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 3be77086336..93f9ec276aa 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -129,6 +129,14 @@ bool BKE_nurb_type_convert(struct Nurb *nu, const short type, const bool use_han void BKE_nurb_points_add(struct Nurb *nu, int number); void BKE_nurb_bezierPoints_add(struct Nurb *nu, int number); +struct BezTriple *BKE_nurb_bezt_get_next(struct Nurb *nu, struct BezTriple *bezt); +struct BezTriple *BKE_nurb_bezt_get_prev(struct Nurb *nu, struct BezTriple *bezt); +struct BPoint *BKE_nurb_bpoint_get_next(struct Nurb *nu, struct BPoint *bp); +struct BPoint *BKE_nurb_bpoint_get_prev(struct Nurb *nu, struct BPoint *bp); + +void BKE_nurb_bezt_calc_normal(struct Nurb *nu, struct BezTriple *bezt, float r_normal[3]); +void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_plane[3]); + void BKE_nurb_handle_calc(struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next, int mode); void BKE_nurb_handles_calc(struct Nurb *nu); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index b6c4505bd78..43e5cc101a7 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -681,6 +681,143 @@ void BKE_nurb_bezierPoints_add(Nurb *nu, int number) nu->pntsu += number; } + +BezTriple *BKE_nurb_bezt_get_next(Nurb *nu, BezTriple *bezt) +{ + BezTriple *bezt_next; + + BLI_assert(ARRAY_HAS_ITEM(bezt, nu->bezt, nu->pntsu)); + + if (bezt == &nu->bezt[nu->pntsu - 1]) { + if (nu->flagu & CU_NURB_CYCLIC) { + bezt_next = nu->bezt; + } + else { + bezt_next = NULL; + } + } + else { + bezt_next = bezt + 1; + } + + return bezt_next; +} + +BPoint *BKE_nurb_bpoint_get_next(Nurb *nu, BPoint *bp) +{ + BPoint *bp_next; + + BLI_assert(ARRAY_HAS_ITEM(bp, nu->bp, nu->pntsu)); + + if (bp == &nu->bp[nu->pntsu - 1]) { + if (nu->flagu & CU_NURB_CYCLIC) { + bp_next = nu->bp; + } + else { + bp_next = NULL; + } + } + else { + bp_next = bp + 1; + } + + return bp_next; +} + +BezTriple *BKE_nurb_bezt_get_prev(Nurb *nu, BezTriple *bezt) +{ + BezTriple *bezt_prev; + + BLI_assert(ARRAY_HAS_ITEM(bezt, nu->bezt, nu->pntsu)); + + if (bezt == nu->bezt) { + if (nu->flagu & CU_NURB_CYCLIC) { + bezt_prev = &nu->bezt[nu->pntsu - 1]; + } + else { + bezt_prev = NULL; + } + } + else { + bezt_prev = bezt - 1; + } + + return bezt_prev; +} + +BPoint *BKE_nurb_bpoint_get_prev(Nurb *nu, BPoint *bp) +{ + BPoint *bp_prev; + + BLI_assert(ARRAY_HAS_ITEM(bp, nu->bp, nu->pntsu)); + + if (bp == nu->bp) { + if (nu->flagu & CU_NURB_CYCLIC) { + bp_prev = &nu->bp[nu->pntsu - 1]; + } + else { + bp_prev = NULL; + } + } + else { + bp_prev = bp - 1; + } + + return bp_prev; +} + +void BKE_nurb_bezt_calc_normal(struct Nurb *UNUSED(nu), struct BezTriple *bezt, float r_normal[3]) +{ + /* calculate the axis matrix from the spline */ + float dir_prev[3], dir_next[3]; + + sub_v3_v3v3(dir_prev, bezt->vec[0], bezt->vec[1]); + sub_v3_v3v3(dir_next, bezt->vec[1], bezt->vec[2]); + + normalize_v3(dir_prev); + normalize_v3(dir_next); + + add_v3_v3v3(r_normal, dir_prev, dir_next); + normalize_v3(r_normal); +} + +void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_plane[3]) +{ + float dir_prev[3], dir_next[3]; + + sub_v3_v3v3(dir_prev, bezt->vec[0], bezt->vec[1]); + sub_v3_v3v3(dir_next, bezt->vec[1], bezt->vec[2]); + + normalize_v3(dir_prev); + normalize_v3(dir_next); + + cross_v3_v3v3(r_plane, dir_prev, dir_next); + if (normalize_v3(r_plane) < FLT_EPSILON) { + BezTriple *bezt_prev = BKE_nurb_bezt_get_prev(nu, bezt); + BezTriple *bezt_next = BKE_nurb_bezt_get_next(nu, bezt); + + if (bezt_prev) { + sub_v3_v3v3(dir_prev, bezt_prev->vec[1], bezt->vec[1]); + normalize_v3(dir_prev); + } + if (bezt_next) { + sub_v3_v3v3(dir_next, bezt->vec[1], bezt_next->vec[1]); + normalize_v3(dir_next); + } + cross_v3_v3v3(r_plane, dir_prev, dir_next); + } + + /* matches with bones more closely */ + { + float dir_mid[3], tvec[3]; + add_v3_v3v3(dir_mid, dir_prev, dir_next); + cross_v3_v3v3(tvec, r_plane, dir_mid); + copy_v3_v3(r_plane, tvec); + } + + normalize_v3(r_plane); +} + /* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline calculations ~~~~~~~~~~~ */ diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 5352b367d05..a988b2295dc 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -2833,44 +2833,6 @@ 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. @@ -2902,7 +2864,7 @@ static void subdividenurb(Object *obedit, int number_cuts) a = nu->pntsu; bezt = nu->bezt; while (a--) { - nextbezt = next_spline_bezier_point_get(nu, bezt); + nextbezt = BKE_nurb_bezt_get_next(nu, bezt); if (nextbezt == NULL) { break; } @@ -2924,7 +2886,7 @@ static void subdividenurb(Object *obedit, int number_cuts) keyIndex_updateBezt(editnurb, bezt, beztn, 1); beztn++; - nextbezt = next_spline_bezier_point_get(nu, bezt); + nextbezt = BKE_nurb_bezt_get_next(nu, bezt); if (nextbezt == NULL) { break; } @@ -2988,7 +2950,7 @@ static void subdividenurb(Object *obedit, int number_cuts) a = nu->pntsu; bp = nu->bp; while (a--) { - nextbp = next_spline_bpoint_get(nu, bp); + nextbp = BKE_nurb_bpoint_get_next(nu, bp); if (nextbp == NULL) { break; } @@ -3013,7 +2975,7 @@ static void subdividenurb(Object *obedit, int number_cuts) keyIndex_updateBP(editnurb, bp, bpn, 1); bpn++; - nextbp = next_spline_bpoint_get(nu, bp); + nextbp = BKE_nurb_bpoint_get_next(nu, bp); if (nextbp == NULL) { break; } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 0019cae9c4e..6c854ef6795 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -110,7 +110,7 @@ static bool transdata_check_local_center(TransInfo *t) { return ((t->around == V3D_LOCAL) && ( (t->flag & (T_OBJECT | T_POSE)) || - (t->obedit && ELEM3(t->obedit->type, OB_MESH, OB_MBALL, OB_ARMATURE)) || + (t->obedit && ELEM4(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE)) || (t->spacetype == SPACE_IPO)) ); } @@ -7355,7 +7355,7 @@ bool checkUseAxisMatrix(TransInfo *t) { /* currenly only checks for editmode */ if (t->flag & T_EDIT) { - if ((t->around == V3D_LOCAL) && (ELEM3(t->obedit->type, OB_MESH, OB_MBALL, OB_ARMATURE))) { + if ((t->around == V3D_LOCAL) && (ELEM4(t->obedit->type, OB_MESH, OB_CURVE, OB_MBALL, OB_ARMATURE))) { /* not all editmode supports axis-matrix */ return true; } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 911d4b0a623..4a1c4203a43 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -725,7 +725,7 @@ void initTransformOrientation(struct bContext *C, TransInfo *t); /* Those two fill in mat and return non-zero on success */ bool createSpaceNormal(float mat[3][3], const float normal[3]); -bool createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]); +bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const float tangent[3]); struct TransformOrientation *addMatrixSpace(struct bContext *C, float mat[3][3], char name[], int overwrite); void applyTransformOrientation(const struct bContext *C, float mat[3][3], char *name); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 15df06be3d6..0a8687339a5 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -1417,6 +1417,23 @@ static void createTransCurveVerts(TransInfo *t) for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) { if (bezt->hide == 0) { TransDataCurveHandleFlags *hdata = NULL; + float axismtx[3][3]; + + if (t->around == V3D_LOCAL) { + float normal[3], plane[3]; + + BKE_nurb_bezt_calc_normal(nu, bezt, normal); + BKE_nurb_bezt_calc_plane(nu, bezt, plane); + + if (createSpaceNormalTangent(axismtx, normal, plane)) { + /* pass */ + } + else { + normalize_v3(normal); + axis_dominant_v3_to_m3(axismtx, normal); + invert_m3(axismtx); + } + } if (propmode || ((bezt->f2 & SELECT) && hide_handles) || @@ -1440,6 +1457,9 @@ static void createTransCurveVerts(TransInfo *t) copy_m3_m3(td->smtx, smtx); copy_m3_m3(td->mtx, mtx); + if (t->around == V3D_LOCAL) { + copy_m3_m3(td->axismtx, axismtx); + } td++; count++; @@ -1469,6 +1489,9 @@ static void createTransCurveVerts(TransInfo *t) copy_m3_m3(td->smtx, smtx); copy_m3_m3(td->mtx, mtx); + if (t->around == V3D_LOCAL) { + copy_m3_m3(td->axismtx, axismtx); + } if ((bezt->f1 & SELECT) == 0 && (bezt->f3 & SELECT) == 0) /* If the middle is selected but the sides arnt, this is needed */ @@ -1504,6 +1527,9 @@ static void createTransCurveVerts(TransInfo *t) copy_m3_m3(td->smtx, smtx); copy_m3_m3(td->mtx, mtx); + if (t->around == V3D_LOCAL) { + copy_m3_m3(td->axismtx, axismtx); + } td++; count++; diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 2be4a072d49..c6cc7bc1330 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -166,6 +166,26 @@ static TransformOrientation *createBoneSpace(bContext *C, ReportList *reports, c return addMatrixSpace(C, mat, name, overwrite); } +static TransformOrientation *createCurveSpace(bContext *C, ReportList *reports, char *name, int overwrite) +{ + float mat[3][3]; + float normal[3], plane[3]; + + getTransformOrientation(C, normal, plane, 0); + + if (createSpaceNormalTangent(mat, normal, plane) == 0) { + BKE_reports_prepend(reports, "Cannot use zero-length curve"); + return NULL; + } + + if (name[0] == 0) { + strcpy(name, "Curve"); + } + + return addMatrixSpace(C, mat, name, overwrite); +} + + static TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, char *name, int overwrite) { float mat[3][3]; @@ -236,26 +256,28 @@ bool createSpaceNormal(float mat[3][3], const float normal[3]) return true; } -bool createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]) +bool createSpaceNormalTangent(float mat[3][3], const float normal[3], const float tangent[3]) { - copy_v3_v3(mat[2], normal); - if (normalize_v3(mat[2]) == 0.0f) { + if (normalize_v3_v3(mat[2], normal) == 0.0f) { return false; /* error return */ } - + + copy_v3_v3(mat[1], tangent); /* preempt zero length tangent from causing trouble */ - if (tangent[0] == 0 && tangent[1] == 0 && tangent[2] == 0) { - tangent[2] = 1; + if (is_zero_v3(mat[1])) { + mat[1][2] = 1.0f; } - cross_v3_v3v3(mat[0], mat[2], tangent); + cross_v3_v3v3(mat[0], mat[2], mat[1]); if (normalize_v3(mat[0]) == 0.0f) { return false; /* error return */ } cross_v3_v3v3(mat[1], mat[2], mat[0]); + normalize_v3(mat[1]); - normalize_m3(mat); + /* final matrix must be normalized, do inline */ + // normalize_m3(mat); return true; } @@ -276,6 +298,8 @@ void BIF_createTransformOrientation(bContext *C, ReportList *reports, char *name ts = createMeshSpace(C, reports, name, overwrite); else if (obedit->type == OB_ARMATURE) ts = createBoneSpace(C, reports, name, overwrite); + else if (obedit->type == OB_CURVE) + ts = createCurveSpace(C, reports, name, overwrite); } else if (ob && (ob->mode & OB_MODE_POSE)) { ts = createBoneSpace(C, reports, name, overwrite); @@ -675,34 +699,67 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3], int a; ListBase *nurbs = BKE_curve_editNurbs_get(cu); - for (nu = nurbs->first; nu; nu = nu->next) { - /* only bezier has a normal */ - if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - /* exception */ - if ((bezt->f1 & SELECT) + (bezt->f2 & SELECT) + (bezt->f3 & SELECT) > SELECT) { - sub_v3_v3v3(normal, bezt->vec[0], bezt->vec[2]); + if (activeOnly && cu->lastsel) { + for (nu = nurbs->first; nu; nu = nu->next) { + if (nu->type == CU_BEZIER) { + if (ARRAY_HAS_ITEM((BezTriple *)cu->lastsel, nu->bezt, nu->pntsu)) { + bezt = cu->lastsel; + BKE_nurb_bezt_calc_normal(nu, bezt, normal); + BKE_nurb_bezt_calc_plane(nu, bezt, plane); + break; } - else { - if (bezt->f1) { - sub_v3_v3v3(normal, bezt->vec[0], bezt->vec[1]); - } - if (bezt->f2) { - sub_v3_v3v3(normal, bezt->vec[0], bezt->vec[2]); - } - if (bezt->f3) { - sub_v3_v3v3(normal, bezt->vec[1], bezt->vec[2]); + } + else { + if (ARRAY_HAS_ITEM((BPoint *)cu->lastsel, nu->bp, nu->pntsu)) { + /* do nothing */ + break; + } + } + } + } + else { + for (nu = nurbs->first; nu; nu = nu->next) { + /* only bezier has a normal */ + if (nu->type == CU_BEZIER) { + bezt = nu->bezt; + a = nu->pntsu; + while (a--) { + /* exception */ + if ((bezt->f1 | bezt->f2 | bezt->f3) & SELECT) { + float tvec[3]; + if ((bezt->f1 & SELECT) + (bezt->f2 & SELECT) + (bezt->f3 & SELECT) > SELECT) { + BKE_nurb_bezt_calc_normal(nu, bezt, tvec); + add_v3_v3(normal, tvec); + } + else { + if (bezt->f1 & SELECT) { + sub_v3_v3v3(tvec, bezt->vec[0], bezt->vec[1]); + normalize_v3(tvec); + add_v3_v3(normal, tvec); + } + if (bezt->f2 & SELECT) { + sub_v3_v3v3(tvec, bezt->vec[0], bezt->vec[2]); + normalize_v3(tvec); + add_v3_v3(normal, tvec); + } + if (bezt->f3 & SELECT) { + sub_v3_v3v3(tvec, bezt->vec[1], bezt->vec[2]); + normalize_v3(tvec); + add_v3_v3(normal, tvec); + } + } + + BKE_nurb_bezt_calc_plane(nu, bezt, tvec); + add_v3_v3(plane, tvec); } + bezt++; } - bezt++; } } } if (!is_zero_v3(normal)) { - result = ORIENTATION_NORMAL; + result = ORIENTATION_FACE; } } else if (obedit->type == OB_MBALL) { |