Blender  V2.93
editlattice_tools.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 "MEM_guardedalloc.h"
25 
26 #include "BLI_math.h"
27 #include "BLI_utildefines.h"
28 
29 #include "DNA_curve_types.h"
30 #include "DNA_lattice_types.h"
31 #include "DNA_object_types.h"
32 #include "DNA_scene_types.h"
33 
34 #include "RNA_access.h"
35 #include "RNA_define.h"
36 
37 #include "BKE_context.h"
38 #include "BKE_lattice.h"
39 #include "BKE_layer.h"
40 
41 #include "DEG_depsgraph.h"
42 
43 #include "ED_screen.h"
44 
45 #include "WM_api.h"
46 #include "WM_types.h"
47 
48 #include "lattice_intern.h"
49 
52 /* -------------------------------------------------------------------- */
57 {
58  Object *ob;
59 
61  return true;
62  }
63 
65  return (ob && ob->type == OB_LATTICE);
66 }
67 
69 {
70  ViewLayer *view_layer = CTX_data_view_layer(C);
71  View3D *v3d = CTX_wm_view3d(C);
72  const bool is_editmode = CTX_data_edit_object(C) != NULL;
73 
74  if (is_editmode) {
75  uint objects_len;
77  view_layer, CTX_wm_view3d(C), &objects_len);
78  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
79  Object *ob = objects[ob_index];
80  Lattice *lt = ob->data;
81 
82  if (lt->editlatt->latt == NULL) {
83  continue;
84  }
85 
86  BKE_lattice_resize(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
87 
90  }
91  MEM_freeN(objects);
92  }
93  else {
94  FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
95  if (ob->type != OB_LATTICE) {
96  continue;
97  }
98 
99  Lattice *lt = ob->data;
100  BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
101 
103  WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
104  }
106  }
107  return OPERATOR_FINISHED;
108 }
109 
111 {
112  /* identifiers */
113  ot->name = "Make Regular";
114  ot->description = "Set UVW control points a uniform distance apart";
115  ot->idname = "LATTICE_OT_make_regular";
116 
117  /* api callbacks */
120 
121  /* flags */
123 }
124 
127 /* -------------------------------------------------------------------- */
131 /* flipping options */
132 typedef enum eLattice_FlipAxes {
137 
144  Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
145 {
146  BPoint *bp;
147  float diff;
148 
149  /* just the point in the middle (unpaired) */
150  bp = &lt->def[BKE_lattice_index_from_uvw(lt, u, v, w)];
151 
152  /* flip over axis */
153  diff = mid - bp->vec[axis];
154  bp->vec[axis] = mid + diff;
155 }
156 
162  Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
163 {
164  BPoint *bpA, *bpB;
165 
166  int numU = lt->pntsu;
167  int numV = lt->pntsv;
168  int numW = lt->pntsw;
169 
170  int u0 = u, u1 = u;
171  int v0 = v, v1 = v;
172  int w0 = w, w1 = w;
173 
174  /* get pair index by just overriding the relevant pair-value
175  * - "-1" else buffer overflow
176  */
177  switch (axis) {
178  case LATTICE_FLIP_U:
179  u1 = numU - u - 1;
180  break;
181  case LATTICE_FLIP_V:
182  v1 = numV - v - 1;
183  break;
184  case LATTICE_FLIP_W:
185  w1 = numW - w - 1;
186  break;
187  }
188 
189  /* get points to operate on */
190  bpA = &lt->def[BKE_lattice_index_from_uvw(lt, u0, v0, w0)];
191  bpB = &lt->def[BKE_lattice_index_from_uvw(lt, u1, v1, w1)];
192 
193  /* Swap all coordinates, so that flipped coordinates belong to
194  * the indices on the correct side of the lattice.
195  *
196  * Coords: (-2 4) |0| (3 4) --> (3 4) |0| (-2 4)
197  * Indices: (0,L) (1,R) --> (0,L) (1,R)
198  */
199  swap_v3_v3(bpA->vec, bpB->vec);
200 
201  /* However, we need to mirror the coordinate values on the axis we're dealing with,
202  * otherwise we'd have effectively only rotated the points around. If we don't do this,
203  * we'd just be reimplementing the naive mirroring algorithm, which causes unwanted deforms
204  * such as flipped normals, etc.
205  *
206  * Coords: (3 4) |0| (-2 4) --\
207  * \-> (-3 4) |0| (2 4)
208  * Indices: (0,L) (1,R) --> (0,L) (1,R)
209  */
210  lattice_flip_point_value(lt, u0, v0, w0, mid, axis);
211  lattice_flip_point_value(lt, u1, v1, w1, mid, axis);
212 }
213 
215 {
216  ViewLayer *view_layer = CTX_data_view_layer(C);
217  uint objects_len;
218  bool changed = false;
219  const eLattice_FlipAxes axis = RNA_enum_get(op->ptr, "axis");
220 
222  view_layer, CTX_wm_view3d(C), &objects_len);
223  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
224  Object *obedit = objects[ob_index];
225  Lattice *lt;
226 
227  int numU, numV, numW;
228  int totP;
229 
230  float mid = 0.0f;
231  short isOdd = 0;
232 
233  /* get lattice - we need the "edit lattice" from the lattice... confusing... */
234  lt = (Lattice *)obedit->data;
235  lt = lt->editlatt->latt;
236 
237  numU = lt->pntsu;
238  numV = lt->pntsv;
239  numW = lt->pntsw;
240  totP = numU * numV * numW;
241 
242  /* First Pass: determine midpoint - used for flipping center verts if there
243  * are odd number of points on axis */
244  switch (axis) {
245  case LATTICE_FLIP_U:
246  isOdd = numU & 1;
247  break;
248  case LATTICE_FLIP_V:
249  isOdd = numV & 1;
250  break;
251  case LATTICE_FLIP_W:
252  isOdd = numW & 1;
253  break;
254 
255  default:
256  printf("lattice_flip(): Unknown flipping axis (%u)\n", axis);
257  return OPERATOR_CANCELLED;
258  }
259 
260  if (isOdd) {
261  BPoint *bp;
262  float avgInv = 1.0f / (float)totP;
263  int i;
264 
265  /* midpoint calculation - assuming that u/v/w are axis-aligned */
266  for (i = 0, bp = lt->def; i < totP; i++, bp++) {
267  mid += bp->vec[axis] * avgInv;
268  }
269  }
270 
271  /* Second Pass: swap pairs of vertices per axis, assuming they are all sorted */
272  switch (axis) {
273  case LATTICE_FLIP_U: {
274  int u, v, w;
275 
276  /* v/w strips - front to back, top to bottom */
277  for (w = 0; w < numW; w++) {
278  for (v = 0; v < numV; v++) {
279  /* swap coordinates of pairs of vertices on u */
280  for (u = 0; u < (numU / 2); u++) {
281  lattice_swap_point_pairs(lt, u, v, w, mid, axis);
282  }
283 
284  /* flip u-coordinate of midpoint (i.e. unpaired point on u) */
285  if (isOdd) {
286  u = (numU / 2);
287  lattice_flip_point_value(lt, u, v, w, mid, axis);
288  }
289  }
290  }
291  break;
292  }
293  case LATTICE_FLIP_V: {
294  int u, v, w;
295 
296  /* u/w strips - front to back, left to right */
297  for (w = 0; w < numW; w++) {
298  for (u = 0; u < numU; u++) {
299  /* swap coordinates of pairs of vertices on v */
300  for (v = 0; v < (numV / 2); v++) {
301  lattice_swap_point_pairs(lt, u, v, w, mid, axis);
302  }
303 
304  /* flip v-coordinate of midpoint (i.e. unpaired point on v) */
305  if (isOdd) {
306  v = (numV / 2);
307  lattice_flip_point_value(lt, u, v, w, mid, axis);
308  }
309  }
310  }
311  break;
312  }
313  case LATTICE_FLIP_W: {
314  int u, v, w;
315 
316  for (v = 0; v < numV; v++) {
317  for (u = 0; u < numU; u++) {
318  /* swap coordinates of pairs of vertices on w */
319  for (w = 0; w < (numW / 2); w++) {
320  lattice_swap_point_pairs(lt, u, v, w, mid, axis);
321  }
322 
323  /* flip w-coordinate of midpoint (i.e. unpaired point on w) */
324  if (isOdd) {
325  w = (numW / 2);
326  lattice_flip_point_value(lt, u, v, w, mid, axis);
327  }
328  }
329  }
330  break;
331  }
332  default: /* shouldn't happen, but just in case */
333  break;
334  }
335 
336  /* updates */
339  changed = true;
340  }
341  MEM_freeN(objects);
342 
343  return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
344 }
345 
347 {
348  static const EnumPropertyItem flip_items[] = {
349  {LATTICE_FLIP_U, "U", 0, "U (X) Axis", ""},
350  {LATTICE_FLIP_V, "V", 0, "V (Y) Axis", ""},
351  {LATTICE_FLIP_W, "W", 0, "W (Z) Axis", ""},
352  {0, NULL, 0, NULL, NULL},
353  };
354 
355  /* identifiers */
356  ot->name = "Flip (Distortion Free)";
357  ot->description = "Mirror all control points without inverting the lattice deform";
358  ot->idname = "LATTICE_OT_flip";
359 
360  /* api callbacks */
364 
365  /* flags */
367 
368  /* properties */
369  ot->prop = RNA_def_enum(ot->srna,
370  "axis",
371  flip_items,
373  "Flip Axis",
374  "Coordinates along this axis get flipped");
375 }
376 
typedef float(TangentPoint)[2]
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1296
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1279
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:760
void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb)
Definition: lattice.c:289
int BKE_lattice_index_from_uvw(struct Lattice *lt, const int u, const int v, const int w)
Definition: lattice.c:214
#define FOREACH_SELECTED_OBJECT_BEGIN(_view_layer, _v3d, _instance)
Definition: BKE_layer.h:200
#define BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, r_len)
Definition: BKE_layer.h:426
#define FOREACH_SELECTED_OBJECT_END
Definition: BKE_layer.h:213
MINLINE void swap_v3_v3(float a[3], float b[3])
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNUSED(x)
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
bool ED_operator_editlattice(struct bContext *C)
Definition: screen_ops.c:598
_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 u1
_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 v1
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:39
#define NC_GEOM
Definition: WM_types.h:294
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_DATA
Definition: WM_types.h:408
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
eLattice_FlipAxes
@ LATTICE_FLIP_W
@ LATTICE_FLIP_V
@ LATTICE_FLIP_U
static bool make_regular_poll(bContext *C)
static int make_regular_exec(bContext *C, wmOperator *UNUSED(op))
static void lattice_flip_point_value(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
void LATTICE_OT_flip(wmOperatorType *ot)
static void lattice_swap_point_pairs(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
static int lattice_flip_exec(bContext *C, wmOperator *op)
void LATTICE_OT_make_regular(wmOperatorType *ot)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt=1)
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
float vec[4]
struct Lattice * latt
struct EditLatt * editlatt
struct BPoint * def
void * data
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3156
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: wm_operators.c:982