Blender V4.5
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
8
9#include "BLI_utildefines.h"
10
11#include "BLI_kdopbvh.hh"
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 = MEM_malloc_arrayN<float[3]>(size_t(mvert_num), __func__);
128 blender::MutableSpan(reinterpret_cast<blender::float3 *>(collmd->x), mvert_num)
129 .copy_from(mesh->vert_positions());
130
131 for (uint i = 0; i < mvert_num; i++) {
132 /* we save global positions */
133 mul_m4_v3(ob->object_to_world().ptr(), collmd->x[i]);
134 }
135
136 collmd->xnew = static_cast<float(*)[3]>(MEM_dupallocN(collmd->x)); /* Frame end position. */
137 collmd->current_x = static_cast<float(*)[3]>(MEM_dupallocN(collmd->x)); /* Inter-frame. */
138 collmd->current_xnew = static_cast<float(*)[3]>(MEM_dupallocN(collmd->x)); /* Inter-frame. */
139 collmd->current_v = static_cast<float(*)[3]>(MEM_dupallocN(collmd->x)); /* Inter-frame. */
140
141 collmd->mvert_num = mvert_num;
142
143 {
144 const blender::Span<blender::int3> corner_tris = mesh->corner_tris();
145 collmd->tri_num = corner_tris.size();
146 int(*vert_tris)[3] = MEM_malloc_arrayN<int[3]>(collmd->tri_num, __func__);
148 mesh->corner_verts(),
149 corner_tris,
150 {reinterpret_cast<blender::int3 *>(vert_tris), collmd->tri_num});
151 collmd->vert_tris = vert_tris;
152 }
153
154 /* create bounding box hierarchy */
156 collmd->x,
157 reinterpret_cast<blender::int3 *>(collmd->vert_tris),
158 collmd->tri_num,
159 ob->pd->pdef_sboft);
160
161 collmd->time_x = collmd->time_xnew = current_time;
162 collmd->is_static = true;
163 }
164 else if (mvert_num == collmd->mvert_num) {
165 /* put positions to old positions */
166 float(*temp)[3] = collmd->x;
167 collmd->x = collmd->xnew;
168 collmd->xnew = temp;
169 collmd->time_x = collmd->time_xnew;
170
171 memcpy(collmd->xnew, mesh->vert_positions().data(), mvert_num * sizeof(float[3]));
172
173 bool is_static = true;
174
175 for (uint i = 0; i < mvert_num; i++) {
176 /* we save global positions */
177 mul_m4_v3(ob->object_to_world().ptr(), collmd->xnew[i]);
178
179 /* detect motion */
180 is_static = is_static && equals_v3v3(collmd->x[i], collmd->xnew[i]);
181 }
182
183 memcpy(collmd->current_xnew, collmd->x, mvert_num * sizeof(float[3]));
184 memcpy(collmd->current_x, collmd->x, mvert_num * sizeof(float[3]));
185
186 /* check if GUI setting has changed for bvh */
187 if (collmd->bvhtree) {
188 if (ob->pd->pdef_sboft != BLI_bvhtree_get_epsilon(collmd->bvhtree)) {
189 BLI_bvhtree_free(collmd->bvhtree);
191 collmd->current_x,
192 reinterpret_cast<const blender::int3 *>(collmd->vert_tris),
193 collmd->tri_num,
194 ob->pd->pdef_sboft);
195 }
196 }
197
198 /* Happens on file load (ONLY when I un-comment changes in `readfile.cc`). */
199 if (!collmd->bvhtree) {
201 collmd->current_x,
202 reinterpret_cast<const blender::int3 *>(collmd->vert_tris),
203 collmd->tri_num,
204 ob->pd->pdef_sboft);
205 }
206 else if (!collmd->is_static || !is_static) {
207 /* recalc static bounding boxes */
209 collmd->current_x,
210 collmd->current_xnew,
211 reinterpret_cast<const blender::int3 *>(collmd->vert_tris),
212 collmd->tri_num,
213 true);
214 }
215
216 collmd->is_static = is_static;
217 collmd->time_xnew = current_time;
218 }
219 else if (mvert_num != collmd->mvert_num) {
220 free_data((ModifierData *)collmd);
221 }
222 }
223}
224
226{
227 DEG_add_depends_on_transform_relation(ctx->node, "Collision Modifier");
228}
229
230static void panel_draw(const bContext * /*C*/, Panel *panel)
231{
232 uiLayout *layout = panel->layout;
233
235
236 layout->label(RPT_("Settings are inside the Physics tab"), ICON_NONE);
237
239}
240
241static void panel_register(ARegionType *region_type)
242{
244}
245
246static void blend_read(BlendDataReader * /*reader*/, ModifierData *md)
247{
249#if 0
250 /* TODO: #CollisionModifier should use point-cache
251 * + have proper reset events before enabling this. */
252 collmd->x = newdataadr(fd, collmd->x);
253 collmd->xnew = newdataadr(fd, collmd->xnew);
254 collmd->mfaces = newdataadr(fd, collmd->mfaces);
255
256 collmd->current_x = MEM_calloc_arrayN<float[3]>(collmd->mvert_num, "current_x");
257 collmd->current_xnew = MEM_calloc_arrayN<float[3]>(collmd->mvert_num, "current_xnew");
258 collmd->current_v = MEM_calloc_arrayN<float[3]>(collmd->mvert_num, "current_v");
259#endif
260
261 collmd->x = nullptr;
262 collmd->xnew = nullptr;
263 collmd->current_x = nullptr;
264 collmd->current_xnew = nullptr;
265 collmd->current_v = nullptr;
266 collmd->time_x = collmd->time_xnew = -1000;
267 collmd->mvert_num = 0;
268 collmd->tri_num = 0;
269 collmd->is_static = false;
270 collmd->bvhtree = nullptr;
271 collmd->vert_tris = nullptr;
272}
273
275 /*idname*/ "Collision",
276 /*name*/ N_("Collision"),
277 /*struct_name*/ "CollisionModifierData",
278 /*struct_size*/ sizeof(CollisionModifierData),
279 /*srna*/ &RNA_CollisionModifier,
282 /*icon*/ ICON_MOD_PHYSICS,
283
284 /*copy_data*/ nullptr,
285
286 /*deform_verts*/ deform_verts,
287 /*deform_matrices*/ nullptr,
288 /*deform_verts_EM*/ nullptr,
289 /*deform_matrices_EM*/ nullptr,
290 /*modify_mesh*/ nullptr,
291 /*modify_geometry_set*/ nullptr,
292
293 /*init_data*/ init_data,
294 /*required_data_mask*/ nullptr,
295 /*free_data*/ free_data,
296 /*is_disabled*/ nullptr,
297 /*update_depsgraph*/ update_depsgraph,
298 /*depends_on_time*/ depends_on_time,
299 /*depends_on_normals*/ nullptr,
300 /*foreach_ID_link*/ nullptr,
301 /*foreach_tex_link*/ nullptr,
302 /*free_runtime_data*/ nullptr,
303 /*panel_register*/ panel_register,
304 /*blend_write*/ nullptr,
305 /*blend_read*/ blend_read,
306 /*foreach_cache*/ nullptr,
307};
struct BVHTree * bvhtree_build_from_mvert(const float(*positions)[3], const blender::int3 *vert_tris, int tri_num, float epsilon)
Definition collision.cc:89
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:113
@ G_DEBUG_SIMDATA
@ eModifierTypeFlag_Single
@ eModifierTypeFlag_AcceptsMesh
#define BLI_assert(a)
Definition BLI_assert.h:46
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)
@ eModifierType_Collision
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
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 panel_draw(const bContext *, Panel *panel)
static void free_data(ModifierData *md)
Definition MOD_bevel.cc:271
static bool depends_on_time(Scene *, ModifierData *)
Definition MOD_build.cc:47
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 *)
PanelType * modifier_panel_register(ARegionType *region_type, ModifierType type, PanelDrawFn draw)
PointerRNA * modifier_panel_get_property_pointers(Panel *panel, PointerRNA *r_ob_ptr)
void modifier_error_message_draw(uiLayout *layout, PointerRNA *ptr)
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:739
constexpr int64_t size() const
Definition BLI_span.hh:252
#define printf(...)
#define MEM_SAFE_FREE(v)
static void update_depsgraph(tGraphSliderOp *gso)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:123
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
#define G(x, y, z)
void vert_tris_from_corner_tris(Span< int > corner_verts, Span< int3 > corner_tris, MutableSpan< int3 > vert_tris)
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
static void * newdataadr(FileData *fd, const void *adr)
Definition readfile.cc:1512
int verts_num
struct PartDeflect * pd
struct uiLayout * layout
void label(blender::StringRef name, int icon)
i
Definition text_draw.cc:230
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4226