- add individual origin support for curves and improve the orientation calculations for curve handles,
- add support for using the active point's orientation. - add support for creating new custom orientations from curves. - fix error where only the last selected curve handle was taken into account for manipulator orientations.
This commit is contained in:
parent
57a4070b9d
commit
b6f58d0ea1
@ -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);
|
||||
|
@ -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 ~~~~~~~~~~~ */
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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++;
|
||||
|
@ -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,6 +699,25 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
|
||||
int a;
|
||||
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
|
||||
|
||||
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 (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) {
|
||||
@ -682,27 +725,41 @@ int getTransformOrientation(const bContext *C, float normal[3], float plane[3],
|
||||
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) {
|
||||
sub_v3_v3v3(normal, bezt->vec[0], bezt->vec[2]);
|
||||
BKE_nurb_bezt_calc_normal(nu, bezt, tvec);
|
||||
add_v3_v3(normal, tvec);
|
||||
}
|
||||
else {
|
||||
if (bezt->f1) {
|
||||
sub_v3_v3v3(normal, bezt->vec[0], bezt->vec[1]);
|
||||
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) {
|
||||
sub_v3_v3v3(normal, bezt->vec[0], bezt->vec[2]);
|
||||
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) {
|
||||
sub_v3_v3v3(normal, bezt->vec[1], bezt->vec[2]);
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_zero_v3(normal)) {
|
||||
result = ORIENTATION_NORMAL;
|
||||
result = ORIENTATION_FACE;
|
||||
}
|
||||
}
|
||||
else if (obedit->type == OB_MBALL) {
|
||||
|
Loading…
Reference in New Issue
Block a user