Blender  V3.3
object_warp.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2013 Blender Foundation. All rights reserved. */
3 
8 #include "DNA_object_types.h"
9 #include "DNA_scene_types.h"
10 #include "DNA_view3d_types.h"
11 
12 #include "BLI_math.h"
13 
14 #include "BKE_context.h"
15 
16 #include "RNA_access.h"
17 #include "RNA_define.h"
18 
19 #include "WM_api.h"
20 #include "WM_types.h"
21 
22 #include "ED_transverts.h"
23 
24 #include "object_intern.h"
25 
26 static void object_warp_calc_view_matrix(float r_mat_view[4][4],
27  float r_center_view[3],
28  Object *obedit,
29  const float viewmat[4][4],
30  const float center[3],
31  const float offset_angle)
32 {
33  float mat_offset[4][4];
34  float viewmat_roll[4][4];
35 
36  /* apply the rotation offset by rolling the view */
37  axis_angle_to_mat4_single(mat_offset, 'Z', offset_angle);
38  mul_m4_m4m4(viewmat_roll, mat_offset, viewmat);
39 
40  /* apply the view and the object matrix */
41  mul_m4_m4m4(r_mat_view, viewmat_roll, obedit->obmat);
42 
43  /* get the view-space cursor */
44  mul_v3_m4v3(r_center_view, viewmat_roll, center);
45 }
46 
48  const float mat_view[4][4],
49  const float center_view[3],
50  float *r_min,
51  float *r_max)
52 {
53  /* no need to apply translation and cursor offset for every vertex, delay this */
54  const float x_ofs = (mat_view[3][0] - center_view[0]);
55  float min = FLT_MAX, max = -FLT_MAX;
56 
57  TransVert *tv = tvs->transverts;
58  for (int i = 0; i < tvs->transverts_tot; i++, tv++) {
59  float val;
60 
61  /* Convert object-space to view-space. */
62  val = dot_m4_v3_row_x(mat_view, tv->loc);
63 
64  min = min_ff(min, val);
65  max = max_ff(max, val);
66  }
67 
68  *r_min = min + x_ofs;
69  *r_max = max + x_ofs;
70 }
71 
73  const float mat_view[4][4],
74  const float center_view[3],
75  const float angle_,
76  const float min,
77  const float max)
78 {
79  TransVert *tv;
80  const float angle = -angle_;
81  /* cache vars for tiny speedup */
82 #if 1
83  const float range = max - min;
84  const float range_inv = 1.0f / range;
85  const float min_ofs = min + (0.5f * range);
86 #endif
87 
88  float dir_min[2], dir_max[2];
89  float imat_view[4][4];
90 
91  invert_m4_m4(imat_view, mat_view);
92 
93  /* calculate the direction vectors outside min/max range */
94  {
95  const float phi = angle * 0.5f;
96 
97  dir_max[0] = cosf(phi);
98  dir_max[1] = sinf(phi);
99 
100  dir_min[0] = -dir_max[0];
101  dir_min[1] = dir_max[1];
102  }
103 
104  tv = tvs->transverts;
105  for (int i = 0; i < tvs->transverts_tot; i++, tv++) {
106  float co[3], co_add[2];
107  float val, phi;
108 
109  /* Convert object-space to view-space. */
110  mul_v3_m4v3(co, mat_view, tv->loc);
111  sub_v2_v2(co, center_view);
112 
113  val = co[0];
114  /* is overwritten later anyway */
115  // co[0] = 0.0f;
116 
117  if (val < min) {
118  mul_v2_v2fl(co_add, dir_min, min - val);
119  val = min;
120  }
121  else if (val > max) {
122  mul_v2_v2fl(co_add, dir_max, val - max);
123  val = max;
124  }
125  else {
126  zero_v2(co_add);
127  }
128 
129  /* map from x axis to (-0.5 - 0.5) */
130 #if 0
131  val = ((val - min) / (max - min)) - 0.5f;
132 #else
133  val = (val - min_ofs) * range_inv;
134 #endif
135 
136  /* convert the x axis into a rotation */
137  phi = val * angle;
138 
139  co[0] = -sinf(phi) * co[1];
140  co[1] = cosf(phi) * co[1];
141 
142  add_v2_v2(co, co_add);
143 
144  /* Convert view-space to object-space. */
145  add_v2_v2(co, center_view);
146  mul_v3_m4v3(tv->loc, imat_view, co);
147  }
148 }
149 
151 {
152  const float warp_angle = RNA_float_get(op->ptr, "warp_angle");
153  const float offset_angle = RNA_float_get(op->ptr, "offset_angle");
154 
155  TransVertStore tvs = {NULL};
156  Object *obedit = CTX_data_edit_object(C);
157 
158  /* typically from 'rv3d' and 3d cursor */
159  float viewmat[4][4];
160  float center[3];
161 
162  /* 'viewmat' relative vars */
163  float mat_view[4][4];
164  float center_view[3];
165 
166  float min, max;
167 
169  if (tvs.transverts == NULL) {
170  return OPERATOR_CANCELLED;
171  }
172 
173  /* Get view-matrix. */
174  {
175  PropertyRNA *prop_viewmat = RNA_struct_find_property(op->ptr, "viewmat");
176  if (RNA_property_is_set(op->ptr, prop_viewmat)) {
177  RNA_property_float_get_array(op->ptr, prop_viewmat, (float *)viewmat);
178  }
179  else {
181 
182  if (rv3d) {
183  copy_m4_m4(viewmat, rv3d->viewmat);
184  }
185  else {
186  unit_m4(viewmat);
187  }
188 
189  RNA_property_float_set_array(op->ptr, prop_viewmat, (float *)viewmat);
190  }
191  }
192 
193  /* get center */
194  {
195  PropertyRNA *prop_center = RNA_struct_find_property(op->ptr, "center");
196  if (RNA_property_is_set(op->ptr, prop_center)) {
197  RNA_property_float_get_array(op->ptr, prop_center, center);
198  }
199  else {
200  const Scene *scene = CTX_data_scene(C);
202 
203  RNA_property_float_set_array(op->ptr, prop_center, center);
204  }
205  }
206 
207  object_warp_calc_view_matrix(mat_view, center_view, obedit, viewmat, center, offset_angle);
208 
209  /* get minmax */
210  {
211  PropertyRNA *prop_min = RNA_struct_find_property(op->ptr, "min");
212  PropertyRNA *prop_max = RNA_struct_find_property(op->ptr, "max");
213 
214  if (RNA_property_is_set(op->ptr, prop_min) || RNA_property_is_set(op->ptr, prop_max)) {
215  min = RNA_property_float_get(op->ptr, prop_min);
216  max = RNA_property_float_get(op->ptr, prop_max);
217  }
218  else {
219  /* handy to set the bounds of the mesh */
220  object_warp_transverts_minmax_x(&tvs, mat_view, center_view, &min, &max);
221 
222  RNA_property_float_set(op->ptr, prop_min, min);
223  RNA_property_float_set(op->ptr, prop_max, max);
224  }
225 
226  if (min > max) {
227  SWAP(float, min, max);
228  }
229  }
230 
231  if (min != max) {
232  object_warp_transverts(&tvs, mat_view, center_view, warp_angle, min, max);
233  }
234 
235  ED_transverts_update_obedit(&tvs, obedit);
236  ED_transverts_free(&tvs);
237 
239 
240  return OPERATOR_FINISHED;
241 }
242 
244 {
245  PropertyRNA *prop;
246 
247  /* identifiers */
248  ot->name = "Warp";
249  ot->description = "Warp vertices around the cursor";
250  ot->idname = "TRANSFORM_OT_vertex_warp";
251 
252  /* api callbacks */
255 
256  /* flags */
258 
259  /* props */
260  prop = RNA_def_float(ot->srna,
261  "warp_angle",
262  DEG2RADF(360.0f),
263  -FLT_MAX,
264  FLT_MAX,
265  "Warp Angle",
266  "Amount to warp about the cursor",
267  DEG2RADF(-360.0f),
268  DEG2RADF(360.0f));
270 
271  prop = RNA_def_float(ot->srna,
272  "offset_angle",
273  DEG2RADF(0.0f),
274  -FLT_MAX,
275  FLT_MAX,
276  "Offset Angle",
277  "Angle to use as the basis for warping",
278  DEG2RADF(-360.0f),
279  DEG2RADF(360.0f));
281 
282  prop = RNA_def_float(ot->srna, "min", -1.0f, -FLT_MAX, FLT_MAX, "Min", "", -100.0, 100.0);
283  prop = RNA_def_float(ot->srna, "max", 1.0f, -FLT_MAX, FLT_MAX, "Max", "", -100.0, 100.0);
284 
285  /* hidden props */
286  prop = RNA_def_float_matrix(
287  ot->srna, "viewmat", 4, 4, NULL, 0.0f, 0.0f, "Matrix", "", 0.0f, 0.0f);
289 
291  ot->srna, "center", 3, NULL, -FLT_MAX, FLT_MAX, "Center", "", -FLT_MAX, FLT_MAX);
293 }
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1370
struct RegionView3D * CTX_wm_region_view3d(const bContext *C)
Definition: context.c:793
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
void unit_m4(float m[4][4])
Definition: rct.c:1090
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
#define DEG2RADF(_deg)
void axis_angle_to_mat4_single(float R[4][4], char axis, float angle)
MINLINE void sub_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v2_v2(float r[2], const float a[2])
MINLINE void zero_v2(float r[2])
MINLINE void mul_v2_v2fl(float r[2], const float a[2], float f)
MINLINE float dot_m4_v3_row_x(const float M[4][4], const float a[3]) ATTR_WARN_UNUSED_RESULT
#define SWAP(type, a, b)
Object is a sort of wrapper for general info.
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
void ED_transverts_update_obedit(TransVertStore *tvs, struct Object *obedit)
Definition: ed_transverts.c:37
void ED_transverts_create_from_obedit(TransVertStore *tvs, const struct Object *obedit, int mode)
bool ED_transverts_poll(struct bContext *C)
void ED_transverts_free(TransVertStore *tvs)
@ TM_SKIP_HANDLES
Definition: ED_transverts.h:55
@ TM_ALL_JOINTS
Definition: ED_transverts.h:53
NSNotificationCenter * center
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
@ PROP_HIDDEN
Definition: RNA_types.h:216
@ PROP_ANGLE
Definition: RNA_types.h:145
#define C
Definition: RandGen.cpp:25
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define ND_DRAW
Definition: WM_types.h:410
#define NC_OBJECT
Definition: WM_types.h:329
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
Scene scene
static int object_warp_verts_exec(bContext *C, wmOperator *op)
Definition: object_warp.c:150
static void object_warp_transverts(TransVertStore *tvs, const float mat_view[4][4], const float center_view[3], const float angle_, const float min, const float max)
Definition: object_warp.c:72
void TRANSFORM_OT_vertex_warp(struct wmOperatorType *ot)
Definition: object_warp.c:243
static void object_warp_calc_view_matrix(float r_mat_view[4][4], float r_center_view[3], Object *obedit, const float viewmat[4][4], const float center[3], const float offset_angle)
Definition: object_warp.c:26
static void object_warp_transverts_minmax_x(TransVertStore *tvs, const float mat_view[4][4], const float center_view[3], float *r_min, float *r_max)
Definition: object_warp.c:47
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2767
void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *values)
Definition: rna_access.c:2879
bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:5271
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:717
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4957
void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values)
Definition: rna_access.c:2978
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
Definition: rna_access.c:2790
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3836
PropertyRNA * RNA_def_float_matrix(StructOrFunctionRNA *cont_, const char *identifier, int rows, int columns, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3954
PropertyRNA * RNA_def_float_vector_xyz(StructOrFunctionRNA *cont_, const char *identifier, int len, const float *default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3894
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
void RNA_def_property_subtype(PropertyRNA *prop, PropertySubType subtype)
Definition: rna_define.c:1534
#define min(a, b)
Definition: sort.c:35
float obmat[4][4]
float viewmat[4][4]
View3DCursor cursor
struct TransVert * transverts
Definition: ED_transverts.h:25
float * loc
Definition: ED_transverts.h:18
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
struct PointerRNA * ptr
float max
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3479