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
path: root/source
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2013-10-13 05:09:23 +0400
committerCampbell Barton <ideasman42@gmail.com>2013-10-13 05:09:23 +0400
commitb00a8122e3e5fa88e3870ca20eedbd251d245237 (patch)
treebea9571ad64f7bd5fcc69a74ecb927d89f198240 /source
parenteabf7ab3351ade8415cd38d6faf2cfba79ba7400 (diff)
improve warp transform so it can be used as a general bending tool too.
Diffstat (limited to 'source')
-rw-r--r--source/blender/editors/transform/transform.c225
-rw-r--r--source/blender/editors/transform/transform.h1
-rw-r--r--source/blender/editors/transform/transform_generics.c5
-rw-r--r--source/blender/editors/transform/transform_input.c16
4 files changed, 150 insertions, 97 deletions
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index ba7bdebd5bf..ea039c15be4 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -105,6 +105,8 @@ static int doVertSlide(TransInfo *t, float perc);
static void drawEdgeSlide(const struct bContext *C, TransInfo *t);
static void drawVertSlide(const struct bContext *C, TransInfo *t);
+static void len_v3_ensure(float v[3], const float length);
+static void postInputRotation(TransInfo *t, float values[3]);
static bool transdata_check_local_center(TransInfo *t)
{
@@ -2576,29 +2578,33 @@ static void constraintSizeLim(TransInfo *t, TransData *td)
/* ************************** WARP *************************** */
-static void postInputWarp(TransInfo *t, float values[3])
-{
- mul_v3_fl(values, (float)(M_PI * 2));
+struct WarpCustomData {
+ float warp_sta[3];
+ float warp_end[3];
- if (t->customData) { /* non-null value indicates reversed input */
- negate_v3(values);
- }
-}
+ float warp_nor[3];
+ float warp_tan[3];
+
+ /* for applying the mouse distance */
+ float warp_init_dist;
+};
void initWarp(TransInfo *t)
{
- float max[3], min[3];
- int i;
+ const float mval_fl[2] = {UNPACK2(t->mval)};
+ const float *curs;
+ float tvec[3];
+ struct WarpCustomData *data;
t->mode = TFM_WARP;
t->transform = Warp;
t->handleEvent = handleEventWarp;
- setInputPostFct(&t->mouse, postInputWarp);
- initMouseInputMode(t, &t->mouse, INPUT_HORIZONTAL_RATIO);
+ setInputPostFct(&t->mouse, postInputRotation);
+ initMouseInputMode(t, &t->mouse, INPUT_ANGLE_SPRING);
- t->idx_max = 0;
- t->num.idx_max = 0;
+ t->idx_max = 1;
+ t->num.idx_max = 1;
t->snap[0] = 0.0f;
t->snap[1] = DEG2RAD(5.0);
t->snap[2] = DEG2RAD(1.0);
@@ -2606,28 +2612,33 @@ void initWarp(TransInfo *t)
t->num.increment = 1.0f;
t->flag |= T_NO_CONSTRAINT;
-
- /* we need min/max in view space */
- for (i = 0; i < t->total; i++) {
- float center[3];
- copy_v3_v3(center, t->data[i].center);
- mul_m3_v3(t->data[i].mtx, center);
- mul_m4_v3(t->viewmat, center);
- sub_v3_v3(center, t->viewmat[3]);
- if (i) {
- minmax_v3v3_v3(min, max, center);
- }
- else {
- copy_v3_v3(max, center);
- copy_v3_v3(min, center);
- }
+
+ //copy_v3_v3(t->center, give_cursor(t->scene, t->view));
+ calculateCenterCursor(t);
+
+ t->val = 0.0f;
+
+ data = MEM_callocN(sizeof(*data), __func__);
+
+ curs = give_cursor(t->scene, t->view);
+ copy_v3_v3(data->warp_sta, curs);
+ ED_view3d_win_to_3d(t->ar, curs, mval_fl, data->warp_end);
+
+ copy_v3_v3(data->warp_nor, t->viewinv[2]);
+ if (t->flag & T_EDIT) {
+ sub_v3_v3(data->warp_sta, t->obedit->obmat[3]);
+ sub_v3_v3(data->warp_end, t->obedit->obmat[3]);
}
+ normalize_v3(data->warp_nor);
- mid_v3_v3v3(t->center, min, max);
+ /* tangent */
+ sub_v3_v3v3(tvec, data->warp_end, data->warp_sta);
+ cross_v3_v3v3(data->warp_tan, tvec, data->warp_nor);
+ normalize_v3(data->warp_tan);
- if (max[0] == min[0])
- max[0] += 0.1f; /* not optimal, but flipping is better than invalid garbage (i.e. division by zero!) */
- t->val = (max[0] - min[0]) / 2.0f; /* t->val is X dimension projected boundbox */
+ data->warp_init_dist = len_v3v3(data->warp_end, data->warp_sta);
+
+ t->customData = data;
}
int handleEventWarp(TransInfo *t, const wmEvent *event)
@@ -2635,11 +2646,7 @@ int handleEventWarp(TransInfo *t, const wmEvent *event)
int status = 0;
if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
- // Use customData pointer to signal warp direction
- if (t->customData == NULL)
- t->customData = (void *)1;
- else
- t->customData = NULL;
+ (void)t;
status = 1;
}
@@ -2650,91 +2657,115 @@ int handleEventWarp(TransInfo *t, const wmEvent *event)
int Warp(TransInfo *t, const int UNUSED(mval[2]))
{
TransData *td = t->data;
- float vec[3], circumfac, dist, phi0, co, si, cursor[3], gcursor[3];
- const float *curs;
+ float vec[3];
+ float pivot[3];
+ float warp_end_radius[3];
int i;
char str[MAX_INFO_LEN];
-
- curs = give_cursor(t->scene, t->view);
- /*
- * gcursor is the one used for helpline.
- * It has to be in the same space as the drawing loop
- * (that means it needs to be in the object's space when in edit mode and
- * in global space in object mode)
- *
- * cursor is used for calculations.
- * It needs to be in view space, but we need to take object's offset
- * into account if in Edit mode.
- */
- copy_v3_v3(cursor, curs);
- copy_v3_v3(gcursor, cursor);
- if (t->flag & T_EDIT) {
- sub_v3_v3(cursor, t->obedit->obmat[3]);
- sub_v3_v3(gcursor, t->obedit->obmat[3]);
- mul_m3_v3(t->data->smtx, gcursor);
- }
- mul_m4_v3(t->viewmat, cursor);
- sub_v3_v3(cursor, t->viewmat[3]);
-
+ const struct WarpCustomData *data = t->customData;
+ const bool is_clamp = (t->flag & T_ALT_TRANSFORM) == 0;
+
+ union {
+ struct { float angle, scale; };
+ float vector[2];
+ } values;
+
/* amount of radians for warp */
- circumfac = t->values[0];
-
- snapGrid(t, &circumfac);
- applyNumInput(&t->num, &circumfac);
+ copy_v2_v2(values.vector, t->values);
+
+#if 0
+ snapGrid(t, angle_rad);
+#else
+ /* hrmf, snapping radius is using 'angle' steps, need to convert to something else
+ * this isnt essential but nicer to give reasonable snapping values for radius */
+ if (t->tsnap.mode == SCE_SNAP_MODE_INCREMENT) {
+ const float radius_snap = 0.1f;
+ const float snap_hack = (t->snap[1] * data->warp_init_dist) / radius_snap;
+ values.scale *= snap_hack;
+ snapGrid(t, values.vector);
+ values.scale /= snap_hack;
+ }
+#endif
/* header print for NumInput */
if (hasNumInput(&t->num)) {
- char c[NUM_STR_REP_LEN];
+ char c[NUM_STR_REP_LEN * 2];
+ applyNumInput(&t->num, values.vector);
+
outputNumInput(&(t->num), c);
- BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp: %s"), c);
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp Angle: %s Radius: %s Alt, Clamp %s"),
+ &c[0], &c[NUM_STR_REP_LEN],
+ WM_bool_as_string(is_clamp));
- circumfac = DEG2RADF(circumfac);
+ values.angle = DEG2RADF(values.angle);
+ values.scale = values.scale / data->warp_init_dist;
}
else {
/* default header print */
- BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp: %.3f"), RAD2DEGF(circumfac));
+ BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp Angle: %.3f Radius: %.4f, Alt, Clamp %s"),
+ RAD2DEGF(values.angle), values.scale * data->warp_init_dist,
+ WM_bool_as_string(is_clamp));
}
- t->values[0] = circumfac;
+ copy_v2_v2(t->values, values.vector);
- circumfac /= 2; /* only need 180 on each side to make 360 */
+ values.angle *= -1.0f;
+ values.scale *= data->warp_init_dist;
+ /* calc 'data->warp_end' from 'data->warp_end_init' */
+ copy_v3_v3(warp_end_radius, data->warp_end);
+ dist_ensure_v3_v3fl(warp_end_radius, data->warp_sta, values.scale);
+ /* done */
+
+ /* calculate pivot */
+ copy_v3_v3(pivot, data->warp_sta);
+ if (values.angle > 0.0f) {
+ madd_v3_v3fl(pivot, data->warp_tan, -values.scale * shell_angle_to_dist((float)M_PI_2 - values.angle));
+ }
+ else {
+ madd_v3_v3fl(pivot, data->warp_tan, +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle));
+ }
+
for (i = 0; i < t->total; i++, td++) {
- float loc[3];
+ float mat[3][3];
+ float delta[3];
+ float fac, fac_scaled;
+
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
-
- /* translate point to center, rotate in such a way that outline==distance */
+
+ if (UNLIKELY(values.angle == 0.0f)) {
+ copy_v3_v3(td->loc, td->iloc);
+ continue;
+ }
+
copy_v3_v3(vec, td->iloc);
mul_m3_v3(td->mtx, vec);
- mul_m4_v3(t->viewmat, vec);
- sub_v3_v3(vec, t->viewmat[3]);
-
- dist = vec[0] - cursor[0];
-
- /* t->val is X dimension projected boundbox */
- phi0 = (circumfac * dist / t->val);
-
- vec[1] = (vec[1] - cursor[1]);
-
- co = cosf(phi0);
- si = sinf(phi0);
- loc[0] = -si * vec[1] + cursor[0];
- loc[1] = co * vec[1] + cursor[1];
- loc[2] = vec[2];
-
- mul_m4_v3(t->viewinv, loc);
- sub_v3_v3(loc, t->viewinv[3]);
- mul_m3_v3(td->smtx, loc);
-
- sub_v3_v3(loc, td->iloc);
- mul_v3_fl(loc, td->factor);
- add_v3_v3v3(td->loc, td->iloc, loc);
+
+ fac = line_point_factor_v3(vec, data->warp_sta, warp_end_radius);
+ if (is_clamp) {
+ CLAMP(fac, 0.0f, 1.0f);
+ }
+
+ fac_scaled = fac * td->factor;
+ axis_angle_normalized_to_mat3(mat, data->warp_nor, values.angle * fac_scaled);
+ interp_v3_v3v3(delta, data->warp_sta, warp_end_radius, fac_scaled);
+ sub_v3_v3(delta, data->warp_sta);
+
+ /* delta is subtracted, rotation adds back this offset */
+ sub_v3_v3(vec, delta);
+
+ sub_v3_v3(vec, pivot);
+ mul_m3_v3(mat, vec);
+ add_v3_v3(vec, pivot);
+
+ mul_m3_v3(td->smtx, vec);
+ copy_v3_v3(td->loc, vec);
}
recalcData(t);
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 9355773c47b..b32ba5ad527 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -678,6 +678,7 @@ typedef enum {
INPUT_SPRING,
INPUT_SPRING_FLIP,
INPUT_ANGLE,
+ INPUT_ANGLE_SPRING,
INPUT_TRACKBALL,
INPUT_HORIZONTAL_RATIO,
INPUT_HORIZONTAL_ABSOLUTE,
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index b6f031614ca..94f481d8dfc 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -1145,6 +1145,11 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *even
if (v3d->flag & V3D_ALIGN) t->flag |= T_V3D_ALIGN;
t->around = v3d->around;
+ /* warp always uses the cursor */
+ if (t->mode == TFM_WARP) {
+ t->around = V3D_CURSOR;
+ }
+
if (op && ((prop = RNA_struct_find_property(op->ptr, "constraint_orientation")) &&
RNA_property_is_set(op->ptr, prop)))
{
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index db214e1f6db..ee993129303 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -279,6 +279,16 @@ static void InputAngle(TransInfo *UNUSED(t), MouseInput *mi, const int mval[2],
output[0] = *angle;
}
+static void InputAngleSpring(TransInfo *t, MouseInput *mi, const int mval[2], float output[3])
+{
+ float toutput[3];
+
+ InputAngle(t, mi, mval, output);
+ InputSpring(t, mi, mval, toutput);
+
+ output[1] = toutput[0];
+}
+
void initMouseInput(TransInfo *UNUSED(t), MouseInput *mi, const float center[2], const int mval[2])
{
mi->factor = 0;
@@ -328,6 +338,12 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
mi->apply = InputAngle;
t->helpline = HLP_ANGLE;
break;
+ case INPUT_ANGLE_SPRING:
+ calcSpringFactor(mi);
+ mi->data = MEM_callocN(sizeof(double), "angle accumulator");
+ mi->apply = InputAngleSpring;
+ t->helpline = HLP_ANGLE;
+ break;
case INPUT_TRACKBALL:
/* factor has to become setting or so */
mi->factor = 0.01f;