Fix #34040: Moving Normal Node with enabled Cycles Material Preview crashes
[blender.git] / source / blender / editors / physics / rigidbody_object.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2013 Blender Foundation
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Joshua Leung, Sergej Reich
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file rigidbody_object.c
29  *  \ingroup editor_physics
30  *  \brief Rigid Body object editing operators
31  */
32
33 #include <stdlib.h>
34 #include <string.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "DNA_group_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_mesh_types.h"
41 #include "DNA_rigidbody_types.h"
42 #include "DNA_scene_types.h"
43
44 #include "BLI_blenlib.h"
45 #include "BLI_math.h"
46
47 #include "BKE_context.h"
48 #include "BKE_depsgraph.h"
49 #include "BKE_global.h"
50 #include "BKE_group.h"
51 #include "BKE_object.h"
52 #include "BKE_report.h"
53 #include "BKE_rigidbody.h"
54
55 #include "RNA_access.h"
56 #include "RNA_define.h"
57 #include "RNA_enum_types.h"
58
59 #include "WM_api.h"
60 #include "WM_types.h"
61
62 #include "ED_physics.h"
63 #include "ED_screen.h"
64
65 #include "physics_intern.h"
66
67 /* ********************************************** */
68 /* Helper API's for RigidBody Objects Editing */
69
70 static int ED_operator_rigidbody_active_poll(bContext *C)
71 {
72         if (ED_operator_object_active_editable(C)) {
73                 Object *ob = CTX_data_active_object(C);
74                 return (ob && ob->rigidbody_object);
75         }
76         else
77                 return 0;
78 }
79
80 static int ED_operator_rigidbody_add_poll(bContext *C)
81 {
82         if (ED_operator_object_active_editable(C)) {
83                 Object *ob = CTX_data_active_object(C);
84                 return (ob && ob->type == OB_MESH);
85         }
86         else
87                 return 0;
88 }
89
90 /* ----------------- */
91
92 void ED_rigidbody_ob_add(wmOperator *op, Scene *scene, Object *ob, int type)
93 {
94         RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
95
96         /* check that object doesn't already belong to the current simulation */
97         if (ob->rigidbody_object) {
98                 BKE_reportf(op->reports, RPT_INFO, "Object '%s' already has a Rigid Body", ob->id.name + 2);
99                 return;
100         }
101         if (ob->type != OB_MESH) {
102                 BKE_report(op->reports, RPT_ERROR, "Can't add Rigid Body to non mesh object");
103                 return;
104         }
105         if (((Mesh *)ob->data)->totpoly == 0) {
106                 BKE_report(op->reports, RPT_ERROR, "Can't create Rigid Body from mesh with no polygons");
107                 return;
108         }
109
110         /* Add rigid body world and group if they don't exist for convenience */
111         if (rbw == NULL) {
112                 rbw = BKE_rigidbody_create_world(scene);
113                 BKE_rigidbody_validate_sim_world(scene, rbw, false);
114                 scene->rigidbody_world = rbw;
115         }
116         if (rbw->group == NULL) {
117                 rbw->group = add_group(G.main, "RigidBodyWorld");
118         }
119
120         /* make rigidbody object settings */
121         ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, type);
122         ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE;
123
124         /* add object to rigid body group */
125         add_to_group(rbw->group, ob, scene, NULL);
126 }
127
128 void ED_rigidbody_ob_remove(Scene *scene, Object *ob)
129 {
130         RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
131
132         BKE_rigidbody_remove_object(scene, ob);
133         if (rbw)
134                 rem_from_group(rbw->group, ob, scene, NULL);
135
136         DAG_id_tag_update(&ob->id, OB_RECALC_OB);
137 }
138
139 /* ********************************************** */
140 /* Active Object Add/Remove Operators */
141
142 /* ************ Add Rigid Body ************** */
143
144 static int rigidbody_ob_add_exec(bContext *C, wmOperator *op)
145 {
146         Scene *scene = CTX_data_scene(C);
147         Object *ob = (scene) ? OBACT : NULL;
148         int type = RNA_enum_get(op->ptr, "type");
149
150         /* apply to active object */
151         ED_rigidbody_ob_add(op, scene, ob, type);
152
153         /* send updates */
154         DAG_ids_flush_update(CTX_data_main(C), 0);
155
156         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
157         WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
158
159         /* done */
160         return OPERATOR_FINISHED;
161 }
162
163 void RIGIDBODY_OT_object_add(wmOperatorType *ot)
164 {
165         /* identifiers */
166         ot->idname = "RIGIDBODY_OT_object_add";
167         ot->name = "Add Rigid Body";
168         ot->description = "Add active object as Rigid Body";
169
170         /* callbacks */
171         ot->exec = rigidbody_ob_add_exec;
172         ot->poll = ED_operator_rigidbody_add_poll;
173
174         /* flags */
175         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
176
177         /* properties */
178         ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_type_items, RBO_TYPE_ACTIVE, "Rigid Body Type", "");
179 }
180
181 /* ************ Remove Rigid Body ************** */
182
183 static int rigidbody_ob_remove_exec(bContext *C, wmOperator *op)
184 {
185         Scene *scene = CTX_data_scene(C);
186         Object *ob = (scene) ? OBACT : NULL;
187
188         /* sanity checks */
189         if (scene == NULL)
190                 return OPERATOR_CANCELLED;
191
192         /* apply to active object */
193         if (ELEM(NULL, ob, ob->rigidbody_object)) {
194                 BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body settings to remove");
195                 return OPERATOR_CANCELLED;
196         }
197         else
198                 ED_rigidbody_ob_remove(scene, ob);
199
200         /* send updates */
201         DAG_ids_flush_update(CTX_data_main(C), 0);
202
203         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
204         WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
205
206         /* done */
207         return OPERATOR_FINISHED;
208 }
209
210 void RIGIDBODY_OT_object_remove(wmOperatorType *ot)
211 {
212         /* identifiers */
213         ot->idname = "RIGIDBODY_OT_object_remove";
214         ot->name = "Remove Rigid Body";
215         ot->description = "Remove Rigid Body settings from Object";
216
217         /* callbacks */
218         ot->exec = rigidbody_ob_remove_exec;
219         ot->poll = ED_operator_rigidbody_active_poll;
220
221         /* flags */
222         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
223 }
224
225 /* ********************************************** */
226 /* Selected Object Add/Remove Operators */
227
228 /* ************ Add Rigid Bodies ************** */
229
230 static int rigidbody_obs_add_exec(bContext *C, wmOperator *op)
231 {
232         Scene *scene = CTX_data_scene(C);
233         int type = RNA_enum_get(op->ptr, "type");
234
235         /* sanity check */
236         if (scene == NULL) {
237                 BKE_report(op->reports, RPT_ERROR, "No Scene to add Rigid Bodies to");
238                 return OPERATOR_CANCELLED;
239         }
240         /* create rigid body objects and add them to the world's group */
241         CTX_DATA_BEGIN(C, Object *, ob, selected_objects) {
242                 ED_rigidbody_ob_add(op, scene, ob, type);
243         }
244         CTX_DATA_END;
245
246         /* send updates */
247         DAG_ids_flush_update(CTX_data_main(C), 0);
248
249         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
250         WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
251
252         /* done */
253         return OPERATOR_FINISHED;
254 }
255
256 void RIGIDBODY_OT_objects_add(wmOperatorType *ot)
257 {
258         /* identifiers */
259         ot->idname = "RIGIDBODY_OT_objects_add";
260         ot->name = "Add Rigid Bodies";
261         ot->description = "Add selected objects as Rigid Bodies";
262
263         /* callbacks */
264         ot->exec = rigidbody_obs_add_exec;
265         ot->poll = ED_operator_rigidbody_add_poll;
266
267         /* flags */
268         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
269
270         /* properties */
271         ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_type_items, RBO_TYPE_ACTIVE, "Rigid Body Type", "");
272 }
273
274 /* ************ Remove Rigid Bodies ************** */
275
276 static int rigidbody_obs_remove_exec(bContext *C, wmOperator *UNUSED(op))
277 {
278         Scene *scene = CTX_data_scene(C);
279
280         /* sanity checks */
281         if (scene == NULL)
282                 return OPERATOR_CANCELLED;
283
284         /* apply this to all selected objects... */
285         CTX_DATA_BEGIN(C, Object *, ob, selected_objects)
286         {
287                 if (ob->rigidbody_object) {
288                         ED_rigidbody_ob_remove(scene, ob);
289                 }
290         }
291         CTX_DATA_END;
292
293         /* send updates */
294         DAG_ids_flush_update(CTX_data_main(C), 0);
295
296         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
297         WM_event_add_notifier(C, NC_GROUP | NA_EDITED, NULL);
298
299         /* done */
300         return OPERATOR_FINISHED;
301 }
302
303 void RIGIDBODY_OT_objects_remove(wmOperatorType *ot)
304 {
305         /* identifiers */
306         ot->idname = "RIGIDBODY_OT_objects_remove";
307         ot->name = "Remove Rigid Bodies";
308         ot->description = "Remove selected objects from Rigid Body simulation";
309
310         /* callbacks */
311         ot->exec = rigidbody_obs_remove_exec;
312         ot->poll = ED_operator_rigidbody_active_poll;
313
314         /* flags */
315         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
316 }
317
318 /* ********************************************** */
319 /* Utility Operators */
320
321 /* ************ Change Collision Shapes ************** */
322
323 static int rigidbody_obs_shape_change_exec(bContext *C, wmOperator *op)
324 {
325         Scene *scene = CTX_data_scene(C);
326         int shape = RNA_enum_get(op->ptr, "type");
327
328         /* sanity checks */
329         if (scene == NULL)
330                 return OPERATOR_CANCELLED;
331
332         /* apply this to all selected objects... */
333         CTX_DATA_BEGIN(C, Object *, ob, selected_objects)
334         {
335                 if (ob->rigidbody_object) {
336                         PointerRNA ptr;
337
338                         /* use RNA-system to change the property and perform all necessary changes */
339                         RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr);
340                         RNA_enum_set(&ptr, "collision_shape", shape);
341                 }
342         }
343         CTX_DATA_END;
344
345         /* send updates */
346         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); // XXX: wrong notifiers for now, but these also do the job...
347
348         /* done */
349         return OPERATOR_FINISHED;
350 }
351
352 void RIGIDBODY_OT_shape_change(wmOperatorType *ot)
353 {
354         /* identifiers */
355         ot->idname = "RIGIDBODY_OT_shape_change";
356         ot->name = "Change Collision Shape";
357         ot->description = "Change collision shapes for selected Rigid Body Objects";
358
359         /* callbacks */
360         ot->invoke = WM_menu_invoke;
361         ot->exec = rigidbody_obs_shape_change_exec;
362         ot->poll = ED_operator_rigidbody_active_poll;
363
364         /* flags */
365         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
366
367         /* properties */
368         ot->prop = RNA_def_enum(ot->srna, "type", rigidbody_ob_shape_items, RB_SHAPE_TRIMESH, "Rigid Body Shape", "");
369 }
370
371 /* ************ Calculate Mass ************** */
372
373 /* Entry in material density table */
374 typedef struct rbMaterialDensityItem {
375         const char *name;   /* Name of material */
376         float density;      /* Density (kg/m^3) */
377 } rbMaterialDensityItem;
378
379 /* Preset density values for materials (kg/m^3)
380  * Selected values obtained from:
381  * 1) http://www.jaredzone.info/2010/09/densities.html
382  * 2) http://www.avlandesign.com/density_construction.htm
383  * 3) http://www.avlandesign.com/density_metal.htm
384  */
385 static rbMaterialDensityItem RB_MATERIAL_DENSITY_TABLE[] = {
386         {"Air", 1.0f}, /* not quite; adapted from 1.43 for oxygen for use as default */
387         {"Acrylic", 1400.0f},
388         {"Asphalt (Crushed)", 721.0f},
389         {"Bark", 240.0f},
390         {"Beans (Cocoa)", 593.0f},
391         {"Beans (Soy)", 721.0f},
392         {"Brick (Pressed)", 2400.0f},
393         {"Brick (Common)", 2000.0f},
394         {"Brick (Soft)", 1600.0f},
395         {"Brass", 8216.0f},
396         {"Bronze", 8860.0f},
397         {"Carbon (Solid)", 2146.0f},
398         {"Cardboard", 689.0f},
399         {"Cast Iron", 7150.0f},
400         //{"Cement", 1442.0f},
401         {"Chalk (Solid)", 2499.0f},
402         //{"Coffee (Fresh/Roast)", ~500},
403         {"Concrete", 2320.0f},
404         {"Charcoal", 208.0f},
405         {"Cork", 240.0f},
406         {"Copper", 8933.0f},
407         {"Garbage", 481.0f},
408         {"Glass (Broken)", 1940.0f},
409         {"Glass (Solid)", 2190.0f},
410         {"Gold", 19282.0f},
411         {"Granite (Broken)", 1650.0f},
412         {"Granite (Solid)", 2691.0f},
413         {"Gravel", 2780.0f},
414         {"Ice (Crushed)", 593.0f},
415         {"Ice (Solid)", 919.0f},
416         {"Iron", 7874.0f},
417         {"Lead", 11342.0f},
418         {"Limestone (Broken)", 1554.0f},
419         {"Limestone (Solid)", 2611.0f},
420         {"Marble (Broken)", 1570.0f},
421         {"Marble (Solid)", 2563.0f},
422         {"Paper", 1201.0f},
423         {"Peanuts (Shelled)", 641.0f},
424         {"Peanuts (Not Shelled)", 272.0f},
425         {"Plaster", 849.0f},
426         {"Plastic", 1200.0f},
427         {"Polystyrene", 1050.0f},
428         {"Rubber", 1522.0f},
429         {"Silver", 10501.0f},
430         {"Steel", 7860.0f},
431         {"Stone", 2515.0f},
432         {"Stone (Crushed)", 1602.0f},
433         {"Timber", 610.0f}
434 };
435 static const int NUM_RB_MATERIAL_PRESETS = sizeof(RB_MATERIAL_DENSITY_TABLE) / sizeof(rbMaterialDensityItem);
436
437
438 /* dynamically generate list of items
439  * - Although there is a runtime cost, this has a lower maintenance cost
440  *       in the long run than other two-list solutions...
441  */
442 static EnumPropertyItem *rigidbody_materials_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free)
443 {
444         EnumPropertyItem item_tmp = {0};
445         EnumPropertyItem *item = NULL;
446         int totitem = 0;
447         int i = 0;
448
449         /* add each preset to the list */
450         for (i = 0; i < NUM_RB_MATERIAL_PRESETS; i++) {
451                 rbMaterialDensityItem *preset = &RB_MATERIAL_DENSITY_TABLE[i];
452
453                 item_tmp.identifier = item_tmp.name = preset->name;
454                 item_tmp.value = i;
455                 RNA_enum_item_add(&item, &totitem, &item_tmp);
456         }
457
458         /* add special "custom" entry to the end of the list */
459         {
460                 item_tmp.identifier = item_tmp.name = "Custom";
461                 item_tmp.value = -1;
462                 RNA_enum_item_add(&item, &totitem, &item_tmp);
463         }
464
465         RNA_enum_item_end(&item, &totitem);
466         *free = 1;
467
468         return item;
469 }
470
471 /* ------------------------------------------ */
472
473 /* helper function to calculate volume of rigidbody object */
474 // TODO: allow a parameter to specify method used to calculate this?
475 static float calc_rigidbody_ob_volume(Object *ob)
476 {
477         RigidBodyOb *rbo = ob->rigidbody_object;
478
479         float size[3]  = {1.0f, 1.0f, 1.0f};
480         float radius = 1.0f;
481         float height = 1.0f;
482
483         float volume = 0.0f;
484
485         /* if automatically determining dimensions, use the Object's boundbox
486          *      - assume that all quadrics are standing upright on local z-axis
487          *      - assume even distribution of mass around the Object's pivot
488          *        (i.e. Object pivot is centralised in boundbox)
489          *      - boundbox gives full width
490          */
491         // XXX: all dimensions are auto-determined now... later can add stored settings for this
492         BKE_object_dimensions_get(ob, size);
493
494         if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
495                 /* take radius as largest x/y dimension, and height as z-dimension */
496                 radius = MAX2(size[0], size[1]) * 0.5f;
497                 height = size[2];
498         }
499         else if (rbo->shape == RB_SHAPE_SPHERE) {
500                 /* take radius to the the largest dimension to try and encompass everything */
501                 radius = max_fff(size[0], size[1], size[2]) * 0.5f;
502         }
503
504         /* calculate volume as appropriate  */
505         switch (rbo->shape) {
506                 case RB_SHAPE_BOX:
507                         volume = size[0] * size[1] * size[2];
508                         break;
509
510                 case RB_SHAPE_SPHERE:
511                         volume = 4.0f / 3.0f * (float)M_PI * radius * radius * radius;
512                         break;
513
514                 /* for now, assume that capsule is close enough to a cylinder... */
515                 case RB_SHAPE_CAPSULE:
516                 case RB_SHAPE_CYLINDER:
517                         volume = (float)M_PI * radius * radius * height;
518                         break;
519
520                 case RB_SHAPE_CONE:
521                         volume = (float)M_PI / 3.0f * radius * radius * height;
522                         break;
523
524                 /* for now, all mesh shapes are just treated as boxes...
525                  * NOTE: this may overestimate the volume, but other methods are overkill
526                  */
527                 case RB_SHAPE_CONVEXH:
528                 case RB_SHAPE_TRIMESH:
529                         volume = size[0] * size[1] * size[2];
530                         break;
531
532 #if 0 // XXX: not defined yet
533                 case RB_SHAPE_COMPOUND:
534                         volume = 0.0f;
535                         break;
536 #endif
537         }
538
539         /* return the volume calculated */
540         return volume;
541 }
542
543 /* ------------------------------------------ */
544
545 static int rigidbody_obs_calc_mass_exec(bContext *C, wmOperator *op)
546 {
547         Scene *scene = CTX_data_scene(C);
548         int material = RNA_enum_get(op->ptr, "material");
549         float density;
550
551         /* sanity checks */
552         if (scene == NULL)
553                 return OPERATOR_CANCELLED;
554
555         /* get density (kg/m^3) to apply */
556         if (material >= 0) {
557                 /* get density from table, and store in props for later repeating */
558                 if (material >= NUM_RB_MATERIAL_PRESETS)
559                         material = 0;
560
561                 density = RB_MATERIAL_DENSITY_TABLE[material].density;
562                 RNA_float_set(op->ptr, "density", density);
563         }
564         else {
565                 /* custom - grab from whatever value is set */
566                 density = RNA_float_get(op->ptr, "density");
567         }
568
569         /* apply this to all selected objects (with rigidbodies)... */
570         CTX_DATA_BEGIN(C, Object *, ob, selected_objects)
571         {
572                 if (ob->rigidbody_object) {
573                         PointerRNA ptr;
574
575                         float volume; /* m^3 */
576                         float mass;   /* kg */
577
578                         /* mass is calculated from the approximate volume of the object,
579                          * and the density of the material we're simulating
580                          */
581                         volume = calc_rigidbody_ob_volume(ob);
582                         mass = volume * density;
583
584                         /* use RNA-system to change the property and perform all necessary changes */
585                         RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr);
586                         RNA_float_set(&ptr, "mass", mass);
587                 }
588         }
589         CTX_DATA_END;
590
591         /* send updates */
592         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); // XXX: wrong notifiers for now, but these also do the job...
593
594         /* done */
595         return OPERATOR_FINISHED;
596 }
597
598 void RIGIDBODY_OT_mass_calculate(wmOperatorType *ot)
599 {
600         PropertyRNA *prop;
601
602         /* identifiers */
603         ot->idname = "RIGIDBODY_OT_mass_calculate";
604         ot->name = "Calculate Mass";
605         ot->description = "Automatically calculate mass values for Rigid Body Objects based on volume";
606
607         /* callbacks */
608         ot->invoke = WM_menu_invoke; // XXX
609         ot->exec = rigidbody_obs_calc_mass_exec;
610         ot->poll = ED_operator_rigidbody_active_poll;
611
612         /* flags */
613         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
614
615         /* properties */
616         ot->prop = prop = RNA_def_enum(ot->srna, "material",
617                                        DummyRNA_DEFAULT_items, 0,
618                                        "Material Preset",
619                                        "Type of material that objects are made of (determines material density)");
620         RNA_def_enum_funcs(prop, rigidbody_materials_itemf);
621
622         RNA_def_float(ot->srna, "density", 1.0, FLT_MIN, FLT_MAX,
623                       "Density",
624                       "Custom density value (kg/m^3) to use instead of material preset",
625                       1.0f, 2500.0f);
626 }
627
628 /* ********************************************** */