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