Blender  V3.3
MOD_collision.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2005 Blender Foundation. All rights reserved. */
3 
8 #include "BLI_utildefines.h"
9 
10 #include "BLI_kdopbvh.h"
11 #include "BLI_math.h"
12 
13 #include "BLT_translation.h"
14 
15 #include "DNA_defaults.h"
16 #include "DNA_mesh_types.h"
17 #include "DNA_meshdata_types.h"
18 #include "DNA_object_force_types.h"
19 #include "DNA_object_types.h"
20 #include "DNA_screen_types.h"
21 
22 #include "MEM_guardedalloc.h"
23 
24 #include "BKE_collision.h"
25 #include "BKE_context.h"
26 #include "BKE_global.h"
27 #include "BKE_lib_id.h"
28 #include "BKE_mesh.h"
29 #include "BKE_mesh_runtime.h"
30 #include "BKE_modifier.h"
31 #include "BKE_pointcache.h"
32 #include "BKE_scene.h"
33 #include "BKE_screen.h"
34 
35 #include "UI_interface.h"
36 #include "UI_resources.h"
37 
38 #include "RNA_access.h"
39 #include "RNA_prototypes.h"
40 
41 #include "MOD_modifiertypes.h"
42 #include "MOD_ui_common.h"
43 #include "MOD_util.h"
44 
45 #include "BLO_read_write.h"
46 
47 #include "DEG_depsgraph_query.h"
48 
49 static void initData(ModifierData *md)
50 {
52 
53  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(collmd, modifier));
54 
56 }
57 
58 static void freeData(ModifierData *md)
59 {
61 
62  if (collmd) { /* Seriously? */
63  if (collmd->bvhtree) {
64  BLI_bvhtree_free(collmd->bvhtree);
65  collmd->bvhtree = NULL;
66  }
67 
68  MEM_SAFE_FREE(collmd->x);
69  MEM_SAFE_FREE(collmd->xnew);
70  MEM_SAFE_FREE(collmd->current_x);
71  MEM_SAFE_FREE(collmd->current_xnew);
72  MEM_SAFE_FREE(collmd->current_v);
73 
74  MEM_SAFE_FREE(collmd->tri);
75 
76  collmd->time_x = collmd->time_xnew = -1000;
77  collmd->mvert_num = 0;
78  collmd->tri_num = 0;
79  collmd->is_static = false;
80  }
81 }
82 
83 static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md))
84 {
85  return true;
86 }
87 
88 static void deformVerts(ModifierData *md,
89  const ModifierEvalContext *ctx,
90  Mesh *mesh,
91  float (*vertexCos)[3],
92  int verts_num)
93 {
95  Mesh *mesh_src;
96  MVert *tempVert = NULL;
97  Object *ob = ctx->object;
98 
99  /* If collision is disabled, free the stale data and exit. */
100  if (!ob->pd || !ob->pd->deflect) {
101  if (!ob->pd) {
102  printf("CollisionModifier: collision settings are missing!\n");
103  }
104 
105  freeData(md);
106  return;
107  }
108 
109  if (mesh == NULL) {
110  mesh_src = MOD_deform_mesh_eval_get(ob, NULL, NULL, NULL, verts_num, false, false);
111  }
112  else {
113  /* Not possible to use get_mesh() in this case as we'll modify its vertices
114  * and get_mesh() would return 'mesh' directly. */
115  mesh_src = (Mesh *)BKE_id_copy_ex(NULL, (ID *)mesh, NULL, LIB_ID_COPY_LOCALIZE);
116  }
117 
118  if (mesh_src) {
119  float current_time = 0;
120  uint mvert_num = 0;
121 
122  BKE_mesh_vert_coords_apply(mesh_src, vertexCos);
123 
124  current_time = DEG_get_ctime(ctx->depsgraph);
125 
126  if (G.debug & G_DEBUG_SIMDATA) {
127  printf("current_time %f, collmd->time_xnew %f\n", current_time, collmd->time_xnew);
128  }
129 
130  mvert_num = mesh_src->totvert;
131 
132  if (current_time < collmd->time_xnew) {
133  freeData((ModifierData *)collmd);
134  }
135  else if (current_time == collmd->time_xnew) {
136  if (mvert_num != collmd->mvert_num) {
137  freeData((ModifierData *)collmd);
138  }
139  }
140 
141  /* check if mesh has changed */
142  if (collmd->x && (mvert_num != collmd->mvert_num)) {
143  freeData((ModifierData *)collmd);
144  }
145 
146  if (collmd->time_xnew == -1000) { /* first time */
147 
148  collmd->x = MEM_dupallocN(mesh_src->mvert); /* frame start position */
149 
150  for (uint i = 0; i < mvert_num; i++) {
151  /* we save global positions */
152  mul_m4_v3(ob->obmat, collmd->x[i].co);
153  }
154 
155  collmd->xnew = MEM_dupallocN(collmd->x); /* Frame end position. */
156  collmd->current_x = MEM_dupallocN(collmd->x); /* Inter-frame. */
157  collmd->current_xnew = MEM_dupallocN(collmd->x); /* Inter-frame. */
158  collmd->current_v = MEM_dupallocN(collmd->x); /* Inter-frame. */
159 
160  collmd->mvert_num = mvert_num;
161 
162  {
163  const MLoop *mloop = mesh_src->mloop;
164  const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh_src);
165  collmd->tri_num = BKE_mesh_runtime_looptri_len(mesh_src);
166  MVertTri *tri = MEM_mallocN(sizeof(*tri) * collmd->tri_num, __func__);
167  BKE_mesh_runtime_verttri_from_looptri(tri, mloop, looptri, collmd->tri_num);
168  collmd->tri = tri;
169  }
170 
171  /* create bounding box hierarchy */
173  collmd->x, collmd->tri, collmd->tri_num, ob->pd->pdef_sboft);
174 
175  collmd->time_x = collmd->time_xnew = current_time;
176  collmd->is_static = true;
177  }
178  else if (mvert_num == collmd->mvert_num) {
179  /* put positions to old positions */
180  tempVert = collmd->x;
181  collmd->x = collmd->xnew;
182  collmd->xnew = tempVert;
183  collmd->time_x = collmd->time_xnew;
184 
185  memcpy(collmd->xnew, mesh_src->mvert, mvert_num * sizeof(MVert));
186 
187  bool is_static = true;
188 
189  for (uint i = 0; i < mvert_num; i++) {
190  /* we save global positions */
191  mul_m4_v3(ob->obmat, collmd->xnew[i].co);
192 
193  /* detect motion */
194  is_static = is_static && equals_v3v3(collmd->x[i].co, collmd->xnew[i].co);
195  }
196 
197  memcpy(collmd->current_xnew, collmd->x, mvert_num * sizeof(MVert));
198  memcpy(collmd->current_x, collmd->x, mvert_num * sizeof(MVert));
199 
200  /* check if GUI setting has changed for bvh */
201  if (collmd->bvhtree) {
202  if (ob->pd->pdef_sboft != BLI_bvhtree_get_epsilon(collmd->bvhtree)) {
203  BLI_bvhtree_free(collmd->bvhtree);
205  collmd->current_x, collmd->tri, collmd->tri_num, ob->pd->pdef_sboft);
206  }
207  }
208 
209  /* Happens on file load (ONLY when I un-comment changes in readfile.c) */
210  if (!collmd->bvhtree) {
212  collmd->current_x, collmd->tri, collmd->tri_num, ob->pd->pdef_sboft);
213  }
214  else if (!collmd->is_static || !is_static) {
215  /* recalc static bounding boxes */
217  collmd->current_x,
218  collmd->current_xnew,
219  collmd->tri,
220  collmd->tri_num,
221  true);
222  }
223 
224  collmd->is_static = is_static;
225  collmd->time_xnew = current_time;
226  }
227  else if (mvert_num != collmd->mvert_num) {
228  freeData((ModifierData *)collmd);
229  }
230  }
231 
232  if (!ELEM(mesh_src, NULL, mesh)) {
233  BKE_id_free(NULL, mesh_src);
234  }
235 }
236 
238 {
239  DEG_add_modifier_to_transform_relation(ctx->node, "Collision Modifier");
240 }
241 
242 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
243 {
244  uiLayout *layout = panel->layout;
245 
247 
248  uiItemL(layout, TIP_("Settings are inside the Physics tab"), ICON_NONE);
249 
250  modifier_panel_end(layout, ptr);
251 }
252 
253 static void panelRegister(ARegionType *region_type)
254 {
256 }
257 
258 static void blendRead(BlendDataReader *UNUSED(reader), ModifierData *md)
259 {
261 #if 0
262  /* TODO: #CollisionModifier should use point-cache
263  * + have proper reset events before enabling this. */
264  collmd->x = newdataadr(fd, collmd->x);
265  collmd->xnew = newdataadr(fd, collmd->xnew);
266  collmd->mfaces = newdataadr(fd, collmd->mfaces);
267 
268  collmd->current_x = MEM_calloc_arrayN(collmd->mvert_num, sizeof(MVert), "current_x");
269  collmd->current_xnew = MEM_calloc_arrayN(collmd->mvert_num, sizeof(MVert), "current_xnew");
270  collmd->current_v = MEM_calloc_arrayN(collmd->mvert_num, sizeof(MVert), "current_v");
271 #endif
272 
273  collmd->x = NULL;
274  collmd->xnew = NULL;
275  collmd->current_x = NULL;
276  collmd->current_xnew = NULL;
277  collmd->current_v = NULL;
278  collmd->time_x = collmd->time_xnew = -1000;
279  collmd->mvert_num = 0;
280  collmd->tri_num = 0;
281  collmd->is_static = false;
282  collmd->bvhtree = NULL;
283  collmd->tri = NULL;
284 }
285 
287  /* name */ N_("Collision"),
288  /* structName */ "CollisionModifierData",
289  /* structSize */ sizeof(CollisionModifierData),
290  /* srna */ &RNA_CollisionModifier,
291  /* type */ eModifierTypeType_OnlyDeform,
293  /* icon */ ICON_MOD_PHYSICS,
294 
295  /* copyData */ NULL,
296 
297  /* deformVerts */ deformVerts,
298  /* deformMatrices */ NULL,
299  /* deformVertsEM */ NULL,
300  /* deformMatricesEM */ NULL,
301  /* modifyMesh */ NULL,
302  /* modifyGeometrySet */ NULL,
303 
304  /* initData */ initData,
305  /* requiredDataMask */ NULL,
306  /* freeData */ freeData,
307  /* isDisabled */ NULL,
308  /* updateDepsgraph */ updateDepsgraph,
309  /* dependsOnTime */ dependsOnTime,
310  /* dependsOnNormals */ NULL,
311  /* foreachIDLink */ NULL,
312  /* foreachTexLink */ NULL,
313  /* freeRuntimeData */ NULL,
314  /* panelRegister */ panelRegister,
315  /* blendWrite */ NULL,
316  /* blendRead */ blendRead,
317 };
struct BVHTree * bvhtree_build_from_mvert(const struct MVert *mvert, const struct MVertTri *tri, int tri_num, float epsilon)
void bvhtree_update_from_mvert(struct BVHTree *bvhtree, const struct MVert *mvert, const struct MVert *mvert_moving, const struct MVertTri *tri, int tri_num, bool moving)
@ G_DEBUG_SIMDATA
Definition: BKE_global.h:192
@ LIB_ID_COPY_LOCALIZE
Definition: BKE_lib_id.h:187
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, int flag)
void BKE_id_free(struct Main *bmain, void *idv)
void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float(*vert_coords)[3])
Definition: mesh.cc:1834
void BKE_mesh_runtime_verttri_from_looptri(struct MVertTri *r_verttri, const struct MLoop *mloop, const struct MLoopTri *looptri, int looptri_num)
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh)
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh)
@ eModifierTypeFlag_Single
Definition: BKE_modifier.h:93
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:66
@ eModifierTypeType_OnlyDeform
Definition: BKE_modifier.h:44
#define BLI_assert(a)
Definition: BLI_assert.h:46
void BLI_bvhtree_free(BVHTree *tree)
Definition: BLI_kdopbvh.c:926
float BLI_bvhtree_get_epsilon(const BVHTree *tree)
Definition: BLI_kdopbvh.c:1044
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:729
MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define TIP_(msgid)
void DEG_add_modifier_to_transform_relation(struct DepsNodeHandle *node_handle, const char *description)
float DEG_get_ctime(const Depsgraph *graph)
#define DNA_struct_default_get(struct_name)
Definition: DNA_defaults.h:29
struct CollisionModifierData CollisionModifierData
@ eModifierType_Collision
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *UNUSED(md))
Definition: MOD_collision.c:83
static void blendRead(BlendDataReader *UNUSED(reader), ModifierData *md)
static void updateDepsgraph(ModifierData *UNUSED(md), const ModifierUpdateDepsgraphContext *ctx)
static void deformVerts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, float(*vertexCos)[3], int verts_num)
Definition: MOD_collision.c:88
ModifierTypeInfo modifierType_Collision
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
static void initData(ModifierData *md)
Definition: MOD_collision.c:49
static void panelRegister(ARegionType *region_type)
static void freeData(ModifierData *md)
Definition: MOD_collision.c:58
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)
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
#define C
Definition: RandGen.cpp:25
void uiItemL(uiLayout *layout, const char *name, int icon)
Scene scene
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
#define G(x, y, z)
static void * newdataadr(FileData *fd, const void *adr)
Definition: readfile.c:1600
struct BVHTree * bvhtree
Definition: DNA_ID.h:368
float co[3]
struct MVert * mvert
int totvert
struct MLoop * mloop
struct Depsgraph * depsgraph
Definition: BKE_modifier.h:140
struct Object * object
Definition: BKE_modifier.h:141
struct DepsNodeHandle * node
Definition: BKE_modifier.h:134
struct PartDeflect * pd
float obmat[4][4]
struct uiLayout * layout
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480