Blender  V3.3
rigidbody_object.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2013 Blender Foundation. All rights reserved. */
3 
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include "DNA_collection_types.h"
13 #include "DNA_object_types.h"
14 #include "DNA_rigidbody_types.h"
15 #include "DNA_scene_types.h"
16 
17 #include "BLI_blenlib.h"
18 
19 #include "BLT_translation.h"
20 
21 #include "BKE_context.h"
22 #include "BKE_main.h"
23 #include "BKE_report.h"
24 #include "BKE_rigidbody.h"
25 
26 #include "DEG_depsgraph.h"
27 #include "DEG_depsgraph_build.h"
28 #include "DEG_depsgraph_query.h"
29 
30 #include "RNA_access.h"
31 #include "RNA_define.h"
32 #include "RNA_enum_types.h"
33 #include "RNA_prototypes.h"
34 
35 #include "WM_api.h"
36 #include "WM_types.h"
37 
38 #include "ED_object.h"
39 #include "ED_physics.h"
40 #include "ED_screen.h"
41 
42 #include "physics_intern.h"
43 
44 /* ********************************************** */
45 /* Helper API's for RigidBody Objects Editing */
46 
48 {
53  return false;
54  }
55  return true;
56 }
57 
59 {
62  return false;
63  }
64 
67  return (ob && ob->rigidbody_object);
68  }
69 
70  return false;
71 }
72 
74 {
77  return false;
78  }
79 
82  return (ob && ob->type == OB_MESH);
83  }
84 
85  return false;
86 }
87 
88 /* ----------------- */
89 
90 bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
91 {
92  return BKE_rigidbody_add_object(bmain, scene, ob, type, reports);
93 }
94 
96 {
97  BKE_rigidbody_remove_object(bmain, scene, ob, false);
98 
101 }
102 
103 /* ********************************************** */
104 /* Active Object Add/Remove Operators */
105 
106 /* ************ Add Rigid Body ************** */
107 
109 {
110  Main *bmain = CTX_data_main(C);
113  int type = RNA_enum_get(op->ptr, "type");
114  bool changed;
115 
116  /* apply to active object */
117  changed = ED_rigidbody_object_add(bmain, scene, ob, type, op->reports);
118 
119  if (changed) {
120  /* send updates */
123 
124  /* done */
125  return OPERATOR_FINISHED;
126  }
127  return OPERATOR_CANCELLED;
128 }
129 
131 {
132  /* identifiers */
133  ot->idname = "RIGIDBODY_OT_object_add";
134  ot->name = "Add Rigid Body";
135  ot->description = "Add active object as Rigid Body";
136 
137  /* callbacks */
140 
141  /* flags */
143 
144  /* properties */
145  ot->prop = RNA_def_enum(ot->srna,
146  "type",
149  "Rigid Body Type",
150  "");
151 }
152 
153 /* ************ Remove Rigid Body ************** */
154 
156 {
157  Main *bmain = CTX_data_main(C);
160  bool changed = false;
161 
162  /* apply to active object */
163  if (!ELEM(NULL, ob, ob->rigidbody_object)) {
164  ED_rigidbody_object_remove(bmain, scene, ob);
165  changed = true;
166  }
167 
168  if (changed) {
169  /* send updates */
172 
173  /* done */
174  return OPERATOR_FINISHED;
175  }
176 
177  BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body settings to remove");
178  return OPERATOR_CANCELLED;
179 }
180 
182 {
183  /* identifiers */
184  ot->idname = "RIGIDBODY_OT_object_remove";
185  ot->name = "Remove Rigid Body";
186  ot->description = "Remove Rigid Body settings from Object";
187 
188  /* callbacks */
191 
192  /* flags */
194 }
195 
196 /* ********************************************** */
197 /* Selected Object Add/Remove Operators */
198 
199 /* ************ Add Rigid Bodies ************** */
200 
202 {
203  Main *bmain = CTX_data_main(C);
205  int type = RNA_enum_get(op->ptr, "type");
206  bool changed = false;
207 
208  /* create rigid body objects and add them to the world's group */
209  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
210  changed |= ED_rigidbody_object_add(bmain, scene, ob, type, op->reports);
211  }
212  CTX_DATA_END;
213 
214  if (changed) {
215  /* send updates */
218 
219  /* done */
220  return OPERATOR_FINISHED;
221  }
222  return OPERATOR_CANCELLED;
223 }
224 
226 {
227  /* identifiers */
228  ot->idname = "RIGIDBODY_OT_objects_add";
229  ot->name = "Add Rigid Bodies";
230  ot->description = "Add selected objects as Rigid Bodies";
231 
232  /* callbacks */
235 
236  /* flags */
238 
239  /* properties */
240  ot->prop = RNA_def_enum(ot->srna,
241  "type",
244  "Rigid Body Type",
245  "");
246 }
247 
248 /* ************ Remove Rigid Bodies ************** */
249 
251 {
252  Main *bmain = CTX_data_main(C);
254  bool changed = false;
255 
256  /* apply this to all selected objects... */
257  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
258  if (ob->rigidbody_object) {
259  ED_rigidbody_object_remove(bmain, scene, ob);
260  changed = true;
261  }
262  }
263  CTX_DATA_END;
264 
265  if (changed) {
266  /* send updates */
269 
270  /* done */
271  return OPERATOR_FINISHED;
272  }
273  return OPERATOR_CANCELLED;
274 }
275 
277 {
278  /* identifiers */
279  ot->idname = "RIGIDBODY_OT_objects_remove";
280  ot->name = "Remove Rigid Bodies";
281  ot->description = "Remove selected objects from Rigid Body simulation";
282 
283  /* callbacks */
286 
287  /* flags */
289 }
290 
291 /* ********************************************** */
292 /* Utility Operators */
293 
294 /* ************ Change Collision Shapes ************** */
295 
297 {
298  int shape = RNA_enum_get(op->ptr, "type");
299  bool changed = false;
300 
301  /* apply this to all selected objects... */
302  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
303  if (ob->rigidbody_object) {
304  PointerRNA ptr;
305 
306  /* use RNA-system to change the property and perform all necessary changes */
307  RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr);
308  RNA_enum_set(&ptr, "collision_shape", shape);
309 
311 
312  changed = true;
313  }
314  }
315  CTX_DATA_END;
316 
317  if (changed) {
318  /* send updates */
321 
322  /* done */
323  return OPERATOR_FINISHED;
324  }
325  return OPERATOR_CANCELLED;
326 }
327 
329 {
330  /* identifiers */
331  ot->idname = "RIGIDBODY_OT_shape_change";
332  ot->name = "Change Collision Shape";
333  ot->description = "Change collision shapes for selected Rigid Body Objects";
334 
335  /* callbacks */
339 
340  /* flags */
342 
343  /* properties */
344  ot->prop = RNA_def_enum(ot->srna,
345  "type",
348  "Rigid Body Shape",
349  "");
350 }
351 
352 /* ************ Calculate Mass ************** */
353 
354 /* Entry in material density table */
355 typedef struct rbMaterialDensityItem {
356  const char *name; /* Name of material */
357  float density; /* Density (kg/m^3) */
359 
360 /* Preset density values for materials (kg/m^3)
361  * Selected values obtained from:
362  * 1) http://www.jaredzone.info/2010/09/densities.html
363  * 2) http://www.avlandesign.com/density_construction.htm
364  * 3) http://www.avlandesign.com/density_metal.htm
365  */
367  {N_("Air"), 1.0f}, /* not quite; adapted from 1.43 for oxygen for use as default */
368  {N_("Acrylic"), 1400.0f},
369  {N_("Asphalt (Crushed)"), 721.0f},
370  {N_("Bark"), 240.0f},
371  {N_("Beans (Cocoa)"), 593.0f},
372  {N_("Beans (Soy)"), 721.0f},
373  {N_("Brick (Pressed)"), 2400.0f},
374  {N_("Brick (Common)"), 2000.0f},
375  {N_("Brick (Soft)"), 1600.0f},
376  {N_("Brass"), 8216.0f},
377  {N_("Bronze"), 8860.0f},
378  {N_("Carbon (Solid)"), 2146.0f},
379  {N_("Cardboard"), 689.0f},
380  {N_("Cast Iron"), 7150.0f},
381  /* {N_("Cement"), 1442.0f}, */
382  {N_("Chalk (Solid)"), 2499.0f},
383  /* {N_("Coffee (Fresh/Roast)"), ~500}, */
384  {N_("Concrete"), 2320.0f},
385  {N_("Charcoal"), 208.0f},
386  {N_("Cork"), 240.0f},
387  {N_("Copper"), 8933.0f},
388  {N_("Garbage"), 481.0f},
389  {N_("Glass (Broken)"), 1940.0f},
390  {N_("Glass (Solid)"), 2190.0f},
391  {N_("Gold"), 19282.0f},
392  {N_("Granite (Broken)"), 1650.0f},
393  {N_("Granite (Solid)"), 2691.0f},
394  {N_("Gravel"), 2780.0f},
395  {N_("Ice (Crushed)"), 593.0f},
396  {N_("Ice (Solid)"), 919.0f},
397  {N_("Iron"), 7874.0f},
398  {N_("Lead"), 11342.0f},
399  {N_("Limestone (Broken)"), 1554.0f},
400  {N_("Limestone (Solid)"), 2611.0f},
401  {N_("Marble (Broken)"), 1570.0f},
402  {N_("Marble (Solid)"), 2563.0f},
403  {N_("Paper"), 1201.0f},
404  {N_("Peanuts (Shelled)"), 641.0f},
405  {N_("Peanuts (Not Shelled)"), 272.0f},
406  {N_("Plaster"), 849.0f},
407  {N_("Plastic"), 1200.0f},
408  {N_("Polystyrene"), 1050.0f},
409  {N_("Rubber"), 1522.0f},
410  {N_("Silver"), 10501.0f},
411  {N_("Steel"), 7860.0f},
412  {N_("Stone"), 2515.0f},
413  {N_("Stone (Crushed)"), 1602.0f},
414  {N_("Timber"), 610.0f},
415 };
417  sizeof(rbMaterialDensityItem);
418 
419 /* dynamically generate list of items
420  * - Although there is a runtime cost, this has a lower maintenance cost
421  * in the long run than other two-list solutions...
422  */
425  PropertyRNA *UNUSED(prop),
426  bool *r_free)
427 {
428  EnumPropertyItem item_tmp = {0};
429  EnumPropertyItem *item = NULL;
430  int totitem = 0;
431  int i = 0;
432 
433  /* add each preset to the list */
434  for (i = 0; i < NUM_RB_MATERIAL_PRESETS; i++) {
436 
437  item_tmp.identifier = preset->name;
438  item_tmp.name = IFACE_(preset->name);
439  item_tmp.value = i;
440  RNA_enum_item_add(&item, &totitem, &item_tmp);
441  }
442 
443  /* add special "custom" entry to the end of the list */
444  {
445  item_tmp.identifier = "Custom";
446  item_tmp.name = IFACE_("Custom");
447  item_tmp.value = -1;
448  RNA_enum_item_add(&item, &totitem, &item_tmp);
449  }
450 
451  RNA_enum_item_end(&item, &totitem);
452  *r_free = true;
453 
454  return item;
455 }
456 
457 /* ------------------------------------------ */
458 
460 {
462  int material = RNA_enum_get(op->ptr, "material");
463  float density;
464  bool changed = false;
465 
466  /* get density (kg/m^3) to apply */
467  if (material >= 0) {
468  /* get density from table, and store in props for later repeating */
470  material = 0;
471  }
472 
474  RNA_float_set(op->ptr, "density", density);
475  }
476  else {
477  /* custom - grab from whatever value is set */
478  density = RNA_float_get(op->ptr, "density");
479  }
480 
481  /* apply this to all selected objects (with rigidbodies)... */
482  CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
483  if (ob->rigidbody_object) {
484  PointerRNA ptr;
485 
486  float volume; /* m^3 */
487  float mass; /* kg */
488 
489  /* mass is calculated from the approximate volume of the object,
490  * and the density of the material we're simulating
491  */
492  Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
493  BKE_rigidbody_calc_volume(ob_eval, &volume);
494  mass = volume * density;
495 
496  /* use RNA-system to change the property and perform all necessary changes */
497  RNA_pointer_create(&ob->id, &RNA_RigidBodyObject, ob->rigidbody_object, &ptr);
498  RNA_float_set(&ptr, "mass", mass);
499 
501 
502  changed = true;
503  }
504  }
505  CTX_DATA_END;
506 
507  if (changed) {
508  /* send updates */
510 
511  /* done */
512  return OPERATOR_FINISHED;
513  }
514  return OPERATOR_CANCELLED;
515 }
516 
518  wmOperator *op,
519  const PropertyRNA *prop)
520 {
521  const char *prop_id = RNA_property_identifier(prop);
522 
523  /* Disable density input when not using the 'Custom' preset. */
524  if (STREQ(prop_id, "density")) {
525  int material = RNA_enum_get(op->ptr, "material");
526  if (material >= 0) {
528  }
529  else {
531  }
532  }
533 
534  return true;
535 }
536 
538 {
539  PropertyRNA *prop;
540 
541  /* identifiers */
542  ot->idname = "RIGIDBODY_OT_mass_calculate";
543  ot->name = "Calculate Mass";
544  ot->description = "Automatically calculate mass values for Rigid Body Objects based on volume";
545 
546  /* callbacks */
547  ot->invoke = WM_menu_invoke; /* XXX */
551 
552  /* flags */
554 
555  /* properties */
556  ot->prop = prop = RNA_def_enum(
557  ot->srna,
558  "material",
560  0,
561  "Material Preset",
562  "Type of material that objects are made of (determines material density)");
565 
567  "density",
568  1.0,
569  FLT_MIN,
570  FLT_MAX,
571  "Density",
572  "Density value (kg/m^3), allows custom value if the 'Custom' preset is used",
573  1.0f,
574  2500.0f);
575 }
576 
577 /* ********************************************** */
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:269
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
#define CTX_DATA_END
Definition: BKE_context.h:278
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
API for Blender-side Rigid Body stuff.
void BKE_rigidbody_remove_object(struct Main *bmain, struct Scene *scene, struct Object *ob, bool free_us)
Definition: rigidbody.c:2339
void BKE_rigidbody_calc_volume(struct Object *ob, float *r_vol)
Definition: rigidbody.c:2290
bool BKE_rigidbody_add_object(struct Main *bmain, struct Scene *scene, struct Object *ob, int type, struct ReportList *reports)
Definition: rigidbody.c:2333
#define UNUSED(x)
#define ELEM(...)
#define STREQ(a, b)
#define IFACE_(msgid)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
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:771
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
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:396
_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
@ PROP_EDITABLE
Definition: RNA_types.h:189
@ PROP_ENUM_NO_TRANSLATE
Definition: RNA_types.h:294
#define C
Definition: RandGen.cpp:25
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define ND_TRANSFORM
Definition: WM_types.h:405
#define ND_POINTCACHE
Definition: WM_types.h:415
#define ND_SPACE_VIEW3D
Definition: WM_types.h:471
#define NC_OBJECT
Definition: WM_types.h:329
#define NC_SPACE
Definition: WM_types.h:342
Scene scene
Material material
const Depsgraph * depsgraph
static const pxr::TfToken density("density", pxr::TfToken::Immortal)
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 operator_rigidbody_editable_poll(Scene *scene)
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:136
const char * RNA_property_identifier(const PropertyRNA *prop)
Definition: rna_access.c:1000
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4957
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
Definition: rna_access.c:4968
void RNA_enum_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:5015
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
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:3836
void RNA_enum_item_end(EnumPropertyItem **items, int *totitem)
Definition: rna_define.c:4487
void RNA_def_property_clear_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1495
void RNA_enum_item_add(EnumPropertyItem **items, int *totitem, const EnumPropertyItem *item)
Definition: rna_define.c:4436
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
void RNA_def_enum_funcs(PropertyRNA *prop, EnumPropertyItemFunc itemfunc)
Definition: rna_define.c:3830
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:3783
const EnumPropertyItem rna_enum_rigidbody_object_type_items[]
Definition: rna_rigidbody.c:29
const EnumPropertyItem rna_enum_rigidbody_object_shape_items[]
Definition: rna_rigidbody.c:44
const EnumPropertyItem DummyRNA_DEFAULT_items[]
Definition: rna_rna.c:31
const char * identifier
Definition: RNA_types.h:461
const char * name
Definition: RNA_types.h:465
Definition: BKE_main.h:121
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:919
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
bool(* poll_property)(const struct bContext *C, struct wmOperator *op, const PropertyRNA *prop) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:949
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct ReportList * reports
struct PointerRNA * ptr
#define N_(msgid)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition: wm_files.c:3480
wmOperatorType * ot
Definition: wm_files.c:3479
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))