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
20 /** \file
21 * \ingroup modifiers
22 */
23
24 #include "BLI_utildefines.h"
25
26 #include "BLI_math.h"
27
28 #include "BLT_translation.h"
29
30 #include "DNA_defaults.h"
31 #include "DNA_mesh_types.h"
32 #include "DNA_meshdata_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_screen_types.h"
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BKE_collision.h"
39 #include "BKE_context.h"
40 #include "BKE_global.h"
41 #include "BKE_lib_id.h"
42 #include "BKE_mesh.h"
43 #include "BKE_mesh_runtime.h"
44 #include "BKE_modifier.h"
45 #include "BKE_pointcache.h"
46 #include "BKE_scene.h"
47 #include "BKE_screen.h"
48
49 #include "UI_interface.h"
50 #include "UI_resources.h"
51
52 #include "RNA_access.h"
53
54 #include "MOD_modifiertypes.h"
55 #include "MOD_ui_common.h"
56 #include "MOD_util.h"
57
58 #include "BLO_read_write.h"
59
60 #include "DEG_depsgraph_query.h"
61
initData(ModifierData * md)62 static void initData(ModifierData *md)
63 {
64 CollisionModifierData *collmd = (CollisionModifierData *)md;
65
66 BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(collmd, modifier));
67
68 MEMCPY_STRUCT_AFTER(collmd, DNA_struct_default_get(CollisionModifierData), modifier);
69 }
70
freeData(ModifierData * md)71 static void freeData(ModifierData *md)
72 {
73 CollisionModifierData *collmd = (CollisionModifierData *)md;
74
75 if (collmd) { /* Seriously? */
76 if (collmd->bvhtree) {
77 BLI_bvhtree_free(collmd->bvhtree);
78 collmd->bvhtree = NULL;
79 }
80
81 MEM_SAFE_FREE(collmd->x);
82 MEM_SAFE_FREE(collmd->xnew);
83 MEM_SAFE_FREE(collmd->current_x);
84 MEM_SAFE_FREE(collmd->current_xnew);
85 MEM_SAFE_FREE(collmd->current_v);
86
87 MEM_SAFE_FREE(collmd->tri);
88
89 collmd->time_x = collmd->time_xnew = -1000;
90 collmd->mvert_num = 0;
91 collmd->tri_num = 0;
92 collmd->is_static = false;
93 }
94 }
95
dependsOnTime(ModifierData * UNUSED (md))96 static bool dependsOnTime(ModifierData *UNUSED(md))
97 {
98 return true;
99 }
100
deformVerts(ModifierData * md,const ModifierEvalContext * ctx,Mesh * mesh,float (* vertexCos)[3],int numVerts)101 static void deformVerts(ModifierData *md,
102 const ModifierEvalContext *ctx,
103 Mesh *mesh,
104 float (*vertexCos)[3],
105 int numVerts)
106 {
107 CollisionModifierData *collmd = (CollisionModifierData *)md;
108 Mesh *mesh_src;
109 MVert *tempVert = NULL;
110 Object *ob = ctx->object;
111
112 if (mesh == NULL) {
113 mesh_src = MOD_deform_mesh_eval_get(ob, NULL, NULL, NULL, numVerts, false, false);
114 }
115 else {
116 /* Not possible to use get_mesh() in this case as we'll modify its vertices
117 * and get_mesh() would return 'mesh' directly. */
118 mesh_src = (Mesh *)BKE_id_copy_ex(NULL, (ID *)mesh, NULL, LIB_ID_COPY_LOCALIZE);
119 }
120
121 if (!ob->pd) {
122 printf("CollisionModifier deformVerts: Should not happen!\n");
123 return;
124 }
125
126 if (mesh_src) {
127 float current_time = 0;
128 uint mvert_num = 0;
129
130 BKE_mesh_vert_coords_apply(mesh_src, vertexCos);
131 BKE_mesh_calc_normals(mesh_src);
132
133 current_time = DEG_get_ctime(ctx->depsgraph);
134
135 if (G.debug & G_DEBUG_SIMDATA) {
136 printf("current_time %f, collmd->time_xnew %f\n", current_time, collmd->time_xnew);
137 }
138
139 mvert_num = mesh_src->totvert;
140
141 if (current_time < collmd->time_xnew) {
142 freeData((ModifierData *)collmd);
143 }
144 else if (current_time == collmd->time_xnew) {
145 if (mvert_num != collmd->mvert_num) {
146 freeData((ModifierData *)collmd);
147 }
148 }
149
150 /* check if mesh has changed */
151 if (collmd->x && (mvert_num != collmd->mvert_num)) {
152 freeData((ModifierData *)collmd);
153 }
154
155 if (collmd->time_xnew == -1000) { /* first time */
156
157 collmd->x = MEM_dupallocN(mesh_src->mvert); /* frame start position */
158
159 for (uint i = 0; i < mvert_num; i++) {
160 /* we save global positions */
161 mul_m4_v3(ob->obmat, collmd->x[i].co);
162 }
163
164 collmd->xnew = MEM_dupallocN(collmd->x); // frame end position
165 collmd->current_x = MEM_dupallocN(collmd->x); // inter-frame
166 collmd->current_xnew = MEM_dupallocN(collmd->x); // inter-frame
167 collmd->current_v = MEM_dupallocN(collmd->x); // inter-frame
168
169 collmd->mvert_num = mvert_num;
170
171 {
172 const MLoop *mloop = mesh_src->mloop;
173 const MLoopTri *looptri = BKE_mesh_runtime_looptri_ensure(mesh_src);
174 collmd->tri_num = BKE_mesh_runtime_looptri_len(mesh_src);
175 MVertTri *tri = MEM_mallocN(sizeof(*tri) * collmd->tri_num, __func__);
176 BKE_mesh_runtime_verttri_from_looptri(tri, mloop, looptri, collmd->tri_num);
177 collmd->tri = tri;
178 }
179
180 /* create bounding box hierarchy */
181 collmd->bvhtree = bvhtree_build_from_mvert(
182 collmd->x, collmd->tri, collmd->tri_num, ob->pd->pdef_sboft);
183
184 collmd->time_x = collmd->time_xnew = current_time;
185 collmd->is_static = true;
186 }
187 else if (mvert_num == collmd->mvert_num) {
188 /* put positions to old positions */
189 tempVert = collmd->x;
190 collmd->x = collmd->xnew;
191 collmd->xnew = tempVert;
192 collmd->time_x = collmd->time_xnew;
193
194 memcpy(collmd->xnew, mesh_src->mvert, mvert_num * sizeof(MVert));
195
196 bool is_static = true;
197
198 for (uint i = 0; i < mvert_num; i++) {
199 /* we save global positions */
200 mul_m4_v3(ob->obmat, collmd->xnew[i].co);
201
202 /* detect motion */
203 is_static = is_static && equals_v3v3(collmd->x[i].co, collmd->xnew[i].co);
204 }
205
206 memcpy(collmd->current_xnew, collmd->x, mvert_num * sizeof(MVert));
207 memcpy(collmd->current_x, collmd->x, mvert_num * sizeof(MVert));
208
209 /* check if GUI setting has changed for bvh */
210 if (collmd->bvhtree) {
211 if (ob->pd->pdef_sboft != BLI_bvhtree_get_epsilon(collmd->bvhtree)) {
212 BLI_bvhtree_free(collmd->bvhtree);
213 collmd->bvhtree = bvhtree_build_from_mvert(
214 collmd->current_x, collmd->tri, collmd->tri_num, ob->pd->pdef_sboft);
215 }
216 }
217
218 /* happens on file load (ONLY when i decomment changes in readfile.c) */
219 if (!collmd->bvhtree) {
220 collmd->bvhtree = bvhtree_build_from_mvert(
221 collmd->current_x, collmd->tri, collmd->tri_num, ob->pd->pdef_sboft);
222 }
223 else if (!collmd->is_static || !is_static) {
224 /* recalc static bounding boxes */
225 bvhtree_update_from_mvert(collmd->bvhtree,
226 collmd->current_x,
227 collmd->current_xnew,
228 collmd->tri,
229 collmd->tri_num,
230 true);
231 }
232
233 collmd->is_static = is_static;
234 collmd->time_xnew = current_time;
235 }
236 else if (mvert_num != collmd->mvert_num) {
237 freeData((ModifierData *)collmd);
238 }
239 }
240
241 if (!ELEM(mesh_src, NULL, mesh)) {
242 BKE_id_free(NULL, mesh_src);
243 }
244 }
245
updateDepsgraph(ModifierData * UNUSED (md),const ModifierUpdateDepsgraphContext * ctx)246 static void updateDepsgraph(ModifierData *UNUSED(md), const ModifierUpdateDepsgraphContext *ctx)
247 {
248 DEG_add_modifier_to_transform_relation(ctx->node, "Collision Modifier");
249 }
250
panel_draw(const bContext * UNUSED (C),Panel * panel)251 static void panel_draw(const bContext *UNUSED(C), Panel *panel)
252 {
253 uiLayout *layout = panel->layout;
254
255 PointerRNA *ptr = modifier_panel_get_property_pointers(panel, NULL);
256
257 uiItemL(layout, IFACE_("Settings are inside the Physics tab"), ICON_NONE);
258
259 modifier_panel_end(layout, ptr);
260 }
261
panelRegister(ARegionType * region_type)262 static void panelRegister(ARegionType *region_type)
263 {
264 modifier_panel_register(region_type, eModifierType_Collision, panel_draw);
265 }
266
blendRead(BlendDataReader * UNUSED (reader),ModifierData * md)267 static void blendRead(BlendDataReader *UNUSED(reader), ModifierData *md)
268 {
269 CollisionModifierData *collmd = (CollisionModifierData *)md;
270 #if 0
271 // TODO: CollisionModifier should use pointcache
272 // + have proper reset events before enabling this
273 collmd->x = newdataadr(fd, collmd->x);
274 collmd->xnew = newdataadr(fd, collmd->xnew);
275 collmd->mfaces = newdataadr(fd, collmd->mfaces);
276
277 collmd->current_x = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_x");
278 collmd->current_xnew = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_xnew");
279 collmd->current_v = MEM_calloc_arrayN(collmd->numverts, sizeof(MVert), "current_v");
280 #endif
281
282 collmd->x = NULL;
283 collmd->xnew = NULL;
284 collmd->current_x = NULL;
285 collmd->current_xnew = NULL;
286 collmd->current_v = NULL;
287 collmd->time_x = collmd->time_xnew = -1000;
288 collmd->mvert_num = 0;
289 collmd->tri_num = 0;
290 collmd->is_static = false;
291 collmd->bvhtree = NULL;
292 collmd->tri = NULL;
293 }
294
295 ModifierTypeInfo modifierType_Collision = {
296 /* name */ "Collision",
297 /* structName */ "CollisionModifierData",
298 /* structSize */ sizeof(CollisionModifierData),
299 /* srna */ &RNA_CollisionModifier,
300 /* type */ eModifierTypeType_OnlyDeform,
301 /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_Single,
302 /* icon */ ICON_MOD_PHYSICS,
303
304 /* copyData */ NULL,
305
306 /* deformVerts */ deformVerts,
307 /* deformMatrices */ NULL,
308 /* deformVertsEM */ NULL,
309 /* deformMatricesEM */ NULL,
310 /* modifyMesh */ NULL,
311 /* modifyHair */ NULL,
312 /* modifyPointCloud */ NULL,
313 /* modifyVolume */ NULL,
314
315 /* initData */ initData,
316 /* requiredDataMask */ NULL,
317 /* freeData */ freeData,
318 /* isDisabled */ NULL,
319 /* updateDepsgraph */ updateDepsgraph,
320 /* dependsOnTime */ dependsOnTime,
321 /* dependsOnNormals */ NULL,
322 /* foreachIDLink */ NULL,
323 /* foreachTexLink */ NULL,
324 /* freeRuntimeData */ NULL,
325 /* panelRegister */ panelRegister,
326 /* blendWrite */ NULL,
327 /* blendRead */ blendRead,
328 };
329