From 089cf12435dfbc4b934a73b73ecd617b27ac678d Mon Sep 17 00:00:00 2001 From: Sergej Reich Date: Wed, 23 Jan 2013 05:56:34 +0000 Subject: [PATCH] rigidbody: Add point cache support Add read/write/interpolate functions. In order to get rigid body point cache id from object it's now required to pass the scene to BKE_ptcache_ids_from_object(). Rigid body cache is drawn in the orange color of the bullet logo. --- release/scripts/startup/bl_ui/space_time.py | 1 + source/blender/blenkernel/BKE_pointcache.h | 3 + source/blender/blenkernel/intern/pointcache.c | 144 ++++++++++++++++++ source/blender/blenkernel/intern/rigidbody.c | 10 +- source/blender/blenloader/intern/readfile.c | 6 + source/blender/blenloader/intern/writefile.c | 1 + source/blender/editors/object/object_edit.c | 2 +- .../blender/editors/space_time/space_time.c | 14 +- source/blender/makesdna/DNA_rigidbody_types.h | 2 + source/blender/makesdna/DNA_space_types.h | 1 + .../blender/makesrna/intern/rna_rigidbody.c | 6 + source/blender/makesrna/intern/rna_space.c | 5 + 12 files changed, 190 insertions(+), 5 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py index cb9e2444793..6af9f377237 100644 --- a/release/scripts/startup/bl_ui/space_time.py +++ b/release/scripts/startup/bl_ui/space_time.py @@ -152,6 +152,7 @@ class TIME_MT_cache(Menu): col.prop(st, "cache_cloth") col.prop(st, "cache_smoke") col.prop(st, "cache_dynamicpaint") + col.prop(st, "cache_rigidbody") class TIME_MT_frame(Menu): diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 7203400b267..1cb50425c40 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -67,6 +67,7 @@ #define PTCACHE_TYPE_SMOKE_DOMAIN 3 #define PTCACHE_TYPE_SMOKE_HIGHRES 4 #define PTCACHE_TYPE_DYNAMICPAINT 5 +#define PTCACHE_TYPE_RIGIDBODY 6 /* high bits reserved for flags that need to be stored in file */ #define PTCACHE_TYPEFLAG_COMPRESS (1 << 16) @@ -91,6 +92,7 @@ struct PointCache; struct Scene; struct SmokeModifierData; struct SoftBody; +struct RigidBodyWorld; /* temp structure for read/write */ typedef struct PTCacheData { @@ -260,6 +262,7 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct Par void BKE_ptcache_id_from_cloth(PTCacheID *pid, struct Object *ob, struct ClothModifierData *clmd); void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd); void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, struct Object *ob, struct DynamicPaintSurface *surface); +void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, struct Object *ob, struct RigidBodyWorld *rbw); void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index ac4b3099ba0..afc552ae7f3 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -43,6 +43,7 @@ #include "DNA_object_types.h" #include "DNA_object_force.h" #include "DNA_particle_types.h" +#include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_smoke_types.h" @@ -72,6 +73,8 @@ #include "BIK_api.h" +#include "RBI_api.h" + /* both in intern */ #ifdef WITH_SMOKE #include "smoke_API.h" @@ -867,6 +870,97 @@ static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v) return 1; } +/* Rigid Body functions */ +static int ptcache_rigidbody_write(int index, void *rb_v, void **data, int UNUSED(cfra)) +{ + RigidBodyWorld *rbw = rb_v; + Object *ob = NULL; + + if (rbw->objects) + ob = rbw->objects[index]; + + if (ob && ob->rigidbody_object) { + RigidBodyOb *rbo = ob->rigidbody_object; + + if (rbo->type == RBO_TYPE_ACTIVE) { + + RB_body_get_position(rbo->physics_object, rbo->pos); + RB_body_get_orientation(rbo->physics_object, rbo->orn); + + PTCACHE_DATA_FROM(data, BPHYS_DATA_LOCATION, rbo->pos); + PTCACHE_DATA_FROM(data, BPHYS_DATA_ROTATION, rbo->orn); + } + } + + return 1; +} +static void ptcache_rigidbody_read(int index, void *rb_v, void **data, float UNUSED(cfra), float *old_data) +{ + RigidBodyWorld *rbw = rb_v; + Object *ob = NULL; + + if (rbw->objects) + ob = rbw->objects[index]; + + if (ob && ob->rigidbody_object) { + RigidBodyOb *rbo = ob->rigidbody_object; + + if (rbo->type == RBO_TYPE_ACTIVE) { + + if (old_data) { + memcpy(rbo->pos, data, 3 * sizeof(float)); + memcpy(rbo->orn, data + 3, 4 * sizeof(float)); + } + else { + PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, rbo->pos); + PTCACHE_DATA_TO(data, BPHYS_DATA_ROTATION, 0, rbo->orn); + } + } + } +} +static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) +{ + RigidBodyWorld *rbw = rb_v; + Object *ob = NULL; + ParticleKey keys[4]; + float dfra; + + if (rbw->objects) + ob = rbw->objects[index]; + + if (ob && ob->rigidbody_object) { + RigidBodyOb *rbo = ob->rigidbody_object; + + if (rbo->type == RBO_TYPE_ACTIVE) { + + copy_v3_v3(keys[1].co, rbo->pos); + copy_v3_v3(keys[1].rot, rbo->orn); + + if (old_data) { + memcpy(keys[2].co, data, 3 * sizeof(float)); + memcpy(keys[2].rot, data + 3, 4 * sizeof(float)); + } + else { + BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); + } + + dfra = cfra2 - cfra1; + + psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1); + interp_qt_qtqt(keys->rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra); + + copy_v3_v3(rbo->pos, keys->co); + copy_v3_v3(rbo->orn, keys->rot); + } + } +} +static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra)) +{ + RigidBodyWorld *rbw = rb_v; + + return rbw->numbodies; +} + /* Creating ID's */ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) { @@ -1072,6 +1166,42 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSu pid->max_step = 1; } +void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *rbw) +{ + + memset(pid, 0, sizeof(PTCacheID)); + + pid->ob= ob; + pid->calldata= rbw; + pid->type= PTCACHE_TYPE_RIGIDBODY; + pid->cache= rbw->pointcache; + pid->cache_ptr= &rbw->pointcache; + pid->ptcaches= &rbw->ptcaches; + pid->totpoint= pid->totwrite= ptcache_rigidbody_totpoint; + + pid->write_point = ptcache_rigidbody_write; + pid->read_point = ptcache_rigidbody_read; + pid->interpolate_point = ptcache_rigidbody_interpolate; + + pid->write_stream = NULL; + pid->read_stream = NULL; + + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; + + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; + + pid->data_types= (1<info_types= 0; + + pid->stack_index = pid->cache->index; + + pid->default_step = 1; + pid->max_step = 1; +} + void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis) { PTCacheID *pid; @@ -1133,6 +1263,12 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup } } } + + if (scene && ob->rigidbody_object && scene->rigidbody_world) { + pid = MEM_callocN(sizeof(PTCacheID), "PTCacheID"); + BKE_ptcache_id_from_rigidbody(pid, ob, scene->rigidbody_world); + BLI_addtail(lb, pid); + } if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) { ListBase *lb_dupli_ob; @@ -2641,6 +2777,14 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) } } + if (scene->rigidbody_world && ob->rigidbody_object) { + if (ob->rigidbody_object) + ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_RESHAPE; + BKE_ptcache_id_from_rigidbody(&pid, ob, scene->rigidbody_world); + /* only flag as outdated, resetting should happen on start frame */ + pid.cache->flag |= PTCACHE_OUTDATED; + } + if (ob->type == OB_ARMATURE) BIK_clear_cache(ob->pose); diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 90200fd6742..17ced6fa54d 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -97,6 +97,10 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw) if (rbw->objects) free(rbw->objects); + /* free cache */ + BKE_ptcache_free_list(&(rbw->ptcaches)); + rbw->pointcache = NULL; + /* free effector weights */ if (rbw->effector_weights) MEM_freeN(rbw->effector_weights); @@ -472,6 +476,9 @@ RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) rbw->steps_per_second = 60; /* Bullet default (60 Hz) */ rbw->num_solver_iterations = 10; /* 10 is bullet default */ + rbw->pointcache = BKE_ptcache_add(&(rbw->ptcaches)); + rbw->pointcache->step = 1; + /* return this sim world */ return rbw; } @@ -749,7 +756,8 @@ void BKE_rigidbody_sync_transforms(Scene *scene, Object *ob, float ctime) void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) { -// RB_TODO implement this + if (rbw) + rbw->pointcache->flag |= PTCACHE_OUTDATED; } /* ------------------ */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index b0f1d3f37ed..edb033e80f8 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5303,6 +5303,12 @@ static void direct_link_scene(FileData *fd, Scene *sce) rbw->effector_weights = newdataadr(fd, rbw->effector_weights); if (!rbw->effector_weights) rbw->effector_weights = BKE_add_effector_weights(NULL); + + /* link cache */ + direct_link_pointcache_list(fd, &rbw->ptcaches, &rbw->pointcache, FALSE); + /* make sure simulation starts from the beginning after loading file */ + if (rbw->pointcache) + rbw->ltime = rbw->pointcache->startframe; } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index da50a05a3d9..ebd752c0118 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2307,6 +2307,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase) if (sce->rigidbody_world) { writestruct(wd, DATA, "RigidBodyWorld", 1, sce->rigidbody_world); writestruct(wd, DATA, "EffectorWeights", 1, sce->rigidbody_world->effector_weights); + write_pointcaches(wd, &(sce->rigidbody_world->ptcaches)); } sce= sce->id.next; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index fcc3b5d012e..5e5e38c3e43 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -376,7 +376,7 @@ void ED_object_exit_editmode(bContext *C, int flag) scene->obedit = NULL; // XXX for context /* flag object caches as outdated */ - BKE_ptcache_ids_from_object(&pidlist, obedit, NULL, 0); + BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0); for (pid = pidlist.first; pid; pid = pid->next) { if (pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */ pid->cache->flag |= PTCACHE_OUTDATED; diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index 13c1938d77c..e5bd9e62c74 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -92,7 +92,7 @@ static void time_draw_sfra_efra(Scene *scene, View2D *v2d) #define CACHE_DRAW_HEIGHT 3.0f -static void time_draw_cache(SpaceTime *stime, Object *ob) +static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) { PTCacheID *pid; ListBase pidlist; @@ -102,7 +102,7 @@ static void time_draw_cache(SpaceTime *stime, Object *ob) if (!(stime->cache_display & TIME_CACHE_DISPLAY) || (!ob)) return; - BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); + BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0); /* iterate over pointcaches on the active object, * add spacetimecache and vertex array for each */ @@ -128,6 +128,9 @@ static void time_draw_cache(SpaceTime *stime, Object *ob) case PTCACHE_TYPE_DYNAMICPAINT: if (!(stime->cache_display & TIME_CACHE_DYNAMICPAINT)) continue; break; + case PTCACHE_TYPE_RIGIDBODY: + if (!(stime->cache_display & TIME_CACHE_RIGIDBODY)) continue; + break; } if (pid->cache->cached_frames == NULL) @@ -193,6 +196,10 @@ static void time_draw_cache(SpaceTime *stime, Object *ob) col[0] = 1.0; col[1] = 0.1; col[2] = 0.75; col[3] = 0.1; break; + case PTCACHE_TYPE_RIGIDBODY: + col[0] = 1.0; col[1] = 0.6; col[2] = 0.0; + col[3] = 0.1; + break; default: BLI_assert(0); col[0] = 1.0; col[1] = 0.0; col[2] = 1.0; @@ -499,7 +506,7 @@ static void time_main_area_draw(const bContext *C, ARegion *ar) draw_markers_time(C, 0); /* caches */ - time_draw_cache(stime, obact); + time_draw_cache(stime, obact, scene); /* reset view matrix */ UI_view2d_view_restore(C); @@ -648,6 +655,7 @@ static void time_init(wmWindowManager *UNUSED(wm), ScrArea *sa) stime->cache_display |= TIME_CACHE_DISPLAY; stime->cache_display |= (TIME_CACHE_SOFTBODY | TIME_CACHE_PARTICLES); stime->cache_display |= (TIME_CACHE_CLOTH | TIME_CACHE_SMOKE | TIME_CACHE_DYNAMICPAINT); + stime->cache_display |= TIME_CACHE_RIGIDBODY; } static SpaceLink *time_duplicate(SpaceLink *sl) diff --git a/source/blender/makesdna/DNA_rigidbody_types.h b/source/blender/makesdna/DNA_rigidbody_types.h index 43c2cdb227a..e08162fedd6 100644 --- a/source/blender/makesdna/DNA_rigidbody_types.h +++ b/source/blender/makesdna/DNA_rigidbody_types.h @@ -57,6 +57,8 @@ typedef struct RigidBodyWorld { float ltime; /* last frame world was evaluated for (internal) */ /* cache */ + struct PointCache *pointcache; + struct ListBase ptcaches; int numbodies; /* number of objects in rigid body group */ short steps_per_second; /* number of simulation steps thaken per second */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index ae845cb5aa3..da9fdc776b5 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -447,6 +447,7 @@ typedef enum eTimeline_Cache_Flag { TIME_CACHE_CLOTH = (1 << 3), TIME_CACHE_SMOKE = (1 << 4), TIME_CACHE_DYNAMICPAINT = (1 << 5), + TIME_CACHE_RIGIDBODY = (1 << 6), } eTimeline_Cache_Flag; diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c index cd8b63cd0de..1e0e250ac66 100644 --- a/source/blender/makesrna/intern/rna_rigidbody.c +++ b/source/blender/makesrna/intern/rna_rigidbody.c @@ -346,6 +346,12 @@ static void rna_def_rigidbody_world(BlenderRNA *brna) 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"); + /* cache */ + prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "pointcache"); + RNA_def_property_ui_text(prop, "Point Cache", ""); + /* effector weights */ prop = RNA_def_property(srna, "effector_weights", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "EffectorWeights"); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 5d009a627e6..f7e9899421e 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2760,6 +2760,11 @@ static void rna_def_space_time(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_DYNAMICPAINT); RNA_def_property_ui_text(prop, "Dynamic Paint", "Show the active object's Dynamic Paint cache"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL); + + prop = RNA_def_property(srna, "cache_rigidbody", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "cache_display", TIME_CACHE_RIGIDBODY); + RNA_def_property_ui_text(prop, "Rigid Body", "Show the active object's Rigid Body cache"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_TIME, NULL); } static void rna_def_console_line(BlenderRNA *brna)