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
20 /** \file
21 * \ingroup bke
22 *
23 * Deform coordinates by a lattice object (used by modifier).
24 */
25
26 #include <math.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "BLI_math.h"
34 #include "BLI_task.h"
35 #include "BLI_utildefines.h"
36
37 #include "DNA_curve_types.h"
38 #include "DNA_lattice_types.h"
39 #include "DNA_mesh_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_object_types.h"
42
43 #include "BKE_curve.h"
44 #include "BKE_displist.h"
45 #include "BKE_editmesh.h"
46 #include "BKE_key.h"
47 #include "BKE_lattice.h"
48 #include "BKE_modifier.h"
49
50 #include "BKE_deform.h"
51
52 #ifdef __SSE2__
53 # include <emmintrin.h>
54 #endif
55
56 /* -------------------------------------------------------------------- */
57 /** \name Lattice Deform API
58 * \{ */
59
60 typedef struct LatticeDeformData {
61 /* Convert from object space to deform space */
62 float latmat[4][4];
63 /* Cached reference to the lattice to use for evaluation. When in edit mode this attribute
64 * is set to the edit mode lattice. */
65 const Lattice *lt;
66 /* Preprocessed lattice points (converted to deform space). */
67 float *latticedata;
68 /* Prefetched DeformWeights of the lattice. */
69 float *lattice_weights;
70 } LatticeDeformData;
71
BKE_lattice_deform_data_create(const Object * oblatt,const Object * ob)72 LatticeDeformData *BKE_lattice_deform_data_create(const Object *oblatt, const Object *ob)
73 {
74 /* we make an array with all differences */
75 Lattice *lt = oblatt->data;
76 BPoint *bp;
77 DispList *dl = oblatt->runtime.curve_cache ?
78 BKE_displist_find(&oblatt->runtime.curve_cache->disp, DL_VERTS) :
79 NULL;
80 const float *co = dl ? dl->verts : NULL;
81 float *fp, imat[4][4];
82 float fu, fv, fw;
83 int u, v, w;
84 float *latticedata;
85 float *lattice_weights = NULL;
86 float latmat[4][4];
87 LatticeDeformData *lattice_deform_data;
88
89 if (lt->editlatt) {
90 lt = lt->editlatt->latt;
91 }
92 bp = lt->def;
93
94 const int32_t num_points = lt->pntsu * lt->pntsv * lt->pntsw;
95 /* We allocate one additional float for SSE2 optimizations. Without this
96 * the SSE2 instructions for the last item would read in unallocated memory. */
97 fp = latticedata = MEM_mallocN(sizeof(float[3]) * num_points + sizeof(float), "latticedata");
98
99 /* for example with a particle system: (ob == NULL) */
100 if (ob == NULL) {
101 /* in deformspace, calc matrix */
102 invert_m4_m4(latmat, oblatt->obmat);
103
104 /* back: put in deform array */
105 invert_m4_m4(imat, latmat);
106 }
107 else {
108 /* in deformspace, calc matrix */
109 invert_m4_m4(imat, oblatt->obmat);
110 mul_m4_m4m4(latmat, imat, ob->obmat);
111
112 /* back: put in deform array */
113 invert_m4_m4(imat, latmat);
114 }
115
116 /* Prefetch latice deform group weights. */
117 int defgrp_index = -1;
118 const MDeformVert *dvert = BKE_lattice_deform_verts_get(oblatt);
119 if (lt->vgroup[0] && dvert) {
120 defgrp_index = BKE_object_defgroup_name_index(oblatt, lt->vgroup);
121
122 if (defgrp_index != -1) {
123 lattice_weights = MEM_malloc_arrayN(sizeof(float), num_points, "lattice_weights");
124 for (int index = 0; index < num_points; index++) {
125 lattice_weights[index] = BKE_defvert_find_weight(dvert + index, defgrp_index);
126 }
127 }
128 }
129
130 for (w = 0, fw = lt->fw; w < lt->pntsw; w++, fw += lt->dw) {
131 for (v = 0, fv = lt->fv; v < lt->pntsv; v++, fv += lt->dv) {
132 for (u = 0, fu = lt->fu; u < lt->pntsu; u++, bp++, co += 3, fp += 3, fu += lt->du) {
133 if (dl) {
134 fp[0] = co[0] - fu;
135 fp[1] = co[1] - fv;
136 fp[2] = co[2] - fw;
137 }
138 else {
139 fp[0] = bp->vec[0] - fu;
140 fp[1] = bp->vec[1] - fv;
141 fp[2] = bp->vec[2] - fw;
142 }
143
144 mul_mat3_m4_v3(imat, fp);
145 }
146 }
147 }
148
149 lattice_deform_data = MEM_mallocN(sizeof(LatticeDeformData), "Lattice Deform Data");
150 lattice_deform_data->latticedata = latticedata;
151 lattice_deform_data->lattice_weights = lattice_weights;
152 lattice_deform_data->lt = lt;
153 copy_m4_m4(lattice_deform_data->latmat, latmat);
154
155 return lattice_deform_data;
156 }
157
BKE_lattice_deform_data_eval_co(LatticeDeformData * lattice_deform_data,float co[3],float weight)158 void BKE_lattice_deform_data_eval_co(LatticeDeformData *lattice_deform_data,
159 float co[3],
160 float weight)
161 {
162 float *latticedata = lattice_deform_data->latticedata;
163 float *lattice_weights = lattice_deform_data->lattice_weights;
164 BLI_assert(latticedata);
165 const Lattice *lt = lattice_deform_data->lt;
166 float u, v, w, tu[4], tv[4], tw[4];
167 float vec[3];
168 int idx_w, idx_v, idx_u;
169 int ui, vi, wi, uu, vv, ww;
170
171 /* vgroup influence */
172 float co_prev[3], weight_blend = 0.0f;
173 copy_v3_v3(co_prev, co);
174 #ifdef __SSE2__
175 __m128 co_vec = _mm_loadu_ps(co_prev);
176 #endif
177
178 /* co is in local coords, treat with latmat */
179 mul_v3_m4v3(vec, lattice_deform_data->latmat, co);
180
181 /* u v w coords */
182
183 if (lt->pntsu > 1) {
184 u = (vec[0] - lt->fu) / lt->du;
185 ui = (int)floor(u);
186 u -= ui;
187 key_curve_position_weights(u, tu, lt->typeu);
188 }
189 else {
190 tu[0] = tu[2] = tu[3] = 0.0;
191 tu[1] = 1.0;
192 ui = 0;
193 }
194
195 if (lt->pntsv > 1) {
196 v = (vec[1] - lt->fv) / lt->dv;
197 vi = (int)floor(v);
198 v -= vi;
199 key_curve_position_weights(v, tv, lt->typev);
200 }
201 else {
202 tv[0] = tv[2] = tv[3] = 0.0;
203 tv[1] = 1.0;
204 vi = 0;
205 }
206
207 if (lt->pntsw > 1) {
208 w = (vec[2] - lt->fw) / lt->dw;
209 wi = (int)floor(w);
210 w -= wi;
211 key_curve_position_weights(w, tw, lt->typew);
212 }
213 else {
214 tw[0] = tw[2] = tw[3] = 0.0;
215 tw[1] = 1.0;
216 wi = 0;
217 }
218
219 const int w_stride = lt->pntsu * lt->pntsv;
220 const int idx_w_max = (lt->pntsw - 1) * lt->pntsu * lt->pntsv;
221 const int v_stride = lt->pntsu;
222 const int idx_v_max = (lt->pntsv - 1) * lt->pntsu;
223 const int idx_u_max = (lt->pntsu - 1);
224
225 for (ww = wi - 1; ww <= wi + 2; ww++) {
226 w = weight * tw[ww - wi + 1];
227 idx_w = CLAMPIS(ww * w_stride, 0, idx_w_max);
228 for (vv = vi - 1; vv <= vi + 2; vv++) {
229 v = w * tv[vv - vi + 1];
230 idx_v = CLAMPIS(vv * v_stride, 0, idx_v_max);
231 for (uu = ui - 1; uu <= ui + 2; uu++) {
232 u = v * tu[uu - ui + 1];
233 idx_u = CLAMPIS(uu, 0, idx_u_max);
234 const int idx = idx_w + idx_v + idx_u;
235 #ifdef __SSE2__
236 {
237 __m128 weight_vec = _mm_set1_ps(u);
238 /* We need to address special case for last item to avoid accessing invalid memory. */
239 __m128 lattice_vec;
240 if (idx * 3 == idx_w_max) {
241 copy_v3_v3((float *)&lattice_vec, &latticedata[idx * 3]);
242 }
243 else {
244 /* When not on last item, we can safely access one extra float, it will be ignored
245 * anyway. */
246 lattice_vec = _mm_loadu_ps(&latticedata[idx * 3]);
247 }
248 co_vec = _mm_add_ps(co_vec, _mm_mul_ps(lattice_vec, weight_vec));
249 }
250 #else
251 madd_v3_v3fl(co, &latticedata[idx * 3], u);
252 #endif
253 if (lattice_weights) {
254 weight_blend += (u * lattice_weights[idx]);
255 }
256 }
257 }
258 }
259 #ifdef __SSE2__
260 {
261 copy_v3_v3(co, (float *)&co_vec);
262 }
263 #endif
264
265 if (lattice_weights) {
266 interp_v3_v3v3(co, co_prev, co, weight_blend);
267 }
268 }
269
BKE_lattice_deform_data_destroy(LatticeDeformData * lattice_deform_data)270 void BKE_lattice_deform_data_destroy(LatticeDeformData *lattice_deform_data)
271 {
272 if (lattice_deform_data->latticedata) {
273 MEM_freeN(lattice_deform_data->latticedata);
274 }
275
276 MEM_freeN(lattice_deform_data);
277 }
278
279 /** \} */
280
281 /* -------------------------------------------------------------------- */
282 /** \name Lattice Deform #BKE_lattice_deform_coords API
283 *
284 * #BKE_lattice_deform_coords and related functions.
285 * \{ */
286
287 typedef struct LatticeDeformUserdata {
288 LatticeDeformData *lattice_deform_data;
289 float (*vert_coords)[3];
290 const MDeformVert *dvert;
291 int defgrp_index;
292 float fac;
293 bool invert_vgroup;
294
295 /** Specific data types. */
296 struct {
297 int cd_dvert_offset;
298 } bmesh;
299 } LatticeDeformUserdata;
300
lattice_deform_vert_with_dvert(const LatticeDeformUserdata * data,const int index,const MDeformVert * dvert)301 static void lattice_deform_vert_with_dvert(const LatticeDeformUserdata *data,
302 const int index,
303 const MDeformVert *dvert)
304 {
305 if (dvert != NULL) {
306 const float weight = data->invert_vgroup ?
307 1.0f - BKE_defvert_find_weight(dvert, data->defgrp_index) :
308 BKE_defvert_find_weight(dvert, data->defgrp_index);
309 if (weight > 0.0f) {
310 BKE_lattice_deform_data_eval_co(
311 data->lattice_deform_data, data->vert_coords[index], weight * data->fac);
312 }
313 }
314 else {
315 BKE_lattice_deform_data_eval_co(
316 data->lattice_deform_data, data->vert_coords[index], data->fac);
317 }
318 }
319
lattice_deform_vert_task(void * __restrict userdata,const int index,const TaskParallelTLS * __restrict UNUSED (tls))320 static void lattice_deform_vert_task(void *__restrict userdata,
321 const int index,
322 const TaskParallelTLS *__restrict UNUSED(tls))
323 {
324 const LatticeDeformUserdata *data = userdata;
325 lattice_deform_vert_with_dvert(data, index, data->dvert ? &data->dvert[index] : NULL);
326 }
327
lattice_vert_task_editmesh(void * __restrict userdata,MempoolIterData * iter)328 static void lattice_vert_task_editmesh(void *__restrict userdata, MempoolIterData *iter)
329 {
330 const LatticeDeformUserdata *data = userdata;
331 BMVert *v = (BMVert *)iter;
332 MDeformVert *dvert = BM_ELEM_CD_GET_VOID_P(v, data->bmesh.cd_dvert_offset);
333 lattice_deform_vert_with_dvert(data, BM_elem_index_get(v), dvert);
334 }
335
lattice_vert_task_editmesh_no_dvert(void * __restrict userdata,MempoolIterData * iter)336 static void lattice_vert_task_editmesh_no_dvert(void *__restrict userdata, MempoolIterData *iter)
337 {
338 const LatticeDeformUserdata *data = userdata;
339 BMVert *v = (BMVert *)iter;
340 lattice_deform_vert_with_dvert(data, BM_elem_index_get(v), NULL);
341 }
342
lattice_deform_coords_impl(const Object * ob_lattice,const Object * ob_target,float (* vert_coords)[3],const int vert_coords_len,const short flag,const char * defgrp_name,const float fac,const Mesh * me_target,BMEditMesh * em_target)343 static void lattice_deform_coords_impl(const Object *ob_lattice,
344 const Object *ob_target,
345 float (*vert_coords)[3],
346 const int vert_coords_len,
347 const short flag,
348 const char *defgrp_name,
349 const float fac,
350 const Mesh *me_target,
351 BMEditMesh *em_target)
352 {
353 LatticeDeformData *lattice_deform_data;
354 const MDeformVert *dvert = NULL;
355 int defgrp_index = -1;
356 int cd_dvert_offset = -1;
357
358 if (ob_lattice->type != OB_LATTICE) {
359 return;
360 }
361
362 lattice_deform_data = BKE_lattice_deform_data_create(ob_lattice, ob_target);
363
364 /* Check whether to use vertex groups (only possible if ob_target is a Mesh or Lattice).
365 * We want either a Mesh/Lattice with no derived data, or derived data with deformverts.
366 */
367 if (defgrp_name && defgrp_name[0] && ob_target && ELEM(ob_target->type, OB_MESH, OB_LATTICE)) {
368 defgrp_index = BKE_object_defgroup_name_index(ob_target, defgrp_name);
369
370 if (defgrp_index != -1) {
371 /* if there's derived data without deformverts, don't use vgroups */
372 if (em_target) {
373 cd_dvert_offset = CustomData_get_offset(&em_target->bm->vdata, CD_MDEFORMVERT);
374 }
375 else if (me_target) {
376 dvert = CustomData_get_layer(&me_target->vdata, CD_MDEFORMVERT);
377 }
378 else if (ob_target->type == OB_LATTICE) {
379 dvert = ((Lattice *)ob_target->data)->dvert;
380 }
381 else {
382 dvert = ((Mesh *)ob_target->data)->dvert;
383 }
384 }
385 }
386
387 LatticeDeformUserdata data = {
388 .lattice_deform_data = lattice_deform_data,
389 .vert_coords = vert_coords,
390 .dvert = dvert,
391 .defgrp_index = defgrp_index,
392 .fac = fac,
393 .invert_vgroup = (flag & MOD_LATTICE_INVERT_VGROUP) != 0,
394 .bmesh =
395 {
396 .cd_dvert_offset = cd_dvert_offset,
397 },
398 };
399
400 if (em_target != NULL) {
401 /* While this could cause an extra loop over mesh data, in most cases this will
402 * have already been properly set. */
403 BM_mesh_elem_index_ensure(em_target->bm, BM_VERT);
404
405 if (cd_dvert_offset != -1) {
406 BLI_task_parallel_mempool(em_target->bm->vpool, &data, lattice_vert_task_editmesh, true);
407 }
408 else {
409 BLI_task_parallel_mempool(
410 em_target->bm->vpool, &data, lattice_vert_task_editmesh_no_dvert, true);
411 }
412 }
413 else {
414 TaskParallelSettings settings;
415 BLI_parallel_range_settings_defaults(&settings);
416 settings.min_iter_per_thread = 32;
417 BLI_task_parallel_range(0, vert_coords_len, &data, lattice_deform_vert_task, &settings);
418 }
419
420 BKE_lattice_deform_data_destroy(lattice_deform_data);
421 }
422
BKE_lattice_deform_coords(const Object * ob_lattice,const Object * ob_target,float (* vert_coords)[3],const int vert_coords_len,const short flag,const char * defgrp_name,float fac)423 void BKE_lattice_deform_coords(const Object *ob_lattice,
424 const Object *ob_target,
425 float (*vert_coords)[3],
426 const int vert_coords_len,
427 const short flag,
428 const char *defgrp_name,
429 float fac)
430 {
431 lattice_deform_coords_impl(
432 ob_lattice, ob_target, vert_coords, vert_coords_len, flag, defgrp_name, fac, NULL, NULL);
433 }
434
BKE_lattice_deform_coords_with_mesh(const Object * ob_lattice,const Object * ob_target,float (* vert_coords)[3],const int vert_coords_len,const short flag,const char * defgrp_name,const float fac,const Mesh * me_target)435 void BKE_lattice_deform_coords_with_mesh(const Object *ob_lattice,
436 const Object *ob_target,
437 float (*vert_coords)[3],
438 const int vert_coords_len,
439 const short flag,
440 const char *defgrp_name,
441 const float fac,
442 const Mesh *me_target)
443 {
444 lattice_deform_coords_impl(ob_lattice,
445 ob_target,
446 vert_coords,
447 vert_coords_len,
448 flag,
449 defgrp_name,
450 fac,
451 me_target,
452 NULL);
453 }
454
BKE_lattice_deform_coords_with_editmesh(const struct Object * ob_lattice,const struct Object * ob_target,float (* vert_coords)[3],const int vert_coords_len,const short flag,const char * defgrp_name,const float fac,struct BMEditMesh * em_target)455 void BKE_lattice_deform_coords_with_editmesh(const struct Object *ob_lattice,
456 const struct Object *ob_target,
457 float (*vert_coords)[3],
458 const int vert_coords_len,
459 const short flag,
460 const char *defgrp_name,
461 const float fac,
462 struct BMEditMesh *em_target)
463 {
464 lattice_deform_coords_impl(ob_lattice,
465 ob_target,
466 vert_coords,
467 vert_coords_len,
468 flag,
469 defgrp_name,
470 fac,
471 NULL,
472 em_target);
473 }
474
475 /** \} */
476