Blender V5.0
editlattice_tools.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "BLI_math_vector.h"
10
11#include "DNA_curve_types.h"
12#include "DNA_lattice_types.h"
13#include "DNA_object_types.h"
14#include "DNA_scene_types.h"
15
16#include "RNA_access.hh"
17#include "RNA_define.hh"
18
19#include "BKE_context.hh"
20#include "BKE_lattice.hh"
21#include "BKE_layer.hh"
22
23#include "DEG_depsgraph.hh"
24
25#include "ED_object.hh"
26#include "ED_screen.hh"
27
28#include "WM_api.hh"
29#include "WM_types.hh"
30
31#include "lattice_intern.hh"
32
33using blender::Vector;
34
35/* -------------------------------------------------------------------- */
38
40{
41 Object *ob;
42
44 return true;
45 }
46
48 return (ob && ob->type == OB_LATTICE);
49}
50
52{
53 const Scene *scene = CTX_data_scene(C);
54 ViewLayer *view_layer = CTX_data_view_layer(C);
55 View3D *v3d = CTX_wm_view3d(C);
56 const bool is_editmode = CTX_data_edit_object(C) != nullptr;
57
58 if (is_editmode) {
60 scene, view_layer, CTX_wm_view3d(C));
61 for (Object *ob : objects) {
62 Lattice *lt = static_cast<Lattice *>(ob->data);
63
64 if (lt->editlatt->latt == nullptr) {
65 continue;
66 }
67
69 continue;
70 }
71
72 BKE_lattice_resize(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, nullptr);
73
76 }
77 }
78 else {
79 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
80 if (ob->type != OB_LATTICE) {
81 continue;
82 }
83
84 Lattice *lt = static_cast<Lattice *>(ob->data);
85 BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, nullptr);
86
89 }
91 }
92 return OPERATOR_FINISHED;
93}
94
96{
97 /* identifiers */
98 ot->name = "Make Regular";
99 ot->description = "Set UVW control points a uniform distance apart";
100 ot->idname = "LATTICE_OT_make_regular";
101
102 /* API callbacks. */
103 ot->exec = make_regular_exec;
104 ot->poll = make_regular_poll;
105
106 /* flags */
108}
109
111
112/* -------------------------------------------------------------------- */
115
116/* flipping options */
122
129 Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
130{
131 BPoint *bp;
132 float diff;
133
134 /* just the point in the middle (unpaired) */
135 bp = &lt->def[BKE_lattice_index_from_uvw(lt, u, v, w)];
136
137 /* flip over axis */
138 diff = mid - bp->vec[axis];
139 bp->vec[axis] = mid + diff;
140}
141
147 Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
148{
149 BPoint *bpA, *bpB;
150
151 int numU = lt->pntsu;
152 int numV = lt->pntsv;
153 int numW = lt->pntsw;
154
155 int u0 = u, u1 = u;
156 int v0 = v, v1 = v;
157 int w0 = w, w1 = w;
158
159 /* get pair index by just overriding the relevant pair-value
160 * - "-1" else buffer overflow
161 */
162 switch (axis) {
163 case LATTICE_FLIP_U:
164 u1 = numU - u - 1;
165 break;
166 case LATTICE_FLIP_V:
167 v1 = numV - v - 1;
168 break;
169 case LATTICE_FLIP_W:
170 w1 = numW - w - 1;
171 break;
172 }
173
174 /* get points to operate on */
175 bpA = &lt->def[BKE_lattice_index_from_uvw(lt, u0, v0, w0)];
176 bpB = &lt->def[BKE_lattice_index_from_uvw(lt, u1, v1, w1)];
177
178 /* Swap all coordinates, so that flipped coordinates belong to
179 * the indices on the correct side of the lattice.
180 *
181 * Coords: (-2 4) |0| (3 4) --> (3 4) |0| (-2 4)
182 * Indices: (0,L) (1,R) --> (0,L) (1,R)
183 */
184 swap_v3_v3(bpA->vec, bpB->vec);
185
186 /* However, we need to mirror the coordinate values on the axis we're dealing with,
187 * otherwise we'd have effectively only rotated the points around. If we don't do this,
188 * we'd just be reimplementing the naive mirroring algorithm, which causes unwanted deforms
189 * such as flipped normals, etc.
190 *
191 * Coords: (3 4) |0| (-2 4) --\
192 * \-> (-3 4) |0| (2 4)
193 * Indices: (0,L) (1,R) --> (0,L) (1,R)
194 */
195 lattice_flip_point_value(lt, u0, v0, w0, mid, axis);
196 lattice_flip_point_value(lt, u1, v1, w1, mid, axis);
197}
198
200{
201 const Scene *scene = CTX_data_scene(C);
202 ViewLayer *view_layer = CTX_data_view_layer(C);
203 bool changed = false;
204 const eLattice_FlipAxes axis = eLattice_FlipAxes(RNA_enum_get(op->ptr, "axis"));
205
207 scene, view_layer, CTX_wm_view3d(C));
208 for (Object *obedit : objects) {
209 Lattice *lt;
210
211 int numU, numV, numW;
212 int totP;
213
214 float mid = 0.0f;
215 short isOdd = 0;
216
217 /* get lattice - we need the "edit lattice" from the lattice... confusing... */
218 lt = (Lattice *)obedit->data;
219 lt = lt->editlatt->latt;
220
222 continue;
223 }
224
225 numU = lt->pntsu;
226 numV = lt->pntsv;
227 numW = lt->pntsw;
228 totP = numU * numV * numW;
229
230 /* First Pass: determine midpoint - used for flipping center verts if there
231 * are odd number of points on axis */
232 switch (axis) {
233 case LATTICE_FLIP_U:
234 isOdd = numU & 1;
235 break;
236 case LATTICE_FLIP_V:
237 isOdd = numV & 1;
238 break;
239 case LATTICE_FLIP_W:
240 isOdd = numW & 1;
241 break;
242
243 default:
244 printf("lattice_flip(): Unknown flipping axis (%d)\n", axis);
245 return OPERATOR_CANCELLED;
246 }
247
248 if (isOdd) {
249 BPoint *bp;
250 float avgInv = 1.0f / float(totP);
251 int i;
252
253 /* midpoint calculation - assuming that u/v/w are axis-aligned */
254 for (i = 0, bp = lt->def; i < totP; i++, bp++) {
255 mid += bp->vec[axis] * avgInv;
256 }
257 }
258
259 /* Second Pass: swap pairs of vertices per axis, assuming they are all sorted */
260 switch (axis) {
261 case LATTICE_FLIP_U: {
262 int u, v, w;
263
264 /* v/w strips - front to back, top to bottom */
265 for (w = 0; w < numW; w++) {
266 for (v = 0; v < numV; v++) {
267 /* swap coordinates of pairs of vertices on u */
268 for (u = 0; u < (numU / 2); u++) {
269 lattice_swap_point_pairs(lt, u, v, w, mid, axis);
270 }
271
272 /* flip u-coordinate of midpoint (i.e. unpaired point on u) */
273 if (isOdd) {
274 u = (numU / 2);
275 lattice_flip_point_value(lt, u, v, w, mid, axis);
276 }
277 }
278 }
279 break;
280 }
281 case LATTICE_FLIP_V: {
282 int u, v, w;
283
284 /* u/w strips - front to back, left to right */
285 for (w = 0; w < numW; w++) {
286 for (u = 0; u < numU; u++) {
287 /* swap coordinates of pairs of vertices on v */
288 for (v = 0; v < (numV / 2); v++) {
289 lattice_swap_point_pairs(lt, u, v, w, mid, axis);
290 }
291
292 /* flip v-coordinate of midpoint (i.e. unpaired point on v) */
293 if (isOdd) {
294 v = (numV / 2);
295 lattice_flip_point_value(lt, u, v, w, mid, axis);
296 }
297 }
298 }
299 break;
300 }
301 case LATTICE_FLIP_W: {
302 int u, v, w;
303
304 for (v = 0; v < numV; v++) {
305 for (u = 0; u < numU; u++) {
306 /* swap coordinates of pairs of vertices on w */
307 for (w = 0; w < (numW / 2); w++) {
308 lattice_swap_point_pairs(lt, u, v, w, mid, axis);
309 }
310
311 /* flip w-coordinate of midpoint (i.e. unpaired point on w) */
312 if (isOdd) {
313 w = (numW / 2);
314 lattice_flip_point_value(lt, u, v, w, mid, axis);
315 }
316 }
317 }
318 break;
319 }
320 default: /* shouldn't happen, but just in case */
321 break;
322 }
323
324 /* updates */
326 WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
327 changed = true;
328 }
329
330 return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
331}
332
334{
335 static const EnumPropertyItem flip_items[] = {
336 {LATTICE_FLIP_U, "U", 0, "U (X) Axis", ""},
337 {LATTICE_FLIP_V, "V", 0, "V (Y) Axis", ""},
338 {LATTICE_FLIP_W, "W", 0, "W (Z) Axis", ""},
339 {0, nullptr, 0, nullptr, nullptr},
340 };
341
342 /* identifiers */
343 ot->name = "Flip (Distortion Free)";
344 ot->description = "Mirror all control points without inverting the lattice deform";
345 ot->idname = "LATTICE_OT_flip";
346
347 /* API callbacks. */
349 ot->invoke = WM_menu_invoke;
350 ot->exec = lattice_flip_exec;
351
352 /* flags */
354
355 /* properties */
356 ot->prop = RNA_def_enum(ot->srna,
357 "axis",
358 flip_items,
360 "Flip Axis",
361 "Coordinates along this axis get flipped");
362}
363
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
int BKE_lattice_index_from_uvw(const Lattice *lt, int u, int v, int w)
Definition lattice.cc:194
void BKE_lattice_resize(Lattice *lt, int u_new, int v_new, int w_new, Object *lt_ob)
Definition lattice.cc:272
#define FOREACH_SELECTED_OBJECT_BEGIN(_view_layer, _v3d, _instance)
Definition BKE_layer.hh:298
#define FOREACH_SELECTED_OBJECT_END
Definition BKE_layer.hh:310
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_edit_mode_unique_data(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
MINLINE void swap_v3_v3(float a[3], float b[3])
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
Object is a sort of wrapper for general info.
@ OB_LATTICE
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
bool ED_operator_editlattice(bContext *C)
#define C
Definition RandGen.cpp:29
#define NC_GEOM
Definition WM_types.hh:393
#define ND_DATA
Definition WM_types.hh:509
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
nullptr float
eLattice_FlipAxes
@ LATTICE_FLIP_W
@ LATTICE_FLIP_V
@ LATTICE_FLIP_U
static bool make_regular_poll(bContext *C)
static wmOperatorStatus make_regular_exec(bContext *C, wmOperator *op)
static wmOperatorStatus lattice_flip_exec(bContext *C, wmOperator *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)
void LATTICE_OT_make_regular(wmOperatorType *ot)
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt)
Definition frames.inl:1166
#define printf(...)
bool shape_key_report_if_locked(const Object *obedit, ReportList *reports)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
float vec[4]
struct Lattice * latt
struct EditLatt * editlatt
struct BPoint * def
struct ReportList * reports
struct PointerRNA * ptr
i
Definition text_draw.cc:230
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4237
wmOperatorStatus WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)