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