rigidbody: Add DNA/RNA/BKE infrastructure for the rigid body sim
authorSergej Reich <sergej.reich@googlemail.com>
Wed, 23 Jan 2013 05:56:22 +0000 (05:56 +0000)
committerSergej Reich <sergej.reich@googlemail.com>
Wed, 23 Jan 2013 05:56:22 +0000 (05:56 +0000)
This is just the basic structure, the simulation isn't hooked up yet.

Scenes get a pointer to a rigid body world that holds rigid body objects.
Objects get a pointer to a rigdid body object.

Both rigid body world and objects aren't used directly in the simulation
and only hold information to create the actual physics objects.

Physics objects are created when rigid body objects are validated.
In order to keep blender and bullet objects in sync care has to be taken
to either call appropriate set functions or flag objects for validation.

Part of GSoC 2010 and 2012.
Authors: Joshua Leung (aligorith), Sergej Reich (sergof)

27 files changed:
source/blender/CMakeLists.txt
source/blender/SConscript
source/blender/blenkernel/BKE_rigidbody.h [new file with mode: 0644]
source/blender/blenkernel/BKE_scene.h
source/blender/blenkernel/CMakeLists.txt
source/blender/blenkernel/SConscript
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/rigidbody.c [new file with mode: 0644]
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_relations.c
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_rigidbody_types.h [new file with mode: 0644]
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/intern/makesdna.c
source/blender/makesrna/RNA_access.h
source/blender/makesrna/RNA_enum_types.h
source/blender/makesrna/SConscript
source/blender/makesrna/intern/CMakeLists.txt
source/blender/makesrna/intern/makesrna.c
source/blender/makesrna/intern/rna_internal.h
source/blender/makesrna/intern/rna_object.c
source/blender/makesrna/intern/rna_rigidbody.c [new file with mode: 0644]
source/blender/makesrna/intern/rna_scene.c

index 9c6dd02..db31321 100644 (file)
@@ -66,6 +66,7 @@ set(SRC_DNA_INC
        ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_packedFile_types.h
        ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_particle_types.h
        ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_property_types.h
+       ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_rigidbody_types.h
        ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_scene_types.h
        ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_screen_types.h
        ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_sdna_types.h
index bf52f2e..80457c7 100644 (file)
@@ -61,6 +61,9 @@ if env['WITH_BF_OPENEXR']:
 if env['WITH_BF_QUICKTIME']:
     SConscript (['quicktime/SConscript'])
 
+if env['WITH_BF_BULLET']:
+    SConscript (['rigidbody/SConscript'])
+
 if env['WITH_BF_COLLADA']:
     SConscript (['collada/SConscript'])
     
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
new file mode 100644 (file)
index 0000000..26a0038
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung, Sergej Reich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file BKE_rigidbody.h
+ *  \ingroup blenkernel
+ *  \brief API for Blender-side Rigid Body stuff
+ */
+
+#ifndef __BKE_RIGIDBODY_H__
+#define __BKE_RIGIDBODY_H__
+
+struct RigidBodyWorld;
+struct RigidBodyOb;
+
+struct Scene;
+struct Object;
+struct Group;
+
+/* -------------- */
+/* Memory Management */
+
+void BKE_rigidbody_free_world(struct RigidBodyWorld *rbw);
+void BKE_rigidbody_free_object(struct Object *ob);
+void BKE_rigidbody_free_constraint(struct Object *ob);
+
+/* ...... */
+
+struct RigidBodyOb *BKE_rigidbody_copy_object(struct Object *ob);
+struct RigidBodyCon *BKE_rigidbody_copy_constraint(struct Object *ob);
+
+/* -------------- */
+/* Setup */
+
+/* create Blender-side settings data - physics objects not initialised yet */
+struct RigidBodyWorld *BKE_rigidbody_create_world(struct Scene *scene);
+struct RigidBodyOb *BKE_rigidbody_create_object(struct Scene *scene, struct Object *ob, short type);
+struct RigidBodyCon *BKE_rigidbody_create_constraint(struct Scene *scene, struct Object *ob, short type);
+
+/* 'validate' (i.e. make new or replace old) Physics-Engine objects */
+void BKE_rigidbody_validate_sim_world(struct Scene *scene, struct RigidBodyWorld *rbw, short rebuild);
+void BKE_rigidbody_validate_sim_object(struct RigidBodyWorld *rbw, struct Object *ob, short rebuild);
+void BKE_rigidbody_validate_sim_shape(struct Object *ob, short rebuild);
+void BKE_rigidbody_validate_sim_constraint(struct RigidBodyWorld *rbw, struct Object *ob, short rebuild);
+
+/* -------------- */
+/* Utilities */
+
+struct RigidBodyWorld *BKE_rigidbody_get_world(struct Scene *scene);
+void BKE_rigidbody_remove_object(struct Scene *scene, struct Object *ob);
+void BKE_rigidbody_remove_constraint(struct Scene *scene, struct Object *ob);
+
+/* -------------- */
+/* Utility Macros */
+
+/* get mass of Rigid Body Object to supply to RigidBody simulators */
+#define RBO_GET_MASS(rbo) \
+       ((rbo && ((rbo->type == RBO_TYPE_PASSIVE) || (rbo->flag & RBO_FLAG_KINEMATIC) || (rbo->flag & RBO_FLAG_DISABLED))) ? (0.0f) : (rbo->mass))
+/* get collision margin for Rigid Body Object, triangle mesh and cone shapes cannot embed margin, convex hull always uses custom margin */
+#define RBO_GET_MARGIN(rbo) \
+       ((rbo->flag & RBO_FLAG_USE_MARGIN || rbo->shape == RB_SHAPE_CONVEXH || rbo->shape == RB_SHAPE_TRIMESH || rbo->shape == RB_SHAPE_CONE) ? (rbo->margin) : (0.04f))
+
+/* -------------- */
+/* Simulation */
+
+void BKE_rigidbody_sync_transforms(struct Scene *scene, struct Object *ob, float ctime);
+void BKE_rigidbody_cache_reset(struct RigidBodyWorld *rbw);
+void BKE_rigidbody_do_simulation(struct Scene *scene, float ctime);
+
+#endif /* __BKE_RIGIDBODY_H__ */
index 6447b2a..2ac32a3 100644 (file)
@@ -72,6 +72,7 @@ struct Scene *BKE_scene_add(struct Main *bmain, const char *name);
 /* base functions */
 struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob);
 struct Base *BKE_scene_base_add(struct Scene *sce, struct Object *ob);
+void         BKE_scene_base_remove(struct Scene *sce, struct Base *base);
 void         BKE_scene_base_deselect_all(struct Scene *sce);
 void         BKE_scene_base_select(struct Scene *sce, struct Base *selbase);
 int          BKE_scene_base_iter_next(struct Scene **scene, int val, struct Base **base, struct Object **ob);
@@ -115,6 +116,7 @@ int BKE_scene_use_new_shading_nodes(struct Scene *scene);
 
 void BKE_scene_disable_color_management(struct Scene *scene);
 int BKE_scene_check_color_management_enabled(const struct Scene *scene);
+int BKE_scene_check_rigidbody_active(const struct Scene *scene);
 
 #ifdef __cplusplus
 }
index aca06a1..846ed8a 100644 (file)
@@ -37,6 +37,7 @@ set(INC
        ../modifiers
        ../nodes
        ../render/extern/include
+       ../rigidbody
        ../../../intern/guardedalloc
        ../../../intern/iksolver/extern
        ../../../intern/memutil
@@ -128,6 +129,7 @@ set(SRC
        intern/pointcache.c
        intern/property.c
        intern/report.c
+       intern/rigidbody.c
        intern/sca.c
        intern/scene.c
        intern/screen.c
@@ -219,6 +221,7 @@ set(SRC
        BKE_pointcache.h
        BKE_property.h
        BKE_report.h
+       BKE_rigidbody.h
        BKE_sca.h
        BKE_scene.h
        BKE_screen.h
index 0286172..b146235 100644 (file)
@@ -41,6 +41,7 @@ incs += ' ../render/extern/include ../makesrna'
 incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes ../modifiers'
 incs += ' #/intern/iksolver/extern ../blenloader'
 incs += ' #/extern/bullet2/src'
+incs += ' ../rigidbody'
 incs += ' #/intern/opennl/extern #/intern/bsp/extern'
 incs += ' ../gpu #/extern/glew/include'
 incs += ' ../bmesh'
index 4238956..78d7bfa 100644 (file)
@@ -2290,7 +2290,7 @@ static short animdata_use_time(AnimData *adt)
        return 0;
 }
 
-static void dag_object_time_update_flags(Object *ob)
+static void dag_object_time_update_flags(Scene *scene, Object *ob)
 {
        if (ob->constraints.first) {
                bConstraint *con;
@@ -2350,6 +2350,9 @@ static void dag_object_time_update_flags(Object *ob)
        if (object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA;
        if ((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA;
        
+       if (ob->rigidbody_object && BKE_scene_check_rigidbody_active(scene))
+               ob->recalc |= OB_RECALC_OB;
+       
        {
                AnimData *adt = BKE_animdata_from_id((ID *)ob->data);
                Mesh *me;
@@ -2434,7 +2437,7 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s
                if (do_time) {
                        /* now if DagNode were part of base, the node->lay could be checked... */
                        /* we do all now, since the scene_flush checks layers and clears recalc flags even */
-                       dag_object_time_update_flags(ob);
+                       dag_object_time_update_flags(scene, ob);
                }
 
                /* handled in next loop */
@@ -2447,7 +2450,7 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s
                for (group = bmain->group.first; group; group = group->id.next) {
                        if (group->id.flag & LIB_DOIT) {
                                for (go = group->gobject.first; go; go = go->next) {
-                                       dag_object_time_update_flags(go->ob);
+                                       dag_object_time_update_flags(scene, go->ob);
                                }
                        }
                }
@@ -2466,7 +2469,7 @@ void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const s
 
                /* hrmf... an exception to look at once, for invisible camera object we do it over */
                if (scene->camera)
-                       dag_object_time_update_flags(scene->camera);
+                       dag_object_time_update_flags(scene, scene->camera);
        }
 
        /* and store the info in groupobject */
index 05031dd..2738c54 100644 (file)
@@ -98,6 +98,7 @@
 #include "BKE_particle.h"
 #include "BKE_pointcache.h"
 #include "BKE_property.h"
+#include "BKE_rigidbody.h"
 #include "BKE_sca.h"
 #include "BKE_scene.h"
 #include "BKE_sequencer.h"
@@ -386,6 +387,7 @@ void BKE_object_free(Object *ob)
        BKE_free_constraints(&ob->constraints);
        
        free_partdeflect(ob->pd);
+       BKE_rigidbody_free_object(ob);
 
        if (ob->soft) sbFree(ob->soft);
        if (ob->bsoft) bsbFree(ob->bsoft);
@@ -1288,6 +1290,7 @@ static Object *object_copy_do(Object *ob, int copy_caches)
        obn->bsoft = copy_bulletsoftbody(ob->bsoft);
 
        BKE_object_copy_particlesystems(obn, ob);
+       obn->rigidbody_object = BKE_rigidbody_copy_object(ob);
        
        obn->derivedDeform = NULL;
        obn->derivedFinal = NULL;
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
new file mode 100644 (file)
index 0000000..e6f6c9a
--- /dev/null
@@ -0,0 +1,718 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung, Sergej Reich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file rigidbody.c
+ *  \ingroup blenkernel
+ *  \brief Blender-side interface and methods for dealing with Rigid Body simulations
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stddef.h>
+#include <float.h>
+#include <math.h>
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+
+#include "RBI_api.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_group_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_rigidbody_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_cdderivedmesh.h"
+#include "BKE_effect.h"
+#include "BKE_group.h"
+#include "BKE_object.h"
+#include "BKE_mesh.h"
+#include "BKE_pointcache.h"
+#include "BKE_rigidbody.h"
+#include "BKE_global.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+
+/* ************************************** */
+/* Memory Management */
+
+/* Freeing Methods --------------------- */
+
+/* Free rigidbody world */
+void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
+{
+       GroupObject *go;
+       /* sanity check */
+       if (!rbw)
+               return;
+
+       if (rbw->physics_world) {
+               /* free physics references, we assume that all physics objects in will have been added to the world */
+               if (rbw->group) {
+                       for (go = rbw->group->gobject.first; go; go = go->next) {
+                               if (go->ob && go->ob->rigidbody_object) {
+                                       RigidBodyOb *rbo = go->ob->rigidbody_object;
+
+                                       if (rbo->physics_object)
+                                               RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
+                               }
+                       }
+               }
+               /* free dynamics world */
+               RB_dworld_delete(rbw->physics_world);
+       }
+       if (rbw->objects)
+               free(rbw->objects);
+
+       /* free rigidbody world itself */
+       MEM_freeN(rbw);
+}
+
+/* Free RigidBody settings and sim instances */
+void BKE_rigidbody_free_object(Object *ob)
+{
+       RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL;
+
+       /* sanity check */
+       if (rbo == NULL)
+               return;
+
+       /* free physics references */
+       if (rbo->physics_object) {
+               RB_body_delete(rbo->physics_object);
+               rbo->physics_object = NULL;
+       }
+
+       if (rbo->physics_shape) {
+               RB_shape_delete(rbo->physics_shape);
+               rbo->physics_shape = NULL;
+       }
+
+       /* free data itself */
+       MEM_freeN(rbo);
+       ob->rigidbody_object = NULL;
+}
+
+/* Copying Methods --------------------- */
+
+/* These just copy the data, clearing out references to physics objects.
+ * Anything that uses them MUST verify that the copied object will
+ * be added to relevant groups later...
+ */
+
+RigidBodyOb *BKE_rigidbody_copy_object(Object *ob)
+{
+       RigidBodyOb *rboN = NULL;
+
+       if (ob->rigidbody_object) {
+               /* just duplicate the whole struct first (to catch all the settings) */
+               rboN = MEM_dupallocN(ob->rigidbody_object);
+
+               /* 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 */
+       return rboN;
+}
+
+/* ************************************** */
+/* Setup Utilities - Validate Sim Instances */
+
+/* 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;
+
+       if (ob->type == OB_MESH && ob->data) {
+               me = ob->data;
+       }
+       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);
+       }
+       else {
+               printf("ERROR: no vertices to define Convex Hull collision shape with\n");
+       }
+
+       return shape;
+}
+
+/* create collision shape of mesh - triangulated mesh
+ * returns NULL if creation fails.
+ */
+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, ob);
+
+               MVert *mvert;
+               MFace *mface;
+               int totvert;
+               int totface;
+
+               /* ensure mesh validity, then grab data */
+               DM_ensure_tessface(dm);
+
+               mvert   = (dm) ? dm->getVertArray(dm) : NULL;
+               totvert = (dm) ? dm->getNumVerts(dm) : 0;
+               mface   = (dm) ? dm->getTessFaceArray(dm) : NULL;
+               totface = (dm) ? dm->getNumTessFaces(dm) : 0;
+
+               /* sanity checking - potential case when no data will be present */
+               if ((totvert == 0) || (totface == 0)) {
+                       printf("WARNING: no geometry data converted for Mesh Collision Shape (ob = %s)\n", ob->id.name + 2);
+               }
+               else {
+                       rbMeshData *mdata;
+                       int i;
+
+                       /* init mesh data for collision shape */
+                       mdata = RB_trimesh_data_new();
+
+                       /* loop over all faces, adding them as triangles to the collision shape
+                        * (so for some faces, more than triangle will get added)
+                        */
+                       for (i = 0; (i < totface) && (mface) && (mvert); i++, mface++) {
+                               /* add first triangle - verts 1,2,3 */
+                               {
+                                       MVert *va = (IN_RANGE(mface->v1, 0, totvert)) ? (mvert + mface->v1) : (mvert);
+                                       MVert *vb = (IN_RANGE(mface->v2, 0, totvert)) ? (mvert + mface->v2) : (mvert);
+                                       MVert *vc = (IN_RANGE(mface->v3, 0, totvert)) ? (mvert + mface->v3) : (mvert);
+
+                                       RB_trimesh_add_triangle(mdata, va->co, vb->co, vc->co);
+                               }
+
+                               /* add second triangle if needed - verts 1,3,4 */
+                               if (mface->v4) {
+                                       MVert *va = (IN_RANGE(mface->v1, 0, totvert)) ? (mvert + mface->v1) : (mvert);
+                                       MVert *vb = (IN_RANGE(mface->v3, 0, totvert)) ? (mvert + mface->v3) : (mvert);
+                                       MVert *vc = (IN_RANGE(mface->v4, 0, totvert)) ? (mvert + mface->v4) : (mvert);
+
+                                       RB_trimesh_add_triangle(mdata, va->co, vb->co, vc->co);
+                               }
+                       }
+
+                       /* construct collision shape
+                        *
+                        * These have been chosen to get better speed/accuracy tradeoffs with regards
+                        * to limitations of each:
+                        *    - BVH-Triangle Mesh: for passive objects only. Despite having greater
+                        *                         speed/accuracy, they cannot be used for moving objects.
+                        *    - GImpact Mesh:      for active objects. These are slower and less stable,
+                        *                         but are more flexible for general usage.
+                        */
+                       if (ob->rigidbody_object->type == RBO_TYPE_PASSIVE) {
+                               shape = RB_shape_new_trimesh(mdata);
+                       }
+                       else {
+                               shape = RB_shape_new_gimpact_mesh(mdata);
+                       }
+               }
+
+               /* cleanup temp data */
+               if (dm) {
+                       dm->release(dm);
+               }
+       }
+       else {
+               printf("ERROR: cannot make Triangular Mesh collision shape for non-Mesh object\n");
+       }
+
+       return shape;
+}
+
+/* Create new physics sim collision shape for object and store it,
+ * or remove the existing one first and replace...
+ */
+void BKE_rigidbody_validate_sim_shape(Object *ob, short rebuild)
+{
+       RigidBodyOb *rbo = ob->rigidbody_object;
+       rbCollisionShape *new_shape = NULL;
+       BoundBox *bb = NULL;
+       float size[3] = {1.0f, 1.0f, 1.0f};
+       float radius = 1.0f;
+       float height = 1.0f;
+       float capsule_height;
+       float hull_margin = 0.0f;
+       bool can_embed = true;
+
+       /* sanity check */
+       if (rbo == NULL)
+               return;
+
+       /* don't create a new shape if we already have one and don't want to rebuild it */
+       if (rbo->physics_shape && !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 centralised in boundbox)
+        */
+       // XXX: all dimensions are auto-determined now... later can add stored settings for this
+       /* get object dimensions without scaling */
+       bb = BKE_object_boundbox_get(ob);
+       if (bb) {
+               size[0] = (bb->vec[4][0] - bb->vec[0][0]);
+               size[1] = (bb->vec[2][1] - bb->vec[0][1]);
+               size[2] = (bb->vec[1][2] - bb->vec[0][2]);
+       }
+       mul_v3_fl(size, 0.5f);
+
+       if (ELEM3(rbo->shape, RB_SHAPE_CAPSULE, RB_SHAPE_CYLINDER, RB_SHAPE_CONE)) {
+               /* take radius as largest x/y dimension, and height as z-dimension */
+               radius = MAX2(size[0], size[1]);
+               height = size[2];
+       }
+       else if (rbo->shape == RB_SHAPE_SPHERE) {
+               /* take radius to the the largest dimension to try and encompass everything */
+               radius = MAX3(size[0], size[1], size[2]);
+       }
+
+       /* create new shape */
+       switch (rbo->shape) {
+               case RB_SHAPE_BOX:
+                       new_shape = RB_shape_new_box(size[0], size[1], size[2]);
+                       break;
+
+               case RB_SHAPE_SPHERE:
+                       new_shape = RB_shape_new_sphere(radius);
+                       break;
+
+               case RB_SHAPE_CAPSULE:
+                       capsule_height = (height - radius) * 2.0f;
+                       new_shape = RB_shape_new_capsule(radius, (capsule_height > 0.0f) ? capsule_height : 0.0f);
+                       break;
+               case RB_SHAPE_CYLINDER:
+                       new_shape = RB_shape_new_cylinder(radius, height);
+                       break;
+               case RB_SHAPE_CONE:
+                       new_shape = RB_shape_new_cone(radius, height * 2.0f);
+                       break;
+
+               case RB_SHAPE_CONVEXH:
+                       /* try to emged collision margin */
+                       if (!(rbo->flag & RBO_FLAG_USE_MARGIN))
+                               hull_margin = 0.04f;
+                       new_shape = rigidbody_get_shape_convexhull_from_mesh(ob, hull_margin, &can_embed);
+                       if (!(rbo->flag & RBO_FLAG_USE_MARGIN))
+                               rbo->margin = (can_embed) ? 0.04f : 0.0f;  /* RB_TODO ideally we shouldn't directly change the margin here */
+                       break;
+               case RB_SHAPE_TRIMESH:
+                       new_shape = rigidbody_get_shape_trimesh_from_mesh(ob);
+                       break;
+       }
+       /* 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));
+       }
+}
+
+/* --------------------- */
+
+/* Create physics sim representation of object given RigidBody settings
+ * < rebuild: even if an instance already exists, replace it
+ */
+void BKE_rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, short rebuild)
+{
+       RigidBodyOb *rbo = (ob) ? ob->rigidbody_object : NULL;
+       float loc[3];
+       float rot[4];
+
+       /* sanity checks:
+        *      - object doesn't have RigidBody info already: then why is it here?
+        */
+       if (rbo == NULL)
+               return;
+
+       /* make sure collision shape exists */
+       if (rbo->physics_shape == NULL || rebuild)
+               BKE_rigidbody_validate_sim_shape(ob, true);
+
+       if (rbo->physics_object) {
+               if (rebuild == false)
+                       RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
+       }
+       if (!rbo->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);
+               }
+
+               mat4_to_loc_quat(loc, rot, ob->obmat);
+
+               rbo->physics_object = RB_body_new(rbo->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_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);
+
+               if (rbo->type == RBO_TYPE_PASSIVE || rbo->flag & RBO_FLAG_START_DEACTIVATED)
+                       RB_body_deactivate(rbo->physics_object);
+
+
+               RB_body_set_linear_factor(rbo->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,
+                                          (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);
+       }
+
+       if (rbw && rbw->physics_world)
+               RB_dworld_add_body(rbw->physics_world, rbo->physics_object, rbo->col_groups);
+}
+
+/* --------------------- */
+
+/* Create physics sim world given RigidBody world settings */
+// NOTE: this does NOT update object references that the scene uses, in case those aren't ready yet!
+void BKE_rigidbody_validate_sim_world(Scene *scene, RigidBodyWorld *rbw, short rebuild)
+{
+       /* sanity checks */
+       if (rbw == NULL)
+               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);
+       }
+
+       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);
+}
+
+/* ************************************** */
+/* Setup Utilities - Create Settings Blocks */
+
+/* Set up RigidBody world */
+RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene)
+{
+       /* try to get whatever RigidBody world that might be representing this already */
+       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
+        */
+       if (scene == NULL)
+               return NULL;
+
+       /* create a new sim world */
+       rbw = MEM_callocN(sizeof(RigidBodyWorld), "RigidBodyWorld");
+
+       /* set default settings */
+       rbw->ltime = PSFRA;
+
+       rbw->time_scale = 1.0f;
+
+       rbw->steps_per_second = 60; /* Bullet default (60 Hz) */
+       rbw->num_solver_iterations = 10; /* 10 is bullet default */
+
+       /* return this sim world */
+       return rbw;
+}
+
+/* Add rigid body settings to the specified object */
+RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type)
+{
+       RigidBodyOb *rbo;
+       RigidBodyWorld *rbw = scene->rigidbody_world;
+
+       /* sanity checks
+        *      - rigidbody world must exist
+        *      - object must exist
+        *      - cannot add rigid body if it already exists
+        */
+       if (ob == NULL || (ob->rigidbody_object != NULL))
+               return NULL;
+
+       /* create new settings data, and link it up */
+       rbo = MEM_callocN(sizeof(RigidBodyOb), "RigidBodyOb");
+
+       /* set default settings */
+       rbo->type = type;
+
+       rbo->mass = 1.0f;
+
+       rbo->friction = 0.5f; /* best when non-zero. 0.5 is Bullet default */
+       rbo->restitution = 0.0f; /* best when zero. 0.0 is Bullet default */
+
+       rbo->margin = 0.04f; /* 0.04 (in meters) is Bullet default */
+
+       rbo->lin_sleep_thresh = 0.4f; /* 0.4 is half of Bullet default */
+       rbo->ang_sleep_thresh = 0.5f; /* 0.5 is half of Bullet default */
+
+       rbo->lin_damping = 0.04f; /* 0.04 is game engine default */
+       rbo->ang_damping = 0.1f; /* 0.1 is game engine default */
+
+       rbo->col_groups = 1;
+
+       /* use triangle meshes for passive objects
+        * use convex hulls for active objects since dynamic triangle meshes are very unstable
+        */
+       if (type == RBO_TYPE_ACTIVE)
+               rbo->shape = RB_SHAPE_CONVEXH;
+       else
+               rbo->shape = RB_SHAPE_TRIMESH;
+
+       /* set initial transform */
+       mat4_to_loc_quat(rbo->pos, rbo->orn, ob->obmat);
+
+       /* flag cache as outdated */
+       BKE_rigidbody_cache_reset(rbw);
+
+       /* return this object */
+       return rbo;
+}
+
+/* ************************************** */
+/* Utilities API */
+
+/* Get RigidBody world for the given scene, creating one if needed
+ * < scene: Scene to find active Rigid Body world for
+ */
+RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene)
+{
+       /* sanity check */
+       if (scene == NULL)
+               return NULL;
+
+       return scene->rigidbody_world;
+}
+
+void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
+{
+       RigidBodyWorld *rbw = scene->rigidbody_world;
+       RigidBodyOb *rbo = ob->rigidbody_object;
+       GroupObject *go;
+       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) {
+                       for (i = 0; i < rbw->numbodies; i++) {
+                               if (rbw->objects[i] == ob) {
+                                       rbw->objects[i] = NULL;
+                                       break;
+                               }
+                       }
+               }
+       }
+       /* remove object's settings */
+       BKE_rigidbody_free_object(ob);
+       /* flag cache as outdated */
+       BKE_rigidbody_cache_reset(rbw);
+}
+
+
+/* ************************************** */
+/* Simulation Interface - Bullet */
+
+/* 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)
+{
+       GroupObject *go;
+       int i, n;
+
+       n = BLI_countlist(&rbw->group->gobject);
+
+       if (rbw->numbodies != n) {
+               rbw->numbodies = n;
+               rbw->objects = realloc(rbw->objects, sizeof(Object *) * rbw->numbodies);
+       }
+
+       for (go = rbw->group->gobject.first, i = 0; go; go = go->next, i++) {
+               Object *ob = go->ob;
+               rbw->objects[i] = ob;
+       }
+}
+
+static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw)
+{
+       float adj_gravity[3];
+
+       /* adjust gravity to take effector weights into account */
+       if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) {
+               copy_v3_v3(adj_gravity, scene->physics_settings.gravity);
+       }
+       else {
+               zero_v3(adj_gravity);
+       }
+
+       /* update gravity, since this RNA setting is not part of RigidBody settings */
+       RB_dworld_set_gravity(rbw->physics_world, adj_gravity);
+
+       /* update object array in case there are changes */
+       rigidbody_update_ob_array(rbw);
+}
+
+static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo)
+{
+       float loc[3];
+       float rot[4];
+       float scale[3];
+
+       /* only update if rigid body exists */
+       if (rbo->physics_object == NULL)
+               return;
+
+       mat4_decompose(loc, rot, scale, ob->obmat);
+
+       /* update scale for all objects */
+       RB_body_set_scale(rbo->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]));
+
+       /* update rigid body location and rotation for kinematic bodies */
+       if (rbo->flag & RBO_FLAG_KINEMATIC) {
+               RB_body_activate(rbo->physics_object);
+               RB_body_set_loc_rot(rbo->physics_object, loc, rot);
+       }
+       /* NOTE: passive objects don't need to be updated since they don't move */
+
+       /* NOTE: no other settings need to be explicitly updated here,
+        * since RNA setters take care of the rest :)
+        */
+}
+
+/* Updates and validates world, bodies and shapes.
+ * < rebuild: rebuild entire simulation
+ */
+static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, int rebuild)
+{
+       GroupObject *go;
+
+       /* update world */
+       if (rebuild)
+               BKE_rigidbody_validate_sim_world(scene, rbw, true);
+       rigidbody_update_sim_world(scene, rbw);
+
+       /* update objects */
+       for (go = rbw->group->gobject.first; go; go = go->next) {
+               Object *ob = go->ob;
+
+               if (ob && ob->type == OB_MESH) {
+                       /* validate that we've got valid object set up here... */
+                       RigidBodyOb *rbo = ob->rigidbody_object;
+                       /* update transformation matrix of the object so we don't get a frame of lag for simple animations */
+                       BKE_object_where_is_calc(scene, ob);
+
+                       if (rbo == NULL) {
+                               /* 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...
+                                */
+                               ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, RBO_TYPE_ACTIVE);
+                               BKE_rigidbody_validate_sim_object(rbw, ob, true);
+
+                               rbo = ob->rigidbody_object;
+                       }
+                       else {
+                               /* perform simulation data updates as tagged */
+                               /* refresh object... */
+                               if (rebuild) {
+                                       /* World has been rebuilt so rebuild object */
+                                       BKE_rigidbody_validate_sim_object(rbw, ob, true);
+                               }
+                               else if (rbo->flag & RBO_FLAG_NEEDS_VALIDATE) {
+                                       BKE_rigidbody_validate_sim_object(rbw, ob, false);
+                               }
+                               /* refresh shape... */
+                               if (rbo->flag & RBO_FLAG_NEEDS_RESHAPE) {
+                                       /* mesh/shape data changed, so force shape refresh */
+                                       BKE_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);
+                               }
+                               rbo->flag &= ~(RBO_FLAG_NEEDS_VALIDATE | RBO_FLAG_NEEDS_RESHAPE);
+                       }
+
+                       /* update simulation object... */
+                       rigidbody_update_sim_ob(scene, rbw, ob, rbo);
+               }
+       }
+}
+
+/* Sync rigid body and object transformations */
+void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime)
+{
+// RB_TODO implement this
+}
+
+void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw)
+{
+// RB_TODO implement this
+}
+
+/* ------------------ */
+
+/* Run RigidBody simulation for the specified physics world */
+void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
+{
+// RB_TODO implement this
+}
+/* ************************************** */
index 9cf0724..e48cf36 100644 (file)
@@ -46,6 +46,7 @@
 #include "DNA_group_types.h"
 #include "DNA_node_types.h"
 #include "DNA_object_types.h"
+#include "DNA_rigidbody_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_sequence_types.h"
@@ -72,6 +73,7 @@
 #include "BKE_object.h"
 #include "BKE_paint.h"
 #include "BKE_pointcache.h"
+#include "BKE_rigidbody.h"
 #include "BKE_scene.h"
 #include "BKE_sequencer.h"
 #include "BKE_world.h"
@@ -310,6 +312,9 @@ void BKE_scene_free(Scene *sce)
        BKE_free_animdata((ID *)sce);
        BKE_keyingsets_free(&sce->keyingsets);
        
+       if (sce->rigidbody_world)
+               BKE_rigidbody_free_world(sce->rigidbody_world);
+       
        if (sce->r.avicodecdata) {
                free_avicodecdata(sce->r.avicodecdata);
                MEM_freeN(sce->r.avicodecdata);
@@ -936,6 +941,16 @@ Base *BKE_scene_base_add(Scene *sce, Object *ob)
        return b;
 }
 
+void BKE_scene_base_remove(Scene *sce, Base *base)
+{
+       /* remove rigid body object from world before removing object */
+       if (base->object->rigidbody_object)
+               BKE_rigidbody_remove_object(sce, base->object);
+       
+       BLI_remlink(&sce->base, base);
+       MEM_freeN(base);
+}
+
 void BKE_scene_base_deselect_all(Scene *sce)
 {
        Base *b;
@@ -1376,3 +1391,8 @@ int BKE_scene_check_color_management_enabled(const Scene *scene)
 {
        return strcmp(scene->display_settings.display_device, "None") != 0;
 }
+
+int BKE_scene_check_rigidbody_active(const Scene *scene)
+{
+       return scene && scene->rigidbody_world && scene->rigidbody_world->group && !(scene->rigidbody_world->flag & RBW_FLAG_MUTED);
+}
index d042e43..95fa401 100644 (file)
@@ -81,6 +81,7 @@
 #include "DNA_packedFile_types.h"
 #include "DNA_particle_types.h"
 #include "DNA_property_types.h"
+#include "DNA_rigidbody_types.h"
 #include "DNA_text_types.h"
 #include "DNA_view3d_types.h"
 #include "DNA_screen_types.h"
@@ -4785,7 +4786,18 @@ static void direct_link_object(FileData *fd, Object *ob)
        }
        ob->bsoft = newdataadr(fd, ob->bsoft);
        ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */
-
+       
+       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;
+       }
+       
        link_list(fd, &ob->particlesystem);
        direct_link_particlesystems(fd, &ob->particlesystem);
        
@@ -5003,6 +5015,14 @@ static void lib_link_scene(FileData *fd, Main *main)
                        BKE_sequencer_update_muting(sce->ed);
                        BKE_sequencer_update_sound_bounds_all(sce);
                        
+                       
+                       /* rigidbody world relies on it's linked groups */
+                       if (sce->rigidbody_world) {
+                               RigidBodyWorld *rbw = sce->rigidbody_world;
+                               if (rbw->group)
+                                       rbw->group = newlibadr(fd, sce->id.lib, rbw->group);
+                       }
+                       
                        if (sce->nodetree) {
                                lib_link_ntree(fd, &sce->id, sce->nodetree);
                                composite_patch(sce->nodetree, sce);
@@ -5079,6 +5099,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        Editing *ed;
        Sequence *seq;
        MetaStack *ms;
+       RigidBodyWorld *rbw;
        
        sce->theDag = NULL;
        sce->dagisvalid = 0;
@@ -5265,6 +5286,17 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        }
 
        direct_link_view_settings(fd, &sce->view_settings);
+       
+       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->objects = NULL;
+               rbw->numbodies = 0;
+       }
 }
 
 /* ************ READ WM ***************** */
@@ -9680,6 +9712,10 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce)
                }
                SEQ_END
        }
+       
+       if (sce->rigidbody_world) {
+               expand_doit(fd, mainvar, sce->rigidbody_world->group);
+       }
 
 #ifdef DURIAN_CAMERA_SWITCH
        {
index ef0c5b0..a52e4e2 100644 (file)
 #include "DNA_packedFile_types.h"
 #include "DNA_particle_types.h"
 #include "DNA_property_types.h"
+#include "DNA_rigidbody_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_sdna_types.h"
 #include "DNA_sequence_types.h"
@@ -1487,6 +1488,11 @@ static void write_objects(WriteData *wd, ListBase *idbase)
                        }
                        writestruct(wd, DATA, "BulletSoftBody", 1, ob->bsoft);
                        
+                       if (ob->rigidbody_object) {
+                               // TODO: if any extra data is added to handle duplis, will need separate function then
+                               writestruct(wd, DATA, "RigidBodyOb", 1, ob->rigidbody_object);
+                       }
+                       
                        write_particlesystems(wd, &ob->particlesystem);
                        write_modifiers(wd, &ob->modifiers);
                }
@@ -2296,7 +2302,12 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
                }
 
                write_view_settings(wd, &sce->view_settings);
-
+               
+               /* writing RigidBodyWorld data to the blend file */
+               if (sce->rigidbody_world) {
+                       writestruct(wd, DATA, "RigidBodyWorld", 1, sce->rigidbody_world);
+               }
+               
                sce= sce->id.next;
        }
        /* flush helps the compression for undo-save */
index 4db416b..897aeb7 100644 (file)
@@ -941,11 +941,10 @@ static void object_delete_check_glsl_update(Object *ob)
 void ED_base_object_free_and_unlink(Main *bmain, Scene *scene, Base *base)
 {
        DAG_id_type_tag(bmain, ID_OB);
-       BLI_remlink(&scene->base, base);
+       BKE_scene_base_remove(scene, base);
        object_delete_check_glsl_update(base->object);
        BKE_libblock_free_us(&bmain->object, base->object);
        if (scene->basact == base) scene->basact = NULL;
-       MEM_freeN(base);
 }
 
 static int object_delete_exec(bContext *C, wmOperator *op)
index fa44d3d..68d7dca 100644 (file)
@@ -354,8 +354,7 @@ static int make_proxy_exec(bContext *C, wmOperator *op)
                
                /* remove base, leave user count of object, it gets linked in BKE_object_make_proxy */
                if (gob == NULL) {
-                       BLI_remlink(&scene->base, oldbase);
-                       MEM_freeN(oldbase);
+                       BKE_scene_base_remove(scene, oldbase);
                }
                
                BKE_object_make_proxy(newob, ob, gob);
index 6cf7133..16859e5 100644 (file)
@@ -56,6 +56,7 @@ struct ParticleSystem;
 struct DerivedMesh;
 struct SculptSession;
 struct bGPdata;
+struct RigidBodyOb;
 
 
 /* Vertex Groups - Name Info */
@@ -270,6 +271,8 @@ typedef struct Object {
        ListBase gpulamp;               /* runtime, for glsl lamp display only */
        ListBase pc_ids;
        ListBase *duplilist;    /* for temporary dupli list storage, only for use by RNA API */
+       
+       struct RigidBodyOb *rigidbody_object;           /* settings for Bullet rigid body */
 
        float ima_ofs[2];               /* offset for image empties */
 } Object;
diff --git a/source/blender/makesdna/DNA_rigidbody_types.h b/source/blender/makesdna/DNA_rigidbody_types.h
new file mode 100644 (file)
index 0000000..8c66a5b
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2013 Blender Foundation
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Joshua Leung, Sergej Reich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file DNA_rigidbody_types.h
+ *  \ingroup DNA
+ *  \brief Types and defines for representing Rigid Body entities
+ */
+
+#ifndef __DNA_RIGIDBODY_TYPES_H__
+#define __DNA_RIGIDBODY_TYPES_H__
+
+#include "DNA_listBase.h"
+
+struct Group;
+
+/* ******************************** */
+/* RigidBody World */
+
+/* RigidBodyWorld (rbw)
+ *
+ * Represents a "simulation scene" existing within the parent scene.
+ */
+typedef struct RigidBodyWorld {
+       /* Sim World Settings ------------------------------------------------------------- */
+       struct Group *group;            /* Group containing objects to use for Rigid Bodies */
+       struct Object **objects;        /* Array to access group objects by index, only used at runtime */
+       
+       int pad;
+       float ltime;                            /* last frame world was evaluated for (internal) */
+       
+       /* cache */
+       int numbodies;              /* number of objects in rigid body group */
+       
+       short steps_per_second;         /* number of simulation steps thaken per second */
+       short num_solver_iterations;/* number of constraint solver iterations made per simulation step */
+       
+       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 */
+typedef enum eRigidBodyWorld_Flag {
+       /* should sim world be skipped when evaluating (user setting) */
+       RBW_FLAG_MUTED                          = (1<<0),
+       /* sim data needs to be rebuilt */
+       RBW_FLAG_NEEDS_REBUILD          = (1<<1),
+       /* usse split impulse when stepping the simulation */
+       RBW_FLAG_USE_SPLIT_IMPULSE      = (1<<2)
+} eRigidBodyWorld_Flag;
+
+/* ******************************** */
+/* RigidBody Object */
+
+/* RigidBodyObject (rbo)
+ *
+ * Represents an object participating in a RigidBody sim.
+ * This is attached to each object that is currently
+ * 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 */ 
+       
+       int flag;                               /* (eRigidBodyOb_Flag) */
+       int col_groups;                 /* Collision groups that determines wich rigid bodies can collide with each other */
+       int pad;
+       
+       /* Physics Parameters */
+       float mass;                             /* how much object 'weighs' (i.e. absolute 'amount of stuff' it holds) */
+       
+       float friction;                 /* resistance of object to movement */
+       float restitution;              /* how 'bouncy' object is when it collides */
+       
+       float margin;                   /* tolerance for detecting collisions */ 
+       
+       float lin_damping;              /* damping for linear velocities */
+       float ang_damping;              /* damping for angular velocities */
+       
+       float lin_sleep_thresh; /* deactivation threshold for linear velocities */
+       float ang_sleep_thresh; /* deactivation threshold for angular velocities */
+       
+       float orn[4];                   /* rigid body orientation */
+       float pos[3];                   /* rigid body position */
+       float pad1;
+} RigidBodyOb;
+
+
+/* Participation types for RigidBodyOb */
+typedef enum eRigidBodyOb_Type {
+       /* active geometry participant in simulation. is directly controlled by sim */
+       RBO_TYPE_ACTIVE = 0,
+       /* passive geometry participant in simulation. is directly controlled by animsys */
+       RBO_TYPE_PASSIVE
+} eRigidBodyOb_Type;
+
+/* Flags for RigidBodyOb */
+typedef enum eRigidBodyOb_Flag {
+       /* rigidbody is kinematic (controlled by the animation system) */
+       RBO_FLAG_KINEMATIC                      = (1<<0),
+       /* rigidbody needs to be validated (usually set after duplicating and not hooked up yet) */
+       RBO_FLAG_NEEDS_VALIDATE         = (1<<1),
+       /* rigidbody shape needs refreshing (usually after exiting editmode) */
+       RBO_FLAG_NEEDS_RESHAPE          = (1<<2),
+       /* rigidbody can be deactivated */
+       RBO_FLAG_USE_DEACTIVATION       = (1<<3),
+       /* rigidbody is deactivated at the beginning of simulation */
+       RBO_FLAG_START_DEACTIVATED      = (1<<4),
+       /* rigidbody is not dynamically simulated */
+       RBO_FLAG_DISABLED                       = (1<<5),
+       /* collision margin is not embedded (only used by convex hull shapes for now) */
+       RBO_FLAG_USE_MARGIN                     = (1<<6)
+} eRigidBodyOb_Flag;
+
+/* RigidBody Collision Shape */
+typedef enum eRigidBody_Shape {
+               /* simple box (i.e. bounding box) */
+       RB_SHAPE_BOX = 0,
+               /* sphere */
+       RB_SHAPE_SPHERE,
+               /* rounded "pill" shape (i.e. calcium tablets) */
+       RB_SHAPE_CAPSULE,
+               /* cylinder (i.e. pringles can) */
+       RB_SHAPE_CYLINDER,
+               /* cone (i.e. party hat) */
+       RB_SHAPE_CONE,
+       
+               /* convex hull (minimal shrinkwrap encompassing all verts) */
+       RB_SHAPE_CONVEXH,
+               /* triangulated mesh */
+       RB_SHAPE_TRIMESH,
+       
+               /* concave mesh approximated using primitives */
+       //RB_SHAPE_COMPOUND,
+} eRigidBody_Shape;
+
+/* ******************************** */
+
+#endif /* __DNA_RIGIDBODY_TYPES_H__ */
+
index b093239..b35323d 100644 (file)
@@ -1170,6 +1170,9 @@ typedef struct Scene {
        ColorManagedViewSettings view_settings;
        ColorManagedDisplaySettings display_settings;
        ColorManagedColorspaceSettings sequencer_colorspace_settings;
+       
+       /* RigidBody simulation world+settings */
+       struct RigidBodyWorld *rigidbody_world;
 } Scene;
 
 
index e131cde..31ff0ff 100644 (file)
@@ -133,6 +133,7 @@ static const char *includefiles[] = {
        "DNA_tracking_types.h",
        "DNA_dynamicpaint_types.h",
        "DNA_mask_types.h",
+       "DNA_rigidbody_types.h",
 
        /* empty string to indicate end of includefiles */
        ""
@@ -1262,4 +1263,5 @@ int main(int argc, char **argv)
 #include "DNA_tracking_types.h"
 #include "DNA_dynamicpaint_types.h"
 #include "DNA_mask_types.h"
+#include "DNA_rigidbody_types.h"
 /* end of list */
index 6ce3ffa..e8c1a5d 100644 (file)
@@ -428,6 +428,8 @@ extern StructRNA RNA_RenderLayer;
 extern StructRNA RNA_RenderPass;
 extern StructRNA RNA_RenderResult;
 extern StructRNA RNA_RenderSettings;
+extern StructRNA RNA_RigidBodyWorld;
+extern StructRNA RNA_RigidBodyObject;
 extern StructRNA RNA_RigidBodyJointConstraint;
 extern StructRNA RNA_SPHFluidSettings;
 extern StructRNA RNA_Scene;
index 75c8b20..f0de36b 100644 (file)
@@ -102,6 +102,9 @@ extern EnumPropertyItem object_type_items[];
 
 extern EnumPropertyItem object_type_curve_items[];
 
+extern EnumPropertyItem rigidbody_ob_type_items[];
+extern EnumPropertyItem rigidbody_ob_shape_items[];
+
 extern EnumPropertyItem object_axis_items[];
 
 extern EnumPropertyItem controller_type_items[];
index aab08a3..df7d0f6 100644 (file)
@@ -38,6 +38,7 @@ incs += ' ../render/extern/include #/intern/cycles/blender'
 incs += ' ../nodes'
 incs += ' #/extern/glew/include'
 incs += ' #/intern/smoke/extern'
+incs += ' ../rigidbody'
 
 incs += ' ../bmesh'
 
index 82c0757..83e7a19 100644 (file)
@@ -70,6 +70,7 @@ set(DEFSRC
        rna_pose.c
        rna_property.c
        rna_render.c
+       rna_rigidbody.c
        rna_rna.c
        rna_scene.c
        rna_screen.c
@@ -253,6 +254,7 @@ blender_include_dirs(
        ../../windowmanager
        ../../editors/include
        ../../render/extern/include
+       ../../rigidbody
        ../../../../intern/audaspace/intern
        ../../../../intern/cycles/blender
        ../../../../intern/guardedalloc
index 605fb18..41b6e3e 100644 (file)
@@ -3259,6 +3259,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
        {"rna_pose.c", "rna_pose_api.c", RNA_def_pose},
        {"rna_property.c", NULL, RNA_def_gameproperty},
        {"rna_render.c", NULL, RNA_def_render},
+       {"rna_rigidbody.c", NULL, RNA_def_rigidbody},
        {"rna_scene.c", "rna_scene_api.c", RNA_def_scene},
        {"rna_screen.c", NULL, RNA_def_screen},
        {"rna_sculpt_paint.c", NULL, RNA_def_sculpt_paint},
index 6520f22..76947d8 100644 (file)
@@ -164,6 +164,7 @@ void RNA_def_packedfile(struct BlenderRNA *brna);
 void RNA_def_particle(struct BlenderRNA *brna);
 void RNA_def_pose(struct BlenderRNA *brna);
 void RNA_def_render(struct BlenderRNA *brna);
+void RNA_def_rigidbody(struct BlenderRNA *brna);
 void RNA_def_rna(struct BlenderRNA *brna);
 void RNA_def_scene(struct BlenderRNA *brna);
 void RNA_def_screen(struct BlenderRNA *brna);
index 5105470..99cecb0 100644 (file)
@@ -2428,6 +2428,12 @@ static void rna_def_object(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Particle Systems", "Particle systems emitted from the object");
        rna_def_object_particle_systems(brna, prop);
 
+       
+       prop = RNA_def_property(srna, "rigid_body", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "rigidbody_object");
+       RNA_def_property_struct_type(prop, "RigidBodyObject");
+       RNA_def_property_ui_text(prop, "Rigid Body Settings", "Settings for rigid body simulation");
+       
        /* restrict */
        prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "restrictflag", OB_RESTRICT_VIEW);
diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c
new file mode 100644 (file)
index 0000000..c7d6324
--- /dev/null
@@ -0,0 +1,499 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Foundation 2013, Joshua Leung, Sergej Reich
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file rna_rigidbody.c
+ *  \ingroup rna
+ *  \brief RNA property definitions for Rigid Body datatypes
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "RNA_define.h"
+
+#include "rna_internal.h"
+
+#include "DNA_group_types.h"
+#include "DNA_object_types.h"
+#include "DNA_rigidbody_types.h"
+#include "DNA_scene_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "WM_types.h"
+
+/* roles of objects in RigidBody Sims */
+EnumPropertyItem rigidbody_ob_type_items[] = {
+       {RBO_TYPE_ACTIVE, "ACTIVE", 0, "Active", "Object is directly controlled by simulation results"},
+       {RBO_TYPE_PASSIVE, "PASSIVE", 0, "Passive", "Object is directly controlled by animation system"},
+       {0, NULL, 0, NULL, NULL}};
+
+/* collision shapes of objects in rigid body sim */
+EnumPropertyItem rigidbody_ob_shape_items[] = {
+       {RB_SHAPE_BOX, "BOX", ICON_MESH_CUBE, "Box", "Box-like shapes (i.e. cubes), including planes (i.e. ground planes)"},
+       {RB_SHAPE_SPHERE, "SPHERE", ICON_MESH_UVSPHERE, "Sphere", ""},
+       {RB_SHAPE_CAPSULE, "CAPSULE", ICON_OUTLINER_OB_META, "Capsule", ""},
+       {RB_SHAPE_CYLINDER, "CYLINDER", ICON_MESH_CYLINDER, "Cylinder", ""},
+       {RB_SHAPE_CONE, "CONE", ICON_MESH_CONE, "Cone", ""},
+       {RB_SHAPE_CONVEXH, "CONVEX_HULL", ICON_MESH_ICOSPHERE, "Convex Hull", "A mesh-like surface encompassing (i.e. shrinkwrap over) all verts. Best results with fewer vertices"},
+       {RB_SHAPE_TRIMESH, "MESH", ICON_MESH_MONKEY, "Mesh", "Mesh consisting of triangles only, allowing for more detailed interactions than convex hulls"},
+       {0, NULL, 0, NULL, NULL}};
+
+
+#ifdef RNA_RUNTIME
+
+#include "RBI_api.h"
+
+#include "BKE_depsgraph.h"
+#include "BKE_rigidbody.h"
+
+#define RB_FLAG_SET(dest, value, flag) { \
+       if (value) \
+               dest |= flag; \
+       else \
+               dest &= ~flag; \
+}
+
+
+/* ******************************** */
+
+static void rna_RigidBodyWorld_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+       RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data;
+       
+       BKE_rigidbody_cache_reset(rbw);
+}
+
+static char *rna_RigidBodyWorld_path(PointerRNA *ptr)
+{      
+       return BLI_sprintfN("rigidbody_world");
+}
+
+static void rna_RigidBodyWorld_num_solver_iterations_set(PointerRNA *ptr, int value)
+{
+       RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data;
+       
+       rbw->num_solver_iterations = value;
+       
+       if (rbw->physics_world)
+               RB_dworld_set_solver_iterations(rbw->physics_world, value);
+}
+
+static void rna_RigidBodyWorld_split_impulse_set(PointerRNA *ptr, int value)
+{
+       RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data;
+       
+       RB_FLAG_SET(rbw->flag, value, RBW_FLAG_USE_SPLIT_IMPULSE);
+       
+       if (rbw->physics_world)
+               RB_dworld_set_split_impulse(rbw->physics_world, value);
+}
+
+/* ******************************** */
+
+static void rna_RigidBodyOb_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+       RigidBodyWorld *rbw = scene->rigidbody_world;
+       
+       BKE_rigidbody_cache_reset(rbw);
+}
+
+static void rna_RigidBodyOb_shape_reset(Main *bmain, Scene *scene, PointerRNA *ptr)
+{
+       RigidBodyWorld *rbw = scene->rigidbody_world;
+       RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+       
+       BKE_rigidbody_cache_reset(rbw);
+       if (rbo->physics_shape)
+               rbo->flag |= RBO_FLAG_NEEDS_RESHAPE;
+}
+
+static char *rna_RigidBodyOb_path(PointerRNA *ptr)
+{
+       /* NOTE: this hardcoded path should work as long as only Objects have this */
+       return BLI_sprintfN("rigid_body");
+}
+
+static void rna_RigidBodyOb_type_set(PointerRNA *ptr, int value)
+{
+       RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+       
+       rbo->type = value;
+       rbo->flag |= RBO_FLAG_NEEDS_VALIDATE;
+       
+       /* do physics sim updates */
+       if (rbo->physics_object)
+               RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
+}
+
+static void rna_RigidBodyOb_disabled_set(PointerRNA *ptr, int value)
+{
+       RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+       
+       RB_FLAG_SET(rbo->flag, !value, RBO_FLAG_DISABLED);
+       
+       /* 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);
+               rbo->flag |= RBO_FLAG_NEEDS_VALIDATE;
+       }
+}
+
+static void rna_RigidBodyOb_shape_set(PointerRNA *ptr, int value)
+{
+       RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+       Object *ob = (Object *)ptr->id.data;
+       
+       rbo->shape = value;
+       
+       /* force creation of new collision shape reflecting this */
+       BKE_rigidbody_validate_sim_shape(ob, TRUE);
+       
+       /* now tell RB sim about it */
+       if (rbo->physics_object && rbo->physics_shape)
+               RB_body_set_collision_shape(rbo->physics_object, rbo->physics_shape);
+}
+
+
+static void rna_RigidBodyOb_mass_set(PointerRNA *ptr, float value)
+{
+       RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+       
+       rbo->mass = value;
+       
+       /* 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));
+}
+
+static void rna_RigidBodyOb_friction_set(PointerRNA *ptr, float value)
+{
+       RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+       
+       rbo->friction = value;
+       
+       if (rbo->physics_object)
+               RB_body_set_friction(rbo->physics_object, value);
+}
+
+static void rna_RigidBodyOb_restitution_set(PointerRNA *ptr, float value)
+{
+       RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+       
+       rbo->restitution = value;
+       
+       if (rbo->physics_object)
+               RB_body_set_restitution(rbo->physics_object, value);
+}
+
+static void rna_RigidBodyOb_collision_margin_set(PointerRNA *ptr, float value)
+{
+       RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+       
+       rbo->margin = value;
+       
+       if (rbo->physics_shape)
+               RB_shape_set_margin(rbo->physics_shape, RBO_GET_MARGIN(rbo));
+}
+
+static void rna_RigidBodyOb_kinematic_state_set(PointerRNA *ptr, int value)
+{
+       RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+       
+       RB_FLAG_SET(rbo->flag, value, RBO_FLAG_KINEMATIC);
+       
+       /* 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);
+               rbo->flag |= RBO_FLAG_NEEDS_VALIDATE;
+       }
+}
+
+static void rna_RigidBodyOb_activation_state_set(PointerRNA *ptr, int value)
+{
+       RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+       
+       RB_FLAG_SET(rbo->flag, value, RBO_FLAG_USE_DEACTIVATION);
+       
+       /* 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);
+}
+
+static void rna_RigidBodyOb_linear_sleepThresh_set(PointerRNA *ptr, float value)
+{
+       RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+       
+       rbo->lin_sleep_thresh = value;
+       
+       /* 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);
+}
+
+static void rna_RigidBodyOb_angular_sleepThresh_set(PointerRNA *ptr, float value)
+{
+       RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+       
+       rbo->ang_sleep_thresh = value;
+       
+       /* 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);
+}
+
+static void rna_RigidBodyOb_linear_damping_set(PointerRNA *ptr, float value)
+{
+       RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+       
+       rbo->lin_damping = value;
+       
+       /* only active bodies need damping update */
+       if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE))
+               RB_body_set_linear_damping(rbo->physics_object, value);
+}
+
+static void rna_RigidBodyOb_angular_damping_set(PointerRNA *ptr, float value)
+{
+       RigidBodyOb *rbo = (RigidBodyOb *)ptr->data;
+       
+       rbo->ang_damping = value;
+       
+       /* only active bodies need damping update */
+       if ((rbo->physics_object) && (rbo->type == RBO_TYPE_ACTIVE))
+               RB_body_set_angular_damping(rbo->physics_object, value);
+}
+
+#else
+
+static void rna_def_rigidbody_world(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+       
+       srna = RNA_def_struct(brna, "RigidBodyWorld", NULL);
+       RNA_def_struct_sdna(srna, "RigidBodyWorld");
+       RNA_def_struct_ui_text(srna, "Rigid Body World", "Self-contained rigid body simulation environment and settings");
+       RNA_def_struct_path_func(srna, "rna_RigidBodyWorld_path");
+       
+       /* groups */
+       prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE);
+       RNA_def_property_struct_type(prop, "Group");
+       RNA_def_property_flag(prop, PROP_EDITABLE|PROP_ID_SELF_CHECK);
+       RNA_def_property_ui_text(prop, "Group", "Group containing objects participating in this simulation");
+       RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset");
+       
+       /* booleans */
+       prop = RNA_def_property(srna, "enabled", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", RBW_FLAG_MUTED);
+       RNA_def_property_ui_text(prop, "Enabled", "Simulation will be evaluated");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       
+       /* time scale */
+       prop = RNA_def_property(srna, "time_scale", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_sdna(prop, NULL, "time_scale");
+       RNA_def_property_range(prop, 0.0f, 100.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
+       RNA_def_property_float_default(prop, 1.0f);
+       RNA_def_property_ui_text(prop, "Time Scale", "Changes the speed of the simulation");
+       RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset");
+       
+       /* timestep */
+       prop = RNA_def_property(srna, "steps_per_second", PROP_INT, PROP_NONE);
+       RNA_def_property_int_sdna(prop, NULL, "steps_per_second");
+       RNA_def_property_range(prop, 1, SHRT_MAX);
+       RNA_def_property_ui_range(prop, 60, 1000, 1, 0);
+       RNA_def_property_int_default(prop, 60);
+       RNA_def_property_ui_text(prop, "Steps Per Second", "Number of simulation steps taken per second (higher values are more accurate but slower)");
+       RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset");
+       
+       /* constraint solver iterations */
+       prop = RNA_def_property(srna, "num_solver_iterations", PROP_INT, PROP_NONE);
+       RNA_def_property_int_sdna(prop, NULL, "num_solver_iterations");
+       RNA_def_property_range(prop, 1, 1000);
+       RNA_def_property_ui_range(prop, 10, 100, 1, 0);
+       RNA_def_property_int_default(prop, 10);
+       RNA_def_property_int_funcs(prop, NULL, "rna_RigidBodyWorld_num_solver_iterations_set", NULL);
+       RNA_def_property_ui_text(prop, "Solver Iterations", "Number of constraint solver iterations made per simulation step (higher values are more accurate but slower)");
+       RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset");
+       
+       /* split impulse */
+       prop = RNA_def_property(srna, "use_split_impulse", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", RBW_FLAG_USE_SPLIT_IMPULSE);
+       RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyWorld_split_impulse_set");
+       RNA_def_property_ui_text(prop, "Split Impulse", "Reduces extra velocity that can build up when objects collide (lowers simulation stabilty a litte so use only when necessary)");
+       RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_reset");
+}
+
+static void rna_def_rigidbody_object(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+       
+       
+       srna = RNA_def_struct(brna, "RigidBodyObject", NULL);
+       RNA_def_struct_sdna(srna, "RigidBodyOb");
+       RNA_def_struct_ui_text(srna, "Rigid Body Object", "Settings for object participating in Rigid Body Simulation");
+       RNA_def_struct_path_func(srna, "rna_RigidBodyOb_path");
+       
+       /* Enums */
+       prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "type");
+       RNA_def_property_enum_items(prop, rigidbody_ob_type_items);
+       RNA_def_property_enum_funcs(prop, NULL, "rna_RigidBodyOb_type_set", NULL);
+       RNA_def_property_ui_text(prop, "Type", "Role of object in Rigid Body Simulations");
+       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);
+       RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyOb_disabled_set");
+       RNA_def_property_ui_text(prop, "Enabled", "Rigid Body actively participated in the simulation");
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+       
+       prop = RNA_def_property(srna, "collision_shape", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "shape");
+       RNA_def_property_enum_items(prop, rigidbody_ob_shape_items);
+       RNA_def_property_enum_funcs(prop, NULL, "rna_RigidBodyOb_shape_set", NULL);
+       RNA_def_property_ui_text(prop, "Collision Shape", "Collision Shape of object in Rigid Body Simulations");
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+       
+       prop = RNA_def_property(srna, "kinematic", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_KINEMATIC);
+       RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyOb_kinematic_state_set");
+       RNA_def_property_ui_text(prop, "Kinematic", "Allows rigid body to be controlled by the animation system");
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+       
+       /* Physics Parameters */
+       prop = RNA_def_property(srna, "mass", PROP_FLOAT, PROP_UNIT_MASS);
+       RNA_def_property_float_sdna(prop, NULL, "mass");
+       RNA_def_property_range(prop, 0.001f, FLT_MAX); // range must always be positive (and non-zero)
+       RNA_def_property_float_default(prop, 1.0f);
+       RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_mass_set", NULL);
+       RNA_def_property_ui_text(prop, "Mass", "How much the object 'weighs' irrespective of gravity");
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+       
+       /* Dynamics Parameters - Activation */
+       // TODO: define and figure out how to implement these
+       
+       /* Dynamics Parameters - Deactivation */
+       prop = RNA_def_property(srna, "use_deactivation", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_USE_DEACTIVATION);
+       RNA_def_property_boolean_default(prop, TRUE);
+       RNA_def_property_boolean_funcs(prop, NULL, "rna_RigidBodyOb_activation_state_set");
+       RNA_def_property_ui_text(prop, "Enable Deactivation", "Enables deactivation of resting rigid bodies (increases performance and stability but can cause glitches)");
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+       
+       prop = RNA_def_property(srna, "start_deactivated", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_START_DEACTIVATED);
+       RNA_def_property_ui_text(prop, "Start Deactivated", "Deactivates rigid body at the start of the simulation");
+       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, "deactivate_linear_velocity", PROP_FLOAT, PROP_UNIT_VELOCITY);
+       RNA_def_property_float_sdna(prop, NULL, "lin_sleep_thresh");
+       RNA_def_property_range(prop, FLT_MIN, FLT_MAX); // range must always be positive (and non-zero)
+       RNA_def_property_float_default(prop, 0.4f);
+       RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_linear_sleepThresh_set", NULL);
+       RNA_def_property_ui_text(prop, "Linear Velocity Deactivation Threshold", "Linear Velocity below which simulation stops simulating object");
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+       
+       prop = RNA_def_property(srna, "deactivate_angular_velocity", PROP_FLOAT, PROP_UNIT_VELOCITY);
+       RNA_def_property_float_sdna(prop, NULL, "ang_sleep_thresh");
+       RNA_def_property_range(prop, FLT_MIN, FLT_MAX); // range must always be positive (and non-zero)
+       RNA_def_property_float_default(prop, 0.5f);
+       RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_angular_sleepThresh_set", NULL);
+       RNA_def_property_ui_text(prop, "Angular Velocity Deactivation Threshold", "Angular Velocity below which simulation stops simulating object");
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+       
+       /* Dynamics Parameters - Damping Parameters */
+       prop = RNA_def_property(srna, "linear_damping", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_sdna(prop, NULL, "lin_damping");
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_float_default(prop, 0.04f);
+       RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_linear_damping_set", NULL);
+       RNA_def_property_ui_text(prop, "Linear Damping", "Amount of linear velocity that is lost over time");
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+       
+       prop = RNA_def_property(srna, "angular_damping", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_sdna(prop, NULL, "ang_damping");
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_float_default(prop, 0.1f);
+       RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_angular_damping_set", NULL);
+       RNA_def_property_ui_text(prop, "Angular Damping", "Amount of angular velocity that is lost over time");
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+       
+       /* Collision Parameters - Surface Parameters */
+       prop = RNA_def_property(srna, "friction", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_sdna(prop, NULL, "friction");
+       RNA_def_property_range(prop, 0.0f, FLT_MAX);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 3);
+       RNA_def_property_float_default(prop, 0.5f);
+       RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_friction_set", NULL);
+       RNA_def_property_ui_text(prop, "Friction", "Resistance of object to movement");
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+       
+       prop = RNA_def_property(srna, "restitution", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_sdna(prop, NULL, "restitution");
+       RNA_def_property_range(prop, 0.0f, FLT_MAX);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 1, 3);
+       RNA_def_property_float_default(prop, 0.0f);
+       RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_restitution_set", NULL);
+       RNA_def_property_ui_text(prop, "Restitution", "Tendency of object to bounce after colliding with another (0 = stays still, 1 = perfectly elastic)");
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+       
+       /* Collision Parameters - Sensitivity */
+       prop = RNA_def_property(srna, "use_margin", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", RBO_FLAG_USE_MARGIN);
+       RNA_def_property_boolean_default(prop, FALSE);
+       RNA_def_property_ui_text(prop, "Collision Margin", "Use custom collision margin (some shapes will have a visible gap around them)");
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_shape_reset");
+       
+       prop = RNA_def_property(srna, "collision_margin", PROP_FLOAT, PROP_UNIT_LENGTH);
+       RNA_def_property_float_sdna(prop, NULL, "margin");
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.01, 3);
+       RNA_def_property_float_default(prop, 0.04f);
+       RNA_def_property_float_funcs(prop, NULL, "rna_RigidBodyOb_collision_margin_set", NULL);
+       RNA_def_property_ui_text(prop, "Collision Margin", "Threshold of distance near surface where collisions are still considered (best results when non-zero)");
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_shape_reset");
+       
+       prop = RNA_def_property(srna, "collision_groups", PROP_BOOLEAN, PROP_LAYER_MEMBER);
+       RNA_def_property_boolean_sdna(prop, NULL, "col_groups", 1);
+       RNA_def_property_array(prop, 20);
+       RNA_def_property_ui_text(prop, "Collison Groups", "Collision Groups Rigid Body belongs to");
+       RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
+       RNA_def_property_flag(prop, PROP_LIB_EXCEPTION);
+}
+
+void RNA_def_rigidbody(BlenderRNA *brna)
+{
+       rna_def_rigidbody_world(brna);
+       rna_def_rigidbody_object(brna);
+}
+
+
+#endif
index bbacc44..705ac09 100644 (file)
@@ -35,6 +35,7 @@
 #include "DNA_group_types.h"
 #include "DNA_modifier_types.h"
 #include "DNA_particle_types.h"
+#include "DNA_rigidbody_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_userdef_types.h"
 #include "DNA_world_types.h"
@@ -405,8 +406,7 @@ static void rna_Scene_object_unlink(Scene *scene, ReportList *reports, Object *o
                scene->basact = NULL;
        }
 
-       BLI_remlink(&scene->base, base);
-       MEM_freeN(base);
+       BKE_scene_base_remove(scene, base);
 
        ob->id.us--;
 
@@ -4553,6 +4553,13 @@ void RNA_def_scene(BlenderRNA *brna)
        RNA_def_property_update(prop, NC_SCENE | ND_KEYINGSET, NULL);
        rna_def_scene_keying_sets_all(brna, prop);
        
+       /* Rigid Body Simulation */
+       prop = RNA_def_property(srna, "rigidbody_world", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "rigidbody_world");
+       RNA_def_property_struct_type(prop, "RigidBodyWorld");
+       RNA_def_property_ui_text(prop, "Rigid Body World", "");
+       RNA_def_property_update(prop, NC_SCENE, NULL);
+       
        /* Tool Settings */
        prop = RNA_def_property(srna, "tool_settings", PROP_POINTER, PROP_NONE);
        RNA_def_property_flag(prop, PROP_NEVER_NULL);