Blender  V2.93
MOD_collision.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  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "BLI_utildefines.h"
25 
26 #include "BLI_kdopbvh.h"
27 #include "BLI_math.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_force_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_screen_types.h"
37 
38 #include "MEM_guardedalloc.h"
39 
40 #include "BKE_collision.h"
41 #include "BKE_context.h"
42 #include "BKE_global.h"
43 #include "BKE_lib_id.h"
44 #include "BKE_mesh.h"
45 #include "BKE_mesh_runtime.h"
46 #include "BKE_modifier.h"
47 #include "BKE_pointcache.h"
48 #include "BKE_scene.h"
49 #include "BKE_screen.h"
50 
51 #include "UI_interface.h"
52 #include "UI_resources.h"
53 
54 #include "RNA_access.h"
55 
56 #include "MOD_modifiertypes.h"
57 #include "MOD_ui_common.h"
58 #include "MOD_util.h"
59 
60 #include "BLO_read_write.h"
61 
62 #include "DEG_depsgraph_query.h"
63 
64 static void initData(ModifierData *md)
65 {
67 
68  BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(collmd, modifier));
69 
71 }
72 
73 static void freeData(ModifierData *md)
74 {
76 
77  if (collmd) { /* Seriously? */
78  if (collmd->bvhtree) {
79  BLI_bvhtree_free(collmd->bvhtree);
80  collmd->bvhtree = NULL;
81  }
82 
83  MEM_SAFE_FREE(collmd->x);
84  MEM_SAFE_FREE(collmd->xnew);
85  MEM_SAFE_FREE(collmd->current_x);
86  MEM_SAFE_FREE(collmd->current_xnew);
87  MEM_SAFE_FREE(collmd->current_v);
88 
89  MEM_SAFE_FREE(collmd->tri);
90 
91  collmd->time_x = collmd->time_xnew = -1000;
92  collmd->mvert_num = 0;
93  collmd->tri_num = 0;
94  collmd->is_static = false;
95  }
96 }
97 
99 {
100  return true;
101 }
102 
103 static void deformVerts(ModifierData *md,
104  const ModifierEvalContext *ctx,
105  Mesh *mesh,
106  float (*vertexCos)[3],
107  int numVerts)
108 {
110  Mesh *mesh_src;
111  MVert *tempVert = NULL;
112  Object *ob = ctx->object;
113 
114  /* If collision is disabled, free the stale data and exit. */
115  if (!ob->pd || !ob->pd->deflect) {
116  if (!ob->pd) {
117  printf("CollisionModifier: collision settings are missing!\n");
118  }
119 
120  freeData(md);
121  return;
122  }
123 
124  if (mesh == NULL) {
125  mesh_src = MOD_deform_mesh_eval_get(ob, NULL, NULL, NULL, numVerts, false, false);
126  }
127  else {
128  /* Not possible to use get_mesh() in this case as we'll modify its vertices
129  * and get_mesh() would return 'mesh' directly. */
130  mesh_src = (Mesh *)BKE_id_copy_ex(NULL, (ID *)mesh, NULL, LIB_ID_COPY_LOCALIZE);
131  }
132 
133  if (mesh_src) {
134  float current_time = 0;
135  uint mvert_num = 0;
136 
137  BKE_mesh_vert_coords_apply(mesh_src, vertexCos);
138  BKE_mesh_calc_normals(mesh_src);
139 
140  current_time = DEG_get_ctime(ctx->depsgraph);
141 
142  if (G.debug & G_DEBUG_SIMDATA) {
143  printf("current_time %f, collmd->time_xnew %f\n", current_time, collmd->time_xnew);
144  }
145 
146  mvert_num = mesh_src->totvert;
147 
148  if (current_time < collmd->time_xnew) {
149  freeData((ModifierData *)collmd);
150  }
151  else if (current_time == collmd->time_xnew) {
152  if (mvert_num != collmd->mvert_num) {
153  freeData((ModifierData *)collmd);
154  }
155  }
156 
157  /* check if mesh has changed */
158  if (collmd->x && (mvert_num != collmd->mvert_num)) {
159  freeData((ModifierData *)collmd);
160  }
161 
162  if (collmd->time_xnew == -1000) { /* first time */
163 
164  collmd->x = MEM_dupallocN(mesh_src->mvert); /* frame start position */
165 
166  for (uint i = 0; i < mvert_num; i++) {
167  /* we save global positions */
168  mul_m4_v3(ob->obmat, collmd->x[i].co);
169  }
170 
171  collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
172  collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
173  collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
174  collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame
175 
176  collmd->mvert_num = mvert_num;
177 
178  {
179  const MLoop *mloop = mesh_src->mloop;
180  const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh_src);
181  collmd->tri_num = BKE_mesh_runtime_looptri_len(mesh_src);
182  MVertTri *tri = MEM_mallocN(sizeof(*tri) * collmd->tri_num, __func__);
183  BKE_mesh_runtime_verttri_from_looptri(tri, mloop, looptri, collmd->tri_num);
184  collmd->tri = tri;
185  }
186 
187  /* create bounding box hierarchy */
189  collmd->x, collmd->tri, collmd->tri_num, ob->pd->pdef_sboft);
190 
191  collmd->time_x = collmd->time_xnew = current_time;
192  collmd->is_static = true;
193  }
194  else if (mvert_num == collmd->mvert_num) {
195  /* put positions to old positions */
196  tempVert = collmd->x;
197  collmd->x = collmd->xnew;
198  collmd->xnew = tempVert;
199  collmd->time_x = collmd->time_xnew;
200 
201  memcpy(collmd->xnew, mesh_src->mvert, mvert_num * sizeof(MVert));
202 
203  bool is_static = true;
204 
205  for (uint i = 0; i < mvert_num; i++) {
206  /* we save global positions */
207  mul_m4_v3(ob->obmat, collmd->xnew[i].co);
208 
209  /* detect motion */
210  is_static = is_static && equals_v3v3(collmd->x[i].co, collmd->xnew[i].co);
211  }
212 
213  memcpy(collmd->current_xnew, collmd->x, mvert_num * sizeof(MVert));
214  memcpy(collmd->current_x, collmd->x, mvert_num * sizeof(MVert));
215 
216  /* check if GUI setting has changed for bvh */
217  if (collmd->bvhtree) {
218  if (ob->pd->pdef_sboft != BLI_bvhtree_get_epsilon(collmd->bvhtree)) {
219  BLI_bvhtree_free(collmd->bvhtree);
221  collmd->current_x, collmd->tri, collmd->tri_num, ob->pd->pdef_sboft);
222  }
223  }
224 
225  /* Happens on file load (ONLY when I un-comment changes in readfile.c) */
226  if (!collmd->bvhtree) {
228  collmd->current_x, collmd->tri, collmd->tri_num, ob->pd->pdef_sboft);
229  }
230  else if (!collmd->is_static || !is_static) {
231  /* recalc static bounding boxes */
233  collmd->current_x,
234  collmd->current_xnew,
235  collmd->tri,
236  collmd->tri_num,
237  true);
238  }
239 
240  collmd->is_static = is_static;
241  collmd->time_xnew = current_time;
242  }
243  else if (mvert_num != collmd->mvert_num) {
244  freeData((ModifierData *)collmd);
245  }
246  }
247 
248  if (!ELEM(mesh_src, NULL, mesh)) {
249  BKE_id_free(NULL, mesh_src);
250  }
251 }
252 
254 {
255  DEG_add_modifier_to_transform_relation(ctx->node, "Collision Modifier");
256 }
257 
258 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
259 {
260  uiLayout *layout = panel->layout;
261 
263 
264  uiItemL(layout, IFACE_("Settings are inside the Physics tab"), ICON_NONE);
265 
266  modifier_panel_end(layout, ptr);
267 }
268 
269 static void panelRegister(ARegionType *region_type)
270 {
272 }
273 
274 static void blendRead(BlendDataReader *UNUSED(reader), ModifierData *md)
275 {
277 #if 0
278  // TODO: CollisionModifier should use pointcache
279  // + have proper reset events before enabling this
280  collmd->x = newdataadr(fd, collmd->x);
281  collmd->xnew = newdataadr(fd, collmd->xnew);
282  collmd->mfaces = newdataadr(fd, collmd->mfaces);
283 
284  collmd->current_x = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_x");
285  collmd->current_xnew = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_xnew");
286  collmd->current_v = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_v");
287 #endif
288 
289  collmd->x = NULL;
290  collmd->xnew = NULL;
291  collmd->current_x = NULL;
292  collmd->current_xnew = NULL;
293  collmd->current_v = NULL;
294  collmd->time_x = collmd->time_xnew = -1000;
295  collmd->mvert_num = 0;
296  collmd->tri_num = 0;
297  collmd->is_static = false;
298  collmd->bvhtree = NULL;
299  collmd->tri = NULL;
300 }
301 
303  /* name */ "Collision",
304  /* structName */ "CollisionModifierData",
305  /* structSize */ sizeof(CollisionModifierData),
306  /* srna */ &RNA_CollisionModifier,
307  /* type */ eModifierTypeType_OnlyDeform,
309  /* icon */ ICON_MOD_PHYSICS,
310 
311  /* copyData */ NULL,
312 
313  /* deformVerts */ deformVerts,
314  /* deformMatrices */ NULL,
315  /* deformVertsEM */ NULL,
316  /* deformMatricesEM */ NULL,
317  /* modifyMesh */ NULL,
318  /* modifyHair */ NULL,
319  /* modifyGeometrySet */ NULL,
320  /* modifyVolume */ NULL,
321 
322  /* initData */ initData,
323  /* requiredDataMask */ NULL,
324  /* freeData */ freeData,
325  /* isDisabled */ NULL,
326  /* updateDepsgraph */ updateDepsgraph,
327  /* dependsOnTime */ dependsOnTime,
328  /* dependsOnNormals */ NULL,
329  /* foreachIDLink */ NULL,
330  /* foreachTexLink */ NULL,
331  /* freeRuntimeData */ NULL,
332  /* panelRegister */ panelRegister,
333  /* blendWrite */ NULL,
334  /* blendRead */ blendRead,
335 };
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:150
@ LIB_ID_COPY_LOCALIZE
Definition: BKE_lib_id.h:145
struct ID * BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const 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.c:1755
void BKE_mesh_calc_normals(struct Mesh *me)
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(struct Mesh *mesh)
Definition: mesh_runtime.c:155
int BKE_mesh_runtime_looptri_len(const struct Mesh *mesh)
@ eModifierTypeFlag_Single
Definition: BKE_modifier.h:107
@ eModifierTypeFlag_AcceptsMesh
Definition: BKE_modifier.h:80
@ eModifierTypeType_OnlyDeform
Definition: BKE_modifier.h:58
#define BLI_assert(a)
Definition: BLI_assert.h:58
void BLI_bvhtree_free(BVHTree *tree)
Definition: BLI_kdopbvh.c:945
float BLI_bvhtree_get_epsilon(const BVHTree *tree)
Definition: BLI_kdopbvh.c:1074
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNUSED(x)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define IFACE_(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:44
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 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 numVerts)
ModifierTypeInfo modifierType_Collision
static bool dependsOnTime(ModifierData *UNUSED(md))
Definition: MOD_collision.c:98
static void panel_draw(const bContext *UNUSED(C), Panel *panel)
static void initData(ModifierData *md)
Definition: MOD_collision.c:64
static void panelRegister(ARegionType *region_type)
static void freeData(ModifierData *md)
Definition: MOD_collision.c:73
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)
Mesh * MOD_deform_mesh_eval_get(Object *ob, struct BMEditMesh *em, Mesh *mesh, const float(*vertexCos)[3], const int num_verts, const bool use_normals, const bool use_orco)
Definition: MOD_util.c:186
StructRNA RNA_CollisionModifier
#define C
Definition: RandGen.cpp:39
void uiItemL(uiLayout *layout, const char *name, int icon)
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:46
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static void * newdataadr(FileData *fd, const void *adr)
Definition: readfile.c:1806
struct BVHTree * bvhtree
Definition: DNA_ID.h:273
float co[3]
struct MVert * mvert
int totvert
struct MLoop * mloop
struct Depsgraph * depsgraph
Definition: BKE_modifier.h:153
struct Object * object
Definition: BKE_modifier.h:154
struct DepsNodeHandle * node
Definition: BKE_modifier.h:147
struct PartDeflect * pd
float obmat[4][4]
struct uiLayout * layout
#define G(x, y, z)
PointerRNA * ptr
Definition: wm_files.c:3157