Prevent copying too much in the Rigid Body simulation

To prevent the pointcache from being copied-on-write too (and requiring
copying back), the cache is now shared between the original and
evaluated scenes. Reading from the cache is always allowed; running the
sim and writing to the cache is only allowed when the depsgraph is
active.

Some pointers have moved from RigidBodyWorld (RBO) to
RigidBodyWorldShared (RBOS). writefile.c copies some pointers back from
RBOS to RBO so that the file can still be opened on older Blenders
without crashing on a segfault.

The RigidBodyWorldShared struct is written to the blend file, because it
refers to the PointCache ID block.

The RigidObjectShared struct is runtime-only, and thus not saved to the
blend file.

An RNA getter-function is used to hide the new 'shared' pointer. As a
result the Python API hasn't changed.

Reviewed by: campbellbarton

Differential Revision: https://developer.blender.org/D3508
This commit is contained in:
Sybren A. Stüvel 2018-06-27 17:08:58 +02:00
parent 9b050b736b
commit 98a0bcd425
Notes: blender-bot 2023-02-14 05:22:18 +01:00
Referenced by commit 769c57b38a, SoftBody: share point cache between CoW copies
Referenced by issue #67123, Blender shuts down when playing a Rigid Body animation in a linked scene
11 changed files with 284 additions and 203 deletions

View File

@ -44,8 +44,8 @@ struct Object;
/* -------------- */
/* Memory Management */
void BKE_rigidbody_free_world(struct RigidBodyWorld *rbw);
void BKE_rigidbody_free_object(struct Object *ob);
void BKE_rigidbody_free_world(struct Scene *scene);
void BKE_rigidbody_free_object(struct Object *ob, struct RigidBodyWorld *rbw);
void BKE_rigidbody_free_constraint(struct Object *ob);
/* ...... */

View File

@ -449,7 +449,7 @@ void BKE_object_free(Object *ob)
BKE_constraints_free_ex(&ob->constraints, false);
free_partdeflect(ob->pd);
BKE_rigidbody_free_object(ob);
BKE_rigidbody_free_object(ob, NULL);
BKE_rigidbody_free_constraint(ob);
if (ob->soft) {

View File

@ -1295,8 +1295,8 @@ static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUS
if (rbo->type == RBO_TYPE_ACTIVE) {
#ifdef WITH_BULLET
RB_body_get_position(rbo->physics_object, rbo->pos);
RB_body_get_orientation(rbo->physics_object, rbo->orn);
RB_body_get_position(rbo->shared->physics_object, rbo->pos);
RB_body_get_orientation(rbo->shared->physics_object, rbo->orn);
#endif
PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, rbo->pos);
PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, rbo->orn);
@ -1619,9 +1619,9 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r
pid->ob= ob;
pid->calldata= rbw;
pid->type= PTCACHE_TYPE_RIGIDBODY;
pid->cache= rbw->pointcache;
pid->cache_ptr= &rbw->pointcache;
pid->ptcaches= &rbw->ptcaches;
pid->cache= rbw->shared->pointcache;
pid->cache_ptr= &rbw->shared->pointcache;
pid->ptcaches= &rbw->shared->ptcaches;
pid->totpoint= pid->totwrite= ptcache_rigidbody_totpoint;
pid->error = ptcache_rigidbody_error;

View File

@ -76,8 +76,10 @@
/* Freeing Methods --------------------- */
#ifndef WITH_BULLET
#ifdef WITH_BULLET
static void rigidbody_update_ob_array(RigidBodyWorld *rbw);
#else
static void RB_dworld_remove_constraint(void *UNUSED(world), void *UNUSED(con)) {}
static void RB_dworld_remove_body(void *UNUSED(world), void *UNUSED(body)) {}
static void RB_dworld_delete(void *UNUSED(world)) {}
@ -88,13 +90,17 @@ static void RB_constraint_delete(void *UNUSED(con)) {}
#endif
/* Free rigidbody world */
void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
void BKE_rigidbody_free_world(Scene *scene)
{
bool is_orig = (scene->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0;
RigidBodyWorld *rbw = scene->rigidbody_world;
scene->rigidbody_world = NULL;
/* sanity check */
if (!rbw)
return;
if (rbw->physics_world) {
if (is_orig && rbw->shared->physics_world) {
/* free physics references, we assume that all physics objects in will have been added to the world */
if (rbw->constraints) {
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, object)
@ -102,7 +108,7 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
if (object->rigidbody_constraint) {
RigidBodyCon *rbc = object->rigidbody_constraint;
if (rbc->physics_constraint) {
RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
RB_dworld_remove_constraint(rbw->shared->physics_world, rbc->physics_constraint);
}
}
}
@ -112,24 +118,23 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
if (rbw->group) {
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object)
{
if (object->rigidbody_object) {
RigidBodyOb *rbo = object->rigidbody_object;
if (rbo->physics_object) {
RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
}
}
BKE_rigidbody_free_object(object, rbw);
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
/* free dynamics world */
RB_dworld_delete(rbw->physics_world);
RB_dworld_delete(rbw->shared->physics_world);
}
if (rbw->objects)
free(rbw->objects);
/* free cache */
BKE_ptcache_free_list(&(rbw->ptcaches));
rbw->pointcache = NULL;
if (is_orig) {
/* free cache */
BKE_ptcache_free_list(&(rbw->shared->ptcaches));
rbw->shared->pointcache = NULL;
MEM_freeN(rbw->shared);
}
/* free effector weights */
if (rbw->effector_weights)
@ -140,8 +145,9 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
}
/* Free RigidBody settings and sim instances */
void BKE_rigidbody_free_object(Object *ob)
void BKE_rigidbody_free_object(Object *ob, RigidBodyWorld *rbw)
{
bool is_orig = (ob->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0;
RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL;
/* sanity check */
@ -149,14 +155,26 @@ void BKE_rigidbody_free_object(Object *ob)
return;
/* free physics references */
if (rbo->physics_object) {
RB_body_delete(rbo->physics_object);
rbo->physics_object = NULL;
}
if (is_orig) {
if (rbo->shared->physics_object) {
BLI_assert(rbw);
if (rbw) {
/* 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(rbw->shared->physics_world, rbo->shared->physics_object);
}
if (rbo->physics_shape) {
RB_shape_delete(rbo->physics_shape);
rbo->physics_shape = NULL;
RB_body_delete(rbo->shared->physics_object);
rbo->shared->physics_object = NULL;
}
if (rbo->shared->physics_shape) {
RB_shape_delete(rbo->shared->physics_shape);
rbo->shared->physics_shape = NULL;
}
MEM_freeN(rbo->shared);
}
/* free data itself */
@ -193,7 +211,7 @@ void BKE_rigidbody_free_constraint(Object *ob)
* be added to relevant groups later...
*/
RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int UNUSED(flag))
RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int flag)
{
RigidBodyOb *rboN = NULL;
@ -201,12 +219,13 @@ RigidBodyOb *BKE_rigidbody_copy_object(const Object *ob, const int UNUSED(flag))
/* just duplicate the whole struct first (to catch all the settings) */
rboN = MEM_dupallocN(ob->rigidbody_object);
if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
/* This is a regular copy, and not a CoW copy for depsgraph evaluation */
rboN->shared = MEM_callocN(sizeof(*rboN->shared), "RigidBodyOb_Shared");
}
/* tag object as needing to be verified */
rboN->flag |= RBO_FLAG_NEEDS_VALIDATE;
/* clear out all the fields which need to be revalidated later */
rboN->physics_object = NULL;
rboN->physics_shape = NULL;
}
/* return new copy of settings */
@ -387,7 +406,7 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
return;
/* don't create a new shape if we already have one and don't want to rebuild it */
if (rbo->physics_shape && !rebuild)
if (rbo->shared->physics_shape && !rebuild)
return;
/* if automatically determining dimensions, use the Object's boundbox
@ -451,15 +470,16 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
break;
}
/* use box shape if we can't fall back to old shape */
if (new_shape == NULL && rbo->physics_shape == NULL) {
if (new_shape == NULL && rbo->shared->physics_shape == NULL) {
new_shape = RB_shape_new_box(size[0], size[1], size[2]);
}
/* assign new collision shape if creation was successful */
if (new_shape) {
if (rbo->physics_shape)
RB_shape_delete(rbo->physics_shape);
rbo->physics_shape = new_shape;
RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo));
if (rbo->shared->physics_shape) {
RB_shape_delete(rbo->shared->physics_shape);
}
rbo->shared->physics_shape = new_shape;
RB_shape_set_margin(rbo->shared->physics_shape, RBO_GET_MARGIN(rbo));
}
}
@ -650,48 +670,48 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool
/* make sure collision shape exists */
/* FIXME we shouldn't always have to rebuild collision shapes when rebuilding objects, but it's needed for constraints to update correctly */
if (rbo->physics_shape == NULL || rebuild)
if (rbo->shared->physics_shape == NULL || rebuild)
rigidbody_validate_sim_shape(ob, true);
if (rbo->physics_object && rebuild == false) {
RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
if (rbo->shared->physics_object) {
RB_dworld_remove_body(rbw->shared->physics_world, rbo->shared->physics_object);
}
if (!rbo->physics_object || rebuild) {
if (!rbo->shared->physics_object || rebuild) {
/* remove rigid body if it already exists before creating a new one */
if (rbo->physics_object) {
RB_body_delete(rbo->physics_object);
if (rbo->shared->physics_object) {
RB_body_delete(rbo->shared->physics_object);
}
mat4_to_loc_quat(loc, rot, ob->obmat);
rbo->physics_object = RB_body_new(rbo->physics_shape, loc, rot);
rbo->shared->physics_object = RB_body_new(rbo->shared->physics_shape, loc, rot);
RB_body_set_friction(rbo->physics_object, rbo->friction);
RB_body_set_restitution(rbo->physics_object, rbo->restitution);
RB_body_set_friction(rbo->shared->physics_object, rbo->friction);
RB_body_set_restitution(rbo->shared->physics_object, rbo->restitution);
RB_body_set_damping(rbo->physics_object, rbo->lin_damping, rbo->ang_damping);
RB_body_set_sleep_thresh(rbo->physics_object, rbo->lin_sleep_thresh, rbo->ang_sleep_thresh);
RB_body_set_activation_state(rbo->physics_object, rbo->flag & RBO_FLAG_USE_DEACTIVATION);
RB_body_set_damping(rbo->shared->physics_object, rbo->lin_damping, rbo->ang_damping);
RB_body_set_sleep_thresh(rbo->shared->physics_object, rbo->lin_sleep_thresh, rbo->ang_sleep_thresh);
RB_body_set_activation_state(rbo->shared->physics_object, rbo->flag & RBO_FLAG_USE_DEACTIVATION);
if (rbo->type == RBO_TYPE_PASSIVE || rbo->flag & RBO_FLAG_START_DEACTIVATED)
RB_body_deactivate(rbo->physics_object);
RB_body_deactivate(rbo->shared->physics_object);
RB_body_set_linear_factor(rbo->physics_object,
RB_body_set_linear_factor(rbo->shared->physics_object,
(ob->protectflag & OB_LOCK_LOCX) == 0,
(ob->protectflag & OB_LOCK_LOCY) == 0,
(ob->protectflag & OB_LOCK_LOCZ) == 0);
RB_body_set_angular_factor(rbo->physics_object,
RB_body_set_angular_factor(rbo->shared->physics_object,
(ob->protectflag & OB_LOCK_ROTX) == 0,
(ob->protectflag & OB_LOCK_ROTY) == 0,
(ob->protectflag & OB_LOCK_ROTZ) == 0);
RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
RB_body_set_mass(rbo->shared->physics_object, RBO_GET_MASS(rbo));
RB_body_set_kinematic_state(rbo->shared->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
}
if (rbw && rbw->physics_world)
RB_dworld_add_body(rbw->physics_world, rbo->physics_object, rbo->col_groups);
if (rbw && rbw->shared->physics_world)
RB_dworld_add_body(rbw->shared->physics_world, rbo->shared->physics_object, rbo->col_groups);
}
/* --------------------- */
@ -755,7 +775,7 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
if (ELEM(NULL, rbc->ob1, rbc->ob1->rigidbody_object, rbc->ob2, rbc->ob2->rigidbody_object)) {
if (rbc->physics_constraint) {
RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
RB_dworld_remove_constraint(rbw->shared->physics_world, rbc->physics_constraint);
RB_constraint_delete(rbc->physics_constraint);
rbc->physics_constraint = NULL;
}
@ -763,11 +783,11 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
}
if (rbc->physics_constraint && rebuild == false) {
RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
RB_dworld_remove_constraint(rbw->shared->physics_world, rbc->physics_constraint);
}
if (rbc->physics_constraint == NULL || rebuild) {
rbRigidBody *rb1 = rbc->ob1->rigidbody_object->physics_object;
rbRigidBody *rb2 = rbc->ob2->rigidbody_object->physics_object;
rbRigidBody *rb1 = rbc->ob1->rigidbody_object->shared->physics_object;
rbRigidBody *rb2 = rbc->ob2->rigidbody_object->shared->physics_object;
/* remove constraint if it already exists before creating a new one */
if (rbc->physics_constraint) {
@ -882,8 +902,8 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
RB_constraint_set_solver_iterations(rbc->physics_constraint, -1);
}
if (rbw && rbw->physics_world && rbc->physics_constraint) {
RB_dworld_add_constraint(rbw->physics_world, rbc->physics_constraint, rbc->flag & RBC_FLAG_DISABLE_COLLISIONS);
if (rbw && rbw->shared->physics_world && rbc->physics_constraint) {
RB_dworld_add_constraint(rbw->shared->physics_world, rbc->physics_constraint, rbc->flag & RBC_FLAG_DISABLE_COLLISIONS);
}
}
@ -898,14 +918,14 @@ void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, bool re
return;
/* create new sim world */
if (rebuild || rbw->physics_world == NULL) {
if (rbw->physics_world)
RB_dworld_delete(rbw->physics_world);
rbw->physics_world = RB_dworld_new(scene->physics_settings.gravity);
if (rebuild || rbw->shared->physics_world == NULL) {
if (rbw->shared->physics_world)
RB_dworld_delete(rbw->shared->physics_world);
rbw->shared->physics_world = RB_dworld_new(scene->physics_settings.gravity);
}
RB_dworld_set_solver_iterations(rbw->physics_world, rbw->num_solver_iterations);
RB_dworld_set_split_impulse(rbw->physics_world, rbw->flag & RBW_FLAG_USE_SPLIT_IMPULSE);
RB_dworld_set_solver_iterations(rbw->shared->physics_world, rbw->num_solver_iterations);
RB_dworld_set_split_impulse(rbw->shared->physics_world, rbw->flag & RBW_FLAG_USE_SPLIT_IMPULSE);
}
/* ************************************** */
@ -926,6 +946,7 @@ RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene)
/* create a new sim world */
rbw = MEM_callocN(sizeof(RigidBodyWorld), "RigidBodyWorld");
rbw->shared = MEM_callocN(sizeof(*rbw->shared), "RigidBodyWorld_Shared");
/* set default settings */
rbw->effector_weights = BKE_add_effector_weights(NULL);
@ -937,8 +958,8 @@ RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene)
rbw->steps_per_second = 60; /* Bullet default (60 Hz) */
rbw->num_solver_iterations = 10; /* 10 is bullet default */
rbw->pointcache = BKE_ptcache_add(&(rbw->ptcaches));
rbw->pointcache->step = 1;
rbw->shared->pointcache = BKE_ptcache_add(&(rbw->shared->ptcaches));
rbw->shared->pointcache->step = 1;
/* return this sim world */
return rbw;
@ -956,12 +977,16 @@ RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw, const int flag)
id_us_plus((ID *)rbw_copy->constraints);
}
/* XXX Never copy caches here? */
rbw_copy->pointcache = BKE_ptcache_copy_list(&rbw_copy->ptcaches, &rbw->ptcaches, flag & ~LIB_ID_COPY_CACHES);
if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
/* This is a regular copy, and not a CoW copy for depsgraph evaluation */
rbw_copy->shared = 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 = rbw_copy->shared->ptcaches.first;
}
rbw_copy->objects = NULL;
rbw_copy->physics_world = NULL;
rbw_copy->numbodies = 0;
rigidbody_update_ob_array(rbw_copy);
return rbw_copy;
}
@ -1003,6 +1028,7 @@ RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
/* create new settings data, and link it up */
rbo = MEM_callocN(sizeof(RigidBodyOb), "RigidBodyOb");
rbo->shared = MEM_callocN(sizeof(*rbo->shared), "RigidBodyOb_Shared");
/* set default settings */
rbo->type = type;
@ -1128,14 +1154,10 @@ RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene)
void BKE_rigidbody_remove_object(struct Main *bmain, Scene *scene, Object *ob)
{
RigidBodyWorld *rbw = scene->rigidbody_world;
RigidBodyOb *rbo = ob->rigidbody_object;
RigidBodyCon *rbc;
int i;
if (rbw) {
/* remove from rigidbody world, free object won't do this */
if (rbw->physics_world && rbo->physics_object)
RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
/* remove object from array */
if (rbw && rbw->objects) {
@ -1164,7 +1186,7 @@ void BKE_rigidbody_remove_object(struct Main *bmain, Scene *scene, Object *ob)
}
/* remove object's settings */
BKE_rigidbody_free_object(ob);
BKE_rigidbody_free_object(ob, rbw);
/* flag cache as outdated */
BKE_rigidbody_cache_reset(rbw);
@ -1176,8 +1198,8 @@ void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob)
RigidBodyCon *rbc = ob->rigidbody_constraint;
/* remove from rigidbody world, free object won't do this */
if (rbw && rbw->physics_world && rbc->physics_constraint) {
RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
if (rbw && rbw->shared->physics_world && rbc->physics_constraint) {
RB_dworld_remove_constraint(rbw->shared->physics_world, rbc->physics_constraint);
}
/* remove object's settings */
BKE_rigidbody_free_constraint(ob);
@ -1193,6 +1215,12 @@ void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob)
/* Update object array and rigid body count so they're in sync with the rigid body group */
static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
{
if (rbw->group == NULL) {
rbw->numbodies = 0;
rbw->objects = realloc(rbw->objects, 0);
return;
}
int n = 0;
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object)
{
@ -1229,7 +1257,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(rbw->physics_world, adj_gravity);
RB_dworld_set_gravity(rbw->shared->physics_world, adj_gravity);
/* update object array in case there are changes */
rigidbody_update_ob_array(rbw);
@ -1242,7 +1270,7 @@ static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Scene *scene, RigidBod
float scale[3];
/* only update if rigid body exists */
if (rbo->physics_object == NULL)
if (rbo->shared->physics_object == NULL)
return;
if (rbo->shape == RB_SHAPE_TRIMESH && rbo->flag & RBO_FLAG_USE_DEFORM) {
@ -1252,28 +1280,28 @@ static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Scene *scene, RigidBod
int totvert = mesh->totvert;
BoundBox *bb = BKE_object_boundbox_get(ob);
RB_shape_trimesh_update(rbo->physics_shape, (float *)mvert, totvert, sizeof(MVert), bb->vec[0], bb->vec[6]);
RB_shape_trimesh_update(rbo->shared->physics_shape, (float *)mvert, totvert, sizeof(MVert), bb->vec[0], bb->vec[6]);
}
}
mat4_decompose(loc, rot, scale, ob->obmat);
/* update scale for all objects */
RB_body_set_scale(rbo->physics_object, scale);
RB_body_set_scale(rbo->shared->physics_object, scale);
/* compensate for embedded convex hull collision margin */
if (!(rbo->flag & RBO_FLAG_USE_MARGIN) && rbo->shape == RB_SHAPE_CONVEXH)
RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo) * MIN3(scale[0], scale[1], scale[2]));
RB_shape_set_margin(rbo->shared->physics_shape, RBO_GET_MARGIN(rbo) * MIN3(scale[0], scale[1], scale[2]));
/* make transformed objects temporarily kinmatic so that they can be moved by the user during simulation */
if (ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ) {
RB_body_set_kinematic_state(rbo->physics_object, true);
RB_body_set_mass(rbo->physics_object, 0.0f);
RB_body_set_kinematic_state(rbo->shared->physics_object, true);
RB_body_set_mass(rbo->shared->physics_object, 0.0f);
}
/* update rigid body location and rotation for kinematic bodies */
if (rbo->flag & RBO_FLAG_KINEMATIC || (ob->flag & SELECT && G.moving & G_TRANSFORM_OBJ)) {
RB_body_activate(rbo->physics_object);
RB_body_set_loc_rot(rbo->physics_object, loc, rot);
RB_body_activate(rbo->shared->physics_object);
RB_body_set_loc_rot(rbo->shared->physics_object, loc, rot);
}
/* update influence of effectors - but don't do it on an effector */
/* only dynamic bodies need effector update */
@ -1290,8 +1318,8 @@ static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Scene *scene, RigidBod
/* create dummy 'point' which represents last known position of object as result of sim */
// XXX: this can create some inaccuracies with sim position, but is probably better than using unsimulated vals?
RB_body_get_position(rbo->physics_object, eff_loc);
RB_body_get_linear_velocity(rbo->physics_object, eff_vel);
RB_body_get_position(rbo->shared->physics_object, eff_loc);
RB_body_get_linear_velocity(rbo->shared->physics_object, eff_vel);
pd_point_from_loc(scene, eff_loc, eff_vel, 0, &epoint);
@ -1303,8 +1331,8 @@ static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Scene *scene, RigidBod
printf("\tapplying force (%f,%f,%f) to '%s'\n", eff_force[0], eff_force[1], eff_force[2], ob->id.name + 2);
/* activate object in case it is deactivated */
if (!is_zero_v3(eff_force))
RB_body_activate(rbo->physics_object);
RB_body_apply_central_force(rbo->physics_object, eff_force);
RB_body_activate(rbo->shared->physics_object);
RB_body_apply_central_force(rbo->shared->physics_object, eff_force);
}
else if (G.f & G_DEBUG)
printf("\tno forces to apply to '%s'\n", ob->id.name + 2);
@ -1342,7 +1370,7 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph, Scene *scene, Rigi
{
RigidBodyCon *rbc = ob->rigidbody_constraint;
if (rbc && rbc->physics_constraint) {
RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
RB_dworld_remove_constraint(rbw->shared->physics_world, rbc->physics_constraint);
RB_constraint_delete(rbc->physics_constraint);
rbc->physics_constraint = NULL;
}
@ -1374,6 +1402,9 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph, Scene *scene, Rigi
/* refresh object... */
if (rebuild) {
/* World has been rebuilt so rebuild object */
/* TODO(Sybren): rigidbody_validate_sim_object() can call rigidbody_validate_sim_shape(),
* but neither resets the RBO_FLAG_NEEDS_RESHAPE flag nor calls RB_body_set_collision_shape().
* This results in the collision shape being created twice, which is unnecessary. */
rigidbody_validate_sim_object(rbw, ob, true);
}
else if (rbo->flag & RBO_FLAG_NEEDS_VALIDATE) {
@ -1385,7 +1416,7 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph, Scene *scene, Rigi
rigidbody_validate_sim_shape(ob, true);
/* now tell RB sim about it */
// XXX: we assume that this can only get applied for active/passive shapes that will be included as rigidbodies
RB_body_set_collision_shape(rbo->physics_object, rbo->physics_shape);
RB_body_set_collision_shape(rbo->shared->physics_object, rbo->shared->physics_shape);
}
rbo->flag &= ~(RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE);
}
@ -1441,11 +1472,11 @@ static void rigidbody_update_simulation_post_step(Depsgraph *depsgraph, RigidBod
RigidBodyOb *rbo = ob->rigidbody_object;
/* Reset kinematic state for transformed objects. */
if (rbo && base && (base->flag & BASE_SELECTED) && (G.moving & G_TRANSFORM_OBJ)) {
RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
RB_body_set_kinematic_state(rbo->shared->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
RB_body_set_mass(rbo->shared->physics_object, RBO_GET_MASS(rbo));
/* Deactivate passive objects so they don't interfere with deactivation of active objects. */
if (rbo->type == RBO_TYPE_PASSIVE)
RB_body_deactivate(rbo->physics_object);
RB_body_deactivate(rbo->shared->physics_object);
}
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
@ -1453,7 +1484,7 @@ static void rigidbody_update_simulation_post_step(Depsgraph *depsgraph, RigidBod
bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime)
{
return (rbw && (rbw->flag & RBW_FLAG_MUTED) == 0 && ctime > rbw->pointcache->startframe);
return (rbw && (rbw->flag & RBW_FLAG_MUTED) == 0 && ctime > rbw->shared->pointcache->startframe);
}
/* Sync rigid body and object transformations */
@ -1543,11 +1574,11 @@ void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], flo
copy_qt_qt(ob->quat, quat);
}
if (rbo->physics_object) {
if (rbo->shared->physics_object) {
/* allow passive objects to return to original transform */
if (rbo->type == RBO_TYPE_PASSIVE)
RB_body_set_kinematic_state(rbo->physics_object, true);
RB_body_set_loc_rot(rbo->physics_object, rbo->pos, rbo->orn);
RB_body_set_kinematic_state(rbo->shared->physics_object, true);
RB_body_set_loc_rot(rbo->shared->physics_object, rbo->pos, rbo->orn);
}
// RB_TODO update rigid body physics object's loc/rot for dynamic objects here as well (needs to be done outside bullet's update loop)
}
@ -1555,7 +1586,7 @@ void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], flo
void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw)
{
if (rbw) {
rbw->pointcache->flag |= PTCACHE_OUTDATED;
rbw->shared->pointcache->flag |= PTCACHE_OUTDATED;
}
}
@ -1572,7 +1603,7 @@ void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime
BKE_ptcache_id_from_rigidbody(&pid, NULL, rbw);
BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL);
cache = rbw->pointcache;
cache = rbw->shared->pointcache;
/* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */
int n = 0;
@ -1583,7 +1614,7 @@ void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
if (rbw->physics_world == NULL || rbw->numbodies != n) {
if (rbw->shared->physics_world == NULL || rbw->numbodies != n) {
cache->flag |= PTCACHE_OUTDATED;
}
@ -1609,7 +1640,7 @@ void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime
BKE_ptcache_id_from_rigidbody(&pid, NULL, rbw);
BKE_ptcache_id_time(&pid, scene, ctime, &startframe, &endframe, NULL);
cache = rbw->pointcache;
cache = rbw->shared->pointcache;
if (ctime <= startframe) {
rbw->ltime = startframe;
@ -1621,7 +1652,7 @@ void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime
}
/* don't try to run the simulation if we don't have a world yet but allow reading baked cache */
if (rbw->physics_world == NULL && !(cache->flag & PTCACHE_BAKED))
if (rbw->shared->physics_world == NULL && !(cache->flag & PTCACHE_BAKED))
return;
else if (rbw->objects == NULL)
rigidbody_update_ob_array(rbw);
@ -1636,6 +1667,12 @@ void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime
return;
}
if (!DEG_is_active(depsgraph)) {
/* When the depsgraph is inactive we should neither write to the cache
* nor run the simulation. */
return;
}
/* advance simulation, we can only step one frame forward */
if (compare_ff_relative(ctime, rbw->ltime + 1, FLT_EPSILON, 64)) {
/* write cache for first frame when on second frame */
@ -1649,7 +1686,7 @@ void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime
/* calculate how much time elapsed since last step in seconds */
timestep = 1.0f / (float)FPS * (ctime - rbw->ltime) * rbw->time_scale;
/* step simulation by the requested timestep, steps per second are adjusted to take time scale into account */
RB_dworld_step_simulation(rbw->physics_world, timestep, INT_MAX, 1.0f / (float)rbw->steps_per_second * min_ff(rbw->time_scale, 1.0f));
RB_dworld_step_simulation(rbw->shared->physics_world, timestep, INT_MAX, 1.0f / (float)rbw->steps_per_second * min_ff(rbw->time_scale, 1.0f));
rigidbody_update_simulation_post_step(depsgraph, rbw);
@ -1698,25 +1735,6 @@ void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime
#endif /* WITH_BULLET */
/* Copy the pointcache from the evaluated to the original scene.
* This allows the re-evaluation of the original scene to use the
* physics cache.
*/
static void rigidbody_copy_cache_to_orig(Scene *scene_eval)
{
if ((scene_eval->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0) {
/* Scene is already an original, this function is a no-op. */
return;
}
Scene *scene_orig = (Scene *)DEG_get_original_id(&scene_eval->id);
RigidBodyWorld *rbw_orig = scene_orig->rigidbody_world;
RigidBodyWorld *rbw_eval = scene_eval->rigidbody_world;
BKE_ptcache_free_list(&rbw_orig->ptcaches);
rbw_orig->pointcache = BKE_ptcache_copy_list(&rbw_orig->ptcaches, &rbw_eval->ptcaches, LIB_ID_COPY_CACHES);
}
/* -------------------- */
/* Depsgraph evaluation */
@ -1743,12 +1761,6 @@ void BKE_rigidbody_eval_simulation(Depsgraph *depsgraph,
return;
}
BKE_rigidbody_do_simulation(depsgraph, scene, ctime);
/* Make sure re-evaluation can use the cache from this simulation */
if (!DEG_is_active(depsgraph)) {
return;
}
rigidbody_copy_cache_to_orig(scene);
}
void BKE_rigidbody_object_sync_transforms(Depsgraph *depsgraph,

View File

@ -461,8 +461,7 @@ void BKE_scene_free_ex(Scene *sce, const bool do_id_user)
}
if (sce->rigidbody_world) {
BKE_rigidbody_free_world(sce->rigidbody_world);
sce->rigidbody_world = NULL;
BKE_rigidbody_free_world(sce);
}
if (sce->r.avicodecdata) {

View File

@ -5476,12 +5476,8 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->rigidbody_object = newdataadr(fd, ob->rigidbody_object);
if (ob->rigidbody_object) {
RigidBodyOb *rbo = ob->rigidbody_object;
/* must nullify the references to physics sim objects, since they no-longer exist
* (and will need to be recalculated)
*/
rbo->physics_object = NULL;
rbo->physics_shape = NULL;
/* Allocate runtime-only struct */
rbo->shared = MEM_callocN(sizeof(*rbo->shared), "RigidBodyObShared");
}
ob->rigidbody_constraint = newdataadr(fd, ob->rigidbody_constraint);
if (ob->rigidbody_constraint)
@ -6280,10 +6276,34 @@ static void direct_link_scene(FileData *fd, Scene *sce)
sce->rigidbody_world = newdataadr(fd, sce->rigidbody_world);
rbw = sce->rigidbody_world;
if (rbw) {
/* must nullify the reference to physics sim object, since it no-longer exist
* (and will need to be recalculated)
*/
rbw->physics_world = NULL;
rbw->shared = newdataadr(fd, rbw->shared);
if (rbw->shared == NULL) {
/* Link deprecated caches if they exist, so we can use them for versioning.
* We should only do this when rbw->shared == NULL, because those pointers
* are always set (for compatibility with older Blenders). We mustn't link
* the same pointcache twice. */
direct_link_pointcache_list(fd, &rbw->ptcaches, &rbw->pointcache, false);
/* make sure simulation starts from the beginning after loading file */
if (rbw->pointcache) {
rbw->ltime = (float)rbw->pointcache->startframe;
}
}
else {
/* must nullify the reference to physics sim object, since it no-longer exist
* (and will need to be recalculated)
*/
rbw->shared->physics_world = NULL;
/* link caches */
direct_link_pointcache_list(fd, &rbw->shared->ptcaches, &rbw->shared->pointcache, false);
/* make sure simulation starts from the beginning after loading file */
if (rbw->shared->pointcache) {
rbw->ltime = (float)rbw->shared->pointcache->startframe;
}
}
rbw->objects = NULL;
rbw->numbodies = 0;
@ -6291,13 +6311,6 @@ static void direct_link_scene(FileData *fd, Scene *sce)
rbw->effector_weights = newdataadr(fd, rbw->effector_weights);
if (!rbw->effector_weights)
rbw->effector_weights = BKE_add_effector_weights(NULL);
/* link cache */
direct_link_pointcache_list(fd, &rbw->ptcaches, &rbw->pointcache, false);
/* make sure simulation starts from the beginning after loading file */
if (rbw->pointcache) {
rbw->ltime = (float)rbw->pointcache->startframe;
}
}
sce->preview = direct_link_preview_image(fd, sce->preview);

View File

@ -49,6 +49,7 @@
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_particle_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_view3d_types.h"
@ -65,6 +66,7 @@
#include "BKE_main.h"
#include "BKE_mesh.h"
#include "BKE_node.h"
#include "BKE_pointcache.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
@ -1530,5 +1532,32 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
scene->toolsettings->manipulator_flag = SCE_MANIP_TRANSLATE | SCE_MANIP_ROTATE | SCE_MANIP_SCALE;
}
}
if (!DNA_struct_elem_find(fd->filesdna, "RigidBodyWorld", "RigidBodyWorld_Shared", "*shared")) {
for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
RigidBodyWorld *rbw = scene->rigidbody_world;
if (rbw == NULL) {
continue;
}
if (rbw->shared == NULL) {
rbw->shared = MEM_callocN(sizeof(*rbw->shared), "RigidBodyWorld_Shared");
}
/* Move shared pointers from deprecated location to current location */
rbw->shared->pointcache = rbw->pointcache;
rbw->shared->ptcaches = rbw->ptcaches;
rbw->pointcache = NULL;
BLI_listbase_clear(&rbw->ptcaches);
if (rbw->shared->pointcache == NULL) {
rbw->shared->pointcache = BKE_ptcache_add(&(rbw->shared->ptcaches));
}
}
}
}
}

View File

@ -2646,9 +2646,14 @@ static void write_scene(WriteData *wd, Scene *sce)
/* writing RigidBodyWorld data to the blend file */
if (sce->rigidbody_world) {
/* Set deprecated pointers to prevent crashes of older Blenders */
sce->rigidbody_world->pointcache = sce->rigidbody_world->shared->pointcache;
sce->rigidbody_world->ptcaches = sce->rigidbody_world->shared->ptcaches;
writestruct(wd, DATA, RigidBodyWorld, 1, sce->rigidbody_world);
writestruct(wd, DATA, RigidBodyWorld_Shared, 1, sce->rigidbody_world->shared);
writestruct(wd, DATA, EffectorWeights, 1, sce->rigidbody_world->effector_weights);
write_pointcaches(wd, &(sce->rigidbody_world->ptcaches));
write_pointcaches(wd, &(sce->rigidbody_world->shared->ptcaches));
}
write_previews(wd, sce->preview);

View File

@ -114,8 +114,7 @@ static int rigidbody_world_remove_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
BKE_rigidbody_free_world(rbw);
scene->rigidbody_world = NULL;
BKE_rigidbody_free_world(scene);
/* done */
return OPERATOR_FINISHED;
@ -152,14 +151,14 @@ 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->physics_world == NULL) {
if (rbw->shared->physics_world == NULL) {
BKE_report(op->reports, RPT_ERROR, "Rigid Body World has no associated physics data to export");
return OPERATOR_CANCELLED;
}
RNA_string_get(op->ptr, "filepath", path);
#ifdef WITH_BULLET
RB_dworld_export(rbw->physics_world, path);
RB_dworld_export(rbw->shared->physics_world, path);
#endif
return OPERATOR_FINISHED;
}

View File

@ -42,6 +42,16 @@ struct EffectorWeights;
/* ******************************** */
/* RigidBody World */
/* Container for data shared by original and evaluated copies of RigidBodyWorld */
typedef struct RigidBodyWorld_Shared {
/* cache */
struct PointCache *pointcache;
struct ListBase ptcaches;
/* References to Physics Sim objects. Exist at runtime only ---------------------- */
void *physics_world; /* Physics sim world (i.e. btDiscreteDynamicsWorld) */
} RigidBodyWorld_Shared;
/* RigidBodyWorld (rbw)
*
* Represents a "simulation scene" existing within the parent scene.
@ -58,9 +68,9 @@ typedef struct RigidBodyWorld {
int pad;
float ltime; /* last frame world was evaluated for (internal) */
/* cache */
struct PointCache *pointcache;
struct ListBase ptcaches;
struct RigidBodyWorld_Shared *shared; /* This pointer is shared between all evaluated copies */
struct PointCache *pointcache DNA_DEPRECATED; /* Moved to shared->pointcache */
struct ListBase ptcaches DNA_DEPRECATED; /* Moved to shared->ptcaches */
int numbodies; /* number of objects in rigid body group */
short steps_per_second; /* number of simulation steps thaken per second */
@ -68,9 +78,6 @@ typedef struct RigidBodyWorld {
int flag; /* (eRigidBodyWorld_Flag) settings for this RigidBodyWorld */
float time_scale; /* used to speed up or slow down the simulation */
/* References to Physics Sim objects. Exist at runtime only ---------------------- */
void *physics_world; /* Physics sim world (i.e. btDiscreteDynamicsWorld) */
} RigidBodyWorld;
/* Flags for RigidBodyWorld */
@ -86,6 +93,18 @@ typedef enum eRigidBodyWorld_Flag {
/* ******************************** */
/* RigidBody Object */
/* Container for data that is shared among CoW copies.
*
* This is placed in a separate struct so that, for example, the physics_shape
* pointer can be replaced without having to update all CoW copies. */
#
#
typedef struct RigidBodyOb_Shared {
/* References to Physics Sim objects. Exist at runtime only */
void *physics_object; /* Physics object representation (i.e. btRigidBody) */
void *physics_shape; /* Collision shape used by physics sim (i.e. btCollisionShape) */
} RigidBodyOb_Shared;
/* RigidBodyObject (rbo)
*
* Represents an object participating in a RigidBody sim.
@ -93,10 +112,6 @@ typedef enum eRigidBodyWorld_Flag {
* participating in a sim.
*/
typedef struct RigidBodyOb {
/* References to Physics Sim objects. Exist at runtime only */
void *physics_object; /* Physics object representation (i.e. btRigidBody) */
void *physics_shape; /* Collision shape used by physics sim (i.e. btCollisionShape) */
/* General Settings for this RigidBodyOb */
short type; /* (eRigidBodyOb_Type) role of RigidBody in sim */
short shape; /* (eRigidBody_Shape) collision shape to use */
@ -123,6 +138,8 @@ typedef struct RigidBodyOb {
float orn[4]; /* rigid body orientation */
float pos[3]; /* rigid body position */
float pad1;
struct RigidBodyOb_Shared *shared; /* This pointer is shared between all evaluated copies */
} RigidBodyOb;

View File

@ -124,8 +124,8 @@ static void rna_RigidBodyWorld_num_solver_iterations_set(PointerRNA *ptr, int va
rbw->num_solver_iterations = value;
#ifdef WITH_BULLET
if (rbw->physics_world) {
RB_dworld_set_solver_iterations(rbw->physics_world, value);
if (rbw->shared->physics_world) {
RB_dworld_set_solver_iterations(rbw->shared->physics_world, value);
}
#endif
}
@ -137,8 +137,8 @@ static void rna_RigidBodyWorld_split_impulse_set(PointerRNA *ptr, int value)
RB_FLAG_SET(rbw->flag, value, RBW_FLAG_USE_SPLIT_IMPULSE);
#ifdef WITH_BULLET
if (rbw->physics_world) {
RB_dworld_set_split_impulse(rbw->physics_world, value);
if (rbw->shared->physics_world) {
RB_dworld_set_split_impulse(rbw->shared->physics_world, value);
}
#endif
}
@ -167,7 +167,7 @@ static void rna_RigidBodyOb_shape_reset(Main *UNUSED(bmain), Scene *scene, Point
RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
BKE_rigidbody_cache_reset(rbw);
if (rbo->physics_shape)
if (rbo->shared->physics_shape)
rbo->flag |= RBO_FLAG_NEEDS_RESHAPE;
}
@ -201,9 +201,9 @@ static void rna_RigidBodyOb_disabled_set(PointerRNA *ptr, int value)
#ifdef WITH_BULLET
/* update kinematic state if necessary - only needed for active bodies */
if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
RB_body_set_kinematic_state(rbo->physics_object, !value);
if ((rbo->shared->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
RB_body_set_mass(rbo->shared->physics_object, RBO_GET_MASS(rbo));
RB_body_set_kinematic_state(rbo->shared->physics_object, !value);
rbo->flag |= RBO_FLAG_NEEDS_VALIDATE;
}
#endif
@ -217,8 +217,8 @@ static void rna_RigidBodyOb_mass_set(PointerRNA *ptr, float value)
#ifdef WITH_BULLET
/* only active bodies need mass update */
if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
if ((rbo->shared->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
RB_body_set_mass(rbo->shared->physics_object, RBO_GET_MASS(rbo));
}
#endif
}
@ -230,8 +230,8 @@ static void rna_RigidBodyOb_friction_set(PointerRNA *ptr, float value)
rbo->friction = value;
#ifdef WITH_BULLET
if (rbo->physics_object) {
RB_body_set_friction(rbo->physics_object, value);
if (rbo->shared->physics_object) {
RB_body_set_friction(rbo->shared->physics_object, value);
}
#endif
}
@ -242,8 +242,8 @@ static void rna_RigidBodyOb_restitution_set(PointerRNA *ptr, float value)
rbo->restitution = value;
#ifdef WITH_BULLET
if (rbo->physics_object) {
RB_body_set_restitution(rbo->physics_object, value);
if (rbo->shared->physics_object) {
RB_body_set_restitution(rbo->shared->physics_object, value);
}
#endif
}
@ -255,8 +255,8 @@ static void rna_RigidBodyOb_collision_margin_set(PointerRNA *ptr, float value)
rbo->margin = value;
#ifdef WITH_BULLET
if (rbo->physics_shape) {
RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo));
if (rbo->shared->physics_shape) {
RB_shape_set_margin(rbo->shared->physics_shape, RBO_GET_MARGIN(rbo));
}
#endif
}
@ -283,9 +283,9 @@ static void rna_RigidBodyOb_kinematic_state_set(PointerRNA *ptr, int value)
#ifdef WITH_BULLET
/* update kinematic state if necessary */
if (rbo->physics_object) {
RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
RB_body_set_kinematic_state(rbo->physics_object, value);
if (rbo->shared->physics_object) {
RB_body_set_mass(rbo->shared->physics_object, RBO_GET_MASS(rbo));
RB_body_set_kinematic_state(rbo->shared->physics_object, value);
rbo->flag |= RBO_FLAG_NEEDS_VALIDATE;
}
#endif
@ -299,8 +299,8 @@ static void rna_RigidBodyOb_activation_state_set(PointerRNA *ptr, int value)
#ifdef WITH_BULLET
/* update activation state if necessary - only active bodies can be deactivated */
if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
RB_body_set_activation_state(rbo->physics_object, value);
if ((rbo->shared->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
RB_body_set_activation_state(rbo->shared->physics_object, value);
}
#endif
}
@ -313,8 +313,8 @@ static void rna_RigidBodyOb_linear_sleepThresh_set(PointerRNA *ptr, float value)
#ifdef WITH_BULLET
/* only active bodies need sleep threshold update */
if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
RB_body_set_linear_sleep_thresh(rbo->physics_object, value);
if ((rbo->shared->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
RB_body_set_linear_sleep_thresh(rbo->shared->physics_object, value);
}
#endif
}
@ -327,8 +327,8 @@ static void rna_RigidBodyOb_angular_sleepThresh_set(PointerRNA *ptr, float value
#ifdef WITH_BULLET
/* only active bodies need sleep threshold update */
if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
RB_body_set_angular_sleep_thresh(rbo->physics_object, value);
if ((rbo->shared->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
RB_body_set_angular_sleep_thresh(rbo->shared->physics_object, value);
}
#endif
}
@ -341,8 +341,8 @@ static void rna_RigidBodyOb_linear_damping_set(PointerRNA *ptr, float value)
#ifdef WITH_BULLET
/* only active bodies need damping update */
if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
RB_body_set_linear_damping(rbo->physics_object, value);
if ((rbo->shared->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
RB_body_set_linear_damping(rbo->shared->physics_object, value);
}
#endif
}
@ -355,8 +355,8 @@ static void rna_RigidBodyOb_angular_damping_set(PointerRNA *ptr, float value)
#ifdef WITH_BULLET
/* only active bodies need damping update */
if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
RB_body_set_angular_damping(rbo->physics_object, value);
if ((rbo->shared->physics_object) && (rbo->type == RBO_TYPE_ACTIVE)) {
RB_body_set_angular_damping(rbo->shared->physics_object, value);
}
#endif
}
@ -706,8 +706,8 @@ static void rna_RigidBodyWorld_convex_sweep_test(
#ifdef WITH_BULLET
RigidBodyOb *rob = object->rigidbody_object;
if (rbw->physics_world != NULL && rob->physics_object != NULL) {
RB_world_convex_sweep_test(rbw->physics_world, rob->physics_object, ray_start, ray_end,
if (rbw->shared->physics_world != NULL && rob->shared->physics_object != NULL) {
RB_world_convex_sweep_test(rbw->shared->physics_world, rob->shared->physics_object, ray_start, ray_end,
r_location, r_hitpoint, r_normal, r_hit);
if (*r_hit == -2) {
BKE_report(reports, RPT_ERROR,
@ -723,6 +723,13 @@ static void rna_RigidBodyWorld_convex_sweep_test(
#endif
}
static PointerRNA rna_RigidBodyWorld_PointCache_get(PointerRNA *ptr)
{
RigidBodyWorld *rbw = ptr->data;
return rna_pointer_inherit_refine(ptr, &RNA_PointCache, rbw->shared->pointcache);
}
#else
static void rna_def_rigidbody_world(BlenderRNA *brna)
@ -801,7 +808,7 @@ static void rna_def_rigidbody_world(BlenderRNA *brna)
/* cache */
prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "pointcache");
RNA_def_property_pointer_funcs(prop, "rna_RigidBodyWorld_PointCache_get", NULL, NULL, NULL);
RNA_def_property_struct_type(prop, "PointCache");
RNA_def_property_ui_text(prop, "Point Cache", "");