Merge branch 'master' into blender2.8
[blender.git] / source / blender / blenkernel / intern / rigidbody.c
index 68bc6c407aca52581e7ea3b182dbdc2bc6bd5bde..4e6d6cf097166ea935bd62a60fe89ddbd518fb3d 100644 (file)
@@ -61,6 +61,7 @@
 #include "BKE_layer.h"
 #include "BKE_library.h"
 #include "BKE_library_query.h"
+#include "BKE_main.h"
 #include "BKE_mesh.h"
 #include "BKE_mesh_runtime.h"
 #include "BKE_object.h"
@@ -148,7 +149,7 @@ void BKE_rigidbody_free_world(Scene *scene)
 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;
+       RigidBodyOb *rbo = ob->rigidbody_object;
 
        /* sanity check */
        if (rbo == NULL)
@@ -410,9 +411,9 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild)
                return;
 
        /* if automatically determining dimensions, use the Object's boundbox
-        *      - assume that all quadrics are standing upright on local z-axis
-        *      - assume even distribution of mass around the Object's pivot
-        *        (i.e. Object pivot is centralized in boundbox)
+        * - assume that all quadrics are standing upright on local z-axis
+        * - assume even distribution of mass around the Object's pivot
+        *   (i.e. Object pivot is centralized in boundbox)
         */
        // XXX: all dimensions are auto-determined now... later can add stored settings for this
        /* get object dimensions without scaling */
@@ -498,10 +499,10 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol)
        float volume = 0.0f;
 
        /* if automatically determining dimensions, use the Object's boundbox
-        *      - assume that all quadrics are standing upright on local z-axis
-        *      - assume even distribution of mass around the Object's pivot
-        *        (i.e. Object pivot is centralized in boundbox)
-        *      - boundbox gives full width
+        * - assume that all quadrics are standing upright on local z-axis
+        * - assume even distribution of mass around the Object's pivot
+        *   (i.e. Object pivot is centralized in boundbox)
+        * - boundbox gives full width
         */
        // XXX: all dimensions are auto-determined now... later can add stored settings for this
        BKE_object_dimensions_get(ob, size);
@@ -583,10 +584,10 @@ void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3])
        zero_v3(r_center);
 
        /* if automatically determining dimensions, use the Object's boundbox
-        *      - assume that all quadrics are standing upright on local z-axis
-        *      - assume even distribution of mass around the Object's pivot
-        *        (i.e. Object pivot is centralized in boundbox)
-        *      - boundbox gives full width
+        * - assume that all quadrics are standing upright on local z-axis
+        * - assume even distribution of mass around the Object's pivot
+        *   (i.e. Object pivot is centralized in boundbox)
+        * - boundbox gives full width
         */
        // XXX: all dimensions are auto-determined now... later can add stored settings for this
        BKE_object_dimensions_get(ob, size);
@@ -642,7 +643,7 @@ void BKE_rigidbody_calc_center_of_mass(Object *ob, float r_center[3])
 /**
  * Create physics sim representation of object given RigidBody settings
  *
- * \param rebuild Even if an instance already exists, replace it
+ * \param rebuild: Even if an instance already exists, replace it
  */
 static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool rebuild)
 {
@@ -651,7 +652,7 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool
        float rot[4];
 
        /* sanity checks:
-        *      - object doesn't have RigidBody info already: then why is it here?
+        * - object doesn't have RigidBody info already: then why is it here?
         */
        if (rbo == NULL)
                return;
@@ -770,7 +771,7 @@ static void rigidbody_constraint_set_limits(
 /**
  * Create physics sim representation of constraint given rigid body constraint settings
  *
- * \param rebuild Even if an instance already exists, replace it
+ * \param rebuild: Even if an instance already exists, replace it
  */
 static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, bool rebuild)
 {
@@ -783,8 +784,8 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
        float ang_upper;
 
        /* sanity checks:
-        *      - object should have a rigid body constraint
-        *  - rigid body constraint should have at least one constrained object
+        * - object should have a rigid body constraint
+        * - rigid body constraint should have at least one constrained object
         */
        if (rbc == NULL) {
                return;
@@ -944,8 +945,8 @@ RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene)
        RigidBodyWorld *rbw;
 
        /* sanity checks
-        *      - there must be a valid scene to add world to
-        *      - there mustn't be a sim world using this group already
+        * - there must be a valid scene to add world to
+        * - there mustn't be a sim world using this group already
         */
        if (scene == NULL)
                return NULL;
@@ -955,7 +956,7 @@ RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene)
        rbw->shared = MEM_callocN(sizeof(*rbw->shared), "RigidBodyWorld_Shared");
 
        /* set default settings */
-       rbw->effector_weights = BKE_add_effector_weights(NULL);
+       rbw->effector_weights = BKE_effector_add_weights(NULL);
 
        rbw->ltime = PSFRA;
 
@@ -1025,9 +1026,9 @@ RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
        RigidBodyWorld *rbw = scene->rigidbody_world;
 
        /* sanity checks
-        *      - rigidbody world must exist
-        *      - object must exist
-        *      - cannot add rigid body if it already exists
+        * - rigidbody world must exist
+        * - object must exist
+        * - cannot add rigid body if it already exists
         */
        if (ob == NULL || (ob->rigidbody_object != NULL))
                return NULL;
@@ -1069,6 +1070,7 @@ RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
 
        /* flag cache as outdated */
        BKE_rigidbody_cache_reset(rbw);
+       rbo->flag |= (RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE);
 
        /* return this object */
        return rbo;
@@ -1081,9 +1083,9 @@ RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short ty
        RigidBodyWorld *rbw = scene->rigidbody_world;
 
        /* sanity checks
-        *      - rigidbody world must exist
-        *      - object must exist
-        *      - cannot add constraint if it already exists
+        * - rigidbody world must exist
+        * - object must exist
+        * - cannot add constraint if it already exists
         */
        if (ob == NULL || (ob->rigidbody_constraint != NULL))
                return NULL;
@@ -1099,6 +1101,7 @@ RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short ty
 
        rbc->flag |= RBC_FLAG_ENABLED;
        rbc->flag |= RBC_FLAG_DISABLE_COLLISIONS;
+       rbc->flag |= RBC_FLAG_NEEDS_VALIDATE;
 
        rbc->spring_type = RBC_SPRING_TYPE2;
 
@@ -1143,12 +1146,58 @@ RigidBodyCon *BKE_rigidbody_create_constraint(Scene *scene, Object *ob, short ty
        return rbc;
 }
 
+void BKE_rigidbody_objects_collection_validate(Scene *scene, RigidBodyWorld *rbw)
+{
+       if (rbw->group != NULL) {
+               FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->group, object)
+               {
+                       if (object->type != OB_MESH || object->rigidbody_object != NULL) {
+                               continue;
+                       }
+                       object->rigidbody_object = BKE_rigidbody_create_object(scene, object, RBO_TYPE_ACTIVE);
+               }
+               FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+       }
+}
+
+void BKE_rigidbody_constraints_collection_validate(Scene *scene, RigidBodyWorld *rbw)
+{
+       if (rbw->constraints != NULL) {
+               FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(rbw->constraints, object)
+               {
+                       if (object->rigidbody_constraint != NULL) {
+                               continue;
+                       }
+                       object->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, object, RBC_TYPE_FIXED);
+               }
+               FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+       }
+}
+
+void BKE_rigidbody_main_collection_object_add(Main *bmain, Collection *collection, Object *object)
+{
+       for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+               RigidBodyWorld *rbw = scene->rigidbody_world;
+
+               if (rbw == NULL) {
+                       continue;
+               }
+
+               if (rbw->group == collection && object->type == OB_MESH && object->rigidbody_object == NULL) {
+                       object->rigidbody_object = BKE_rigidbody_create_object(scene, object, RBO_TYPE_ACTIVE);
+               }
+               if (rbw->constraints == collection && object->rigidbody_constraint == NULL) {
+                       object->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, object, RBC_TYPE_FIXED);
+               }
+       }
+}
+
 /* ************************************** */
 /* Utilities API */
 
 /* Get RigidBody world for the given scene, creating one if needed
  *
- * \param scene Scene to find active Rigid Body world for
+ * \param scene: Scene to find active Rigid Body world for
  */
 RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene)
 {
@@ -1332,7 +1381,7 @@ static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Scene *scene, RigidBod
                        pd_point_from_loc(scene, eff_loc, eff_vel, 0, &epoint);
 
                        /* calculate net force of effectors, and apply to sim object
-                        *      - we use 'central force' since apply force requires a "relative position" which we don't have...
+                        * - we use 'central force' since apply force requires a "relative position" which we don't have...
                         */
                        BKE_effectors_apply(effectors, NULL, effector_weights, &epoint, eff_force, NULL);
                        if (G.f & G_DEBUG)
@@ -1358,7 +1407,7 @@ static void rigidbody_update_sim_ob(Depsgraph *depsgraph, Scene *scene, RigidBod
 /**
  * Updates and validates world, bodies and shapes.
  *
- * \param rebuild Rebuild entire simulation
+ * \param rebuild: Rebuild entire simulation
  */
 static void rigidbody_update_simulation(Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, bool rebuild)
 {
@@ -1395,10 +1444,13 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph, Scene *scene, Rigi
                        /* update transformation matrix of the object so we don't get a frame of lag for simple animations */
                        BKE_object_where_is_calc(depsgraph, scene, ob);
 
+                       /* TODO remove this whole block once we are sure we never get NULL rbo here anymore. */
+                       /* This cannot be done in CoW evaluation context anymore... */
                        if (rbo == NULL) {
+                               BLI_assert(!"CoW object part of RBW object collection without RB object data, should not happen.\n");
                                /* Since this object is included in the sim group but doesn't have
                                 * rigid body settings (perhaps it was added manually), add!
-                                *      - assume object to be active? That is the default for newly added settings...
+                                * - assume object to be active? That is the default for newly added settings...
                                 */
                                ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, RBO_TYPE_ACTIVE);
                                rigidbody_validate_sim_object(rbw, ob, true);
@@ -1426,8 +1478,8 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph, Scene *scene, Rigi
                                        // 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->shared->physics_object, rbo->shared->physics_shape);
                                }
-                               rbo->flag &= ~(RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE);
                        }
+                       rbo->flag &= ~(RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE);
 
                        /* update simulation object... */
                        rigidbody_update_sim_ob(depsgraph, scene, rbw, ob, rbo);
@@ -1446,7 +1498,10 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph, Scene *scene, Rigi
                /* update transformation matrix of the object so we don't get a frame of lag for simple animations */
                BKE_object_where_is_calc(depsgraph, scene, ob);
 
+               /* TODO remove this whole block once we are sure we never get NULL rbo here anymore. */
+               /* This cannot be done in CoW evaluation context anymore... */
                if (rbc == NULL) {
+                       BLI_assert(!"CoW object part of RBW constraints collection without RB constraint data, should not happen.\n");
                        /* Since this object is included in the group but doesn't have
                         * constraint settings (perhaps it was added manually), add!
                         */
@@ -1464,8 +1519,8 @@ static void rigidbody_update_simulation(Depsgraph *depsgraph, Scene *scene, Rigi
                        else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) {
                                rigidbody_validate_sim_constraint(rbw, ob, false);
                        }
-                       rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
                }
+               rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
        }
        FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
 }
@@ -1735,6 +1790,9 @@ bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime) { return
 void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {}
 void BKE_rigidbody_rebuild_world(Depsgraph *depsgraph, Scene *scene, float ctime) {}
 void BKE_rigidbody_do_simulation(Depsgraph *depsgraph, Scene *scene, float ctime) {}
+void BKE_rigidbody_objects_collection_validate(Scene *scene, RigidBodyWorld *rbw) {}
+void BKE_rigidbody_constraints_collection_validate(Scene *scene, RigidBodyWorld *rbw) {}
+void BKE_rigidbody_main_collection_object_add(Main *bmain, Collection *collection, Object *object) {}
 
 #if defined(__GNUC__) || defined(__clang__)
 #  pragma GCC diagnostic pop