Blender V4.3
rigidbody.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2013 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10#include <algorithm>
11#include <cfloat>
12#include <climits>
13#include <cmath>
14#include <cstddef>
15#include <cstdio>
16#include <cstring>
17
18#include "CLG_log.h"
19
20#include "MEM_guardedalloc.h"
21
22#include "BLI_listbase.h"
23#include "BLI_math_matrix.h"
24#include "BLI_math_rotation.h"
25#include "BLI_math_vector.h"
26
27#ifdef WITH_BULLET
28# include "RBI_api.h"
29#endif
30
31#include "DNA_ID.h"
33#include "DNA_mesh_types.h"
35#include "DNA_object_types.h"
36#include "DNA_rigidbody_types.h"
37#include "DNA_scene_types.h"
38
39#include "BKE_collection.hh"
40#include "BKE_effect.h"
41#include "BKE_global.hh"
42#include "BKE_layer.hh"
43#include "BKE_main.hh"
44#include "BKE_mesh.hh"
45#include "BKE_mesh_runtime.hh"
46#include "BKE_object.hh"
47#include "BKE_pointcache.h"
48#include "BKE_report.hh"
49#include "BKE_rigidbody.h"
50#include "BKE_scene.hh"
51#ifdef WITH_BULLET
52# include "BKE_lib_id.hh"
53# include "BKE_lib_query.hh"
54#endif
55
56#include "DEG_depsgraph.hh"
58
59#ifdef WITH_BULLET
60static CLG_LogRef LOG = {"bke.rigidbody"};
61#endif
62
63#ifndef WITH_BULLET
64/* #RBI_api.h is not included, some types still need to be declared. */
65struct rbCollisionShape;
66struct rbConstraint;
67struct rbDynamicsWorld;
68struct rbRigidBody;
69#endif /* !WITH_BULLET */
70
71/* ************************************** */
72/* Memory Management */
73
74/* Freeing Methods --------------------- */
75
76#ifdef WITH_BULLET
77static void rigidbody_update_ob_array(RigidBodyWorld *rbw);
78
79#else
80static void RB_dworld_remove_constraint(void * /*world*/, void * /*con*/) {}
81static void RB_dworld_remove_body(void * /*world*/, void * /*body*/) {}
82static void RB_dworld_delete(void * /*world*/) {}
83static void RB_body_delete(void * /*body*/) {}
84static void RB_shape_delete(void * /*shape*/) {}
85static void RB_constraint_delete(void * /*con*/) {}
86
87#endif
88
90{
91 bool is_orig = (scene->id.tag & ID_TAG_COPIED_ON_EVAL) == 0;
92 RigidBodyWorld *rbw = scene->rigidbody_world;
93 scene->rigidbody_world = nullptr;
94
95 /* sanity check */
96 if (!rbw) {
97 return;
98 }
99
100 if (is_orig && rbw->shared->physics_world) {
101 /* Free physics references,
102 * we assume that all physics objects in will have been added to the world. */
103 if (rbw->constraints) {
105 if (object->rigidbody_constraint) {
106 RigidBodyCon *rbc = object->rigidbody_constraint;
107 if (rbc->physics_constraint) {
109 static_cast<rbConstraint *>(rbc->physics_constraint));
110 }
111 }
112 }
114 }
115
116 if (rbw->group) {
118 BKE_rigidbody_free_object(object, rbw);
119 }
121 }
122 /* free dynamics world */
124 }
125 if (rbw->objects) {
126 free(rbw->objects);
127 }
128
129 if (is_orig) {
130 /* free cache */
132 rbw->shared->pointcache = nullptr;
133
134 MEM_freeN(rbw->shared);
135 }
136
137 /* free effector weights */
138 if (rbw->effector_weights) {
140 }
141
142 /* free rigidbody world itself */
143 MEM_freeN(rbw);
144}
145
147{
148 bool is_orig = (ob->id.tag & ID_TAG_COPIED_ON_EVAL) == 0;
149 RigidBodyOb *rbo = ob->rigidbody_object;
150
151 /* sanity check */
152 if (rbo == nullptr) {
153 return;
154 }
155
156 /* free physics references */
157 if (is_orig) {
158 if (rbo->shared->physics_object) {
159 if (rbw != nullptr && rbw->shared->physics_world != nullptr) {
160 /* We can only remove the body from the world if the world is known.
161 * The world is generally only unknown if it's an evaluated copy of
162 * an object that's being freed, in which case this code isn't run anyway. */
164 static_cast<rbRigidBody *>(rbo->shared->physics_object));
165 }
166 else {
167 /* We have no access to 'owner' RBW when deleting the object ID itself... No choice bu to
168 * loop over all scenes then. */
169 for (Scene *scene = static_cast<Scene *>(G_MAIN->scenes.first); scene != nullptr;
170 scene = static_cast<Scene *>(scene->id.next))
171 {
172 RigidBodyWorld *scene_rbw = scene->rigidbody_world;
173 if (scene_rbw != nullptr && scene_rbw->shared->physics_world != nullptr) {
174 RB_dworld_remove_body(static_cast<rbDynamicsWorld *>(scene_rbw->shared->physics_world),
175 static_cast<rbRigidBody *>(rbo->shared->physics_object));
176 }
177 }
178 }
179
180 RB_body_delete(static_cast<rbRigidBody *>(rbo->shared->physics_object));
181 rbo->shared->physics_object = nullptr;
182 }
183
184 if (rbo->shared->physics_shape) {
186 rbo->shared->physics_shape = nullptr;
187 }
188
189 MEM_freeN(rbo->shared);
190 }
191
192 /* free data itself */
193 MEM_freeN(rbo);
194 ob->rigidbody_object = nullptr;
195}
196
198{
199 RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : nullptr;
200
201 /* sanity check */
202 if (rbc == nullptr) {
203 return;
204 }
205
206 /* free physics reference */
207 if (rbc->physics_constraint) {
209 rbc->physics_constraint = nullptr;
210 }
211
212 /* free data itself */
213 MEM_freeN(rbc);
214 ob->rigidbody_constraint = nullptr;
215}
216
218{
219 /* Check if the object will have its transform changed by the rigidbody simulation. */
220
221 /* True if the shape of this object's parent is of type compound */
222 bool obCompoundParent = (ob->parent != nullptr && ob->parent->rigidbody_object != nullptr &&
224
225 RigidBodyOb *rbo = ob->rigidbody_object;
226 if (rbo == nullptr || rbo->flag & RBO_FLAG_KINEMATIC || rbo->type == RBO_TYPE_PASSIVE ||
227 obCompoundParent)
228 {
229 return false;
230 }
231
232 return true;
233}
234
235#ifdef WITH_BULLET
236
237/* Copying Methods --------------------- */
238
239/* These just copy the data, clearing out references to physics objects.
240 * Anything that uses them MUST verify that the copied object will
241 * be added to relevant groups later...
242 */
243
244static RigidBodyOb *rigidbody_copy_object(const Object *ob, const int flag)
245{
246 RigidBodyOb *rboN = nullptr;
247
248 if (ob->rigidbody_object) {
249 const bool is_orig = (flag & LIB_ID_COPY_SET_COPIED_ON_WRITE) == 0;
250
251 /* just duplicate the whole struct first (to catch all the settings) */
252 rboN = static_cast<RigidBodyOb *>(MEM_dupallocN(ob->rigidbody_object));
253
254 if (is_orig) {
255 /* This is a regular copy, and not an evaluated copy for depsgraph evaluation */
256 rboN->shared = static_cast<RigidBodyOb_Shared *>(
257 MEM_callocN(sizeof(*rboN->shared), "RigidBodyOb_Shared"));
258 }
259
260 /* tag object as needing to be verified */
262 }
263
264 /* return new copy of settings */
265 return rboN;
266}
267
268static RigidBodyCon *rigidbody_copy_constraint(const Object *ob, const int /*flag*/)
269{
270 RigidBodyCon *rbcN = nullptr;
271
272 if (ob->rigidbody_constraint) {
273 /* Just duplicate the whole struct first (to catch all the settings). */
274 rbcN = static_cast<RigidBodyCon *>(MEM_dupallocN(ob->rigidbody_constraint));
275
276 /* Tag object as needing to be verified. */
278
279 /* Clear out all the fields which need to be re-validated later. */
280 rbcN->physics_constraint = nullptr;
281 }
282
283 /* return new copy of settings */
284 return rbcN;
285}
286
287void BKE_rigidbody_object_copy(Main *bmain, Object *ob_dst, const Object *ob_src, const int flag)
288{
289 ob_dst->rigidbody_object = rigidbody_copy_object(ob_src, flag);
290 ob_dst->rigidbody_constraint = rigidbody_copy_constraint(ob_src, flag);
291
293 return;
294 }
295
296 /* We have to ensure that duplicated object ends up in relevant rigidbody collections...
297 * Otherwise duplicating the RB data itself is meaningless. */
298 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
299 RigidBodyWorld *rigidbody_world = scene->rigidbody_world;
300
301 if (rigidbody_world != nullptr) {
302 bool need_objects_update = false;
303 bool need_constraints_update = false;
304
305 if (ob_dst->rigidbody_object) {
306 if (BKE_collection_has_object(rigidbody_world->group, ob_src)) {
307 BKE_collection_object_add(bmain, rigidbody_world->group, ob_dst);
308 need_objects_update = true;
309 }
310 }
311 if (ob_dst->rigidbody_constraint) {
312 if (BKE_collection_has_object(rigidbody_world->constraints, ob_src)) {
313 BKE_collection_object_add(bmain, rigidbody_world->constraints, ob_dst);
314 need_constraints_update = true;
315 }
316 }
317
318 if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0 &&
319 (need_objects_update || need_constraints_update))
320 {
321 BKE_rigidbody_cache_reset(rigidbody_world);
322
324 if (need_objects_update) {
326 }
327 if (need_constraints_update) {
329 }
331 }
332 }
333 }
334}
335
336/* ************************************** */
337/* Setup Utilities - Validate Sim Instances */
338
339/* get the appropriate evaluated mesh based on rigid body mesh source */
340static const Mesh *rigidbody_get_mesh(Object *ob)
341{
342 BLI_assert(ob->type == OB_MESH);
343
344 switch (ob->rigidbody_object->mesh_source) {
345 case RBO_MESH_DEFORM:
347 case RBO_MESH_FINAL:
349 case RBO_MESH_BASE:
350 /* This mesh may be used for computing corner_tris, which should be done
351 * on the original; otherwise every time the evaluated copy is recreated it will
352 * have to be recomputed. */
354 return (Mesh *)ob->runtime->data_orig;
355 }
356
357 /* Just return something sensible so that at least Blender won't crash. */
358 BLI_assert_msg(0, "Unknown mesh source");
360}
361
362/* create collision shape of mesh - convex hull */
363static rbCollisionShape *rigidbody_get_shape_convexhull_from_mesh(Object *ob,
364 float margin,
365 bool *can_embed)
366{
367 rbCollisionShape *shape = nullptr;
368 const Mesh *mesh = nullptr;
369 const float(*positions)[3] = nullptr;
370 int totvert = 0;
371
372 if (ob->type == OB_MESH && ob->data) {
373 mesh = rigidbody_get_mesh(ob);
374 positions = (mesh) ? reinterpret_cast<const float(*)[3]>(mesh->vert_positions().data()) :
375 nullptr;
376 totvert = (mesh) ? mesh->verts_num : 0;
377 }
378 else {
379 CLOG_ERROR(&LOG, "cannot make Convex Hull collision shape for non-Mesh object");
380 }
381
382 if (totvert) {
384 (float *)positions, sizeof(float[3]), totvert, margin, can_embed);
385 }
386 else {
387 CLOG_ERROR(&LOG, "no vertices to define Convex Hull collision shape with");
388 }
389
390 return shape;
391}
392
393/* create collision shape of mesh - triangulated mesh
394 * returns nullptr if creation fails.
395 */
396static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
397{
398 rbCollisionShape *shape = nullptr;
399
400 if (ob->type == OB_MESH) {
401 const Mesh *mesh = rigidbody_get_mesh(ob);
402 if (mesh == nullptr) {
403 return nullptr;
404 }
405
406 const blender::Span<blender::float3> positions = mesh->vert_positions();
407 const int totvert = mesh->verts_num;
408 const blender::Span<blender::int3> corner_tris = mesh->corner_tris();
409 const int tottri = corner_tris.size();
410 const blender::Span<int> corner_verts = mesh->corner_verts();
411
412 /* sanity checking - potential case when no data will be present */
413 if ((totvert == 0) || (tottri == 0)) {
414 CLOG_WARN(
415 &LOG, "no geometry data converted for Mesh Collision Shape (ob = %s)", ob->id.name + 2);
416 }
417 else {
418 rbMeshData *mdata;
419 int i;
420
421 /* init mesh data for collision shape */
422 mdata = RB_trimesh_data_new(tottri, totvert);
423
424 RB_trimesh_add_vertices(mdata, (float *)positions.data(), totvert, sizeof(float[3]));
425
426 /* loop over all faces, adding them as triangles to the collision shape
427 * (so for some faces, more than triangle will get added)
428 */
429 if (positions.data()) {
430 for (i = 0; i < tottri; i++) {
431 /* add first triangle - verts 1,2,3 */
432 const blender::int3 &tri = corner_tris[i];
433 int vtri[3];
434
435 vtri[0] = corner_verts[tri[0]];
436 vtri[1] = corner_verts[tri[1]];
437 vtri[2] = corner_verts[tri[2]];
438
440 }
441 }
442
443 RB_trimesh_finish(mdata);
444
445 /* construct collision shape
446 *
447 * These have been chosen to get better speed/accuracy tradeoffs with regards
448 * to limitations of each:
449 * - BVH-Triangle Mesh: for passive objects only. Despite having greater
450 * speed/accuracy, they cannot be used for moving objects.
451 * - GImpact Mesh: for active objects. These are slower and less stable,
452 * but are more flexible for general usage.
453 */
455 shape = RB_shape_new_trimesh(mdata);
456 }
457 else {
458 shape = RB_shape_new_gimpact_mesh(mdata);
459 }
460 }
461 }
462 else {
463 CLOG_ERROR(&LOG, "cannot make Triangular Mesh collision shape for non-Mesh object");
464 }
465
466 return shape;
467}
468
469/* Helper function to create physics collision shape for object.
470 * Returns a new collision shape.
471 */
472static rbCollisionShape *rigidbody_validate_sim_shape_helper(RigidBodyWorld *rbw, Object *ob)
473{
474 RigidBodyOb *rbo = ob->rigidbody_object;
475 rbCollisionShape *new_shape = nullptr;
476 float size[3] = {1.0f, 1.0f, 1.0f};
477 float radius = 1.0f;
478 float height = 1.0f;
479 float capsule_height;
480 float hull_margin = 0.0f;
481 bool can_embed = true;
482 bool has_volume;
483
484 /* sanity check */
485 if (rbo == nullptr) {
486 return nullptr;
487 }
488
489 /* if automatically determining dimensions, use the Object's boundbox
490 * - assume that all quadrics are standing upright on local z-axis
491 * - assume even distribution of mass around the Object's pivot
492 * (i.e. Object pivot is centralized in boundbox)
493 */
494 /* XXX: all dimensions are auto-determined now... later can add stored settings for this */
495 /* get object dimensions without scaling */
496 if (const std::optional<blender::Bounds<blender::float3>> bounds = BKE_object_boundbox_get(ob)) {
497 copy_v3_v3(size, bounds->max - bounds->min);
498 }
499 mul_v3_fl(size, 0.5f);
500
502 /* take radius as largest x/y dimension, and height as z-dimension */
503 radius = std::max(size[0], size[1]);
504 height = size[2];
505 }
506 else if (rbo->shape == RB_SHAPE_SPHERE) {
507 /* take radius to the largest dimension to try and encompass everything */
508 radius = std::max({size[0], size[1], size[2]});
509 }
510
511 /* create new shape */
512 switch (rbo->shape) {
513 case RB_SHAPE_BOX:
514 new_shape = RB_shape_new_box(size[0], size[1], size[2]);
515 break;
516
517 case RB_SHAPE_SPHERE:
518 new_shape = RB_shape_new_sphere(radius);
519 break;
520
521 case RB_SHAPE_CAPSULE:
522 capsule_height = (height - radius) * 2.0f;
523 new_shape = RB_shape_new_capsule(radius, (capsule_height > 0.0f) ? capsule_height : 0.0f);
524 break;
526 new_shape = RB_shape_new_cylinder(radius, height);
527 break;
528 case RB_SHAPE_CONE:
529 new_shape = RB_shape_new_cone(radius, height * 2.0f);
530 break;
531
532 case RB_SHAPE_CONVEXH:
533 /* try to embed collision margin */
534 has_volume = (std::min({size[0], size[1], size[2]}) > 0.0f);
535
536 if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && has_volume) {
537 hull_margin = 0.04f;
538 }
539 new_shape = rigidbody_get_shape_convexhull_from_mesh(ob, hull_margin, &can_embed);
540 if (!(rbo->flag & RBO_FLAG_USE_MARGIN)) {
541 rbo->margin = (can_embed && has_volume) ?
542 0.04f :
543 0.0f; /* RB_TODO ideally we shouldn't directly change the margin here */
544 }
545 break;
546 case RB_SHAPE_TRIMESH:
547 new_shape = rigidbody_get_shape_trimesh_from_mesh(ob);
548 break;
550 new_shape = RB_shape_new_compound();
551 rbCollisionShape *childShape = nullptr;
552 float loc[3], rot[4];
553 float mat[4][4];
554 /* Add children to the compound shape */
556 if (childObject->parent == ob) {
557 childShape = rigidbody_validate_sim_shape_helper(rbw, childObject);
558 if (childShape) {
559 BKE_object_matrix_local_get(childObject, mat);
560 mat4_to_loc_quat(loc, rot, mat);
561 RB_compound_add_child_shape(new_shape, childShape, loc, rot);
562 }
563 }
564 }
566
567 break;
568 }
569 /* use box shape if it failed to create new shape */
570 if (new_shape == nullptr) {
571 new_shape = RB_shape_new_box(size[0], size[1], size[2]);
572 }
573 if (new_shape) {
574 RB_shape_set_margin(new_shape, RBO_GET_MARGIN(rbo));
575 }
576
577 return new_shape;
578}
579
580/* Create new physics sim collision shape for object and store it,
581 * or remove the existing one first and replace...
582 */
583static void rigidbody_validate_sim_shape(RigidBodyWorld *rbw, Object *ob, bool rebuild)
584{
585 RigidBodyOb *rbo = ob->rigidbody_object;
586 rbCollisionShape *new_shape = nullptr;
587
588 /* sanity check */
589 if (rbo == nullptr) {
590 return;
591 }
592
593 /* don't create a new shape if we already have one and don't want to rebuild it */
594 if (rbo->shared->physics_shape && !rebuild) {
595 return;
596 }
597
598 /* Also don't create a shape if this object is parent of a compound shape */
599 if (ob->parent != nullptr && ob->parent->rigidbody_object != nullptr &&
601 {
602 return;
603 }
604
605 new_shape = rigidbody_validate_sim_shape_helper(rbw, ob);
606
607 /* assign new collision shape if creation was successful */
608 if (new_shape) {
609 if (rbo->shared->physics_shape) {
611 }
612 rbo->shared->physics_shape = new_shape;
613 }
614}
615
616/* --------------------- */
617
618void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
619{
620 RigidBodyOb *rbo = ob->rigidbody_object;
621
622 float size[3] = {1.0f, 1.0f, 1.0f};
623 float radius = 1.0f;
624 float height = 1.0f;
625
626 float volume = 0.0f;
627
628 /* if automatically determining dimensions, use the Object's boundbox
629 * - assume that all quadrics are standing upright on local z-axis
630 * - assume even distribution of mass around the Object's pivot
631 * (i.e. Object pivot is centralized in boundbox)
632 * - boundbox gives full width
633 */
634 /* XXX: all dimensions are auto-determined now... later can add stored settings for this */
636
638 /* take radius as largest x/y dimension, and height as z-dimension */
639 radius = std::max(size[0], size[1]) * 0.5f;
640 height = size[2];
641 }
642 else if (rbo->shape == RB_SHAPE_SPHERE) {
643 /* take radius to the largest dimension to try and encompass everything */
644 radius = max_fff(size[0], size[1], size[2]) * 0.5f;
645 }
646
647 /* Calculate volume as appropriate. */
648 switch (rbo->shape) {
649 case RB_SHAPE_BOX:
650 volume = size[0] * size[1] * size[2];
651 break;
652
653 case RB_SHAPE_SPHERE:
654 volume = 4.0f / 3.0f * float(M_PI) * radius * radius * radius;
655 break;
656
657 /* for now, assume that capsule is close enough to a cylinder... */
658 case RB_SHAPE_CAPSULE:
660 volume = float(M_PI) * radius * radius * height;
661 break;
662
663 case RB_SHAPE_CONE:
664 volume = float(M_PI) / 3.0f * radius * radius * height;
665 break;
666
667 case RB_SHAPE_CONVEXH:
668 case RB_SHAPE_TRIMESH: {
669 if (ob->type == OB_MESH) {
670 const Mesh *mesh = rigidbody_get_mesh(ob);
671 if (mesh == nullptr) {
672 return;
673 }
674
675 const blender::Span<blender::float3> positions = mesh->vert_positions();
676 const blender::Span<blender::int3> corner_tris = mesh->corner_tris();
677 const blender::Span<int> corner_verts = mesh->corner_verts();
678
679 if (!positions.is_empty() && !corner_tris.is_empty()) {
680 BKE_mesh_calc_volume(reinterpret_cast<const float(*)[3]>(positions.data()),
681 positions.size(),
682 corner_tris.data(),
683 corner_tris.size(),
684 corner_verts.data(),
685 &volume,
686 nullptr);
687 const float volume_scale = mat4_to_volume_scale(ob->object_to_world().ptr());
688 volume *= fabsf(volume_scale);
689 }
690 }
691 else {
692 /* rough estimate from boundbox as fallback */
693 /* XXX could implement other types of geometry here (curves, etc.) */
694 volume = size[0] * size[1] * size[2];
695 }
696 break;
697 }
698 }
699
700 /* return the volume calculated */
701 if (r_vol) {
702 *r_vol = volume;
703 }
704}
705
706void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3])
707{
708 RigidBodyOb *rbo = ob->rigidbody_object;
709
710 float size[3] = {1.0f, 1.0f, 1.0f};
711 float height = 1.0f;
712
713 zero_v3(r_center);
714
715 /* if automatically determining dimensions, use the Object's boundbox
716 * - assume that all quadrics are standing upright on local z-axis
717 * - assume even distribution of mass around the Object's pivot
718 * (i.e. Object pivot is centralized in boundbox)
719 * - boundbox gives full width
720 */
721 /* XXX: all dimensions are auto-determined now... later can add stored settings for this. */
723
724 /* Calculate volume as appropriate. */
725 switch (rbo->shape) {
726 case RB_SHAPE_BOX:
727 case RB_SHAPE_SPHERE:
728 case RB_SHAPE_CAPSULE:
730 break;
731
732 case RB_SHAPE_CONE:
733 /* take radius as largest x/y dimension, and height as z-dimension */
734 height = size[2];
735 /* cone is geometrically centered on the median,
736 * center of mass is 1/4 up from the base
737 */
738 r_center[2] = -0.25f * height;
739 break;
740
741 case RB_SHAPE_CONVEXH:
742 case RB_SHAPE_TRIMESH: {
743 if (ob->type == OB_MESH) {
744 const Mesh *mesh = rigidbody_get_mesh(ob);
745 if (mesh == nullptr) {
746 return;
747 }
748
749 const blender::Span<blender::float3> positions = mesh->vert_positions();
750 const blender::Span<blender::int3> corner_tris = mesh->corner_tris();
751
752 if (!positions.is_empty() && !corner_tris.is_empty()) {
753 BKE_mesh_calc_volume(reinterpret_cast<const float(*)[3]>(positions.data()),
754 positions.size(),
755 corner_tris.data(),
756 corner_tris.size(),
757 mesh->corner_verts().data(),
758 nullptr,
759 r_center);
760 }
761 }
762 break;
763 }
764 }
765}
766
767/* --------------------- */
768
774static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool rebuild)
775{
776 RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : nullptr;
777 float loc[3];
778 float rot[4];
779
780 /* sanity checks:
781 * - object doesn't have RigidBody info already: then why is it here?
782 */
783 if (rbo == nullptr) {
784 return;
785 }
786
787 /* make sure collision shape exists */
788 /* FIXME we shouldn't always have to rebuild collision shapes when rebuilding objects,
789 * but it's needed for constraints to update correctly. */
790 if (rbo->shared->physics_shape == nullptr || rebuild) {
791 rigidbody_validate_sim_shape(rbw, ob, true);
792 }
793
794 if (rbo->shared->physics_object && !rebuild) {
795 /* Don't remove body on rebuild as it has already been removed when deleting and rebuilding the
796 * world. */
798 static_cast<rbRigidBody *>(rbo->shared->physics_object));
799 }
800 if (!rbo->shared->physics_object || rebuild) {
801 /* remove rigid body if it already exists before creating a new one */
802 if (rbo->shared->physics_object) {
803 RB_body_delete(static_cast<rbRigidBody *>(rbo->shared->physics_object));
804 rbo->shared->physics_object = nullptr;
805 }
806 /* Don't create rigid body object if the parent is a compound shape */
807 if (ob->parent != nullptr && ob->parent->rigidbody_object != nullptr &&
809 {
810 return;
811 }
812
813 mat4_to_loc_quat(loc, rot, ob->object_to_world().ptr());
814
816 static_cast<rbCollisionShape *>(rbo->shared->physics_shape), loc, rot);
817
820 rbo->restitution);
821
823 rbo->lin_damping,
824 rbo->ang_damping);
826 rbo->lin_sleep_thresh,
827 rbo->ang_sleep_thresh);
830
833 }
834
836 (ob->protectflag & OB_LOCK_LOCX) == 0,
837 (ob->protectflag & OB_LOCK_LOCY) == 0,
838 (ob->protectflag & OB_LOCK_LOCZ) == 0);
840 (ob->protectflag & OB_LOCK_ROTX) == 0,
841 (ob->protectflag & OB_LOCK_ROTY) == 0,
842 (ob->protectflag & OB_LOCK_ROTZ) == 0);
843
847 }
848
849 if (rbw && rbw->shared->physics_world && rbo->shared->physics_object) {
851 static_cast<rbRigidBody *>(rbo->shared->physics_object),
852 rbo->col_groups);
853 }
854}
855
856/* --------------------- */
857
858static void rigidbody_constraint_init_spring(RigidBodyCon *rbc,
859 void (*set_spring)(rbConstraint *, int, int),
860 void (*set_stiffness)(rbConstraint *, int, float),
861 void (*set_damping)(rbConstraint *, int, float))
862{
863 set_spring(static_cast<rbConstraint *>(rbc->physics_constraint),
866 set_stiffness(static_cast<rbConstraint *>(rbc->physics_constraint),
868 rbc->spring_stiffness_x);
869 set_damping(
871
872 set_spring(static_cast<rbConstraint *>(rbc->physics_constraint),
875 set_stiffness(static_cast<rbConstraint *>(rbc->physics_constraint),
877 rbc->spring_stiffness_y);
878 set_damping(
880
881 set_spring(static_cast<rbConstraint *>(rbc->physics_constraint),
884 set_stiffness(static_cast<rbConstraint *>(rbc->physics_constraint),
886 rbc->spring_stiffness_z);
887 set_damping(
889
890 set_spring(static_cast<rbConstraint *>(rbc->physics_constraint),
893 set_stiffness(static_cast<rbConstraint *>(rbc->physics_constraint),
896 set_damping(static_cast<rbConstraint *>(rbc->physics_constraint),
899
900 set_spring(static_cast<rbConstraint *>(rbc->physics_constraint),
903 set_stiffness(static_cast<rbConstraint *>(rbc->physics_constraint),
906 set_damping(static_cast<rbConstraint *>(rbc->physics_constraint),
909
910 set_spring(static_cast<rbConstraint *>(rbc->physics_constraint),
913 set_stiffness(static_cast<rbConstraint *>(rbc->physics_constraint),
916 set_damping(static_cast<rbConstraint *>(rbc->physics_constraint),
919}
920
921static void rigidbody_constraint_set_limits(RigidBodyCon *rbc,
922 void (*set_limits)(rbConstraint *, int, float, float))
923{
924 if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) {
925 set_limits(static_cast<rbConstraint *>(rbc->physics_constraint),
928 rbc->limit_lin_x_upper);
929 }
930 else {
931 set_limits(static_cast<rbConstraint *>(rbc->physics_constraint), RB_LIMIT_LIN_X, 0.0f, -1.0f);
932 }
933
934 if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Y) {
935 set_limits(static_cast<rbConstraint *>(rbc->physics_constraint),
938 rbc->limit_lin_y_upper);
939 }
940 else {
941 set_limits(static_cast<rbConstraint *>(rbc->physics_constraint), RB_LIMIT_LIN_Y, 0.0f, -1.0f);
942 }
943
944 if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Z) {
945 set_limits(static_cast<rbConstraint *>(rbc->physics_constraint),
948 rbc->limit_lin_z_upper);
949 }
950 else {
951 set_limits(static_cast<rbConstraint *>(rbc->physics_constraint), RB_LIMIT_LIN_Z, 0.0f, -1.0f);
952 }
953
954 if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X) {
955 set_limits(static_cast<rbConstraint *>(rbc->physics_constraint),
958 rbc->limit_ang_x_upper);
959 }
960 else {
961 set_limits(static_cast<rbConstraint *>(rbc->physics_constraint), RB_LIMIT_ANG_X, 0.0f, -1.0f);
962 }
963
964 if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Y) {
965 set_limits(static_cast<rbConstraint *>(rbc->physics_constraint),
968 rbc->limit_ang_y_upper);
969 }
970 else {
971 set_limits(static_cast<rbConstraint *>(rbc->physics_constraint), RB_LIMIT_ANG_Y, 0.0f, -1.0f);
972 }
973
974 if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z) {
975 set_limits(static_cast<rbConstraint *>(rbc->physics_constraint),
978 rbc->limit_ang_z_upper);
979 }
980 else {
981 set_limits(static_cast<rbConstraint *>(rbc->physics_constraint), RB_LIMIT_ANG_Z, 0.0f, -1.0f);
982 }
983}
984
990static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, bool rebuild)
991{
992 RigidBodyCon *rbc = (ob) ? ob->rigidbody_constraint : nullptr;
993 float loc[3];
994 float rot[4];
995 float lin_lower;
996 float lin_upper;
997 float ang_lower;
998 float ang_upper;
999
1000 /* sanity checks:
1001 * - object should have a rigid body constraint
1002 * - rigid body constraint should have at least one constrained object
1003 */
1004 if (rbc == nullptr) {
1005 return;
1006 }
1007
1008 if (ELEM(nullptr, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) {
1009 if (rbc->physics_constraint) {
1011 static_cast<rbConstraint *>(rbc->physics_constraint));
1013 rbc->physics_constraint = nullptr;
1014 }
1015 return;
1016 }
1017
1018 if (rbc->physics_constraint && rebuild == false) {
1020 static_cast<rbConstraint *>(rbc->physics_constraint));
1021 }
1022 if (rbc->physics_constraint == nullptr || rebuild) {
1023 rbRigidBody *rb1 = static_cast<rbRigidBody *>(
1025 rbRigidBody *rb2 = static_cast<rbRigidBody *>(
1027
1028 /* remove constraint if it already exists before creating a new one */
1029 if (rbc->physics_constraint) {
1031 rbc->physics_constraint = nullptr;
1032 }
1033
1034 mat4_to_loc_quat(loc, rot, ob->object_to_world().ptr());
1035
1036 if (rb1 && rb2) {
1037 switch (rbc->type) {
1038 case RBC_TYPE_POINT:
1039 rbc->physics_constraint = RB_constraint_new_point(loc, rb1, rb2);
1040 break;
1041 case RBC_TYPE_FIXED:
1042 rbc->physics_constraint = RB_constraint_new_fixed(loc, rot, rb1, rb2);
1043 break;
1044 case RBC_TYPE_HINGE:
1045 rbc->physics_constraint = RB_constraint_new_hinge(loc, rot, rb1, rb2);
1046 if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z) {
1048 rbc->limit_ang_z_lower,
1049 rbc->limit_ang_z_upper);
1050 }
1051 else {
1053 static_cast<rbConstraint *>(rbc->physics_constraint), 0.0f, -1.0f);
1054 }
1055 break;
1056 case RBC_TYPE_SLIDER:
1057 rbc->physics_constraint = RB_constraint_new_slider(loc, rot, rb1, rb2);
1058 if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) {
1060 rbc->limit_lin_x_lower,
1061 rbc->limit_lin_x_upper);
1062 }
1063 else {
1065 static_cast<rbConstraint *>(rbc->physics_constraint), 0.0f, -1.0f);
1066 }
1067 break;
1068 case RBC_TYPE_PISTON:
1069 rbc->physics_constraint = RB_constraint_new_piston(loc, rot, rb1, rb2);
1070 if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X) {
1071 lin_lower = rbc->limit_lin_x_lower;
1072 lin_upper = rbc->limit_lin_x_upper;
1073 }
1074 else {
1075 lin_lower = 0.0f;
1076 lin_upper = -1.0f;
1077 }
1078 if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X) {
1079 ang_lower = rbc->limit_ang_x_lower;
1080 ang_upper = rbc->limit_ang_x_upper;
1081 }
1082 else {
1083 ang_lower = 0.0f;
1084 ang_upper = -1.0f;
1085 }
1087 lin_lower,
1088 lin_upper,
1089 ang_lower,
1090 ang_upper);
1091 break;
1093 if (rbc->spring_type == RBC_SPRING_TYPE2) {
1095
1096 rigidbody_constraint_init_spring(rbc,
1100
1102 static_cast<rbConstraint *>(rbc->physics_constraint));
1103
1104 rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof_spring2);
1105 }
1106 else {
1108
1109 rigidbody_constraint_init_spring(rbc,
1113
1115 static_cast<rbConstraint *>(rbc->physics_constraint));
1116
1117 rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof);
1118 }
1119 break;
1120 case RBC_TYPE_6DOF:
1121 rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2);
1122
1123 rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof);
1124 break;
1125 case RBC_TYPE_MOTOR:
1126 rbc->physics_constraint = RB_constraint_new_motor(loc, rot, rb1, rb2);
1127
1135 static_cast<rbConstraint *>(rbc->physics_constraint),
1138 break;
1139 }
1140 }
1141 else { /* can't create constraint without both rigid bodies */
1142 return;
1143 }
1144
1145 /* When 'rbc->type' is unknown. */
1146 if (rbc->physics_constraint == nullptr) {
1147 return;
1148 }
1149
1151 rbc->flag & RBC_FLAG_ENABLED);
1152
1153 if (rbc->flag & RBC_FLAG_USE_BREAKING) {
1155 rbc->breaking_threshold);
1156 }
1157 else {
1159 FLT_MAX);
1160 }
1161
1165 }
1166 else {
1168 -1);
1169 }
1170 }
1171
1172 if (rbw && rbw->shared->physics_world && rbc->physics_constraint) {
1174 static_cast<rbConstraint *>(rbc->physics_constraint),
1176 }
1177}
1178
1179/* --------------------- */
1180
1181void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild)
1182{
1183 /* sanity checks */
1184 if (rbw == nullptr) {
1185 return;
1186 }
1187
1188 /* create new sim world */
1189 if (rebuild || rbw->shared->physics_world == nullptr) {
1190 if (rbw->shared->physics_world) {
1192 }
1193 rbw->shared->physics_world = RB_dworld_new(scene->physics_settings.gravity);
1194 }
1195
1200}
1201
1202/* ************************************** */
1203/* Setup Utilities - Create Settings Blocks */
1204
1206{
1207 /* try to get whatever RigidBody world that might be representing this already */
1208 RigidBodyWorld *rbw;
1209
1210 /* sanity checks
1211 * - there must be a valid scene to add world to
1212 * - there mustn't be a sim world using this group already
1213 */
1214 if (scene == nullptr) {
1215 return nullptr;
1216 }
1217
1218 /* create a new sim world */
1219 rbw = static_cast<RigidBodyWorld *>(MEM_callocN(sizeof(RigidBodyWorld), "RigidBodyWorld"));
1220 rbw->shared = static_cast<RigidBodyWorld_Shared *>(
1221 MEM_callocN(sizeof(*rbw->shared), "RigidBodyWorld_Shared"));
1222
1223 /* set default settings */
1225
1226 rbw->ltime = PSFRA;
1227
1228 rbw->time_scale = 1.0f;
1229
1230 /* Most high quality Bullet example files has an internal frame-rate of 240hz.
1231 * The blender default scene has a frame rate of 24, so take 10 sub-steps (24fps * 10). */
1232 rbw->substeps_per_frame = 10;
1233 rbw->num_solver_iterations = 10; /* 10 is bullet default */
1234
1236 rbw->shared->pointcache->step = 1;
1237
1238 /* return this sim world */
1239 return rbw;
1240}
1241
1243{
1244 RigidBodyWorld *rbw_copy = static_cast<RigidBodyWorld *>(MEM_dupallocN(rbw));
1245
1246 if (rbw->effector_weights) {
1247 rbw_copy->effector_weights = static_cast<EffectorWeights *>(
1249 if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
1251 }
1252 }
1253 if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
1254 id_us_plus((ID *)rbw_copy->group);
1255 id_us_plus((ID *)rbw_copy->constraints);
1256 }
1257
1259 /* This is a regular copy, and not an evaluated copy for depsgraph evaluation. */
1260 rbw_copy->shared = static_cast<RigidBodyWorld_Shared *>(
1261 MEM_callocN(sizeof(*rbw_copy->shared), "RigidBodyWorld_Shared"));
1263 rbw_copy->shared->pointcache = static_cast<PointCache *>(rbw_copy->shared->ptcaches.first);
1264 }
1265
1266 rbw_copy->objects = nullptr;
1267 rbw_copy->numbodies = 0;
1268 rigidbody_update_ob_array(rbw_copy);
1269
1270 return rbw_copy;
1271}
1272
1274{
1275 ID_NEW_REMAP(rbw->group);
1278}
1279
1281{
1282 func(rbw, (ID **)&rbw->group, userdata, IDWALK_CB_USER);
1283 func(rbw, (ID **)&rbw->constraints, userdata, IDWALK_CB_USER);
1284 func(rbw, (ID **)&rbw->effector_weights->group, userdata, IDWALK_CB_USER);
1285
1286 if (rbw->objects) {
1287 int i;
1288 for (i = 0; i < rbw->numbodies; i++) {
1289 func(rbw, (ID **)&rbw->objects[i], userdata, IDWALK_CB_NOP);
1290 }
1291 }
1292}
1293
1294RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
1295{
1296 RigidBodyOb *rbo;
1297 RigidBodyWorld *rbw = scene->rigidbody_world;
1298
1299 /* sanity checks
1300 * - rigidbody world must exist
1301 * - object must exist
1302 * - cannot add rigid body if it already exists
1303 */
1304 if (ob == nullptr) {
1305 return nullptr;
1306 }
1307 if (ob->rigidbody_object != nullptr) {
1308 return ob->rigidbody_object;
1309 }
1310
1311 /* create new settings data, and link it up */
1312 rbo = static_cast<RigidBodyOb *>(MEM_callocN(sizeof(RigidBodyOb), "RigidBodyOb"));
1313 rbo->shared = static_cast<RigidBodyOb_Shared *>(
1314 MEM_callocN(sizeof(*rbo->shared), "RigidBodyOb_Shared"));
1315
1316 /* set default settings */
1317 rbo->type = type;
1318
1319 rbo->mass = 1.0f;
1320
1321 rbo->friction = 0.5f; /* best when non-zero. 0.5 is Bullet default */
1322 rbo->restitution = 0.0f; /* best when zero. 0.0 is Bullet default */
1323
1324 rbo->margin = 0.04f; /* 0.04 (in meters) is Bullet default */
1325
1326 rbo->lin_sleep_thresh = 0.4f; /* 0.4 is half of Bullet default */
1327 rbo->ang_sleep_thresh = 0.5f; /* 0.5 is half of Bullet default */
1328
1329 rbo->lin_damping = 0.04f;
1330 rbo->ang_damping = 0.1f;
1331
1332 rbo->col_groups = 1;
1333
1334 /* use triangle meshes for passive objects
1335 * use convex hulls for active objects since dynamic triangle meshes are very unstable
1336 */
1337 if (type == RBO_TYPE_ACTIVE) {
1338 rbo->shape = RB_SHAPE_CONVEXH;
1339 }
1340 else {
1341 rbo->shape = RB_SHAPE_TRIMESH;
1342 }
1343
1345
1346 /* set initial transform */
1347 mat4_to_loc_quat(rbo->pos, rbo->orn, ob->object_to_world().ptr());
1348
1349 /* flag cache as outdated */
1352
1353 /* return this object */
1354 return rbo;
1355}
1356
1358{
1359 RigidBodyCon *rbc;
1360 RigidBodyWorld *rbw = scene->rigidbody_world;
1361
1362 /* sanity checks
1363 * - rigidbody world must exist
1364 * - object must exist
1365 * - cannot add constraint if it already exists
1366 */
1367 if (ob == nullptr || (ob->rigidbody_constraint != nullptr)) {
1368 return nullptr;
1369 }
1370
1371 /* create new settings data, and link it up */
1372 rbc = static_cast<RigidBodyCon *>(MEM_callocN(sizeof(RigidBodyCon), "RigidBodyCon"));
1373
1374 /* set default settings */
1375 rbc->type = type;
1376
1377 rbc->ob1 = nullptr;
1378 rbc->ob2 = nullptr;
1379
1380 rbc->flag |= RBC_FLAG_ENABLED;
1383
1385
1386 rbc->breaking_threshold = 10.0f; /* no good default here, just use 10 for now */
1387 rbc->num_solver_iterations = 10; /* 10 is Bullet default */
1388
1389 rbc->limit_lin_x_lower = -1.0f;
1390 rbc->limit_lin_x_upper = 1.0f;
1391 rbc->limit_lin_y_lower = -1.0f;
1392 rbc->limit_lin_y_upper = 1.0f;
1393 rbc->limit_lin_z_lower = -1.0f;
1394 rbc->limit_lin_z_upper = 1.0f;
1395 rbc->limit_ang_x_lower = -M_PI_4;
1397 rbc->limit_ang_y_lower = -M_PI_4;
1399 rbc->limit_ang_z_lower = -M_PI_4;
1401
1402 rbc->spring_damping_x = 0.5f;
1403 rbc->spring_damping_y = 0.5f;
1404 rbc->spring_damping_z = 0.5f;
1405 rbc->spring_damping_ang_x = 0.5f;
1406 rbc->spring_damping_ang_y = 0.5f;
1407 rbc->spring_damping_ang_z = 0.5f;
1408 rbc->spring_stiffness_x = 10.0f;
1409 rbc->spring_stiffness_y = 10.0f;
1410 rbc->spring_stiffness_z = 10.0f;
1411 rbc->spring_stiffness_ang_x = 10.0f;
1412 rbc->spring_stiffness_ang_y = 10.0f;
1413 rbc->spring_stiffness_ang_z = 10.0f;
1414
1415 rbc->motor_lin_max_impulse = 1.0f;
1416 rbc->motor_lin_target_velocity = 1.0f;
1417 rbc->motor_ang_max_impulse = 1.0f;
1418 rbc->motor_ang_target_velocity = 1.0f;
1419
1420 /* flag cache as outdated */
1422
1423 /* return this object */
1424 return rbc;
1425}
1426
1428{
1429 if (rbw->group != nullptr) {
1431 if (object->type != OB_MESH || object->rigidbody_object != nullptr) {
1432 continue;
1433 }
1434 object->rigidbody_object = BKE_rigidbody_create_object(scene, object, RBO_TYPE_ACTIVE);
1436 }
1439 }
1440}
1441
1443{
1444 if (rbw->constraints != nullptr) {
1446 if (object->rigidbody_constraint != nullptr) {
1447 continue;
1448 }
1449 object->rigidbody_constraint = BKE_rigidbody_create_constraint(
1450 scene, object, RBC_TYPE_FIXED);
1451 }
1453 }
1454}
1455
1456void BKE_rigidbody_main_collection_object_add(Main *bmain, Collection *collection, Object *object)
1457{
1458 for (Scene *scene = static_cast<Scene *>(bmain->scenes.first); scene;
1459 scene = static_cast<Scene *>(scene->id.next))
1460 {
1461 RigidBodyWorld *rbw = scene->rigidbody_world;
1462
1463 if (rbw == nullptr) {
1464 continue;
1465 }
1466
1467 if (rbw->group == collection && object->type == OB_MESH && object->rigidbody_object == nullptr)
1468 {
1469 object->rigidbody_object = BKE_rigidbody_create_object(scene, object, RBO_TYPE_ACTIVE);
1470 }
1471 if (rbw->constraints == collection && object->rigidbody_constraint == nullptr) {
1472 object->rigidbody_constraint = BKE_rigidbody_create_constraint(
1473 scene, object, RBC_TYPE_FIXED);
1474 }
1475 }
1476}
1477
1478/* ************************************** */
1479/* Utilities API */
1480
1482{
1483 /* sanity check */
1484 if (scene == nullptr) {
1485 return nullptr;
1486 }
1487
1488 return scene->rigidbody_world;
1489}
1490
1491static bool rigidbody_add_object_to_scene(Main *bmain, Scene *scene, Object *ob)
1492{
1493 /* Add rigid body world and group if they don't exist for convenience */
1495 if (rbw == nullptr) {
1496 rbw = BKE_rigidbody_create_world(scene);
1497 if (rbw == nullptr) {
1498 return false;
1499 }
1500
1501 BKE_rigidbody_validate_sim_world(scene, rbw, false);
1502 scene->rigidbody_world = rbw;
1503 }
1504
1505 if (rbw->group == nullptr) {
1506 rbw->group = BKE_collection_add(bmain, nullptr, "RigidBodyWorld");
1507 id_us_plus(&rbw->group->id);
1508 }
1509
1510 /* Add object to rigid body group. */
1511 BKE_collection_object_add(bmain, rbw->group, ob);
1513
1516
1517 return true;
1518}
1519
1520static bool rigidbody_add_constraint_to_scene(Main *bmain, Scene *scene, Object *ob)
1521{
1522 /* Add rigid body world and group if they don't exist for convenience */
1524 if (rbw == nullptr) {
1525 rbw = BKE_rigidbody_create_world(scene);
1526 if (rbw == nullptr) {
1527 return false;
1528 }
1529
1530 BKE_rigidbody_validate_sim_world(scene, rbw, false);
1531 scene->rigidbody_world = rbw;
1532 }
1533
1534 if (rbw->constraints == nullptr) {
1535 rbw->constraints = BKE_collection_add(bmain, nullptr, "RigidBodyConstraints");
1536 id_us_plus(&rbw->constraints->id);
1537 }
1538
1539 /* Add object to rigid body group. */
1540 BKE_collection_object_add(bmain, rbw->constraints, ob);
1542
1545
1546 return true;
1547}
1548
1550{
1551 if (ob->rigidbody_object != nullptr) {
1552 /* Add newly local object to scene. */
1553 for (Scene *scene = static_cast<Scene *>(bmain->scenes.first); scene;
1554 scene = static_cast<Scene *>(scene->id.next))
1555 {
1556 if (BKE_scene_object_find(scene, ob)) {
1557 rigidbody_add_object_to_scene(bmain, scene, ob);
1558 }
1559 }
1560 }
1561 if (ob->rigidbody_constraint != nullptr) {
1562 /* Add newly local object to scene. */
1563 for (Scene *scene = static_cast<Scene *>(bmain->scenes.first); scene;
1564 scene = static_cast<Scene *>(scene->id.next))
1565 {
1566 if (BKE_scene_object_find(scene, ob)) {
1567 rigidbody_add_constraint_to_scene(bmain, scene, ob);
1568 }
1569 }
1570 }
1571}
1572
1573bool BKE_rigidbody_add_object(Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
1574{
1575 if (ob->type != OB_MESH) {
1576 BKE_report(reports, RPT_ERROR, "Can't add Rigid Body to non mesh object");
1577 return false;
1578 }
1579
1580 /* Add object to rigid body world in scene. */
1581 if (!rigidbody_add_object_to_scene(bmain, scene, ob)) {
1582 BKE_report(reports, RPT_ERROR, "Can't create Rigid Body world");
1583 return false;
1584 }
1585
1586 /* make rigidbody object settings */
1587 if (ob->rigidbody_object == nullptr) {
1588 ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, type);
1589 }
1590 ob->rigidbody_object->type = type;
1592
1595
1596 return true;
1597}
1598
1599void BKE_rigidbody_remove_object(Main *bmain, Scene *scene, Object *ob, const bool free_us)
1600{
1601 RigidBodyWorld *rbw = scene->rigidbody_world;
1602 RigidBodyCon *rbc;
1603 int i;
1604
1605 if (rbw) {
1606
1607 /* remove object from array */
1608 if (rbw->objects) {
1609 for (i = 0; i < rbw->numbodies; i++) {
1610 if (rbw->objects[i] == ob) {
1611 rbw->objects[i] = nullptr;
1612 break;
1613 }
1614 }
1615 }
1616
1617 /* remove object from rigid body constraints */
1618 if (rbw->constraints) {
1620 if (obt && obt->rigidbody_constraint) {
1621 rbc = obt->rigidbody_constraint;
1622 if (rbc->ob1 == ob) {
1623 rbc->ob1 = nullptr;
1625 }
1626 if (rbc->ob2 == ob) {
1627 rbc->ob2 = nullptr;
1629 }
1630 }
1631 }
1633 }
1634
1635 /* Relying on user-count of the object should be OK, and it is much cheaper than looping in all
1636 * collections to check whether the object is already in another one... */
1637 if (ID_REAL_USERS(&ob->id) == 1) {
1638 /* Some users seems to find it funny to use a view-layer instancing collection
1639 * as RBW collection... Despite this being a bad (ab)use of the system, avoid losing objects
1640 * when we remove them from RB simulation. */
1641 BKE_collection_object_add(bmain, scene->master_collection, ob);
1642 }
1643 if (rbw->group) {
1644 BKE_collection_object_remove(bmain, rbw->group, ob, free_us);
1646 }
1647
1648 /* flag cache as outdated */
1650 /* Reset cache as the object order probably changed after freeing the object. */
1651 PTCacheID pid;
1652 BKE_ptcache_id_from_rigidbody(&pid, nullptr, rbw);
1654 }
1655
1656 /* remove object's settings */
1658
1659 /* Dependency graph update */
1662}
1663
1664void BKE_rigidbody_remove_constraint(Main *bmain, Scene *scene, Object *ob, const bool free_us)
1665{
1666 RigidBodyWorld *rbw = scene->rigidbody_world;
1668
1669 if (rbw != nullptr) {
1670 /* Remove from RBW constraints collection. */
1671 if (rbw->constraints != nullptr) {
1672 BKE_collection_object_remove(bmain, rbw->constraints, ob, free_us);
1674 }
1675
1676 /* remove from rigidbody world, free object won't do this */
1677 if (rbw->shared->physics_world && rbc->physics_constraint) {
1679 static_cast<rbConstraint *>(rbc->physics_constraint));
1680 }
1681 }
1682
1683 /* remove object's settings */
1685
1686 /* flag cache as outdated */
1688}
1689
1690/* ************************************** */
1691/* Simulation Interface - Bullet */
1692
1693/* Update object array and rigid body count so they're in sync with the rigid body group */
1694static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
1695{
1696 if (rbw->group == nullptr) {
1697 rbw->numbodies = 0;
1698 rbw->objects = static_cast<Object **>(realloc(rbw->objects, 0));
1699 return;
1700 }
1701
1702 int n = 0;
1704 (void)object;
1705 /* Ignore if this object is the direct child of an object with a compound shape */
1706 if (object->parent == nullptr || object->parent->rigidbody_object == nullptr ||
1707 object->parent->rigidbody_object->shape != RB_SHAPE_COMPOUND)
1708 {
1709 n++;
1710 }
1711 }
1713
1714 if (rbw->numbodies != n) {
1715 rbw->numbodies = n;
1716 rbw->objects = static_cast<Object **>(
1717 realloc(rbw->objects, sizeof(Object *) * rbw->numbodies));
1718 }
1719
1720 int i = 0;
1722 /* Ignore if this object is the direct child of an object with a compound shape */
1723 if (object->parent == nullptr || object->parent->rigidbody_object == nullptr ||
1724 object->parent->rigidbody_object->shape != RB_SHAPE_COMPOUND)
1725 {
1726 rbw->objects[i] = object;
1727 i++;
1728 }
1729 }
1731}
1732
1733static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw)
1734{
1735 float adj_gravity[3];
1736
1737 /* adjust gravity to take effector weights into account */
1738 if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
1739 copy_v3_v3(adj_gravity, scene->physics_settings.gravity);
1740 mul_v3_fl(adj_gravity,
1742 }
1743 else {
1744 zero_v3(adj_gravity);
1745 }
1746
1747 /* update gravity, since this RNA setting is not part of RigidBody settings */
1748 RB_dworld_set_gravity(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world), adj_gravity);
1749
1750 /* update object array in case there are changes */
1751 rigidbody_update_ob_array(rbw);
1752}
1753
1754static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Object *ob, RigidBodyOb *rbo)
1755{
1756 /* only update if rigid body exists */
1757 if (rbo->shared->physics_object == nullptr) {
1758 return;
1759 }
1760
1761 const Scene *scene = DEG_get_input_scene(depsgraph);
1763 BKE_view_layer_synced_ensure(scene, view_layer);
1764 Base *base = BKE_view_layer_base_find(view_layer, ob);
1765 const bool is_selected = base ? (base->flag & BASE_SELECTED) != 0 : false;
1766
1767 if (rbo->shape == RB_SHAPE_TRIMESH && rbo->flag & RBO_FLAG_USE_DEFORM) {
1768 const Mesh *mesh = BKE_object_get_mesh_deform_eval(ob);
1769 if (mesh) {
1770 const float(*positions)[3] = reinterpret_cast<const float(*)[3]>(
1771 mesh->vert_positions().data());
1772 int totvert = mesh->verts_num;
1773 const std::optional<blender::Bounds<blender::float3>> bounds = BKE_object_boundbox_get(ob);
1774
1776 (float *)positions,
1777 totvert,
1778 sizeof(float[3]),
1779 bounds->min,
1780 bounds->max);
1781 }
1782 }
1783
1784 if (!(rbo->flag & RBO_FLAG_KINEMATIC)) {
1785 /* update scale for all non kinematic objects */
1786 float new_scale[3], old_scale[3];
1787 mat4_to_size(new_scale, ob->object_to_world().ptr());
1788 RB_body_get_scale(static_cast<rbRigidBody *>(rbo->shared->physics_object), old_scale);
1789
1790 /* Avoid updating collision shape AABBs if scale didn't change. */
1791 if (!compare_size_v3v3(old_scale, new_scale, 0.001f)) {
1792 RB_body_set_scale(static_cast<rbRigidBody *>(rbo->shared->physics_object), new_scale);
1793 /* compensate for embedded convex hull collision margin */
1794 if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && rbo->shape == RB_SHAPE_CONVEXH) {
1796 RBO_GET_MARGIN(rbo) *
1797 std::min({new_scale[0], new_scale[1], new_scale[2]}));
1798 }
1799 }
1800 }
1801
1802 /* Make transformed objects temporarily kinematic
1803 * so that they can be moved by the user during simulation. */
1804 if (is_selected && (G.moving & G_TRANSFORM_OBJ)) {
1805 RB_body_set_kinematic_state(static_cast<rbRigidBody *>(rbo->shared->physics_object), true);
1806 RB_body_set_mass(static_cast<rbRigidBody *>(rbo->shared->physics_object), 0.0f);
1807 }
1808
1809 /* NOTE: no other settings need to be explicitly updated here,
1810 * since RNA setters take care of the rest :)
1811 */
1812}
1813
1819static void rigidbody_update_simulation(Depsgraph *depsgraph,
1820 Scene *scene,
1821 RigidBodyWorld *rbw,
1822 bool rebuild)
1823{
1824 /* update world */
1825 /* Note physics_world can get nullptr when undoing the deletion of the last object in it (see
1826 * #70667). */
1827 if (rebuild || rbw->shared->physics_world == nullptr) {
1828 BKE_rigidbody_validate_sim_world(scene, rbw, rebuild);
1829 /* We have rebuilt the world so we need to make sure the rest is rebuilt as well. */
1830 rebuild = true;
1831 }
1832
1833 rigidbody_update_sim_world(scene, rbw);
1834
1835 /* XXX TODO: For rebuild: remove all constraints first.
1836 * Otherwise we can end up deleting objects that are still
1837 * referenced by constraints, corrupting bullet's internal list.
1838 *
1839 * Memory management needs redesign here, this is just a dirty workaround.
1840 */
1841 if (rebuild && rbw->constraints) {
1844 if (rbc && rbc->physics_constraint) {
1846 static_cast<rbConstraint *>(rbc->physics_constraint));
1848 rbc->physics_constraint = nullptr;
1849 }
1850 }
1852 }
1853
1854 /* update objects */
1856 if (ob->type == OB_MESH) {
1857 /* validate that we've got valid object set up here... */
1858 RigidBodyOb *rbo = ob->rigidbody_object;
1859
1860 /* TODO: remove this whole block once we are sure we never get nullptr rbo here anymore. */
1861 /* This cannot be done in copy-on-eval evaluation context anymore... */
1862 if (rbo == nullptr) {
1864 "Evaluated object part of RBW object collection without RB object data, "
1865 "should not happen.\n");
1866 /* Since this object is included in the sim group but doesn't have
1867 * rigid body settings (perhaps it was added manually), add!
1868 * - assume object to be active? That is the default for newly added settings...
1869 */
1871 rigidbody_validate_sim_object(rbw, ob, true);
1872
1873 rbo = ob->rigidbody_object;
1874 }
1875 else {
1876 /* perform simulation data updates as tagged */
1877 /* refresh object... */
1878 if (rebuild) {
1879 /* World has been rebuilt so rebuild object */
1880 /* TODO(Sybren): rigidbody_validate_sim_object() can call rigidbody_validate_sim_shape(),
1881 * but neither resets the RBO_FLAG_NEEDS_RESHAPE flag nor
1882 * calls RB_body_set_collision_shape().
1883 * This results in the collision shape being created twice, which is unnecessary. */
1884 rigidbody_validate_sim_object(rbw, ob, true);
1885 }
1886 else if (rbo->flag & RBO_FLAG_NEEDS_VALIDATE) {
1887 rigidbody_validate_sim_object(rbw, ob, false);
1888 }
1889 /* refresh shape... */
1890 if (rbo->flag & RBO_FLAG_NEEDS_RESHAPE) {
1891 /* mesh/shape data changed, so force shape refresh */
1892 rigidbody_validate_sim_shape(rbw, ob, true);
1893 /* now tell RB sim about it */
1894 /* XXX: we assume that this can only get applied for active/passive shapes
1895 * that will be included as rigid-bodies. */
1896 if (rbo->shared->physics_object != nullptr && rbo->shared->physics_shape != nullptr) {
1898 static_cast<rbRigidBody *>(rbo->shared->physics_object),
1899 static_cast<rbCollisionShape *>(rbo->shared->physics_shape));
1900 }
1901 }
1902 }
1904
1905 /* update simulation object... */
1906 rigidbody_update_sim_ob(depsgraph, ob, rbo);
1907 }
1908 }
1910
1911 /* update constraints */
1912 if (rbw->constraints == nullptr) { /* no constraints, move on */
1913 return;
1914 }
1915
1917 /* validate that we've got valid object set up here... */
1919
1920 /* TODO: remove this whole block once we are sure we never get nullptr rbo here anymore. */
1921 /* This cannot be done in copy-on-eval evaluation context anymore... */
1922 if (rbc == nullptr) {
1924 0,
1925 "Evaluated object part of RBW constraints collection without RB constraint data, "
1926 "should not happen.\n");
1927 /* Since this object is included in the group but doesn't have
1928 * constraint settings (perhaps it was added manually), add!
1929 */
1931 rigidbody_validate_sim_constraint(rbw, ob, true);
1932
1933 rbc = ob->rigidbody_constraint;
1934 }
1935 else {
1936 /* perform simulation data updates as tagged */
1937 if (rebuild) {
1938 /* World has been rebuilt so rebuild constraint */
1939 rigidbody_validate_sim_constraint(rbw, ob, true);
1940 }
1941 else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) {
1942 rigidbody_validate_sim_constraint(rbw, ob, false);
1943 }
1944 }
1945 rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
1946 }
1948}
1949
1950struct KinematicSubstepData {
1951 RigidBodyOb *rbo;
1952 float old_pos[3];
1953 float new_pos[3];
1954 float old_rot[4];
1955 float new_rot[4];
1956 bool scale_changed;
1957 float old_scale[3];
1958 float new_scale[3];
1959};
1960
1961static ListBase rigidbody_create_substep_data(RigidBodyWorld *rbw)
1962{
1963 /* Objects that we want to update substep location/rotation for. */
1964 ListBase substep_targets = {nullptr, nullptr};
1965
1967 RigidBodyOb *rbo = ob->rigidbody_object;
1968 /* only update if rigid body exists */
1969 if (!rbo || rbo->shared->physics_object == nullptr) {
1970 continue;
1971 }
1972
1973 if (rbo->flag & RBO_FLAG_KINEMATIC) {
1974 float loc[3], rot[4], scale[3];
1975
1976 KinematicSubstepData *data = static_cast<KinematicSubstepData *>(
1977 MEM_callocN(sizeof(KinematicSubstepData), "RigidBody Substep data"));
1978
1979 data->rbo = rbo;
1980
1981 RB_body_get_position(static_cast<rbRigidBody *>(rbo->shared->physics_object), loc);
1983 RB_body_get_scale(static_cast<rbRigidBody *>(rbo->shared->physics_object), scale);
1984
1985 copy_v3_v3(data->old_pos, loc);
1986 copy_v4_v4(data->old_rot, rot);
1987 copy_v3_v3(data->old_scale, scale);
1988
1989 mat4_decompose(loc, rot, scale, ob->object_to_world().ptr());
1990
1991 copy_v3_v3(data->new_pos, loc);
1992 copy_v4_v4(data->new_rot, rot);
1993 copy_v3_v3(data->new_scale, scale);
1994
1995 data->scale_changed = !compare_size_v3v3(data->old_scale, data->new_scale, 0.001f);
1996
1997 LinkData *ob_link = BLI_genericNodeN(data);
1998 BLI_addtail(&substep_targets, ob_link);
1999 }
2000 }
2002
2003 return substep_targets;
2004}
2005
2006static void rigidbody_update_kinematic_obj_substep(ListBase *substep_targets, float interp_fac)
2007{
2008 LISTBASE_FOREACH (LinkData *, link, substep_targets) {
2009 KinematicSubstepData *data = static_cast<KinematicSubstepData *>(link->data);
2010 RigidBodyOb *rbo = data->rbo;
2011
2012 float loc[3], rot[4];
2013
2014 interp_v3_v3v3(loc, data->old_pos, data->new_pos, interp_fac);
2015 interp_qt_qtqt(rot, data->old_rot, data->new_rot, interp_fac);
2016
2017 RB_body_activate(static_cast<rbRigidBody *>(rbo->shared->physics_object));
2018 RB_body_set_loc_rot(static_cast<rbRigidBody *>(rbo->shared->physics_object), loc, rot);
2019
2020 if (!data->scale_changed) {
2021 /* Avoid having to rebuild the collision shape AABBs if scale didn't change. */
2022 continue;
2023 }
2024
2025 float scale[3];
2026
2027 interp_v3_v3v3(scale, data->old_scale, data->new_scale, interp_fac);
2028
2029 RB_body_set_scale(static_cast<rbRigidBody *>(rbo->shared->physics_object), scale);
2030
2031 /* compensate for embedded convex hull collision margin */
2032 if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && rbo->shape == RB_SHAPE_CONVEXH) {
2034 RBO_GET_MARGIN(rbo) * std::min({scale[0], scale[1], scale[2]}));
2035 }
2036 }
2037}
2038
2039static void rigidbody_update_external_forces(Depsgraph *depsgraph,
2040 Scene *scene,
2041 RigidBodyWorld *rbw)
2042{
2044 /* only update if rigid body exists */
2045 RigidBodyOb *rbo = ob->rigidbody_object;
2046 if (ob->type != OB_MESH || rbo->shared->physics_object == nullptr) {
2047 continue;
2048 }
2049
2050 /* update influence of effectors - but don't do it on an effector */
2051 /* only dynamic bodies need effector update */
2052 if (rbo->type == RBO_TYPE_ACTIVE &&
2053 ((ob->pd == nullptr) || (ob->pd->forcefield == PFIELD_NULL)))
2054 {
2055 EffectorWeights *effector_weights = rbw->effector_weights;
2056 EffectedPoint epoint;
2057 ListBase *effectors;
2058
2059 /* get effectors present in the group specified by effector_weights */
2060 effectors = BKE_effectors_create(depsgraph, ob, nullptr, effector_weights, false);
2061 if (effectors) {
2062 float eff_force[3] = {0.0f, 0.0f, 0.0f};
2063 float eff_loc[3], eff_vel[3];
2064
2065 /* create dummy 'point' which represents last known position of object as result of sim
2066 */
2067 /* XXX: this can create some inaccuracies with sim position,
2068 * but is probably better than using un-simulated values? */
2069 RB_body_get_position(static_cast<rbRigidBody *>(rbo->shared->physics_object), eff_loc);
2071 eff_vel);
2072
2073 pd_point_from_loc(scene, eff_loc, eff_vel, 0, &epoint);
2074
2075 /* Calculate net force of effectors, and apply to sim object:
2076 * - we use 'central force' since apply force requires a "relative position"
2077 * which we don't have... */
2079 effectors, nullptr, effector_weights, &epoint, eff_force, nullptr, nullptr);
2080 if (G.f & G_DEBUG) {
2081 printf("\tapplying force (%f,%f,%f) to '%s'\n",
2082 eff_force[0],
2083 eff_force[1],
2084 eff_force[2],
2085 ob->id.name + 2);
2086 }
2087 /* activate object in case it is deactivated */
2088 if (!is_zero_v3(eff_force)) {
2089 RB_body_activate(static_cast<rbRigidBody *>(rbo->shared->physics_object));
2090 }
2092 eff_force);
2093 }
2094 else if (G.f & G_DEBUG) {
2095 printf("\tno forces to apply to '%s'\n", ob->id.name + 2);
2096 }
2097
2098 /* cleanup */
2099 BKE_effectors_free(effectors);
2100 }
2101 /* NOTE: passive objects don't need to be updated since they don't move */
2102 }
2104}
2105
2106static void rigidbody_free_substep_data(ListBase *substep_targets)
2107{
2108 LISTBASE_FOREACH (LinkData *, link, substep_targets) {
2109 KinematicSubstepData *data = static_cast<KinematicSubstepData *>(link->data);
2110 MEM_freeN(data);
2111 }
2112
2113 BLI_freelistN(substep_targets);
2114}
2115static void rigidbody_update_simulation_post_step(Depsgraph *depsgraph, RigidBodyWorld *rbw)
2116{
2117 const Scene *scene = DEG_get_input_scene(depsgraph);
2119 BKE_view_layer_synced_ensure(scene, view_layer);
2120
2122 Base *base = BKE_view_layer_base_find(view_layer, ob);
2123 RigidBodyOb *rbo = ob->rigidbody_object;
2124 /* Reset kinematic state for transformed objects. */
2125 if (rbo && base && (base->flag & BASE_SELECTED) && (G.moving & G_TRANSFORM_OBJ) &&
2126 rbo->shared->physics_object)
2127 {
2130 RB_body_set_mass(static_cast<rbRigidBody *>(rbo->shared->physics_object), RBO_GET_MASS(rbo));
2131 /* Deactivate passive objects so they don't interfere with deactivation of active objects. */
2132 if (rbo->type == RBO_TYPE_PASSIVE) {
2133 RB_body_deactivate(static_cast<rbRigidBody *>(rbo->shared->physics_object));
2134 }
2135 }
2136 }
2138}
2139
2140bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime)
2141{
2142 return (rbw && (rbw->flag & RBW_FLAG_MUTED) == 0 && ctime > rbw->shared->pointcache->startframe);
2143}
2144
2145void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime)
2146{
2148 /* Don't sync transforms for objects that are not affected/changed by the simulation. */
2149 return;
2150 }
2151
2152 RigidBodyOb *rbo = ob->rigidbody_object;
2153
2154 /* use rigid body transform after cache start frame if objects is not being transformed */
2155 if (BKE_rigidbody_check_sim_running(rbw, ctime) &&
2156 !(ob->base_flag & BASE_SELECTED && G.moving & G_TRANSFORM_OBJ))
2157 {
2158 float mat[4][4], size_mat[4][4], size[3];
2159
2160 normalize_qt(rbo->orn); /* RB_TODO investigate why quaternion isn't normalized at this point */
2161 quat_to_mat4(mat, rbo->orn);
2162 copy_v3_v3(mat[3], rbo->pos);
2163
2164 mat4_to_size(size, ob->object_to_world().ptr());
2165 size_to_mat4(size_mat, size);
2166 mul_m4_m4m4(mat, mat, size_mat);
2167
2168 copy_m4_m4(ob->runtime->object_to_world.ptr(), mat);
2169 }
2170 /* otherwise set rigid body transform to current obmat */
2171 else {
2172 mat4_to_loc_quat(rbo->pos, rbo->orn, ob->object_to_world().ptr());
2173 }
2174}
2175
2177 Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle)
2178{
2179 bool correct_delta = BKE_rigidbody_is_affected_by_simulation(ob);
2180 RigidBodyOb *rbo = ob->rigidbody_object;
2181
2182 /* return rigid body and object to their initial states */
2183 copy_v3_v3(rbo->pos, ob->loc);
2184 copy_v3_v3(ob->loc, loc);
2185
2186 if (correct_delta) {
2187 add_v3_v3(rbo->pos, ob->dloc);
2188 }
2189
2190 if (ob->rotmode > 0) {
2191 float qt[4];
2192 eulO_to_quat(qt, ob->rot, ob->rotmode);
2193
2194 if (correct_delta) {
2195 float dquat[4];
2196 eulO_to_quat(dquat, ob->drot, ob->rotmode);
2197
2198 mul_qt_qtqt(rbo->orn, dquat, qt);
2199 }
2200 else {
2201 copy_qt_qt(rbo->orn, qt);
2202 }
2203
2204 copy_v3_v3(ob->rot, rot);
2205 }
2206 else if (ob->rotmode == ROT_MODE_AXISANGLE) {
2207 float qt[4];
2208 axis_angle_to_quat(qt, ob->rotAxis, ob->rotAngle);
2209
2210 if (correct_delta) {
2211 float dquat[4];
2212 axis_angle_to_quat(dquat, ob->drotAxis, ob->drotAngle);
2213
2214 mul_qt_qtqt(rbo->orn, dquat, qt);
2215 }
2216 else {
2217 copy_qt_qt(rbo->orn, qt);
2218 }
2219
2220 copy_v3_v3(ob->rotAxis, rotAxis);
2221 ob->rotAngle = rotAngle;
2222 }
2223 else {
2224 if (correct_delta) {
2225 mul_qt_qtqt(rbo->orn, ob->dquat, ob->quat);
2226 }
2227 else {
2228 copy_qt_qt(rbo->orn, ob->quat);
2229 }
2230
2231 copy_qt_qt(ob->quat, quat);
2232 }
2233
2234 if (rbo->shared->physics_object) {
2235 /* allow passive objects to return to original transform */
2236 if (rbo->type == RBO_TYPE_PASSIVE) {
2237 RB_body_set_kinematic_state(static_cast<rbRigidBody *>(rbo->shared->physics_object), true);
2238 }
2240 static_cast<rbRigidBody *>(rbo->shared->physics_object), rbo->pos, rbo->orn);
2241 }
2242 /* RB_TODO update rigid body physics object's loc/rot for dynamic objects here as well
2243 * (needs to be done outside bullet's update loop). */
2244}
2245
2247{
2248 if (rbw) {
2250 }
2251}
2252
2253/* ------------------ */
2254
2255void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime)
2256{
2257 RigidBodyWorld *rbw = scene->rigidbody_world;
2258 PointCache *cache;
2259 PTCacheID pid;
2260 int startframe, endframe;
2261
2262 BKE_ptcache_id_from_rigidbody(&pid, nullptr, rbw);
2263 BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, nullptr);
2264 cache = rbw->shared->pointcache;
2265
2266 /* Flag cache as outdated if we don't have a world or number of objects
2267 * in the simulation has changed. */
2268 int n = 0;
2270 (void)object;
2271 /* Ignore if this object is the direct child of an object with a compound shape */
2272 if (object->parent == nullptr || object->parent->rigidbody_object == nullptr ||
2273 object->parent->rigidbody_object->shape != RB_SHAPE_COMPOUND)
2274 {
2275 n++;
2276 }
2277 }
2279
2280 if (rbw->shared->physics_world == nullptr || rbw->numbodies != n) {
2281 cache->flag |= PTCACHE_OUTDATED;
2282 }
2283
2284 if (ctime == startframe + 1 && rbw->ltime == startframe) {
2285 if (cache->flag & PTCACHE_OUTDATED) {
2287 rigidbody_update_simulation(depsgraph, scene, rbw, true);
2288 BKE_ptcache_validate(cache, int(ctime));
2289 cache->last_exact = 0;
2290 cache->flag &= ~PTCACHE_REDO_NEEDED;
2291 }
2292 }
2293}
2294
2295void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime)
2296{
2297 RigidBodyWorld *rbw = scene->rigidbody_world;
2298 PointCache *cache;
2299 PTCacheID pid;
2300 int startframe, endframe;
2301
2302 BKE_ptcache_id_from_rigidbody(&pid, nullptr, rbw);
2303 BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, nullptr);
2304 cache = rbw->shared->pointcache;
2305
2306 if (ctime <= startframe) {
2307 rbw->ltime = startframe;
2308 return;
2309 }
2310 /* make sure we don't go out of cache frame range */
2311 if (ctime > endframe) {
2312 ctime = endframe;
2313 }
2314
2315 /* don't try to run the simulation if we don't have a world yet but allow reading baked cache */
2316 if (rbw->shared->physics_world == nullptr && !(cache->flag & PTCACHE_BAKED)) {
2317 return;
2318 }
2319 if (rbw->objects == nullptr) {
2320 rigidbody_update_ob_array(rbw);
2321 }
2322
2323 /* try to read from cache */
2324 /* RB_TODO deal with interpolated, old and baked results */
2325 bool can_simulate = (ctime == rbw->ltime + 1) && !(cache->flag & PTCACHE_BAKED);
2326
2327 if (BKE_ptcache_read(&pid, ctime, can_simulate) == PTCACHE_READ_EXACT) {
2328 BKE_ptcache_validate(cache, int(ctime));
2329 rbw->ltime = ctime;
2330 return;
2331 }
2332
2333 if (!DEG_is_active(depsgraph)) {
2334 /* When the depsgraph is inactive we should neither write to the cache
2335 * nor run the simulation. */
2336 return;
2337 }
2338
2339 /* advance simulation, we can only step one frame forward */
2340 if (compare_ff_relative(ctime, rbw->ltime + 1, FLT_EPSILON, 64)) {
2341 /* write cache for first frame when on second frame */
2342 if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) {
2343 BKE_ptcache_write(&pid, startframe);
2344 }
2345
2346 const float frame_diff = ctime - rbw->ltime;
2347 /* calculate how much time elapsed since last step in seconds */
2348 const float timestep = 1.0f / float(FPS) * frame_diff * rbw->time_scale;
2349
2350 const float substep = timestep / rbw->substeps_per_frame;
2351
2352 ListBase kinematic_substep_targets = rigidbody_create_substep_data(rbw);
2353
2354 const float interp_step = 1.0f / rbw->substeps_per_frame;
2355 float cur_interp_val = interp_step;
2356
2357 /* update and validate simulation */
2358 rigidbody_update_simulation(depsgraph, scene, rbw, false);
2359
2360 for (int i = 0; i < rbw->substeps_per_frame; i++) {
2361 rigidbody_update_external_forces(depsgraph, scene, rbw);
2362 rigidbody_update_kinematic_obj_substep(&kinematic_substep_targets, cur_interp_val);
2364 static_cast<rbDynamicsWorld *>(rbw->shared->physics_world), substep, 0, substep);
2365 cur_interp_val += interp_step;
2366 }
2367 rigidbody_free_substep_data(&kinematic_substep_targets);
2368
2369 rigidbody_update_simulation_post_step(depsgraph, rbw);
2370
2371 /* write cache for current frame */
2372 BKE_ptcache_validate(cache, int(ctime));
2373 BKE_ptcache_write(&pid, uint(ctime));
2374
2375 rbw->ltime = ctime;
2376 }
2377}
2378/* ************************************** */
2379
2380#else /* WITH_BULLET */
2381
2382/* stubs */
2383# if defined(__GNUC__) || defined(__clang__)
2384# pragma GCC diagnostic push
2385# pragma GCC diagnostic ignored "-Wunused-parameter"
2386# elif defined(_MSC_VER)
2387/* Suppress unreferenced formal parameter warning. */
2388# pragma warning(disable : 4100)
2389# endif
2390
2391void BKE_rigidbody_object_copy(Main *bmain, Object *ob_dst, const Object *ob_src, const int flag)
2392{
2393}
2394void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild) {}
2395
2396void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
2397{
2398 if (r_vol) {
2399 *r_vol = 0.0f;
2400 }
2401}
2402void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3])
2403{
2404 zero_v3(r_center);
2405}
2407{
2408 return nullptr;
2409}
2411{
2412 return nullptr;
2413}
2417{
2418 return nullptr;
2419}
2421{
2422 return nullptr;
2423}
2425{
2426 return nullptr;
2427}
2428
2430
2431bool BKE_rigidbody_add_object(Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
2432{
2433 BKE_report(reports, RPT_ERROR, "Compiled without Bullet physics engine");
2434 return false;
2435}
2436
2437void BKE_rigidbody_remove_object(Main *bmain, Scene *scene, Object *ob, const bool free_us) {}
2438void BKE_rigidbody_remove_constraint(Main *bmain, Scene *scene, Object *ob, const bool free_us) {}
2441 Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle)
2442{
2443}
2445{
2446 return false;
2447}
2449void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime) {}
2450void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime) {}
2454{
2455}
2456
2457# if defined(__GNUC__) || defined(__clang__)
2458# pragma GCC diagnostic pop
2459# endif
2460
2461#endif /* WITH_BULLET */
2462
2463/* -------------------- */
2464/* Depsgraph evaluation */
2465
2467{
2468 float ctime = DEG_get_ctime(depsgraph);
2469 DEG_debug_print_eval_time(depsgraph, __func__, scene->id.name, scene, ctime);
2470 /* rebuild sim data (i.e. after resetting to start of timeline) */
2473 }
2474}
2475
2477{
2478 float ctime = DEG_get_ctime(depsgraph);
2479 DEG_debug_print_eval_time(depsgraph, __func__, scene->id.name, scene, ctime);
2480
2481 /* evaluate rigidbody sim */
2483 return;
2484 }
2486}
2487
2489{
2490 RigidBodyWorld *rbw = scene->rigidbody_world;
2491 float ctime = DEG_get_ctime(depsgraph);
2492 DEG_debug_print_eval_time(depsgraph, __func__, ob->id.name, ob, ctime);
2493 /* read values pushed into RBO from sim/cache... */
2494 BKE_rigidbody_sync_transforms(rbw, ob, ctime);
2495}
bool BKE_collection_object_remove(Main *bmain, Collection *collection, Object *ob, bool free_us)
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_END
Collection * BKE_collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
bool BKE_collection_has_object(Collection *collection, const Object *ob)
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(_collection, _object)
bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
struct EffectorWeights * BKE_effector_add_weights(struct Collection *collection)
Definition effect.cc:57
void BKE_effectors_free(struct ListBase *lb)
Definition effect.cc:364
void BKE_effectors_apply(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *wind_force, float *impulse)
Definition effect.cc:1110
struct ListBase * BKE_effectors_create(struct Depsgraph *depsgraph, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights, bool use_rotation)
Definition effect.cc:309
void pd_point_from_loc(struct Scene *scene, float *loc, float *vel, int index, struct EffectedPoint *point)
Definition effect.cc:417
#define G_MAIN
@ G_DEBUG
@ G_TRANSFORM_OBJ
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Base * BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
@ LIB_ID_COPY_CACHES
@ LIB_ID_COPY_SET_COPIED_ON_WRITE
@ LIB_ID_CREATE_NO_USER_REFCOUNT
@ LIB_ID_CREATE_NO_MAIN
@ LIB_ID_CREATE_NO_DEG_TAG
@ LIB_ID_COPY_RIGID_BODY_NO_COLLECTION_HANDLING
void id_us_plus(ID *id)
Definition lib_id.cc:351
@ IDWALK_CB_USER
@ IDWALK_CB_NOP
void BKE_mesh_calc_volume(const float(*vert_positions)[3], int mverts_num, const blender::int3 *corner_tris, int corner_tris_num, const int *corner_verts, float *r_volume, float r_center[3])
General operations, lookup, etc. for blender objects.
void BKE_object_matrix_local_get(Object *ob, float r_mat[4][4])
void BKE_object_dimensions_get(Object *ob, float r_vec[3])
Mesh * BKE_object_get_evaluated_mesh(const Object *object_eval)
const Mesh * BKE_object_get_mesh_deform_eval(const Object *object)
std::optional< blender::Bounds< blender::float3 > > BKE_object_boundbox_get(const Object *ob)
struct PointCache * BKE_ptcache_copy_list(struct ListBase *ptcaches_new, const struct ListBase *ptcaches_old, int flag)
void BKE_ptcache_id_time(PTCacheID *pid, struct Scene *scene, float cfra, int *startframe, int *endframe, float *timescale)
void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, struct Object *ob, struct RigidBodyWorld *rbw)
void BKE_ptcache_validate(struct PointCache *cache, int framenr)
struct PointCache * BKE_ptcache_add(struct ListBase *ptcaches)
int BKE_ptcache_read(PTCacheID *pid, float cfra, bool no_extrapolate_old)
int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra)
void BKE_ptcache_free_list(struct ListBase *ptcaches)
#define PTCACHE_RESET_OUTDATED
int BKE_ptcache_id_reset(struct Scene *scene, PTCacheID *pid, int mode)
#define PTCACHE_READ_EXACT
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
API for Blender-side Rigid Body stuff.
#define RBO_GET_MASS(rbo)
#define RBO_GET_MARGIN(rbo)
void(* RigidbodyWorldIDFunc)(struct RigidBodyWorld *rbw, struct ID **idpoin, void *userdata, int cb_flag)
bool BKE_scene_check_rigidbody_active(const Scene *scene)
Definition scene.cc:2844
bool BKE_scene_object_find(Scene *scene, Object *ob)
Definition scene.cc:1963
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
void BLI_kdtree_nd_ free(KDTree *tree)
#define LISTBASE_FOREACH(type, var, list)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:496
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
struct LinkData * BLI_genericNodeN(void *data)
Definition listbase.cc:909
MINLINE float max_fff(float a, float b, float c)
#define M_PI
#define M_PI_4
MINLINE int compare_ff_relative(float a, float b, float max_diff, int max_ulps)
float mat4_to_volume_scale(const float mat[4][4])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void mat4_decompose(float loc[3], float quat[4], float size[3], const float wmat[4][4])
void size_to_mat4(float R[4][4], const float size[3])
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void mat4_to_loc_quat(float loc[3], float quat[4], const float wmat[4][4])
void mat4_to_size(float size[3], const float M[4][4])
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], float t)
void axis_angle_to_quat(float r[4], const float axis[3], float angle)
float normalize_qt(float q[4])
void quat_to_mat4(float m[4][4], const float q[4])
void eulO_to_quat(float q[4], const float e[3], short order)
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
void copy_qt_qt(float q[4], const float a[4])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition math_vector.c:36
MINLINE bool is_zero_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE bool compare_size_v3v3(const float v1[3], const float v2[3], float limit) ATTR_WARN_UNUSED_RESULT
unsigned int uint
#define UNPACK3(a)
#define ELEM(...)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_debug_print_eval_time(Depsgraph *depsgraph, const char *function_name, const char *object_name, const void *object_address, float time)
bool DEG_is_active(const Depsgraph *depsgraph)
Definition depsgraph.cc:318
void DEG_relations_tag_update(Main *bmain)
float DEG_get_ctime(const Depsgraph *graph)
ViewLayer * DEG_get_input_view_layer(const Depsgraph *graph)
Scene * DEG_get_input_scene(const Depsgraph *graph)
ID and Library types, which are fundamental for SDNA.
#define ID_NEW_REMAP(a)
Definition DNA_ID.h:711
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:1021
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1085
@ ID_TAG_COPIED_ON_EVAL
Definition DNA_ID.h:964
#define ID_REAL_USERS(id)
Definition DNA_ID.h:637
@ ROT_MODE_AXISANGLE
Object groups, one object can be in many groups at once.
Object is a sort of wrapper for general info.
@ OB_LOCK_ROTZ
@ OB_LOCK_ROTX
@ OB_LOCK_LOCY
@ OB_LOCK_LOCZ
@ OB_LOCK_ROTY
@ OB_LOCK_LOCX
@ OB_MESH
@ PTCACHE_BAKED
@ PTCACHE_OUTDATED
Types and defines for representing Rigid Body entities.
@ RBO_TYPE_ACTIVE
@ RBO_TYPE_PASSIVE
@ RBW_FLAG_MUTED
@ RBW_FLAG_USE_SPLIT_IMPULSE
@ RBO_MESH_DEFORM
@ RBO_MESH_FINAL
@ RBO_MESH_BASE
@ RBC_TYPE_POINT
@ RBC_TYPE_HINGE
@ RBC_TYPE_FIXED
@ RBC_TYPE_SLIDER
@ RBC_TYPE_MOTOR
@ RBC_TYPE_6DOF_SPRING
@ RBC_TYPE_PISTON
@ RBC_TYPE_6DOF
@ RBO_FLAG_USE_MARGIN
@ RBO_FLAG_START_DEACTIVATED
@ RBO_FLAG_KINEMATIC
@ RBO_FLAG_USE_DEFORM
@ RBO_FLAG_NEEDS_VALIDATE
@ RBO_FLAG_USE_DEACTIVATION
@ RBO_FLAG_NEEDS_RESHAPE
@ RBO_FLAG_DISABLED
@ RBC_FLAG_NEEDS_VALIDATE
@ RBC_FLAG_USE_MOTOR_ANG
@ RBC_FLAG_USE_SPRING_Y
@ RBC_FLAG_USE_SPRING_ANG_Y
@ RBC_FLAG_USE_SPRING_ANG_X
@ RBC_FLAG_USE_LIMIT_ANG_X
@ RBC_FLAG_USE_LIMIT_LIN_Y
@ RBC_FLAG_USE_LIMIT_ANG_Y
@ RBC_FLAG_USE_MOTOR_LIN
@ RBC_FLAG_DISABLE_COLLISIONS
@ RBC_FLAG_OVERRIDE_SOLVER_ITERATIONS
@ RBC_FLAG_USE_BREAKING
@ RBC_FLAG_ENABLED
@ RBC_FLAG_USE_SPRING_Z
@ RBC_FLAG_USE_LIMIT_LIN_X
@ RBC_FLAG_USE_SPRING_ANG_Z
@ RBC_FLAG_USE_SPRING_X
@ RBC_FLAG_USE_LIMIT_LIN_Z
@ RBC_FLAG_USE_LIMIT_ANG_Z
@ RB_SHAPE_CAPSULE
@ RB_SHAPE_CONVEXH
@ RB_SHAPE_COMPOUND
@ RB_SHAPE_BOX
@ RB_SHAPE_TRIMESH
@ RB_SHAPE_SPHERE
@ RB_SHAPE_CYLINDER
@ RB_SHAPE_CONE
@ RBC_SPRING_TYPE2
#define BASE_SELECTED(v3d, base)
#define PSFRA
@ PHYS_GLOBAL_GRAVITY
#define FPS
Read Guarded memory(de)allocation.
Rigid Body API for interfacing with external Physics Engines.
#define RB_LIMIT_LIN_Y
Definition RBI_api.h:311
#define RB_LIMIT_LIN_X
Definition RBI_api.h:310
#define RB_LIMIT_LIN_Z
Definition RBI_api.h:312
#define RB_LIMIT_ANG_X
Definition RBI_api.h:313
#define RB_LIMIT_ANG_Z
Definition RBI_api.h:315
#define RB_LIMIT_ANG_Y
Definition RBI_api.h:314
struct rbConstraint rbConstraint
Definition RBI_api.h:44
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
constexpr const T * data() const
Definition BLI_span.hh:216
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr bool is_empty() const
Definition BLI_span.hh:261
#define printf
const Depsgraph * depsgraph
#define fabsf(x)
draw_view in_light_buf[] float
#define rot(x, k)
#define LOG(severity)
Definition log.h:33
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
#define G(x, y, z)
void RB_constraint_set_max_impulse_motor(rbConstraint *con, float max_impulse_lin, float max_impulse_ang)
void RB_dworld_set_solver_iterations(rbDynamicsWorld *world, int num_solver_iterations)
void RB_dworld_add_body(rbDynamicsWorld *world, rbRigidBody *object, int col_groups)
void RB_dworld_set_split_impulse(rbDynamicsWorld *world, int split_impulse)
rbCollisionShape * RB_shape_new_compound()
void RB_constraint_set_stiffness_6dof_spring(rbConstraint *con, int axis, float stiffness)
void RB_body_set_restitution(rbRigidBody *object, float value)
rbCollisionShape * RB_shape_new_box(float x, float y, float z)
void RB_body_set_friction(rbRigidBody *object, float value)
void RB_body_set_mass(rbRigidBody *object, float value)
rbConstraint * RB_constraint_new_fixed(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
void RB_body_set_activation_state(rbRigidBody *object, int use_deactivation)
rbConstraint * RB_constraint_new_6dof_spring(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
void RB_dworld_add_constraint(rbDynamicsWorld *world, rbConstraint *con, int disable_collisions)
void RB_constraint_set_damping_6dof_spring(rbConstraint *con, int axis, float damping)
rbCollisionShape * RB_shape_new_gimpact_mesh(rbMeshData *mesh)
rbCollisionShape * RB_shape_new_trimesh(rbMeshData *mesh)
rbConstraint * RB_constraint_new_slider(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
void RB_body_get_linear_velocity(rbRigidBody *object, float v_out[3])
void RB_constraint_set_enabled(rbConstraint *con, int enabled)
void RB_constraint_set_stiffness_6dof_spring2(rbConstraint *con, int axis, float stiffness)
void RB_constraint_set_equilibrium_6dof_spring(rbConstraint *con)
void RB_body_apply_central_force(rbRigidBody *object, const float v_in[3])
void RB_constraint_set_limits_slider(rbConstraint *con, float lower, float upper)
rbConstraint * RB_constraint_new_piston(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
void RB_constraint_set_breaking_threshold(rbConstraint *con, float threshold)
void RB_constraint_set_enable_motor(rbConstraint *con, int enable_lin, int enable_ang)
void RB_body_get_orientation(rbRigidBody *object, float v_out[4])
void RB_dworld_set_gravity(rbDynamicsWorld *world, const float g_in[3])
void RB_compound_add_child_shape(rbCollisionShape *parentShape, rbCollisionShape *shape, const float loc[3], const float rot[4])
rbDynamicsWorld * RB_dworld_new(const float gravity[3])
void RB_trimesh_add_triangle_indices(rbMeshData *mesh, int num, int index0, int index1, int index2)
rbMeshData * RB_trimesh_data_new(int num_tris, int num_verts)
void RB_trimesh_add_vertices(rbMeshData *mesh, float *vertices, int num_verts, int vert_stride)
void RB_constraint_set_limits_6dof_spring2(rbConstraint *con, int axis, float lower, float upper)
rbConstraint * RB_constraint_new_6dof(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
void RB_constraint_set_solver_iterations(rbConstraint *con, int num_solver_iterations)
rbCollisionShape * RB_shape_new_cylinder(float radius, float height)
void RB_constraint_set_damping_6dof_spring2(rbConstraint *con, int axis, float damping)
void RB_body_set_collision_shape(rbRigidBody *object, rbCollisionShape *shape)
void RB_body_set_scale(rbRigidBody *object, const float scale[3])
void RB_body_set_damping(rbRigidBody *object, float linear, float angular)
void RB_shape_trimesh_update(rbCollisionShape *shape, const float *vertices, int num_verts, int vert_stride, const float min[3], const float max[3])
void RB_constraint_set_spring_6dof_spring(rbConstraint *con, int axis, int enable)
void RB_shape_set_margin(rbCollisionShape *shape, float value)
rbRigidBody * RB_body_new(rbCollisionShape *shape, const float loc[3], const float rot[4])
void RB_body_deactivate(rbRigidBody *object)
void RB_body_set_kinematic_state(rbRigidBody *object, int kinematic)
rbConstraint * RB_constraint_new_6dof_spring2(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
rbConstraint * RB_constraint_new_hinge(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
void RB_trimesh_finish(rbMeshData *mesh)
void RB_body_get_position(rbRigidBody *object, float v_out[3])
rbCollisionShape * RB_shape_new_convex_hull(const float *verts, int stride, int count, float margin, bool *can_embed)
rbConstraint * RB_constraint_new_point(const float pivot[3], rbRigidBody *rb1, rbRigidBody *rb2)
rbCollisionShape * RB_shape_new_cone(float radius, float height)
void RB_constraint_set_limits_piston(rbConstraint *con, float lin_lower, float lin_upper, float ang_lower, float ang_upper)
void RB_constraint_set_limits_6dof(rbConstraint *con, int axis, float lower, float upper)
void RB_body_set_loc_rot(rbRigidBody *object, const float loc[3], const float rot[4])
void RB_constraint_set_limits_hinge(rbConstraint *con, float lower, float upper)
void RB_constraint_set_target_velocity_motor(rbConstraint *con, float velocity_lin, float velocity_ang)
rbCollisionShape * RB_shape_new_sphere(float radius)
void RB_body_activate(rbRigidBody *object)
void RB_body_set_linear_factor(rbRigidBody *object, float x, float y, float z)
void RB_body_set_sleep_thresh(rbRigidBody *object, float linear, float angular)
void RB_dworld_step_simulation(rbDynamicsWorld *world, float timeStep, int maxSubSteps, float timeSubStep)
void RB_constraint_set_equilibrium_6dof_spring2(rbConstraint *con)
rbCollisionShape * RB_shape_new_capsule(float radius, float height)
rbConstraint * RB_constraint_new_motor(float pivot[3], float orn[4], rbRigidBody *rb1, rbRigidBody *rb2)
void RB_body_get_scale(rbRigidBody *object, float v_out[3])
void RB_constraint_set_spring_6dof_spring2(rbConstraint *con, int axis, int enable)
void RB_body_set_angular_factor(rbRigidBody *object, float x, float y, float z)
RigidBodyWorld * BKE_rigidbody_world_copy(RigidBodyWorld *rbw, const int flag)
void BKE_rigidbody_free_world(Scene *scene)
Definition rigidbody.cc:89
void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool rebuild)
void BKE_rigidbody_object_sync_transforms(Depsgraph *depsgraph, Scene *scene, Object *ob)
void BKE_rigidbody_objects_collection_validate(Main *bmain, Scene *scene, RigidBodyWorld *rbw)
void BKE_rigidbody_remove_constraint(Main *bmain, Scene *scene, Object *ob, const bool free_us)
void BKE_rigidbody_world_id_loop(RigidBodyWorld *rbw, RigidbodyWorldIDFunc func, void *userdata)
void BKE_rigidbody_main_collection_object_add(Main *bmain, Collection *collection, Object *object)
static void RB_dworld_remove_body(void *, void *)
Definition rigidbody.cc:81
void BKE_rigidbody_object_copy(Main *bmain, Object *ob_dst, const Object *ob_src, const int flag)
void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime)
void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw)
void BKE_rigidbody_free_constraint(Object *ob)
Definition rigidbody.cc:197
void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3])
void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime)
static void RB_dworld_remove_constraint(void *, void *)
Definition rigidbody.cc:80
static void RB_body_delete(void *)
Definition rigidbody.cc:83
bool BKE_rigidbody_add_object(Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
void BKE_rigidbody_eval_simulation(Depsgraph *depsgraph, Scene *scene)
RigidBodyWorld * BKE_rigidbody_create_world(Scene *scene)
RigidBodyOb * BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
bool BKE_rigidbody_is_affected_by_simulation(Object *ob)
Definition rigidbody.cc:217
void BKE_rigidbody_ensure_local_object(Main *bmain, Object *ob)
void BKE_rigidbody_remove_object(Main *bmain, Scene *scene, Object *ob, const bool free_us)
bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime)
static void RB_dworld_delete(void *)
Definition rigidbody.cc:82
static void RB_shape_delete(void *)
Definition rigidbody.cc:84
RigidBodyWorld * BKE_rigidbody_get_world(Scene *scene)
void BKE_rigidbody_free_object(Object *ob, RigidBodyWorld *rbw)
Definition rigidbody.cc:146
void BKE_rigidbody_rebuild_sim(Depsgraph *depsgraph, Scene *scene)
RigidBodyCon * BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short type)
void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime)
void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
void BKE_rigidbody_constraints_collection_validate(Scene *scene, RigidBodyWorld *rbw)
static void RB_constraint_delete(void *)
Definition rigidbody.cc:85
void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle)
void BKE_rigidbody_world_groups_relink(RigidBodyWorld *rbw)
#define FLT_MAX
Definition stdcycles.h:14
short flag
struct Collection * group
Definition DNA_ID.h:413
int tag
Definition DNA_ID.h:434
char name[66]
Definition DNA_ID.h:425
void * first
ListBase scenes
Definition BKE_main.hh:210
short base_flag
ObjectRuntimeHandle * runtime
float drot[3]
float dquat[4]
struct RigidBodyOb * rigidbody_object
float loc[3]
struct PartDeflect * pd
float dloc[3]
float rot[3]
float drotAxis[3]
float quat[4]
float rotAxis[3]
float drotAngle
short protectflag
struct Object * parent
struct RigidBodyCon * rigidbody_constraint
struct Object * ob1
struct Object * ob2
struct RigidBodyOb_Shared * shared
struct PointCache * pointcache
struct Collection * constraints
struct Collection * group
struct RigidBodyWorld_Shared * shared
struct Object ** objects
struct EffectorWeights * effector_weights
uint8_t flag
Definition wm_window.cc:138