Blender  V3.3
transform_mode_bend.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include <stdlib.h>
9 
10 #include "MEM_guardedalloc.h"
11 
12 #include "DNA_gpencil_types.h"
13 
14 #include "BLI_math.h"
15 #include "BLI_string.h"
16 #include "BLI_task.h"
17 
18 #include "BKE_context.h"
19 #include "BKE_unit.h"
20 
21 #include "ED_screen.h"
22 
23 #include "WM_api.h"
24 #include "WM_types.h"
25 
26 #include "UI_interface.h"
27 
28 #include "BLT_translation.h"
29 
30 #include "transform.h"
31 #include "transform_convert.h"
32 #include "transform_snap.h"
33 
34 #include "transform_mode.h"
35 
36 /* -------------------------------------------------------------------- */
44  /* All values are in global space. */
45  float warp_sta[3];
46  float warp_end[3];
47 
48  float warp_nor[3];
49  float warp_tan[3];
50 
51  /* for applying the mouse distance */
53 };
54 
57 /* -------------------------------------------------------------------- */
65  const TransInfo *t;
67 
68  float angle;
70 
71  const float warp_sta_local[3];
72  const float warp_end_local[3];
73  const float warp_end_radius_local[3];
74  const float pivot_local[3];
75  bool is_clamp;
76 };
77 
78 static void transdata_elem_bend(const TransInfo *t,
79  const TransDataContainer *tc,
80  TransData *td,
81  float angle,
82  const struct BendCustomData *bend_data,
83  const float warp_sta_local[3],
84  const float UNUSED(warp_end_local[3]),
85  const float warp_end_radius_local[3],
86  const float pivot_local[3],
87 
88  bool is_clamp)
89 {
90  if (UNLIKELY(angle == 0.0f)) {
91  copy_v3_v3(td->loc, td->iloc);
92  return;
93  }
94 
95  float vec[3];
96  float mat[3][3];
97  float delta[3];
98  float fac, fac_scaled;
99 
100  copy_v3_v3(vec, td->iloc);
101  mul_m3_v3(td->mtx, vec);
102 
103  fac = line_point_factor_v3(vec, warp_sta_local, warp_end_radius_local);
104  if (is_clamp) {
105  CLAMP(fac, 0.0f, 1.0f);
106  }
107 
108  if (t->options & CTX_GPENCIL_STROKES) {
109  /* Grease pencil multi-frame falloff. */
110  bGPDstroke *gps = (bGPDstroke *)td->extra;
111  if (gps != NULL) {
112  fac_scaled = fac * td->factor * gps->runtime.multi_frame_falloff;
113  }
114  else {
115  fac_scaled = fac * td->factor;
116  }
117  }
118  else {
119  fac_scaled = fac * td->factor;
120  }
121 
122  axis_angle_normalized_to_mat3(mat, bend_data->warp_nor, angle * fac_scaled);
123  interp_v3_v3v3(delta, warp_sta_local, warp_end_radius_local, fac_scaled);
124  sub_v3_v3(delta, warp_sta_local);
125 
126  /* delta is subtracted, rotation adds back this offset */
127  sub_v3_v3(vec, delta);
128 
129  sub_v3_v3(vec, pivot_local);
130  mul_m3_v3(mat, vec);
131  add_v3_v3(vec, pivot_local);
132 
133  mul_m3_v3(td->smtx, vec);
134 
135  /* rotation */
136  if ((t->flag & T_POINTS) == 0) {
138  }
139 
140  /* location */
141  copy_v3_v3(td->loc, vec);
142 }
143 
144 static void transdata_elem_bend_fn(void *__restrict iter_data_v,
145  const int iter,
146  const TaskParallelTLS *__restrict UNUSED(tls))
147 {
148  struct TransDataArgs_Bend *data = iter_data_v;
149  TransData *td = &data->tc->data[iter];
150  if (td->flag & TD_SKIP) {
151  return;
152  }
154  data->tc,
155  td,
156  data->angle,
157  &data->bend_data,
158  data->warp_sta_local,
159  data->warp_end_local,
160  data->warp_end_radius_local,
161  data->pivot_local,
162  data->is_clamp);
163 }
164 
167 /* -------------------------------------------------------------------- */
172 {
173  eRedrawFlag status = TREDRAW_NOTHING;
174 
175  if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
176  status = TREDRAW_HARD;
177  }
178 
179  return status;
180 }
181 
182 static void Bend(TransInfo *t, const int UNUSED(mval[2]))
183 {
184  float pivot_global[3];
185  float warp_end_radius_global[3];
186  int i;
187  char str[UI_MAX_DRAW_STR];
188  const struct BendCustomData *bend_data = t->custom.mode.data;
189  const bool is_clamp = (t->flag & T_ALT_TRANSFORM) == 0;
190 
191  union {
192  struct {
193  float angle, scale;
194  };
195  float vector[2];
196  } values;
197 
198  /* amount of radians for bend */
199  copy_v2_v2(values.vector, t->values);
200 
201 #if 0
202  snapGrid(t, angle_rad);
203 #else
204  /* hrmf, snapping radius is using 'angle' steps, need to convert to something else
205  * this isn't essential but nicer to give reasonable snapping values for radius. */
206  if (t->tsnap.mode & SCE_SNAP_MODE_INCREMENT) {
207  const float radius_snap = 0.1f;
208  const float snap_hack = (t->snap[0] * bend_data->warp_init_dist) / radius_snap;
209  values.scale *= snap_hack;
210  transform_snap_increment(t, values.vector);
211  values.scale /= snap_hack;
212  }
213 #endif
214 
215  if (applyNumInput(&t->num, values.vector)) {
216  values.scale = values.scale / bend_data->warp_init_dist;
217  }
218 
219  copy_v2_v2(t->values_final, values.vector);
220 
221  /* header print for NumInput */
222  if (hasNumInput(&t->num)) {
223  char c[NUM_STR_REP_LEN * 2];
224 
225  outputNumInput(&(t->num), c, &t->scene->unit);
226 
228  sizeof(str),
229  TIP_("Bend Angle: %s Radius: %s Alt, Clamp %s"),
230  &c[0],
231  &c[NUM_STR_REP_LEN],
232  WM_bool_as_string(is_clamp));
233  }
234  else {
235  /* default header print */
237  sizeof(str),
238  TIP_("Bend Angle: %.3f Radius: %.4f, Alt, Clamp %s"),
239  RAD2DEGF(values.angle),
240  values.scale * bend_data->warp_init_dist,
241  WM_bool_as_string(is_clamp));
242  }
243 
244  values.angle *= -1.0f;
245  values.scale *= bend_data->warp_init_dist;
246 
247  /* calc 'data->warp_end' from 'data->warp_end_init' */
248  copy_v3_v3(warp_end_radius_global, bend_data->warp_end);
249  dist_ensure_v3_v3fl(warp_end_radius_global, bend_data->warp_sta, values.scale);
250  /* done */
251 
252  /* calculate pivot */
253  copy_v3_v3(pivot_global, bend_data->warp_sta);
254  if (values.angle > 0.0f) {
255  madd_v3_v3fl(pivot_global,
256  bend_data->warp_tan,
257  -values.scale * shell_angle_to_dist((float)M_PI_2 - values.angle));
258  }
259  else {
260  madd_v3_v3fl(pivot_global,
261  bend_data->warp_tan,
262  +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle));
263  }
264 
265  /* TODO(campbell): xform, compensate object center. */
267 
268  float warp_sta_local[3];
269  float warp_end_local[3];
270  float warp_end_radius_local[3];
271  float pivot_local[3];
272 
273  if (tc->use_local_mat) {
274  sub_v3_v3v3(warp_sta_local, bend_data->warp_sta, tc->mat[3]);
275  sub_v3_v3v3(warp_end_local, bend_data->warp_end, tc->mat[3]);
276  sub_v3_v3v3(warp_end_radius_local, warp_end_radius_global, tc->mat[3]);
277  sub_v3_v3v3(pivot_local, pivot_global, tc->mat[3]);
278  }
279  else {
280  copy_v3_v3(warp_sta_local, bend_data->warp_sta);
281  copy_v3_v3(warp_end_local, bend_data->warp_end);
282  copy_v3_v3(warp_end_radius_local, warp_end_radius_global);
283  copy_v3_v3(pivot_local, pivot_global);
284  }
285 
286  if (tc->data_len < TRANSDATA_THREAD_LIMIT) {
287  TransData *td = tc->data;
288 
289  for (i = 0; i < tc->data_len; i++, td++) {
290  if (td->flag & TD_SKIP) {
291  continue;
292  }
294  tc,
295  td,
296  values.angle,
297  bend_data,
298  warp_sta_local,
299  warp_end_local,
300  warp_end_radius_local,
301  pivot_local,
302  is_clamp);
303  }
304  }
305  else {
306  struct TransDataArgs_Bend data = {
307  .t = t,
308  .tc = tc,
309  .angle = values.angle,
310  .bend_data = *bend_data,
311  .warp_sta_local = {UNPACK3(warp_sta_local)},
312  .warp_end_local = {UNPACK3(warp_end_local)},
313  .warp_end_radius_local = {UNPACK3(warp_end_radius_local)},
314  .pivot_local = {UNPACK3(pivot_local)},
315  .is_clamp = is_clamp,
316  };
317  TaskParallelSettings settings;
320  }
321  }
322 
323  recalcData(t);
324 
325  ED_area_status_text(t->area, str);
326 }
327 
329 {
330  const float mval_fl[2] = {UNPACK2(t->mval)};
331  const float *curs;
332  float tvec[3];
333  struct BendCustomData *data;
334 
335  t->mode = TFM_BEND;
336  t->transform = Bend;
337  t->handleEvent = handleEventBend;
338 
340 
341  t->idx_max = 1;
342  t->num.idx_max = 1;
343  t->snap[0] = SNAP_INCREMENTAL_ANGLE;
344  t->snap[1] = t->snap[0] * 0.2;
345 
346  copy_v3_fl(t->num.val_inc, t->snap[0]);
347  t->num.unit_sys = t->scene->unit.system;
348  t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
349  t->num.unit_type[0] = B_UNIT_ROTATION;
350  t->num.unit_type[1] = B_UNIT_LENGTH;
351 
352  t->flag |= T_NO_CONSTRAINT;
353 
354  // copy_v3_v3(t->center, ED_view3d_cursor3d_get(t->scene, t->view));
355  if ((t->flag & T_OVERRIDE_CENTER) == 0) {
356  calculateCenterCursor(t, t->center_global);
357  }
358  calculateCenterLocal(t, t->center_global);
359 
360  data = MEM_callocN(sizeof(*data), __func__);
361 
362  curs = t->scene->cursor.location;
363  copy_v3_v3(data->warp_sta, curs);
365  (View3D *)t->area->spacedata.first, t->region, curs, mval_fl, data->warp_end);
366 
367  copy_v3_v3(data->warp_nor, t->viewinv[2]);
368  normalize_v3(data->warp_nor);
369 
370  /* tangent */
371  sub_v3_v3v3(tvec, data->warp_end, data->warp_sta);
372  cross_v3_v3v3(data->warp_tan, tvec, data->warp_nor);
373  normalize_v3(data->warp_tan);
374 
375  data->warp_init_dist = len_v3v3(data->warp_end, data->warp_sta);
376 
377  t->custom.mode.data = data;
378  t->custom.mode.use_free = true;
379 }
380 
@ B_UNIT_LENGTH
Definition: BKE_unit.h:101
@ B_UNIT_ROTATION
Definition: BKE_unit.h:105
#define M_PI_2
Definition: BLI_math_base.h:23
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3254
MINLINE float shell_angle_to_dist(float angle)
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
void axis_angle_normalized_to_mat3(float R[3][3], const float axis[3], float angle)
#define RAD2DEGF(_rad)
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_fl(float r[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
void dist_ensure_v3_v3fl(float v1[3], const float v2[3], float dist)
Definition: math_vector.c:917
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:293
#define UNPACK2(a)
#define UNUSED(x)
#define UNPACK3(a)
#define UNLIKELY(x)
#define TIP_(msgid)
#define USER_UNIT_ROT_RADIANS
@ SCE_SNAP_MODE_INCREMENT
@ V3D_AROUND_LOCAL_ORIGINS
void outputNumInput(NumInput *n, char *str, struct UnitSettings *unit_settings)
Definition: numinput.c:87
#define NUM_STR_REP_LEN
Definition: ED_numinput.h:13
bool applyNumInput(NumInput *n, float *vec)
Definition: numinput.c:189
bool hasNumInput(const NumInput *n)
Definition: numinput.c:170
void ED_area_status_text(ScrArea *area, const char *str)
Definition: area.c:792
#define SNAP_INCREMENTAL_ANGLE
Definition: ED_transform.h:172
@ TFM_BEND
Definition: ED_transform.h:36
void ED_view3d_win_to_3d(const struct View3D *v3d, const struct ARegion *region, const float depth_pt[3], const float mval[2], float r_out[3])
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
#define UI_MAX_DRAW_STR
Definition: UI_interface.h:91
@ KM_PRESS
Definition: WM_types.h:267
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
#define str(s)
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static unsigned c
Definition: RandGen.cpp:83
void calculateCenterCursor(TransInfo *t, float r_center[3])
void calculateCenterLocal(TransInfo *t, const float center_global[3])
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
#define FOREACH_TRANS_DATA_CONTAINER(t, th)
const float pivot_local[3]
const TransDataContainer * tc
const TransInfo * t
const float warp_end_local[3]
const float warp_end_radius_local[3]
const float warp_sta_local[3]
struct BendCustomData bend_data
float smtx[3][3]
float mtx[3][3]
bGPDstroke_Runtime runtime
short val
Definition: WM_types.h:680
short type
Definition: WM_types.h:678
void recalcData(TransInfo *t)
conversion and adaptation of different datablocks to a common struct.
@ TD_SKIP
#define TRANSDATA_THREAD_LIMIT
void ElementRotation(const TransInfo *t, const TransDataContainer *tc, TransData *td, const float mat[3][3], const short around)
transform modes used by different operators.
static eRedrawFlag handleEventBend(TransInfo *UNUSED(t), const wmEvent *event)
static void transdata_elem_bend_fn(void *__restrict iter_data_v, const int iter, const TaskParallelTLS *__restrict UNUSED(tls))
static void Bend(TransInfo *t, const int UNUSED(mval[2]))
static void transdata_elem_bend(const TransInfo *t, const TransDataContainer *tc, TransData *td, float angle, const struct BendCustomData *bend_data, const float warp_sta_local[3], const float UNUSED(warp_end_local[3]), const float warp_end_radius_local[3], const float pivot_local[3], bool is_clamp)
void initBend(TransInfo *t)
bool transform_snap_increment(const TransInfo *t, float *r_val)
@ MIDDLEMOUSE
const char * WM_bool_as_string(bool test)
Definition: wm_keymap.c:2052