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.
This commit is contained in:
2009-06-27 15:28:58 +00:00
parent 9becf3c310
commit 912c2f440b
19 changed files with 760 additions and 330 deletions

View File

@@ -130,11 +130,7 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
cache = psys.point_cache
row = layout.row()
row.itemR(cache, "name", text="")
if cache.outdated:
row.itemL(text="Cache is outdated.")
else:
row.itemL(text="")
row.itemR(cache, "name")
row = layout.row()
@@ -142,18 +138,29 @@ class PARTICLE_PT_cache(ParticleButtonsPanel):
row.itemO("PTCACHE_OT_free_bake_particle_system", text="Free Bake")
else:
row.item_booleanO("PTCACHE_OT_cache_particle_system", "bake", True, text="Bake")
subrow = row.row()
subrow.enabled = (cache.frames_skipped or cache.outdated) and particle_panel_enabled(psys)
subrow.itemO("PTCACHE_OT_cache_particle_system", text="Calculate to Current Frame")
row = layout.row()
row.enabled = particle_panel_enabled(psys)
row.itemO("PTCACHE_OT_bake_from_particles_cache", text="Current Cache to Bake")
if cache.autocache == 0:
row.itemO("PTCACHE_OT_cache_particle_system", text="Cache to Current Frame")
row.itemR(cache, "step");
row = layout.row()
row.enabled = particle_panel_enabled(psys)
#row.itemR(cache, "autocache")
row.itemR(cache, "quick_cache")
row.itemR(cache, "disk_cache")
row.itemL(text=cache.info)
layout.itemL(text=cache.info)
layout.itemS()
row = layout.row()
row.item_booleanO("PTCACHE_OT_bake_all", "bake", True, text="Bake All Dynamics")
row.itemO("PTCACHE_OT_free_bake_all", text="Free All Bakes")
layout.itemO("PTCACHE_OT_bake_all", text="Update All Dynamics to current frame")
# for particles these are figured out automatically
#row.itemR(cache, "start_frame")

View File

@@ -43,7 +43,54 @@ class Physic_PT_cloth(PhysicButtonsPanel):
col.itemR(cloth, "goal_spring", text="Stiffness")
col.itemR(cloth, "goal_friction", text="Friction")
"""
class PHYSICS_PT_cloth_cache(PhysicButtonsPanel):
__idname__= "PHYSICS_PT_cloth_cache"
__label__ = "Cache"
__default_closed__ = True
def draw(self, context):
layout = self.layout
cache = context.cloth.point_cache
row = layout.row()
row.itemR(cache, "name")
row = layout.row()
row.itemR(cache, "start_frame")
row.itemR(cache, "end_frame")
row = layout.row()
if cache.baked == True:
row.itemO("PTCACHE_OT_free_bake_cloth", text="Free Bake")
else:
row.item_booleanO("PTCACHE_OT_cache_cloth", "bake", True, text="Bake")
subrow = row.row()
subrow.enabled = cache.frames_skipped or cache.outdated
subrow.itemO("PTCACHE_OT_cache_cloth", text="Calculate to Current Frame")
row = layout.row()
#row.enabled = particle_panel_enabled(psys)
row.itemO("PTCACHE_OT_bake_from_cloth_cache", text="Current Cache to Bake")
row.itemR(cache, "step");
row = layout.row()
#row.enabled = particle_panel_enabled(psys)
row.itemR(cache, "quick_cache")
row.itemR(cache, "disk_cache")
layout.itemL(text=cache.info)
layout.itemS()
row = layout.row()
row.itemO("PTCACHE_OT_bake_all", "bake", True, text="Bake All Dynamics")
row.itemO("PTCACHE_OT_free_bake_all", text="Free All Bakes")
layout.itemO("PTCACHE_OT_bake_all", text="Update All Dynamics to current frame")
class Physic_PT_cloth_collision(PhysicButtonsPanel):
__idname__ = "Physic_PT_clothcollision"
__label__ = "Cloth Collision"
@@ -102,5 +149,6 @@ class Physic_PT_cloth_stiffness(PhysicButtonsPanel):
sub.itemR(cloth, "bending_stiffness_max", text="Max")
bpy.types.register(Physic_PT_cloth)
bpy.types.register(PHYSICS_PT_cloth_cache)
bpy.types.register(Physic_PT_cloth_collision)
bpy.types.register(Physic_PT_cloth_stiffness)

View File

@@ -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 );

View File

@@ -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);

View File

@@ -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);

View File

@@ -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,43 +341,88 @@ void bvhselftree_update_from_cloth(ClothModifierData *clmd, int moving)
}
int modifiers_indexInObject(Object *ob, ModifierData *md_seek);
int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr)
static void cloth_write_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;
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)
{
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);
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;
if(cfra1 == cfra2) {
cloth_read_state(index, cloth, data1);
return;
}
else
ret = 0;
return ret;
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);
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);
}
int cloth_read_cache(Scene *scene, Object *ob, ClothModifierData *clmd, float cfra, int *old_framenr)
{
PTCacheReader reader;
PTCacheID pid;
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;
@@ -389,30 +436,6 @@ void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr)
BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr);
}
void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr)
{
Cloth *cloth = clmd->clothObject;
PTCacheID pid;
PTCacheFile *pf;
unsigned int a;
if(!cloth)
return;
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_WRITE, framenr);
if(!pf)
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);
}
static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr)
{
PointCache *cache;
@@ -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;
}

View File

@@ -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
{

View File

@@ -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){

View File

@@ -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;

View File

@@ -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;
}
if(ret)
;
/* 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;
}
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;
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, (float)cfra1, (float)cfra2, data1, data2);
}
else {
data1 = MEM_callocN(elemsize, "pointcache read data1");
data2 = MEM_callocN(elemsize, "pointcache read data2");
reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, (float)cfra1, (float)cfra2, data1, data2);
data1 += incr;
data2 += incr;
}
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);
}
else {
reader->interpolate_elem(i, reader->calldata, frs_sec, cfra, cfra1, cfra2, data1, data2);
data1 += incr;
data2 += incr;
}
}
if(pf) {
BKE_ptcache_file_close(pf);
BKE_ptcache_file_close(pf2);
MEM_freeN(data1);
MEM_freeN(data2);
}
return PTCACHE_READ_INTERPOLATED;
}
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");
if(pf) {
BKE_ptcache_file_close(pf);
BKE_ptcache_file_close(pf2);
MEM_freeN(data1);
MEM_freeN(data2);
}
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;
}
}
ret = PTCACHE_READ_INTERPOLATED;
}
else if(pf || pm) {
/* use last valid cache frame */
float *data;
if(pf) {
/* don't read cache if allready simulated past cached frame */
if(cfra1 && cfra1 <= pid->cache->simframe) {
if(pf)
BKE_ptcache_file_close(pf);
MEM_freeN(data);
}
if(pf2)
BKE_ptcache_file_close(pf2);
return PTCACHE_READ_OLD;
return 0;
}
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(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--;
for(i=0; i<writer->totelem; i++)
BKE_ptcache_file_write_floats(pf, writer->elem_ptr(i, writer->calldata), incr);
/* 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;
}
}
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;
for(i=0; i<writer->totelem; i++, pmdata+=incr)
memcpy(pmdata, writer->elem_ptr(i, writer->calldata), elemsize);
pm->frame = writer->cfra;
pm->totpoint = writer->totelem;
/* 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);
/* 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 {
while(pm2->next && pm2->next->frame < writer->cfra)
pm2 = pm2->next;
pm2 = cache->mem_cache.last;
BLI_insertlinkafter(&cache->mem_cache, pm2, pm);
if(pm2 && writer->cfra > pm2->frame) {
if(pm2 && pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
overwrite = 1;
else
add = 1;
}
}
if(overwrite) {
pm = cache->mem_cache.last;
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;
}
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_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);
}

View File

@@ -9013,6 +9013,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
Tex *tx;
ParticleSettings *part;
Object *ob;
PTCacheID *pid;
ListBase pidlist;
for(screen= main->screen.first; screen; screen= screen->id.next) {
do_versions_windowmanager_2_50(screen);
@@ -9073,14 +9075,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
/* set old pointcaches to have disk cache flag */
for(ob = main->object.first; ob; ob= ob->id.next) {
ParticleSystem *psys = ob->particlesystem.first;
for(; psys; psys=psys->next) {
if(psys->pointcache)
psys->pointcache->flag |= PTCACHE_DISK_CACHE;
}
BKE_ptcache_ids_from_object(&pidlist, ob);
/* TODO: softbody & cloth caches */
for(pid=pidlist.first; pid; pid=pid->next)
pid->cache->flag |= PTCACHE_DISK_CACHE;
BLI_freelistN(&pidlist);
}
}

View File

@@ -552,6 +552,7 @@ static void write_userdef(WriteData *wd)
/* TODO: replace *cache with *cachelist once it's coded */
#define PTCACHE_WRITE_PSYS 0
#define PTCACHE_WRITE_CLOTH 1
static void write_pointcaches(WriteData *wd, PointCache *cache, int type)
{
writestruct(wd, DATA, "PointCache", 1, cache);
@@ -563,6 +564,8 @@ static void write_pointcaches(WriteData *wd, PointCache *cache, int type)
writestruct(wd, DATA, "PTCacheMem", 1, pm);
if(type==PTCACHE_WRITE_PSYS)
writestruct(wd, DATA, "ParticleKey", pm->totpoint, pm->data);
else if(type==PTCACHE_WRITE_CLOTH)
writedata(wd, DATA, 9 * sizeof(float) * pm->totpoint, pm->data);
}
}
}
@@ -1025,7 +1028,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase, int write_undo)
writestruct(wd, DATA, "ClothSimSettings", 1, clmd->sim_parms);
writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms);
writestruct(wd, DATA, "PointCache", 1, clmd->point_cache);
write_pointcaches(wd, clmd->point_cache, PTCACHE_WRITE_CLOTH);
}
else if(md->type==eModifierType_Fluidsim) {
FluidsimModifierData *fluidmd = (FluidsimModifierData*) md;

View File

@@ -31,6 +31,7 @@
#include "DNA_scene_types.h"
#include "DNA_object_force.h"
#include "DNA_modifier_types.h"
#include "BKE_context.h"
#include "BKE_particle.h"
@@ -39,7 +40,7 @@
#include "BKE_utildefines.h"
#include "BKE_pointcache.h"
#include "BKE_global.h"
#include "BKE_multires.h"
#include "BKE_modifier.h"
#include "BLI_blenlib.h"
@@ -81,6 +82,7 @@ static int ptcache_bake_all_exec(bContext *C, wmOperator *op)
baker.pid = NULL;
baker.bake = RNA_boolean_get(op->ptr, "bake");
baker.render = 0;
baker.quick_step = 1;
baker.break_test = cache_break_test;
baker.break_data = NULL;
baker.progressbar = (void (*)(void *, int))WM_timecursor;
@@ -104,12 +106,11 @@ static int ptcache_free_bake_all_exec(bContext *C, wmOperator *op)
for(pid=pidlist.first; pid; pid=pid->next) {
pid->cache->flag &= ~PTCACHE_BAKED;
BKE_ptcache_id_reset(scene, pid, PTCACHE_RESET_OUTDATED);
}
BLI_freelistN(&pidlist);
}
BLI_freelistN(&pidlist);
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
return OPERATOR_FINISHED;
@@ -127,6 +128,8 @@ void PTCACHE_OT_bake_all(wmOperatorType *ot)
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
}
void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
{
@@ -142,6 +145,112 @@ void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/**************************** cloth **********************************/
static int ptcache_bake_cloth_poll(bContext *C)
{
Scene *scene= CTX_data_scene(C);
Object *ob= CTX_data_active_object(C);
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
if(!scene || !ob || ob->id.lib || !clmd)
return 0;
return 1;
}
static int ptcache_bake_cloth_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *ob= CTX_data_active_object(C);
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
PTCacheID pid;
PTCacheBaker baker;
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
baker.scene = scene;
baker.pid = &pid;
baker.bake = RNA_boolean_get(op->ptr, "bake");
baker.render = 0;
baker.quick_step = 1;
baker.break_test = cache_break_test;
baker.break_data = NULL;
baker.progressbar = WM_timecursor;
baker.progresscontext = CTX_wm_window(C);
BKE_ptcache_make_cache(&baker);
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
return OPERATOR_FINISHED;
}
static int ptcache_free_bake_cloth_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *ob= CTX_data_active_object(C);
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
PTCacheID pid;
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
pid.cache->flag &= ~PTCACHE_BAKED;
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
return OPERATOR_FINISHED;
}
void PTCACHE_OT_cache_cloth(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Bake Cloth";
ot->idname= "PTCACHE_OT_cache_cloth";
/* api callbacks */
ot->exec= ptcache_bake_cloth_exec;
ot->poll= ptcache_bake_cloth_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
}
void PTCACHE_OT_free_bake_cloth(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Free Cloth Bake";
ot->idname= "PTCACHE_OT_free_bake_cloth";
/* api callbacks */
ot->exec= ptcache_free_bake_cloth_exec;
ot->poll= ptcache_bake_cloth_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
static int ptcache_bake_from_cloth_cache_exec(bContext *C, wmOperator *op)
{
Object *ob= CTX_data_active_object(C);
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
PTCacheID pid;
BKE_ptcache_id_from_cloth(&pid, ob, clmd);
pid.cache->flag |= PTCACHE_BAKED;
return OPERATOR_FINISHED;
}
void PTCACHE_OT_bake_from_cloth_cache(wmOperatorType *ot)
{
/* identifiers */
ot->name= "Bake From Cache";
ot->idname= "PTCACHE_OT_bake_from_cloth_cache";
/* api callbacks */
ot->exec= ptcache_bake_from_cloth_cache_exec;
ot->poll= ptcache_bake_cloth_poll;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
/**************************** particles **********************************/
static int ptcache_bake_particle_system_poll(bContext *C)
{
@@ -168,6 +277,7 @@ static int ptcache_bake_particle_system_exec(bContext *C, wmOperator *op)
baker.pid = &pid;
baker.bake = RNA_boolean_get(op->ptr, "bake");
baker.render = 0;
baker.quick_step = 1;
baker.break_test = cache_break_test;
baker.break_data = NULL;
baker.progressbar = (void (*)(void *, int))WM_timecursor;
@@ -188,7 +298,6 @@ static int ptcache_free_bake_particle_system_exec(bContext *C, wmOperator *op)
BKE_ptcache_id_from_particles(&pid, ob, psys);
psys->pointcache->flag &= ~PTCACHE_BAKED;
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene);
@@ -256,6 +365,9 @@ void ED_operatortypes_pointcache(void)
WM_operatortype_append(PTCACHE_OT_cache_particle_system);
WM_operatortype_append(PTCACHE_OT_free_bake_particle_system);
WM_operatortype_append(PTCACHE_OT_bake_from_particles_cache);
WM_operatortype_append(PTCACHE_OT_cache_cloth);
WM_operatortype_append(PTCACHE_OT_free_bake_cloth);
WM_operatortype_append(PTCACHE_OT_bake_from_cloth_cache);
}
//void ED_keymap_pointcache(wmWindowManager *wm)

View File

@@ -4674,6 +4674,12 @@ void special_aftertrans_update(TransInfo *t)
/* pointcache refresh */
if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH))
ob->recalc |= OB_RECALC_DATA;
/* Needed for proper updating of "quick cached" dynamics. */
/* Creates troubles for moving animated objects without */
/* autokey though, probably needed is an anim sys override? */
/* Please remove if some other solution is found. -jahka */
DAG_object_flush_update(scene, ob, OB_RECALC_OB);
/* Set autokey if necessary */
if (!cancelled)

View File

@@ -82,7 +82,8 @@ typedef struct PTCacheMem {
} PTCacheMem;
typedef struct PointCache {
int flag, rt; /* generic flag */
int flag; /* generic flag */
int step; /* frames between cached frames */
int simframe; /* current frame of simulation (only if SIMULATION_VALID) */
int startframe; /* simulation start frame */
int endframe; /* simulation end frame */
@@ -263,7 +264,11 @@ typedef struct SoftBody {
#define PTCACHE_BAKE_EDIT 16
#define PTCACHE_BAKE_EDIT_ACTIVE 32
#define PTCACHE_DISK_CACHE 64
#define PTCACHE_AUTOCACHE 128
#define PTCACHE_QUICK_CACHE 128
#define PTCACHE_FRAMES_SKIPPED 256
/* PTCACHE_OUTDATED + PTCACHE_FRAMES_SKIPPED */
#define PTCACHE_REDO_NEEDED 258
/* ob->softflag */
#define OB_SB_ENABLE 1

View File

@@ -34,9 +34,24 @@
#include "BKE_modifier.h"
#include "DNA_cloth_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "WM_types.h"
#ifdef RNA_RUNTIME
#include "BKE_context.h"
#include "BKE_depsgraph.h"
static void rna_cloth_update(bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
Object *ob = ptr->id.data;
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
}
static void rna_ClothSettings_max_bend_set(struct PointerRNA *ptr, float value)
{
ClothSimSettings *settings = (ClothSimSettings*)ptr->data;
@@ -165,42 +180,50 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "mingoal");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Goal Minimum", "Goal minimum, vertex group weights are scaled to match this range.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "goal_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "maxgoal");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Goal Maximum", "Goal maximum, vertex group weights are scaled to match this range.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "goal_default", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "defgoal");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Goal Default", "Default Goal (vertex target position) value, when no Vertex Group used.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "goal_spring", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "goalspring");
RNA_def_property_range(prop, 0.0f, 0.999f);
RNA_def_property_ui_text(prop, "Goal Stiffness", "Goal (vertex target position) spring stiffness.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "goal_friction", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "goalfrict");
RNA_def_property_range(prop, 0.0f, 50.0f);
RNA_def_property_ui_text(prop, "Goal Damping", "Goal (vertex target position) friction.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
/* mass */
prop= RNA_def_property(srna, "mass", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 10.0f);
RNA_def_property_ui_text(prop, "Mass", "Mass of cloth material.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "mass_vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_ClothSettings_mass_vgroup_get", "rna_ClothSettings_mass_vgroup_length", "rna_ClothSettings_mass_vgroup_set");
RNA_def_property_ui_text(prop, "Mass Vertex Group", "Vertex group for fine control over mass distribution.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_VECTOR);
RNA_def_property_array(prop, 3);
RNA_def_property_range(prop, -100.0, 100.0);
RNA_def_property_float_funcs(prop, "rna_ClothSettings_gravity_get", "rna_ClothSettings_gravity_set", NULL);
RNA_def_property_ui_text(prop, "Gravity", "Gravity or external force vector.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
/* various */
@@ -208,61 +231,73 @@ static void rna_def_cloth_sim_settings(BlenderRNA *brna)
RNA_def_property_float_sdna(prop, NULL, "Cvi");
RNA_def_property_range(prop, 0.0f, 10.0f);
RNA_def_property_ui_text(prop, "Air Damping", "Air has normally some thickness which slows falling things down.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "pin_cloth", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_GOAL);
RNA_def_property_ui_text(prop, "Pin Cloth", "Define forces for vertices to stick to animated position.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "pin_stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "goalspring");
RNA_def_property_range(prop, 0.0f, 50.0);
RNA_def_property_ui_text(prop, "Pin Stiffness", "Pin (vertex target position) spring stiffness.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "quality", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "stepsPerFrame");
RNA_def_property_range(prop, 4, 80);
RNA_def_property_ui_text(prop, "Quality", "Quality of the simulation in steps per frame (higher is better quality but slower).");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
/* springs */
prop= RNA_def_property(srna, "stiffness_scaling", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_SIMSETTINGS_FLAG_SCALING);
RNA_def_property_ui_text(prop, "Stiffness Scaling", "If enabled, stiffness can be scaled along a weight painted vertex group.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "spring_damping", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "Cdis");
RNA_def_property_range(prop, 0.0f, 50.0f);
RNA_def_property_ui_text(prop, "Spring Damping", "Damping of cloth velocity (higher = more smooth, less jiggling)");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "structural_stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "structural");
RNA_def_property_range(prop, 1.0f, 10000.0f);
RNA_def_property_ui_text(prop, "Structural Stiffness", "Overall stiffness of structure.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "structural_stiffness_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_struct");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_struct_set", NULL);
RNA_def_property_ui_text(prop, "Structural Stiffness Maximum", "Maximum structural stiffness value.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "structural_stiffness_vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_ClothSettings_struct_vgroup_get", "rna_ClothSettings_struct_vgroup_length", "rna_ClothSettings_struct_vgroup_set");
RNA_def_property_ui_text(prop, "Structural Stiffness Vertex Group", "Vertex group for fine control over structural stiffness.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "bending_stiffness", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "bending");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_ui_text(prop, "Bending Stiffness", "Wrinkle coefficient (higher = less smaller but more big wrinkles).");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "bending_stiffness_max", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_bend");
RNA_def_property_range(prop, 0.0f, 10000.0f);
RNA_def_property_float_funcs(prop, NULL, "rna_ClothSettings_max_bend_set", NULL);
RNA_def_property_ui_text(prop, "Bending Stiffness Maximum", "Maximum bending stiffness value.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "bending_vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop, "rna_ClothSettings_bend_vgroup_get", "rna_ClothSettings_bend_vgroup_length", "rna_ClothSettings_bend_vgroup_set");
RNA_def_property_ui_text(prop, "Bending Stiffness Vertex Group", "Vertex group for fine control over bending stiffness.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
/* unused */
@@ -323,40 +358,48 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
prop= RNA_def_property(srna, "enable_collision", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_COLLSETTINGS_FLAG_ENABLED);
RNA_def_property_ui_text(prop, "Enable Collision", "Enable collisions with other objects.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "min_distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "epsilon");
RNA_def_property_range(prop, 0.001f, 1.0f);
RNA_def_property_ui_text(prop, "Minimum Distance", "Minimum distance between collision objects before collision response takes in, can be changed for each frame.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "friction", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 80.0f);
RNA_def_property_ui_text(prop, "Friction", "Friction force if a collision happened (0=movement not changed, 100=no movement left)");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "collision_quality", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "loop_count");
RNA_def_property_range(prop, 1, 20);
RNA_def_property_ui_text(prop, "Collision Quality", "How many collision iterations should be done. (higher is better quality but slower)");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
/* self collision */
prop= RNA_def_property(srna, "enable_self_collision", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flags", CLOTH_COLLSETTINGS_FLAG_SELF);
RNA_def_property_ui_text(prop, "Enable Self Collision", "Enable self collisions.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "self_min_distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "selfepsilon");
RNA_def_property_range(prop, 0.5f, 1.0f);
RNA_def_property_ui_text(prop, "Self Minimum Distance", "0.5 means no distance at all, 1.0 is maximum distance");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "self_friction", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 80.0f);
RNA_def_property_ui_text(prop, "Self Friction", "Friction/damping with self contact.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
prop= RNA_def_property(srna, "self_collision_quality", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "self_loop_count");
RNA_def_property_range(prop, 1, 10);
RNA_def_property_ui_text(prop, "Self Collision Quality", "How many self collision iterations should be done. (higher is better quality but slower), can be changed for each frame.");
RNA_def_property_update(prop, NC_OBJECT|ND_GEOM_DATA, "rna_cloth_update");
}
void RNA_def_cloth(BlenderRNA *brna)

View File

@@ -31,6 +31,7 @@
#include "DNA_object_types.h"
#include "DNA_object_force.h"
#include "DNA_scene_types.h"
#include "WM_types.h"
@@ -40,9 +41,38 @@
#include "BKE_context.h"
#include "BKE_pointcache.h"
#include "BKE_depsgraph.h"
#include "BLI_blenlib.h"
static void rna_Cache_change(bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
PointCache *cache = (PointCache*)ptr->data;
PTCacheID *pid = NULL;
ListBase pidlist;
if(!ob)
return;
cache->flag |= PTCACHE_OUTDATED;
BKE_ptcache_ids_from_object(&pidlist, ob);
DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
for(pid=pidlist.first; pid; pid=pid->next) {
if(pid->cache==cache)
break;
}
if(pid)
BKE_ptcache_update_info(pid);
BLI_freelistN(&pidlist);
}
static void rna_Cache_toggle_disk_cache(bContext *C, PointerRNA *ptr)
{
Object *ob = CTX_data_active_object(C);
@@ -240,6 +270,12 @@ static void rna_def_pointcache(BlenderRNA *brna)
RNA_def_property_range(prop, 1, 300000);
RNA_def_property_ui_text(prop, "End", "Frame on which the simulation stops.");
prop= RNA_def_property(srna, "step", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "step");
RNA_def_property_range(prop, 1, 20);
RNA_def_property_ui_text(prop, "Cache Step", "Number of frames between cached frames.");
RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
/* flags */
prop= RNA_def_property(srna, "baked", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_BAKED);
@@ -257,21 +293,24 @@ static void rna_def_pointcache(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Cache is outdated", "");
prop= RNA_def_property(srna, "frames_skipped", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_FRAMES_SKIPPED);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "name");
RNA_def_property_ui_text(prop, "Name", "Cache name");
RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change");
prop= RNA_def_property(srna, "autocache", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_AUTOCACHE);
RNA_def_property_ui_text(prop, "Auto Cache", "Cache changes automatically");
//RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_toggle_autocache");
prop= RNA_def_property(srna, "quick_cache", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_QUICK_CACHE);
RNA_def_property_ui_text(prop, "Quick Cache", "Update simulation with cache steps");
RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change");
prop= RNA_def_property(srna, "info", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "info");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Cache Info", "Info on current cache status.");
}
static void rna_def_collision(BlenderRNA *brna)

View File

@@ -2421,6 +2421,7 @@ static void update_physics_cache(Render *re, Scene *scene)
baker.pid = NULL;
baker.bake = 0;
baker.render = 1;
baker.quick_step = 1;
baker.break_test = re->test_break;
baker.break_data = re->tbh;
baker.progressbar = NULL;

View File

@@ -49,6 +49,7 @@
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_utildefines.h"
#include "BKE_pointcache.h"
#include "ED_fileselect.h"
#include "ED_screen.h"
@@ -234,6 +235,8 @@ void wm_event_do_notifiers(bContext *C)
for(base= scene->base.first; base; base= base->next) {
object_handle_update(scene, base->object);
}
BKE_ptcache_quick_cache_all(scene);
}
}
CTX_wm_window_set(C, NULL);