Blender  V2.93
transform_mode_bend.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19 
24 #include <stdlib.h>
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "DNA_gpencil_types.h"
29 
30 #include "BLI_math.h"
31 #include "BLI_string.h"
32 
33 #include "BKE_context.h"
34 #include "BKE_unit.h"
35 
36 #include "ED_screen.h"
37 
38 #include "WM_api.h"
39 #include "WM_types.h"
40 
41 #include "UI_interface.h"
42 
43 #include "BLT_translation.h"
44 
45 #include "transform.h"
46 #include "transform_mode.h"
47 #include "transform_snap.h"
48 
49 /* -------------------------------------------------------------------- */
54  /* All values are in global space. */
55  float warp_sta[3];
56  float warp_end[3];
57 
58  float warp_nor[3];
59  float warp_tan[3];
60 
61  /* for applying the mouse distance */
63 };
64 
66 {
68 
69  if (event->type == MIDDLEMOUSE && event->val == KM_PRESS) {
70  status = TREDRAW_HARD;
71  }
72 
73  return status;
74 }
75 
76 static void Bend(TransInfo *t, const int UNUSED(mval[2]))
77 {
78  float vec[3];
79  float pivot_global[3];
80  float warp_end_radius_global[3];
81  int i;
82  char str[UI_MAX_DRAW_STR];
83  const struct BendCustomData *data = t->custom.mode.data;
84  const bool is_clamp = (t->flag & T_ALT_TRANSFORM) == 0;
85 
86  union {
87  struct {
88  float angle, scale;
89  };
90  float vector[2];
91  } values;
92 
93  /* amount of radians for bend */
94  copy_v2_v2(values.vector, t->values);
95 
96 #if 0
97  snapGrid(t, angle_rad);
98 #else
99  /* hrmf, snapping radius is using 'angle' steps, need to convert to something else
100  * this isn't essential but nicer to give reasonable snapping values for radius. */
101  if (t->tsnap.mode & SCE_SNAP_MODE_INCREMENT) {
102  const float radius_snap = 0.1f;
103  const float snap_hack = (t->snap[0] * data->warp_init_dist) / radius_snap;
104  values.scale *= snap_hack;
105  transform_snap_increment(t, values.vector);
106  values.scale /= snap_hack;
107  }
108 #endif
109 
110  if (applyNumInput(&t->num, values.vector)) {
111  values.scale = values.scale / data->warp_init_dist;
112  }
113 
114  copy_v2_v2(t->values_final, values.vector);
115 
116  /* header print for NumInput */
117  if (hasNumInput(&t->num)) {
118  char c[NUM_STR_REP_LEN * 2];
119 
120  outputNumInput(&(t->num), c, &t->scene->unit);
121 
123  sizeof(str),
124  TIP_("Bend Angle: %s Radius: %s Alt, Clamp %s"),
125  &c[0],
126  &c[NUM_STR_REP_LEN],
127  WM_bool_as_string(is_clamp));
128  }
129  else {
130  /* default header print */
132  sizeof(str),
133  TIP_("Bend Angle: %.3f Radius: %.4f, Alt, Clamp %s"),
134  RAD2DEGF(values.angle),
135  values.scale * data->warp_init_dist,
136  WM_bool_as_string(is_clamp));
137  }
138 
139  values.angle *= -1.0f;
140  values.scale *= data->warp_init_dist;
141 
142  /* calc 'data->warp_end' from 'data->warp_end_init' */
143  copy_v3_v3(warp_end_radius_global, data->warp_end);
144  dist_ensure_v3_v3fl(warp_end_radius_global, data->warp_sta, values.scale);
145  /* done */
146 
147  /* calculate pivot */
148  copy_v3_v3(pivot_global, data->warp_sta);
149  if (values.angle > 0.0f) {
150  madd_v3_v3fl(pivot_global,
151  data->warp_tan,
152  -values.scale * shell_angle_to_dist((float)M_PI_2 - values.angle));
153  }
154  else {
155  madd_v3_v3fl(pivot_global,
156  data->warp_tan,
157  +values.scale * shell_angle_to_dist((float)M_PI_2 + values.angle));
158  }
159 
160  /* TODO(campbell): xform, compensate object center. */
162  TransData *td = tc->data;
163 
164  float warp_sta_local[3];
165  float warp_end_local[3];
166  float warp_end_radius_local[3];
167  float pivot_local[3];
168 
169  if (tc->use_local_mat) {
170  sub_v3_v3v3(warp_sta_local, data->warp_sta, tc->mat[3]);
171  sub_v3_v3v3(warp_end_local, data->warp_end, tc->mat[3]);
172  sub_v3_v3v3(warp_end_radius_local, warp_end_radius_global, tc->mat[3]);
173  sub_v3_v3v3(pivot_local, pivot_global, tc->mat[3]);
174  }
175  else {
176  copy_v3_v3(warp_sta_local, data->warp_sta);
177  copy_v3_v3(warp_end_local, data->warp_end);
178  copy_v3_v3(warp_end_radius_local, warp_end_radius_global);
179  copy_v3_v3(pivot_local, pivot_global);
180  }
181 
182  for (i = 0; i < tc->data_len; i++, td++) {
183  float mat[3][3];
184  float delta[3];
185  float fac, fac_scaled;
186 
187  if (td->flag & TD_SKIP) {
188  continue;
189  }
190 
191  if (UNLIKELY(values.angle == 0.0f)) {
192  copy_v3_v3(td->loc, td->iloc);
193  continue;
194  }
195 
196  copy_v3_v3(vec, td->iloc);
197  mul_m3_v3(td->mtx, vec);
198 
199  fac = line_point_factor_v3(vec, warp_sta_local, warp_end_radius_local);
200  if (is_clamp) {
201  CLAMP(fac, 0.0f, 1.0f);
202  }
203 
204  if (t->options & CTX_GPENCIL_STROKES) {
205  /* grease pencil multiframe falloff */
206  bGPDstroke *gps = (bGPDstroke *)td->extra;
207  if (gps != NULL) {
208  fac_scaled = fac * td->factor * gps->runtime.multi_frame_falloff;
209  }
210  else {
211  fac_scaled = fac * td->factor;
212  }
213  }
214  else {
215  fac_scaled = fac * td->factor;
216  }
217 
218  axis_angle_normalized_to_mat3(mat, data->warp_nor, values.angle * fac_scaled);
219  interp_v3_v3v3(delta, warp_sta_local, warp_end_radius_local, fac_scaled);
220  sub_v3_v3(delta, warp_sta_local);
221 
222  /* delta is subtracted, rotation adds back this offset */
223  sub_v3_v3(vec, delta);
224 
225  sub_v3_v3(vec, pivot_local);
226  mul_m3_v3(mat, vec);
227  add_v3_v3(vec, pivot_local);
228 
229  mul_m3_v3(td->smtx, vec);
230 
231  /* rotation */
232  if ((t->flag & T_POINTS) == 0) {
234  }
235 
236  /* location */
237  copy_v3_v3(td->loc, vec);
238  }
239  }
240 
241  recalcData(t);
242 
243  ED_area_status_text(t->area, str);
244 }
245 
247 {
248  const float mval_fl[2] = {UNPACK2(t->mval)};
249  const float *curs;
250  float tvec[3];
251  struct BendCustomData *data;
252 
253  t->mode = TFM_BEND;
254  t->transform = Bend;
255  t->handleEvent = handleEventBend;
256 
258 
259  t->idx_max = 1;
260  t->num.idx_max = 1;
261  t->snap[0] = SNAP_INCREMENTAL_ANGLE;
262  t->snap[1] = t->snap[0] * 0.2;
263 
264  copy_v3_fl(t->num.val_inc, t->snap[0]);
265  t->num.unit_sys = t->scene->unit.system;
266  t->num.unit_use_radians = (t->scene->unit.system_rotation == USER_UNIT_ROT_RADIANS);
267  t->num.unit_type[0] = B_UNIT_ROTATION;
268  t->num.unit_type[1] = B_UNIT_LENGTH;
269 
270  t->flag |= T_NO_CONSTRAINT;
271 
272  // copy_v3_v3(t->center, ED_view3d_cursor3d_get(t->scene, t->view));
273  if ((t->flag & T_OVERRIDE_CENTER) == 0) {
274  calculateCenterCursor(t, t->center_global);
275  }
276  calculateCenterLocal(t, t->center_global);
277 
278  data = MEM_callocN(sizeof(*data), __func__);
279 
280  curs = t->scene->cursor.location;
281  copy_v3_v3(data->warp_sta, curs);
283  (View3D *)t->area->spacedata.first, t->region, curs, mval_fl, data->warp_end);
284 
285  copy_v3_v3(data->warp_nor, t->viewinv[2]);
286  normalize_v3(data->warp_nor);
287 
288  /* tangent */
289  sub_v3_v3v3(tvec, data->warp_end, data->warp_sta);
290  cross_v3_v3v3(data->warp_tan, tvec, data->warp_nor);
291  normalize_v3(data->warp_tan);
292 
293  data->warp_init_dist = len_v3v3(data->warp_end, data->warp_sta);
294 
295  t->custom.mode.data = data;
296  t->custom.mode.use_free = true;
297 }
@ B_UNIT_LENGTH
Definition: BKE_unit.h:79
@ B_UNIT_ROTATION
Definition: BKE_unit.h:83
#define M_PI_2
Definition: BLI_math_base.h:41
float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
Definition: math_geom.c:3449
MINLINE float shell_angle_to_dist(const float angle)
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:930
void axis_angle_normalized_to_mat3(float R[3][3], const float axis[3], const float angle)
#define RAD2DEGF(_rad)
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], const float t)
Definition: math_vector.c:49
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])
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)
void dist_ensure_v3_v3fl(float v1[3], const float v2[3], const float dist)
Definition: math_vector.c:1068
MINLINE void add_v3_v3(float r[3], const float a[3])
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
#define UNPACK2(a)
#define UNUSED(x)
#define UNLIKELY(x)
#define TIP_(msgid)
#define USER_UNIT_ROT_RADIANS
#define SCE_SNAP_MODE_INCREMENT
@ V3D_AROUND_LOCAL_ORIGINS
void outputNumInput(NumInput *n, char *str, struct UnitSettings *unit_settings)
Definition: numinput.c:102
#define NUM_STR_REP_LEN
Definition: ED_numinput.h:27
bool applyNumInput(NumInput *n, float *vec)
Definition: numinput.c:207
bool hasNumInput(const NumInput *n)
Definition: numinput.c:185
void ED_area_status_text(ScrArea *area, const char *str)
Definition: area.c:815
#define SNAP_INCREMENTAL_ANGLE
Definition: ED_transform.h:173
@ TFM_BEND
Definition: ED_transform.h:52
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 RGB to Bright Vector Camera CLAMP
#define UI_MAX_DRAW_STR
Definition: UI_interface.h:90
#define KM_PRESS
Definition: WM_types.h:242
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:45
static unsigned c
Definition: RandGen.cpp:97
float smtx[3][3]
float mtx[3][3]
bGPDstroke_Runtime runtime
short val
Definition: WM_types.h:579
short type
Definition: WM_types.h:577
@ INPUT_ANGLE_SPRING
Definition: transform.h:733
void recalcData(TransInfo *t)
@ CTX_GPENCIL_STROKES
Definition: transform.h:82
eRedrawFlag
Definition: transform.h:197
@ TREDRAW_NOTHING
Definition: transform.h:198
@ TREDRAW_HARD
Definition: transform.h:199
@ T_OVERRIDE_CENTER
Definition: transform.h:143
@ T_ALT_TRANSFORM
Definition: transform.h:140
@ T_POINTS
Definition: transform.h:104
@ T_NO_CONSTRAINT
Definition: transform.h:106
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)
Definition: transform.h:813
@ TD_SKIP
void ElementRotation(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around)
transform modes used by different operators.
static eRedrawFlag handleEventBend(TransInfo *UNUSED(t), const wmEvent *event)
static void Bend(TransInfo *t, const int UNUSED(mval[2]))
void initBend(TransInfo *t)
bool transform_snap_increment(TransInfo *t, float *r_val)
@ MIDDLEMOUSE
const char * WM_bool_as_string(bool test)
Definition: wm_keymap.c:2003