Blender V4.3
MOD_collision.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BLI_utildefines.h"
10
11#include "BLI_kdopbvh.h"
12#include "BLI_math_matrix.h"
13#include "BLI_math_vector.h"
14
15#include "BLT_translation.hh"
16
17#include "DNA_defaults.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_global.hh"
26#include "BKE_mesh.hh"
27#include "BKE_modifier.hh"
28
29#include "UI_interface.hh"
30#include "UI_resources.hh"
31
32#include "RNA_prototypes.hh"
33
34#include "MOD_ui_common.hh"
35
37
46
47static void free_data(ModifierData *md)
48{
50
51 if (collmd) { /* Seriously? */
52 if (collmd->bvhtree) {
54 collmd->bvhtree = nullptr;
55 }
56
57 MEM_SAFE_FREE(collmd->x);
58 MEM_SAFE_FREE(collmd->xnew);
59 MEM_SAFE_FREE(collmd->current_x);
61 MEM_SAFE_FREE(collmd->current_v);
62
63 MEM_SAFE_FREE(collmd->vert_tris);
64
65 collmd->time_x = collmd->time_xnew = -1000;
66 collmd->mvert_num = 0;
67 collmd->tri_num = 0;
68 collmd->is_static = false;
69 }
70}
71
72static bool depends_on_time(Scene * /*scene*/, ModifierData * /*md*/)
73{
74 return true;
75}
76
77static void deform_verts(ModifierData *md,
78 const ModifierEvalContext *ctx,
79 Mesh *mesh,
81{
83 Object *ob = ctx->object;
84
85 /* If collision is disabled, free the stale data and exit. */
86 if (!ob->pd || !ob->pd->deflect) {
87 if (!ob->pd) {
88 printf("CollisionModifier: collision settings are missing!\n");
89 }
90
91 free_data(md);
92 return;
93 }
94
95 if (mesh) {
96 float current_time = 0;
97 int mvert_num = 0;
98
99 mesh->vert_positions_for_write().copy_from(positions);
100 mesh->tag_positions_changed();
101
102 current_time = DEG_get_ctime(ctx->depsgraph);
103
104 if (G.debug & G_DEBUG_SIMDATA) {
105 printf("current_time %f, collmd->time_xnew %f\n", current_time, collmd->time_xnew);
106 }
107
108 mvert_num = mesh->verts_num;
109
110 if (current_time < collmd->time_xnew) {
111 free_data((ModifierData *)collmd);
112 }
113 else if (current_time == collmd->time_xnew) {
114 if (mvert_num != collmd->mvert_num) {
115 free_data((ModifierData *)collmd);
116 }
117 }
118
119 /* check if mesh has changed */
120 if (collmd->x && (mvert_num != collmd->mvert_num)) {
121 free_data((ModifierData *)collmd);
122 }
123
124 if (collmd->time_xnew == -1000) { /* first time */
125
126 mvert_num = mesh->verts_num;
127 collmd->x = static_cast<float(*)[3]>(
128 MEM_malloc_arrayN(mvert_num, sizeof(float[3]), __func__));
129 blender::MutableSpan(reinterpret_cast<blender::float3 *>(collmd->x), mvert_num)
130 .copy_from(mesh->vert_positions());
131
132 for (uint i = 0; i < mvert_num; i++) {
133 /* we save global positions */
134 mul_m4_v3(ob->object_to_world().ptr(), collmd->x[i]);
135 }
136
137 collmd->xnew = static_cast<float(*)[3]>(MEM_dupallocN(collmd->x)); /* Frame end position. */
138 collmd->current_x = static_cast<float(*)[3]>(MEM_dupallocN(collmd->x)); /* Inter-frame. */
139 collmd->current_xnew = static_cast<float(*)[3]>(MEM_dupallocN(collmd->x)); /* Inter-frame. */
140 collmd->current_v = static_cast<float(*)[3]>(MEM_dupallocN(collmd->x)); /* Inter-frame. */
141
142 collmd->mvert_num = mvert_num;
143
144 {
145 const blender::Span<blender::int3> corner_tris = mesh->corner_tris();
146 collmd->tri_num = corner_tris.size();
147 int(*vert_tris)[3] = static_cast<int(*)[3]>(
148 MEM_malloc_arrayN(collmd->tri_num, sizeof(int[3]), __func__));
150 mesh->corner_verts(),
151 corner_tris,
152 {reinterpret_cast<blender::int3 *>(vert_tris), collmd->tri_num});
153 collmd->vert_tris = vert_tris;
154 }
155
156 /* create bounding box hierarchy */
158 collmd->x,
159 reinterpret_cast<blender::int3 *>(collmd->vert_tris),
160 collmd->tri_num,
161 ob->pd->pdef_sboft);
162
163 collmd->time_x = collmd->time_xnew = current_time;
164 collmd->is_static = true;
165 }
166 else if (mvert_num == collmd->mvert_num) {
167 /* put positions to old positions */
168 float(*temp)[3] = collmd->x;
169 collmd->x = collmd->xnew;
170 collmd->xnew = temp;
171 collmd->time_x = collmd->time_xnew;
172
173 memcpy(collmd->xnew, mesh->vert_positions().data(), mvert_num * sizeof(float[3]));
174
175 bool is_static = true;
176
177 for (uint i = 0; i < mvert_num; i++) {
178 /* we save global positions */
179 mul_m4_v3(ob->object_to_world().ptr(), collmd->xnew[i]);
180
181 /* detect motion */
182 is_static = is_static && equals_v3v3(collmd->x[i], collmd->xnew[i]);
183 }
184
185 memcpy(collmd->current_xnew, collmd->x, mvert_num * sizeof(float[3]));
186 memcpy(collmd->current_x, collmd->x, mvert_num * sizeof(float[3]));
187
188 /* check if GUI setting has changed for bvh */
189 if (collmd->bvhtree) {
190 if (ob->pd->pdef_sboft != BLI_bvhtree_get_epsilon(collmd->bvhtree)) {
191 BLI_bvhtree_free(collmd->bvhtree);
193 collmd->current_x,
194 reinterpret_cast<const blender::int3 *>(collmd->vert_tris),
195 collmd->tri_num,
196 ob->pd->pdef_sboft);
197 }
198 }
199
200 /* Happens on file load (ONLY when I un-comment changes in `readfile.cc`). */
201 if (!collmd->bvhtree) {
203 collmd->current_x,
204 reinterpret_cast<const blender::int3 *>(collmd->vert_tris),
205 collmd->tri_num,
206 ob->pd->pdef_sboft);
207 }
208 else if (!collmd->is_static || !is_static) {
209 /* recalc static bounding boxes */
211 collmd->current_x,
212 collmd->current_xnew,
213 reinterpret_cast<const blender::int3 *>(collmd->vert_tris),
214 collmd->tri_num,
215 true);
216 }
217
218 collmd->is_static = is_static;
219 collmd->time_xnew = current_time;
220 }
221 else if (mvert_num != collmd->mvert_num) {
222 free_data((ModifierData *)collmd);
223 }
224 }
225}
226
228{
229 DEG_add_depends_on_transform_relation(ctx->node, "Collision Modifier");
230}
231
232static void panel_draw(const bContext * /*C*/, Panel *panel)
233{
234 uiLayout *layout = panel->layout;
235
237
238 uiItemL(layout, RPT_("Settings are inside the Physics tab"), ICON_NONE);
239
240 modifier_panel_end(layout, ptr);
241}
242
243static void panel_register(ARegionType *region_type)
244{
246}
247
248static void blend_read(BlendDataReader * /*reader*/, ModifierData *md)
249{
251#if 0
252 /* TODO: #CollisionModifier should use point-cache
253 * + have proper reset events before enabling this. */
254 collmd->x = newdataadr(fd, collmd->x);
255 collmd->xnew = newdataadr(fd, collmd->xnew);
256 collmd->mfaces = newdataadr(fd, collmd->mfaces);
257
258 collmd->current_x = MEM_calloc_arrayN(collmd->mvert_num, sizeof(float[3]), "current_x");
259 collmd->current_xnew = MEM_calloc_arrayN(collmd->mvert_num, sizeof(float[3]), "current_xnew");
260 collmd->current_v = MEM_calloc_arrayN(collmd->mvert_num, sizeof(float[3]), "current_v");
261#endif
262
263 collmd->x = nullptr;
264 collmd->xnew = nullptr;
265 collmd->current_x = nullptr;
266 collmd->current_xnew = nullptr;
267 collmd->current_v = nullptr;
268 collmd->time_x = collmd->time_xnew = -1000;
269 collmd->mvert_num = 0;
270 collmd->tri_num = 0;
271 collmd->is_static = false;
272 collmd->bvhtree = nullptr;
273 collmd->vert_tris = nullptr;
274}
275
277 /*idname*/ "Collision",
278 /*name*/ N_("Collision"),
279 /*struct_name*/ "CollisionModifierData",
280 /*struct_size*/ sizeof(CollisionModifierData),
281 /*srna*/ &RNA_CollisionModifier,
284 /*icon*/ ICON_MOD_PHYSICS,
285
286 /*copy_data*/ nullptr,
287
288 /*deform_verts*/ deform_verts,
289 /*deform_matrices*/ nullptr,
290 /*deform_verts_EM*/ nullptr,
291 /*deform_matrices_EM*/ nullptr,
292 /*modify_mesh*/ nullptr,
293 /*modify_geometry_set*/ nullptr,
294
295 /*init_data*/ init_data,
296 /*required_data_mask*/ nullptr,
297 /*free_data*/ free_data,
298 /*is_disabled*/ nullptr,
299 /*update_depsgraph*/ update_depsgraph,
300 /*depends_on_time*/ depends_on_time,
301 /*depends_on_normals*/ nullptr,
302 /*foreach_ID_link*/ nullptr,
303 /*foreach_tex_link*/ nullptr,
304 /*free_runtime_data*/ nullptr,
305 /*panel_register*/ panel_register,
306 /*blend_write*/ nullptr,
307 /*blend_read*/ blend_read,
308 /*foreach_cache*/ nullptr,
309};
struct BVHTree * bvhtree_build_from_mvert(const float(*positions)[3], const blender::int3 *vert_tris, int tri_num, float epsilon)
Definition collision.cc:90
void bvhtree_update_from_mvert(struct BVHTree *bvhtree, const float(*positions)[3], const float(*positions_moving)[3], const blender::int3 *vert_tris, int tri_num, bool moving)
Definition collision.cc:114
@ G_DEBUG_SIMDATA
@ eModifierTypeFlag_Single
@ eModifierTypeFlag_AcceptsMesh
#define BLI_assert(a)
Definition BLI_assert.h:50
void BLI_bvhtree_free(BVHTree *tree)
float BLI_bvhtree_get_epsilon(const BVHTree *tree)
void mul_m4_v3(const float M[4][4], float r[3])
MINLINE bool equals_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define RPT_(msgid)
void DEG_add_depends_on_transform_relation(DepsNodeHandle *node_handle, const char *description)
float DEG_get_ctime(const Depsgraph *graph)
#define DNA_struct_default_get(struct_name)
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 init_data(ModifierData *md)
static void deform_verts(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh, blender::MutableSpan< blender::float3 > positions)
static void panel_register(ARegionType *region_type)
static void blend_read(BlendDataReader *, ModifierData *md)
static void free_data(ModifierData *md)
static void update_depsgraph(ModifierData *, const ModifierUpdateDepsgraphContext *ctx)
ModifierTypeInfo modifierType_Collision
static void panel_draw(const bContext *, Panel *panel)
static bool depends_on_time(Scene *, ModifierData *)
void modifier_panel_end(uiLayout *layout, PointerRNA *ptr)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void uiItemL(uiLayout *layout, const char *name, int icon)
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:726
constexpr int64_t size() const
Definition BLI_span.hh:253
#define printf
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:43
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
#define G(x, y, z)
void vert_tris_from_corner_tris(Span< int > corner_verts, Span< int3 > corner_tris, MutableSpan< int3 > vert_tris)
static void * newdataadr(FileData *fd, const void *adr)
Definition readfile.cc:1467
struct PartDeflect * pd
struct uiLayout * layout
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4126