Merge branch 'blender-v4.4-release'

This commit is contained in:
Brecht Van Lommel
2025-02-21 18:50:21 +01:00
6 changed files with 87 additions and 49 deletions

View File

@@ -13,6 +13,7 @@
struct RigidBodyOb;
struct RigidBodyWorld;
struct rbDynamicsWorld;
struct Collection;
struct Depsgraph;
@@ -110,6 +111,12 @@ void BKE_rigidbody_main_collection_object_add(struct Main *bmain,
struct RigidBodyWorld *BKE_rigidbody_world_copy(struct RigidBodyWorld *rbw, int flag);
void BKE_rigidbody_world_groups_relink(struct RigidBodyWorld *rbw);
/**
* Runtime data.
*/
void BKE_rigidbody_world_init_runtime(struct RigidBodyWorld *rbw);
struct rbDynamicsWorld *BKE_rigidbody_world_physics(struct RigidBodyWorld *rbw);
/**
* 'validate' (i.e. make new or replace old) Physics-Engine objects.
*/

View File

@@ -12,6 +12,7 @@
#include <cmath>
#include <cstdio>
#include <cstring>
#include <mutex>
#include "CLG_log.h"
@@ -69,9 +70,24 @@ struct rbRigidBody;
/* Freeing Methods --------------------- */
struct RigidBodyWorld_Runtime {
#ifdef WITH_BULLET
rbDynamicsWorld *physics_world = nullptr;
#endif
std::mutex mutex;
~RigidBodyWorld_Runtime()
{
#ifdef WITH_BULLET
if (physics_world) {
RB_dworld_delete(physics_world);
}
#endif
}
};
#ifdef WITH_BULLET
static void rigidbody_update_ob_array(RigidBodyWorld *rbw);
#else
static void RB_dworld_remove_constraint(void * /*world*/, void * /*con*/) {}
static void RB_dworld_remove_body(void * /*world*/, void * /*body*/) {}
@@ -82,6 +98,18 @@ static void RB_constraint_delete(void * /*con*/) {}
#endif
void BKE_rigidbody_world_init_runtime(RigidBodyWorld *rbw)
{
if (rbw->shared) {
rbw->shared->runtime = MEM_new<RigidBodyWorld_Runtime>(__func__);
}
}
rbDynamicsWorld *BKE_rigidbody_world_physics(RigidBodyWorld *rbw)
{
return (rbw->shared) ? rbw->shared->runtime->physics_world : nullptr;
}
void BKE_rigidbody_free_world(Scene *scene)
{
bool is_orig = (scene->id.tag & ID_TAG_COPIED_ON_EVAL) == 0;
@@ -93,7 +121,7 @@ void BKE_rigidbody_free_world(Scene *scene)
return;
}
if (is_orig && rbw->shared->physics_world) {
if (is_orig && rbw->shared->runtime->physics_world) {
/* Free physics references,
* we assume that all physics objects in will have been added to the world. */
if (rbw->constraints) {
@@ -101,7 +129,7 @@ void BKE_rigidbody_free_world(Scene *scene)
if (object->rigidbody_constraint) {
RigidBodyCon *rbc = object->rigidbody_constraint;
if (rbc->physics_constraint) {
RB_dworld_remove_constraint(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world),
RB_dworld_remove_constraint(rbw->shared->runtime->physics_world,
static_cast<rbConstraint *>(rbc->physics_constraint));
}
}
@@ -115,8 +143,6 @@ void BKE_rigidbody_free_world(Scene *scene)
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
/* free dynamics world */
RB_dworld_delete(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world));
}
if (rbw->objects) {
free(rbw->objects);
@@ -127,6 +153,7 @@ void BKE_rigidbody_free_world(Scene *scene)
BKE_ptcache_free_list(&(rbw->shared->ptcaches));
rbw->shared->pointcache = nullptr;
MEM_delete(rbw->shared->runtime);
MEM_freeN(rbw->shared);
}
@@ -152,11 +179,11 @@ void BKE_rigidbody_free_object(Object *ob, RigidBodyWorld *rbw)
/* free physics references */
if (is_orig) {
if (rbo->shared->physics_object) {
if (rbw != nullptr && rbw->shared->physics_world != nullptr) {
if (rbw != nullptr && rbw->shared->runtime->physics_world != nullptr) {
/* We can only remove the body from the world if the world is known.
* The world is generally only unknown if it's an evaluated copy of
* an object that's being freed, in which case this code isn't run anyway. */
RB_dworld_remove_body(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world),
RB_dworld_remove_body(rbw->shared->runtime->physics_world,
static_cast<rbRigidBody *>(rbo->shared->physics_object));
}
else {
@@ -166,8 +193,8 @@ void BKE_rigidbody_free_object(Object *ob, RigidBodyWorld *rbw)
scene = static_cast<Scene *>(scene->id.next))
{
RigidBodyWorld *scene_rbw = scene->rigidbody_world;
if (scene_rbw != nullptr && scene_rbw->shared->physics_world != nullptr) {
RB_dworld_remove_body(static_cast<rbDynamicsWorld *>(scene_rbw->shared->physics_world),
if (scene_rbw != nullptr && scene_rbw->shared->runtime->physics_world != nullptr) {
RB_dworld_remove_body(scene_rbw->shared->runtime->physics_world,
static_cast<rbRigidBody *>(rbo->shared->physics_object));
}
}
@@ -695,7 +722,7 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool
if (rbo->shared->physics_object && !rebuild) {
/* Don't remove body on rebuild as it has already been removed when deleting and rebuilding the
* world. */
RB_dworld_remove_body(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world),
RB_dworld_remove_body(rbw->shared->runtime->physics_world,
static_cast<rbRigidBody *>(rbo->shared->physics_object));
}
if (!rbo->shared->physics_object || rebuild) {
@@ -747,8 +774,8 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool
rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
}
if (rbw && rbw->shared->physics_world && rbo->shared->physics_object) {
RB_dworld_add_body(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world),
if (rbw && rbw->shared->runtime->physics_world && rbo->shared->physics_object) {
RB_dworld_add_body(rbw->shared->runtime->physics_world,
static_cast<rbRigidBody *>(rbo->shared->physics_object),
rbo->col_groups);
}
@@ -908,7 +935,7 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
if (ELEM(nullptr, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) {
if (rbc->physics_constraint) {
RB_dworld_remove_constraint(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world),
RB_dworld_remove_constraint(rbw->shared->runtime->physics_world,
static_cast<rbConstraint *>(rbc->physics_constraint));
RB_constraint_delete(static_cast<rbConstraint *>(rbc->physics_constraint));
rbc->physics_constraint = nullptr;
@@ -917,7 +944,7 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
}
if (rbc->physics_constraint && rebuild == false) {
RB_dworld_remove_constraint(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world),
RB_dworld_remove_constraint(rbw->shared->runtime->physics_world,
static_cast<rbConstraint *>(rbc->physics_constraint));
}
if (rbc->physics_constraint == nullptr || rebuild) {
@@ -1070,8 +1097,8 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
}
}
if (rbw && rbw->shared->physics_world && rbc->physics_constraint) {
RB_dworld_add_constraint(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world),
if (rbw && rbw->shared->runtime->physics_world && rbc->physics_constraint) {
RB_dworld_add_constraint(rbw->shared->runtime->physics_world,
static_cast<rbConstraint *>(rbc->physics_constraint),
rbc->flag & RBC_FLAG_DISABLE_COLLISIONS);
}
@@ -1087,16 +1114,15 @@ void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool re
}
/* create new sim world */
if (rebuild || rbw->shared->physics_world == nullptr) {
if (rbw->shared->physics_world) {
RB_dworld_delete(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world));
if (rebuild || rbw->shared->runtime->physics_world == nullptr) {
if (rbw->shared->runtime->physics_world) {
RB_dworld_delete(rbw->shared->runtime->physics_world);
}
rbw->shared->physics_world = RB_dworld_new(scene->physics_settings.gravity);
rbw->shared->runtime->physics_world = RB_dworld_new(scene->physics_settings.gravity);
}
RB_dworld_set_solver_iterations(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world),
rbw->num_solver_iterations);
RB_dworld_set_split_impulse(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world),
RB_dworld_set_solver_iterations(rbw->shared->runtime->physics_world, rbw->num_solver_iterations);
RB_dworld_set_split_impulse(rbw->shared->runtime->physics_world,
rbw->flag & RBW_FLAG_USE_SPLIT_IMPULSE);
}
@@ -1136,6 +1162,8 @@ RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene)
rbw->shared->pointcache = BKE_ptcache_add(&(rbw->shared->ptcaches));
rbw->shared->pointcache->step = 1;
BKE_rigidbody_world_init_runtime(rbw);
/* return this sim world */
return rbw;
}
@@ -1162,6 +1190,7 @@ RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw, const int flag)
MEM_callocN(sizeof(*rbw_copy->shared), "RigidBodyWorld_Shared"));
BKE_ptcache_copy_list(&rbw_copy->shared->ptcaches, &rbw->shared->ptcaches, LIB_ID_COPY_CACHES);
rbw_copy->shared->pointcache = static_cast<PointCache *>(rbw_copy->shared->ptcaches.first);
BKE_rigidbody_world_init_runtime(rbw_copy);
}
rbw_copy->objects = nullptr;
@@ -1561,8 +1590,8 @@ void BKE_rigidbody_remove_constraint(Main *bmain, Scene *scene, Object *ob, cons
}
/* remove from rigidbody world, free object won't do this */
if (rbw->shared->physics_world && rbc->physics_constraint) {
RB_dworld_remove_constraint(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world),
if (rbw->shared->runtime->physics_world && rbc->physics_constraint) {
RB_dworld_remove_constraint(rbw->shared->runtime->physics_world,
static_cast<rbConstraint *>(rbc->physics_constraint));
}
}
@@ -1632,7 +1661,7 @@ static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw)
}
/* update gravity, since this RNA setting is not part of RigidBody settings */
RB_dworld_set_gravity(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world), adj_gravity);
RB_dworld_set_gravity(rbw->shared->runtime->physics_world, adj_gravity);
/* update object array in case there are changes */
rigidbody_update_ob_array(rbw);
@@ -1711,7 +1740,7 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph,
/* update world */
/* Note physics_world can get nullptr when undoing the deletion of the last object in it (see
* #70667). */
if (rebuild || rbw->shared->physics_world == nullptr) {
if (rebuild || rbw->shared->runtime->physics_world == nullptr) {
BKE_rigidbody_validate_sim_world(scene, rbw, rebuild);
/* We have rebuilt the world so we need to make sure the rest is rebuilt as well. */
rebuild = true;
@@ -1729,7 +1758,7 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph,
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (rbw->constraints, ob) {
RigidBodyCon *rbc = ob->rigidbody_constraint;
if (rbc && rbc->physics_constraint) {
RB_dworld_remove_constraint(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world),
RB_dworld_remove_constraint(rbw->shared->runtime->physics_world,
static_cast<rbConstraint *>(rbc->physics_constraint));
RB_constraint_delete(static_cast<rbConstraint *>(rbc->physics_constraint));
rbc->physics_constraint = nullptr;
@@ -2146,6 +2175,9 @@ void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime
PTCacheID pid;
int startframe, endframe;
/* Avoid multiple depsgraph evaluations accessing the same shared data. */
std::unique_lock lock(rbw->shared->runtime->mutex);
BKE_ptcache_id_from_rigidbody(&pid, nullptr, rbw);
BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, nullptr);
cache = rbw->shared->pointcache;
@@ -2164,7 +2196,7 @@ void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
if (rbw->shared->physics_world == nullptr || rbw->numbodies != n) {
if (rbw->shared->runtime->physics_world == nullptr || rbw->numbodies != n) {
cache->flag |= PTCACHE_OUTDATED;
}
@@ -2198,7 +2230,7 @@ void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime
ctime = std::min<float>(ctime, endframe);
/* don't try to run the simulation if we don't have a world yet but allow reading baked cache */
if (rbw->shared->physics_world == nullptr && !(cache->flag & PTCACHE_BAKED)) {
if (rbw->shared->runtime->physics_world == nullptr && !(cache->flag & PTCACHE_BAKED)) {
return;
}
if (rbw->objects == nullptr) {
@@ -2245,8 +2277,7 @@ void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime
for (int i = 0; i < rbw->substeps_per_frame; i++) {
rigidbody_update_external_forces(depsgraph, scene, rbw);
rigidbody_update_kinematic_obj_substep(&kinematic_substep_targets, cur_interp_val);
RB_dworld_step_simulation(
static_cast<rbDynamicsWorld *>(rbw->shared->physics_world), substep, 0, substep);
RB_dworld_step_simulation(rbw->shared->runtime->physics_world, substep, 0, substep);
cur_interp_val += interp_step;
}
rigidbody_free_substep_data(&kinematic_substep_targets);

View File

@@ -1451,11 +1451,6 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
}
}
else {
/* must nullify the reference to physics sim object, since it no-longer exist
* (and will need to be recalculated)
*/
rbw->shared->physics_world = nullptr;
/* link caches */
BKE_ptcache_blend_read_data(reader, &rbw->shared->ptcaches, &rbw->shared->pointcache, false);
@@ -1464,6 +1459,8 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
rbw->ltime = float(rbw->shared->pointcache->startframe);
}
}
BKE_rigidbody_world_init_runtime(rbw);
rbw->objects = nullptr;
rbw->numbodies = 0;

View File

@@ -140,7 +140,8 @@ static int rigidbody_world_export_exec(bContext *C, wmOperator *op)
BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to export");
return OPERATOR_CANCELLED;
}
if (rbw->shared->physics_world == nullptr) {
rbDynamicsWorld *physics_world = BKE_rigidbody_world_physics(rbw);
if (physics_world == nullptr) {
BKE_report(
op->reports, RPT_ERROR, "Rigid Body World has no associated physics data to export");
return OPERATOR_CANCELLED;
@@ -148,7 +149,7 @@ static int rigidbody_world_export_exec(bContext *C, wmOperator *op)
RNA_string_get(op->ptr, "filepath", filepath);
#ifdef WITH_BULLET
RB_dworld_export(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world), filepath);
RB_dworld_export(physics_world, filepath);
#endif
return OPERATOR_FINISHED;
}

View File

@@ -15,6 +15,7 @@
struct Collection;
struct EffectorWeights;
struct RigidBodyWorld_Runtime;
/* ******************************** */
/* RigidBody World */
@@ -25,9 +26,8 @@ typedef struct RigidBodyWorld_Shared {
struct PointCache *pointcache;
struct ListBase ptcaches;
/* References to Physics Sim objects. Exist at runtime only ---------------------- */
/** Physics sim world (i.e. #btDiscreteDynamicsWorld). */
void *physics_world;
/* Runtime data. */
struct RigidBodyWorld_Runtime *runtime;
} RigidBodyWorld_Shared;
/* RigidBodyWorld (rbw)

View File

@@ -159,9 +159,9 @@ static void rna_RigidBodyWorld_num_solver_iterations_set(PointerRNA *ptr, int va
rbw->num_solver_iterations = value;
# ifdef WITH_BULLET
if (rbw->shared->physics_world) {
RB_dworld_set_solver_iterations(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world),
value);
rbDynamicsWorld *physics_world = BKE_rigidbody_world_physics(rbw);
if (physics_world) {
RB_dworld_set_solver_iterations(physics_world, value);
}
# endif
}
@@ -173,8 +173,9 @@ static void rna_RigidBodyWorld_split_impulse_set(PointerRNA *ptr, bool value)
SET_FLAG_FROM_TEST(rbw->flag, value, RBW_FLAG_USE_SPLIT_IMPULSE);
# ifdef WITH_BULLET
if (rbw->shared->physics_world) {
RB_dworld_set_split_impulse(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world), value);
rbDynamicsWorld *physics_world = BKE_rigidbody_world_physics(rbw);
if (physics_world) {
RB_dworld_set_split_impulse(physics_world, value);
}
# endif
}
@@ -826,9 +827,10 @@ static void rna_RigidBodyWorld_convex_sweep_test(RigidBodyWorld *rbw,
{
# ifdef WITH_BULLET
RigidBodyOb *rob = object->rigidbody_object;
rbDynamicsWorld *physics_world = BKE_rigidbody_world_physics(rbw);
if (rbw->shared->physics_world != nullptr && rob->shared->physics_object != nullptr) {
RB_world_convex_sweep_test(static_cast<rbDynamicsWorld *>(rbw->shared->physics_world),
if (physics_world != nullptr && rob->shared->physics_object != nullptr) {
RB_world_convex_sweep_test(physics_world,
static_cast<rbRigidBody *>(rob->shared->physics_object),
ray_start,
ray_end,