Blender  V2.93
MOD_meshcache.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 
21 #include <stdio.h>
22 
23 #include "BLI_utildefines.h"
24 
25 #include "BLI_math.h"
26 #include "BLI_path_util.h"
27 #include "BLI_string.h"
28 
29 #include "BLT_translation.h"
30 
31 #include "DNA_defaults.h"
32 #include "DNA_mesh_types.h"
33 #include "DNA_meshdata_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_scene_types.h"
36 #include "DNA_screen_types.h"
37 
38 #include "BKE_context.h"
39 #include "BKE_main.h"
40 #include "BKE_mesh.h"
41 #include "BKE_scene.h"
42 #include "BKE_screen.h"
43 
44 #include "UI_interface.h"
45 #include "UI_resources.h"
46 
47 #include "RNA_access.h"
48 
49 #include "DEG_depsgraph_query.h"
50 
51 #include "MEM_guardedalloc.h"
52 
53 #include "MOD_meshcache_util.h" /* utility functions */
54 #include "MOD_modifiertypes.h"
55 #include "MOD_ui_common.h"
56 
57 static void initData(ModifierData *md)
58 {
60 
61  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(mcmd, modifier));
62 
64 }
65 
66 static bool dependsOnTime(ModifierData *md)
67 {
69  return (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA);
70 }
71 
72 static bool isDisabled(const struct Scene *UNUSED(scene),
73  ModifierData *md,
74  bool UNUSED(useRenderParams))
75 {
77 
78  /* leave it up to the modifier to check the file is valid on calculation */
79  return (mcmd->factor <= 0.0f) || (mcmd->filepath[0] == '\0');
80 }
81 
83  Scene *scene,
84  Object *ob,
85  float (*vertexCos_Real)[3],
86  int numVerts)
87 {
88  const bool use_factor = mcmd->factor < 1.0f;
89  float(*vertexCos_Store)[3] = (use_factor ||
92  numVerts, sizeof(*vertexCos_Store), __func__) :
93  NULL;
94  float(*vertexCos)[3] = vertexCos_Store ? vertexCos_Store : vertexCos_Real;
95 
96  const float fps = FPS;
97 
98  char filepath[FILE_MAX];
99  const char *err_str = NULL;
100  bool ok;
101 
102  float time;
103 
104  /* -------------------------------------------------------------------- */
105  /* Interpret Time (the reading functions also do some of this ) */
106  if (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA) {
107  const float cfra = BKE_scene_frame_get(scene);
108 
109  switch (mcmd->time_mode) {
111  time = cfra;
112  break;
113  }
115  time = cfra / fps;
116  break;
117  }
119  default: {
120  time = cfra / fps;
121  break;
122  }
123  }
124 
125  /* apply offset and scale */
126  time = (mcmd->frame_scale * time) - mcmd->frame_start;
127  }
128  else { /* if (mcmd->play_mode == MOD_MESHCACHE_PLAY_EVAL) { */
129  switch (mcmd->time_mode) {
131  time = mcmd->eval_frame;
132  break;
133  }
135  time = mcmd->eval_time;
136  break;
137  }
139  default: {
140  time = mcmd->eval_factor;
141  break;
142  }
143  }
144  }
145 
146  /* -------------------------------------------------------------------- */
147  /* Read the File (or error out when the file is bad) */
148 
149  /* would be nice if we could avoid doing this _every_ frame */
150  BLI_strncpy(filepath, mcmd->filepath, sizeof(filepath));
151  BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL((ID *)ob));
152 
153  switch (mcmd->type) {
156  filepath, vertexCos, numVerts, mcmd->interp, time, fps, mcmd->time_mode, &err_str);
157  break;
160  filepath, vertexCos, numVerts, mcmd->interp, time, fps, mcmd->time_mode, &err_str);
161  break;
162  default:
163  ok = false;
164  break;
165  }
166 
167  /* -------------------------------------------------------------------- */
168  /* tricky shape key integration (slow!) */
170  Mesh *me = ob->data;
171 
172  /* we could support any object type */
173  if (UNLIKELY(ob->type != OB_MESH)) {
174  BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' only valid for Mesh objects");
175  }
176  else if (UNLIKELY(me->totvert != numVerts)) {
177  BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' original mesh vertex mismatch");
178  }
179  else if (UNLIKELY(me->totpoly == 0)) {
180  BKE_modifier_set_error(ob, &mcmd->modifier, "'Integrate' requires faces");
181  }
182  else {
183  /* the moons align! */
184  int i;
185 
186  float(*vertexCos_Source)[3] = MEM_malloc_arrayN(
187  numVerts, sizeof(*vertexCos_Source), __func__);
188  float(*vertexCos_New)[3] = MEM_malloc_arrayN(numVerts, sizeof(*vertexCos_New), __func__);
189  MVert *mv = me->mvert;
190 
191  for (i = 0; i < numVerts; i++, mv++) {
192  copy_v3_v3(vertexCos_Source[i], mv->co);
193  }
194 
196  me->mpoly,
197  me->totpoly,
198  me->mloop,
199  me->totvert,
200 
201  (const float(*)[3])vertexCos_Source, /* from the original Mesh*/
202  (const float(*)[3])vertexCos_Real, /* the input we've been given (shape keys!) */
203 
204  (const float(*)[3])vertexCos, /* the result of this modifier */
205  vertexCos_New /* the result of this function */
206  );
207 
208  /* write the corrected locations back into the result */
209  memcpy(vertexCos, vertexCos_New, sizeof(*vertexCos) * numVerts);
210 
211  MEM_freeN(vertexCos_Source);
212  MEM_freeN(vertexCos_New);
213  }
214  }
215 
216  /* -------------------------------------------------------------------- */
217  /* Apply the transformation matrix (if needed) */
218  if (UNLIKELY(err_str)) {
219  BKE_modifier_set_error(ob, &mcmd->modifier, "%s", err_str);
220  }
221  else if (ok) {
222  bool use_matrix = false;
223  float mat[3][3];
224  unit_m3(mat);
225 
226  if (mat3_from_axis_conversion(mcmd->forward_axis, mcmd->up_axis, 1, 2, mat)) {
227  use_matrix = true;
228  }
229 
230  if (mcmd->flip_axis) {
231  float tmat[3][3];
232  unit_m3(tmat);
233  if (mcmd->flip_axis & (1 << 0)) {
234  tmat[0][0] = -1.0f;
235  }
236  if (mcmd->flip_axis & (1 << 1)) {
237  tmat[1][1] = -1.0f;
238  }
239  if (mcmd->flip_axis & (1 << 2)) {
240  tmat[2][2] = -1.0f;
241  }
242  mul_m3_m3m3(mat, tmat, mat);
243 
244  use_matrix = true;
245  }
246 
247  if (use_matrix) {
248  int i;
249  for (i = 0; i < numVerts; i++) {
250  mul_m3_v3(mat, vertexCos[i]);
251  }
252  }
253  }
254 
255  if (vertexCos_Store) {
256  if (ok) {
257  if (use_factor) {
258  interp_vn_vn(*vertexCos_Real, *vertexCos_Store, mcmd->factor, numVerts * 3);
259  }
260  else {
261  memcpy(vertexCos_Real, vertexCos_Store, sizeof(*vertexCos_Store) * numVerts);
262  }
263  }
264 
265  MEM_freeN(vertexCos_Store);
266  }
267 }
268 
269 static void deformVerts(ModifierData *md,
270  const ModifierEvalContext *ctx,
271  Mesh *UNUSED(mesh),
272  float (*vertexCos)[3],
273  int numVerts)
274 {
277 
278  meshcache_do(mcmd, scene, ctx->object, vertexCos, numVerts);
279 }
280 
281 static void deformVertsEM(ModifierData *md,
282  const ModifierEvalContext *ctx,
283  struct BMEditMesh *UNUSED(editData),
284  Mesh *UNUSED(mesh),
285  float (*vertexCos)[3],
286  int numVerts)
287 {
290 
291  meshcache_do(mcmd, scene, ctx->object, vertexCos, numVerts);
292 }
293 
294 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
295 {
296  uiLayout *layout = panel->layout;
297 
299 
300  uiLayoutSetPropSep(layout, true);
301 
302  uiItemR(layout, ptr, "cache_format", 0, NULL, ICON_NONE);
303  uiItemR(layout, ptr, "filepath", 0, NULL, ICON_NONE);
304 
305  uiItemR(layout, ptr, "factor", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
306  uiItemR(layout, ptr, "deform_mode", 0, NULL, ICON_NONE);
307  uiItemR(layout, ptr, "interpolation", 0, NULL, ICON_NONE);
308 
309  modifier_panel_end(layout, ptr);
310 }
311 
312 static void time_remapping_panel_draw(const bContext *UNUSED(C), Panel *panel)
313 {
314  uiLayout *layout = panel->layout;
315 
317 
318  uiItemR(layout, ptr, "time_mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
319 
320  uiLayoutSetPropSep(layout, true);
321 
322  uiItemR(layout, ptr, "play_mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
323 
324  if (RNA_enum_get(ptr, "play_mode") == MOD_MESHCACHE_PLAY_CFEA) {
325  uiItemR(layout, ptr, "frame_start", 0, NULL, ICON_NONE);
326  uiItemR(layout, ptr, "frame_scale", 0, NULL, ICON_NONE);
327  }
328  else { /* play_mode == MOD_MESHCACHE_PLAY_EVAL */
329  int time_mode = RNA_enum_get(ptr, "time_mode");
330  if (time_mode == MOD_MESHCACHE_TIME_FRAME) {
331  uiItemR(layout, ptr, "eval_frame", 0, NULL, ICON_NONE);
332  }
333  else if (time_mode == MOD_MESHCACHE_TIME_SECONDS) {
334  uiItemR(layout, ptr, "eval_time", 0, NULL, ICON_NONE);
335  }
336  else { /* time_mode == MOD_MESHCACHE_TIME_FACTOR */
337  uiItemR(layout, ptr, "eval_factor", 0, NULL, ICON_NONE);
338  }
339  }
340 }
341 
342 static void axis_mapping_panel_draw(const bContext *UNUSED(C), Panel *panel)
343 {
344  uiLayout *col;
345  uiLayout *layout = panel->layout;
346 
348 
349  uiLayoutSetPropSep(layout, true);
350 
351  col = uiLayoutColumn(layout, true);
352  uiLayoutSetRedAlert(col, RNA_enum_get(ptr, "forward_axis") == RNA_enum_get(ptr, "up_axis"));
353  uiItemR(col, ptr, "forward_axis", 0, NULL, ICON_NONE);
354  uiItemR(col, ptr, "up_axis", 0, NULL, ICON_NONE);
355 
356  uiItemR(layout, ptr, "flip_axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
357 }
358 
359 static void panelRegister(ARegionType *region_type)
360 {
361  PanelType *panel_type = modifier_panel_register(
362  region_type, eModifierType_MeshCache, panel_draw);
363  modifier_subpanel_register(region_type,
364  "time_remapping",
365  "Time Remapping",
366  NULL,
368  panel_type);
370  region_type, "axis_mapping", "Axis Mapping", NULL, axis_mapping_panel_draw, panel_type);
371 }
372 
374  /* name */ "MeshCache",
375  /* structName */ "MeshCacheModifierData",
376  /* structSize */ sizeof(MeshCacheModifierData),
377  /* srna */ &RNA_MeshCacheModifier,
378  /* type */ eModifierTypeType_OnlyDeform,
381  /* icon */ ICON_MOD_MESHDEFORM, /* TODO: Use correct icon. */
382 
383  /* copyData */ BKE_modifier_copydata_generic,
384 
385  /* deformVerts */ deformVerts,
386  /* deformMatrices */ NULL,
387  /* deformVertsEM */ deformVertsEM,
388  /* deformMatricesEM */ NULL,
389  /* modifyMesh */ NULL,
390  /* modifyHair */ NULL,
391  /* modifyGeometrySet */ NULL,
392  /* modifyVolume */ NULL,
393 
394  /* initData */ initData,
395  /* requiredDataMask */ NULL,
396  /* freeData */ NULL,
397  /* isDisabled */ isDisabled,
398  /* updateDepsgraph */ NULL,
399  /* dependsOnTime */ dependsOnTime,
400  /* dependsOnNormals */ NULL,
401  /* foreachIDLink */ NULL,
402  /* foreachTexLink */ NULL,
403  /* freeRuntimeData */ NULL,
404  /* panelRegister */ panelRegister,
405  /* blendWrite */ NULL,
406  /* blendRead */ NULL,
407 };
typedef float(TangentPoint)[2]
void BKE_mesh_calc_relative_deform(const struct MPoly *mpoly, const int totpoly, const struct MLoop *mloop, const 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])
@ eModifierTypeFlag_AcceptsCVs
Definition: BKE_modifier.h:81
@ eModifierTypeFlag_SupportsEditmode
Definition: BKE_modifier.h:83
@ eModifierTypeFlag_AcceptsVertexCosOnly
Definition: BKE_modifier.h:114
void BKE_modifier_copydata_generic(const struct ModifierData *md, struct ModifierData *md_dst, const int flag)
@ eModifierTypeType_OnlyDeform
Definition: BKE_modifier.h:58
void BKE_modifier_set_error(const struct Object *ob, struct ModifierData *md, const char *format,...) ATTR_PRINTF_FORMAT(3
float BKE_scene_frame_get(const struct Scene *scene)
#define BLI_assert(a)
Definition: BLI_assert.h:58
void mul_m3_v3(const float M[3][3], float r[3])
Definition: math_matrix.c:930
void unit_m3(float m[3][3])
Definition: math_matrix.c:58
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:391
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_vn_vn(float *array_tar, const float *array_src, const float t, const int size)
Definition: math_vector.c:1361
#define FILE_MAX
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:1016
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
#define UNUSED(x)
#define UNLIKELY(x)
#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:421
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:44
struct MeshCacheModifierData MeshCacheModifierData
@ MOD_MESHCACHE_TYPE_PC2
@ MOD_MESHCACHE_TYPE_MDD
@ MOD_MESHCACHE_DEFORM_INTEGRATE
@ eModifierType_MeshCache
@ MOD_MESHCACHE_PLAY_CFEA
@ MOD_MESHCACHE_TIME_FRAME
@ MOD_MESHCACHE_TIME_FACTOR
@ MOD_MESHCACHE_TIME_SECONDS
Object is a sort of wrapper for general info.
@ OB_MESH
#define FPS
Read Guarded memory(de)allocation.
static void time_remapping_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void meshcache_do(MeshCacheModifierData *mcmd, Scene *scene, Object *ob, float(*vertexCos_Real)[3], int numVerts)
Definition: MOD_meshcache.c:82
ModifierTypeInfo modifierType_MeshCache
static bool isDisabled(const struct Scene *UNUSED(scene), ModifierData *md, bool UNUSED(useRenderParams))
Definition: MOD_meshcache.c:72
static void axis_mapping_panel_draw(const bContext *UNUSED(C), Panel *panel)
static void deformVertsEM(ModifierData *md, const ModifierEvalContext *ctx, struct BMEditMesh *UNUSED(editData), Mesh *UNUSED(mesh), float(*vertexCos)[3], int numVerts)
static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *UNUSED(mesh), float(*vertexCos)[3], int numVerts)
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
static void initData(ModifierData *md)
Definition: MOD_meshcache.c:57
static void panelRegister(ARegionType *region_type)
static bool dependsOnTime(ModifierData *md)
Definition: MOD_meshcache.c:66
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)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PanelType * modifier_subpanel_register(ARegionType *region_type, const char *name, const char *label, PanelDrawFn draw_header, PanelDrawFn draw, PanelType *parent)
StructRNA RNA_MeshCacheModifier
#define C
Definition: RandGen.cpp:39
@ UI_ITEM_R_EXPAND
@ UI_ITEM_R_SLIDER
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetRedAlert(uiLayout *layout, bool redalert)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
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:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
Definition: DNA_ID.h:273
struct MVert * mvert
int totvert
struct MLoop * mloop
int totpoly
struct MPoly * mpoly
struct Depsgraph * depsgraph
Definition: BKE_modifier.h:153
struct Object * object
Definition: BKE_modifier.h:154
struct uiLayout * layout
PointerRNA * ptr
Definition: wm_files.c:3157