Blender  V2.93
rigidbody_object.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) 2013 Blender Foundation
17  * All rights reserved.
18  */
19 
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "DNA_collection_types.h"
29 #include "DNA_object_types.h"
30 #include "DNA_rigidbody_types.h"
31 #include "DNA_scene_types.h"
32 
33 #include "BLI_blenlib.h"
34 
35 #include "BLT_translation.h"
36 
37 #include "BKE_context.h"
38 #include "BKE_main.h"
39 #include "BKE_report.h"
40 #include "BKE_rigidbody.h"
41 
42 #include "DEG_depsgraph.h"
43 #include "DEG_depsgraph_build.h"
44 #include "DEG_depsgraph_query.h"
45 
46 #include "RNA_access.h"
47 #include "RNA_define.h"
48 #include "RNA_enum_types.h"
49 
50 #include "WM_api.h"
51 #include "WM_types.h"
52 
53 #include "ED_object.h"
54 #include "ED_physics.h"
55 #include "ED_screen.h"
56 
57 #include "physics_intern.h"
58 
59 /* ********************************************** */
60 /* Helper API's for RigidBody Objects Editing */
61 
63 {
65  if (scene == NULL || ID_IS_LINKED(&scene->id) ||
68  return false;
69  }
70 
73  return (ob && ob->rigidbody_object);
74  }
75  return 0;
76 }
77 
79 {
81  if (scene == NULL || ID_IS_LINKED(&scene->id) ||
84  return false;
85  }
86 
89  return (ob && ob->type == OB_MESH);
90  }
91  return false;
92 }
93 
94 /* ----------------- */
95 
96 bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
97 {
98  return BKE_rigidbody_add_object(bmain, scene, ob, type, reports);
99 }
100 
102 {
103  BKE_rigidbody_remove_object(bmain, scene, ob, false);
104 
107 }
108 
109 /* ********************************************** */
110 /* Active Object Add/Remove Operators */
111 
112 /* ************ Add Rigid Body ************** */
113 
115 {
116  Main *bmain = CTX_data_main(C);
119  int type = RNA_enum_get(op->ptr, "type");
120  bool changed;
121 
122  /* apply to active object */
123  changed = ED_rigidbody_object_add(bmain, scene, ob, type, op->reports);
124 
125  if (changed) {
126  /* send updates */
129 
130  /* done */
131  return OPERATOR_FINISHED;
132  }
133  return OPERATOR_CANCELLED;
134 }
135 
137 {
138  /* identifiers */
139  ot->idname = "RIGIDBODY_OT_object_add";
140  ot->name = "Add Rigid Body";
141  ot->description = "Add active object as Rigid Body";
142 
143  /* callbacks */
146 
147  /* flags */
149 
150  /* properties */
151  ot->prop = RNA_def_enum(ot->srna,
152  "type",
155  "Rigid Body Type",
156  "");
157 }
158 
159 /* ************ Remove Rigid Body ************** */
160 
162 {
163  Main *bmain = CTX_data_main(C);
166  bool changed = false;
167 
168  /* apply to active object */
169  if (!ELEM(NULL, ob, ob->rigidbody_object)) {
170  ED_rigidbody_object_remove(bmain, scene, ob);
171  changed = true;
172  }
173 
174  if (changed) {
175  /* send updates */
178 
179  /* done */
180  return OPERATOR_FINISHED;
181  }
182 
183  BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body settings to remove");
184  return OPERATOR_CANCELLED;
185 }
186 
188 {
189  /* identifiers */
190  ot->idname = "RIGIDBODY_OT_object_remove";
191  ot->name = "Remove Rigid Body";
192  ot->description = "Remove Rigid Body settings from Object";
193 
194  /* callbacks */
197 
198  /* flags */
200 }
201 
202 /* ********************************************** */
203 /* Selected Object Add/Remove Operators */
204 
205 /* ************ Add Rigid Bodies ************** */
206 
208 {
209  Main *bmain = CTX_data_main(C);
211  int type = RNA_enum_get(op->ptr, "type");
212  bool changed = false;
213 
214  /* create rigid body objects and add them to the world's group */
215  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
216  changed |= ED_rigidbody_object_add(bmain, scene, ob, type, op->reports);
217  }
218  CTX_DATA_END;
219 
220  if (changed) {
221  /* send updates */
224 
225  /* done */
226  return OPERATOR_FINISHED;
227  }
228  return OPERATOR_CANCELLED;
229 }
230 
232 {
233  /* identifiers */
234  ot->idname = "RIGIDBODY_OT_objects_add";
235  ot->name = "Add Rigid Bodies";
236  ot->description = "Add selected objects as Rigid Bodies";
237 
238  /* callbacks */
241 
242  /* flags */
244 
245  /* properties */
246  ot->prop = RNA_def_enum(ot->srna,
247  "type",
250  "Rigid Body Type",
251  "");
252 }
253 
254 /* ************ Remove Rigid Bodies ************** */
255 
257 {
258  Main *bmain = CTX_data_main(C);
260  bool changed = false;
261 
262  /* apply this to all selected objects... */
263  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
264  if (ob->rigidbody_object) {
265  ED_rigidbody_object_remove(bmain, scene, ob);
266  changed = true;
267  }
268  }
269  CTX_DATA_END;
270 
271  if (changed) {
272  /* send updates */
275 
276  /* done */
277  return OPERATOR_FINISHED;
278  }
279  return OPERATOR_CANCELLED;
280 }
281 
283 {
284  /* identifiers */
285  ot->idname = "RIGIDBODY_OT_objects_remove";
286  ot->name = "Remove Rigid Bodies";
287  ot->description = "Remove selected objects from Rigid Body simulation";
288 
289  /* callbacks */
292 
293  /* flags */
295 }
296 
297 /* ********************************************** */
298 /* Utility Operators */
299 
300 /* ************ Change Collision Shapes ************** */
301 
303 {
304  int shape = RNA_enum_get(op->ptr, "type");
305  bool changed = false;
306 
307  /* apply this to all selected objects... */
308  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
309  if (ob->rigidbody_object) {
310  PointerRNA ptr;
311 
312  /* use RNA-system to change the property and perform all necessary changes */
313  RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr);
314  RNA_enum_set(&ptr, "collision_shape", shape);
315 
317 
318  changed = true;
319  }
320  }
321  CTX_DATA_END;
322 
323  if (changed) {
324  /* send updates */
327 
328  /* done */
329  return OPERATOR_FINISHED;
330  }
331  return OPERATOR_CANCELLED;
332 }
333 
335 {
336  /* identifiers */
337  ot->idname = "RIGIDBODY_OT_shape_change";
338  ot->name = "Change Collision Shape";
339  ot->description = "Change collision shapes for selected Rigid Body Objects";
340 
341  /* callbacks */
345 
346  /* flags */
348 
349  /* properties */
350  ot->prop = RNA_def_enum(ot->srna,
351  "type",
354  "Rigid Body Shape",
355  "");
356 }
357 
358 /* ************ Calculate Mass ************** */
359 
360 /* Entry in material density table */
361 typedef struct rbMaterialDensityItem {
362  const char *name; /* Name of material */
363  float density; /* Density (kg/m^3) */
365 
366 /* Preset density values for materials (kg/m^3)
367  * Selected values obtained from:
368  * 1) http://www.jaredzone.info/2010/09/densities.html
369  * 2) http://www.avlandesign.com/density_construction.htm
370  * 3) http://www.avlandesign.com/density_metal.htm
371  */
373  {N_("Air"), 1.0f}, /* not quite; adapted from 1.43 for oxygen for use as default */
374  {N_("Acrylic"), 1400.0f},
375  {N_("Asphalt (Crushed)"), 721.0f},
376  {N_("Bark"), 240.0f},
377  {N_("Beans (Cocoa)"), 593.0f},
378  {N_("Beans (Soy)"), 721.0f},
379  {N_("Brick (Pressed)"), 2400.0f},
380  {N_("Brick (Common)"), 2000.0f},
381  {N_("Brick (Soft)"), 1600.0f},
382  {N_("Brass"), 8216.0f},
383  {N_("Bronze"), 8860.0f},
384  {N_("Carbon (Solid)"), 2146.0f},
385  {N_("Cardboard"), 689.0f},
386  {N_("Cast Iron"), 7150.0f},
387  /* {N_("Cement"), 1442.0f}, */
388  {N_("Chalk (Solid)"), 2499.0f},
389  /* {N_("Coffee (Fresh/Roast)"), ~500}, */
390  {N_("Concrete"), 2320.0f},
391  {N_("Charcoal"), 208.0f},
392  {N_("Cork"), 240.0f},
393  {N_("Copper"), 8933.0f},
394  {N_("Garbage"), 481.0f},
395  {N_("Glass (Broken)"), 1940.0f},
396  {N_("Glass (Solid)"), 2190.0f},
397  {N_("Gold"), 19282.0f},
398  {N_("Granite (Broken)"), 1650.0f},
399  {N_("Granite (Solid)"), 2691.0f},
400  {N_("Gravel"), 2780.0f},
401  {N_("Ice (Crushed)"), 593.0f},
402  {N_("Ice (Solid)"), 919.0f},
403  {N_("Iron"), 7874.0f},
404  {N_("Lead"), 11342.0f},
405  {N_("Limestone (Broken)"), 1554.0f},
406  {N_("Limestone (Solid)"), 2611.0f},
407  {N_("Marble (Broken)"), 1570.0f},
408  {N_("Marble (Solid)"), 2563.0f},
409  {N_("Paper"), 1201.0f},
410  {N_("Peanuts (Shelled)"), 641.0f},
411  {N_("Peanuts (Not Shelled)"), 272.0f},
412  {N_("Plaster"), 849.0f},
413  {N_("Plastic"), 1200.0f},
414  {N_("Polystyrene"), 1050.0f},
415  {N_("Rubber"), 1522.0f},
416  {N_("Silver"), 10501.0f},
417  {N_("Steel"), 7860.0f},
418  {N_("Stone"), 2515.0f},
419  {N_("Stone (Crushed)"), 1602.0f},
420  {N_("Timber"), 610.0f},
421 };
423  sizeof(rbMaterialDensityItem);
424 
425 /* dynamically generate list of items
426  * - Although there is a runtime cost, this has a lower maintenance cost
427  * in the long run than other two-list solutions...
428  */
431  PropertyRNA *UNUSED(prop),
432  bool *r_free)
433 {
434  EnumPropertyItem item_tmp = {0};
435  EnumPropertyItem *item = NULL;
436  int totitem = 0;
437  int i = 0;
438 
439  /* add each preset to the list */
440  for (i = 0; i < NUM_RB_MATERIAL_PRESETS; i++) {
442 
443  item_tmp.identifier = preset->name;
444  item_tmp.name = IFACE_(preset->name);
445  item_tmp.value = i;
446  RNA_enum_item_add(&item, &totitem, &item_tmp);
447  }
448 
449  /* add special "custom" entry to the end of the list */
450  {
451  item_tmp.identifier = "Custom";
452  item_tmp.name = IFACE_("Custom");
453  item_tmp.value = -1;
454  RNA_enum_item_add(&item, &totitem, &item_tmp);
455  }
456 
457  RNA_enum_item_end(&item, &totitem);
458  *r_free = true;
459 
460  return item;
461 }
462 
463 /* ------------------------------------------ */
464 
466 {
468  int material = RNA_enum_get(op->ptr, "material");
469  float density;
470  bool changed = false;
471 
472  /* get density (kg/m^3) to apply */
473  if (material >= 0) {
474  /* get density from table, and store in props for later repeating */
476  material = 0;
477  }
478 
480  RNA_float_set(op->ptr, "density", density);
481  }
482  else {
483  /* custom - grab from whatever value is set */
484  density = RNA_float_get(op->ptr, "density");
485  }
486 
487  /* apply this to all selected objects (with rigidbodies)... */
488  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
489  if (ob->rigidbody_object) {
490  PointerRNA ptr;
491 
492  float volume; /* m^3 */
493  float mass; /* kg */
494 
495  /* mass is calculated from the approximate volume of the object,
496  * and the density of the material we're simulating
497  */
498  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
499  BKE_rigidbody_calc_volume(ob_eval, &volume);
500  mass = volume * density;
501 
502  /* use RNA-system to change the property and perform all necessary changes */
503  RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr);
504  RNA_float_set(&ptr, "mass", mass);
505 
507 
508  changed = true;
509  }
510  }
511  CTX_DATA_END;
512 
513  if (changed) {
514  /* send updates */
516 
517  /* done */
518  return OPERATOR_FINISHED;
519  }
520  return OPERATOR_CANCELLED;
521 }
522 
524  wmOperator *op,
525  const PropertyRNA *prop)
526 {
527  const char *prop_id = RNA_property_identifier(prop);
528 
529  /* Disable density input when not using the 'Custom' preset. */
530  if (STREQ(prop_id, "density")) {
531  int material = RNA_enum_get(op->ptr, "material");
532  if (material >= 0) {
534  }
535  else {
537  }
538  }
539 
540  return true;
541 }
542 
544 {
545  PropertyRNA *prop;
546 
547  /* identifiers */
548  ot->idname = "RIGIDBODY_OT_mass_calculate";
549  ot->name = "Calculate Mass";
550  ot->description = "Automatically calculate mass values for Rigid Body Objects based on volume";
551 
552  /* callbacks */
553  ot->invoke = WM_menu_invoke; /* XXX */
557 
558  /* flags */
560 
561  /* properties */
562  ot->prop = prop = RNA_def_enum(
563  ot->srna,
564  "material",
566  0,
567  "Material Preset",
568  "Type of material that objects are made of (determines material density)");
571 
573  "density",
574  1.0,
575  FLT_MIN,
576  FLT_MAX,
577  "Density",
578  "Density value (kg/m^3), allows custom value if the 'Custom' preset is used",
579  1.0f,
580  2500.0f);
581 }
582 
583 /* ********************************************** */
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:252
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
#define CTX_DATA_END
Definition: BKE_context.h:260
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
API for Blender-side Rigid Body stuff.
void BKE_rigidbody_remove_object(struct Main *bmain, struct Scene *scene, struct Object *ob, const bool free_us)
Definition: rigidbody.c:2322
void BKE_rigidbody_calc_volume(struct Object *ob, float *r_vol)
Definition: rigidbody.c:2273
bool BKE_rigidbody_add_object(struct Main *bmain, struct Scene *scene, struct Object *ob, int type, struct ReportList *reports)
Definition: rigidbody.c:2316
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
#define IFACE_(msgid)
#define N_(msgid)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:599
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:426
Object groups, one object can be in many groups at once.
Object is a sort of wrapper for general info.
@ OB_MESH
Types and defines for representing Rigid Body entities.
@ RBO_TYPE_ACTIVE
@ RB_SHAPE_TRIMESH
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
struct Object * ED_object_active_context(const struct bContext *C)
bool ED_operator_object_active_editable(struct bContext *C)
Definition: screen_ops.c:366
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
StructRNA RNA_RigidBodyObject
@ PROP_EDITABLE
Definition: RNA_types.h:175
@ PROP_ENUM_NO_TRANSLATE
Definition: RNA_types.h:279
#define C
Definition: RandGen.cpp:39
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_TRANSFORM
Definition: WM_types.h:357
#define ND_POINTCACHE
Definition: WM_types.h:367
#define ND_SPACE_VIEW3D
Definition: WM_types.h:423
#define NC_OBJECT
Definition: WM_types.h:280
#define NC_SPACE
Definition: WM_types.h:293
Scene scene
Material material
const Depsgraph * depsgraph
static int rigidbody_objects_shape_change_exec(bContext *C, wmOperator *op)
void RIGIDBODY_OT_object_remove(wmOperatorType *ot)
static const int NUM_RB_MATERIAL_PRESETS
void RIGIDBODY_OT_shape_change(wmOperatorType *ot)
struct rbMaterialDensityItem rbMaterialDensityItem
static bool mass_calculate_poll_property(const bContext *UNUSED(C), wmOperator *op, const PropertyRNA *prop)
static bool ED_operator_rigidbody_active_poll(bContext *C)
static int rigidbody_objects_calc_mass_exec(bContext *C, wmOperator *op)
void RIGIDBODY_OT_object_add(wmOperatorType *ot)
void RIGIDBODY_OT_mass_calculate(wmOperatorType *ot)
static int rigidbody_objects_add_exec(bContext *C, wmOperator *op)
void RIGIDBODY_OT_objects_remove(wmOperatorType *ot)
static const EnumPropertyItem * rigidbody_materials_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free)
void RIGIDBODY_OT_objects_add(wmOperatorType *ot)
static rbMaterialDensityItem RB_MATERIAL_DENSITY_TABLE[]
static int rigidbody_objects_remove_exec(bContext *C, wmOperator *UNUSED(op))
static bool ED_operator_rigidbody_add_poll(bContext *C)
static int rigidbody_object_add_exec(bContext *C, wmOperator *op)
void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)
static int rigidbody_object_remove_exec(bContext *C, wmOperator *op)
bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:146
const char * RNA_property_identifier(const PropertyRNA *prop)
Definition: rna_access.c:1145
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6355
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:6366
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:6413
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3825
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
Definition: rna_define.c:4470
void RNA_def_property_clear_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1517
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
Definition: rna_define.c:4416
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1512
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3819
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
const EnumPropertyItem rna_enum_rigidbody_object_type_items[]
Definition: rna_rigidbody.c:43
const EnumPropertyItem rna_enum_rigidbody_object_shape_items[]
Definition: rna_rigidbody.c:58
const EnumPropertyItem DummyRNA_DEFAULT_items[]
Definition: rna_rna.c:45
const char * identifier
Definition: RNA_types.h:446
const char * name
Definition: RNA_types.h:450
Definition: BKE_main.h:116
struct RigidBodyOb * rigidbody_object
struct Collection * group
struct RigidBodyWorld * rigidbody_world
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
bool(* poll_property)(const struct bContext *C, struct wmOperator *op, const PropertyRNA *prop) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:782
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct ReportList * reports
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: wm_operators.c:982