Revision: 25441 http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25441 Author: kazanbas Date: 2009-12-17 16:50:17 +0100 (Thu, 17 Dec 2009)
Log Message: ----------- Physics branch: Basic rigid body setup is possible now via game physics panel. The set of options used is limited to physics type and mass. Physics types used are 'static' and 'rigid body', all other types treated as static. With these options at hand it is possible to setup and simulate simple physics scenes involving static and dynamic objects. A "How-To" video: http://vimeo.com/8236800 Currently only box collision shape is used and it is not updated when you modify mesh. Also no caching, baking and animation blending yet, physics is simulated on every playback. Modified Paths: -------------- branches/physics25/extern/bullet2/src/Bullet-C-Api.h branches/physics25/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp branches/physics25/source/blender/blenkernel/BKE_rigidbody.h branches/physics25/source/blender/blenkernel/intern/group.c branches/physics25/source/blender/blenkernel/intern/object.c branches/physics25/source/blender/blenkernel/intern/rigidbody.c branches/physics25/source/blender/editors/screen/screen_edit.c branches/physics25/source/blender/makesrna/intern/rna_object.c Modified: branches/physics25/extern/bullet2/src/Bullet-C-Api.h =================================================================== --- branches/physics25/extern/bullet2/src/Bullet-C-Api.h 2009-12-17 15:39:36 UTC (rev 25440) +++ branches/physics25/extern/bullet2/src/Bullet-C-Api.h 2009-12-17 15:50:17 UTC (rev 25441) @@ -172,10 +172,20 @@ typedef void (*SetTransformFunc)(void *data, float m[][4]); void plSetMotionState(plRigidBodyHandle body, void *data, GetTransformFunc get, SetTransformFunc set); + void plDeleteMotionState(plRigidBodyHandle body); void plSetTransform(plRigidBodyHandle body, float m[][4]); void plGetTransform(plRigidBodyHandle body, float m[][4]); + void plSetMass(plRigidBodyHandle body, float mass); + void plSetCollisionShape(plRigidBodyHandle b, plCollisionShapeHandle shape); + /* void plRigidBodyActivate(plRigidBodyHandle body); */ + void plRigidBodyClearVelocities(plRigidBodyHandle b); + void plRigidBodyDisableSleeping(plRigidBodyHandle b); + int plRigidBodyIsStaticOrKinematic(plRigidBodyHandle b); + void plRigidBodySetGravity(plRigidBodyHandle b, float g[3]); - void plWorldSetGravity(plDynamicsWorldHandle world, float v[3]); + void plWorldSetGravity(plDynamicsWorldHandle world, float g[3]); + void plWorldGetGravity(plDynamicsWorldHandle world, float g[3]); + void plWorldStepSimulation(plDynamicsWorldHandle world, float timestep, int max_substeps, float fixed_timestep); #ifdef __cplusplus } Modified: branches/physics25/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp =================================================================== --- branches/physics25/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp 2009-12-17 15:39:36 UTC (rev 25440) +++ branches/physics25/extern/bullet2/src/BulletDynamics/Dynamics/Bullet-C-API.cpp 2009-12-17 15:50:17 UTC (rev 25441) @@ -464,7 +464,76 @@ #endif } +void plSetMass(plRigidBodyHandle b, float mass) +{ + btRigidBody *body = (btRigidBody*)b; + btVector3 localInertia(0, 0, 0); + + if (mass) + body->getCollisionShape()->calculateLocalInertia(mass, localInertia); + + body->setMassProps(mass, localInertia); + body->updateInertiaTensor(); +} + +void plSetCollisionShape(plRigidBodyHandle b, plCollisionShapeHandle shape) +{ + btRigidBody *body = ((btRigidBody*)b); + + if (body->getCollisionShape()) + plDeleteShape((plCollisionShapeHandle)body->getCollisionShape()); + + body->setCollisionShape((btCollisionShape*)shape); +} + +#if 0 +void plRigidBodyActivate(plRigidBodyHandle b) +{ + ((btRigidBody*)b)->activate(false); +} +#endif + +void plRigidBodyClearVelocities(plRigidBodyHandle b) +{ + btRigidBody *body= (btRigidBody*)b; + + body->setLinearVelocity(btVector3(0, 0, 0)); + body->setAngularVelocity(btVector3(0, 0, 0)); +} + +void plRigidBodyDisableSleeping(plRigidBodyHandle b) +{ + ((btRigidBody*)b)->setActivationState(DISABLE_DEACTIVATION); +} + +int plRigidBodyIsStaticOrKinematic(plRigidBodyHandle b) +{ + return ((btRigidBody*)b)->isStaticOrKinematicObject(); +} + +void plRigidBodySetGravity(plRigidBodyHandle b, float g[3]) +{ + btVector3 gravity(g[0], g[1], g[2]); + ((btRigidBody*)b)->setGravity(gravity); +} + void plWorldSetGravity(plDynamicsWorldHandle world, float v[3]) { ((btDynamicsWorld*)world)->setGravity(btVector3(v[0], v[1], v[2])); } + +void plWorldGetGravity(plDynamicsWorldHandle world, float v[3]) +{ + btVector3 g = ((btDynamicsWorld*)world)->getGravity(); + v[0] = (float)g[0]; + v[1] = (float)g[1]; + v[2] = (float)g[2]; +} + +void plWorldStepSimulation(plDynamicsWorldHandle world, float timestep, int max_substeps, float fixed_timestep) +{ + btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world); + btAssert(dynamicsWorld); + dynamicsWorld->stepSimulation(timestep, max_substeps, fixed_timestep); +} + Modified: branches/physics25/source/blender/blenkernel/BKE_rigidbody.h =================================================================== --- branches/physics25/source/blender/blenkernel/BKE_rigidbody.h 2009-12-17 15:39:36 UTC (rev 25440) +++ branches/physics25/source/blender/blenkernel/BKE_rigidbody.h 2009-12-17 15:50:17 UTC (rev 25441) @@ -31,6 +31,12 @@ #ifndef BKE_RIGIDBODY_H #define BKE_RIGIDBODY_H +extern void rigidbody_start(struct Scene *scene); extern void rigidbody_group_step(struct Group *group, struct Scene *scene); +extern void free_rigidbody_world(struct Group *group); +extern void rigidbody_sync_properties(struct Object *ob); +extern int object_is_rigidbody(struct Object *ob); +extern void free_rigidbody(struct Object *ob); + #endif Modified: branches/physics25/source/blender/blenkernel/intern/group.c =================================================================== --- branches/physics25/source/blender/blenkernel/intern/group.c 2009-12-17 15:39:36 UTC (rev 25440) +++ branches/physics25/source/blender/blenkernel/intern/group.c 2009-12-17 15:50:17 UTC (rev 25441) @@ -51,6 +51,7 @@ #include "BKE_library.h" #include "BKE_main.h" #include "BKE_object.h" +#include "BKE_rigidbody.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -72,6 +73,8 @@ BLI_remlink(&group->gobject, go); free_group_object(go); } + + free_rigidbody_world(group); } void unlink_group(Group *group) Modified: branches/physics25/source/blender/blenkernel/intern/object.c =================================================================== --- branches/physics25/source/blender/blenkernel/intern/object.c 2009-12-17 15:39:36 UTC (rev 25440) +++ branches/physics25/source/blender/blenkernel/intern/object.c 2009-12-17 15:50:17 UTC (rev 25441) @@ -106,6 +106,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_screen.h" @@ -308,6 +309,8 @@ free_sculptsession(&ob->sculpt); if(ob->pc_ids.first) BLI_freelistN(&ob->pc_ids); + + free_rigidbody(ob); } static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin) Modified: branches/physics25/source/blender/blenkernel/intern/rigidbody.c =================================================================== --- branches/physics25/source/blender/blenkernel/intern/rigidbody.c 2009-12-17 15:39:36 UTC (rev 25440) +++ branches/physics25/source/blender/blenkernel/intern/rigidbody.c 2009-12-17 15:50:17 UTC (rev 25441) @@ -33,28 +33,44 @@ #include "MEM_guardedalloc.h" #include "BLI_math.h" #include "BKE_object.h" +#include "BKE_group.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_scene.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" #include "DNA_group_types.h" +#include "DNA_action_types.h" #include "Bullet-C-Api.h" -static plPhysicsSdkHandle bullet_sdk; /* XXX global var */ +static plPhysicsSdkHandle bullet_sdk; /* XXX global */ typedef struct RigidBody { Object *ob; plRigidBodyHandle body; - float initm[4][4]; /* transform at start frame */ + + float initm[4][4]; /* initial transform */ + + /* used to detect if ob transform changed by non-physics */ + float prevloc[3]; + float prevrot[3]; } RigidBody; /* void object_to_rigidbody(); */ -static void make_rigid_body(Object *ob); +static RigidBody *make_rigid_body(Object *ob); static void reset_transform(Object *ob); +static plCollisionShapeHandle make_collision_shape(Object *ob); +static plDynamicsWorldHandle verify_world(Group *group); +static void push_transform(RigidBody *rb, float m[][4]); +static RigidBody *verify_rigidbody(Object *ob); +static int eq_v3_v3(float a[3], float b[3]); /* Q: how to update rigid body mass as it changes in Object + A: use rna_def_property_update() to catch property change Q: how to update collision shape when mesh changes? Q: when to free things? Q: what happens if object is in 2 or more physics groups simultaneously. Avoid this? @@ -68,6 +84,112 @@ int frame= scene->r.cfra, startframe= scene->r.sfra; float delta; + world= verify_world(group); + + for(go= group->gobject.first; go; go= go->next) { + Object *ob= go->ob; + RigidBody *r= verify_rigidbody(ob); + + /* sync transform */ + push_transform(go->ob->rigid, go->ob->obmat); + + /* if user translates ob, save the new loc as initial */ + if (!eq_v3_v3(ob->loc, r->prevloc)) + copy_v3_v3(r->initm[3], ob->loc); + + /* if user rotates ob, save the new rot as initial */ + if (!eq_v3_v3(ob->rot, r->prevrot)) { + float loc[3]; + copy_v3_v3(loc, r->initm[3]); + eul_to_mat4(r->initm, ob->rot); + copy_v3_v3(r->initm[3], loc); + } + } + + if (frame == startframe) { + /* start frame - reset positions */ + for(go= group->gobject.first; go; go= go->next) { + reset_transform(go->ob); + } + + prevframe= frame; + return; + } + + delta= FRA2TIME(frame) - FRA2TIME(prevframe); + + prevframe= frame; + + if (delta <= 0.0f) + return; + + /* do maximum 5 substeps */ + plWorldStepSimulation(world, delta, 5, 1.0f / FPS); + + /* save new positions */ + for(go= group->gobject.first; go; go= go->next) { + RigidBody *r= go->ob->rigid; + Object *ob= go->ob; + copy_v3_v3(r->prevloc, ob->loc); + copy_v3_v3(r->prevrot, ob->rot); + } +} + +/* not used anymore */ +void rigidbody_start(Scene *scene) +{ +#if 0 + Group *group; + GroupObject *go; + + /* for each physics group */ + for (group= G.main->group.first; group; group= group->id.next) { + if (group->flag & GR_PHYSICS) { + for (go= group->gobject.first; go; go= go->next) { + Object *ob= go->ob; + if (object_in_scene(ob, scene)) { + RigidBody *rb= verify_rigidbody(ob); + + /* store this transform as "initial"*/ + copy_m4_m4(rb->initm, ob->obmat); + push_transform(rb, rb->initm); + } + } + } + } +#endif +} + +void free_rigidbody_world(Group *group) +{ + if (group->physics_world) { + plDeleteDynamicsWorld(group->physics_world); + group->physics_world= NULL; + } +} + +static float rigid_body_mass(Object *ob) +{ + return ob->body_type == OB_BODY_TYPE_RIGID ? ob->mass : 0.0f; +} + +/* finds first physics group in which ob appears */ +static Group *find_physics_group(Object *ob) +{ + Group *group; + + for (group= G.main->group.first; group; group= group->id.next) { + if (group->flag & GR_PHYSICS) { + if (object_in_group(ob, group)) + return group; + } + } + + return NULL; +} + +static plDynamicsWorldHandle verify_world(Group *group) +{ if (!bullet_sdk) bullet_sdk= plNewBulletSdk(); @@ -77,34 +199,77 @@ plWorldSetGravity(group->physics_world, gra); } - world= group->physics_world; + return group->physics_world; +} @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org http://lists.blender.org/mailman/listinfo/bf-blender-cvs