Rigidbody: Add option to choose mesh source for collision shapes
authorSergej Reich <sergej.reich@googlemail.com>
Thu, 26 Dec 2013 16:02:28 +0000 (17:02 +0100)
committerSergej Reich <sergej.reich@googlemail.com>
Thu, 26 Dec 2013 17:38:05 +0000 (18:38 +0100)
The options are:
Base: Base mesh
Deform: shape keys and deform modifiers
Final: All deformations and modifiers

It would be nice to have a way of specifying where exactly in the
modifier stack the collision shape is generated. However this is not
staight forward since the rigid body simulation is not part of the
modifier system and would require hacks to make it work.

release/scripts/startup/bl_ui/properties_physics_rigidbody.py
source/blender/blenkernel/intern/rigidbody.c
source/blender/makesdna/DNA_rigidbody_types.h
source/blender/makesrna/intern/rna_rigidbody.c

index cd701178976c985b3e69e19525731484678a79c9..7a6c8e0a066ca47af06d6686a8a138de5d8fb493 100644 (file)
@@ -70,6 +70,9 @@ class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel):
 
         layout.prop(rbo, "collision_shape", text="Shape")
 
+        if rbo.collision_shape in {'MESH', 'CONVEX_HULL'}:
+            layout.prop(rbo, "mesh_source", text="Source")
+
         split = layout.split()
 
         col = split.column()
index 1a7782f4b899fc5ed51cf16f9d7573490addc90f..fa455fad0908ed2ab0196efc1c07b4ee7f1afba1 100644 (file)
@@ -225,26 +225,47 @@ void BKE_rigidbody_relink_constraint(RigidBodyCon *rbc)
 /* ************************************** */
 /* Setup Utilities - Validate Sim Instances */
 
+/* get the appropriate DerivedMesh based on rigid body mesh source */
+static DerivedMesh *rigidbody_get_mesh(Object *ob)
+{
+       if (ob->rigidbody_object->mesh_source == RBO_MESH_DEFORM) {
+               return ob->derivedDeform;
+       }
+       else if (ob->rigidbody_object->mesh_source == RBO_MESH_FINAL) {
+               return ob->derivedFinal;
+       }
+       else {
+               return CDDM_from_mesh(ob->data);
+       }
+}
+
 /* create collision shape of mesh - convex hull */
 static rbCollisionShape *rigidbody_get_shape_convexhull_from_mesh(Object *ob, float margin, bool *can_embed)
 {
        rbCollisionShape *shape = NULL;
-       Mesh *me = NULL;
+       DerivedMesh *dm = NULL;
+       MVert *mvert = NULL;
+       int totvert = 0;
 
        if (ob->type == OB_MESH && ob->data) {
-               me = ob->data;
+               dm = rigidbody_get_mesh(ob);
+               mvert   = (dm) ? dm->getVertArray(dm) : NULL;
+               totvert = (dm) ? dm->getNumVerts(dm) : 0;
        }
        else {
                printf("ERROR: cannot make Convex Hull collision shape for non-Mesh object\n");
        }
 
-       if (me && me->totvert) {
-               shape = RB_shape_new_convex_hull((float *)me->mvert, sizeof(MVert), me->totvert, margin, can_embed);
+       if (totvert) {
+               shape = RB_shape_new_convex_hull((float *)mvert, sizeof(MVert), totvert, margin, can_embed);
        }
        else {
                printf("ERROR: no vertices to define Convex Hull collision shape with\n");
        }
 
+       if (dm && ob->rigidbody_object->mesh_source == RBO_MESH_BASE)
+               dm->release(dm);
+
        return shape;
 }
 
@@ -256,14 +277,18 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
        rbCollisionShape *shape = NULL;
 
        if (ob->type == OB_MESH) {
-               DerivedMesh *dm = CDDM_from_mesh(ob->data);
-
+               DerivedMesh *dm = NULL;
                MVert *mvert;
                MFace *mface;
                int totvert;
                int totface;
 
+               dm = rigidbody_get_mesh(ob);
+
                /* ensure mesh validity, then grab data */
+               if (dm == NULL)
+                       return NULL;
+
                DM_ensure_tessface(dm);
 
                mvert   = (dm) ? dm->getVertArray(dm) : NULL;
@@ -323,7 +348,7 @@ static rbCollisionShape *rigidbody_get_shape_trimesh_from_mesh(Object *ob)
                }
 
                /* cleanup temp data */
-               if (dm) {
+               if (dm && ob->rigidbody_object->mesh_source == RBO_MESH_BASE) {
                        dm->release(dm);
                }
        }
@@ -425,7 +450,8 @@ void BKE_rigidbody_validate_sim_shape(Object *ob, short rebuild)
                rbo->physics_shape = new_shape;
                RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo));
        }
-       else { /* otherwise fall back to box shape */
+       /* use box shape if we can't fall back to old shape */
+       else if (rbo->physics_shape == NULL) {
                rbo->shape = RB_SHAPE_BOX;
                BKE_rigidbody_validate_sim_shape(ob, true);
        }
@@ -798,6 +824,8 @@ RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
        else
                rbo->shape = RB_SHAPE_TRIMESH;
 
+       rbo->mesh_source = RBO_MESH_DEFORM;
+
        /* set initial transform */
        mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat);
 
index 4a96c324f0490d2705aa65c34146a95cdf49dea9..de23a3c2370e5a5f15253faf906f5f0b9f8a4a20 100644 (file)
@@ -103,7 +103,8 @@ typedef struct RigidBodyOb {
        
        int flag;                               /* (eRigidBodyOb_Flag) */
        int col_groups;                 /* Collision groups that determines wich rigid bodies can collide with each other */
-       int pad;
+       short mesh_source;              /* (eRigidBody_MeshSource) mesh source for mesh based collision shapes */
+       short pad;
        
        /* Physics Parameters */
        float mass;                             /* how much object 'weighs' (i.e. absolute 'amount of stuff' it holds) */
@@ -173,6 +174,15 @@ typedef enum eRigidBody_Shape {
        //RB_SHAPE_COMPOUND,
 } eRigidBody_Shape;
 
+typedef enum eRigidBody_MeshSource {
+       /* base mesh */
+       RBO_MESH_BASE = 0,
+       /* only deformations */
+       RBO_MESH_DEFORM,
+       /* final derived mesh */
+       RBO_MESH_FINAL
+} eRigidBody_MeshSource;
+
 /* ******************************** */
 /* RigidBody Constraint */
 
index cc14e60f45a900618819fa5234afbf019734b7fa..34b0f6a335a02bd467b885c3a69544550de0e0ed 100644 (file)
@@ -76,6 +76,13 @@ EnumPropertyItem rigidbody_constraint_type_items[] = {
        {RBC_TYPE_MOTOR, "MOTOR", ICON_NONE, "Motor", "Drive rigid body around or along an axis"},
        {0, NULL, 0, NULL, NULL}};
 
+/* mesh source for collision shape creation */
+EnumPropertyItem rigidbody_mesh_source_items[] = {
+       {RBO_MESH_BASE, "BASE", 0, "Base", "Base mesh"},
+       {RBO_MESH_DEFORM, "DEFORM", 0, "Deform", "Deformations (shaps keys, deform modifiers"},
+       {RBO_MESH_FINAL, "FINAL", 0, "Final", "All modifiers"},
+       {0, NULL, 0, NULL, NULL}};
+
 
 #ifdef RNA_RUNTIME
 
@@ -769,6 +776,13 @@ static void rna_def_rigidbody_object(BlenderRNA *brna)
        RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
        RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
        
+       prop = RNA_def_property(srna, "mesh_source", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "mesh_source");
+       RNA_def_property_enum_items(prop, rigidbody_mesh_source_items);
+       RNA_def_property_ui_text(prop, "Mesh Source", "Source of the mesh used to create collision shape");
+       RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+       
        /* booleans */
        prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", RBO_FLAG_DISABLED);