Blender  V3.3
MOD_meshcache.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <stdio.h>
8 
9 #include "BLI_utildefines.h"
10 
11 #include "BLI_math.h"
12 #include "BLI_path_util.h"
13 #include "BLI_string.h"
14 
15 #include "BLT_translation.h"
16 
17 #include "DNA_defaults.h"
18 #include "DNA_mesh_types.h"
19 #include "DNA_meshdata_types.h"
20 #include "DNA_object_types.h"
21 #include "DNA_scene_types.h"
22 #include "DNA_screen_types.h"
23 
24 #include "BKE_context.h"
25 #include "BKE_deform.h"
26 #include "BKE_lib_id.h"
27 #include "BKE_main.h"
28 #include "BKE_mesh.h"
29 #include "BKE_mesh_wrapper.h"
30 #include "BKE_scene.h"
31 #include "BKE_screen.h"
32 
33 #include "UI_interface.h"
34 #include "UI_resources.h"
35 
36 #include "RNA_access.h"
37 #include "RNA_prototypes.h"
38 
39 #include "DEG_depsgraph_query.h"
40 
41 #include "MEM_guardedalloc.h"
42 
43 #include "MOD_meshcache_util.h" /* utility functions */
44 #include "MOD_modifiertypes.h"
45 #include "MOD_ui_common.h"
46 #include "MOD_util.h"
47 
48 static void initData(ModifierData *md)
49 {
51 
52  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(mcmd, modifier));
53 
55 }
56 
57 static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md)
58 {
60  return (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA);
61 }
62 
63 static bool isDisabled(const struct Scene *UNUSED(scene),
64  ModifierData *md,
65  bool UNUSED(useRenderParams))
66 {
68 
69  /* leave it up to the modifier to check the file is valid on calculation */
70  return (mcmd->factor <= 0.0f) || (mcmd->filepath[0] == '\0');
71 }
72 
74  Scene *scene,
75  Object *ob,
76  Mesh *mesh,
77  float (*vertexCos_Real)[3],
78  int verts_num)
79 {
80  const bool use_factor = mcmd->factor < 1.0f;
81  int influence_group_index;
82  MDeformVert *dvert;
83  MOD_get_vgroup(ob, mesh, mcmd->defgrp_name, &dvert, &influence_group_index);
84 
85  float(*vertexCos_Store)[3] = (use_factor || influence_group_index != -1 ||
88  verts_num, sizeof(*vertexCos_Store), __func__) :
89  NULL;
90  float(*vertexCos)[3] = vertexCos_Store ? vertexCos_Store : vertexCos_Real;
91 
92  const float fps = FPS;
93 
94  char filepath[FILE_MAX];
95  const char *err_str = NULL;
96  bool ok;
97 
98  float time;
99 
100  /* -------------------------------------------------------------------- */
101  /* Interpret Time (the reading functions also do some of this ) */
102  if (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA) {
103  const float ctime = BKE_scene_ctime_get(scene);
104 
105  switch (mcmd->time_mode) {
107  time = ctime;
108  break;
109  }
111  time = ctime / fps;
112  break;
113  }
115  default: {
116  time = ctime / fps;
117  break;
118  }
119  }
120 
121  /* apply offset and scale */
122  time = (mcmd->frame_scale * time) - mcmd->frame_start;
123  }
124  else { /* if (mcmd->play_mode == MOD_MESHCACHE_PLAY_EVAL) { */
125  switch (mcmd->time_mode) {
127  time = mcmd->eval_frame;
128  break;
129  }
131  time = mcmd->eval_time;
132  break;
133  }
135  default: {
136  time = mcmd->eval_factor;
137  break;
138  }
139  }
140  }
141 
142  /* -------------------------------------------------------------------- */
143  /* Read the File (or error out when the file is bad) */
144 
145  /* would be nice if we could avoid doing this _every_ frame */
146  BLI_strncpy(filepath, mcmd->filepath, sizeof(filepath));
147  BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL((ID *)ob));
148 
149  switch (mcmd->type) {
152  filepath, vertexCos, verts_num, mcmd->interp, time, fps, mcmd->time_mode, &err_str);
153  break;
156  filepath, vertexCos, verts_num, mcmd->interp, time, fps, mcmd->time_mode, &err_str);
157  break;
158  default:
159  ok = false;
160  break;
161  }
162 
163  /* -------------------------------------------------------------------- */
164  /* tricky shape key integration (slow!) */
166  Mesh *me = ob->data;
167 
168  /* we could support any object type */
169  if (UNLIKELY(ob->type != OB_MESH)) {
170  BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' only valid for Mesh objects");
171  }
172  else if (UNLIKELY(me->totvert != verts_num)) {
173  BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' original mesh vertex mismatch");
174  }
175  else if (UNLIKELY(me->totpoly == 0)) {
176  BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' requires faces");
177  }
178  else {
179  /* the moons align! */
180  int i;
181 
182  float(*vertexCos_Source)[3] = MEM_malloc_arrayN(
183  verts_num, sizeof(*vertexCos_Source), __func__);
184  float(*vertexCos_New)[3] = MEM_malloc_arrayN(verts_num, sizeof(*vertexCos_New), __func__);
185  MVert *mv = me->mvert;
186 
187  for (i = 0; i < verts_num; i++, mv++) {
188  copy_v3_v3(vertexCos_Source[i], mv->co);
189  }
190 
192  me->mpoly,
193  me->totpoly,
194  me->mloop,
195  me->totvert,
196 
197  (const float(*)[3])vertexCos_Source, /* From the original Mesh. */
198  (const float(*)[3])vertexCos_Real, /* the input we've been given (shape keys!) */
199 
200  (const float(*)[3])vertexCos, /* The result of this modifier. */
201  vertexCos_New /* The result of this function. */
202  );
203 
204  /* write the corrected locations back into the result */
205  memcpy(vertexCos, vertexCos_New, sizeof(*vertexCos) * verts_num);
206 
207  MEM_freeN(vertexCos_Source);
208  MEM_freeN(vertexCos_New);
209  }
210  }
211 
212  /* -------------------------------------------------------------------- */
213  /* Apply the transformation matrix (if needed) */
214  if (UNLIKELY(err_str)) {
215  BKE_modifier_set_error(ob, &mcmd->modifier, "%s", err_str);
216  }
217  else if (ok) {
218  bool use_matrix = false;
219  float mat[3][3];
220  unit_m3(mat);
221 
222  if (mat3_from_axis_conversion(mcmd->forward_axis, mcmd->up_axis, 1, 2, mat)) {
223  use_matrix = true;
224  }
225 
226  if (mcmd->flip_axis) {
227  float tmat[3][3];
228  unit_m3(tmat);
229  if (mcmd->flip_axis & (1 << 0)) {
230  tmat[0][0] = -1.0f;
231  }
232  if (mcmd->flip_axis & (1 << 1)) {
233  tmat[1][1] = -1.0f;
234  }
235  if (mcmd->flip_axis & (1 << 2)) {
236  tmat[2][2] = -1.0f;
237  }
238  mul_m3_m3m3(mat, tmat, mat);
239 
240  use_matrix = true;
241  }
242 
243  if (use_matrix) {
244  int i;
245  for (i = 0; i < verts_num; i++) {
246  mul_m3_v3(mat, vertexCos[i]);
247  }
248  }
249  }
250 
251  if (vertexCos_Store) {
252  if (ok) {
253  if (influence_group_index != -1) {
254  const float global_factor = (mcmd->flag & MOD_MESHCACHE_INVERT_VERTEX_GROUP) ?
255  -mcmd->factor :
256  mcmd->factor;
257  const float global_offset = (mcmd->flag & MOD_MESHCACHE_INVERT_VERTEX_GROUP) ?
258  mcmd->factor :
259  0.0f;
260  if (mesh->dvert != NULL) {
261  for (int i = 0; i < verts_num; i++) {
262  /* For each vertex, compute its blending factor between the mesh cache (for `fac = 0`)
263  * and the former position of the vertex (for `fac = 1`). */
264  const MDeformVert *currentIndexDVert = dvert + i;
265  const float local_vertex_fac = global_offset +
266  BKE_defvert_find_weight(currentIndexDVert,
267  influence_group_index) *
268  global_factor;
270  vertexCos_Real[i], vertexCos_Real[i], vertexCos_Store[i], local_vertex_fac);
271  }
272  }
273  }
274  else if (use_factor) {
275  /* Influence_group_index is -1. */
276  interp_vn_vn(*vertexCos_Real, *vertexCos_Store, mcmd->factor, verts_num * 3);
277  }
278  else {
279  memcpy(vertexCos_Real, vertexCos_Store, sizeof(*vertexCos_Store) * verts_num);
280  }
281  }
282 
283  MEM_freeN(vertexCos_Store);
284  }
285 }
286 
287 static void deformVerts(ModifierData *md,
288  const ModifierEvalContext *ctx,
289  Mesh *mesh,
290  float (*vertexCos)[3],
291  int verts_num)
292 {
295 
296  Mesh *mesh_src = NULL;
297 
298  if (ctx->object->type == OB_MESH && mcmd->defgrp_name[0] != '\0') {
299  /* `mesh_src` is only needed for vertex groups. */
300  mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, verts_num, false, false);
301  }
302  meshcache_do(mcmd, scene, ctx->object, mesh_src, vertexCos, verts_num);
303 
304  if (!ELEM(mesh_src, NULL, mesh)) {
305  BKE_id_free(NULL, mesh_src);
306  }
307 }
308 
309 static void deformVertsEM(ModifierData *md,
310  const ModifierEvalContext *ctx,
311  struct BMEditMesh *editData,
312  Mesh *mesh,
313  float (*vertexCos)[3],
314  int verts_num)
315 {
318 
319  Mesh *mesh_src = NULL;
320 
321  if (ctx->object->type == OB_MESH && mcmd->defgrp_name[0] != '\0') {
322  /* `mesh_src` is only needed for vertex groups. */
323  mesh_src = MOD_deform_mesh_eval_get(
324  ctx->object, editData, mesh, NULL, verts_num, false, false);
325  }
326  if (mesh_src != NULL) {
328  }
329 
330  meshcache_do(mcmd, scene, ctx->object, mesh_src, vertexCos, verts_num);
331 
332  if (!ELEM(mesh_src, NULL, mesh)) {
333  BKE_id_free(NULL, mesh_src);
334  }
335 }
336 
337 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
338 {
339  uiLayout *layout = panel->layout;
340 
341  PointerRNA ob_ptr;
343 
344  uiLayoutSetPropSep(layout, true);
345 
346  uiItemR(layout, ptr, "cache_format", 0, NULL, ICON_NONE);
347  uiItemR(layout, ptr, "filepath", 0, NULL, ICON_NONE);
348 
349  uiItemR(layout, ptr, "factor", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
350  uiItemR(layout, ptr, "deform_mode", 0, NULL, ICON_NONE);
351  uiItemR(layout, ptr, "interpolation", 0, NULL, ICON_NONE);
352  modifier_vgroup_ui(layout, ptr, &ob_ptr, "vertex_group", "invert_vertex_group", NULL);
353 
354  modifier_panel_end(layout, ptr);
355 }
356 
357 static void time_remapping_panel_draw(const bContext *UNUSED(C), Panel *panel)
358 {
359  uiLayout *layout = panel->layout;
360 
362 
363  uiItemR(layout, ptr, "time_mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
364 
365  uiLayoutSetPropSep(layout, true);
366 
367  uiItemR(layout, ptr, "play_mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
368 
369  if (RNA_enum_get(ptr, "play_mode") == MOD_MESHCACHE_PLAY_CFEA) {
370  uiItemR(layout, ptr, "frame_start", 0, NULL, ICON_NONE);
371  uiItemR(layout, ptr, "frame_scale", 0, NULL, ICON_NONE);
372  }
373  else { /* play_mode == MOD_MESHCACHE_PLAY_EVAL */
374  int time_mode = RNA_enum_get(ptr, "time_mode");
375  if (time_mode == MOD_MESHCACHE_TIME_FRAME) {
376  uiItemR(layout, ptr, "eval_frame", 0, NULL, ICON_NONE);
377  }
378  else if (time_mode == MOD_MESHCACHE_TIME_SECONDS) {
379  uiItemR(layout, ptr, "eval_time", 0, NULL, ICON_NONE);
380  }
381  else { /* time_mode == MOD_MESHCACHE_TIME_FACTOR */
382  uiItemR(layout, ptr, "eval_factor", 0, NULL, ICON_NONE);
383  }
384  }
385 }
386 
387 static void axis_mapping_panel_draw(const bContext *UNUSED(C), Panel *panel)
388 {
389  uiLayout *col;
390  uiLayout *layout = panel->layout;
391 
393 
394  uiLayoutSetPropSep(layout, true);
395 
396  col = uiLayoutColumn(layout, true);
397  uiLayoutSetRedAlert(col, RNA_enum_get(ptr, "forward_axis") == RNA_enum_get(ptr, "up_axis"));
398  uiItemR(col, ptr, "forward_axis", 0, NULL, ICON_NONE);
399  uiItemR(col, ptr, "up_axis", 0, NULL, ICON_NONE);
400 
401  uiItemR(layout, ptr, "flip_axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
402 }
403 
404 static void panelRegister(ARegionType *region_type)
405 {
406  PanelType *panel_type = modifier_panel_register(
407  region_type, eModifierType_MeshCache, panel_draw);
408  modifier_subpanel_register(region_type,
409  "time_remapping",
410  "Time Remapping",
411  NULL,
413  panel_type);
415  region_type, "axis_mapping", "Axis Mapping", NULL, axis_mapping_panel_draw, panel_type);
416 }
417 
419  /* name */ N_("MeshCache"),
420  /* structName */ "MeshCacheModifierData",
421  /* structSize */ sizeof(MeshCacheModifierData),
422  /* srna */ &RNA_MeshCacheModifier,
423  /* type */ eModifierTypeType_OnlyDeform,
426  /* icon */ ICON_MOD_MESHDEFORM, /* TODO: Use correct icon. */
427 
428  /* copyData */ BKE_modifier_copydata_generic,
429 
430  /* deformVerts */ deformVerts,
431  /* deformMatrices */ NULL,
432  /* deformVertsEM */ deformVertsEM,
433  /* deformMatricesEM */ NULL,
434  /* modifyMesh */ NULL,
435  /* modifyGeometrySet */ NULL,
436 
437  /* initData */ initData,
438  /* requiredDataMask */ NULL,
439  /* freeData */ NULL,
440  /* isDisabled */ isDisabled,
441  /* updateDepsgraph */ NULL,
442  /* dependsOnTime */ dependsOnTime,
443  /* dependsOnNormals */ NULL,
444  /* foreachIDLink */ NULL,
445  /* foreachTexLink */ NULL,
446  /* freeRuntimeData */ NULL,
447  /* panelRegister */ panelRegister,
448  /* blendWrite */ NULL,
449  /* blendRead */ NULL,
450 };
typedef float(TangentPoint)[2]
support for deformation groups and hooks.
float BKE_defvert_find_weight(const struct MDeformVert *dvert, int defgroup)
Definition: deform.c:704
void BKE_id_free(struct Main *bmain, void *idv)
void BKE_mesh_calc_relative_deform(const struct MPoly *mpoly, int totpoly, const struct MLoop *mloop, int totvert, const float(*vert_cos_src)[3], const float(*vert_cos_dst)[3], const float(*vert_cos_org)[3], float(*vert_cos_new)[3])
void BKE_mesh_wrapper_ensure_mdata(struct Mesh *me)
Definition: mesh_wrapper.cc:94
@ eModifierTypeFlag_AcceptsCVs
Definition: BKE_modifier.h:67
@ eModifierTypeFlag_SupportsEditmode
Definition: BKE_modifier.h:69
@ eModifierTypeFlag_AcceptsVertexCosOnly
Definition: BKE_modifier.h:100
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, int flag)
@ eModifierTypeType_OnlyDeform
Definition: BKE_modifier.h:44
void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
float BKE_scene_ctime_get(const struct Scene *scene)
#define BLI_assert(a)
Definition: BLI_assert.h:46
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:926
void unit_m3(float m[3][3])
Definition: math_matrix.c:40
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:388
bool mat3_from_axis_conversion(int src_forward, int src_up, int dst_forward, int dst_up, float r_mat[3][3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition: math_vector.c:29
void interp_vn_vn(float *array_tar, const float *array_src, float t, int size)
Definition: math_vector.c:1210
#define FILE_MAX
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:897
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#define UNUSED(x)
#define UNLIKELY(x)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
Definition: DNA_ID.h:561
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
struct MeshCacheModifierData MeshCacheModifierData
@ MOD_MESHCACHE_TYPE_PC2
@ MOD_MESHCACHE_TYPE_MDD
@ MOD_MESHCACHE_DEFORM_INTEGRATE
@ eModifierType_MeshCache
@ MOD_MESHCACHE_INVERT_VERTEX_GROUP
@ MOD_MESHCACHE_TIME_FRAME
@ MOD_MESHCACHE_TIME_FACTOR
@ MOD_MESHCACHE_TIME_SECONDS
@ MOD_MESHCACHE_PLAY_CFEA
Object is a sort of wrapper for general info.
@ OB_MESH
#define FPS
Read Guarded memory(de)allocation.
static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float(*vertexCos)[3], int verts_num)
static void time_remapping_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void deformVertsEM(ModifierData *md, const ModifierEvalContext *ctx, struct BMEditMesh *editData, Mesh *mesh, float(*vertexCos)[3], int verts_num)
static void meshcache_do(MeshCacheModifierData *mcmd, Scene *scene, Object *ob, Mesh *mesh, float(*vertexCos_Real)[3], int verts_num)
Definition: MOD_meshcache.c:73
ModifierTypeInfo modifierType_MeshCache
static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md)
Definition: MOD_meshcache.c:57
static bool isDisabled(const struct Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams))
Definition: MOD_meshcache.c:63
static void axis_mapping_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
static void initData(ModifierData *md)
Definition: MOD_meshcache.c:48
static void panelRegister(ARegionType *region_type)
bool MOD_meshcache_read_mdd_times(const char *filepath, float(*vertexCos)[3], const int verts_tot, const char interp, const float time, const float fps, const char time_mode, const char **err_str)
bool MOD_meshcache_read_pc2_times(const char *filepath, float(*vertexCos)[3], const int verts_tot, const char interp, const float time, const float fps, const char time_mode, const char **err_str)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
Definition: MOD_ui_common.c:91
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
void modifier_vgroup_ui(uiLayout *layout, PointerRNA *ptr, PointerRNA *ob_ptr, const char *vgroup_prop, const char *invert_vgroup_prop, const char *text)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
Mesh * MOD_deform_mesh_eval_get(Object *ob, struct BMEditMesh *em, Mesh *mesh, const float(*vertexCos)[3], const int verts_num, const bool use_normals, const bool use_orco)
Definition: MOD_util.c:167
void MOD_get_vgroup(Object *ob, struct Mesh *mesh, const char *name, MDeformVert **dvert, int *defgrp_index)
Definition: MOD_util.c:235
#define C
Definition: RandGen.cpp:25
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetRedAlert(uiLayout *layout, bool redalert)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
@ UI_ITEM_R_EXPAND
@ UI_ITEM_R_SLIDER
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
double time
Scene scene
uint col
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
Definition: DNA_ID.h:368
struct MVert * mvert
struct MDeformVert * dvert
int totvert
struct MLoop * mloop
int totpoly
struct MPoly * mpoly
struct Depsgraph * depsgraph
Definition: BKE_modifier.h:140
struct Object * object
Definition: BKE_modifier.h:141
struct uiLayout * layout
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480