Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJanne Karhu <jhkarh@gmail.com>2009-06-27 19:28:58 +0400
committerJanne Karhu <jhkarh@gmail.com>2009-06-27 19:28:58 +0400
commit912c2f440b447aa8cae9f3e3a86acf51cd495e3d (patch)
tree57b5274640b0c0854f83ff0e3e4ba43902a69ddc /source/blender/blenkernel
parent9becf3c310b1051d1e9dc7170cb02d73bc4d6e08 (diff)
Pointcache refresh part 2
* Based on what happens during simulation the cache is marked (also in cache panel, this could possibly be extended to 3d view as well) as: - exact (not marked) - outdated (simulation is not done completely with current settings) - non-exact (frames were skipped during simulation) * The parameter "cache step" effects the number of frames between saved cache frames. - This can save a lot of memory (or disk space) if absolutely frame accurate simulation is not required. - Speeds up the "quick caching" very much. - Frames between cached frames are interpolated from the cached frames. - Current default value of 10 frames works nicely with up/down-arrows (skip 10 frames forwards/backwards on timeline), but can be changed if wanted. * The caching can work in normal or "quick" mode: [Normal cache] - Basic: Calculate what even happens (settings change, big frame steps etc.) and cache results, if possible try to use "cache step" when saving cache frames. - Becomes non-exact: After larger than 1 frame steps. - Becomes outdated: After any change effecting the simulation other than frame steps. - Pros/cons: Freedom of doing anything and playing with particles, but exact results have to calculated from the beginning. [Quick cache] - Basic: Calculate simulation up to current frame automatically on changes with cache step sized jumps in simulation. With multiple "quick cached" simulations the smallest cache step is used. - Becomes non-exact: Always from frame 1 (unless cache step = 1). - Becomes outdated: Never. - Pros/cons: Not very accurate, but super fast! - Todo: Transform of any animated (non-autokeyed) object is locked! Probably needs some tinkering with anim sys overrides. * The simulation can be run forwards or backwards even if it's cache is outdated or non-exact, the following rules apply in these situations: - step forwards (to unknown) -> simulate from last exact frame, store result - step backwards (to known) -> result is interpolated from existing frames, store result, clear cache forwards if current frame is after last exact frame * "Calculate to current frame" runs the simulation from start to current frame with a frame steps of 1. - Baking does the same, but runs the simulation all the way to the end of simulation. - Rendering does this automatically if the simulation is outdated of non-exact, so all rendered simulations will always be updated and exact. * Every cache panel also holds buttons to "Bake all dynamics", "Free all dynamics" and "Update all dynamics to current frame". * Cloth simulation supports the new cache too.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_cloth.h5
-rw-r--r--source/blender/blenkernel/BKE_particle.h1
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h13
-rw-r--r--source/blender/blenkernel/intern/cloth.c164
-rw-r--r--source/blender/blenkernel/intern/implicit.c10
-rw-r--r--source/blender/blenkernel/intern/particle.c27
-rw-r--r--source/blender/blenkernel/intern/particle_system.c57
-rw-r--r--source/blender/blenkernel/intern/pointcache.c475
8 files changed, 457 insertions, 295 deletions
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index e09be838f06..4270c677338 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -46,6 +46,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
#include "BKE_collision.h"
@@ -245,8 +246,8 @@ void bvhtree_update_from_cloth ( ClothModifierData *clmd, int moving );
void bvhselftree_update_from_cloth ( ClothModifierData *clmd, int moving );
// needed for editmesh.c
-void cloth_write_cache ( Object *ob, ClothModifierData *clmd, float framenr );
-int cloth_read_cache ( Object *ob, ClothModifierData *clmd, float framenr );
+void cloth_write_cache( Object *ob, ClothModifierData *clmd, int framenr );
+int cloth_read_cache( Scene *scene, Object *ob, ClothModifierData *clmd, float framenr, int *old_framenr );
// needed for button_object.c
void cloth_clear_cache ( Object *ob, ClothModifierData *clmd, float framenr );
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 0ecd71fc4a3..08aa111e0e6 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -252,7 +252,6 @@ struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct P
struct ParticleSettings *psys_new_settings(char *name, struct Main *main);
struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part);
-int psys_count_autocache(struct Scene *scene, struct ParticleSettings *part);
void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *part, int recalc);
void make_local_particlesettings(struct ParticleSettings *part);
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index b79357edf36..3f1c45d28ec 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -93,7 +93,7 @@ typedef struct PTCacheWriter {
int cfra;
int totelem;
- float *(*elem_ptr)(int index, void *calldata);
+ void (*set_elem)(int index, void *calldata, float *data);
void *calldata;
} PTCacheWriter;
@@ -103,12 +103,10 @@ typedef struct PTCacheReader {
float cfra;
int totelem;
- void (*set_elem)(int index, void *calldata, float *data);
- void (*interpolate_elem)(int index, void *calldata, float frs_sec, float cfra, int cfra1, int cfra2, float *data1, float *data2);
+ void (*set_elem)(int elem_index, void *calldata, float *data);
+ void (*interpolate_elem)(int index, void *calldata, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2);
void *calldata;
- int allow_interpolate;
- int allow_old;
int *old_frame;
} PTCacheReader;
@@ -116,6 +114,7 @@ typedef struct PTCacheBaker {
struct Scene *scene;
int bake;
int render;
+ int quick_step;
struct PTCacheID *pid;
int (*break_test)(void *data);
void *break_data;
@@ -146,6 +145,8 @@ void BKE_ptcache_file_close(PTCacheFile *pf);
int BKE_ptcache_file_read_floats(PTCacheFile *pf, float *f, int tot);
int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot);
+void BKE_ptcache_update_info(PTCacheID *pid);
+
/* General cache reading/writing */
int BKE_ptcache_read_cache(PTCacheReader *reader);
int BKE_ptcache_write_cache(PTCacheWriter *writer);
@@ -160,7 +161,7 @@ void BKE_ptcache_free(struct PointCache *cache);
struct PointCache *BKE_ptcache_copy(struct PointCache *cache);
/* Baking */
-void BKE_ptcache_autocache_all(struct Scene *scene);
+void BKE_ptcache_quick_cache_all(struct Scene *scene);
void BKE_ptcache_make_cache(struct PTCacheBaker* baker);
void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid);
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index e98d7bb01a4..08caea565aa 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -33,6 +33,7 @@
#include "DNA_mesh_types.h"
#include "DNA_object_force.h"
#include "DNA_scene_types.h"
+#include "DNA_particle_types.h"
#include "BKE_deform.h"
#include "BKE_DerivedMesh.h"
@@ -42,6 +43,7 @@
#include "BKE_object.h"
#include "BKE_modifier.h"
#include "BKE_utildefines.h"
+#include "BKE_particle.h"
#include "BKE_pointcache.h"
@@ -339,78 +341,99 @@ void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving)
}
int modifiers_indexInObject(Object *ob, ModifierData *md_seek);
+static void cloth_write_state(int index, Cloth *cloth, float *data)
+{
+ ClothVertex *vert = cloth->verts + index;
-int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr)
+ memcpy(data, vert->x, 3 * sizeof(float));
+ memcpy(data + 3, vert->xconst, 3 * sizeof(float));
+ memcpy(data + 6, vert->v, 3 * sizeof(float));
+}
+static void cloth_read_state(int index, Cloth *cloth, float *data)
{
- PTCacheID pid;
- PTCacheFile *pf;
- Cloth *cloth = clmd->clothObject;
- unsigned int a, ret = 1;
+ ClothVertex *vert = cloth->verts + index;
- if(!cloth)
- return 0;
-
- BKE_ptcache_id_from_cloth(&pid, ob, clmd);
- pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, framenr);
- if(pf) {
- for(a = 0; a < cloth->numverts; a++) {
- if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].x, 3)) {
- ret = 0;
- break;
- }
- if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].xconst, 3)) {
- ret = 0;
- break;
- }
- if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].v, 3)) {
- ret = 0;
- break;
- }
- }
-
- BKE_ptcache_file_close(pf);
- }
- else
- ret = 0;
-
- return ret;
+ memcpy(vert->x, data, 3 * sizeof(float));
+ memcpy(vert->xconst, data + 3, 3 * sizeof(float));
+ memcpy(vert->v, data + 6, 3 * sizeof(float));
}
+static void cloth_cache_interpolate(int index, Cloth *cloth, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2)
+{
+ ClothVertex *vert = cloth->verts + index;
+ ParticleKey keys[4];
+ float dfra;
-void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
+ if(cfra1 == cfra2) {
+ cloth_read_state(index, cloth, data1);
+ return;
+ }
+
+ memcpy(keys[1].co, data1, 3 * sizeof(float));
+ memcpy(keys[1].vel, data1 + 6, 3 * sizeof(float));
+
+ memcpy(keys[2].co, data2, 3 * sizeof(float));
+ memcpy(keys[2].vel, data2 + 6, 3 * sizeof(float));
+
+ dfra = cfra2 - cfra1;
+
+ VecMulf(keys[1].vel, dfra);
+ VecMulf(keys[2].vel, dfra);
+
+ psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1);
+
+ VecMulf(keys->vel, 1.0f / dfra);
+
+ memcpy(vert->x, keys->co, 3 * sizeof(float));
+ memcpy(vert->v, keys->vel, 3 * sizeof(float));
+
+ /* not sure what to do with this - jahka */
+ memcpy(vert->xconst, data1 + 3, 3 * sizeof(float));
+}
+void cloth_write_cache(Object *ob, ClothModifierData *clmd, int cfra)
{
+ PTCacheWriter writer;
PTCacheID pid;
-
+
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
- // don't do anything as long as we're in editmode!
- if(pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE)
- return;
-
- BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr);
+ writer.calldata = clmd->clothObject;
+ writer.cfra = cfra;
+ writer.set_elem = cloth_write_state;
+ writer.pid = &pid;
+ writer.totelem = clmd->clothObject->numverts;
+
+ BKE_ptcache_write_cache(&writer);
}
-void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr)
+int cloth_read_cache(Scene *scene, Object *ob, ClothModifierData *clmd, float cfra, int *old_framenr)
{
- Cloth *cloth = clmd->clothObject;
+ PTCacheReader reader;
PTCacheID pid;
- PTCacheFile *pf;
- unsigned int a;
- if(!cloth)
- return;
+ BKE_ptcache_id_from_cloth(&pid, ob, clmd);
+
+ reader.calldata = clmd->clothObject;
+ reader.cfra = cfra;
+ reader.interpolate_elem = cloth_cache_interpolate;
+ reader.old_frame = old_framenr;
+ reader.pid = &pid;
+ reader.scene = scene;
+ reader.set_elem = cloth_read_state;
+ reader.totelem = clmd->clothObject->numverts;
+
+ return BKE_ptcache_read_cache(&reader);
+}
+void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
+{
+ PTCacheID pid;
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
- pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_WRITE, framenr);
- if(!pf)
+
+ // don't do anything as long as we're in editmode!
+ if(pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE)
return;
- for(a = 0; a < cloth->numverts; a++) {
- BKE_ptcache_file_write_floats(pf, cloth->verts[a].x, 3);
- BKE_ptcache_file_write_floats(pf, cloth->verts[a].xconst, 3);
- BKE_ptcache_file_write_floats(pf, cloth->verts[a].v, 3);
- }
-
- BKE_ptcache_file_close(pf);
+ BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr);
}
static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr)
@@ -486,6 +509,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
PTCacheID pid;
float timescale;
int framedelta, framenr, startframe, endframe;
+ int cache_result, old_framenr;
clmd->scene= scene; /* nice to pass on later :) */
framenr= (int)scene->r.cfra;
@@ -499,6 +523,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
if(!result) {
cache->flag &= ~PTCACHE_SIMULATION_VALID;
cache->simframe= 0;
+ cache->last_exact= 0;
return dm;
}
@@ -510,6 +535,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
if(result->getNumVerts(result) != clmd->clothObject->numverts) {
cache->flag &= ~PTCACHE_SIMULATION_VALID;
cache->simframe= 0;
+ cache->last_exact= 0;
return result;
}
}
@@ -521,6 +547,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
if(BKE_ptcache_get_continue_physics()) {
cache->flag &= ~PTCACHE_SIMULATION_VALID;
cache->simframe= 0;
+ cache->last_exact= 0;
/* do simulation */
if(!do_init_cloth(ob, clmd, result, framenr))
@@ -536,6 +563,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
if(framenr < startframe) {
cache->flag &= ~PTCACHE_SIMULATION_VALID;
cache->simframe= 0;
+ cache->last_exact= 0;
return result;
}
else if(framenr > endframe) {
@@ -552,7 +580,9 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
return result;
/* try to read from cache */
- if(cloth_read_cache(ob, clmd, framenr)) {
+ cache_result = cloth_read_cache(scene, ob, clmd, framenr, &old_framenr);
+
+ if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) {
cache->flag |= PTCACHE_SIMULATION_VALID;
cache->simframe= framenr;
@@ -561,25 +591,40 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
return result;
}
+ else if(cache_result==PTCACHE_READ_OLD) {
+ BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE);
+
+ implicit_set_positions(clmd);
+
+ cache->flag |= PTCACHE_SIMULATION_VALID;
+ cache->simframe= old_framenr;
+ }
else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) {
/* if baked and nothing in cache, do nothing */
cache->flag &= ~PTCACHE_SIMULATION_VALID;
cache->simframe= 0;
+ cache->last_exact= 0;
return result;
}
if(framenr == startframe) {
+ if(cache->flag & PTCACHE_REDO_NEEDED) {
+ BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
+ do_init_cloth(ob, clmd, result, framenr);
+ }
cache->flag |= PTCACHE_SIMULATION_VALID;
cache->simframe= framenr;
/* don't write cache on first frame, but on second frame write
* cache for frame 1 and 2 */
}
- else if(framedelta == 1) {
+ else {
/* if on second frame, write cache for first frame */
- if(framenr == startframe+1)
+ if(cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
cloth_write_cache(ob, clmd, startframe);
+ clmd->sim_parms->timescale *= framenr - cache->simframe;
+
/* do simulation */
cache->flag |= PTCACHE_SIMULATION_VALID;
cache->simframe= framenr;
@@ -587,16 +632,13 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob,
if(!do_step_cloth(ob, clmd, result, framenr)) {
cache->flag &= ~PTCACHE_SIMULATION_VALID;
cache->simframe= 0;
+ cache->last_exact= 0;
}
else
cloth_write_cache(ob, clmd, framenr);
cloth_to_object (ob, clmd, result);
}
- else {
- cache->flag &= ~PTCACHE_SIMULATION_VALID;
- cache->simframe= 0;
- }
return result;
}
diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c
index 40c98c1d9cc..fc5213d5532 100644
--- a/source/blender/blenkernel/intern/implicit.c
+++ b/source/blender/blenkernel/intern/implicit.c
@@ -1600,6 +1600,10 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
if(clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED)
{
+ float temp = clmd->sim_parms->stepsPerFrame;
+ /* not too nice hack, but collisions need this correction -jahka */
+ clmd->sim_parms->stepsPerFrame /= clmd->sim_parms->timescale;
+
// collisions
// itstart();
@@ -1614,7 +1618,7 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
// call collision function
// TODO: check if "step" or "step+dt" is correct - dg
- result = cloth_bvh_objcollision(ob, clmd, step, dt);
+ result = cloth_bvh_objcollision(ob, clmd, step/clmd->sim_parms->timescale, dt/clmd->sim_parms->timescale);
// correct velocity again, just to be sure we had to change it due to adaptive collisions
for(i = 0; i < numverts; i++)
@@ -1637,6 +1641,9 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
}
}
+ /* restore original stepsPerFrame */
+ clmd->sim_parms->stepsPerFrame = temp;
+
// X = Xnew;
cp_lfvector(id->X, id->Xnew, numverts);
@@ -1654,7 +1661,6 @@ int implicit_solver (Object *ob, float frame, ClothModifierData *clmd, ListBase
simulate_implicit_euler(id->Vnew, id->X, id->V, id->F, id->dFdV, id->dFdX, dt / 2.0f, id->A, id->B, id->dV, id->S, id->z, id->olddV, id->P, id->Pinv, id->M, id->bigI);
}
-
}
else
{
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 5b3720cd6b0..04215b1ddd1 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -236,31 +236,6 @@ Object *psys_find_object(Scene *scene, ParticleSystem *psys)
return NULL;
}
-int psys_count_autocache(Scene *scene, ParticleSettings *part)
-{
- Base *base = scene->base.first;
- ParticleSystem *psys;
- PTCacheID pid;
- int autocache_count= 0;
-
- for(base = scene->base.first; base; base = base->next) {
- for(psys = base->object->particlesystem.first; psys; psys=psys->next) {
- if(part && psys->part != part)
- continue;
-
- BKE_ptcache_id_from_particles(&pid, base->object, psys);
-
- if((psys->pointcache->flag & PTCACHE_BAKED)
- || (psys->pointcache->flag & PTCACHE_AUTOCACHE)==0)
- continue;
-
- if((psys->pointcache->flag & PTCACHE_OUTDATED)
- || BKE_ptcache_id_exist(&pid, CFRA)==0)
- autocache_count++;
- }
- }
- return autocache_count;
-}
/* change object's active particle system */
void psys_change_act(void *ob_v, void *act_v)
{
@@ -3740,6 +3715,8 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
if((pa->alive==PARS_UNBORN && (part->flag & PART_UNBORN)==0)
|| (pa->alive==PARS_DEAD && (part->flag & PART_DIED)==0))
return 0;
+
+ state->time = MIN2(state->time, pa->dietime);
}
if(psys->flag & PSYS_KEYED){
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 97b1956bba9..591b6ca9be5 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -2205,11 +2205,9 @@ void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra
*sfra = MAX2(1, (int)part->sta);
*efra = MIN2((int)(part->end + part->lifetime + 1.0), scene->r.efra);
}
-static float *particle_state_ptr(int index, void *psys_ptr)
+static void particle_write_state(int index, ParticleSystem *psys, float *data)
{
- ParticleSystem *psys= psys_ptr;
-
- return (float *)(&(psys->particles+index)->state);
+ memcpy(data, (float *)(&(psys->particles+index)->state), sizeof(ParticleKey));
}
static void particle_read_state(int index, void *psys_ptr, float *data)
{
@@ -2222,24 +2220,35 @@ static void particle_read_state(int index, void *psys_ptr, float *data)
copy_particle_key(&pa->state, key, 1);
}
-static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec, float cfra, int cfra1, int cfra2, float *data1, float *data2)
+static void particle_cache_interpolate(int index, void *psys_ptr, float frs_sec, float cfra, float cfra1, float cfra2, float *data1, float *data2)
{
ParticleSystem *psys= psys_ptr;
ParticleData *pa = psys->particles + index;
ParticleKey keys[4];
- float dfra;
+ float dfra, cfra1f = (float)cfra1, cfra2f(float);
+
+ cfra = MIN2(cfra, pa->dietime);
+ cfra1 = MIN2(cfra1, pa->dietime);
+ cfra2 = MIN2(cfra2, pa->dietime);
keys[1] = *((ParticleKey*)data1);
keys[2] = *((ParticleKey*)data2);
- dfra = keys[2].time - keys[1].time;
+ if(cfra1 == cfra2) {
+ copy_particle_key(&pa->state, &keys[1], 1);
+ return;
+ }
+
+ dfra = cfra2 - cfra1;
VecMulf(keys[1].vel, dfra / frs_sec);
VecMulf(keys[2].vel, dfra / frs_sec);
- psys_interpolate_particle(-1, keys, (keys[1].time - cfra) / dfra, &pa->state, 1);
+ psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1);
VecMulf(pa->state.vel, frs_sec / dfra);
+
+ pa->state.time = cfra;
}
static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra)
{
@@ -2250,22 +2259,20 @@ static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra)
writer.calldata = psys;
writer.cfra = cfra;
- writer.elem_ptr = particle_state_ptr;
+ writer.set_elem = particle_write_state;
writer.pid = &pid;
writer.totelem = psys->totpart;
BKE_ptcache_write_cache(&writer);
}
-static int get_particles_from_cache(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int allow_interpolate, int allow_old, int *old_frame)
+static int get_particles_from_cache(Scene *scene, Object *ob, ParticleSystem *psys, float cfra, int *old_frame)
{
PTCacheReader reader;
PTCacheID pid;
BKE_ptcache_id_from_particles(&pid, ob, psys);
- reader.allow_interpolate = allow_interpolate;
- reader.allow_old = allow_old;
reader.calldata = psys;
reader.cfra = cfra;
reader.interpolate_elem = particle_cache_interpolate;
@@ -2402,6 +2409,8 @@ static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obs
Object *tob;
for(i=0; epsys; epsys=epsys->next,i++){
+ if(!psys_check_enabled(ob, epsys))
+ continue;
type=0;
if(epsys!=psys || (psys->part->flag & PART_SELF_EFFECT)){
epart=epsys->part;
@@ -4366,7 +4375,7 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps
pa->alive = PARS_UNBORN;
else if(dietime <= cfra){
if(dietime > psys->cfra){
- state.time = pa->dietime;
+ state.time = dietime;
psys_get_particle_state(scene, ob,psys,p,&state,1);
push_reaction(ob,psys,p,PART_EVENT_DEATH,&state);
}
@@ -4668,9 +4677,9 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
/* try to read from the cache */
if(usecache) {
- int result = get_particles_from_cache(scene, ob, psys, (float)framenr, 0, 1, &old_framenr);
+ int result = get_particles_from_cache(scene, ob, psys, (float)framenr, &old_framenr);
- if(result == PTCACHE_READ_EXACT) {
+ if(result == PTCACHE_READ_EXACT || result == PTCACHE_READ_INTERPOLATED) {
//if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
// psys_count_keyed_targets(ob,psys);
// set_keyed_keys(scene, ob, psys);
@@ -4687,15 +4696,12 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
cache->simframe= framenr;
cache->flag |= PTCACHE_SIMULATION_VALID;
- if(cache->flag & PTCACHE_OUTDATED)
- BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE);
+ if(result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED)
+ write_particles_to_cache(ob, psys, cfra);
return;
}
- else if((cache->flag & PTCACHE_AUTOCACHE)==0 && result==PTCACHE_READ_OLD) {
- /* clear cache after current frame */
- BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_FREE);
-
+ else if(result==PTCACHE_READ_OLD) {
/* set old cfra */
psys->cfra = (float)old_framenr;
@@ -4715,15 +4721,6 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
psys->recalc = 0;
return;
}
-
- if(framenr != startframe && framedelta != 1 && cache->flag & PTCACHE_AUTOCACHE) {
- //psys_reset(psys, PSYS_RESET_CACHE_MISS);
- /* make sure cache is recalculated */
- BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_FRAME, (int)cfra);
- psys->cfra = cfra;
- psys->recalc = 0;
- return;
- }
}
else {
cache->flag &= ~PTCACHE_SIMULATION_VALID;
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index b514ac026fb..64473d07151 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -303,7 +303,7 @@ static int ptcache_pid_elemsize(PTCacheID *pid)
else if(pid->type==PTCACHE_TYPE_PARTICLES)
return sizeof(ParticleKey);
else if(pid->type==PTCACHE_TYPE_CLOTH)
- return 0; // TODO
+ return 9 * sizeof(float);
return 0;
}
@@ -321,10 +321,11 @@ static int ptcache_pid_totelem(PTCacheID *pid)
return 0;
}
-void ptcache_update_info(PTCacheID *pid)
+void BKE_ptcache_update_info(PTCacheID *pid)
{
PointCache *cache = pid->cache;
int totframes = 0;
+ char mem_info[64];
if(cache->flag & PTCACHE_DISK_CACHE) {
int cfra = cache->startframe;
@@ -334,7 +335,7 @@ void ptcache_update_info(PTCacheID *pid)
totframes++;
}
- sprintf(cache->info, "%i frames on disk.", totframes);
+ sprintf(mem_info, "%i frames on disk", totframes);
}
else {
PTCacheMem *pm = cache->mem_cache.first;
@@ -351,11 +352,20 @@ void ptcache_update_info(PTCacheID *pid)
mb = (bytes > 1024.0f * 1024.0f);
- sprintf(cache->info, "%i frames in memory (%.1f %s).",
+ sprintf(mem_info, "%i frames in memory (%.1f %s)",
totframes,
bytes / (mb ? 1024.0f * 1024.0f : 1024.0f),
mb ? "Mb" : "kb");
}
+
+ if(cache->flag & PTCACHE_OUTDATED) {
+ sprintf(cache->info, "%s, cache is outdated!", mem_info);
+ }
+ else if(cache->flag & PTCACHE_FRAMES_SKIPPED) {
+ sprintf(cache->info, "%s, not exact since frame %i.", mem_info, cache->last_exact);
+ }
+ else
+ sprintf(cache->info, "%s.", mem_info);
}
/* reads cache from disk or memory */
/* possible to get old or interpolated result */
@@ -370,10 +380,13 @@ int BKE_ptcache_read_cache(PTCacheReader *reader)
int elemsize = ptcache_pid_elemsize(pid);
int i, incr = elemsize / sizeof(float);
float frs_sec = reader->scene->r.frs_sec;
+ int cfra1=0, cfra2;
+ int ret = 0;
if(totelem == 0)
return 0;
+
/* first check if we have the actual frame cached */
if(cfra == (float)cfrai) {
if(pid->cache->flag & PTCACHE_DISK_CACHE) {
@@ -419,130 +432,147 @@ int BKE_ptcache_read_cache(PTCacheReader *reader)
MEM_freeN(data);
}
- return PTCACHE_READ_EXACT;
+ ret = PTCACHE_READ_EXACT;
}
- /* no exact cache frame found so try to find cached frames around cfra */
- if(reader->allow_interpolate || reader->allow_old) {
- int cfra1, cfra2;
- if(pid->cache->flag & PTCACHE_DISK_CACHE) {
- pf=NULL;
- while(cfrai > pid->cache->startframe && !pf) {
- cfrai--;
- pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
- cfra1 = cfrai;
- }
+ if(ret)
+ ;
+ /* no exact cache frame found so try to find cached frames around cfra */
+ else if(pid->cache->flag & PTCACHE_DISK_CACHE) {
+ pf=NULL;
+ while(cfrai > pid->cache->startframe && !pf) {
+ cfrai--;
+ pf= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
+ cfra1 = cfrai;
+ }
+ if(reader->old_frame)
*(reader->old_frame) = cfrai;
- cfrai = (int)cfra;
- while(cfrai < pid->cache->endframe && !pf2) {
- cfrai++;
- pf2= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
- cfra2 = cfrai;
- }
+ cfrai = (int)cfra;
+ while(cfrai < pid->cache->endframe && !pf2) {
+ cfrai++;
+ pf2= BKE_ptcache_file_open(pid, PTCACHE_FILE_READ, cfrai);
+ cfra2 = cfrai;
}
- else if(pid->cache->mem_cache.first){
- pm = pid->cache->mem_cache.first;
+ }
+ else if(pid->cache->mem_cache.first){
+ pm = pid->cache->mem_cache.first;
- while(pm->next && pm->next->frame < cfra)
- pm= pm->next;
+ while(pm->next && pm->next->frame < cfra)
+ pm= pm->next;
- if(pm) {
+ if(pm) {
+ if(reader->old_frame)
*(reader->old_frame) = pm->frame;
- cfra1 = pm->frame;
- }
+ cfra1 = pm->frame;
+ }
- pm2 = pid->cache->mem_cache.last;
+ pm2 = pid->cache->mem_cache.last;
- while(pm2->prev && pm2->frame > cfra)
+ if(pm2 && pm2->frame < cfra)
+ pm2 = NULL;
+ else {
+ while(pm2->prev && pm2->prev->frame > cfra)
pm2= pm2->prev;
if(pm2)
cfra2 = pm2->frame;
}
+ }
- if(reader->allow_interpolate && ((pf && pf2) || (pm && pm2))) {
- /* interpolate from nearest frames */
- float *data1, *data2;
+ if(ret)
+ ;
+ else if((pf && pf2) || (pm && pm2)) {
+ /* interpolate from nearest frames if cache isn't outdated */
+ float *data1, *data2;
- if(pm) {
- data1 = pm->data;
- data2 = pm2->data;
- }
- else {
- data1 = MEM_callocN(elemsize, "pointcache read data1");
- data2 = MEM_callocN(elemsize, "pointcache read data2");
- }
+ if(pm) {
+ data1 = pm->data;
+ data2 = pm2->data;
+ }
+ else {
+ data1 = MEM_callocN(elemsize, "pointcache read data1");
+ data2 = MEM_callocN(elemsize, "pointcache read data2");
+ }
- for(i=0; i<totelem; i++) {
- if(pf && pf2) {
- if(!BKE_ptcache_file_read_floats(pf, data1, incr)) {
- BKE_ptcache_file_close(pf);
- BKE_ptcache_file_close(pf2);
- MEM_freeN(data1);
- MEM_freeN(data2);
- return 0;
- }
- if(!BKE_ptcache_file_read_floats(pf2, data2, incr)) {
- BKE_ptcache_file_close(pf);
- BKE_ptcache_file_close(pf2);
- MEM_freeN(data1);
- MEM_freeN(data2);
- return 0;
- }
- reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, cfra1, cfra2, data1, data2);
+ for(i=0; i<totelem; i++) {
+ if(pf && pf2) {
+ if(!BKE_ptcache_file_read_floats(pf, data1, incr)) {
+ BKE_ptcache_file_close(pf);
+ BKE_ptcache_file_close(pf2);
+ MEM_freeN(data1);
+ MEM_freeN(data2);
+ return 0;
}
- else {
- reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, cfra1, cfra2, data1, data2);
- data1 += incr;
- data2 += incr;
+ if(!BKE_ptcache_file_read_floats(pf2, data2, incr)) {
+ BKE_ptcache_file_close(pf);
+ BKE_ptcache_file_close(pf2);
+ MEM_freeN(data1);
+ MEM_freeN(data2);
+ return 0;
}
+ reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2);
}
+ else {
+ reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2);
+ data1 += incr;
+ data2 += incr;
+ }
+ }
- if(pf) {
+ if(pf) {
+ BKE_ptcache_file_close(pf);
+ BKE_ptcache_file_close(pf2);
+ MEM_freeN(data1);
+ MEM_freeN(data2);
+ }
+
+ ret = PTCACHE_READ_INTERPOLATED;
+ }
+ else if(pf || pm) {
+ /* use last valid cache frame */
+ float *data;
+
+ /* don't read cache if allready simulated past cached frame */
+ if(cfra1 && cfra1 <= pid->cache->simframe) {
+ if(pf)
BKE_ptcache_file_close(pf);
+ if(pf2)
BKE_ptcache_file_close(pf2);
- MEM_freeN(data1);
- MEM_freeN(data2);
- }
- return PTCACHE_READ_INTERPOLATED;
+ return 0;
}
- else if(reader->allow_old && (pf || pm)) {
- /* use last valid cache frame */
- float *data;
- if(pm)
- data = pm->data;
- else
- data = MEM_callocN(elemsize, "pointcache read data");
-
- for(i=0; i<totelem; i++) {
- if(pf) {
- if(!BKE_ptcache_file_read_floats(pf, data, incr)) {
- BKE_ptcache_file_close(pf);
- if(pf2)
- BKE_ptcache_file_close(pf2);
- return 0;
- }
- reader->set_elem(i, reader->calldata, data);
- }
- else {
- reader->set_elem(i, reader->calldata, data);
- data += incr;
- }
- }
+ if(pm)
+ data = pm->data;
+ else
+ data = MEM_callocN(elemsize, "pointcache read data");
+ for(i=0; i<totelem; i++) {
if(pf) {
- BKE_ptcache_file_close(pf);
- MEM_freeN(data);
+ if(!BKE_ptcache_file_read_floats(pf, data, incr)) {
+ BKE_ptcache_file_close(pf);
+ if(pf2)
+ BKE_ptcache_file_close(pf2);
+ return 0;
+ }
+ reader->set_elem(i, reader->calldata, data);
}
- if(pf2)
- BKE_ptcache_file_close(pf2);
+ else {
+ reader->set_elem(i, reader->calldata, data);
+ data += incr;
+ }
+ }
- return PTCACHE_READ_OLD;
+ if(pf) {
+ BKE_ptcache_file_close(pf);
+ MEM_freeN(data);
}
+ if(pf2)
+ BKE_ptcache_file_close(pf2);
+
+ ret = PTCACHE_READ_OLD;
}
if(pf)
@@ -550,7 +580,20 @@ int BKE_ptcache_read_cache(PTCacheReader *reader)
if(pf2)
BKE_ptcache_file_close(pf2);
- return 0;
+ if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) {
+ /* clear invalid cache frames so that better stuff can be simulated */
+ if(pid->cache->flag & PTCACHE_OUTDATED) {
+ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra);
+ }
+ else if(pid->cache->flag & PTCACHE_FRAMES_SKIPPED) {
+ if(cfra <= pid->cache->last_exact)
+ pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
+
+ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfra,pid->cache->last_exact));
+ }
+ }
+
+ return ret;
}
/* writes cache to disk or memory */
int BKE_ptcache_write_cache(PTCacheWriter *writer)
@@ -559,57 +602,118 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer)
PTCacheFile *pf= NULL;
int elemsize = ptcache_pid_elemsize(writer->pid);
int i, incr = elemsize / sizeof(float);
+ int add = 0, overwrite = 0, ocfra;
+ float temp[14];
if(writer->totelem == 0 || writer->cfra <= 0)
return 0;
if(cache->flag & PTCACHE_DISK_CACHE) {
- pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra);
- if(!pf)
- return 0;
+ /* allways start from scratch on the first frame */
+ if(writer->cfra == cache->startframe) {
+ BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
+ cache->flag &= ~PTCACHE_REDO_NEEDED;
+ add = 1;
+ }
+ else {
+ int cfra = cache->endframe;
+ /* find last cached frame */
+ while(cfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, cfra))
+ cfra--;
+
+ /* find second last cached frame */
+ ocfra = cfra-1;
+ while(ocfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, ocfra))
+ ocfra--;
+
+ if(writer->cfra > cfra) {
+ if(ocfra >= cache->startframe && cfra - ocfra < cache->step)
+ overwrite = 1;
+ else
+ add = 1;
+ }
+ }
- for(i=0; i<writer->totelem; i++)
- BKE_ptcache_file_write_floats(pf, writer->elem_ptr(i, writer->calldata), incr);
+ if(add || overwrite) {
+ if(overwrite)
+ BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_FRAME, ocfra);
+
+ pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra);
+ if(!pf)
+ return 0;
+
+ for(i=0; i<writer->totelem; i++) {
+ writer->set_elem(i, writer->calldata, &temp);
+ BKE_ptcache_file_write_floats(pf, &temp, incr);
+ }
+ }
}
else {
- PTCacheMem *pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
+ PTCacheMem *pm;
PTCacheMem *pm2;
float *pmdata;
- pm->data = MEM_callocN(elemsize * writer->totelem, "Pointcache mem data");
- pmdata = pm->data;
+ pm2 = cache->mem_cache.first;
+
+ /* allways start from scratch on the first frame */
+ if(writer->cfra == cache->startframe) {
+ BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
+ cache->flag &= ~PTCACHE_REDO_NEEDED;
+ add = 1;
+ }
+ else {
+ pm2 = cache->mem_cache.last;
+
+ if(pm2 && writer->cfra > pm2->frame) {
+ if(pm2 && pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
+ overwrite = 1;
+ else
+ add = 1;
+ }
+ }
- for(i=0; i<writer->totelem; i++, pmdata+=incr)
- memcpy(pmdata, writer->elem_ptr(i, writer->calldata), elemsize);
+ if(overwrite) {
+ pm = cache->mem_cache.last;
+ pmdata = pm->data;
- pm->frame = writer->cfra;
- pm->totpoint = writer->totelem;
+ for(i=0; i<writer->totelem; i++, pmdata+=incr) {
+ writer->set_elem(i, writer->calldata, &temp);
+ memcpy(pmdata, &temp, elemsize);
+ }
- /* find add location */
- pm2 = cache->mem_cache.first;
- if(!pm2)
- BLI_addtail(&cache->mem_cache, pm);
- else if(pm2->frame == writer->cfra) {
- /* overwrite same frame */
- MEM_freeN(pm2->data);
- pm2->data = pm->data;
- MEM_freeN(pm);
+ pm->frame = writer->cfra;
}
- else {
- while(pm2->next && pm2->next->frame < writer->cfra)
- pm2 = pm2->next;
+ else if(add) {
+ pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem");
+ pm->data = MEM_callocN(elemsize * writer->totelem, "Pointcache mem data");
+ pmdata = pm->data;
+
+ for(i=0; i<writer->totelem; i++, pmdata+=incr) {
+ writer->set_elem(i, writer->calldata, &temp);
+ memcpy(pmdata, &temp, elemsize);
+ }
+
+ pm->frame = writer->cfra;
+ pm->totpoint = writer->totelem;
- BLI_insertlinkafter(&cache->mem_cache, pm2, pm);
+ BLI_addtail(&cache->mem_cache, pm);
}
}
- if(writer->cfra - cache->last_exact == 1)
- cache->last_exact = writer->cfra;
+ if(add || overwrite) {
+ if(writer->cfra - cache->last_exact == 1
+ || writer->cfra == cache->startframe) {
+ cache->last_exact = writer->cfra;
+ cache->flag &= ~PTCACHE_FRAMES_SKIPPED;
+ }
+ else
+ cache->flag |= PTCACHE_FRAMES_SKIPPED;
+ }
if(pf)
BKE_ptcache_file_close(pf);
- ptcache_update_info(writer->pid);
+ BKE_ptcache_update_info(writer->pid);
return 1;
}
@@ -730,7 +834,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra)
break;
}
- ptcache_update_info(pid);
+ BKE_ptcache_update_info(pid);
}
int BKE_ptcache_id_exist(PTCacheID *pid, int cfra)
@@ -762,6 +866,9 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
PointCache *cache;
float offset, time, nexttime;
+ /* TODO: this has to be sorter out once bsystem_time gets redone, */
+ /* now caches can handle interpolating etc. too - jahka */
+
/* time handling for point cache:
* - simulation time is scaled by result of bsystem_time
* - for offsetting time only time offset is taken into account, since
@@ -798,7 +905,7 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra
int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
{
PointCache *cache;
- int reset, clear, current, after;
+ int reset, clear, after;
if(!pid->cache)
return 0;
@@ -806,23 +913,17 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
cache= pid->cache;
reset= 0;
clear= 0;
- current= 0;
after= 0;
if(mode == PTCACHE_RESET_DEPSGRAPH) {
if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
- if(cache->flag & PTCACHE_AUTOCACHE) {
- reset= 1;
+ if(cache->flag & PTCACHE_QUICK_CACHE)
clear= 1;
- }
- else {
- current= 1;
- after= 1;
- cache->flag |= PTCACHE_OUTDATED;
- }
+
+ after= 1;
}
- else
- cache->flag |= PTCACHE_OUTDATED;
+
+ cache->flag |= PTCACHE_OUTDATED;
}
else if(mode == PTCACHE_RESET_BAKED) {
if(!BKE_ptcache_get_continue_physics()) {
@@ -839,17 +940,9 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
if(!(cache->flag & PTCACHE_BAKED))
clear= 1;
}
- else if(mode == PTCACHE_RESET_FREE) {
- if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) {
- if((cache->flag & PTCACHE_AUTOCACHE)==0) {
- current= 1;
- after= 1;
- }
- }
- }
if(reset) {
- cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_SIMULATION_VALID);
+ cache->flag &= ~(PTCACHE_REDO_NEEDED|PTCACHE_SIMULATION_VALID);
cache->simframe= 0;
cache->last_exact= 0;
@@ -862,12 +955,10 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode)
}
if(clear)
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
- if(after)
+ else if(after)
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, CFRA);
- if(current)
- BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, CFRA);
- return (reset || clear || current || after);
+ return (reset || clear || after);
}
int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode)
@@ -987,6 +1078,7 @@ PointCache *BKE_ptcache_add()
cache= MEM_callocN(sizeof(PointCache), "PointCache");
cache->startframe= 1;
cache->endframe= 250;
+ cache->step= 10;
return cache;
}
@@ -1019,7 +1111,39 @@ PointCache *BKE_ptcache_copy(PointCache *cache)
/* Baking */
-void BKE_ptcache_autocache_all(Scene *scene)
+static int count_quick_cache(Scene *scene, int *quick_step)
+{
+ Base *base = scene->base.first;
+ PTCacheID *pid;
+ ListBase pidlist;
+ int autocache_count= 0;
+
+ for(base = scene->base.first; base; base = base->next) {
+ if(base->object) {
+ BKE_ptcache_ids_from_object(&pidlist, base->object);
+
+ for(pid=pidlist.first; pid; pid=pid->next) {
+ if((pid->cache->flag & PTCACHE_BAKED)
+ || (pid->cache->flag & PTCACHE_QUICK_CACHE)==0)
+ continue;
+
+ if(pid->cache->flag & PTCACHE_OUTDATED || (pid->cache->flag & PTCACHE_SIMULATION_VALID)==0) {
+ if(!autocache_count)
+ *quick_step = pid->cache->step;
+ else
+ *quick_step = MIN2(*quick_step, pid->cache->step);
+
+ autocache_count++;
+ }
+ }
+
+ BLI_freelistN(&pidlist);
+ }
+ }
+
+ return autocache_count;
+}
+void BKE_ptcache_quick_cache_all(Scene *scene)
{
PTCacheBaker baker;
@@ -1032,7 +1156,7 @@ void BKE_ptcache_autocache_all(Scene *scene)
baker.render=0;
baker.scene=scene;
- if(psys_count_autocache(scene, NULL))
+ if(count_quick_cache(scene, &baker.quick_step))
BKE_ptcache_make_cache(&baker);
}
@@ -1050,11 +1174,10 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
int endframe = CFRA;
int bake = baker->bake;
int render = baker->render;
+ int step = baker->quick_step;
G.afbreek = 0;
- //printf("Caching physics...");
-
/* set caches to baking mode and figure out start frame */
if(pid) {
/* cache/bake a single object */
@@ -1063,7 +1186,7 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
if(pid->type==PTCACHE_TYPE_PARTICLES)
psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
- if(bake || cache->flag & PTCACHE_OUTDATED)
+ if(bake || cache->flag & PTCACHE_REDO_NEEDED)
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
startframe = MAX2(cache->last_exact, cache->startframe);
@@ -1072,8 +1195,9 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
endframe = cache->endframe;
cache->flag |= PTCACHE_BAKING;
}
- else
+ else {
endframe = MIN2(endframe, cache->endframe);
+ }
cache->flag &= ~PTCACHE_BAKED;
}
@@ -1088,31 +1212,30 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
if(pid->type==PTCACHE_TYPE_PARTICLES)
psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
- if(cache->flag & PTCACHE_OUTDATED)
+ if((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0)
+ && ((cache->flag & PTCACHE_QUICK_CACHE)==0 || render || bake))
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
startframe = MIN2(startframe, cache->startframe);
- if(bake) {
- endframe = MAX2(endframe, cache->endframe);
+ if(bake || render) {
cache->flag |= PTCACHE_BAKING;
+
+ if(bake)
+ endframe = MAX2(endframe, cache->endframe);
}
- else if(render)
- cache->flag |= PTCACHE_BAKING;
cache->flag &= ~PTCACHE_BAKED;
}
}
-
BLI_freelistN(&pidlist);
}
CFRA= startframe;
scene->r.framelen = 1.0;
- scene_update_for_newframe(scene, scene->lay);
- for(; CFRA <= endframe; CFRA++) {
+ for(; CFRA <= endframe; CFRA+=step) {
float prog;
if(bake)
@@ -1133,7 +1256,8 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
/* clear baking flag */
if(pid) {
- cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
+ cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
+ cache->flag |= PTCACHE_SIMULATION_VALID;
if(bake)
cache->flag |= PTCACHE_BAKED;
}
@@ -1141,17 +1265,26 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
BKE_ptcache_ids_from_object(&pidlist, base->object);
for(pid=pidlist.first; pid; pid=pid->next) {
- cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
+ cache = pid->cache;
+
+ if(step > 1)
+ cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED);
+ else
+ cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED);
+
+ cache->flag |= PTCACHE_SIMULATION_VALID;
+
if(bake)
cache->flag |= PTCACHE_BAKED;
}
+ BLI_freelistN(&pidlist);
}
-
- //printf("done!\n");
scene->r.framelen = frameleno;
CFRA = cfrao;
scene_update_for_newframe(scene, scene->lay);
+
+ /* TODO: call redraw all windows somehow */
}
void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
@@ -1161,6 +1294,7 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
int totelem=0;
int float_count=0;
int tot;
+ int last_exact = cache->last_exact;
if (!G.relbase_valid){
cache->flag &= ~PTCACHE_DISK_CACHE;
@@ -1230,6 +1364,7 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
}
pm->frame = cfra;
+ pm->totpoint = totelem;
BLI_addtail(&pid->cache->mem_cache, pm);
@@ -1241,4 +1376,8 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0);
cache->flag &= ~PTCACHE_DISK_CACHE;
}
+
+ cache->last_exact = last_exact;
+
+ BKE_ptcache_update_info(pid);
}