diff options
Diffstat (limited to 'source')
42 files changed, 2462 insertions, 1750 deletions
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 418102aa973..f1a439e2e04 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -147,16 +147,18 @@ ClothSpring; /* These are the bits used in SimSettings.flags. */ typedef enum { - CLOTH_SIMSETTINGS_FLAG_RESET = ( 1 << 1 ), // The CM object requires a reinitializaiton. + //CLOTH_SIMSETTINGS_FLAG_RESET = ( 1 << 1 ), // The CM object requires a reinitializaiton. CLOTH_SIMSETTINGS_FLAG_COLLOBJ = ( 1 << 2 ),// object is only collision object, no cloth simulation is done CLOTH_SIMSETTINGS_FLAG_GOAL = ( 1 << 3 ), // we have goals enabled CLOTH_SIMSETTINGS_FLAG_TEARING = ( 1 << 4 ),// true if tearing is enabled - CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT = ( 1 << 5 ), // true if tearing is enabled - CLOTH_SIMSETTINGS_FLAG_EDITMODE = ( 1 << 6 ), // are we in editmode? -several things disabled - CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE = ( 1 << 7 ), /* force cache freeing */ + //CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT = ( 1 << 5 ), // true if tearing is enabled + //CLOTH_SIMSETTINGS_FLAG_EDITMODE = ( 1 << 6 ), // are we in editmode? -several things disabled + //CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE = ( 1 << 7 ), /* force cache freeing */ CLOTH_SIMSETTINGS_FLAG_SCALING = ( 1 << 8 ), /* is advanced scaling active? */ - CLOTH_SIMSETTINGS_FLAG_LOADED = ( 1 << 9 ), /* did we just got load? */ - CLOTH_SIMSETTINGS_FLAG_AUTOPROTECT = ( 1 << 10 ), /* is autoprotect enabled? */ + //CLOTH_SIMSETTINGS_FLAG_LOADED = ( 1 << 9 ), /* did we just got load? */ + //CLOTH_SIMSETTINGS_FLAG_AUTOPROTECT = ( 1 << 10 ), /* is autoprotect enabled? */ + //CLOTH_SIMSETTINGS_FLAG_CCACHE_OUTDATED = (1 << 11), /* while protected, did cache get outdated? */ + CLOTH_SIMSETTINGS_FLAG_CCACHE_EDIT = (1 << 12) /* edit cache in editmode */ } CLOTH_SIMSETTINGS_FLAGS; /* COLLISION FLAGS */ diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h index 294f61e54bd..36f26d42cee 100644 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ b/source/blender/blenkernel/BKE_depsgraph.h @@ -104,7 +104,7 @@ void DAG_scene_update_flags(struct Scene *sce, unsigned int lay); void DAG_object_update_flags(struct Scene *sce, struct Object *ob, unsigned int lay); /* flushes all recalc flags in objects down the dependency tree */ -void DAG_scene_flush_update(struct Scene *sce, unsigned int lay); +void DAG_scene_flush_update(struct Scene *sce, unsigned int lay, int time); /* flushes all recalc flags for this object down the dependency tree */ void DAG_object_flush_update(struct Scene *sce, struct Object *ob, short flag); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index f134c4597c1..45be121661b 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -41,6 +41,7 @@ struct ParticleSystemModifierData; struct ParticleSystem; struct ParticleKey; +struct ParticleSettings; struct HairKey; struct Main; @@ -222,9 +223,6 @@ void psys_render_restore(struct Object *ob, struct ParticleSystem *psys); int psys_render_simplify_distribution(struct ParticleThreadContext *ctx, int tot); int psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params); -void clear_particles_from_cache(struct Object *ob, struct ParticleSystem *psys, int cfra); -//void psys_remove_from_particle_list(struct Object *ob, short nbr, struct ParticleSystem *psys); - void psys_interpolate_uvs(struct MTFace *tface, int quad, float *uv, float *uvco); void psys_interpolate_mcol(struct MCol *mcol, int quad, float *uv, struct MCol *mc); @@ -237,6 +235,10 @@ struct ParticleSettings *psys_new_settings(char *name, struct Main *main); struct ParticleSettings *psys_copy_settings(struct ParticleSettings *part); void psys_flush_settings(struct ParticleSettings *part, int event, int hair_recalc); +struct LinkNode *psys_using_settings(struct ParticleSettings *part, int flush_update); +void psys_changed_type(struct ParticleSystem *psys); +void psys_reset(struct ParticleSystem *psys, int mode); + void psys_find_parents(struct Object *ob, struct ParticleSystemModifierData *psmd, struct ParticleSystem *psys); void psys_cache_paths(struct Object *ob, struct ParticleSystem *psys, float cfra, int editupdate); @@ -251,7 +253,7 @@ int psys_get_particle_state(struct Object *ob, struct ParticleSystem *psys, int void psys_get_dupli_texture(struct Object *ob, struct ParticleSettings *part, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, float *uv, float *orco); void psys_get_dupli_path_transform(struct Object *ob, struct ParticleSystem *psys, struct ParticleSystemModifierData *psmd, struct ParticleData *pa, struct ChildParticle *cpa, struct ParticleCacheKey *cache, float mat[][4], float *scale); -ParticleThread *psys_threads_create(struct Object *ob, struct ParticleSystem *psys, int totthread); +ParticleThread *psys_threads_create(struct Object *ob, struct ParticleSystem *psys); int psys_threads_init_distribution(ParticleThread *threads, struct DerivedMesh *dm, int from); int psys_threads_init_path(ParticleThread *threads, float cfra, int editupdate); void psys_threads_free(ParticleThread *threads); @@ -298,6 +300,11 @@ void do_effectors(int pa_no, struct ParticleData *pa, struct ParticleKey *state, void psys_calc_dmcache(struct Object *ob, struct DerivedMesh *dm, struct ParticleSystem *psys); int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int index, float *fw, struct LinkNode *node); +/* psys_reset */ +#define PSYS_RESET_ALL 1 +#define PSYS_RESET_DEPSGRAPH 2 +#define PSYS_RESET_CHILDREN 3 + /* ParticleEffectorCache->type */ #define PSYS_EC_EFFECTOR 1 #define PSYS_EC_DEFLECT 2 diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 12068f7dedf..5bc467465a8 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -31,24 +31,84 @@ #include "DNA_ID.h" -/* options for clearing pointcache - used for BKE_ptcache_id_clear - Before and after are non inclusive (they wont remove the cfra) */ +/* Point cache clearing option, for BKE_ptcache_id_clear, before + * and after are non inclusive (they wont remove the cfra) */ #define PTCACHE_CLEAR_ALL 0 #define PTCACHE_CLEAR_FRAME 1 #define PTCACHE_CLEAR_BEFORE 2 #define PTCACHE_CLEAR_AFTER 3 +/* Point cache reset options */ +#define PTCACHE_RESET_DEPSGRAPH 0 +#define PTCACHE_RESET_BAKED 1 +#define PTCACHE_RESET_OUTDATED 2 + /* Add the blendfile name after blendcache_ */ #define PTCACHE_EXT ".bphys" #define PTCACHE_PATH "blendcache_" +/* File open options, for BKE_ptcache_file_open */ +#define PTCACHE_FILE_READ 0 +#define PTCACHE_FILE_WRITE 1 + +/* PTCacheID types */ +#define PTCACHE_TYPE_SOFTBODY 0 +#define PTCACHE_TYPE_PARTICLES 1 +#define PTCACHE_TYPE_CLOTH 2 + +/* Structs */ +struct Object; +struct SoftBody; +struct ParticleSystem; +struct ClothModifierData; +struct PointCache; +struct ListBase; + +typedef struct PTCacheFile { + FILE *fp; +} PTCacheFile; + +typedef struct PTCacheID { + struct PTCacheID *next, *prev; + + struct Object *ob; + void *data; + int type; + int stack_index; + + struct PointCache *cache; +} PTCacheID; + +/* Creating ID's */ +void BKE_ptcache_id_from_softbody(PTCacheID *pid, struct Object *ob, struct SoftBody *sb); +void BKE_ptcache_id_from_particles(PTCacheID *pid, struct Object *ob, struct ParticleSystem *psys); +void BKE_ptcache_id_from_cloth(PTCacheID *pid, struct Object *ob, struct ClothModifierData *clmd); + +void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob); + /* Global funcs */ void BKE_ptcache_remove(void); -/* Object spesific funcs */ -int BKE_ptcache_id_filename(struct ID *id, char *filename, int cfra, int stack_index, short do_path, short do_ext); -FILE * BKE_ptcache_id_fopen(struct ID *id, char mode, int cfra, int stack_index); -void BKE_ptcache_id_clear(struct ID *id, char mode, int cfra, int stack_index); -int BKE_ptcache_id_exist(struct ID *id, int cfra, int stack_index); +/* ID specific functions */ +void BKE_ptcache_id_clear(PTCacheID *id, int mode, int cfra); +int BKE_ptcache_id_exist(PTCacheID *id, int cfra); +int BKE_ptcache_id_reset(PTCacheID *id, int mode); +void BKE_ptcache_id_time(PTCacheID *pid, float cfra, int *startframe, int *endframe, float *timescale); +int BKE_ptcache_object_reset(struct Object *ob, int mode); + +/* File reading/writing */ +PTCacheFile *BKE_ptcache_file_open(PTCacheID *id, int mode, int cfra); +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); + +/* Continue physics */ +void BKE_ptcache_set_continue_physics(int enable); +int BKE_ptcache_get_continue_physics(void); + +/* Point Cache */ +struct PointCache *BKE_ptcache_add(void); +void BKE_ptcache_free(struct PointCache *cache); +struct PointCache *BKE_ptcache_copy(struct PointCache *cache); #endif diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h index 91bc4cc070d..8a3688fbe09 100644 --- a/source/blender/blenkernel/BKE_softbody.h +++ b/source/blender/blenkernel/BKE_softbody.h @@ -55,7 +55,8 @@ extern struct SoftBody *sbNew(void); /* frees internal data and softbody itself */ extern void sbFree(struct SoftBody *sb); -extern void softbody_clear_cache(struct Object *ob, float framenr); +/* frees simulation data to reset simulation */ +extern void sbFreeSimulation(struct SoftBody *sb); /* do one simul step, reading and writing vertex locs from given array */ extern void sbObjectStep(struct Object *ob, float framnr, float (*vertexCos)[3], int numVerts); @@ -67,6 +68,8 @@ extern void sbObjectToSoftbody(struct Object *ob); /* pass NULL to unlink again */ extern void sbSetInterruptCallBack(int (*f)(void)); +/* writing to cache for bake editing */ +extern void sbWriteCache(struct Object *ob, int framenr); #endif diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index b0103fa812b..7624ca04984 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -2012,8 +2012,7 @@ static void mesh_calc_modifiers(Object *ob, float (*inputVertexCos)[3], if((md->mode & required_mode) != required_mode) continue; if(mti->type == eModifierTypeType_OnlyDeform && !useDeform) continue; if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) { - modifier_setError(md, "Internal error, modifier requires " - "original data (bad stack position)."); + modifier_setError(md, "Modifier requires original data, bad stack position."); continue; } if(mti->isDisabled && mti->isDisabled(md)) continue; @@ -2194,8 +2193,7 @@ static int editmesh_modifier_is_enabled(ModifierData *md, DerivedMesh *dm) if((md->mode & required_mode) != required_mode) return 0; if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) { - modifier_setError(md, "Internal error, modifier requires" - "original data (bad stack position)."); + modifier_setError(md, "Modifier requires original data, bad stack position."); return 0; } if(mti->isDisabled && mti->isDisabled(md)) return 0; diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 6123b1b5e35..15f4051c109 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -34,6 +34,7 @@ #include "DNA_cloth_types.h" #include "DNA_mesh_types.h" +#include "DNA_object_force.h" #include "DNA_scene_types.h" #include "BKE_deform.h" @@ -92,7 +93,7 @@ static CM_SOLVER_DEF solvers [] = */ static void cloth_to_object (Object *ob, ClothModifierData *clmd, DerivedMesh *dm); static void cloth_from_mesh ( Object *ob, ClothModifierData *clmd, DerivedMesh *dm ); -static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr); +static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first); int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ); static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ); @@ -121,18 +122,11 @@ void cloth_init ( ClothModifierData *clmd ) clmd->sim_parms->Cvi = 1.0; clmd->sim_parms->mass = 0.3f; clmd->sim_parms->stepsPerFrame = 5; - clmd->sim_parms->sim_time = 1.0; - clmd->sim_parms->flags = CLOTH_SIMSETTINGS_FLAG_AUTOPROTECT; + clmd->sim_parms->flags = 0; clmd->sim_parms->solver_type = 0; clmd->sim_parms->preroll = 0; clmd->sim_parms->maxspringlen = 10; - clmd->sim_parms->firstframe = 1; - clmd->sim_parms->lastframe = 250; clmd->sim_parms->vgroup_mass = 0; - clmd->sim_parms->lastcachedframe = 0; - clmd->sim_parms->editedframe = 0; - clmd->sim_parms->autoprotect = 25; - clmd->sim_parms->firstcachedframe = -1.0; clmd->sim_parms->avg_spring_len = 0.0; clmd->sim_parms->presets = 2; /* cotton as start setting */ clmd->sim_parms->timescale = 1.0f; /* speed factor, describes how fast cloth moves */ @@ -246,395 +240,266 @@ int modifiers_indexInObject(Object *ob, ModifierData *md_seek); int cloth_read_cache(Object *ob, ClothModifierData *clmd, float framenr) { - FILE *fp = NULL; - int stack_index = -1; - unsigned int a, ret = 1; + PTCacheID pid; + PTCacheFile *pf; Cloth *cloth = clmd->clothObject; + unsigned int a, ret = 1; if(!cloth) return 0; - stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); - - fp = BKE_ptcache_id_fopen((ID *)ob, 'r', framenr, stack_index); - if(!fp) - ret = 0; - else { - for(a = 0; a < cloth->numverts; a++) - { - if(fread(&cloth->verts[a].x, sizeof(float), 3, fp) != 3) - { + 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(fread(&cloth->verts[a].xconst, sizeof(float), 3, fp) != 3) - { + if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].xconst, 3)) { ret = 0; break; } - if(fread(&cloth->verts[a].v, sizeof(float), 3, fp) != 3) - { + if(!BKE_ptcache_file_read_floats(pf, cloth->verts[a].v, 3)) { ret = 0; break; } } - fclose(fp); - - if(clmd->sim_parms->lastcachedframe < framenr) - { - if(G.rt > 0) - printf("cloth_read_cache problem: lnex - f#: %f, lastCF: %d\n", framenr, clmd->sim_parms->lastcachedframe); - } - - if(G.rt > 0) - printf("cloth_read_cache: %f successfully \n", framenr); + BKE_ptcache_file_close(pf); } - - if(G.rt > 0) - printf("cloth_read_cache: %f\n", framenr); + else + ret = 0; return ret; } void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) { - int stack_index = -1; + PTCacheID pid; + BKE_ptcache_id_from_cloth(&pid, ob, clmd); + // don't do anything as long as we're in editmode! - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE) - { - /* delete cache free request */ - clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; - + if(pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE) return; - } - - /* clear cache if specific frame cleaning requested or cache is not protected */ - if((!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) || (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE)) - { - stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); - - BKE_ptcache_id_clear((ID *)ob, PTCACHE_CLEAR_AFTER, framenr, stack_index); - - /* update last cached frame # */ - clmd->sim_parms->lastcachedframe = framenr; - - /* update first cached frame # */ - if((framenr < clmd->sim_parms->firstcachedframe) && (clmd->sim_parms->firstcachedframe >=0.0)) - clmd->sim_parms->firstcachedframe = -1.0; - - if(G.rt > 0) - printf("cloth_clear_cache: %f\n", framenr); - } - - /* delete cache free request */ - clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; - + BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr); } + void cloth_write_cache(Object *ob, ClothModifierData *clmd, float framenr) { - FILE *fp = NULL; - int stack_index = -1; - unsigned int a; Cloth *cloth = clmd->clothObject; - - if(G.rt > 0) - printf("cloth_write_cache: %f\n", framenr); + PTCacheID pid; + PTCacheFile *pf; + unsigned int a; if(!cloth) - { - if(G.rt > 0) - printf("cloth_write_cache: no cloth\n"); return; - } - - stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); - fp = BKE_ptcache_id_fopen((ID *)ob, 'w', framenr, stack_index); - if(!fp) - { - if(G.rt > 0) - printf("cloth_write_cache: no fp\n"); + 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++) - { - fwrite(&cloth->verts[a].x, sizeof(float),3,fp); - fwrite(&cloth->verts[a].xconst, sizeof(float),3,fp); - fwrite(&cloth->verts[a].v, sizeof(float),3,fp); + 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); } - /* update last cached frame # */ - clmd->sim_parms->lastcachedframe = MAX2(clmd->sim_parms->lastcachedframe, framenr); + BKE_ptcache_file_close(pf); +} + +static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr) +{ + PointCache *cache; + + cache= clmd->point_cache; + + /* initialize simulation data if it didn't exist already */ + if(clmd->clothObject == NULL) { + if(!cloth_from_object(ob, clmd, result, framenr, 1)) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; + return 0; + } + + if(clmd->clothObject == NULL) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; + return 0; + } - /* update first cached frame # */ - if((clmd->sim_parms->firstcachedframe < 0.0) || ((framenr < clmd->sim_parms->firstcachedframe) && (clmd->sim_parms->firstcachedframe > 0.0))) - clmd->sim_parms->firstcachedframe = framenr; + implicit_set_positions(clmd); + } + + return 1; +} + +static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr) +{ + ClothVertex *verts = NULL; + Cloth *cloth; + ListBase *effectors = NULL; + MVert *mvert; + int i, ret = 0; + + /* simulate 1 frame forward */ + cloth = clmd->clothObject; + verts = cloth->verts; + mvert = result->getVertArray(result); + + /* force any pinned verts to their constrained location. */ + for(i = 0; i < clmd->clothObject->numverts; i++, verts++) { + /* save the previous position. */ + VECCOPY(verts->xold, verts->xconst); + VECCOPY(verts->txold, verts->x); + + /* Get the current position. */ + VECCOPY(verts->xconst, mvert[i].co); + Mat4MulVecfl(ob->obmat, verts->xconst); + } - if(G.rt > 0) - printf("lcf: %d, framenr: %f\n", clmd->sim_parms->lastcachedframe, framenr); + tstart(); + + /* call the solver. */ + if(solvers [clmd->sim_parms->solver_type].solver) + ret = solvers[clmd->sim_parms->solver_type].solver(ob, framenr, clmd, effectors); + + tend(); - fclose(fp); + /* printf ( "Cloth simulation time: %f\n", ( float ) tval() ); */ + + return ret; } /************************************************ * clothModifier_do - main simulation function ************************************************/ -DerivedMesh *clothModifier_do(ClothModifierData *clmd,Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) - +DerivedMesh *clothModifier_do(ClothModifierData *clmd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc) { - unsigned int i; - Cloth *cloth = clmd->clothObject; - float framenr = G.scene->r.cfra; - float current_time = bsystem_time ( ob, ( float ) G.scene->r.cfra, 0.0 ); - ListBase *effectors = NULL; - ClothVertex *verts = NULL; - float deltaTime = current_time - clmd->sim_parms->sim_time; - unsigned int numverts = -1; - unsigned int numedges = -1; - unsigned int numfaces = -1; - MVert *mvert = NULL; - MEdge *medge = NULL; - MFace *mface = NULL; - DerivedMesh *result = NULL; - int ret = 0; - - if(G.rt > 0) - printf("clothModifier_do start\n"); - - /* we're getting called two times during file load, - resulting in a not valid G.relbase on the first time (cache makes problems) - --> just return back */ - if((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_LOADED) && (!G.relbase_valid)) - { - clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_LOADED; - return dm; - } - + DerivedMesh *result; + PointCache *cache; + PTCacheID pid; + float timescale; + int framedelta, framenr, startframe, endframe; + + framenr= (int)G.scene->r.cfra; + cache= clmd->point_cache; result = CDDM_copy(dm); - - if(!result) - { + + BKE_ptcache_id_from_cloth(&pid, ob, clmd); + BKE_ptcache_id_time(&pid, framenr, &startframe, &endframe, ×cale); + clmd->sim_parms->timescale= timescale; + + /* TODO: use timescale somewhere! */ + + if(!result) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; return dm; } - numverts = result->getNumVerts(result); - numedges = result->getNumEdges(result); - numfaces = result->getNumFaces(result); - mvert = result->getVertArray(result); - medge = result->getEdgeArray(result); - mface = result->getFaceArray(result); - - /* check if cache is active / if file is already saved */ - /* - if ((!G.relbase_valid) && ( deltaTime != 1.0f )) - { - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; -} - */ - - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_RESET) - { - cloth_free_modifier (ob, clmd); - if(G.rt > 0) - printf("clothModifier_do CLOTH_SIMSETTINGS_FLAG_RESET\n"); - - // prevent rebuilding of cloth each time you move backward - if(deltaTime < 0.0) + /* verify we still have the same number of vertices, if not do nothing. + * note that this should only happen if the number of vertices changes + * during an animation due to a preceding modifier, this should not + * happen because of object changes! */ + if(clmd->clothObject) { + if(result->getNumVerts(result) != clmd->clothObject->numverts) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; return result; + } } // unused in the moment, calculated seperately in implicit.c clmd->sim_parms->dt = clmd->sim_parms->timescale / clmd->sim_parms->stepsPerFrame; - - if ( ( clmd->clothObject == NULL ) || (clmd->clothObject && (numverts != clmd->clothObject->numverts )) ) - { - /* only force free the cache if we have a different number of verts */ - if(clmd->clothObject && (numverts != clmd->clothObject->numverts )) - { - if(G.rt > 0) - printf("Force Freeing: numverts != clmd->clothObject->numverts\n"); - - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; - cloth_free_modifier ( ob, clmd ); - } - - cloth_clear_cache(ob, clmd, 0); - - if ( !cloth_from_object ( ob, clmd, result, framenr ) ) - return result; - - if ( clmd->clothObject == NULL ) + + /* handle continuous simulation with the play button */ + if(BKE_ptcache_get_continue_physics()) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; + + /* do simulation */ + if(!do_init_cloth(ob, clmd, result, framenr)) return result; - - cloth = clmd->clothObject; - - if(!cloth_read_cache(ob, clmd, framenr)) - { - /* save first frame in case we have a reseted object - and we move one frame forward. - In that case we would only start with the SECOND frame - if we don't save the current state before - TODO PROBLEM: IMHO we can't track external movement from the - first frame in this case! */ - /* - if ( deltaTime == 1.0f ) - cloth_write_cache(ob, clmd, framenr-1.0); - */ - if(G.rt > 0) - printf("cloth_from_object NO cloth_read_cache cloth_write_cache\n"); - } - else - { - if(G.rt > 0) - printf("cloth_from_object cloth_read_cache\n"); - - implicit_set_positions(clmd); - } - - clmd->sim_parms->sim_time = current_time; - } - - // only be active during a specific period: - // that's "first frame" and "last frame" on GUI - if ( current_time < clmd->sim_parms->firstframe ) - { - if(G.rt > 0) - printf("current_time < clmd->sim_parms->firstframe\n"); + + do_step_cloth(ob, clmd, result, framenr); + cloth_to_object(ob, clmd, result); + return result; } - else if ( current_time > clmd->sim_parms->lastframe ) - { - int stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); - - if(G.rt > 0) - printf("current_time > clmd->sim_parms->lastframe\n"); - - if(BKE_ptcache_id_exist((ID *)ob, clmd->sim_parms->lastcachedframe, stack_index)) - { - if(cloth_read_cache(ob, clmd, clmd->sim_parms->lastcachedframe)) - { - implicit_set_positions(clmd); - - // Copy the result back to the object. - cloth_to_object (ob, clmd, result); - } - } + + /* simulation is only active during a specific period */ + if(framenr < startframe) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; return result; } - - // check for autoprotection, but only if cache active - if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_AUTOPROTECT) - { - if((framenr >= clmd->sim_parms->autoprotect) && (G.relbase_valid)) - { - if(G.rt > 0) - printf("fr#: %f, auto: %d\n", framenr, clmd->sim_parms->autoprotect); - - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT; - } + else if(framenr > endframe) { + framenr= endframe; } - /* nice moving one frame forward */ - if ( deltaTime == 1.0f ) - { - clmd->sim_parms->sim_time = current_time; - - if(G.rt > 0) - printf("clothModifier_do deltaTime=1\n"); - - if(!cloth_read_cache(ob, clmd, framenr)) - { - verts = cloth->verts; + /* dt is unused at the moment, calculated seperately in implicit.c */ + clmd->sim_parms->dt= 1.0f/clmd->sim_parms->stepsPerFrame; - // Force any pinned verts to their constrained location. - for ( i = 0; i < clmd->clothObject->numverts; i++, verts++ ) - { - // Save the previous position. - VECCOPY ( verts->xold, verts->xconst ); - VECCOPY ( verts->txold, verts->x ); + if(cache->flag & PTCACHE_SIMULATION_VALID) + framedelta= framenr - cache->simframe; + else + framedelta= -1; - // Get the current position. - VECCOPY ( verts->xconst, mvert[i].co ); - Mat4MulVecfl ( ob->obmat, verts->xconst ); - } - - tstart(); + /* initialize simulation data if it didn't exist already */ + if(!do_init_cloth(ob, clmd, result, framenr)) + return result; - // Call the solver. - if ( solvers [clmd->sim_parms->solver_type].solver ) - { - ret = solvers [clmd->sim_parms->solver_type].solver ( ob, framenr, clmd, effectors ); - } + /* try to read from cache */ + if(cloth_read_cache(ob, clmd, framenr)) { + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->simframe= framenr; - tend(); - // printf ( "Cloth simulation time: %f\n", ( float ) tval() ); - - if(ret) - cloth_write_cache(ob, clmd, framenr); - else - clmd->sim_parms->sim_time--; - } - else - { - if(G.rt > 0) - printf("clothModifier_do deltaTime=1 cacheread\n"); - implicit_set_positions(clmd); - } - - // Copy the result back to the object. + implicit_set_positions(clmd); cloth_to_object (ob, clmd, result); + + return result; } - else if(deltaTime == 0.0f) - { - if(G.rt > 0) - printf("dt = 0, %f\n", framenr); - if(cloth_read_cache(ob, clmd, framenr)) - { - cloth_to_object (ob, clmd, result); - implicit_set_positions(clmd); - } - else /* same cache parts are missing */ - { - /* jump to a non-existing frame makes sim reset if cache is not protected */ - if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) - { - /* prevent freeing when used with vectorblur */ - if(!useRenderParams) - { - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; - cloth_clear_cache(ob, clmd, 0); - - cloth_write_cache(ob, clmd, 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; + return result; } - else - { - if(G.rt > 0) - printf("dt > 1.0 || dt < 0.0, %f, st: %f, ct: %f\n", framenr, clmd->sim_parms->sim_time, current_time); - if(cloth_read_cache(ob, clmd, framenr)) - { - cloth_to_object (ob, clmd, result); - implicit_set_positions(clmd); + + if(framenr == startframe) { + 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) { + /* if on second frame, write cache for first frame */ + if(framenr == startframe+1) + cloth_write_cache(ob, clmd, startframe); + + /* do simulation */ + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->simframe= framenr; + + if(!do_step_cloth(ob, clmd, result, framenr)) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; } else - { - /* jump to a non-existing frame makes sim reset if cache is not protected */ - if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) - { - /* prevent freeing when used with vectorblur */ - if(!useRenderParams) - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; - } - } - clmd->sim_parms->sim_time = current_time; + cloth_write_cache(ob, clmd, framenr); + + cloth_to_object (ob, clmd, result); } - + else { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; + } + return result; } @@ -702,7 +567,6 @@ void cloth_free_modifier ( Object *ob, ClothModifierData *clmd ) MEM_freeN ( cloth ); clmd->clothObject = NULL; } - clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_RESET; } /* frees all */ @@ -888,13 +752,12 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) } } -static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr) +static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *dm, float framenr, int first) { unsigned int i = 0; MVert *mvert = NULL; ClothVertex *verts = NULL; float tnull[3] = {0,0,0}; - int cache_there = 0; Cloth *cloth = NULL; // If we have a clothObject, free it. @@ -926,21 +789,6 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d cloth_from_mesh ( ob, clmd, dm ); - if((clmd->sim_parms->firstcachedframe < 0.0) || ((clmd->sim_parms->firstcachedframe >= 0.0) && (!cloth_read_cache(ob, clmd, clmd->sim_parms->firstcachedframe)))) - { - // no cache there - cache_there = 0; - if(G.rt > 0) - printf("cache_there = 0\n"); - } - else - { - // we have a cache - cache_there = 1; - if(G.rt > 0) - printf("cache_there = 1, fcf: %d\n", clmd->sim_parms->firstcachedframe); - } - // create springs clmd->clothObject->springs = NULL; clmd->clothObject->numsprings = -1; @@ -951,7 +799,7 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d // set initial values for ( i = 0; i < dm->getNumVerts(dm); i++, verts++ ) { - if(!cache_there) + if(first) { VECCOPY ( verts->x, mvert[i].co ); Mat4MulVecfl ( ob->obmat, verts->x ); @@ -998,10 +846,11 @@ static int cloth_from_object(Object *ob, ClothModifierData *clmd, DerivedMesh *d } // init our solver - if ( solvers [clmd->sim_parms->solver_type].init ) + if ( solvers [clmd->sim_parms->solver_type].init ) { solvers [clmd->sim_parms->solver_type].init ( ob, clmd ); + } - if(cache_there) + if(!first) implicit_set_positions(clmd); clmd->clothObject->tree = bvh_build_from_cloth ( clmd, clmd->coll_parms->epsilon ); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 5f95ce61aca..ab6cf070a80 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -74,6 +74,7 @@ #include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_particle.h" +#include "BKE_pointcache.h" #include "BKE_utildefines.h" #include "BKE_scene.h" @@ -1647,6 +1648,7 @@ static void flush_update_node(DagNode *node, unsigned int layer, int curtime) ob= node->ob; if(ob && (ob->recalc & OB_RECALC)) { all_layer= ob->lay; + /* got an object node that changes, now check relations */ for(itA = node->child; itA; itA= itA->next) { all_layer |= itA->lay; @@ -1720,18 +1722,24 @@ static void flush_update_node(DagNode *node, unsigned int layer, int curtime) } /* node was checked to have lasttime != curtime , and is of type ID_OB */ -static unsigned int flush_layer_node(DagNode *node, int curtime) +static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime) { + Base *base; DagAdjList *itA; node->lasttime= curtime; - node->lay= ((Object *)node->ob)->lay; + node->lay= 0; + for(base= sce->base.first; base; base= base->next) { + if(node->ob == base->object) { + node->lay= ((Object *)node->ob)->lay; + break; + } + } for(itA = node->child; itA; itA= itA->next) { if(itA->node->type==ID_OB) { if(itA->node->lasttime!=curtime) { - itA->lay= flush_layer_node(itA->node, curtime); // lay is only set once for each relation - //printf("layer %d for relation %s to %s\n", itA->lay, ((Object *)node->ob)->id.name, ((Object *)itA->node->ob)->id.name); + itA->lay= flush_layer_node(sce, itA->node, curtime); // lay is only set once for each relation } else itA->lay= itA->node->lay; @@ -1742,11 +1750,32 @@ static unsigned int flush_layer_node(DagNode *node, int curtime) return node->lay; } +/* node was checked to have lasttime != curtime , and is of type ID_OB */ +static void flush_pointcache_reset(DagNode *node, int curtime) +{ + DagAdjList *itA; + Object *ob; + + node->lasttime= curtime; + + for(itA = node->child; itA; itA= itA->next) { + if(itA->node->type==ID_OB) { + if(itA->node->lasttime!=curtime) { + ob= (Object*)(node->ob); + if(BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH)) + ob->recalc |= OB_RECALC_DATA; + flush_pointcache_reset(itA->node, curtime); + } + } + } +} + /* flushes all recalc flags in objects down the dependency tree */ -void DAG_scene_flush_update(Scene *sce, unsigned int lay) +void DAG_scene_flush_update(Scene *sce, unsigned int lay, int time) { DagNode *firstnode; DagAdjList *itA; + Object *ob; int lasttime; if(sce->theDag==NULL) { @@ -1755,21 +1784,37 @@ void DAG_scene_flush_update(Scene *sce, unsigned int lay) } firstnode= sce->theDag->DagNode.first; // always scene node + + for(itA = firstnode->child; itA; itA= itA->next) + itA->lay= 0; /* first we flush the layer flags */ sce->theDag->time++; // so we know which nodes were accessed lasttime= sce->theDag->time; - for(itA = firstnode->child; itA; itA= itA->next) { + + for(itA = firstnode->child; itA; itA= itA->next) if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB) - flush_layer_node(itA->node, lasttime); - } + flush_layer_node(sce, itA->node, lasttime); /* then we use the relationships + layer info to flush update events */ sce->theDag->time++; // so we know which nodes were accessed lasttime= sce->theDag->time; - for(itA = firstnode->child; itA; itA= itA->next) { - if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB) + for(itA = firstnode->child; itA; itA= itA->next) + if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB) flush_update_node(itA->node, lay, lasttime); + + /* if update is not due to time change, do pointcache clears */ + if(!time) { + sce->theDag->time++; // so we know which nodes were accessed + lasttime= sce->theDag->time; + for(itA = firstnode->child; itA; itA= itA->next) { + if(itA->node->lasttime!=lasttime && itA->node->type==ID_OB) { + ob= (Object*)(itA->node->ob); + if(BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH)) + ob->recalc |= OB_RECALC_DATA; + flush_pointcache_reset(itA->node, lasttime); + } + } } } @@ -1955,7 +2000,7 @@ void DAG_scene_update_flags(Scene *scene, unsigned int lay) } for(sce= scene; sce; sce= sce->set) - DAG_scene_flush_update(sce, lay); + DAG_scene_flush_update(sce, lay, 1); /* test: set time flag, to disable baked systems to update */ for(SETLOOPER(scene, base)) { @@ -2005,7 +2050,9 @@ void DAG_object_flush_update(Scene *sce, Object *ob, short flag) { if(ob==NULL || sce->theDag==NULL) return; + ob->recalc |= flag; + BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH); /* all users of this ob->data should be checked */ /* BUT! displists for curves are still only on cu */ @@ -2018,8 +2065,9 @@ void DAG_object_flush_update(Scene *sce, Object *ob, short flag) else { Object *obt; for (obt=G.main->object.first; obt; obt= obt->id.next) { - if (obt->data==ob->data) { + if (obt != ob && obt->data==ob->data) { obt->recalc |= OB_RECALC_DATA; + BKE_ptcache_object_reset(obt, PTCACHE_RESET_DEPSGRAPH); } } } @@ -2028,9 +2076,9 @@ void DAG_object_flush_update(Scene *sce, Object *ob, short flag) } if(G.curscreen) - DAG_scene_flush_update(sce, dag_screen_view3d_layers()); + DAG_scene_flush_update(sce, dag_screen_view3d_layers(), 0); else - DAG_scene_flush_update(sce, sce->lay); + DAG_scene_flush_update(sce, sce->lay, 0); } /* recursively descends tree, each node only checked once */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 2d609811efe..0f51c74c248 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -3453,7 +3453,7 @@ static DerivedMesh *decimateModifier_applyModifier( if(numTris<3) { modifier_setError(md, - "There must be more than 3 input faces (triangles)."); + "Modifier requires more than 3 input faces (triangles)."); goto exit; } @@ -5057,9 +5057,10 @@ static void clothModifier_initData(ModifierData *md) clmd->sim_parms = MEM_callocN(sizeof(ClothSimSettings), "cloth sim parms"); clmd->coll_parms = MEM_callocN(sizeof(ClothCollSettings), "cloth coll parms"); + clmd->point_cache = BKE_ptcache_add(); /* check for alloc failing */ - if(!clmd->sim_parms || !clmd->coll_parms) + if(!clmd->sim_parms || !clmd->coll_parms || !clmd->point_cache) return; cloth_init (clmd); @@ -5138,11 +5139,9 @@ static void clothModifier_copyData(ModifierData *md, ModifierData *target) tclmd->sim_parms = MEM_dupallocN(clmd->sim_parms); tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms); - - tclmd->sim_parms->lastcachedframe = 0; + tclmd->point_cache = BKE_ptcache_copy(clmd->point_cache); } - static int clothModifier_dependsOnTime(ModifierData *md) { return 1; @@ -5163,6 +5162,8 @@ static void clothModifier_freeData(ModifierData *md) MEM_freeN(clmd->sim_parms); if(clmd->coll_parms) MEM_freeN(clmd->coll_parms); + if(clmd->point_cache) + BKE_ptcache_free(clmd->point_cache); } } @@ -5435,7 +5436,6 @@ static void particleSystemModifier_freeData(ModifierData *md) psmd->dm=0; } - psmd->psys->flag &= ~PSYS_ENABLED; psmd->psys->flag |= PSYS_DELETE; } static void particleSystemModifier_copyData(ModifierData *md, ModifierData *target) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 287708a8ed4..ff5dcb763f4 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -105,6 +105,7 @@ #include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_particle.h" +#include "BKE_pointcache.h" #include "BKE_property.h" #include "BKE_sca.h" #include "BKE_scene.h" @@ -295,6 +296,7 @@ void unlink_object(Object *ob) Camera *camera; bConstraint *con; bActionStrip *strip; + ModifierData *md; int a; unlink_controllers(&ob->controllers); @@ -397,6 +399,11 @@ void unlink_object(Object *ob) obt->recalc |= OB_RECALC_DATA; else if(obt->soft) obt->recalc |= OB_RECALC_DATA; + + /* cloth */ + for(md=obt->modifiers.first; md; md=md->next) + if(md->type == eModifierType_Cloth) + obt->recalc |= OB_RECALC_DATA; } /* strips */ @@ -1011,12 +1018,14 @@ SoftBody *copy_softbody(SoftBody *sb) sbn->totspring= sbn->totpoint= 0; sbn->bpoint= NULL; sbn->bspring= NULL; - sbn->ctime= 0.0f; sbn->keys= NULL; sbn->totkey= sbn->totpointkey= 0; sbn->scratch= NULL; + + sbn->pointcache= BKE_ptcache_copy(sb->pointcache); + return sbn; } @@ -1047,6 +1056,8 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys) psysn->edit= NULL; psysn->effectors.first= psysn->effectors.last= 0; + psysn->pointcache= BKE_ptcache_copy(psys->pointcache); + id_us_plus((ID *)psysn->part); return psysn; @@ -2180,7 +2191,7 @@ void object_handle_update(Object *ob) if(ob->recalc & OB_RECALC) { if(ob->recalc & OB_RECALC_OB) { - + // printf("recalcob %s\n", ob->id.name+2); /* handle proxy copy for target */ diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 6b2f2f911c6..6bdb4e6f8d3 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -78,6 +78,7 @@ #include "BKE_modifier.h" #include "BKE_mesh.h" #include "BKE_cdderivedmesh.h" +#include "BKE_pointcache.h" #include "blendef.h" #include "RE_render_ext.h" @@ -226,14 +227,14 @@ void psys_disable_all(Object *ob) ParticleSystem *psys=ob->particlesystem.first; for(; psys; psys=psys->next) - psys->flag &= ~PSYS_ENABLED; + psys->flag |= PSYS_DISABLED; } void psys_enable_all(Object *ob) { ParticleSystem *psys=ob->particlesystem.first; for(; psys; psys=psys->next) - psys->flag |= PSYS_ENABLED; + psys->flag &= ~PSYS_DISABLED; } int psys_ob_has_hair(Object *ob) { @@ -253,7 +254,7 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys) { ParticleSystemModifierData *psmd; - if(!(psys->flag & PSYS_ENABLED)) + if(psys->flag & PSYS_DISABLED) return 0; psmd= psys_get_modifier(ob, psys); @@ -370,6 +371,9 @@ void psys_free(Object *ob, ParticleSystem * psys) } MEM_freeN(psys); + + if(psys->pointcache) + BKE_ptcache_free(psys->pointcache); } } @@ -2251,7 +2255,7 @@ void psys_cache_child_paths(Object *ob, ParticleSystem *psys, float cfra, int ed int i, totchild, totparent, totthread; unsigned long totchildstep; - pthreads= psys_threads_create(ob, psys, G.scene->r.threads); + pthreads= psys_threads_create(ob, psys); if(!psys_threads_init_path(pthreads, cfra, editupdate)) { psys_threads_free(pthreads); @@ -3080,6 +3084,42 @@ void psys_flush_settings(ParticleSettings *part, int event, int hair_recalc) } } } + +LinkNode *psys_using_settings(ParticleSettings *part, int flush_update) +{ + Object *ob, *tob; + ParticleSystem *psys, *tpsys; + LinkNode *node= NULL; + int found; + + /* update all that have same particle settings */ + for(ob=G.main->object.first; ob; ob=ob->id.next) { + found= 0; + + for(psys=ob->particlesystem.first; psys; psys=psys->next) { + if(psys->part == part) { + BLI_linklist_append(&node, psys); + found++; + } + else if(psys->part->type == PART_REACTOR){ + tob= (psys->target_ob)? psys->target_ob: ob; + tpsys= BLI_findlink(&tob->particlesystem, psys->target_psys-1); + + if(tpsys && tpsys->part==part) { + BLI_linklist_append(&node, tpsys); + found++; + } + } + } + + if(flush_update && found) + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + } + + return node; +} + + /************************************************/ /* Textures */ /************************************************/ diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 8bde0afb752..cd0d6b5d113 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -121,7 +121,48 @@ static int get_current_display_percentage(ParticleSystem *psys) return psys->part->disp; } -static void alloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) +void psys_reset(ParticleSystem *psys, int mode) +{ + ParticleSettings *part= psys->part; + ParticleData *pa; + int i; + + if(ELEM(mode, PSYS_RESET_ALL, PSYS_RESET_DEPSGRAPH)) { + if(mode == PSYS_RESET_ALL || !(part->type == PART_HAIR && (psys->flag & PSYS_EDITED))) { + if(psys->particles) { + if(psys->particles->keys) + MEM_freeN(psys->particles->keys); + + for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++) + if(pa->hair) MEM_freeN(pa->hair); + + MEM_freeN(psys->particles); + psys->particles= NULL; + } + + psys->totpart= 0; + psys->totkeyed= 0; + psys->flag &= ~(PSYS_HAIR_DONE|PSYS_KEYED); + } + } + + /* reset children */ + if(psys->child) { + MEM_freeN(psys->child); + psys->child= 0; + } + + psys->totchild= 0; + + /* reset path cache */ + psys_free_path_cache(psys); + + /* reset point cache */ + psys->pointcache->flag &= ~PTCACHE_SIMULATION_VALID; + psys->pointcache->simframe= 0; +} + +static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) { ParticleData *newpars = 0, *pa; int i, totpart, totsaved = 0; @@ -145,6 +186,12 @@ static void alloc_particles(Object *ob, ParticleSystem *psys, int new_totpart) if(totsaved) memcpy(newpars,psys->particles,totsaved*sizeof(ParticleData)); + if(psys->particles->keys) + MEM_freeN(psys->particles->keys); + + for(i=0, pa=psys->particles; i<totsaved; i++, pa++) + if(pa->keys) pa->keys= NULL; + for(i=totsaved, pa=psys->particles+totsaved; i<psys->totpart; i++, pa++) if(pa->hair) MEM_freeN(pa->hair); @@ -1313,7 +1360,7 @@ static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, Particl ParticleThreadContext *ctx; int i, totthread; - pthreads= psys_threads_create(ob, psys, G.scene->r.threads); + pthreads= psys_threads_create(ob, psys); if(!psys_threads_init_distribution(pthreads, finaldm, from)) { psys_threads_free(pthreads); @@ -1385,11 +1432,16 @@ static void distribute_particles(Object *ob, ParticleSystem *psys, int from) } /* threaded child particle distribution and path caching */ -ParticleThread *psys_threads_create(struct Object *ob, struct ParticleSystem *psys, int totthread) +ParticleThread *psys_threads_create(struct Object *ob, struct ParticleSystem *psys) { ParticleThread *threads; ParticleThreadContext *ctx; - int i; + int i, totthread; + + if(G.scene->r.mode & R_FIXED_THREADS) + totthread= G.scene->r.threads; + else + totthread= BLI_system_thread_count(); threads= MEM_callocN(sizeof(ParticleThread)*totthread, "ParticleThread"); ctx= MEM_callocN(sizeof(ParticleThreadContext), "ParticleThreadContext"); @@ -1922,7 +1974,8 @@ int psys_count_keyed_targets(Object *ob, ParticleSystem *psys) BLI_freelistN(&lb); return select; } -void set_keyed_keys(Object *ob, ParticleSystem *psys) + +static void set_keyed_keys(Object *ob, ParticleSystem *psys) { Object *kob = ob; ParticleSystem *kpsys = psys; @@ -1932,17 +1985,16 @@ void set_keyed_keys(Object *ob, ParticleSystem *psys) float prevtime, nexttime, keyedtime; /* no proper targets so let's clear and bail out */ - if(psys->totkeyed==0){ + if(psys->totkeyed==0) { free_keyed_keys(psys); psys->flag &= ~PSYS_KEYED; return; } - if(totpart && psys->particles->totkey != totkeys){ + if(totpart && psys->particles->totkey != totkeys) { free_keyed_keys(psys); - psys->particles->keys = MEM_callocN(psys->totpart * totkeys * sizeof(ParticleKey),"Keyed keys"); - + psys->particles->keys = MEM_callocN(psys->totpart*totkeys*sizeof(ParticleKey), "Keyed keys"); psys->particles->totkey = totkeys; for(i=1, pa=psys->particles+1; i<totpart; i++,pa++){ @@ -1954,9 +2006,10 @@ void set_keyed_keys(Object *ob, ParticleSystem *psys) psys->flag &= ~PSYS_KEYED; state.time=-1.0; - for(k=0; k<totkeys; k++){ - for(i=0,pa=psys->particles; i<totpart; i++, pa++){ - psys_get_particle_state(kob, kpsys, i%kpsys->totpart, pa->keys + k, 1); + for(k=0; k<totkeys; k++) { + for(i=0,pa=psys->particles; i<totpart; i++, pa++) { + if(kpsys->totpart > 0) + psys_get_particle_state(kob, kpsys, i%kpsys->totpart, pa->keys + k, 1); if(k==0) pa->keys->time = pa->time; @@ -2097,60 +2150,57 @@ void psys_get_reactor_target(Object *ob, ParticleSystem *psys, Object **target_o /************************************************/ /* Point Cache */ /************************************************/ -void clear_particles_from_cache(Object *ob, ParticleSystem *psys, int cfra) -{ - ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys); - int stack_index = modifiers_indexInObject(ob,(ModifierData*)psmd); - - BKE_ptcache_id_clear((ID *)ob, PTCACHE_CLEAR_ALL, cfra, stack_index); - /* reactors need to initialize particles always since their birth times might have changed */ - if(psys && psys->part && psys->part->type == PART_REACTOR) - psys->recalc |= PSYS_INIT; -} static void write_particles_to_cache(Object *ob, ParticleSystem *psys, int cfra) { - FILE *fp = NULL; - ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys); + PTCacheID pid; + PTCacheFile *pf; ParticleData *pa; - int stack_index = modifiers_indexInObject(ob,(ModifierData*)psmd); - int i, totpart = psys->totpart; + int i, totpart= psys->totpart; - if(totpart == 0) return; + if(totpart == 0) + return; - fp = BKE_ptcache_id_fopen((ID *)ob, 'w', cfra, stack_index); - if(!fp) return; + BKE_ptcache_id_from_particles(&pid, ob, psys); + pf= BKE_ptcache_file_open(&pid, PTCACHE_FILE_WRITE, cfra); + if(!pf) + return; + /* assuming struct consists of tightly packed floats */ for(i=0, pa=psys->particles; i<totpart; i++, pa++) - fwrite(&pa->state, sizeof(ParticleKey), 1, fp); + BKE_ptcache_file_write_floats(pf, (float*)&pa->state, sizeof(ParticleKey)/sizeof(float)); - fclose(fp); + BKE_ptcache_file_close(pf); } + static int get_particles_from_cache(Object *ob, ParticleSystem *psys, int cfra) { - FILE *fp = NULL; - ParticleSystemModifierData *psmd = psys_get_modifier(ob,psys); + PTCacheID pid; + PTCacheFile *pf; ParticleData *pa; - int stack_index = modifiers_indexInObject(ob,(ModifierData*)psmd); - int i, totpart = psys->totpart, ret = 1; + int i, totpart= psys->totpart; - if(totpart == 0) return 0; + if(totpart == 0) + return 0; - fp = BKE_ptcache_id_fopen((ID *)ob, 'r', cfra, stack_index); - if(!fp) - ret = 0; - else { - for(i=0, pa=psys->particles; i<totpart; i++, pa++) - if((fread(&pa->state, sizeof(ParticleKey), 1, fp)) != 1) { - ret = 0; - break; - } - - fclose(fp); + BKE_ptcache_id_from_particles(&pid, ob, psys); + pf= BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, cfra); + if(!pf) + return 0; + + /* assuming struct consists of tightly packed floats */ + for(i=0, pa=psys->particles; i<totpart; i++, pa++) { + if(!BKE_ptcache_file_read_floats(pf, (float*)&pa->state, sizeof(ParticleKey)/sizeof(float))) { + BKE_ptcache_file_close(pf); + return 0; + } } - return ret; + BKE_ptcache_file_close(pf); + + return 1; } + /************************************************/ /* Effectors */ /************************************************/ @@ -4203,7 +4253,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi copy_particle_key(key,&pa->state,1); } - if(dfra>0.0 || psys->recalc){ + if(1) { if(psys->reactevents.first && ELEM(pa->alive,PARS_DEAD,PARS_KILLED)==0) react_to_events(psys,p); @@ -4306,7 +4356,7 @@ static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd, if(distr){ if(alloc) - alloc_particles(ob,psys,psys->totpart); + realloc_particles(ob,psys,psys->totpart); if(get_psys_tot_child(psys)) { /* don't generate children while computing the hair keys */ @@ -4366,7 +4416,7 @@ static void hair_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSyst } /* updates cached particles' alive & other flags etc..*/ -static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra, float *vg_size) +static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra) { ParticleSettings *part=psys->part; ParticleData *pa; @@ -4374,7 +4424,10 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE); Material *ma=give_current_material(ob,part->omat); int p; - float ipotime=cfra, disp, birthtime, dietime; + float ipotime=cfra, disp, birthtime, dietime, *vg_size= NULL; + + if(part->from!=PART_FROM_PARTICLE) + vg_size= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); if(psys->effectors.first) psys_end_effectors(psys); @@ -4437,10 +4490,48 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy /* make sure that children are up to date */ if(psys->part->childtype && psys->totchild != get_psys_tot_child(psys)) { - alloc_particles(ob, psys, psys->totpart); + realloc_particles(ob, psys, psys->totpart); distribute_particles(ob, psys, PART_FROM_CHILD); } + + if(vg_size) + MEM_freeN(vg_size); } + +void psys_changed_type(ParticleSystem *psys) +{ + ParticleSettings *part; + + part= psys->part; + + /* system type has changed so set sensible defaults and clear non applicable flags */ + if(part->from == PART_FROM_PARTICLE) { + if(part->type != PART_REACTOR) + part->from = PART_FROM_FACE; + if(part->distr == PART_DISTR_GRID) + part->distr = PART_DISTR_JIT; + } + + if(psys->part->phystype != PART_PHYS_KEYED) + psys->flag &= ~PSYS_KEYED; + + if(part->type == PART_HAIR) { + part->draw_as = PART_DRAW_PATH; + part->rotfrom = PART_ROT_IINCR; + } + else { + free_hair(psys, 1); + + if(part->draw_as == PART_DRAW_PATH) + if(psys->part->phystype != PART_PHYS_KEYED) + part->draw_as = PART_DRAW_DOT; + } + + psys->softflag= 0; + + psys_reset(psys, PSYS_RESET_ALL); +} + static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra) { if(psys->particles){ @@ -4448,6 +4539,7 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra) psys->particles = 0; psys->totpart = 0; } + /* fluid sim particle import handling, actual loading of particles from file */ #ifndef DISABLE_ELBEEM if( (1) && (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) && // broken, disabled for now! @@ -4488,7 +4580,7 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra) part->lifetime = G.scene->r.efra + 1; /* initialize particles */ - alloc_particles(ob, psys, part->totpart); + realloc_particles(ob, psys, part->totpart); initialize_all_particles(ob, psys, 0); // set up reading mask @@ -4496,8 +4588,7 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra) for(p=0, pa=psys->particles; p<totpart; p++, pa++) { int ptype=0; - short shsize=0; - float convertSize=0.0; + gzread(gzf, &ptype, sizeof( ptype )); if(ptype&readMask) { activeParts++; @@ -4540,113 +4631,107 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra) } // fluid sim particles done #endif // DISABLE_ELBEEM } + /* Calculates the next state for all particles of the system */ /* In particles code most fra-ending are frames, time-ending are fra*timestep (seconds)*/ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) { ParticleSettings *part; ParticleData *pa; - int totpart,oldtotpart=0,p; - float disp, *vg_vel=0, *vg_tan=0, *vg_rot=0, *vg_size=0; - int init=0,distr=0,alloc=0; + PointCache *cache; + PTCacheID pid; + int totpart, oldtotpart, totchild, oldtotchild, p; + float disp, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; + int init= 0, distr= 0, alloc= 0, usecache= 0; + int framenr, framedelta, startframe, endframe; - /*----start validity checks----*/ + part= psys->part; + cache= psys->pointcache; - part=psys->part; + framenr= (int)CFRA; + framedelta= framenr - cache->simframe; - if(part->flag&PART_ABS_TIME && part->ipo){ + BKE_ptcache_id_from_particles(&pid, ob, psys); + BKE_ptcache_id_time(&pid, 0.0f, &startframe, &endframe, NULL); + + /* update ipo's */ + if((part->flag & PART_ABS_TIME) && part->ipo) { calc_ipo(part->ipo, cfra); execute_ipo((ID *)part, part->ipo); } - if(part->from!=PART_FROM_PARTICLE && part->type!=PART_FLUID) - vg_size=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); - - if(part->type == PART_HAIR) { - if(psys->flag & PSYS_HAIR_DONE) { - hair_step(ob, psmd, psys, cfra); - psys->cfra = cfra; - psys->recalc = 0; - return; - } + /* hair if it's already done is handled separate */ + if(part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DONE)) { + hair_step(ob, psmd, psys, cfra); + psys->cfra = cfra; + psys->recalc = 0; + return; } + /* fluid is also handled separate */ else if(part->type == PART_FLUID) { - particles_fluid_step(ob, psys, (int)cfra); + particles_fluid_step(ob, psys, framenr); psys->cfra = cfra; psys->recalc = 0; return; } - else if(ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) - ; /* cache shouldn't be used for "none" or "keyed" physics */ - else { - if(psys->recalc && (psys->flag & PSYS_PROTECT_CACHE) == 0) - clear_particles_from_cache(ob,psys,(int)cfra); - else if(get_particles_from_cache(ob, psys, (int)cfra)) { - cached_step(ob,psmd,psys,cfra,vg_size); - psys->cfra=cfra; - psys->recalc = 0; - return; - } - } - /* if still here react to events */ + /* cache shouldn't be used for hair or "none" or "first keyed" physics */ + if(part->type == PART_HAIR || part->phystype == PART_PHYS_NO) + usecache= 0; + else if(part->type == PART_PHYS_KEYED && (psys->flag & PSYS_FIRST_KEYED)) + usecache= 0; + else if(BKE_ptcache_get_continue_physics()) + usecache= 0; + else + usecache= 1; - if(psys->recalc&PSYS_TYPE) { - /* system type has changed so set sensible defaults and clear non applicable flags */ - if(part->from == PART_FROM_PARTICLE) { - if(part->type != PART_REACTOR) - part->from = PART_FROM_FACE; - if(part->distr == PART_DISTR_GRID) - part->distr = PART_DISTR_JIT; + if(usecache) { + /* frame clamping */ + if(framenr < startframe) { + psys_reset(psys, PSYS_RESET_DEPSGRAPH); + psys->cfra = cfra; + psys->recalc = 0; + return; } - - if(psys->part->phystype != PART_PHYS_KEYED) - psys->flag &= ~PSYS_KEYED; - - if(part->type == PART_HAIR) { - part->draw_as = PART_DRAW_PATH; - part->rotfrom = PART_ROT_IINCR; + else if(framenr > endframe) { + framenr= endframe; } - else - free_hair(psys, 1); - - psys->softflag= 0; - psys->recalc &= ~PSYS_TYPE; - alloc = 1; - - /* this is a bad level call, but currently type change - * can happen after redraw, so force redraw from here */ - allqueue(REDRAWBUTSOBJECT, 0); } - else - oldtotpart = psys->totpart; + + /* verify if we need to reallocate */ + oldtotpart = psys->totpart; + oldtotchild = psys->totchild; if(part->distr == PART_DISTR_GRID) - totpart = part->grid_res * part->grid_res * part->grid_res; + totpart = part->grid_res*part->grid_res*part->grid_res; else totpart = psys->part->totpart; + totchild = get_psys_tot_child(psys); - if(oldtotpart != totpart || psys->recalc&PSYS_ALLOC || (psys->part->childtype && psys->totchild != get_psys_tot_child(psys))) + if(oldtotpart != totpart || (psys->part->childtype && oldtotchild != totchild)) { + realloc_particles(ob, psys, totpart); alloc = 1; + distr= 1; + init= 1; + } - if(alloc || psys->recalc&PSYS_DISTR || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT) && ob==OBACT)) - distr = 1; - - if(distr || psys->recalc&PSYS_INIT) - init = 1; + if(psys->recalc & PSYS_DISTR) { + distr= 1; + init= 1; + } if(init) { if(distr) { if(alloc) - alloc_particles(ob, psys, totpart); + realloc_particles(ob, psys, totpart); distribute_particles(ob, psys, part->from); if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE)) - /* don't generate children while growing hair - waste of time */ - psys_free_children(psys); - else if(get_psys_tot_child(psys)) - distribute_particles(ob, psys, PART_FROM_CHILD); + /* don't generate children while growing hair - waste of time */ + psys_free_children(psys); + else if(get_psys_tot_child(psys)) + distribute_particles(ob, psys, PART_FROM_CHILD); } initialize_all_particles(ob, psys, psmd); @@ -4657,17 +4742,59 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier psmd->flag |= eParticleSystemFlag_Pars; } + /* try to read from the cache */ + if(usecache) { + if(get_particles_from_cache(ob, psys, framenr)) { + if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) { + psys_count_keyed_targets(ob,psys); + set_keyed_keys(ob, psys); + } + + cached_step(ob,psmd,psys,cfra); + psys->cfra=cfra; + psys->recalc = 0; + + if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) { + psys_update_path_cache(ob,psmd,psys,framenr); + } + + return; + } + else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { + psys_reset(psys, PSYS_RESET_DEPSGRAPH); + psys->cfra=cfra; + psys->recalc = 0; + return; + } + + if(framenr != startframe && framedelta != 1) { + psys_reset(psys, PSYS_RESET_DEPSGRAPH); + psys->cfra = cfra; + psys->recalc = 0; + return; + } + } + else { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; + } + + /* if on second frame, write cache for first frame */ + if(usecache && framenr == startframe+1) + write_particles_to_cache(ob, psys, startframe); if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) psys_count_keyed_targets(ob,psys); - if(part->from!=PART_FROM_PARTICLE){ - vg_vel=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_VEL); - vg_tan=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_TAN); - vg_rot=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROT); + /* initialize vertex groups */ + if(part->from!=PART_FROM_PARTICLE) { + vg_vel= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_VEL); + vg_tan= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_TAN); + vg_rot= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROT); + vg_size= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE); } - /* set particles to be not calculated */ + /* set particles to be not calculated TODO: can't work with pointcache */ disp= (float)get_current_display_percentage(psys)/50.0f-1.0f; for(p=0, pa=psys->particles; p<totpart; p++,pa++){ @@ -4680,15 +4807,16 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier /* ok now we're all set so let's go */ if(psys->totpart) dynamics_step(ob,psys,psmd,cfra,vg_vel,vg_tan,vg_rot,vg_size); + + cache->simframe= framenr; + cache->flag |= PTCACHE_SIMULATION_VALID; psys->recalc = 0; psys->cfra = cfra; - if(part->type == PART_HAIR || part->phystype == PART_PHYS_NO - || (part->phystype == PART_PHYS_KEYED && psys->flag & PSYS_FIRST_KEYED)) - ; /* cache shouldn't be used for hair or "none" or "first keyed" physics */ - else - write_particles_to_cache(ob, psys, cfra); + /* only write cache starting from second frame */ + if(usecache && framenr != startframe) + write_particles_to_cache(ob, psys, framenr); /* for keyed particles the path is allways known so it can be drawn */ if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED){ @@ -4698,9 +4826,11 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier else if(psys->pathcache) psys_free_path_cache(psys); + /* cleanup */ if(vg_vel) MEM_freeN(vg_vel); if(vg_tan) MEM_freeN(vg_tan); if(vg_rot) MEM_freeN(vg_rot); + if(vg_size) MEM_freeN(vg_size); if(psys->lattice){ end_latt_deform(); @@ -4708,106 +4838,97 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier } } -void psys_to_softbody(Object *ob, ParticleSystem *psys, int force_recalc) +void psys_to_softbody(Object *ob, ParticleSystem *psys) { SoftBody *sb; short softflag; - if((psys->softflag&OB_SB_ENABLE)==0) return; - - if(psys->recalc || force_recalc) - psys->softflag|=OB_SB_REDO; + if(!(psys->softflag & OB_SB_ENABLE)) + return; /* let's replace the object's own softbody with the particle softbody */ /* a temporary solution before cloth simulation is implemented, jahka */ /* save these */ - sb=ob->soft; - softflag=ob->softflag; + sb= ob->soft; + softflag= ob->softflag; /* swich to new ones */ - ob->soft=psys->soft; - ob->softflag=psys->softflag; + ob->soft= psys->soft; + ob->softflag= psys->softflag; /* do softbody */ sbObjectStep(ob, (float)G.scene->r.cfra, NULL, psys_count_keys(psys)); /* return things back to normal */ - psys->soft=ob->soft; - psys->softflag=ob->softflag; + psys->soft= ob->soft; + psys->softflag= ob->softflag; - ob->soft=sb; - ob->softflag=softflag; + ob->soft= sb; + ob->softflag= softflag; } + static int hair_needs_recalc(ParticleSystem *psys) { - if((psys->flag & PSYS_EDITED)==0 && ( - (psys->flag & PSYS_HAIR_DONE)==0 - || psys->recalc & PSYS_RECALC_HAIR) - ) { + if((psys->flag & PSYS_EDITED)==0 && + ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_HAIR)) { psys->recalc &= ~PSYS_RECALC_HAIR; return 1; } return 0; } -/* main particle update call, checks that things are ok on the large scale before actual particle calculations */ -void particle_system_update(Object *ob, ParticleSystem *psys){ - ParticleSystemModifierData *psmd=0; +/* main particle update call, checks that things are ok on the large scale before actual particle calculations */ +void particle_system_update(Object *ob, ParticleSystem *psys) +{ + ParticleSystemModifierData *psmd; float cfra; if(!psys_check_enabled(ob, psys)) return; - cfra=bsystem_time(ob,(float)CFRA,0.0); + cfra= bsystem_time(ob, CFRA, 0.0f); psmd= psys_get_modifier(ob, psys); /* system was already updated from modifier stack */ - if(psmd->flag&eParticleSystemFlag_psys_updated) { + if(psmd->flag & eParticleSystemFlag_psys_updated) { psmd->flag &= ~eParticleSystemFlag_psys_updated; /* make sure it really was updated to cfra */ - if(psys->cfra==cfra) + if(psys->cfra == cfra) return; } if(!psmd->dm) return; - /* baked path softbody */ - if(psys->part->type==PART_HAIR && psys->soft) - psys_to_softbody(ob, psys, 0); - - /* not needed, this is all handled in hair_step */ - ///* is the mesh changing under the edited particles? */ - //if((psys->flag & PSYS_EDITED) && psys->part->type==PART_HAIR && psys->recalc & PSYS_RECALC_HAIR) { - // /* Just update the particles on the mesh */ - // psys_update_edithair_dmfaces(ob, psmd->dm, psys); - //} - - if(psys->part->type==PART_HAIR && hair_needs_recalc(psys)){ + /* (re-)create hair */ + if(psys->part->type==PART_HAIR && hair_needs_recalc(psys)) { float hcfra=0.0f; int i; free_hair(psys, 0); /* first step is negative so particles get killed and reset */ - psys->cfra=1.0f; + psys->cfra= 1.0f; for(i=0; i<=psys->part->hair_step; i++){ hcfra=100.0f*(float)i/(float)psys->part->hair_step; - system_step(ob,psys,psmd,hcfra); - save_hair(ob,psys,psmd,hcfra); + system_step(ob, psys, psmd, hcfra); + save_hair(ob, psys, psmd, hcfra); } psys->flag |= PSYS_HAIR_DONE; - - if(psys->softflag&OB_SB_ENABLE) - psys_to_softbody(ob,psys,1); } - system_step(ob,psys,psmd,cfra); + /* handle softbody hair */ + if(psys->part->type==PART_HAIR && psys->soft) + psys_to_softbody(ob, psys); + + /* the main particle system step */ + system_step(ob, psys, psmd, cfra); - Mat4Invert(psys->imat, ob->obmat); /* used for duplicators */ + /* save matrix for duplicators */ + Mat4Invert(psys->imat, ob->obmat); } diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index cdb95e2f015..3b411e758c0 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -27,21 +27,36 @@ * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ - #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/stat.h> #include <sys/types.h> -#include "BKE_pointcache.h" +#include "MEM_guardedalloc.h" -#include "BKE_utildefines.h" -#include "BKE_global.h" -#include "BKE_library.h" +#include "DNA_ID.h" +#include "DNA_cloth_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_particle_types.h" +#include "DNA_scene_types.h" #include "BLI_blenlib.h" + +#include "BKE_cloth.h" +#include "BKE_depsgraph.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_modifier.h" +#include "BKE_object.h" +#include "BKE_particle.h" +#include "BKE_pointcache.h" +#include "BKE_softbody.h" #include "BKE_utildefines.h" + #include "blendef.h" /* needed for directory lookup */ @@ -58,19 +73,114 @@ #include <unistd.h> #endif +/* Creating ID's */ + +void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) +{ + ParticleSystemModifierData *psmd; + ModifierData *md; + int a; + + memset(pid, 0, sizeof(PTCacheID)); + + pid->ob= ob; + pid->data= sb; + pid->type= PTCACHE_TYPE_SOFTBODY; + pid->cache= sb->pointcache; + + if(sb->particles) { + psmd= psys_get_modifier(ob, sb->particles); + pid->stack_index= modifiers_indexInObject(ob, (ModifierData*)psmd); + } + else { + for(a=0, md=ob->modifiers.first; md; md=md->next, a++) { + if(md->type == eModifierType_Softbody) { + pid->stack_index = a; + break; + } + } + } +} + +void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys) +{ + ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys); + + memset(pid, 0, sizeof(PTCacheID)); + + pid->ob= ob; + pid->data= psys; + pid->type= PTCACHE_TYPE_PARTICLES; + pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)psmd); + pid->cache= psys->pointcache; +} + +void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd) +{ + memset(pid, 0, sizeof(PTCacheID)); + + pid->ob= ob; + pid->data= clmd; + pid->type= PTCACHE_TYPE_CLOTH; + pid->stack_index= modifiers_indexInObject(ob, (ModifierData *)clmd); + pid->cache= clmd->point_cache; +} + +void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob) +{ + PTCacheID *pid; + ParticleSystem *psys; + ModifierData *md; + + lb->first= lb->last= NULL; + + if(ob->soft) { + pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); + BKE_ptcache_id_from_softbody(pid, ob, ob->soft); + BLI_addtail(lb, pid); + } + + for(psys=ob->particlesystem.first; psys; psys=psys->next) { + pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); + BKE_ptcache_id_from_particles(pid, ob, psys); + BLI_addtail(lb, pid); + + if(psys->soft) { + pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); + BKE_ptcache_id_from_softbody(pid, ob, psys->soft); + BLI_addtail(lb, pid); + } + } + + for(md=ob->modifiers.first; md; md=md->next) { + if(md->type == eModifierType_Cloth) { + pid= MEM_callocN(sizeof(PTCacheID), "PTCacheID"); + BKE_ptcache_id_from_cloth(pid, ob, (ClothModifierData*)md); + BLI_addtail(lb, pid); + } + } +} + /* Takes an Object ID and returns a unique name - id: object id - cfra: frame for the cache, can be negative - stack_index: index in the modifier stack. we can have cache for more then one stack_index */ -static int ptcache_path(char *filename) +static int ptcache_path(PTCacheID *pid, char *filename) { + Library *lib; int i; - if (G.relbase_valid) { + + lib= (pid)? pid->ob->id.lib: NULL; + + if (G.relbase_valid || lib) { char dir[FILE_MAX], file[FILE_MAX]; /* we dont want the dir, only the file */ - - BLI_split_dirfile(G.sce, dir, file); + char *blendfilename; + + blendfilename= (lib)? lib->filename: G.sce; + + BLI_split_dirfile(blendfilename, dir, file); i = strlen(file); /* remove .blend */ @@ -78,7 +188,7 @@ static int ptcache_path(char *filename) file[i-6] = '\0'; sprintf(filename, "//"PTCACHE_PATH"%s/", file); /* add blend file name to pointcache dir */ - BLI_convertstringcode(filename, G.sce, 0); + BLI_convertstringcode(filename, blendfilename, 0); return strlen(filename); } @@ -87,7 +197,7 @@ static int ptcache_path(char *filename) return sprintf(filename, "%s"PTCACHE_PATH"%d/", btempdir, abs(getpid())); } -int BKE_ptcache_id_filename(struct ID *id, char *filename, int cfra, int stack_index, short do_path, short do_ext) +static int BKE_ptcache_id_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext) { int len=0; char *idname; @@ -99,10 +209,10 @@ int BKE_ptcache_id_filename(struct ID *id, char *filename, int cfra, int stack_i /* start with temp dir */ if (do_path) { - len = ptcache_path(filename); + len = ptcache_path(pid, filename); newname += len; } - idname = (id->name+2); + idname = (pid->ob->id.name+2); /* convert chars to hex so they are always a valid filename */ while('\0' != *idname) { sprintf(newname, "%02X", (char)(*idname++)); @@ -111,7 +221,7 @@ int BKE_ptcache_id_filename(struct ID *id, char *filename, int cfra, int stack_i } if (do_ext) { - sprintf(newname, "_%06d_%02d"PTCACHE_EXT, cfra, stack_index); /* always 6 chars */ + sprintf(newname, "_%06d_%02d"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */ len += 16; } @@ -119,31 +229,53 @@ int BKE_ptcache_id_filename(struct ID *id, char *filename, int cfra, int stack_i } /* youll need to close yourself after! */ -FILE *BKE_ptcache_id_fopen(struct ID *id, char mode, int cfra, int stack_index) +PTCacheFile *BKE_ptcache_file_open(PTCacheID *pid, int mode, int cfra) { - /* mode is same as fopen's modes */ + PTCacheFile *pf; FILE *fp = NULL; char filename[(FILE_MAXDIR+FILE_MAXFILE)*2]; + /* don't allow writing for linked objects */ + if(pid->ob->id.lib && mode == PTCACHE_FILE_WRITE) + return NULL; + /*if (!G.relbase_valid) return NULL; *//* save blend file before using pointcache */ - BKE_ptcache_id_filename(id, filename, cfra, stack_index, 1, 1); + BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); - if (mode=='r') { + if (mode==PTCACHE_FILE_READ) { if (!BLI_exists(filename)) { return NULL; } fp = fopen(filename, "rb"); - } else if (mode=='w') { + } else if (mode==PTCACHE_FILE_WRITE) { BLI_make_existing_file(filename); /* will create the dir if needs be, same as //textures is created */ fp = fopen(filename, "wb"); } - if (!fp) { + if (!fp) return NULL; - } + + pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile"); + pf->fp= fp; - return fp; + return pf; +} + +void BKE_ptcache_file_close(PTCacheFile *pf) +{ + fclose(pf->fp); + MEM_freeN(pf); +} + +int BKE_ptcache_file_read_floats(PTCacheFile *pf, float *f, int tot) +{ + return (fread(f, sizeof(float), tot, pf->fp) == tot); +} + +int BKE_ptcache_file_write_floats(PTCacheFile *pf, float *f, int tot) +{ + return (fwrite(f, sizeof(float), tot, pf->fp) == tot); } /* youll need to close yourself after! @@ -151,7 +283,7 @@ FILE *BKE_ptcache_id_fopen(struct ID *id, char mode, int cfra, int stack_index) */ -void BKE_ptcache_id_clear(struct ID *id, char mode, int cfra, int stack_index) +void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) { int len; /* store the length of the string */ @@ -161,7 +293,14 @@ void BKE_ptcache_id_clear(struct ID *id, char mode, int cfra, int stack_index) char path[FILE_MAX]; char filename[(FILE_MAXDIR+FILE_MAXFILE)*2]; char path_full[(FILE_MAXDIR+FILE_MAXFILE)*2]; - + + if(!pid->cache) + return; + + /* don't allow clearing for linked objects */ + if(pid->ob->id.lib) + return; + /*if (!G.relbase_valid) return; *//* save blend file before using pointcache */ /* clear all files in the temp dir with the prefix of the ID and the ".bphys" suffix */ @@ -169,9 +308,9 @@ void BKE_ptcache_id_clear(struct ID *id, char mode, int cfra, int stack_index) case PTCACHE_CLEAR_ALL: case PTCACHE_CLEAR_BEFORE: case PTCACHE_CLEAR_AFTER: - ptcache_path(path); + ptcache_path(pid, path); - len = BKE_ptcache_id_filename(id, filename, cfra, stack_index, 0, 0); /* no path */ + len = BKE_ptcache_id_filename(pid, filename, cfra, 0, 0); /* no path */ dir = opendir(path); if (dir==NULL) @@ -206,22 +345,149 @@ void BKE_ptcache_id_clear(struct ID *id, char mode, int cfra, int stack_index) break; case PTCACHE_CLEAR_FRAME: - len = BKE_ptcache_id_filename(id, filename, cfra, stack_index, 1, 1); /* no path */ + len = BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); /* no path */ BLI_delete(filename, 0, 0); break; } - return; } -int BKE_ptcache_id_exist(struct ID *id, int cfra, int stack_index) +int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) { char filename[(FILE_MAXDIR+FILE_MAXFILE)*2]; + + if(!pid->cache) + return 0; - BKE_ptcache_id_filename(id, filename, cfra, stack_index, 1, 1); + BKE_ptcache_id_filename(pid, filename, cfra, 1, 1); return BLI_exists(filename); } +void BKE_ptcache_id_time(PTCacheID *pid, float cfra, int *startframe, int *endframe, float *timescale) +{ + Object *ob; + PointCache *cache; + float offset, time, nexttime; + + /* 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 + * that's always the same and can't be animated. a timeoffset which + * varies over time is not simpe to support. + * - field and motion blur offsets are currently ignored, proper solution + * is probably to interpolate results from two frames for that .. + */ + + ob= pid->ob; + cache= pid->cache; + + if(timescale) { + time= bsystem_time(ob, cfra, 0.0f); + nexttime= bsystem_time(ob, cfra+1.0f, 0.0f); + + *timescale= MAX2(nexttime - time, 0.0f); + } + + if(startframe && endframe) { + *startframe= cache->startframe; + *endframe= cache->endframe; + + if ((ob->ipoflag & OB_OFFS_PARENT) && (ob->partype & PARSLOW)==0) { + offset= give_timeoffset(ob); + + *startframe += (int)(offset+0.5f); + *endframe += (int)(offset+0.5f); + } + } +} + +int BKE_ptcache_id_reset(PTCacheID *pid, int mode) +{ + PointCache *cache; + int reset, clear; + + if(!pid->cache) + return 0; + + cache= pid->cache; + reset= 0; + clear= 0; + + if(mode == PTCACHE_RESET_DEPSGRAPH) { + if(!(cache->flag & PTCACHE_BAKED) && !BKE_ptcache_get_continue_physics()) { + reset= 1; + clear= 1; + } + else + cache->flag |= PTCACHE_OUTDATED; + } + else if(mode == PTCACHE_RESET_BAKED) { + if(!BKE_ptcache_get_continue_physics()) { + reset= 1; + clear= 1; + } + else + cache->flag |= PTCACHE_OUTDATED; + } + else if(mode == PTCACHE_RESET_OUTDATED) { + reset = 1; + + if(cache->flag & PTCACHE_OUTDATED) + if(!(cache->flag & PTCACHE_BAKED)) + clear= 1; + } + + if(reset) { + cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_SIMULATION_VALID); + cache->simframe= 0; + + if(pid->type == PTCACHE_TYPE_CLOTH) + cloth_free_modifier(pid->ob, pid->data); + else if(pid->type == PTCACHE_TYPE_SOFTBODY) + sbFreeSimulation(pid->data); + else if(pid->type == PTCACHE_TYPE_PARTICLES) + psys_reset(pid->data, PSYS_RESET_DEPSGRAPH); + } + if(clear) + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); + + return (reset || clear); +} + +int BKE_ptcache_object_reset(Object *ob, int mode) +{ + PTCacheID pid; + ParticleSystem *psys; + ModifierData *md; + int reset; + + reset= 0; + + if(ob->soft) { + BKE_ptcache_id_from_softbody(&pid, ob, ob->soft); + reset |= BKE_ptcache_id_reset(&pid, mode); + } + + for(psys=ob->particlesystem.first; psys; psys=psys->next) { + BKE_ptcache_id_from_particles(&pid, ob, psys); + reset |= BKE_ptcache_id_reset(&pid, mode); + + if(psys->soft) { + BKE_ptcache_id_from_softbody(&pid, ob, psys->soft); + reset |= BKE_ptcache_id_reset(&pid, mode); + } + } + + for(md=ob->modifiers.first; md; md=md->next) { + if(md->type == eModifierType_Cloth) { + BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md); + reset |= BKE_ptcache_id_reset(&pid, mode); + } + } + + return reset; +} + /* Use this when quitting blender, with unsaved files */ void BKE_ptcache_remove(void) { @@ -229,7 +495,7 @@ void BKE_ptcache_remove(void) char path_full[FILE_MAX]; int rmdir = 1; - ptcache_path(path); + ptcache_path(NULL, path); if (BLI_exists(path)) { /* TODO, Check with win32, probably needs last slash removed */ @@ -260,3 +526,58 @@ void BKE_ptcache_remove(void) BLI_delete(path, 1, 0); } } + +/* Continuous Interaction */ + +static int CONTINUE_PHYSICS = 0; + +void BKE_ptcache_set_continue_physics(int enable) +{ + Object *ob; + + if(CONTINUE_PHYSICS != enable) { + CONTINUE_PHYSICS = enable; + + if(CONTINUE_PHYSICS == 0) { + for(ob=G.main->object.first; ob; ob=ob->id.next) + if(BKE_ptcache_object_reset(ob, PTCACHE_RESET_OUTDATED)) + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + } + } +} + +int BKE_ptcache_get_continue_physics() +{ + return CONTINUE_PHYSICS; +} + +/* Point Cache */ + +PointCache *BKE_ptcache_add() +{ + PointCache *cache; + + cache= MEM_callocN(sizeof(PointCache), "PointCache"); + cache->startframe= 1; + cache->endframe= 250; + + return cache; +} + +void BKE_ptcache_free(PointCache *cache) +{ + MEM_freeN(cache); +} + +PointCache *BKE_ptcache_copy(PointCache *cache) +{ + PointCache *ncache; + + ncache= MEM_dupallocN(cache); + + ncache->flag= 0; + ncache->simframe= 0; + + return ncache; +} + diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index df6b0d37867..c7440f39a0c 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3219,105 +3219,66 @@ static void softbody_to_object(Object *ob, float (*vertexCos)[3], int numVerts, } } -void softbody_clear_cache(Object *ob, float framenr) +void sbWriteCache(Object *ob, int framenr) { - SoftBody *sb = ob->soft; - ModifierData *md = ob->modifiers.first; - int stack_index = -1; - int a; - - if(sb==NULL) return; - - if(sb->particles) - stack_index = modifiers_indexInObject(ob,(ModifierData*)psys_get_modifier(ob,sb->particles)); - else { - for(a=0; md; md=md->next, a++) { - if(md->type == eModifierType_Softbody) { - stack_index = a; - break; - } - } - } - - BKE_ptcache_id_clear((ID *)ob, PTCACHE_CLEAR_ALL, framenr, stack_index); -} -static void softbody_write_cache(Object *ob, float framenr) -{ - FILE *fp = NULL; - SoftBody *sb = ob->soft; + SoftBody *sb= ob->soft; BodyPoint *bp; - ModifierData *md = ob->modifiers.first; - int stack_index = -1; + PTCacheID pid; + PTCacheFile *pf; int a; - if(sb->totpoint == 0) return; - - if(sb->particles) - stack_index = modifiers_indexInObject(ob,(ModifierData*)psys_get_modifier(ob,sb->particles)); - else { - for(a=0; md; md=md->next, a++) { - if(md->type == eModifierType_Softbody) { - stack_index = a; - break; - } - } - } - - fp = BKE_ptcache_id_fopen((ID *)ob, 'w', framenr, stack_index); - if(!fp) return; + if(sb->totpoint == 0) + return; + BKE_ptcache_id_from_softbody(&pid, ob, sb); + pf= BKE_ptcache_file_open(&pid, PTCACHE_FILE_WRITE, framenr); + if(!pf) + return; + for(a=0, bp=sb->bpoint; a<sb->totpoint; a++, bp++) - fwrite(&bp->pos, sizeof(float), 3, fp); -/*write velocities too */ + BKE_ptcache_file_write_floats(pf, bp->pos, 3); + for(a=0, bp=sb->bpoint; a<sb->totpoint; a++, bp++) - fwrite(&bp->vec, sizeof(float), 3, fp); - - fclose(fp); + BKE_ptcache_file_write_floats(pf, bp->vec, 3); + + BKE_ptcache_file_close(pf); } + static int softbody_read_cache(Object *ob, float framenr) { - FILE *fp = NULL; - SoftBody *sb = ob->soft; + SoftBody *sb= ob->soft; BodyPoint *bp; - ModifierData *md = ob->modifiers.first; - int stack_index = -1; - int a, ret = 1; - - if(sb->totpoint == 0) return 0; + PTCacheID pid; + PTCacheFile *pf; + int a; + if(sb->totpoint == 0) + return 0; + + BKE_ptcache_id_from_softbody(&pid, ob, sb); + pf= BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, framenr); + if(!pf) + return 0; - if(sb->particles) - stack_index = modifiers_indexInObject(ob,(ModifierData*)psys_get_modifier(ob,sb->particles)); - else { - for(a=0; md; md=md->next, a++) { - if(md->type == eModifierType_Softbody) { - stack_index = a; - break; - } + for(a=0, bp=sb->bpoint; a<sb->totpoint; a++, bp++) { + if(!BKE_ptcache_file_read_floats(pf, bp->pos, 3)) { + BKE_ptcache_file_close(pf); + return 0; } } - fp = BKE_ptcache_id_fopen((ID *)ob, 'r', framenr, stack_index); - if(!fp) - ret = 0; - else { - for(a=0, bp=sb->bpoint; a<sb->totpoint; a++, bp++) - if(fread(&bp->pos, sizeof(float), 3, fp) != 3) { - ret = 0; - break; - } - /*read velocities too !*/ - for(a=0, bp=sb->bpoint; a<sb->totpoint; a++, bp++){ - if(fread(&bp->vec, sizeof(float), 3, fp) != 3) { - ret = 0; - break; - } - } - fclose(fp); + for(a=0, bp=sb->bpoint; a<sb->totpoint; a++, bp++) { + if(!BKE_ptcache_file_read_floats(pf, bp->vec, 3)) { + BKE_ptcache_file_close(pf); + return 0; + } } - return ret; + BKE_ptcache_file_close(pf); + + return 1; } + /* +++ ************ maintaining scratch *************** */ void sb_new_scratch(SoftBody *sb) { @@ -3376,6 +3337,9 @@ SoftBody *sbNew(void) /*todo backward file compat should set sb->shearstiff = 1.0f while reading old files*/ sb->shearstiff = 1.0f; sb->solverflags |= SBSO_OLDERR; + + sb->pointcache = BKE_ptcache_add(); + return sb; } @@ -3383,14 +3347,19 @@ SoftBody *sbNew(void) void sbFree(SoftBody *sb) { free_softbody_intern(sb); + BKE_ptcache_free(sb->pointcache); MEM_freeN(sb); } +void sbFreeSimulation(SoftBody *sb) +{ + free_softbody_intern(sb); +} /* makes totally fresh start situation */ void sbObjectToSoftbody(Object *ob) { - ob->softflag |= OB_SB_REDO; + //ob->softflag |= OB_SB_REDO; free_softbody_intern(ob->soft); } @@ -3414,323 +3383,406 @@ void sbSetInterruptCallBack(int (*f)(void)) SB_localInterruptCallBack = f; } - -/* simulates one step. framenr is in frames */ -void sbObjectStep(Object *ob, float framenr, float (*vertexCos)[3], int numVerts) +static void softbody_update_positions(Object *ob, SoftBody *sb, float (*vertexCos)[3], int numVerts) { - ParticleSystemModifierData *psmd=0; - ParticleData *pa=0; - SoftBody *sb; + ParticleSystemModifierData *psmd= NULL; + ParticleData *pa= NULL; HairKey *key= NULL; BodyPoint *bp; + float hairmat[4][4]; int a; - float dtime,ctime,forcetime; + + /* update the vertex locations */ + if(sb->particles) { + psmd= psys_get_modifier(ob,sb->particles); + pa= sb->particles->particles; + key= pa->hair; + + psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); + } + + for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) { + /* store where goals are now */ + VECCOPY(bp->origS, bp->origE); + /* copy the position of the goals at desired end time */ + if(sb->particles) { + if(key == pa->hair + pa->totkey) { + pa++; + key = pa->hair; + + psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); + } + VECCOPY(bp->origE, key->co); + Mat4MulVecfl(hairmat,bp->origE); + + key++; + } + else{ + VECCOPY(bp->origE, vertexCos[a]); + /* vertexCos came from local world, go global */ + Mat4MulVecfl(ob->obmat, bp->origE); + } + /* just to be save give bp->origT a defined value + will be calulated in interpolate_exciter()*/ + VECCOPY(bp->origT, bp->origE); + } +} + +static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int numVerts) +{ + ParticleSystemModifierData *psmd= NULL; + HairKey *key= NULL; + ParticleData *pa= NULL; + BodyPoint *bp; float hairmat[4][4]; + int a; - /* This part only sets goals and springs, based on original mesh/curve/lattice data. - Copying coordinates happens in next chunk by setting softbody flag OB_SB_RESET */ - /* remake softbody if: */ - if( (ob->softflag & OB_SB_REDO) || /* signal after weightpainting */ - (ob->soft==NULL) || /* just to be nice we allow full init */ - (ob->soft->bpoint==NULL) || /* after reading new file, or acceptable as signal to refresh */ - (numVerts!=ob->soft->totpoint) || /* should never happen, just to be safe */ - ((ob->softflag & OB_SB_EDGES) && !ob->soft->bspring && object_has_edges(ob))) /* happens when in UI edges was set */ - { - if(ob->soft && ob->soft->bpoint) /* don't clear on file load */ - softbody_clear_cache(ob, framenr); + if(sb->particles) { + psmd= psys_get_modifier(ob, sb->particles); + pa= sb->particles->particles; + key= pa->hair; - if(ob->soft->particles){ - particles_to_softbody(ob); + psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); + } + + for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) { + if(sb->particles) { + if(key == pa->hair + pa->totkey) { + pa++; + key = pa->hair; + + psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); + } + VECCOPY(bp->pos, key->co); + Mat4MulVecfl(hairmat, bp->pos); + key++; + } + else { + VECCOPY(bp->pos, vertexCos[a]); + Mat4MulVecfl(ob->obmat, bp->pos); /* yep, sofbody is global coords*/ } - else switch(ob->type) { + VECCOPY(bp->origS, bp->pos); + VECCOPY(bp->origE, bp->pos); + VECCOPY(bp->origT, bp->pos); + bp->vec[0]= bp->vec[1]= bp->vec[2]= 0.0f; + + /* the bp->prev*'s are for rolling back from a canceled try to propagate in time + adaptive step size algo in a nutshell: + 1. set sheduled time step to new dtime + 2. try to advance the sheduled time step, beeing optimistic execute it + 3. check for success + 3.a we 're fine continue, may be we can increase sheduled time again ?? if so, do so! + 3.b we did exceed error limit --> roll back, shorten the sheduled time and try again at 2. + 4. check if we did reach dtime + 4.a nope we need to do some more at 2. + 4.b yup we're done + */ + + VECCOPY(bp->prevpos, bp->pos); + VECCOPY(bp->prevvec, bp->vec); + VECCOPY(bp->prevdx, bp->vec); + VECCOPY(bp->prevdv, bp->vec); + } + + /* make a nice clean scratch struc */ + free_scratch(sb); /* clear if any */ + sb_new_scratch(sb); /* make a new */ + sb->scratch->needstobuildcollider=1; + + if((sb->particles)==0) { + /* copy some info to scratch */ + switch(ob->type) { case OB_MESH: - mesh_to_softbody(ob); + if (ob->softflag & OB_SB_FACECOLL) mesh_faces_to_scratch(ob); break; case OB_LATTICE: - lattice_to_softbody(ob); break; case OB_CURVE: case OB_SURF: - curve_surf_to_softbody(ob); break; default: - renew_softbody(ob, numVerts, 0); break; } - - /* still need to update to correct vertex locations, happens on next step */ - ob->softflag |= OB_SB_RESET; - ob->softflag &= ~OB_SB_REDO; } +} - sb= ob->soft; +static void softbody_step(Object *ob, SoftBody *sb, float dtime) +{ + /* the simulator */ + float forcetime; + double sct,sst=PIL_check_seconds_timer(); + ccd_update_deflector_hache(ob,sb->scratch->colliderhash); - /* still no points? go away */ - if(sb->totpoint==0) return; + if(sb->scratch->needstobuildcollider){ + if (query_external_colliders(ob)){ + ccd_build_deflector_hache(ob,sb->scratch->colliderhash); + } + sb->scratch->needstobuildcollider=0; + } + + if (sb->solver_ID < 2) { + /* special case of 2nd order Runge-Kutta type AKA Heun */ + int mid_flags=0; + float err = 0; + float forcetimemax = 1.0f; + float forcetimemin = 0.001f; + float timedone =0.0; /* how far did we get without violating error condition */ + /* loops = counter for emergency brake + * we don't want to lock up the system if physics fail + */ + int loops =0 ; + SoftHeunTol = sb->rklimit; /* humm .. this should be calculated from sb parameters and sizes */ + if (sb->minloops > 0) forcetimemax = 1.0f / sb->minloops; + + if (sb->maxloops > 0) forcetimemin = 1.0f / sb->maxloops; + + if(sb->solver_ID>0) mid_flags |= MID_PRESERVE; + + //forcetime = dtime; /* hope for integrating in one step */ + forcetime =forcetimemax; /* hope for integrating in one step */ + while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) ) + { + /* set goals in time */ + interpolate_exciter(ob,200,(int)(200.0*(timedone/dtime))); + + sb->scratch->flag &= ~SBF_DOFUZZY; + /* do predictive euler step */ + softbody_calc_forces(ob, forcetime,timedone/dtime,0); + softbody_apply_forces(ob, forcetime, 1, NULL,mid_flags); - if(sb->particles){ - psmd=psys_get_modifier(ob,sb->particles); - pa=sb->particles->particles; - } - /* checking time: */ + /* crop new slope values to do averaged slope step */ + softbody_calc_forces(ob, forcetime,timedone/dtime,0); + softbody_apply_forces(ob, forcetime, 2, &err,mid_flags); - ctime= bsystem_time(ob, framenr, 0.0); + softbody_apply_goalsnap(ob); + + if (err > SoftHeunTol) { /* error needs to be scaled to some quantity */ + + if (forcetime > forcetimemin){ + forcetime = MAX2(forcetime / 2.0f,forcetimemin); + softbody_restore_prev_step(ob); + //printf("down,"); + } + else { + timedone += forcetime; + } + } + else { + float newtime = forcetime * 1.1f; /* hope for 1.1 times better conditions in next step */ + + if (sb->scratch->flag & SBF_DOFUZZY){ + //if (err > SoftHeunTol/(2.0f*sb->fuzzyness)) { /* stay with this stepsize unless err really small */ + newtime = forcetime; + //} + } + else { + if (err > SoftHeunTol/2.0f) { /* stay with this stepsize unless err really small */ + newtime = forcetime; + } + } + timedone += forcetime; + newtime=MIN2(forcetimemax,MAX2(newtime,forcetimemin)); + //if (newtime > forcetime) printf("up,"); + if (forcetime > 0.0) + forcetime = MIN2(dtime - timedone,newtime); + else + forcetime = MAX2(dtime - timedone,newtime); + } + loops++; + if(sb->solverflags & SBSO_MONITOR ){ + sct=PIL_check_seconds_timer(); + if (sct-sst > 0.5f) printf("%3.0f%% \r",100.0f*timedone); + } + /* ask for user break */ + if (SB_localInterruptCallBack && SB_localInterruptCallBack()) break; - if (ob->softflag&OB_SB_RESET) { - dtime = 0.0; - } else { - dtime= ctime - sb->ctime; + } + /* move snapped to final position */ + interpolate_exciter(ob, 2, 2); + softbody_apply_goalsnap(ob); + + // if(G.f & G_DEBUG){ + if(sb->solverflags & SBSO_MONITOR ){ + if (loops > HEUNWARNLIMIT) /* monitor high loop counts */ + printf("\r needed %d steps/frame ",loops); + } + } + else if (sb->solver_ID == 2) + {/* do semi "fake" implicit euler */ + //removed + }/*SOLVER SELECT*/ + else if (sb->solver_ID == 4) + { + /* do semi "fake" implicit euler */ + }/*SOLVER SELECT*/ + else if (sb->solver_ID == 3){ + /* do "stupid" semi "fake" implicit euler */ + //removed - if(softbody_read_cache(ob, framenr)) { - if(sb->particles==0) - softbody_to_object(ob, vertexCos, numVerts, sb->local); - sb->ctime = ctime; - return; + }/*SOLVER SELECT*/ + else{ + printf("softbody no valid solver ID!"); + }/*SOLVER SELECT*/ + if(sb->plastic){ apply_spring_memory(ob);} + + if(sb->solverflags & SBSO_MONITOR ){ + sct=PIL_check_seconds_timer(); + if (sct-sst > 0.5f) printf(" solver time %f %s \r",sct-sst,ob->id.name); } +} - /* the simulator */ +/* simulates one step. framenr is in frames */ +void sbObjectStep(Object *ob, float cfra, float (*vertexCos)[3], int numVerts) +{ + ParticleSystemModifierData *psmd=0; + ParticleData *pa=0; + SoftBody *sb= ob->soft; + PointCache *cache; + PTCacheID pid; + float dtime, timescale; + int framedelta, framenr, startframe, endframe; - /* update the vertex locations */ - if (dtime!=0.0) { - if(sb->particles) { - pa=sb->particles->particles; - key = pa->hair; + cache= sb->pointcache; - psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); - } + framenr= (int)cfra; + framedelta= framenr - cache->simframe; - for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) { - /* store where goals are now */ - VECCOPY(bp->origS, bp->origE); - /* copy the position of the goals at desired end time */ - if(sb->particles) { - if(key == pa->hair + pa->totkey) { - pa++; - key = pa->hair; + BKE_ptcache_id_from_softbody(&pid, ob, sb); + BKE_ptcache_id_time(&pid, framenr, &startframe, &endframe, ×cale); - psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); - } - VECCOPY(bp->origE, key->co); - Mat4MulVecfl(hairmat,bp->origE); + /* check for changes in mesh, should only happen in case the mesh + * structure changes during an animation */ + if(sb->bpoint && numVerts != sb->totpoint) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; - key++; - } - else{ - VECCOPY(bp->origE, vertexCos[a]); - /* vertexCos came from local world, go global */ - Mat4MulVecfl(ob->obmat, bp->origE); - } - /* just to be save give bp->origT a defined value - will be calulated in interpolate_exciter()*/ - VECCOPY(bp->origT, bp->origE); - } + return; } - if((ob->softflag&OB_SB_RESET) || /* got a reset signal */ - (dtime<0.0) || /* back in time */ - (dtime>=9.9*G.scene->r.framelen) /* too far forward in time --> goals won't be accurate enough */ - ) - { - if(sb->particles) { - pa=sb->particles->particles; - key = pa->hair; - - psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); - } + /* clamp frame ranges */ + if(framenr < startframe) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; - for(a=0,bp=sb->bpoint; a<numVerts; a++, bp++) { - if(sb->particles) { - if(key == pa->hair + pa->totkey) { - pa++; - key = pa->hair; + return; + } + else if(framenr > endframe) { + framenr = endframe; + } - psys_mat_hair_to_global(ob, psmd->dm, sb->particles->part->from, pa, hairmat); - } - VECCOPY(bp->pos, key->co); - Mat4MulVecfl(hairmat, bp->pos); - key++; - } - else { - VECCOPY(bp->pos, vertexCos[a]); - Mat4MulVecfl(ob->obmat, bp->pos); /* yep, sofbody is global coords*/ - } - VECCOPY(bp->origS, bp->pos); - VECCOPY(bp->origE, bp->pos); - VECCOPY(bp->origT, bp->pos); - bp->vec[0]= bp->vec[1]= bp->vec[2]= 0.0f; - - /* the bp->prev*'s are for rolling back from a canceled try to propagate in time - adaptive step size algo in a nutshell: - 1. set sheduled time step to new dtime - 2. try to advance the sheduled time step, beeing optimistic execute it - 3. check for success - 3.a we 're fine continue, may be we can increase sheduled time again ?? if so, do so! - 3.b we did exceed error limit --> roll back, shorten the sheduled time and try again at 2. - 4. check if we did reach dtime - 4.a nope we need to do some more at 2. - 4.b yup we're done - */ + /* verify if we need to create the softbody data */ + if(sb->bpoint == NULL || + ((ob->softflag & OB_SB_EDGES) && !ob->soft->bspring && object_has_edges(ob))) { - VECCOPY(bp->prevpos, bp->pos); - VECCOPY(bp->prevvec, bp->vec); - VECCOPY(bp->prevdx, bp->vec); - VECCOPY(bp->prevdv, bp->vec); + if(sb->particles){ + particles_to_softbody(ob); } - /* make a nice clean scratch struc */ - free_scratch(sb); /* clear if any */ - sb_new_scratch(sb); /* make a new */ - sb->scratch->needstobuildcollider=1; - - if((sb->particles)==0) { - /* copy some info to scratch */ + else { switch(ob->type) { - case OB_MESH: - if (ob->softflag & OB_SB_FACECOLL) mesh_faces_to_scratch(ob); - break; - case OB_LATTICE: - break; - case OB_CURVE: - case OB_SURF: - break; - default: - break; + case OB_MESH: + mesh_to_softbody(ob); + break; + case OB_LATTICE: + lattice_to_softbody(ob); + break; + case OB_CURVE: + case OB_SURF: + curve_surf_to_softbody(ob); + break; + default: + renew_softbody(ob, numVerts, 0); + break; } } - ob->softflag &= ~OB_SB_RESET; + softbody_update_positions(ob, sb, vertexCos, numVerts); + softbody_reset(ob, sb, vertexCos, numVerts); } - else if(dtime>0.0) { - double sct,sst=PIL_check_seconds_timer(); - ccd_update_deflector_hache(ob,sb->scratch->colliderhash); + /* continue physics special case */ + if(BKE_ptcache_get_continue_physics()) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; - if(sb->scratch->needstobuildcollider){ - if (query_external_colliders(ob)){ - ccd_build_deflector_hache(ob,sb->scratch->colliderhash); - } - sb->scratch->needstobuildcollider=0; - } + /* do simulation */ + dtime = timescale; + softbody_update_positions(ob, sb, vertexCos, numVerts); + softbody_step(ob, sb, dtime); - if (sb->solver_ID < 2) { - /* special case of 2nd order Runge-Kutta type AKA Heun */ - int mid_flags=0; - float err = 0; - float forcetimemax = 1.0f; - float forcetimemin = 0.001f; - float timedone =0.0; /* how far did we get without violating error condition */ - /* loops = counter for emergency brake - * we don't want to lock up the system if physics fail - */ - int loops =0 ; - SoftHeunTol = sb->rklimit; /* humm .. this should be calculated from sb parameters and sizes */ - if (sb->minloops > 0) forcetimemax = 1.0f / sb->minloops; - - if (sb->maxloops > 0) forcetimemin = 1.0f / sb->maxloops; + if(sb->particles==0) + softbody_to_object(ob, vertexCos, numVerts, 0); - if(sb->solver_ID>0) mid_flags |= MID_PRESERVE; - - //forcetime = dtime; /* hope for integrating in one step */ - forcetime =forcetimemax; /* hope for integrating in one step */ - while ( (ABS(timedone) < ABS(dtime)) && (loops < 2000) ) - { - /* set goals in time */ - interpolate_exciter(ob,200,(int)(200.0*(timedone/dtime))); - - sb->scratch->flag &= ~SBF_DOFUZZY; - /* do predictive euler step */ - softbody_calc_forces(ob, forcetime,timedone/dtime,0); - softbody_apply_forces(ob, forcetime, 1, NULL,mid_flags); + return; + } + /* still no points? go away */ + if(sb->totpoint==0) return; - /* crop new slope values to do averaged slope step */ - softbody_calc_forces(ob, forcetime,timedone/dtime,0); - softbody_apply_forces(ob, forcetime, 2, &err,mid_flags); + if(sb->particles){ + psmd= psys_get_modifier(ob, sb->particles); + pa= sb->particles->particles; + } - softbody_apply_goalsnap(ob); - - if (err > SoftHeunTol) { /* error needs to be scaled to some quantity */ - - if (forcetime > forcetimemin){ - forcetime = MAX2(forcetime / 2.0f,forcetimemin); - softbody_restore_prev_step(ob); - //printf("down,"); - } - else { - timedone += forcetime; - } - } - else { - float newtime = forcetime * 1.1f; /* hope for 1.1 times better conditions in next step */ - - if (sb->scratch->flag & SBF_DOFUZZY){ - //if (err > SoftHeunTol/(2.0f*sb->fuzzyness)) { /* stay with this stepsize unless err really small */ - newtime = forcetime; - //} - } - else { - if (err > SoftHeunTol/2.0f) { /* stay with this stepsize unless err really small */ - newtime = forcetime; - } - } - timedone += forcetime; - newtime=MIN2(forcetimemax,MAX2(newtime,forcetimemin)); - //if (newtime > forcetime) printf("up,"); - if (forcetime > 0.0) - forcetime = MIN2(dtime - timedone,newtime); - else - forcetime = MAX2(dtime - timedone,newtime); - } - loops++; - if(sb->solverflags & SBSO_MONITOR ){ - sct=PIL_check_seconds_timer(); - if (sct-sst > 0.5f) printf("%3.0f%% \r",100.0f*timedone); - } - /* ask for user break */ - if (SB_localInterruptCallBack && SB_localInterruptCallBack()) break; + /* try to read from cache */ + if(softbody_read_cache(ob, framenr)) { + if(sb->particles==0) + softbody_to_object(ob, vertexCos, numVerts, sb->local); - } - /* move snapped to final position */ - interpolate_exciter(ob, 2, 2); - softbody_apply_goalsnap(ob); - - // if(G.f & G_DEBUG){ - if(sb->solverflags & SBSO_MONITOR ){ - if (loops > HEUNWARNLIMIT) /* monitor high loop counts */ - printf("\r needed %d steps/frame ",loops); - } - - } - else if (sb->solver_ID == 2) - {/* do semi "fake" implicit euler */ - //removed - }/*SOLVER SELECT*/ - else if (sb->solver_ID == 4) - { - /* do semi "fake" implicit euler */ - }/*SOLVER SELECT*/ - else if (sb->solver_ID == 3){ - /* do "stupid" semi "fake" implicit euler */ - //removed + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->simframe= framenr; - }/*SOLVER SELECT*/ - else{ - printf("softbody no valid solver ID!"); - }/*SOLVER SELECT*/ - if(sb->plastic){ apply_spring_memory(ob);} + return; + } + else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { + /* if baked and nothing in cache, do nothing */ + if(cache->flag & PTCACHE_SIMULATION_VALID) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; + } - if(sb->solverflags & SBSO_MONITOR ){ - sct=PIL_check_seconds_timer(); - if (sct-sst > 0.5f) printf(" solver time %f %s \r",sct-sst,ob->id.name); - } + return; } - if(sb->particles==0) - softbody_to_object(ob, vertexCos, numVerts, 0); - sb->ctime= ctime; + if(framenr == startframe) { + /* first frame, no simulation to do, just set the positions */ + softbody_update_positions(ob, sb, vertexCos, numVerts); + + 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) { + /* if on second frame, write cache for first frame */ + if(framenr == startframe+1) + sbWriteCache(ob, startframe); + + softbody_update_positions(ob, sb, vertexCos, numVerts); + + /* do simulation */ + cache->flag |= PTCACHE_SIMULATION_VALID; + cache->simframe= framenr; + + /* checking time: */ + dtime = framedelta*timescale; - softbody_write_cache(ob, framenr); + softbody_step(ob, sb, dtime); + + if(sb->particles==0) + softbody_to_object(ob, vertexCos, numVerts, 0); + + sbWriteCache(ob, framenr); + } + else { + /* time step backwards or too large forward - do nothing */ + if(cache->flag & PTCACHE_SIMULATION_VALID) { + cache->flag &= ~PTCACHE_SIMULATION_VALID; + cache->simframe= 0; + } + } } diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index e5b11412aa1..a9da0c9c738 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -333,7 +333,7 @@ int BLI_delete(char *file, int dir, int recursive) else { if (recursive) sprintf(str, "/bin/rm -rf \"%s\"", file); else if (dir) sprintf(str, "/bin/rmdir \"%s\"", file); - else sprintf(str, "/bin/rm -f \"%s\"", file); + else remove(file); //sprintf(str, "/bin/rm -f \"%s\"", file); return system(str); } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index b055e62cddb..7fe023c782d 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -134,6 +134,7 @@ #include "BKE_node.h" // for tree type defines #include "BKE_object.h" #include "BKE_particle.h" +#include "BKE_pointcache.h" #include "BKE_property.h" // for get_property #include "BKE_sca.h" // for init_actuator #include "BKE_scene.h" @@ -2529,6 +2530,12 @@ static void direct_link_material(FileData *fd, Material *ma) /* ************ READ PARTICLE SETTINGS ***************** */ +static void direct_link_pointcache(FileData *fd, PointCache *cache) +{ + cache->flag &= ~(PTCACHE_SIMULATION_VALID|PTCACHE_BAKE_EDIT_ACTIVE); + cache->simframe= 0; +} + static void lib_link_particlesettings(FileData *fd, Main *main) { ParticleSettings *part; @@ -2582,8 +2589,12 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles) } if(psys->particles && psys->particles->keys){ ParticleData *pa = psys->particles; - for(a=0; a<psys->totpart; a++, pa++) - pa->keys=newdataadr(fd,pa->keys); + for(a=0; a<psys->totpart; a++, pa++) { + pa->keys= NULL; + pa->totkey= 0; + } + + psys->flag &= ~PSYS_KEYED; } psys->child=newdataadr(fd,psys->child); psys->effectors.first=psys->effectors.last=0; @@ -2595,12 +2606,20 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles) sb->bpoint= NULL; // init pointers so it gets rebuilt nicely sb->bspring= NULL; sb->scratch= NULL; + + sb->pointcache= newdataadr(fd, sb->pointcache); + if(sb->pointcache) + direct_link_pointcache(fd, sb->pointcache); } psys->edit = 0; psys->pathcache = 0; psys->childcache = 0; psys->reactevents.first = psys->reactevents.last = 0; + + psys->pointcache= newdataadr(fd, psys->pointcache); + if(psys->pointcache) + direct_link_pointcache(fd, psys->pointcache); } return; } @@ -3009,8 +3028,8 @@ static void lib_link_object(FileData *fd, Main *main) } -static void direct_link_pose(FileData *fd, bPose *pose) { - +static void direct_link_pose(FileData *fd, bPose *pose) +{ bPoseChannel *pchan; if (!pose) @@ -3054,12 +3073,12 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) clmd->sim_parms= newdataadr(fd, clmd->sim_parms); clmd->coll_parms= newdataadr(fd, clmd->coll_parms); + clmd->point_cache= newdataadr(fd, clmd->point_cache); + + if(clmd->point_cache) + direct_link_pointcache(fd, clmd->point_cache); - if(clmd->sim_parms) - { - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_LOADED; - clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_EDITMODE; - + if(clmd->sim_parms) { if(clmd->sim_parms->presets > 10) clmd->sim_parms->presets = 0; } @@ -3245,6 +3264,10 @@ static void direct_link_object(FileData *fd, Object *ob) sb->keys[a]= newdataadr(fd, sb->keys[a]); } } + + sb->pointcache= newdataadr(fd, sb->pointcache); + if(sb->pointcache) + direct_link_pointcache(fd, sb->pointcache); } ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */ if(ob->fluidsimSettings) { @@ -6910,6 +6933,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main) Mesh *me; bNodeTree *ntree; Tex *tex; + ModifierData *md; + ParticleSystem *psys; /* unless the file was created 2.44.3 but not 2.45, update the constraints */ if ( !(main->versionfile==244 && main->subversionfile==3) && @@ -7034,6 +7059,27 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + /* add point caches */ + for(ob=main->object.first; ob; ob=ob->id.next) { + if(ob->soft && !ob->soft->pointcache) + ob->soft->pointcache= BKE_ptcache_add(); + + for(psys=ob->particlesystem.first; psys; psys=psys->next) { + if(psys->soft && !psys->soft->pointcache) + psys->soft->pointcache= BKE_ptcache_add(); + if(!psys->pointcache) + psys->pointcache= BKE_ptcache_add(); + } + + for(md=ob->modifiers.first; md; md=md->next) { + if(md->type==eModifierType_Cloth) { + ClothModifierData *clmd = (ClothModifierData*) md; + if(!clmd->point_cache) + clmd->point_cache= BKE_ptcache_add(); + } + } + } + /* Copy over old per-level multires vertex data into a single vertex array in struct Multires */ for(me = main->mesh.first; me; me=me->id.next) { @@ -7287,7 +7333,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) sb->keys = NULL; sb->totkey = 0; - ob->softflag &= ~OB_SB_BAKESET; } } } @@ -7311,7 +7356,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) sb->keys = NULL; sb->totkey = 0; - ob->softflag &= ~OB_SB_BAKESET; } /* convert old particles to new system */ @@ -7333,7 +7377,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) part->id.flag |= (ob->id.flag & LIB_NEEDLINK); psys->totpart=0; - psys->flag=PSYS_ENABLED|PSYS_CURRENT; + psys->flag= PSYS_ENABLED|PSYS_CURRENT; BLI_addtail(&ob->particlesystem, psys); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 6308f092044..269ea1e8e02 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -576,16 +576,11 @@ static void write_particlesystems(WriteData *wd, ListBase *particles) for(a=0; a<psys->totpart; a++, pa++) writestruct(wd, DATA, "HairKey", pa->totkey, pa->hair); } - - if(psys->particles->keys) { - ParticleData *pa = psys->particles; - - for(a=0; a<psys->totpart; a++, pa++) - writestruct(wd, DATA, "ParticleKey", pa->totkey, pa->keys); - } } if(psys->child) writestruct(wd, DATA, "ChildParticle", psys->totchild ,psys->child); writestruct(wd, DATA, "SoftBody", 1, psys->soft); + if(psys->soft) writestruct(wd, DATA, "PointCache", 1, psys->soft->pointcache); + writestruct(wd, DATA, "PointCache", 1, psys->pointcache); } } @@ -864,7 +859,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) writestruct(wd, DATA, "ClothSimSettings", 1, clmd->sim_parms); writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms); - + writestruct(wd, DATA, "PointCache", 1, clmd->point_cache); } else if (md->type==eModifierType_Collision) { @@ -930,6 +925,7 @@ static void write_objects(WriteData *wd, ListBase *idbase) writestruct(wd, DATA, "PartDeflect", 1, ob->pd); writestruct(wd, DATA, "SoftBody", 1, ob->soft); + if(ob->soft) writestruct(wd, DATA, "PointCache", 1, ob->soft->pointcache); writestruct(wd, DATA, "FluidsimSettings", 1, ob->fluidsimSettings); // NT write_particlesystems(wd, &ob->particlesystem); diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index b3e0e1a23e0..17a887e9cf4 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -295,13 +295,10 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_GROUP_RELINK 1460 #define B_OBJECT_IPOFLAG 1461 -#define B_BAKEABLE_CHANGE 1470 +#define B_BAKE_CACHE_CHANGE 1470 /* Cloth sim button defines */ -#define B_CLOTH_CLEARCACHEALL 1480 -#define B_CLOTH_CLEARCACHEFRAME 1481 -#define B_CLOTH_CHANGEPREROLL 1482 -#define B_CLOTH_RENEW 1483 +#define B_CLOTH_CHANGEPREROLL 1480 /* *********************** */ #define B_WORLDBUTS 1600 diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index b8a6ddddfa7..5f6aff096f2 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -32,7 +32,6 @@ #ifndef DNA_CLOTH_TYPES_H #define DNA_CLOTH_TYPES_H - /** * This struct contains all the global data required to run a simulation. * At the time of this writing, this structure contains data appropriate @@ -61,8 +60,8 @@ typedef struct ClothSimSettings float structural; /* Structural spring stiffness. */ float shear; /* Shear spring stiffness. */ float bending; /* Flexion spring stiffness. */ - float sim_time; - int flags; /* flags, see CSIMSETT_FLAGS enum above. */ + float padf; + int flags; /* flags, see CSIMSETT_FLAGS enum above. */ short solver_type; /* which solver should be used? txold */ short vgroup_bend; /* vertex group for scaling bending stiffness */ float maxgoal; /* see SB */ @@ -74,21 +73,14 @@ typedef struct ClothSimSettings int goalfrict; float goalspring; int maxspringlen; /* in percent!; if tearing enabled, a spring will get cut */ - int lastframe; /* frame on which simulation stops */ - int firstframe; /* frame on which simulation starts */ - int lastcachedframe; - int editedframe; /* which frame is in buffer */ - int autoprotect; /* starting from this frame, cache gets protected */ float max_bend; /* max bending scaling value, min is "bending" */ float max_struct; /* max structural scaling value, min is "structural" */ float max_shear; /* max shear scaling value, UNUSED */ - int firstcachedframe; float avg_spring_len; /* used for normalized springs */ short presets; /* used for presets on GUI */ short pad; float timescale; /* parameter how fast cloth runs */ -} -ClothSimSettings; +} ClothSimSettings; typedef struct ClothCollSettings @@ -101,9 +93,7 @@ typedef struct ClothCollSettings struct LinkNode *collision_list; /* e.g. pointer to temp memory for collisions */ int flags; /* collision flags defined in BKE_cloth.h */ float selfepsilon; /* for selfcollision */ -} -ClothCollSettings; - +} ClothCollSettings; /** * This structure describes a cloth object against which the @@ -130,7 +120,6 @@ typedef struct Cloth struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ struct Implicit_Data *implicitEM; /* our implicit solver connects to this pointer */ struct EdgeHash *edgehash; /* used for selfcollisions */ -} -Cloth; +} Cloth; #endif diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index c62d012643a..b7b43817474 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -371,6 +371,7 @@ typedef struct ClothModifierData { struct Cloth *clothObject; /* The internal data structure for cloth. */ struct ClothSimSettings *sim_parms; /* definition is in DNA_cloth_types.h */ struct ClothCollSettings *coll_parms; /* definition is in DNA_cloth_types.h */ + struct PointCache *point_cache; /* definition is in DNA_object_force.h */ } ClothModifierData; typedef struct CollisionModifierData { diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index 70e0e91eca6..192c74283f9 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -72,6 +72,13 @@ typedef struct PartDeflect { struct Tex *tex; /* Texture of the texture effector */ } PartDeflect; +typedef struct PointCache { + int flag; /* generic flag */ + int simframe; /* current frame of simulation (only if SIMULATION_VALID) */ + int startframe; /* simulation start frame */ + int endframe; /* simulation end frame */ + int editframe; /* frame being edited (runtime only) */ +} PointCache; typedef struct SBVertex { float vec[4]; @@ -84,7 +91,7 @@ typedef struct SoftBody { int totpoint, totspring; struct BodyPoint *bpoint; /* not saved in file */ struct BodySpring *bspring; /* not saved in file */ - float ctime; /* last time calculated */ + float pad; /* part of UI: */ @@ -137,6 +144,8 @@ typedef struct SoftBody { float shearstiff; float inpush; + struct PointCache *pointcache; + } SoftBody; /* pd->forcefield: Effector Fields types */ @@ -177,21 +186,29 @@ typedef struct SoftBody { #define PFIELD_TEX_GRAD 1 #define PFIELD_TEX_CURL 2 +/* pointcache->flag */ +#define PTCACHE_BAKED 1 +#define PTCACHE_OUTDATED 2 +#define PTCACHE_SIMULATION_VALID 4 +#define PTCACHE_BAKING 8 +#define PTCACHE_BAKE_EDIT 16 +#define PTCACHE_BAKE_EDIT_ACTIVE 32 + /* ob->softflag */ #define OB_SB_ENABLE 1 #define OB_SB_GOAL 2 #define OB_SB_EDGES 4 #define OB_SB_QUADS 8 #define OB_SB_POSTDEF 16 -#define OB_SB_REDO 32 -#define OB_SB_BAKESET 64 -#define OB_SB_BAKEDO 128 -#define OB_SB_RESET 256 +// #define OB_SB_REDO 32 +// #define OB_SB_BAKESET 64 +// #define OB_SB_BAKEDO 128 +// #define OB_SB_RESET 256 #define OB_SB_SELF 512 #define OB_SB_FACECOLL 1024 #define OB_SB_EDGECOLL 2048 #define OB_SB_COLLFINAL 4096 -#define OB_SB_PROTECT_CACHE 8192 +//#define OB_SB_PROTECT_CACHE 8192 #define OB_SB_AERO_ANGLE 16384 /* sb->solverflags */ diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 2203de1c862..d2f27665862 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -206,6 +206,9 @@ typedef struct ParticleSystem{ /* temporary storage during render */ void *renderdata; + + /* point cache */ + struct PointCache *pointcache; }ParticleSystem; /* general particle maximums */ @@ -387,7 +390,7 @@ typedef struct ParticleSystem{ //#define PSYS_BAKING 2 //#define PSYS_BAKE_UI 4 #define PSYS_KEYED_TIME 8 -#define PSYS_ENABLED 16 +#define PSYS_ENABLED 16 /* deprecated */ #define PSYS_FIRST_KEYED 32 #define PSYS_DRAWING 64 //#define PSYS_SOFT_BAKE 128 @@ -395,7 +398,8 @@ typedef struct ParticleSystem{ #define PSYS_HAIR_DONE 512 #define PSYS_KEYED 1024 #define PSYS_EDITED 2048 -#define PSYS_PROTECT_CACHE 4096 +//#define PSYS_PROTECT_CACHE 4096 +#define PSYS_DISABLED 8192 /* pars->flag */ #define PARS_UNEXIST 1 diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index f96a4fea891..9e49b3a5e0c 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -633,6 +633,7 @@ typedef struct SpaceImaSel { #define TIME_WITH_SEQ_AUDIO 16 #define TIME_SEQ 32 #define TIME_ALL_IMAGE_WIN 64 +#define TIME_CONTINUE_PHYSICS 128 /* sseq->mainb */ #define SEQ_DRAW_SEQUENCE 0 diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 144b266759d..80ca4db9cac 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -930,7 +930,6 @@ void do_modifier_panels(unsigned short event) break; case B_MODIFIER_RECALC: - ob->softflag |= OB_SB_RESET; allqueue(REDRAWBUTSEDIT, 0); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWIMAGE, 0); @@ -2230,11 +2229,11 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiButSetFunc(but, modifiers_reassignHook, ob, md); } } else if (md->type==eModifierType_Softbody) { - uiDefBut(block, LABEL, 1, "See Softbody panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, LABEL, 1, "See Soft Body panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); } else if (md->type==eModifierType_Cloth) { uiDefBut(block, LABEL, 1, "See Cloth panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); } else if (md->type==eModifierType_Collision) { - uiDefBut(block, LABEL, 1, "See Deflection panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); + uiDefBut(block, LABEL, 1, "See Collision panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); } else if (md->type==eModifierType_Boolean) { BooleanModifierData *bmd = (BooleanModifierData*) md; uiDefButI(block, MENU, B_MODIFIER_RECALC, "Operation%t|Intersect%x0|Union%x1|Difference%x2", lx,(cy-=19),buttonWidth,19, &bmd->operation, 0.0, 1.0, 0, 0, "Boolean operation to perform"); @@ -2444,17 +2443,17 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco } if (md->error) { - char str[512]; - - y -= 20; + y -= 6; uiBlockSetCol(block, color); /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */ uiDefBut(block, ROUNDBOX, 0, "", x-10, y, width, 20, NULL, 5.0, 0.0, 15, 40, ""); uiBlockSetCol(block, TH_AUTO); - sprintf(str, "Modifier Error: %s", md->error); - uiDefBut(block, LABEL, B_NOP, str, x+15, y+15, width-35, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); + uiDefIconBut(block,LABEL,B_NOP,ICON_ERROR, x-9, y,19,19, 0,0,0,0,0, ""); + uiDefBut(block, LABEL, B_NOP, md->error, x+5, y, width-15, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); + + y -= 18; } uiClearButLock(); @@ -2481,7 +2480,7 @@ static void editing_panel_modifiers(Object *ob) uiDefBlockBut(block, modifiers_add_menu, ob, "Add Modifier", 0, 190, 130, 20, "Add a new modifier"); sprintf(str, "To: %s", ob->id.name+2); - uiDefBut(block, LABEL, 1, str, 140, 190, 150, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited"); + uiDefBut(block, LABEL, 1, str, 140, 190, 160, 20, NULL, 0.0, 0.0, 0, 0, "Object whose modifier stack is being edited"); xco = 0; yco = 160; @@ -3708,11 +3707,6 @@ void do_latticebuts(unsigned short event) lt = ob->data; if(ob==G.obedit) resizelattice(editLatt, lt->opntsu, lt->opntsv, lt->opntsw, NULL); else resizelattice(ob->data, lt->opntsu, lt->opntsv, lt->opntsw, NULL); - ob->softflag |= OB_SB_REDO; - if(modifiers_isClothEnabled(ob)) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; - } DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); allqueue(REDRAWVIEW3D, 0); } @@ -3720,11 +3714,6 @@ void do_latticebuts(unsigned short event) if(ob) { lt = ob->data; resizelattice(ob->data, lt->opntsu, lt->opntsv, lt->opntsw, ob); - ob->softflag |= OB_SB_REDO; - if(modifiers_isClothEnabled(ob)) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; - } DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); allqueue(REDRAWVIEW3D, 0); } @@ -5032,7 +5021,7 @@ static void editing_panel_mesh_tools1(Object *ob, Mesh *me) block= uiNewBlock(&curarea->uiblocks, "editing_panel_mesh_tools1", UI_EMBOSS, UI_HELV, curarea->win); - if(uiNewPanel(curarea, block, "Mesh Tools 1", "Editing", 960, 0, 318, 204)==0) return; + if(uiNewPanel(curarea, block, "Mesh Tools More", "Editing", 960, 0, 318, 204)==0) return; uiBlockBeginAlign(block); uiDefBut(block, BUT,B_SELSWAP, "Select Swap", 955, 200, 106, 19, 0, 0, 0, 0, 0, "Selects unselected faces, and deselects selected faces (Ctrl+I)"); diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index c88f280f847..aeb94ff769c 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -54,6 +54,7 @@ #include "BKE_softbody.h" #include "BKE_utildefines.h" #include "BKE_particle.h" +#include "BKE_pointcache.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" @@ -2052,72 +2053,133 @@ void do_constraintbuts(unsigned short event) allqueue (REDRAWBUTSOBJECT, 0); } -void softbody_bake(Object *ob) +void pointcache_bake(PTCacheID *pid, int startframe) { Base *base; - SoftBody *sb; ScrArea *sa; + PointCache *cache; + ListBase pidlist; float frameleno= G.scene->r.framelen; - int cfrao= CFRA, sfra=100000, efra=0, didbreak =0; - + int cfrao= CFRA, didbreak =0, endframe, cstart, cend; G.scene->r.framelen= 1.0; // baking has to be in uncorrected time sbSetInterruptCallBack(blender_test_break); // make softbody module ESC aware G.afbreek=0; // init global break system - if(ob) { - sb= ob->soft; - sfra= MIN2(sfra, sb->sfra); - efra= MAX2(efra, sb->efra); - sbObjectToSoftbody(ob); // put softbody in restposition, free bake - ob->softflag |= OB_SB_BAKEDO; + if(pid) { + cache= pid->cache; + + BKE_ptcache_id_time(pid, 0.0f, &cstart, &cend, NULL); + + startframe= startframe; + endframe= cend; + + cache->flag |= PTCACHE_BAKING; + cache->flag &= ~PTCACHE_BAKED; } else { + startframe= MAXFRAME; + endframe= 0; + for(base=G.scene->base.first; base; base= base->next) { if(TESTBASELIB(base)) { - if(base->object->soft) { - sb= base->object->soft; - sfra= MIN2(sfra, sb->sfra); - efra= MAX2(efra, sb->efra); - sbObjectToSoftbody(base->object); // put softbody in restposition, free bake - base->object->softflag |= OB_SB_BAKEDO; + BKE_ptcache_ids_from_object(&pidlist, base->object); + + for(pid=pidlist.first; pid; pid=pid->next) { + cache= pid->cache; + + BKE_ptcache_id_time(pid, 0.0f, &cstart, &cend, NULL); + + startframe= MIN2(startframe, cstart); + endframe= MAX2(endframe, cend); + + cache->flag |= PTCACHE_BAKING; + cache->flag &= ~PTCACHE_BAKED; } + + BLI_freelistN(&pidlist); } } } - CFRA= sfra; + CFRA= startframe; update_for_newframe_muted(); // put everything on this frame curarea->win_swap= 0; // clean swapbuffers - for(; CFRA <= efra; CFRA++) { + for(; CFRA <= endframe; CFRA++) { set_timecursor(CFRA); update_for_newframe_muted(); - for(sa= G.curscreen->areabase.first; sa; sa= sa->next) { - if(sa->spacetype == SPACE_VIEW3D) { + for(sa= G.curscreen->areabase.first; sa; sa= sa->next) + if(sa->spacetype == SPACE_VIEW3D) scrarea_do_windraw(sa); - } - } screen_swapbuffers(); + //blender_test_break() has a granularity of 10 ms, who cares .. baking the unit cube is kinda boring - if (blender_test_break()){ + if(blender_test_break()) { didbreak = 1; break; } + } + + if(didbreak && G.qual!=LR_SHIFTKEY) { + /* failed to bake, free the frames we baked */ + if(pid) { + cache= pid->cache; + + BKE_ptcache_id_time(pid, 0.0f, &cstart, &cend, NULL); + + cache->flag &= ~PTCACHE_BAKING; + if(startframe == cstart) + cache->flag &= ~PTCACHE_BAKED; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, startframe-1); + } + else { + for(base=G.scene->base.first; base; base= base->next) { + if(TESTBASELIB(base)) { + BKE_ptcache_ids_from_object(&pidlist, base->object); + for(pid=pidlist.first; pid; pid=pid->next) { + cache= pid->cache; + + BKE_ptcache_id_time(pid, 0.0f, &cstart, &cend, NULL); + + cache->flag &= ~PTCACHE_BAKING; + if(startframe == cstart) + cache->flag &= ~PTCACHE_BAKED; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, startframe-1); + } + + BLI_freelistN(&pidlist); + } + } + } } - if((didbreak)&&(G.qual!=LR_SHIFTKEY)) { - if(ob) - sbObjectToSoftbody(ob); // free bake + else { + /* succesfully finished baking */ + if(pid) { + cache= pid->cache; + + cache->flag &= ~PTCACHE_BAKING; + cache->flag |= PTCACHE_BAKED; + } else { for(base=G.scene->base.first; base; base= base->next) { if(TESTBASELIB(base)) { - if(base->object->soft) { - sbObjectToSoftbody(base->object); // free bake + BKE_ptcache_ids_from_object(&pidlist, base->object); + + for(pid=pidlist.first; pid; pid=pid->next) { + cache= pid->cache; + + cache->flag &= ~PTCACHE_BAKING; + cache->flag |= PTCACHE_BAKED; } + + BLI_freelistN(&pidlist); } } } @@ -2127,16 +2189,7 @@ void softbody_bake(Object *ob) waitcursor(0); sbSetInterruptCallBack(NULL); // softbody module won't ESC G.afbreek=0; // reset global break system - - if(ob) - ob->softflag &= ~OB_SB_BAKEDO; - else { - for(base=G.scene->base.first; base; base= base->next) - if(TESTBASELIB(base)) - if(base->object->soft) - base->object->softflag &= ~OB_SB_BAKEDO; - } - + CFRA= cfrao; G.scene->r.framelen= frameleno; update_for_newframe_muted(); @@ -2144,6 +2197,42 @@ void softbody_bake(Object *ob) allqueue(REDRAWBUTSOBJECT, 0); } +void pointcache_free(PTCacheID *pid, int cacheonly) +{ + Base *base; + ListBase pidlist; + + if(pid) { + if(cacheonly) + BKE_ptcache_id_reset(pid, PTCACHE_RESET_DEPSGRAPH); + else + BKE_ptcache_id_reset(pid, PTCACHE_RESET_BAKED); + + DAG_object_flush_update(G.scene, pid->ob, OB_RECALC_DATA); + } + else { + for(base=G.scene->base.first; base; base= base->next) { + if(TESTBASELIB(base)) { + BKE_ptcache_ids_from_object(&pidlist, base->object); + + for(pid=pidlist.first; pid; pid=pid->next) { + if(cacheonly) + BKE_ptcache_id_reset(pid, PTCACHE_RESET_DEPSGRAPH); + else + BKE_ptcache_id_reset(pid, PTCACHE_RESET_BAKED); + + DAG_object_flush_update(G.scene, pid->ob, OB_RECALC_DATA); + } + + BLI_freelistN(&pidlist); + } + } + } + + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSOBJECT, 0); +} + // store processed path & file prefix for fluidsim bake directory void fluidsimFilesel(char *selection) { @@ -2274,34 +2363,15 @@ void do_object_panels(unsigned short event) allqueue(REDRAWVIEW3D, 0); break; - case B_SOFTBODY_CHANGE: - ob= OBACT; - if(ob) { - ParticleSystem *psys = PE_get_current(ob); - if(psys) - psys->softflag |= OB_SB_REDO; - else - ob->softflag |= OB_SB_REDO; - allqueue(REDRAWBUTSOBJECT, 0); - allqueue(REDRAWVIEW3D, 0); - } - break; case B_SOFTBODY_DEL_VG: if(ob->soft) { ob->soft->vertgroup= 0; - ob->softflag |= OB_SB_REDO; + //ob->softflag |= OB_SB_REDO; + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); allqueue(REDRAWBUTSOBJECT, 0); allqueue(REDRAWVIEW3D, 0); } break; - case B_SOFTBODY_BAKE: - if(ob->soft) softbody_bake(ob); - break; - case B_SOFTBODY_BAKE_FREE: - if(ob->soft) sbObjectToSoftbody(ob); - allqueue(REDRAWBUTSOBJECT, 0); - allqueue(REDRAWVIEW3D, 0); - break; case B_FLUIDSIM_BAKE: /* write config files (currently no simulation) */ fluidsimBake(ob); @@ -2316,6 +2386,7 @@ void do_object_panels(unsigned short event) part->type = PART_FLUID; psys->part = part; + psys->pointcache = BKE_ptcache_add(); psys->flag |= PSYS_ENABLED; ob->fluidsimSettings->type = OB_FLUIDSIM_PARTICLE; @@ -2375,63 +2446,21 @@ void do_object_panels(unsigned short event) group_relink_nla_objects(ob); allqueue(REDRAWVIEW3D, 0); break; - case B_BAKEABLE_CHANGE: - allqueue(REDRAWBUTSOBJECT, 0); - allqueue(REDRAWVIEW3D, 0); - break; case B_OBJECT_IPOFLAG: if(ob->ipo) ob->ipo->showkey= (ob->ipoflag & OB_DRAWKEY)?1:0; allqueue(REDRAWVIEW3D, 0); break; - case B_CLOTH_CLEARCACHEALL: - { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - if(clmd) - { - // do nothing in editmode - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE) - break; - - /* force freeing because user wants */ - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; - - /*user wants to free all, so free whole cloth, this helps to start sim at later frame */ - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; - - CFRA= 1; - update_for_newframe_muted(); - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - cloth_clear_cache(ob, clmd, 0); - allqueue(REDRAWBUTSOBJECT, 0); - allqueue(REDRAWVIEW3D, 0); - } - } - break; - case B_CLOTH_CLEARCACHEFRAME: - { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - if(clmd) - { - // do nothing in editmode - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE) - break; - - /* force freeing because user wants */ - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; - - cloth_clear_cache(ob, clmd, MAX2(0.0,G.scene->r.cfra)); - // MAX2(1.0,G.scene->r.cfra + 1.0) - allqueue(REDRAWBUTSOBJECT, 0); - } - } - break; case B_CLOTH_CHANGEPREROLL: { ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) { + PTCacheID pid; + + BKE_ptcache_id_from_cloth(&pid, ob, clmd); + // do nothing in editmode - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE) + if(pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE) break; CFRA= 1; @@ -2442,17 +2471,11 @@ void do_object_panels(unsigned short event) } } break; - case B_CLOTH_RENEW: + case B_BAKE_CACHE_CHANGE: { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - - if(clmd) - { - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; - DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - allqueue(REDRAWBUTSOBJECT, 0); - allqueue(REDRAWVIEW3D, 0); - } + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + allqueue(REDRAWBUTSOBJECT, 0); + allqueue(REDRAWVIEW3D, 0); } break; @@ -2833,6 +2856,7 @@ void do_effects_panels(unsigned short event) ParticleSystemModifierData *psmd; ParticleSystem *psys; ParticleSettings *part; + LinkNode *node, *firstnode; ID *id,*idtest; int nr; @@ -3013,6 +3037,8 @@ void do_effects_panels(unsigned short event) short nr=0; if(id==0){ /* no psys previously -> no modifier -> need to create that also */ psys = MEM_callocN(sizeof(ParticleSystem), "particle_system"); + psys->pointcache = BKE_ptcache_add(); + psys->flag |= PSYS_ENABLED; BLI_addtail(&ob->particlesystem,psys); md= modifier_new(eModifierType_ParticleSystem); @@ -3025,7 +3051,7 @@ void do_effects_panels(unsigned short event) idtest->us++; psys->part=(ParticleSettings*)idtest; psys->totpart=0; - psys->flag=PSYS_ENABLED|PSYS_CURRENT; + psys->flag= PSYS_ENABLED|PSYS_CURRENT; psys->cfra=bsystem_time(ob,G.scene->r.cfra+1,0.0); /* check need for dupliobjects */ @@ -3094,6 +3120,27 @@ void do_effects_panels(unsigned short event) } } break; + + case B_PART_ALLOC: + case B_PART_DISTR: + case B_PART_INIT: + case B_PART_RECALC: + case B_PART_ALLOC_CHILD: + case B_PART_DISTR_CHILD: + case B_PART_INIT_CHILD: + case B_PART_RECALC_CHILD: + if(psys) { + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSOBJECT, 0); + } + break; + + /* there were separate update events before the pointcache refactor, + * now it only does a flush update which means it is recalculating + * more than strictly needed, but how to restore such partial updates + * i'm not sure - brecht. */ +#if 0 case B_PART_ALLOC: case B_PART_ALLOC_CHILD: if(psys){ @@ -3103,6 +3150,7 @@ void do_effects_panels(unsigned short event) allqueue(REDRAWOOPS, 0); } break; + case B_PART_DISTR: case B_PART_DISTR_CHILD: if(psys){ @@ -3129,13 +3177,8 @@ void do_effects_panels(unsigned short event) allqueue(REDRAWBUTSEDIT, 0); } break; - case B_PART_RECALC: - case B_PART_RECALC_CHILD: - if(psys){ - psys_flush_settings(psys->part,0,event==B_PART_RECALC); - allqueue(REDRAWOOPS, 0); - } /* no break! */ +#endif case B_PART_REDRAW_DEPS: if(event == B_PART_REDRAW_DEPS) DAG_scene_sort(G.scene); @@ -3155,13 +3198,17 @@ void do_effects_panels(unsigned short event) allqueue(REDRAWBUTSOBJECT, 0); break; case B_PARTTYPE: - if((psys=psys_get_current(ob))){ - DAG_scene_sort(G.scene); + if(psys) { + /* 1 = do DAG_object_flush_update */ + firstnode= psys_using_settings(psys->part, 1); - psys_flush_settings(psys->part,PSYS_TYPE,1); + for(node=firstnode; node; node=node->next) + psys_changed_type(node->link); + + BLI_linklist_free(firstnode, NULL); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWBUTSOBJECT, 0); } - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWBUTSOBJECT, 0); break; case B_PARTACT: allqueue(REDRAWVIEW3D, 0); @@ -3318,15 +3365,16 @@ static void object_collision__enabletoggle ( void *ob_v, void *arg2 ) } /* Panels for particle interaction settings */ -static void object_panel_deflection(Object *ob) +static void object_panel_collision(Object *ob) { uiBlock *block; uiBut *but; block= uiNewBlock(&curarea->uiblocks, "object_panel_deflection", UI_EMBOSS, UI_HELV, curarea->win); - if(uiNewPanel(curarea, block, "Deflection", "Physics", 0, 0, 318, 204)==0) return; + uiNewPanelTabbed("Fields", "Physics"); + if(uiNewPanel(curarea, block, "Collision", "Physics", 0, 0, 318, 204)==0) return; - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + uiSetButLock(object_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* should become button, option? */ if(ob->pd==NULL) { @@ -3341,27 +3389,33 @@ static void object_panel_deflection(Object *ob) if(ob->pd && ob->type==OB_MESH) { PartDeflect *pd= ob->pd; - but = uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",160,160,150,20, &pd->deflect, 0, 0, 0, 0, "Deflects particles based on collision"); + but = uiDefButBitS(block, TOG, 1, B_REDR, "Collision",10,160,150,20, &pd->deflect, 0, 0, 0, 0, "Enable this objects as a collider for physics systems"); uiButSetFunc(but, object_collision__enabletoggle, ob, NULL); + + uiDefBut(block, LABEL, 0, "",160,160,150,2, NULL, 0.0, 0, 0, 0, ""); if(pd->deflect) { - uiDefBut(block, LABEL, 0, "Particles", 160,140,75,20, NULL, 0.0, 0, 0, 0, ""); - uiDefButBitS(block, TOG, PDEFLE_KILL_PART, B_DIFF, "Kill",235,140,75,20, &pd->flag, 0, 0, 0, 0, "Kill collided particles"); + uiDefBut(block, LABEL, 0, "Particle Interaction", 10,135,310,20, NULL, 0.0, 0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_DIFF, "Damping: ", 160,120,75,20, &pd->pdef_damp, 0.0, 1.0, 10, 0, "Amount of damping during particle collision"); - uiDefButF(block, NUM, B_DIFF, "Rnd Damping: ", 235,120,75,20, &pd->pdef_rdamp, 0.0, 1.0, 10, 0, "Random variation of damping"); - uiDefButF(block, NUM, B_DIFF, "Friction: ", 160,100,75,20, &pd->pdef_frict, 0.0, 1.0, 10, 0, "Amount of friction during particle collision"); - uiDefButF(block, NUM, B_DIFF, "Rnd Friction: ", 235,100,75,20, &pd->pdef_rfrict, 0.0, 1.0, 10, 0, "Random variation of friction"); - uiDefButF(block, NUM, B_DIFF, "Permeability: ", 160,80,150,20, &pd->pdef_perm, 0.0, 1.0, 10, 0, "Chance that the particle will pass through the mesh"); + uiDefButF(block, NUM, B_FIELD_CHANGE, "Damping: ", 10,115,105,20, &pd->pdef_damp, 0.0, 1.0, 10, 2, "Amount of damping during particle collision"); + uiDefButF(block, NUM, B_FIELD_CHANGE, "Rnd: ", 115,115,75,20, &pd->pdef_rdamp, 0.0, 1.0, 10, 2, "Random variation of damping"); + uiDefButF(block, NUM, B_FIELD_CHANGE, "Friction: ", 10,95,105,20, &pd->pdef_frict, 0.0, 1.0, 10, 2, "Amount of friction during particle collision"); + uiDefButF(block, NUM, B_FIELD_CHANGE, "Rnd: ", 115,95,75,20, &pd->pdef_rfrict, 0.0, 1.0, 10, 2, "Random variation of friction"); uiBlockEndAlign(block); + + uiDefButBitS(block, TOG, PDEFLE_KILL_PART, B_FIELD_CHANGE, "Kill",200,115,120,20, &pd->flag, 0, 0, 0, 0, "Kill collided particles"); + uiDefButF(block, NUM, B_FIELD_CHANGE, "Permeability: ", 200,90,120,20, &pd->pdef_perm, 0.0, 1.0, 10, 2, "Chance that the particle will pass through the mesh"); - uiDefBut(block, LABEL, 0, "Soft Body / Cloth", 160,60,150,20, NULL, 0.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Soft Body and Cloth Interaction", 10,65,310,20, NULL, 0.0, 0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_FIELD_CHANGE, "Damping:", 160,40,150,20, &pd->pdef_sbdamp, 0.0, 1.0, 10, 0, "Amount of damping during soft body collision"); - uiDefButF(block, NUM, B_FIELD_CHANGE, "Inner:", 160,20,150,20, &pd->pdef_sbift, 0.001, 1.0, 10, 0, "Inner face thickness"); - uiDefButF(block, NUM, B_FIELD_CHANGE, "Outer:", 160, 0,150,20, &pd->pdef_sboft, 0.001, 1.0, 10, 0, "Outer face thickness"); + uiDefButF(block, NUM, B_FIELD_CHANGE, "Damping:", 10,45,150,20, &pd->pdef_sbdamp, 0.0, 1.0, 10, 0, "Amount of damping during collision"); + uiDefButF(block, NUM, B_FIELD_CHANGE, "Inner:", 10,25,150,20, &pd->pdef_sbift, 0.001, 1.0, 10, 0, "Inner face thickness"); + uiDefButF(block, NUM, B_FIELD_CHANGE, "Outer:", 10, 5,150,20, &pd->pdef_sboft, 0.001, 1.0, 10, 0, "Outer face thickness"); + uiBlockEndAlign(block); + + uiDefButBitS(block, TOG, OB_SB_COLLFINAL, B_FIELD_CHANGE, "Ev.M.Stack", 170,45,150,20, &ob->softflag, 0, 0, 0, 0, "Pick collision object from modifier stack (softbody only)"); } } } @@ -3373,10 +3427,9 @@ static void object_panel_fields(Object *ob) static short actpsys=-1; block= uiNewBlock(&curarea->uiblocks, "object_panel_fields", UI_EMBOSS, UI_HELV, curarea->win); - uiNewPanelTabbed("Deflection", "Physics"); if(uiNewPanel(curarea, block, "Fields", "Physics", 0, 0, 318, 204)==0) return; - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + uiSetButLock(object_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* should become button, option? */ if(ob->pd==NULL) { @@ -3391,6 +3444,8 @@ static void object_panel_fields(Object *ob) PartDeflect *pd= ob->pd; char *menustr= MEM_mallocN(256, "temp string"); char *tipstr="Choose field type"; + + uiBlockBeginAlign(block); if(ob->particlesystem.first) { ParticleSystem *psys; @@ -3443,6 +3498,9 @@ static void object_panel_fields(Object *ob) else uiDefButS(block, MENU, B_FIELD_DEP, menustr, 10,180,140,20, &pd->forcefield, 0.0, 0.0, 0, 0, tipstr); + uiBlockEndAlign(block); + uiDefBut(block, LABEL, 0, "",160,180,150,2, NULL, 0.0, 0, 0, 0, ""); + MEM_freeN(menustr); if(pd->forcefield) { @@ -3460,10 +3518,12 @@ static void object_panel_fields(Object *ob) uiDefButF(block, NUM, B_FIELD_CHANGE, "Strength: ", 10,140,140,20, &pd->f_strength, -1000, 1000, 10, 3, "Strength of force field"); if(pd->forcefield == PFIELD_TEXTURE){ - uiDefIDPoinBut(block, field_testTexture, ID_TE, B_FIELD_CHANGE, "Texture: ", 10, 120, 140, 20, &pd->tex, "Texture to use as force"); - uiDefButBitS(block, TOG, PFIELD_TEX_OBJECT, B_FIELD_CHANGE, "Use Object Co", 10,100,140,20, &pd->flag, 0.0, 0, 0, 0, "Use object/global coordinates for texture"); - uiDefButBitS(block, TOG, PFIELD_TEX_ROOTCO, B_FIELD_CHANGE, "Root TexCo", 10,80,120,20, &pd->flag, 0.0, 0, 0, 0, "Texture coords from root particle locations"); - uiDefButBitS(block, TOG, PFIELD_TEX_2D, B_FIELD_CHANGE, "2D", 130,80,20,20, &pd->flag, 0.0, 0, 0, 0, "Apply force only in 2d"); + uiDefIDPoinBut(block, field_testTexture, ID_TE, B_FIELD_CHANGE, "Texture: ", 10,120,140,20, &pd->tex, "Texture to use as force"); + uiBlockEndAlign(block); + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, PFIELD_TEX_OBJECT, B_FIELD_CHANGE, "Use Object Co", 10,95,140,20, &pd->flag, 0.0, 0, 0, 0, "Use object/global coordinates for texture"); + uiDefButBitS(block, TOG, PFIELD_TEX_ROOTCO, B_FIELD_CHANGE, "Root TexCo", 10,75,100,20, &pd->flag, 0.0, 0, 0, 0, "Texture coords from root particle locations"); + uiDefButBitS(block, TOG, PFIELD_TEX_2D, B_FIELD_CHANGE, "2D", 120,75,30,20, &pd->flag, 0.0, 0, 0, 0, "Apply force only in 2d"); } else if(pd->forcefield == PFIELD_HARMONIC) uiDefButF(block, NUM, B_FIELD_CHANGE, "Damp: ", 10,120,140,20, &pd->f_damp, 0, 10, 10, 0, "Damping of the harmonic force"); @@ -3475,13 +3535,13 @@ static void object_panel_fields(Object *ob) uiDefButBitS(block, TOG, PFIELD_GUIDE_PATH_ADD, B_FIELD_CHANGE, "Additive", 10,40,140,20, &pd->flag, 0.0, 0, 0, 0, "Based on distance/falloff it adds a portion of the entire path"); } else if(pd->forcefield==PFIELD_TEXTURE){ - uiDefButS(block, MENU, B_FIELD_CHANGE, "Texture mode%t|RGB%x0|Gradient%x1|Curl%x2", 10,40,140,20, &pd->tex_mode, 0.0, 0.0, 0, 0, "How the texture effect is calculated (RGB & Curl need a RGB texture else Gradient will be used instead)"); + uiDefButS(block, MENU, B_FIELD_CHANGE, "Texture mode%t|RGB%x0|Gradient%x1|Curl%x2", 10,50,140,20, &pd->tex_mode, 0.0, 0.0, 0, 0, "How the texture effect is calculated (RGB & Curl need a RGB texture else Gradient will be used instead)"); - uiDefButF(block, NUM, B_FIELD_CHANGE, "Nabla:", 10,20,140,20, &pd->tex_nabla, 0.0001f, 1.0, 1, 0, "Specify the dimension of the area for gradient and curl calculation"); + uiDefButF(block, NUM, B_FIELD_CHANGE, "Nabla:", 10,30,140,20, &pd->tex_nabla, 0.0001f, 1.0, 1, 0, "Specify the dimension of the area for gradient and curl calculation"); } else if(particles==0 && ELEM(pd->forcefield,PFIELD_VORTEX,PFIELD_WIND)==0){ //uiDefButF(block, NUM, B_FIELD_CHANGE, "Distance: ", 10,20,140,20, &pd->f_dist, 0, 1000.0, 10, 0, "Falloff power (real gravitational fallof = 2)"); - uiDefButBitS(block, TOG, PFIELD_PLANAR, B_FIELD_CHANGE, "Planar", 10,0,140,20, &pd->flag, 0.0, 0, 0, 0, "Create planar field"); + uiDefButBitS(block, TOG, PFIELD_PLANAR, B_FIELD_CHANGE, "Planar", 10,15,140,20, &pd->flag, 0.0, 0, 0, 0, "Create planar field"); } uiBlockEndAlign(block); @@ -3542,30 +3602,159 @@ static void object_panel_fields(Object *ob) } } +/* Generic physics baking buttons */ + +static void object_physics__baketoggle(void *pid_v, void *unused_v) +{ + PTCacheID *pid = pid_v; + Object *ob = pid->ob; + PointCache *cache = pid->cache; + ClothModifierData *clmd; + int cageIndex, stack_index, startframe, endframe; + + // automatically enable modifier in editmode when we have a protected cache + if(!(cache->flag & PTCACHE_BAKED)) { + BKE_ptcache_id_time(pid, 0.0f, &startframe, &endframe, NULL); + pointcache_bake(pid, startframe); + + if(pid->type == PTCACHE_TYPE_CLOTH) { + clmd= (ClothModifierData*)pid->data; + cageIndex = modifiers_getCageIndex(ob, NULL ); + stack_index = modifiers_indexInObject(ob, (ModifierData *)clmd); + if(stack_index >= cageIndex) + ((ModifierData *)clmd)->mode ^= eModifierMode_OnCage; + } + } + else { + if(cache->flag & PTCACHE_BAKE_EDIT_ACTIVE) { + notice("Can't free bake in editmode"); + } + else { + if(pid->type == PTCACHE_TYPE_CLOTH) { + clmd= (ClothModifierData*)pid->data; + ((ModifierData *)clmd)->mode ^= eModifierMode_OnCage; + } + + cache->flag &= ~PTCACHE_BAKED; + BKE_ptcache_id_reset(pid, PTCACHE_RESET_OUTDATED); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + } + } +} + +static void object_physics__rebake(void *pid_v, void *unused_v) +{ + PTCacheID *pid = pid_v; + int curframe = (int)G.scene->r.cfra; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, curframe); + pointcache_bake(pid, curframe); +} + +static void object_physics__clearcache(void *pid_v, void *unused_v) +{ + PTCacheID *pid = pid_v; + Object *ob = pid->ob; + PointCache *cache = pid->cache; + + if(cache->flag & PTCACHE_BAKE_EDIT_ACTIVE) + return; + + BKE_ptcache_id_reset(pid, PTCACHE_RESET_BAKED); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + + allqueue(REDRAWBUTSOBJECT, 0); + allqueue(REDRAWVIEW3D, 0); +} + +static void object_physics_bake_buttons(uiBlock *block, PTCacheID *pid, int y, int libdata) +{ + uiBut *but; + PointCache *cache; + + cache= pid->cache; + + if(!libdata && G.obedit) + uiSetButLock(1, "Can't change bake settings in editmode"); + + if(cache->flag & PTCACHE_BAKED) + but = uiDefBut(block, BUT, REDRAWBUTSOBJECT, "Free Bake", 10,y+25,85,20, NULL, 0.0, 0.0, 0, 0, "Free baked simulation"); + else + but = uiDefBut(block, BUT, REDRAWBUTSOBJECT, "Bake", 10,y+25,85,20, NULL, 0.0, 0.0, 0, 0, "Bake specified frame range"); + uiButSetFunc(but, object_physics__baketoggle, pid, NULL); + + if(!libdata && !G.obedit && (cache->flag & PTCACHE_BAKED)) + uiSetButLock(1, "Simulation frames are baked"); + + uiBlockBeginAlign(block); + uiDefButI(block, NUM, B_BAKE_CACHE_CHANGE, "Start:", 100,y+25,105,20, &cache->startframe, 1, MAXFRAME, 1, 0, "Frame on which the simulation starts"); + uiDefButI(block, NUM, B_BAKE_CACHE_CHANGE, "End:", 205,y+25,105,20, &cache->endframe, 1, MAXFRAME, 1, 0, "Frame on which the simulation stops"); + uiBlockEndAlign(block); + + if(cache->flag & PTCACHE_BAKED) { + if(pid->type == PTCACHE_TYPE_CLOTH || + (pid->type == PTCACHE_TYPE_SOFTBODY && !((SoftBody*)pid->data)->particles)) { + if(!libdata && !G.obedit) + uiClearButLock(); + + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, PTCACHE_BAKE_EDIT, REDRAWVIEW3D, "Bake Editing", 10,y,100,20, &cache->flag, 0, 0, 0, 0, "Enable editing of the baked results in editmode."); + but= uiDefBut(block, BUT, REDRAWBUTSOBJECT, "Rebake From Current Frame", 110,y,200,20, NULL, 0.0, 0.0, 0, 0, "Bake again from current frame"); + uiButSetFunc(but, object_physics__rebake, pid, NULL); + uiBlockEndAlign(block); + } + + if(!libdata) + uiClearButLock(); + } + else { + char str[512]; + int exist, startframe, endframe; + + if(!libdata) + uiClearButLock(); + + BKE_ptcache_id_time(pid, 0.0f, &startframe, &endframe, NULL); + exist= BKE_ptcache_id_exist(pid, startframe); + + sprintf(str, "%simulation frames in disk cache.", (exist)? "S": "No s"); + uiDefBut(block, LABEL, 0, str, 10,y,200,20, NULL, 0.0, 0, 0, 0, ""); + + if(exist) { + but= uiDefBut(block, BUT, REDRAWBUTSOBJECT, "Free Cache", 210,y,100,20, NULL, 0.0, 0.0, 0, 0, "Free cached simulation results"); + uiButSetFunc(but, object_physics__clearcache, pid, NULL); + } + } +} + /* Panel for softbodies */ static void object_softbodies__enable(void *ob_v, void *arg2) { Object *ob = ob_v; ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody); + PTCacheID pid; - if (modifiers_isSoftbodyEnabled(ob)) { - if (md) { - md->mode &= ~(eModifierMode_Render|eModifierMode_Realtime); - } - } else { - if (!md) { - md = modifier_new(eModifierType_Softbody); - BLI_addhead(&ob->modifiers, md); - } + if(md) { + BLI_remlink(&ob->modifiers, md); + modifier_free(md); + BIF_undo_push("Del modifier"); - md->mode |= eModifierMode_Render|eModifierMode_Realtime; + ob->softflag &= ~OB_SB_ENABLE; + } else { + md = modifier_new(eModifierType_Softbody); + BLI_addhead(&ob->modifiers, md); if (!ob->soft) { ob->soft= sbNew(); ob->softflag |= OB_SB_GOAL|OB_SB_EDGES; - softbody_clear_cache(ob, CFRA); + + BKE_ptcache_id_from_softbody(&pid, ob, ob->soft); + BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); } + + ob->softflag |= OB_SB_ENABLE; } + /* needed so that initial state is cached correctly */ DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); @@ -3589,7 +3778,7 @@ static void object_softbodies__enable_psys(void *ob_v, void *psys_v) ParticleSystem *psys = psys_v; Object *ob = ob_v; - if(psys->softflag & OB_SB_ENABLE){ + if(psys->softflag & OB_SB_ENABLE) { psys->softflag &= ~OB_SB_ENABLE; } else{ @@ -3597,7 +3786,6 @@ static void object_softbodies__enable_psys(void *ob_v, void *psys_v) psys->soft= sbNew(); psys->softflag |= OB_SB_GOAL|OB_SB_EDGES; psys->soft->particles=psys; - clear_particles_from_cache(ob, psys, CFRA); } psys->softflag |= OB_SB_ENABLE; } @@ -3620,10 +3808,12 @@ static void object_softbodies_collision(Object *ob) { SoftBody *sb=ob->soft; uiBlock *block; - uiBut *but = NULL; static int val; short *softflag=&ob->softflag, psys_cur=0; int ob_has_hair=psys_ob_has_hair(ob); + static PTCacheID staticpid; + int libdata; + if(!_can_softbodies_at_all(ob)) return; /*bah that is ugly! creating missing data members in UI code*/ if(ob->pd == NULL){ @@ -3636,7 +3826,8 @@ static void object_softbodies_collision(Object *ob) uiNewPanelTabbed("Soft Body", "Physics"); if(uiNewPanel(curarea, block, "Soft Body Collision", "Physics", 651, 0, 318, 204)==0) return; - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + libdata= object_is_libdata(ob); + uiSetButLock(libdata, ERROR_LIBDATA_MESSAGE); if(ob_has_hair) { if(PE_get_current_num(ob) >= 0) { @@ -3662,64 +3853,43 @@ static void object_softbodies_collision(Object *ob) uiDefBut(block, LABEL, 0, "",10,10,1,2, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ uiBlockBeginAlign(block); if(psys_cur){ - uiDefBut(block, LABEL, 0, "Hair is not a softbody",10,190,300,20, NULL, 0.0, 0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "However the emitter can deflect a softbody",10,170,300,20, NULL, 0.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Hair is not a softbody.",10,190,300,20, NULL, 0.0, 0, 0, 0, ""); } else { - uiDefBut(block, LABEL, 0, "Object is not a softbody",10,190,300,20, NULL, 0.0, 0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "However it can deflect a softbody",10,170,300,20, NULL, 0.0, 0, 0, 0, ""); - } - /* OTHER OBJECTS COLLISION STUFF */ - if (ob->type==OB_MESH){ - uiBlockBeginAlign(block); - but = uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",10,50,150,20, &ob->pd->deflect, 0, 0, 0, 0, "Makes this object visible to softbody objects"); - uiButSetFunc(but, object_collision__enabletoggle, ob, NULL); - if(ob->pd->deflect) { - uiDefButF(block, NUM, B_FIELD_CHANGE, "Damping:", 160,50,150,20, &ob->pd->pdef_sbdamp, 0.0, 1.0, 10, 0, "Amount of damping during soft body collision"); - uiDefButBitS(block, TOG,OB_SB_COLLFINAL , B_DIFF, "Ev.M.Stack",10,30,150,20, &ob->softflag, 0, 0, 0, 0, "Pick collision object from modifier stack"); - uiDefButF(block, NUM, B_FIELD_CHANGE, "Inner:", 160,30,150,20, &ob->pd->pdef_sbift, 0.001, 1.0, 10, 0, "Inner face thickness"); - uiDefButF(block, NUM, B_FIELD_CHANGE, "Outer:", 160,10,150,20, &ob->pd->pdef_sboft, 0.001, 1.0, 10, 0, "Outer face thickness"); - } + uiDefBut(block, LABEL, 0, "Object is not a softbody.",10,190,300,20, NULL, 0.0, 0, 0, 0, ""); } uiBlockEndAlign(block); } else{ + BKE_ptcache_id_from_softbody(&staticpid, ob, sb); + object_physics_bake_buttons(block, &staticpid, 125, libdata); + /* SELF COLLISION STUFF */ if ((ob->type==OB_MESH)||(ob->type==OB_CURVE) ) { uiBlockBeginAlign(block); if (*softflag & OB_SB_EDGES){ - uiDefButBitS(block, TOG, OB_SB_SELF, B_SOFTBODY_CHANGE, "Self Collision", 10,170,150,20, softflag, 0, 0, 0, 0, "enable naive vertex ball self collision"); + uiDefButBitS(block, TOG, OB_SB_SELF, B_BAKE_CACHE_CHANGE, "Self Collision", 10,80,150,20, softflag, 0, 0, 0, 0, "enable naive vertex ball self collision"); if(*softflag & OB_SB_SELF){ - uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Ball Size:", 160,170,150,20, &sb->colball, -10.0, 10.0, 10, 0, "Absolute ball size or factor if not manual adjusted"); - uiDefButS(block, ROW, B_DIFF, "Man",10,150,60,20, &sb->sbc_mode, 4.0,SBC_MODE_MANUAL, 0, 0, "Manual adjust"); - uiDefButS(block, ROW, B_DIFF, "Av",70,150,60,20, &sb->sbc_mode, 4.0,SBC_MODE_AVG, 0, 0, "Average Spring lenght * Ball Size"); - uiDefButS(block, ROW, B_DIFF, "Min",130,150,60,20, &sb->sbc_mode, 4.0,SBC_MODE_MIN, 0, 0, "Minimal Spring lenght * Ball Size"); - uiDefButS(block, ROW, B_DIFF, "Max",190,150,60,20, &sb->sbc_mode, 4.0,SBC_MODE_MAX, 0, 0, "Maximal Spring lenght * Ball Size"); - uiDefButS(block, ROW, B_DIFF, "AvMiMa",250,150,60,20, &sb->sbc_mode, 4.0,SBC_MODE_AVGMINMAX, 0, 0, "(Min+Max)/2 * Ball Size"); - uiDefButF(block, NUM, B_DIFF, "B Stiff:", 10,130,150,20, &sb->ballstiff, 0.001, 100.0, 10, 0, "Ball inflating presure"); - uiDefButF(block, NUM, B_DIFF, "B Damp:", 160,130,150,20, &sb->balldamp, 0.001, 1.0, 10, 0, "Blending to inelastic collision"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Ball Size:", 160,80,150,20, &sb->colball, -10.0, 10.0, 10, 0, "Absolute ball size or factor if not manual adjusted"); + uiDefButS(block, ROW, B_BAKE_CACHE_CHANGE, "Man",10,60,60,20, &sb->sbc_mode, 4.0,SBC_MODE_MANUAL, 0, 0, "Manual adjust"); + uiDefButS(block, ROW, B_BAKE_CACHE_CHANGE, "Av",70,60,60,20, &sb->sbc_mode, 4.0,SBC_MODE_AVG, 0, 0, "Average Spring lenght * Ball Size"); + uiDefButS(block, ROW, B_BAKE_CACHE_CHANGE, "Min",130,60,60,20, &sb->sbc_mode, 4.0,SBC_MODE_MIN, 0, 0, "Minimal Spring lenght * Ball Size"); + uiDefButS(block, ROW, B_BAKE_CACHE_CHANGE, "Max",190,60,60,20, &sb->sbc_mode, 4.0,SBC_MODE_MAX, 0, 0, "Maximal Spring lenght * Ball Size"); + uiDefButS(block, ROW, B_BAKE_CACHE_CHANGE, "AvMiMa",250,60,60,20, &sb->sbc_mode, 4.0,SBC_MODE_AVGMINMAX, 0, 0, "(Min+Max)/2 * Ball Size"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "B Stiff:", 10,40,150,20, &sb->ballstiff, 0.001, 100.0, 10, 0, "Ball inflating presure"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "B Damp:", 160,40,150,20, &sb->balldamp, 0.001, 1.0, 10, 0, "Blending to inelastic collision"); } } else{ - uiDefBut(block, LABEL, 0, "<Self Collision> not available because there",10,170,300,20, NULL, 0.0, 0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "are no edges, enable <Use Edges>",10,150,300,20, NULL, 0.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "<Self Collision> not available because there",10,80,300,20, NULL, 0.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "are no edges, enable <Use Edges>",10,60,300,20, NULL, 0.0, 0, 0, 0, ""); } uiBlockEndAlign(block); /*SOLVER SETTINGS*/ /* done in another panel now*/ } - /* OTHER OBJECTS COLLISION STUFF */ - if (ob->type==OB_MESH){ - but = uiDefButBitS(block, TOG, 1, B_REDR, "Deflection",10,50,150,20, &ob->pd->deflect, 0, 0, 0, 0, "Makes this object visible to other softbody objects"); - uiButSetFunc(but, object_collision__enabletoggle, ob, NULL); - if(ob->pd->deflect) { - uiDefButF(block, NUM, B_DIFF, "Damping:", 160,50,150,20, &ob->pd->pdef_sbdamp, 0.0, 1.0, 10, 0, "Amount of damping during soft body collision"); - uiDefButBitS(block, TOG,OB_SB_COLLFINAL , B_DIFF, "Ev.M.Stack",10,30,150,20, softflag, 0, 0, 0, 0, "Pick collision object from modifier stack"); - uiDefButF(block, NUM, B_DIFF, "Inner:", 160,30,150,20, &ob->pd->pdef_sbift, 0.001, 1.0, 10, 0, "Inner face thickness"); - uiDefButF(block, NUM, B_DIFF, "Outer:", 160,10,150,20, &ob->pd->pdef_sboft, 0.001, 1.0, 10, 0, "Outer face thickness"); - } - } + uiDefBut(block, LABEL, 0, "",10,10,1,2, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ } uiBlockEndAlign(block); @@ -3736,7 +3906,8 @@ static void object_softbodies_solver(Object *ob) uiNewPanelTabbed("Soft Body", "Physics"); if(uiNewPanel(curarea, block, "Soft Body Solver", "Physics", 651, 0, 318, 204)==0) return; - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + uiSetButLock(object_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + /* doubt that is really needed here but for now */ if(ob_has_hair) { if(PE_get_current_num(ob) >= 0) { @@ -3761,10 +3932,10 @@ static void object_softbodies_solver(Object *ob) if(!val) { uiDefBut(block, LABEL, 0, "",10,10,1,2, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ if(psys_cur){ - uiDefBut(block, LABEL, 0, "Hair is not a softbody",10,190,300,20, NULL, 0.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Hair is not a softbody.",10,190,300,20, NULL, 0.0, 0, 0, 0, ""); } else { - uiDefBut(block, LABEL, 0, "Object is not a softbody",10,190,300,20, NULL, 0.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "Object is not a softbody.",10,190,300,20, NULL, 0.0, 0, 0, 0, ""); } } else{ @@ -3772,7 +3943,7 @@ static void object_softbodies_solver(Object *ob) /*SOLVER SETTINGS*/ uiBlockBeginAlign(block); uiDefBut(block, LABEL, 0, "Solver select",10,200,300,20, NULL, 0.0, 0, 0, 0, ""); - uiDefButS(block, MENU, B_SOFTBODY_CHANGE, sbsolvers,10,180,300,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver"); + uiDefButS(block, MENU, B_BAKE_CACHE_CHANGE, sbsolvers,10,180,300,20, &sb->solver_ID, 14.0, 0.0, 0, 0, "Select Solver"); uiBlockEndAlign(block); /*some have adapive step size - some not*/ @@ -3787,31 +3958,31 @@ static void object_softbodies_solver(Object *ob) if(adaptive_mode){ uiBlockBeginAlign(block); uiDefBut(block, LABEL, 0, "Step size controls",10,160,300,20, NULL, 0.0, 0, 0, 0, ""); - uiDefButF(block, NUM, B_DIFF, "Error Lim:", 10,140,280,20, &sb->rklimit , 0.001, 10.0, 10, 0, "The Runge-Kutta ODE solver error limit, low value gives more precision, high values speed"); - uiDefButBitS(block, TOG, SBSO_OLDERR, B_DIFF,"V", 290,140,20,20, &sb->solverflags, 0, 0, 0, 0, "Use velocities for automagic step sizes"); - uiDefButS(block, NUM, B_DIFF, "MinS:", 10,120,150,20, &sb->minloops, 0.00, 30000.0, 10, 0, "Minimal # solver steps/frame "); - uiDefButS(block, NUM, B_DIFF, "MaxS:", 160,120,150,20, &sb->maxloops, 0.00, 30000.0, 10, 0, "Maximal # solver steps/frame "); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Error Lim:", 10,140,280,20, &sb->rklimit , 0.001, 10.0, 10, 0, "The Runge-Kutta ODE solver error limit, low value gives more precision, high values speed"); + uiDefButBitS(block, TOG, SBSO_OLDERR, B_BAKE_CACHE_CHANGE,"V", 290,140,20,20, &sb->solverflags, 0, 0, 0, 0, "Use velocities for automagic step sizes"); + uiDefButS(block, NUM, B_BAKE_CACHE_CHANGE, "MinS:", 10,120,150,20, &sb->minloops, 0.00, 30000.0, 10, 0, "Minimal # solver steps/frame "); + uiDefButS(block, NUM, B_BAKE_CACHE_CHANGE, "MaxS:", 160,120,150,20, &sb->maxloops, 0.00, 30000.0, 10, 0, "Maximal # solver steps/frame "); uiBlockEndAlign(block); uiBlockBeginAlign(block); uiDefBut(block, LABEL, 0, "Collision helpers",10,100,300,20, NULL, 0.0, 0, 0, 0, ""); - uiDefButS(block, NUM, B_DIFF, "Choke:", 10,80,150,20, &sb->choke, 0.00, 100.0, 10, 0, "'Viscosity' inside collision target "); - uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 160,80,150,20, &sb->fuzzyness, 1.00, 100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable"); + uiDefButS(block, NUM, B_BAKE_CACHE_CHANGE, "Choke:", 10,80,150,20, &sb->choke, 0.00, 100.0, 10, 0, "'Viscosity' inside collision target "); + uiDefButS(block, NUM, B_BAKE_CACHE_CHANGE, "Fuzzy:", 160,80,150,20, &sb->fuzzyness, 1.00, 100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable"); uiBlockEndAlign(block); uiBlockBeginAlign(block); uiDefBut(block, LABEL, 0, "Diagnosis",10,60,300,20, NULL, 0.0, 0, 0, 0, ""); - uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"Print Performance to Console", 10,40,300,20, &sb->solverflags, 0, 0, 0, 0, "Turn on SB diagnose console prints"); + uiDefButBitS(block, TOG, SBSO_MONITOR, B_BAKE_CACHE_CHANGE,"Print Performance to Console", 10,40,300,20, &sb->solverflags, 0, 0, 0, 0, "Turn on SB diagnose console prints"); uiBlockEndAlign(block); } else{ uiBlockEndAlign(block); uiBlockBeginAlign(block); - uiDefButS(block, NUM, B_DIFF, "Fuzzy:", 210,100,90,20, &sb->fuzzyness, 1.00, 100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable"); - uiDefButBitS(block, TOG, SBSO_MONITOR, B_DIFF,"M", 290,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Turn on SB diagnose console prints"); + uiDefButS(block, NUM, B_BAKE_CACHE_CHANGE, "Fuzzy:", 210,100,90,20, &sb->fuzzyness, 1.00, 100.0, 10, 0, "Fuzzyness while on collision, high values make collsion handling faster but less stable"); + uiDefButBitS(block, TOG, SBSO_MONITOR, B_BAKE_CACHE_CHANGE,"M", 290,100,20,20, &sb->solverflags, 0, 0, 0, 0, "Turn on SB diagnose console prints"); uiBlockEndAlign(block); - uiDefButS(block, NUM, B_DIFF, "Steps:", 10,80,100,20, &sb->minloops, 1.00, 30000.0, 10, 0, "Solver steps/frame "); - uiDefButS(block, NUM, B_DIFF, "Choke:", 210,80,100,20, &sb->choke, 0.00, 100.0, 10, 0, "'Viscosity' inside collision target "); + uiDefButS(block, NUM, B_BAKE_CACHE_CHANGE, "Steps:", 10,80,100,20, &sb->minloops, 1.00, 30000.0, 10, 0, "Solver steps/frame "); + uiDefButS(block, NUM, B_BAKE_CACHE_CHANGE, "Choke:", 210,80,100,20, &sb->choke, 0.00, 100.0, 10, 0, "'Viscosity' inside collision target "); } uiBlockEndAlign(block); @@ -3821,22 +3992,13 @@ static void object_softbodies_solver(Object *ob) uiBlockEndAlign(block); } -static void sb_clear_cache(void *ob_v, void *actsoft_v) -{ - Object *ob = ob_v; - short *actsoft = actsoft_v; - - if(actsoft) - clear_particles_from_cache(ob, BLI_findlink(&ob->particlesystem, *actsoft), CFRA); - else - softbody_clear_cache(ob, CFRA); -} static void object_softbodies(Object *ob) { SoftBody *sb=ob->soft; ParticleSystem *psys=NULL; uiBlock *block; uiBut *but; + ModifierData *md; static int val; short *softflag=&ob->softflag, psys_cur=0; int ob_has_hair = psys_ob_has_hair(ob); @@ -3846,12 +4008,11 @@ static void object_softbodies(Object *ob) block= uiNewBlock(&curarea->uiblocks, "object_softbodies", UI_EMBOSS, UI_HELV, curarea->win); uiNewPanelTabbed("Soft Body", "Physics"); if(uiNewPanel(curarea, block, "Soft Body", "Physics", 640, 0, 318, 204)==0) return; - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + uiSetButLock(object_is_libdata(ob), ERROR_LIBDATA_MESSAGE); if(ob_has_hair) { - char *menustr = psys_menu_string(ob,1); - psys= psys_get_current(ob); + if(psys && actsoft >= 0) { actsoft= psys_get_current_num(ob)+1; @@ -3861,52 +4022,56 @@ static void object_softbodies(Object *ob) } else actsoft= -1; /* -1 = object */ - - but=uiDefButS(block, MENU, B_BAKE_REDRAWEDIT, menustr, 10,200,100,20, &actsoft, 14.0, 0.0, 0, 0, "Browse systems"); - uiButSetFunc(but, PE_change_act, ob, &actsoft); - - MEM_freeN(menustr); } - if(psys_cur && psys){ + if(psys_cur && psys) { if(*softflag & OB_SB_ENABLE) - val=1; + val = 1; else - val=0; + val = 0; - but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Soft Body", 110,200,70,20, &val, 0, 0, 0, 0, "Sets hair to become soft body"); + but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Soft Body", 10,200,130,20, &val, 0, 0, 0, 0, "Sets hair to become soft body"); uiButSetFunc(but, object_softbodies__enable_psys, ob, psys); } - else{ - val = modifiers_isSoftbodyEnabled(ob); + else { + md = modifiers_findByType(ob, eModifierType_Softbody); + val = (md != NULL); + if(ob_has_hair) - but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Soft Body", 110,200,70,20, &val, 0, 0, 0, 0, "Sets object to become soft body"); + but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Soft Body", 10,200,130,20, &val, 0, 0, 0, 0, "Sets object to become soft body"); else but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Soft Body", 10,200,130,20, &val, 0, 0, 0, 0, "Sets object to become soft body"); - uiButSetFunc(but, object_softbodies__enable, ob, NULL); + + if(md) { + uiBlockBeginAlign(block); + uiDefIconButBitI(block, TOG, eModifierMode_Render, B_BAKE_CACHE_CHANGE, ICON_SCENE, 145, 200, 20, 20,&md->mode, 0, 0, 1, 0, "Enable soft body during rendering"); + but= uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_BAKE_CACHE_CHANGE, VICON_VIEW3D, 165, 200, 20, 20,&md->mode, 0, 0, 1, 0, "Enable soft body during interactive display"); + uiBlockEndAlign(block); + } } + + if(ob_has_hair) { + char *menustr = psys_menu_string(ob,1); + + but=uiDefButS(block, MENU, B_BAKE_REDRAWEDIT, menustr, 210,200,100,20, &actsoft, 14.0, 0.0, 0, 0, "Browse systems"); + uiButSetFunc(but, PE_change_act, ob, &actsoft); + + MEM_freeN(menustr); + } + + uiDefBut(block, LABEL, 0, "",10,10,300,0, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ - if(val){ + if(val) { int defCount; char *menustr; static char str[128]; - //uiDefButBitS(block, TOG, OB_SB_BAKESET, REDRAWBUTSOBJECT, "Bake settings", 180,200,130,20, &ob->softflag, 0, 0, 0, 0, "To convert simulation into baked (cached) result"); - - //if(sb->keys) uiSetButLock(1, "Soft Body is baked, free it first"); - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, OB_SB_PROTECT_CACHE, REDRAWBUTSOBJECT, "Protect", 180,200,50,20, softflag, 0.0, 0.0, 10, 0, "Protect the cache"); - but=uiDefBut(block, BUT, B_SOFTBODY_CHANGE, "Clear", 230,200,50,20, NULL, 0.0, 0.0, 10, 0, "Clear the cache"); - if((*softflag & PSYS_PROTECT_CACHE)==0) - uiButSetFunc(but, sb_clear_cache, ob, &actsoft); - - uiBlockEndAlign(block); - - if(*softflag & OB_SB_PROTECT_CACHE) uiSetButLock(1, "Cache is protected"); + if(sb->pointcache->flag & PTCACHE_BAKED) + uiSetButLock(1, "Simulation frames are baked"); //if(ob->softflag & OB_SB_BAKESET) { // uiBlockBeginAlign(block); @@ -3939,66 +4104,66 @@ static void object_softbodies(Object *ob) sprintf(str, "Vertex Mass"); } uiBlockBeginAlign(block); - uiDefButF(block, NUM, B_DIFF, "Friction:", 10, 170,150,20, &sb->mediafrict, 0.0, 50.0, 10, 0, "General media friction for point movements"); - uiDefButF(block, NUM, B_DIFF, "Mass:", 160, 170,150,20, &sb->nodemass , 0.001, 50000.0, 10, 0, str); - uiDefButF(block, NUM, B_DIFF, "Grav:", 10,150,150,20, &sb->grav , -10.0, 10.0, 10, 0, "Apply gravitation to point movement"); - uiDefButF(block, NUM, B_DIFF, "Speed:", 160,150,150,20, &sb->physics_speed , 0.01, 100.0, 10, 0, "Tweak timing for physics to control frequency and speed"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Friction:", 10, 170,150,20, &sb->mediafrict, 0.0, 50.0, 10, 0, "General media friction for point movements"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Mass:", 160, 170,150,20, &sb->nodemass , 0.001, 50000.0, 10, 0, str); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Grav:", 10,150,150,20, &sb->grav , -10.0, 10.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Speed:", 160,150,150,20, &sb->physics_speed , 0.01, 100.0, 10, 0, "Tweak timing for physics to control frequency and speed"); uiBlockEndAlign(block); /* GOAL STUFF */ uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, OB_SB_GOAL, B_SOFTBODY_CHANGE, "Use Goal", 10,120,130,20, softflag, 0, 0, 0, 0, "Define forces for vertices to stick to animated position"); + uiDefButBitS(block, TOG, OB_SB_GOAL, B_BAKE_CACHE_CHANGE, "Use Goal", 10,120,130,20, softflag, 0, 0, 0, 0, "Define forces for vertices to stick to animated position"); if (*softflag & OB_SB_GOAL){ if(ob->type==OB_MESH) { menustr= get_vertexgroup_menustr(ob); defCount=BLI_countlist(&ob->defbase); if(defCount==0) sb->vertgroup= 0; - uiDefButS(block, MENU, B_SOFTBODY_CHANGE, menustr, 140,120,20,20, &sb->vertgroup, 0, defCount, 0, 0, "Browses available vertex groups"); + uiDefButS(block, MENU, B_BAKE_CACHE_CHANGE, menustr, 140,120,20,20, &sb->vertgroup, 0, defCount, 0, 0, "Browses available vertex groups"); MEM_freeN (menustr); if(sb->vertgroup) { bDeformGroup *defGroup = BLI_findlink(&ob->defbase, sb->vertgroup-1); if(defGroup) - uiDefBut(block, BUT, B_DIFF, defGroup->name, 160,120,130,20, NULL, 0.0, 0.0, 0, 0, "Name of current vertex group"); + uiDefBut(block, BUT, B_BAKE_CACHE_CHANGE, defGroup->name, 160,120,130,20, NULL, 0.0, 0.0, 0, 0, "Name of current vertex group"); else - uiDefBut(block, BUT, B_DIFF, "(no group)", 160,120,130,20, NULL, 0.0, 0.0, 0, 0, "Vertex Group doesn't exist anymore"); + uiDefBut(block, BUT, B_BAKE_CACHE_CHANGE, "(no group)", 160,120,130,20, NULL, 0.0, 0.0, 0, 0, "Vertex Group doesn't exist anymore"); uiDefIconBut(block, BUT, B_SOFTBODY_DEL_VG, ICON_X, 290,120,20,20, 0, 0, 0, 0, 0, "Disable use of vertex group"); } else - uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Goal:", 160,120,150,20, &sb->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Goal:", 160,120,150,20, &sb->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); } else { - uiDefButS(block, TOG, B_SOFTBODY_CHANGE, "W", 140,120,20,20, &sb->vertgroup, 0, 1, 0, 0, "Use control point weight values"); - uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Goal:", 160,120,150,20, &sb->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); + uiDefButS(block, TOG, B_BAKE_CACHE_CHANGE, "W", 140,120,20,20, &sb->vertgroup, 0, 1, 0, 0, "Use control point weight values"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Goal:", 160,120,150,20, &sb->defgoal, 0.0, 1.0, 10, 0, "Default Goal (vertex target position) value, when no Vertex Group used"); } - uiDefButF(block, NUM, B_DIFF, "G Stiff:", 10,100,150,20, &sb->goalspring, 0.0, 0.999, 10, 0, "Goal (vertex target position) spring stiffness"); - uiDefButF(block, NUM, B_DIFF, "G Damp:", 160,100,150,20, &sb->goalfrict , 0.0, 50.0, 10, 0, "Goal (vertex target position) friction"); - uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "G Min:", 10,80,150,20, &sb->mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range"); - uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "G Max:", 160,80,150,20, &sb->maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "G Stiff:", 10,100,150,20, &sb->goalspring, 0.0, 0.999, 10, 0, "Goal (vertex target position) spring stiffness"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "G Damp:", 160,100,150,20, &sb->goalfrict , 0.0, 50.0, 10, 0, "Goal (vertex target position) friction"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "G Min:", 10,80,150,20, &sb->mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "G Max:", 160,80,150,20, &sb->maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range"); } uiBlockEndAlign(block); /* EDGE SPRING STUFF */ if(ob->type!=OB_SURF) { uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, OB_SB_EDGES, B_SOFTBODY_CHANGE, "Use Edges", 10,50,90,20, softflag, 0, 0, 0, 0, "Use Edges as springs"); + uiDefButBitS(block, TOG, OB_SB_EDGES, B_BAKE_CACHE_CHANGE, "Use Edges", 10,50,90,20, softflag, 0, 0, 0, 0, "Use Edges as springs"); if (*softflag & OB_SB_EDGES){ - uiDefButBitS(block, TOG, OB_SB_QUADS, B_SOFTBODY_CHANGE, "Stiff Quads", 110,50,90,20, softflag, 0, 0, 0, 0, "Adds diagonal springs on 4-gons"); - uiDefButBitS(block, TOG, OB_SB_EDGECOLL, B_DIFF, "CEdge", 220,50,45,20, softflag, 0, 0, 0, 0, "Edge collide too"); - uiDefButBitS(block, TOG, OB_SB_FACECOLL, B_DIFF, "CFace", 265,50,45,20, softflag, 0, 0, 0, 0, "Faces collide too SLOOOOOW warning "); - uiDefButF(block, NUM, B_DIFF, "Pull:", 10,30,75,20, &sb->inspring, 0.0, 0.999, 10, 0, "Edge spring stiffness when longer than rest length"); - uiDefButF(block, NUM, B_DIFF, "Push:", 85,30,75,20, &sb->inpush, 0.0, 0.999, 10, 0, "Edge spring stiffness when shorter than rest length"); - uiDefButF(block, NUM, B_DIFF, "Damp:", 160,30,70,20, &sb->infrict, 0.0, 50.0, 10, 0, "Edge spring friction"); - uiDefButS(block, NUM, B_SOFTBODY_CHANGE, "SL:",250 ,30,60,20, &sb->springpreload, 0.0, 200.0, 10, 0, "Alter spring lenght to shrink/blow up (unit %) 0 to disable "); - - uiDefButBitS(block, TOG,OB_SB_AERO_ANGLE,B_SOFTBODY_CHANGE, "N",10,10,20,20, softflag, 0, 0, 0, 0, "New aero(uses angle and length)"); - uiDefButS(block, NUM, B_DIFF, "Aero:", 30,10,60,20, &sb->aeroedge, 0.00, 30000.0, 10, 0, "Make edges 'sail'"); - uiDefButS(block, NUM, B_SOFTBODY_CHANGE, "Plas:", 90,10,60,20, &sb->plastic, 0.0, 100.0, 10, 0, "Permanent deform"); + uiDefButBitS(block, TOG, OB_SB_QUADS, B_BAKE_CACHE_CHANGE, "Stiff Quads", 110,50,90,20, softflag, 0, 0, 0, 0, "Adds diagonal springs on 4-gons"); + uiDefButBitS(block, TOG, OB_SB_EDGECOLL, B_BAKE_CACHE_CHANGE, "CEdge", 220,50,45,20, softflag, 0, 0, 0, 0, "Edge collide too"); + uiDefButBitS(block, TOG, OB_SB_FACECOLL, B_BAKE_CACHE_CHANGE, "CFace", 265,50,45,20, softflag, 0, 0, 0, 0, "Faces collide too SLOOOOOW warning "); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Pull:", 10,30,75,20, &sb->inspring, 0.0, 0.999, 10, 0, "Edge spring stiffness when longer than rest length"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Push:", 85,30,75,20, &sb->inpush, 0.0, 0.999, 10, 0, "Edge spring stiffness when shorter than rest length"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Damp:", 160,30,70,20, &sb->infrict, 0.0, 50.0, 10, 0, "Edge spring friction"); + uiDefButS(block, NUM, B_BAKE_CACHE_CHANGE, "SL:",250 ,30,60,20, &sb->springpreload, 0.0, 200.0, 10, 0, "Alter spring lenght to shrink/blow up (unit %) 0 to disable "); + + uiDefButBitS(block, TOG,OB_SB_AERO_ANGLE,B_BAKE_CACHE_CHANGE, "N",10,10,20,20, softflag, 0, 0, 0, 0, "New aero(uses angle and length)"); + uiDefButS(block, NUM, B_BAKE_CACHE_CHANGE, "Aero:", 30,10,60,20, &sb->aeroedge, 0.00, 30000.0, 10, 0, "Make edges 'sail'"); + uiDefButS(block, NUM, B_BAKE_CACHE_CHANGE, "Plas:", 90,10,60,20, &sb->plastic, 0.0, 100.0, 10, 0, "Permanent deform"); if(ob->type==OB_MESH) { - uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Be:", 150,10,80,20, &sb->secondspring, 0.0, 10.0, 10, 0, "Bendig Stiffness"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Be:", 150,10,80,20, &sb->secondspring, 0.0, 10.0, 10, 0, "Bendig Stiffness"); if (*softflag & OB_SB_QUADS){ - uiDefButF(block, NUM, B_SOFTBODY_CHANGE, "Sh:", 230,10,80,20, &sb->shearstiff, 0.0, 1.0, 10, 0, "Shear Stiffness"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Sh:", 230,10,80,20, &sb->shearstiff, 0.0, 1.0, 10, 0, "Shear Stiffness"); } } else sb->secondspring = 0; @@ -4011,6 +4176,28 @@ static void object_softbodies(Object *ob) uiBlockEndAlign(block); } +static void object_panel_particle_bake(Object *ob) +{ + uiBlock *block; + ParticleSystem *psys= psys_get_current(ob); + static PTCacheID staticpid; + int libdata; + + if (psys==NULL || psys->part==NULL) return; + if (ELEM(psys->part->type, PART_HAIR, PART_FLUID)) return; + if (psys->part->phystype == PART_PHYS_KEYED) return; + + block= uiNewBlock(&curarea->uiblocks, "object_panel_particle_bake", UI_EMBOSS, UI_HELV, curarea->win); + uiNewPanelTabbed("Particle System", "Particle"); + if(uiNewPanel(curarea, block, "Bake", "Particle", 320, 0, 318, 204)==0) return; + + libdata= object_is_libdata(ob); + uiSetButLock(libdata, ERROR_LIBDATA_MESSAGE); + + BKE_ptcache_id_from_particles(&staticpid, ob, psys); + object_physics_bake_buttons(block, &staticpid, 10, libdata); +} + /* Panels for new particles*/ static void object_panel_particle_children(Object *ob) { @@ -4025,8 +4212,10 @@ static void object_panel_particle_children(Object *ob) if(part==NULL) return; block= uiNewBlock(&curarea->uiblocks, "object_panel_particle_child", UI_EMBOSS, UI_HELV, curarea->win); - if(uiNewPanel(curarea, block, "Children", "Particle", 1300, 0, 318, 204)==0) return; uiNewPanelTabbed("Extras", "Particle"); + if(uiNewPanel(curarea, block, "Children", "Particle", 1300, 0, 318, 204)==0) return; + + uiSetButLock((part->id.lib != NULL), ERROR_LIBDATA_MESSAGE); if(part->type == PART_FLUID) { uiDefBut(block, LABEL, 0, "No settings for fluid particles", butx,(buty-=2*buth),2*butw,buth, NULL, 0.0, 0, 0, 0, ""); @@ -4037,7 +4226,7 @@ static void object_panel_particle_children(Object *ob) if(part->childtype==0) return; - if(part->childtype==PART_CHILD_FACES && (psys->flag&(PSYS_HAIR_DONE|PSYS_KEYED))==0) { + if(part->childtype==PART_CHILD_FACES && !(part->phystype==PART_PHYS_KEYED || part->type==PART_HAIR)) { uiDefBut(block, LABEL, 0, "Hair or keyed", butx,(buty-=2*buth),butw,buth, NULL, 0.0, 0, 0, 0, ""); uiDefBut(block, LABEL, 0, "particles needed!", butx,(buty-=2*buth),butw,buth, NULL, 0.0, 0, 0, 0, ""); return; @@ -4083,12 +4272,12 @@ static void object_panel_particle_children(Object *ob) butx=160; buty=180; - if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED)) + if(part->phystype==PART_PHYS_KEYED || part->type==PART_HAIR) uiDefButBitS(block, TOG, 1, B_PART_REDRAW, "Kink/Branch", butx,(buty-=buth),butw,buth, &kink_ui, 0, 0, 0, 0, "Show kink and branch options"); else buty-=buth; - if(kink_ui || (psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED)) == 0) { + if(kink_ui || !(part->phystype==PART_PHYS_KEYED || part->type==PART_HAIR)) { buty -= buth/2; /* kink */ @@ -4106,7 +4295,7 @@ static void object_panel_particle_children(Object *ob) } uiBlockEndAlign(block); - if(part->childtype==PART_CHILD_PARTICLES && psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED)) { + if(part->childtype==PART_CHILD_PARTICLES && (part->phystype==PART_PHYS_KEYED || part->type==PART_HAIR)) { if(part->flag & PART_BRANCHING) { uiDefButBitI(block, TOG, PART_BRANCHING, B_PART_RECALC_CHILD, "Branching", butx,(buty-=2*buth),butw,buth, &part->flag, 0, 0, 0, 0, "Branch child paths from eachother"); uiDefButBitI(block, TOG, PART_ANIM_BRANCHING, B_PART_RECALC_CHILD, "Animated", butx,(buty-=buth),butw/2,buth, &part->flag, 0, 0, 0, 0, "Animate branching"); @@ -4183,6 +4372,8 @@ static void object_panel_particle_extra(Object *ob) block= uiNewBlock(&curarea->uiblocks, "object_panel_particle_extra", UI_EMBOSS, UI_HELV, curarea->win); if(uiNewPanel(curarea, block, "Extras", "Particle", 980, 0, 318, 204)==0) return; + uiSetButLock((part->id.lib != NULL), ERROR_LIBDATA_MESSAGE); + if(part->type == PART_FLUID) { uiDefBut(block, LABEL, 0, "No settings for fluid particles", butx,(buty-=2*buth),2*butw,buth, NULL, 0.0, 0, 0, 0, ""); return; @@ -4363,7 +4554,7 @@ static void object_panel_particle_visual(Object *ob) uiDefButF(block, NUM, B_PART_REDRAW, "Front:", butx,(buty-=buth),butw,buth, &part->draw_line[1], 0.0, 10.0, 0, 0, "Length of the line's head"); break; case PART_DRAW_PATH: - if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED)) { + if(part->phystype==PART_PHYS_KEYED || part->type==PART_HAIR) { uiDefButS(block, NUM, B_PART_RECALC, "Steps:", butx,(buty+=buth),butw,buth, &part->draw_step, 0.0, 7.0, 0, 0, "How many steps paths are drawn with (power of 2)"); uiDefButS(block, NUM, B_PART_REDRAW, "Render:", butx,(buty-=buth),butw,buth, &part->ren_step, 0.0, 9.0, 0, 0, "How many steps paths are rendered with (power of 2)"); @@ -4484,11 +4675,12 @@ static void object_panel_particle_physics(Object *ob) return; } - if(ob->id.lib) uiSetButLock(1, "Can't edit library data"); - - if(psys->flag & PSYS_EDITED || psys->flag & PSYS_PROTECT_CACHE) { - uiSetButLock(1, "Hair is edited or cache is protected!"); - } + if(ob->id.lib) + uiSetButLock(1, "Can't edit library data"); + else if(psys->flag & PSYS_EDITED) + uiSetButLock(1, "Hair is edited!"); + else if(psys->pointcache->flag & PTCACHE_BAKED) + uiSetButLock(1, "Simulation frames are baked!"); if(part->phystype==PART_PHYS_KEYED){ uiBlockBeginAlign(block); @@ -4641,10 +4833,6 @@ static void object_panel_particle_physics(Object *ob) } } -static void psys_clear_cache(void *ob_v, void *psys_v) -{ - clear_particles_from_cache((Object *)ob_v, (ParticleSystem *)psys_v, CFRA); -} static void object_panel_particle_system(Object *ob) { uiBlock *block; @@ -4652,10 +4840,11 @@ static void object_panel_particle_system(Object *ob) ParticleSystem *psys=NULL; ParticleSettings *part; ID *id, *idfrom; + ModifierData *md; short butx=0, buty=160, butw=150, buth=20; - char str[30]; + char str[30], *lockmessage= NULL; static short partact; - short totpart, lock; + short totpart, lock= 0; block= uiNewBlock(&curarea->uiblocks, "object_panel_particle_system", UI_EMBOSS, UI_HELV, curarea->win); if(uiNewPanel(curarea, block, "Particle System", "Particle", 0, 0, 318, 204)==0) return; @@ -4685,7 +4874,7 @@ static void object_panel_particle_system(Object *ob) partact=psys_get_current_num(ob)+1; totpart=BLI_countlist(&ob->particlesystem); sprintf(str, "%d Part", totpart); - but=uiDefButS(block, NUM, B_PARTACT, str, 224,buty,88,buth, &partact, 1.0, totpart+1, 0, 0, "Shows the number of particle systems in the object and the active particle system"); + but=uiDefButS(block, NUM, B_PARTACT, str, 230,buty,83,buth, &partact, 1.0, totpart+1, 0, 0, "Shows the number of particle systems in the object and the active particle system"); uiButSetFunc(but, PE_change_act, ob, &partact); if(psys==NULL) @@ -4697,38 +4886,43 @@ static void object_panel_particle_system(Object *ob) return; butx=0; - buty-=5; if(part->type == PART_FLUID) { - uiDefButBitI(block, TOG, PSYS_ENABLED, B_PART_ENABLE, "Enabled", 0, buty+5, 100,buth, &psys->flag, 0, 0, 0, 0, "Sets particle system to be calculated and shown"); - uiDefBut(block, LABEL, 0, "No settings for fluid particles", butx,(buty-=2*buth),2*butw,buth, NULL, 0.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "No settings for fluid particles", butx,buty,2*butw,buth, NULL, 0.0, 0, 0, 0, ""); return; } - else - uiDefButBitI(block, TOG, PSYS_ENABLED, B_PART_ENABLE, "Enabled", 0,(buty-=buth),100,buth, &psys->flag, 0, 0, 0, 0, "Sets particle system to be calculated and shown"); + + buty -= (buth+5); if(part->type == PART_HAIR){ if(psys->flag & PSYS_EDITED) - uiDefBut(block, BUT, B_PART_EDITABLE, "Free Edit", 105,buty,100,buth, NULL, 0.0, 0.0, 10, 0, "Free editing"); + uiDefBut(block, BUT, B_PART_EDITABLE, "Free Edit", butx+butw+10,buty,butw,buth, NULL, 0.0, 0.0, 10, 0, "Free editing"); else - uiDefBut(block, BUT, B_PART_EDITABLE, "Set Editable", 105,buty,100,buth, NULL, 0.0, 0.0, 10, 0, "Finalize hair to enable editing in particle mode"); + uiDefBut(block, BUT, B_PART_EDITABLE, "Set Editable", butx+butw+10,buty,butw,buth, NULL, 0.0, 0.0, 10, 0, "Finalize hair to enable editing in particle mode"); } - else { - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, PSYS_PROTECT_CACHE, B_PART_REDRAW, "Protect", 105,buty,50,buth, &psys->flag, 0.0, 0.0, 10, 0, "Protect the cache"); - but=uiDefBut(block, BUT, B_PART_RECALC, "Clear", 155,buty,50,buth, NULL, 0.0, 0.0, 10, 0, "Clear the cache"); - if((psys->flag & PSYS_PROTECT_CACHE)==0) - uiButSetFunc(but, psys_clear_cache, ob, &partact); - uiBlockEndAlign(block); + if(psys->flag & PSYS_EDITED) { + lockmessage= "Hair is edited!"; + lock= 1; + } + else if(psys->pointcache->flag & PTCACHE_BAKED) { + lockmessage= "Simulation frames are baked!"; + lock= 1; } - lock= (psys->flag & PSYS_EDITED || psys->flag & PSYS_PROTECT_CACHE); if(lock) - uiSetButLock(1, "Hair is edited or cache is protected!"); + uiSetButLock(1, lockmessage); + + uiDefButS(block, MENU, B_PARTTYPE, "Type%t|Hair%x2|Reactor%x1|Emitter%x0", butx,buty,butw-45,buth, &part->type, 14.0, 0.0, 0, 0, "Type of particle system"); - uiDefButS(block, MENU, B_PARTTYPE, "Type%t|Hair%x2|Reactor%x1|Emitter%x0", 210,buty,100,buth, &part->type, 14.0, 0.0, 0, 0, "Type of particle system"); + md= (ModifierData*)psys_get_modifier(ob, psys); + if(md) { + uiBlockBeginAlign(block); + uiDefIconButBitI(block, TOG, eModifierMode_Render, B_PART_RECALC, ICON_SCENE, butx+butw-40, buty, 20, 20,&md->mode, 0, 0, 1, 0, "Enable particle system during rendering"); + but= uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_PART_RECALC, VICON_VIEW3D, butx+butw-20, buty, 20, 20,&md->mode, 0, 0, 1, 0, "Enable particle system during interactive display"); + uiBlockEndAlign(block); + } buty-=5; uiDefBut(block, LABEL, 0, "Basic:", butx,(buty-=buth),butw,buth, NULL, 0.0, 0, 0, 0, ""); @@ -4775,7 +4969,7 @@ static void object_panel_particle_system(Object *ob) if(lock) uiClearButLock(); uiDefButBitI(block, TOG, PART_TRAND, B_PART_DISTR, "Random", butx,(buty-=buth),butw/2,buth, &part->flag, 0, 0, 0, 0, "Emit in random order of elements"); - if(lock) uiSetButLock(1, "Hair is edited or cache is protected!"); + if(lock) uiSetButLock(1, lockmessage); if(part->type==PART_REACTOR) uiDefButS(block, MENU, B_PART_DISTR, "Particle %x3|Volume %x2|Faces %x1|Verts %x0", butx+butw/2,buty,butw/2,buth, &part->from, 14.0, 0.0, 0, 0, "Where to emit particles from"); @@ -4785,7 +4979,7 @@ static void object_panel_particle_system(Object *ob) if(ELEM(part->from,PART_FROM_FACE,PART_FROM_VOLUME)) { if(lock) uiClearButLock(); uiDefButBitI(block, TOG, PART_EDISTR, B_PART_DISTR, "Even",butx,(buty-=buth),butw/2,buth, &part->flag, 0, 0, 0, 0, "Use even distribution from faces based on face areas or edge lengths"); - if(lock) uiSetButLock(1, "Hair is edited or cache is protected!"); + if(lock) uiSetButLock(1, lockmessage); uiDefButS(block, MENU, B_PART_DISTR, "Distribution %t|Grid%x2|Random%x1|Jittered%x0", butx+butw/2,buty,butw/2,buth, &part->distr, 14.0, 0.0, 0, 0, "How to distribute particles on selected element"); if(part->distr==PART_DISTR_JIT) { uiDefButF(block, NUM, B_PART_DISTR, "Amount:", butx,(buty-=buth),butw,buth, &part->jitfac, 0, 2.0, 1, 1, "Amount of jitter applied to the sampling"); @@ -4847,9 +5041,9 @@ static void object_panel_fluidsim(Object *ob) char *msg = NULL; block= uiNewBlock(&curarea->uiblocks, "object_fluidsim", UI_EMBOSS, UI_HELV, curarea->win); - if(uiNewPanel(curarea, block, "Fluid Simulation", "Physics", 1060, 0, 318, 204)==0) return; + if(uiNewPanel(curarea, block, "Fluid", "Physics", 1060, 0, 318, 204)==0) return; - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + uiSetButLock(object_is_libdata(ob), ERROR_LIBDATA_MESSAGE); if(ob->type==OB_MESH) { if(((Mesh *)ob->data)->totvert == 0) { @@ -5143,10 +5337,10 @@ static void object_panel_fluidsim(Object *ob) return; } else { - msg = "Object not enabled for fluid simulation..."; + msg = "Object not enabled for fluid simulation."; } } else { - msg = "Only Mesh Objects can participate."; + msg = "Only mesh objects can do fluid simulation."; } errMessage: yline -= lineHeight + 5; @@ -5183,7 +5377,7 @@ static void object_cloth__enabletoggle(void *ob_v, void *arg2) BIF_undo_push("Del modifier"); - ob->softflag |= OB_SB_RESET; + //ob->softflag |= OB_SB_RESET; allqueue(REDRAWBUTSEDIT, 0); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWIMAGE, 0); @@ -5266,10 +5460,15 @@ static void object_panel_cloth(Object *ob) uiBut *but=NULL; static int val, val2; ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + PointCache *cache; + ModifierData *md; + int libdata = 0; block= uiNewBlock(&curarea->uiblocks, "object_cloth", UI_EMBOSS, UI_HELV, curarea->win); if(uiNewPanel(curarea, block, "Cloth ", "Physics", 640, 0, 318, 204)==0) return; - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + + libdata= object_is_libdata(ob); + uiSetButLock(libdata, ERROR_LIBDATA_MESSAGE); val = (clmd ? 1:0); @@ -5281,6 +5480,14 @@ static void object_panel_cloth(Object *ob) { but = uiDefButI(block, TOG, REDRAWBUTSOBJECT, "Cloth", 10,200,130,20, &val, 0, 0, 0, 0, "Sets object to become cloth"); uiButSetFunc(but, object_cloth__enabletoggle, ob, NULL); + + md = (ModifierData*)clmd; + if(md) { + uiBlockBeginAlign(block); + uiDefIconButBitI(block, TOG, eModifierMode_Render, B_BAKE_CACHE_CHANGE, ICON_SCENE, 145, 200, 20, 20,&md->mode, 0, 0, 1, 0, "Enable cloth during rendering"); + but= uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_BAKE_CACHE_CHANGE, VICON_VIEW3D, 165, 200, 20, 20,&md->mode, 0, 0, 1, 0, "Enable cloth during interactive display"); + uiBlockEndAlign(block); + } } uiDefBut(block, LABEL, 0, "",10,10,300,0, NULL, 0.0, 0, 0, 0, ""); /* tell UI we go to 10,10*/ @@ -5292,45 +5499,50 @@ static void object_panel_cloth(Object *ob) char clmvg [] = "Vertex Groups%t|"; val2=0; + cache= clmd->point_cache; /* GENERAL STUFF */ - uiClearButLock(); - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE) uiSetButLock(1, "Please leave editmode."); - else if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT) uiSetButLock(1, "Cache is protected"); + if(!libdata) { + uiClearButLock(); + if(cache->flag & PTCACHE_BAKE_EDIT_ACTIVE) + uiSetButLock(1, "Please leave editmode."); + else if(cache->flag & PTCACHE_BAKED) + uiSetButLock(1, "Simulation frames are baked"); + } uiDefBut(block, LABEL, 0, "Material Preset:", 10,170,150,20, NULL, 0.0, 0, 0, 0, ""); - but=uiDefButS(block, MENU, B_CLOTH_RENEW, "Silk %x1|Cotton %x2|Rubber %x3|Denim %x4|Leather %x5|Custom %x0", + but=uiDefButS(block, MENU, B_BAKE_CACHE_CHANGE, "Silk %x1|Cotton %x2|Rubber %x3|Denim %x4|Leather %x5|Custom %x0", 160,170,150,20, &clmd->sim_parms->presets, 0, 0, 0, 0, ""); uiButSetFunc(but, cloth_presets_material, ob, NULL); uiBlockBeginAlign(block); - but = uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff:", 10,150,150,20, &clmd->sim_parms->structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure"); + but = uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "StructStiff:", 10,150,150,20, &clmd->sim_parms->structural, 1.0, 10000.0, 100, 0, "Overall stiffness of structure"); uiButSetFunc(but, cloth_presets_custom_material, ob, NULL); - but = uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff:", 160,150,150,20, &clmd->sim_parms->bending, 0.0, 10000.0, 1000, 0, "Wrinkle coefficient (higher = less smaller but more big wrinkles)"); + but = uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "BendStiff:", 160,150,150,20, &clmd->sim_parms->bending, 0.0, 10000.0, 1000, 0, "Wrinkle coefficient (higher = less smaller but more big wrinkles)"); uiButSetFunc(but, cloth_presets_custom_material, ob, NULL); - but = uiDefButF(block, NUM, B_CLOTH_RENEW, "Spring Damp:", 10,130,150,20, &clmd->sim_parms->Cdis, 0.0, 50.0, 100, 0, "Damping of cloth velocity (higher = more smooth, less jiggling)"); + but = uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Spring Damp:", 10,130,150,20, &clmd->sim_parms->Cdis, 0.0, 50.0, 100, 0, "Damping of cloth velocity (higher = more smooth, less jiggling)"); uiButSetFunc(but, cloth_presets_custom_material, ob, NULL); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Air Damp:", 160,130,150,20, &clmd->sim_parms->Cvi, 0.0, 10.0, 10, 0, "Air has normaly some thickness which slows falling things down"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Air Damp:", 160,130,150,20, &clmd->sim_parms->Cvi, 0.0, 10.0, 10, 0, "Air has normaly some thickness which slows falling things down"); - uiDefButI(block, NUM, B_CLOTH_RENEW, "Quality:", 10,110,150,20, &clmd->sim_parms->stepsPerFrame, 4.0, 80.0, 5, 0, "Quality of the simulation (higher=better=slower)"); + uiDefButI(block, NUM, B_BAKE_CACHE_CHANGE, "Quality:", 10,110,150,20, &clmd->sim_parms->stepsPerFrame, 4.0, 80.0, 5, 0, "Quality of the simulation (higher=better=slower)"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Mass:", 160,110,150,20, &clmd->sim_parms->mass, 0.0, 10.0, 1000, 0, "Mass of cloth material."); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Mass:", 160,110,150,20, &clmd->sim_parms->mass, 0.0, 10.0, 1000, 0, "Mass of cloth material."); uiDefBut(block, LABEL, 0, "Gravity:", 10,90,60,20, NULL, 0.0, 0, 0, 0, ""); - uiDefButF(block, NUM, B_CLOTH_RENEW, "X:", 70,90,80,20, &clmd->sim_parms->gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Y:", 150,90,80,20, &clmd->sim_parms->gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Z:", 230,90,80,20, &clmd->sim_parms->gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "X:", 70,90,80,20, &clmd->sim_parms->gravity[0], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Y:", 150,90,80,20, &clmd->sim_parms->gravity[1], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Z:", 230,90,80,20, &clmd->sim_parms->gravity[2], -100.0, 100.0, 10, 0, "Apply gravitation to point movement"); uiBlockEndAlign(block); /* GOAL STUFF */ uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, B_CLOTH_RENEW, "Pinning of cloth", 10,60,150,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position"); + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_GOAL, B_BAKE_CACHE_CHANGE, "Pinning of cloth", 10,60,150,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Define forces for vertices to stick to animated position"); if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) && (BLI_countlist (&ob->defbase) > 0)) { @@ -5359,18 +5571,18 @@ static void object_panel_cloth(Object *ob) sprintf (clvg2, "%s%s", clmvg, clvg1); - uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 160,60,150,20, &clmd->sim_parms->vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups"); + uiDefButS(block, MENU, B_BAKE_CACHE_CHANGE, clvg2, 160,60,150,20, &clmd->sim_parms->vgroup_mass, 0, defCount, 0, 0, "Browses available vertex groups"); MEM_freeN (clvg1); MEM_freeN (clvg2); } - uiDefButF(block, NUM, B_CLOTH_RENEW, "Pin Stiff:", 10,40,150,20, &clmd->sim_parms->goalspring, 0.0, 50.0, 50, 0, "Pin (vertex target position) spring stiffness"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Pin Stiff:", 10,40,150,20, &clmd->sim_parms->goalspring, 0.0, 50.0, 50, 0, "Pin (vertex target position) spring stiffness"); uiDefBut(block, LABEL, 0, "",160,40,150,20, NULL, 0.0, 0, 0, 0, ""); - // uiDefButI(block, NUM, B_CLOTH_RENEW, "Pin Damp:", 160,50,150,20, &clmd->sim_parms->goalfrict, 1.0, 100.0, 10, 0, "Pined damping (higher = doesn't oszilate so much)"); + // uiDefButI(block, NUM, B_BAKE_CACHE_CHANGE, "Pin Damp:", 160,50,150,20, &clmd->sim_parms->goalfrict, 1.0, 100.0, 10, 0, "Pined damping (higher = doesn't oszilate so much)"); /* // nobody is changing these ones anyway - uiDefButF(block, NUM, B_CLOTH_RENEW, "G Min:", 10,30,150,20, &clmd->sim_parms->mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "G Max:", 160,30,150,20, &clmd->sim_parms->maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "G Min:", 10,30,150,20, &clmd->sim_parms->mingoal, 0.0, 1.0, 10, 0, "Goal minimum, vertex group weights are scaled to match this range"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "G Max:", 160,30,150,20, &clmd->sim_parms->maxgoal, 0.0, 1.0, 10, 0, "Goal maximum, vertex group weights are scaled to match this range"); */ } else if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_GOAL) @@ -5400,78 +5612,42 @@ static void object_panel_cloth(Object *ob) uiBlockEndAlign(block); } -static void object_cloth__protecttoggle(void *ob_v, void *arg2) -{ - Object *ob = ob_v; - int cageIndex, stack_index; - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - - // automatically enable modifier in editmode when we havee a protected cache - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT) - { - cageIndex = modifiers_getCageIndex(ob_v, NULL ); - stack_index = modifiers_indexInObject(ob_v, (ModifierData *)clmd); - if( stack_index >= cageIndex ) - ((ModifierData *)clmd)->mode ^= eModifierMode_OnCage; - } - else - { - ((ModifierData *)clmd)->mode ^= eModifierMode_OnCage; - } - -} - - static void object_panel_cloth_II(Object *ob) { uiBlock *block; - uiBut *but = NULL; ClothModifierData *clmd = NULL; + PointCache *cache; + static PTCacheID staticpid; + int libdata; block= uiNewBlock(&curarea->uiblocks, "object_cloth_II", UI_EMBOSS, UI_HELV, curarea->win); uiNewPanelTabbed("Cloth ", "Physics"); - if(uiNewPanel(curarea, block, "Cloth Cache/Collisions", "Physics", 651, 0, 318, 204)==0) return; + if(uiNewPanel(curarea, block, "Cloth Collision", "Physics", 651, 0, 318, 204)==0) return; - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + libdata= object_is_libdata(ob); + uiSetButLock(libdata, ERROR_LIBDATA_MESSAGE); clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); if(clmd) - { - uiClearButLock(); - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE) uiSetButLock(1, "Please leave editmode."); - else if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT) uiSetButLock(1, "Cache is protected"); - - uiDefButI(block, NUM, B_CLOTH_RENEW, "First Frame:",10,160,150,20, &clmd->sim_parms->firstframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation starts"); - uiDefButI(block, NUM, B_CLOTH_RENEW, "Last Frame:",160,160,150,20, &clmd->sim_parms->lastframe, 0, MAXFRAME, 1, 0, "Frame on which the simulation stops"); - - uiDefBut(block, LABEL, 0, "",10,140,300,20, NULL, 0.0, 0, 0, 0, ""); - - if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE)) - { - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT) - uiClearButLock(); - } - - if (!G.relbase_valid) - { - uiDefBut(block, LABEL, 0, "Cache deactivated until file is saved.", 10,120,300,20, NULL, 0.0, 0, 0, 0, ""); - uiDefBut(block, LABEL, 0, " ", 10,100,300,40, NULL, 0.0, 0, 0, 0, ""); - } - else - { - but = uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT, REDRAWVIEW3D, "Protect Cache & Enable Cache Editing", 10,120,300,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Protect cache from automatic freeing when scene changed. This also enabled the cache beeing edited in editmode."); - uiButSetFunc(but, object_cloth__protecttoggle, ob, NULL); - uiDefBut(block, LABEL, 0, "Clear cache:", 10,100,90,20, NULL, 0.0, 0, 0, 0, ""); - uiDefBut(block, BUT, B_CLOTH_CLEARCACHEALL, "All", 100, 100,100,20, NULL, 0.0, 0.0, 10, 0, "Free ALL cloth cache without preroll"); - uiDefBut(block, BUT, B_CLOTH_CLEARCACHEFRAME, "From next frame", 200, 100,110,20, NULL, 0.0, 0.0, 10, 0, "Free cloth cache starting from next frame"); - uiDefBut(block, LABEL, 0, " ", 10,80,300,20, NULL, 0.0, 0, 0, 0, ""); + { + BKE_ptcache_id_from_cloth(&staticpid, ob, clmd); + cache= staticpid.cache; + + if(!libdata) { + uiClearButLock(); + if(cache->flag & PTCACHE_BAKE_EDIT_ACTIVE) + uiSetButLock(1, "Please leave editmode."); } - - if(!(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE)) - { - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT) - uiSetButLock(1, "Cache is protected"); + + object_physics_bake_buttons(block, &staticpid, 135, libdata); + + uiDefBut(block, LABEL, 0, "",10,140,300,20, NULL, 0.0, 0, 0, 0, ""); + + if(!libdata) { + if(!(cache->flag & PTCACHE_BAKE_EDIT_ACTIVE)) + if(cache->flag & PTCACHE_BAKED) + uiSetButLock(1, "Simulation frames are baked"); } /* @@ -5482,19 +5658,19 @@ static void object_panel_cloth_II(Object *ob) uiDefBut(block, LABEL, 0, " ", 10,80,145,20, NULL, 0.0, 0, 0, 0, ""); */ #if WITH_BULLET == 1 - uiDefButBitI(block, TOG, CLOTH_COLLSETTINGS_FLAG_ENABLED, B_CLOTH_RENEW, "Enable collisions", 10,60,150,20, &clmd->coll_parms->flags, 0, 0, 0, 0, "Enable collisions with this object"); + uiDefButBitI(block, TOG, CLOTH_COLLSETTINGS_FLAG_ENABLED, B_BAKE_CACHE_CHANGE, "Enable collisions", 10,60,150,20, &clmd->coll_parms->flags, 0, 0, 0, 0, "Enable collisions with this object"); if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_ENABLED) { - uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 160,60,150,20, &clmd->coll_parms->epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in, can be changed for each frame"); - uiDefButS(block, NUM, B_CLOTH_RENEW, "Collision Quality:", 10,40,150,20, &clmd->coll_parms->loop_count, 1.0, 20.0, 1.0, 0, "How many collision iterations should be done. (higher = better = slower)"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "Friction:", 160,40,150,20, &clmd->coll_parms->friction, 0.0, 80.0, 1.0, 0, "Friction force if a collision happened (0=movement not changed, 100=no movement left)"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Min Distance:", 160,60,150,20, &clmd->coll_parms->epsilon, 0.001f, 1.0, 0.01f, 0, "Minimum distance between collision objects before collision response takes in, can be changed for each frame"); + uiDefButS(block, NUM, B_BAKE_CACHE_CHANGE, "Collision Quality:", 10,40,150,20, &clmd->coll_parms->loop_count, 1.0, 20.0, 1.0, 0, "How many collision iterations should be done. (higher = better = slower)"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Friction:", 160,40,150,20, &clmd->coll_parms->friction, 0.0, 80.0, 1.0, 0, "Friction force if a collision happened (0=movement not changed, 100=no movement left)"); - uiDefButBitI(block, TOG, CLOTH_COLLSETTINGS_FLAG_SELF, B_CLOTH_RENEW, "Enable selfcollisions", 10,20,150,20, &clmd->coll_parms->flags, 0, 0, 0, 0, "Enable selfcollisions with this object"); + uiDefButBitI(block, TOG, CLOTH_COLLSETTINGS_FLAG_SELF, B_BAKE_CACHE_CHANGE, "Enable selfcollisions", 10,20,150,20, &clmd->coll_parms->flags, 0, 0, 0, 0, "Enable selfcollisions with this object"); if (clmd->coll_parms->flags & CLOTH_COLLSETTINGS_FLAG_SELF) { - uiDefButF(block, NUM, B_CLOTH_RENEW, "Min Distance:", 160,20,150,20, &clmd->coll_parms->selfepsilon, 0.5f, 1.0, 0.01f, 0, "0.5 means no distance at all, 1.0 is maximum distance"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "Min Distance:", 160,20,150,20, &clmd->coll_parms->selfepsilon, 0.5f, 1.0, 0.01f, 0, "0.5 means no distance at all, 1.0 is maximum distance"); // self_loop_count - uiDefButS(block, NUM, B_CLOTH_RENEW, "Selfcoll Quality:", 10,0,150,20, &clmd->coll_parms->self_loop_count, 1.0, 10.0, 1.0, 0, "How many selfcollision iterations should be done. (higher = better = slower), can be changed for each frame"); + uiDefButS(block, NUM, B_BAKE_CACHE_CHANGE, "Selfcoll Quality:", 10,0,150,20, &clmd->coll_parms->self_loop_count, 1.0, 10.0, 1.0, 0, "How many selfcollision iterations should be done. (higher = better = slower), can be changed for each frame"); } else uiDefBut(block, LABEL, 0, "",160,20,150,20, NULL, 0.0, 0, 0, 0, ""); @@ -5514,12 +5690,15 @@ static void object_panel_cloth_III(Object *ob) { uiBlock *block; ClothModifierData *clmd = NULL; + PointCache *cache; + int libdata; block= uiNewBlock(&curarea->uiblocks, "object_cloth_III", UI_EMBOSS, UI_HELV, curarea->win); uiNewPanelTabbed("Cloth ", "Physics"); if(uiNewPanel(curarea, block, "Cloth Advanced", "Physics", 651, 0, 318, 204)==0) return; - uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); + libdata= object_is_libdata(ob); + uiSetButLock(libdata, ERROR_LIBDATA_MESSAGE); clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); @@ -5529,23 +5708,18 @@ static void object_panel_cloth_III(Object *ob) char *clvg1, *clvg2; char clmvg [] = "Vertex Groups%t|None%x0|"; char clmvg2 [] = "Vertex Groups%t|None%x0|"; + + cache= clmd->point_cache; - uiClearButLock(); - if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_EDITMODE) uiSetButLock(1, "Please leave editmode."); - else if(clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT) uiSetButLock(1, "Cache is protected"); - - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_AUTOPROTECT, REDRAWBUTSOBJECT, "Autoprotect cache",10,160,150,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "Enables automatic toggling of the 'Protect cache' button from the 2nd panel."); - - if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_AUTOPROTECT) - { - uiDefButI(block, NUM, B_DIFF, "From frame:",160,160,150,20, &clmd->sim_parms->autoprotect, 0.0, MAXFRAME + 1, 1, 0, "Frame on which the 'Protect Cache' button (2nd panel) is toggled automatically (To prevent accidently cleaning it)."); - } - else - { - uiDefBut(block, LABEL, 0, " ", 160,160,150,20, NULL, 0.0, 0, 0, 0, ""); + if(!libdata) { + uiClearButLock(); + if(cache->flag & PTCACHE_BAKE_EDIT_ACTIVE) + uiSetButLock(1, "Please leave editmode."); + else if(cache->flag & PTCACHE_BAKED) + uiSetButLock(1, "Simulation frames are baked"); } - - uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_SCALING, B_CLOTH_RENEW, "Enable stiffness scaling",10,130,300,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "If enabled, stiffness can be scaled along a weight painted vertex group."); + + uiDefButBitI(block, TOG, CLOTH_SIMSETTINGS_FLAG_SCALING, B_BAKE_CACHE_CHANGE, "Enable stiffness scaling",10,130,300,20, &clmd->sim_parms->flags, 0, 0, 0, 0, "If enabled, stiffness can be scaled along a weight painted vertex group."); if ((clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING)&& (BLI_countlist (&ob->defbase) > 0)) { @@ -5572,7 +5746,7 @@ static void object_panel_cloth_III(Object *ob) sprintf (clvg2, "%s%s", clmvg, clvg1); - uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 10,90,150,20, &clmd->sim_parms->vgroup_struct, 0, defCount, 0, 0, "Browses available vertex groups"); + uiDefButS(block, MENU, B_BAKE_CACHE_CHANGE, clvg2, 10,90,150,20, &clmd->sim_parms->vgroup_struct, 0, defCount, 0, 0, "Browses available vertex groups"); MEM_freeN (clvg1); MEM_freeN (clvg2); @@ -5596,19 +5770,19 @@ static void object_panel_cloth_III(Object *ob) sprintf (clvg2, "%s%s", clmvg2, clvg1); - uiDefButS(block, MENU, B_CLOTH_RENEW, clvg2, 160,90,150,20, &clmd->sim_parms->vgroup_bend, 0, defCount, 0, 0, "Browses available vertex groups"); + uiDefButS(block, MENU, B_BAKE_CACHE_CHANGE, clvg2, 160,90,150,20, &clmd->sim_parms->vgroup_bend, 0, defCount, 0, 0, "Browses available vertex groups"); MEM_freeN (clvg1); MEM_freeN (clvg2); - uiDefButF(block, NUM, B_CLOTH_RENEW, "StructStiff Max:",10,70,150,20, &clmd->sim_parms->max_struct, clmd->sim_parms->structural, 10000.0, 0.01f, 0, "Maximum structural stiffness value"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "StructStiff Max:",10,70,150,20, &clmd->sim_parms->max_struct, clmd->sim_parms->structural, 10000.0, 0.01f, 0, "Maximum structural stiffness value"); - uiDefButF(block, NUM, B_CLOTH_RENEW, "BendStiff Max:",160,70,150,20, &clmd->sim_parms->max_bend, clmd->sim_parms->bending, 10000.0, 0.01f, 0, "Maximum bending stiffness value"); + uiDefButF(block, NUM, B_BAKE_CACHE_CHANGE, "BendStiff Max:",160,70,150,20, &clmd->sim_parms->max_bend, clmd->sim_parms->bending, 10000.0, 0.01f, 0, "Maximum bending stiffness value"); } else if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING) { uiDefBut(block, LABEL, 0, " ", 10,110,300,20, NULL, 0.0, 0, 0, 0, ""); - uiDefBut(block, LABEL, 0, "No vertex group for pinning available.", 10,90,300,20, NULL, 0.0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "No vertex group for stiffness scaling available.", 10,90,300,20, NULL, 0.0, 0, 0, 0, ""); } @@ -5642,9 +5816,9 @@ void physics_panels() /* check context here */ ob= OBACT; if(ob) { - if(ob->type==OB_MESH) - object_panel_deflection(ob); object_panel_fields(ob); + if(ob->type==OB_MESH) + object_panel_collision(ob); object_softbodies(ob); object_softbodies_collision(ob); object_softbodies_solver(ob); @@ -5666,7 +5840,8 @@ void particle_panels() psys=psys_get_current(ob); - if(psys){ + if(psys ){ + object_panel_particle_bake(ob); object_panel_particle_physics(ob); object_panel_particle_visual(ob); object_panel_particle_simplification(ob); diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index b6b1f632041..faab326ee6b 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -3507,34 +3507,28 @@ static int cached_dynamics(int sfra, int efra) { Base *base = G.scene->base.first; Object *ob; - ModifierData *md; ParticleSystem *psys; - int i, stack_index=-1, cached=1; + int i, cached=1; + PTCacheID pid; while(base && cached) { ob = base->object; if(ob->softflag & OB_SB_ENABLE && ob->soft) { - for(i=0, md=ob->modifiers.first; md; i++, md=md->next) { - if(md->type == eModifierType_Softbody) { - stack_index = i; - break; - } - } + BKE_ptcache_id_from_softbody(&pid, ob, ob->soft); + for(i=sfra; i<=efra && cached; i++) - cached &= BKE_ptcache_id_exist(&ob->id,i,stack_index); + cached &= BKE_ptcache_id_exist(&pid, i); } for(psys=ob->particlesystem.first; psys; psys=psys->next) { - stack_index = modifiers_indexInObject(ob,(ModifierData*)psys_get_modifier(ob,psys)); if(psys->part->type==PART_HAIR) { - if(psys->softflag & OB_SB_ENABLE && psys->soft); - else - stack_index = -1; - } + if(psys->softflag & OB_SB_ENABLE && psys->soft) { + BKE_ptcache_id_from_softbody(&pid, ob, psys->soft); - if(stack_index >= 0) - for(i=sfra; i<=efra && cached; i++) - cached &= BKE_ptcache_id_exist(&ob->id,i,stack_index); + for(i=sfra; i<=efra && cached; i++) + cached &= BKE_ptcache_id_exist(&pid, i); + } + } } base = base->next; diff --git a/source/blender/src/edit.c b/source/blender/src/edit.c index 9190b3263f0..504c2ab107f 100644 --- a/source/blender/src/edit.c +++ b/source/blender/src/edit.c @@ -842,6 +842,11 @@ void countall() G.totobj+=tot; count_object(ob, base->flag & SELECT, tot); } + else if((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) { + int tot= count_duplilist(ob); + G.totobj+=tot; + count_object(ob, base->flag & SELECT, tot); + } else { count_object(ob, base->flag & SELECT, 1); G.totobj++; @@ -1301,7 +1306,7 @@ void snap_sel_to_grid() base= base->next; } - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); allqueue(REDRAWVIEW3D, 0); } @@ -1414,7 +1419,7 @@ void snap_sel_to_curs() base= base->next; } - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); allqueue(REDRAWVIEW3D, 0); } @@ -1819,7 +1824,7 @@ void snap_to_center() base= base->next; } - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); allqueue(REDRAWVIEW3D, 0); } diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index fb8a3e5f769..e5c92de5e98 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -349,18 +349,6 @@ void editipo_changed(SpaceIpo *si, int doredraw) allqueue(REDRAWVIEW3D, 0); } else if(si->blocktype==ID_PA){ - Object *ob=OBACT; - ParticleSystem *psys = ob->particlesystem.first; - - /* find out if we need to initialize particles */ - for(; psys; psys=psys->next) { - if(psys->part->ipo==si->ipo) { - ei= si->editipo; - for(a=0; a<si->totipo; a++, ei++) - if(ei->icu && ELEM3(ei->icu->adrcode,PART_EMIT_FREQ,PART_EMIT_LIFE,PART_EMIT_SIZE)) - psys_flush_settings(psys->part,PSYS_INIT,1); - } - } DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); allqueue(REDRAWVIEW3D, 0); } @@ -3499,7 +3487,7 @@ void common_insertkey(void) else if(event==13) BIF_undo_push("Insert VisualLocRot Key"); else if(event==15) BIF_undo_push("Insert Needed Key"); - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); allspace(REMAKEIPO, 0); allqueue(REDRAWIPO, 0); diff --git a/source/blender/src/editmesh.c b/source/blender/src/editmesh.c index 2c1118bb588..765374f9967 100644 --- a/source/blender/src/editmesh.c +++ b/source/blender/src/editmesh.c @@ -77,6 +77,7 @@ #include "BKE_multires.h" #include "BKE_object.h" #include "BKE_pointcache.h" +#include "BKE_softbody.h" #include "BKE_texture.h" #include "BKE_utildefines.h" @@ -796,6 +797,78 @@ static void edge_drawflags(void) } } +static int editmesh_pointcache_edit(Object *ob, int totvert, PTCacheID *pid_p, float mat[][4], int load) +{ + Cloth *cloth; + SoftBody *sb; + ClothModifierData *clmd; + PTCacheID pid, tmpid; + int cfra= (int)G.scene->r.cfra, found= 0; + + pid.cache= NULL; + + /* check for cloth */ + if(modifiers_isClothEnabled(ob)) { + clmd= (ClothModifierData*)modifiers_findByType(ob, eModifierType_Cloth); + cloth= clmd->clothObject; + + BKE_ptcache_id_from_cloth(&tmpid, ob, clmd); + + /* verify vertex count and baked status */ + if(cloth && (totvert == cloth->numverts)) { + if((tmpid.cache->flag & PTCACHE_BAKED) && (tmpid.cache->flag & PTCACHE_BAKE_EDIT)) { + pid= tmpid; + + if(load && (pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE)) + found= 1; + } + } + } + + /* check for softbody */ + if(!found && ob->soft) { + sb= ob->soft; + + BKE_ptcache_id_from_softbody(&tmpid, ob, sb); + + /* verify vertex count and baked status */ + if(sb->bpoint && (totvert == sb->totpoint)) { + if((tmpid.cache->flag & PTCACHE_BAKED) && (tmpid.cache->flag & PTCACHE_BAKE_EDIT)) { + pid= tmpid; + + if(load && (pid.cache->flag & PTCACHE_BAKE_EDIT_ACTIVE)) + found= 1; + } + } + } + + /* if not making editmesh verify editing was active for this point cache */ + if(load) { + if(found) + pid.cache->flag &= ~PTCACHE_BAKE_EDIT_ACTIVE; + else + return 0; + } + + /* check if we have cache for this frame */ + if(pid.cache && BKE_ptcache_id_exist(&pid, cfra)) { + *pid_p = pid; + + if(load) { + Mat4CpyMat4(mat, ob->obmat); + } + else { + pid.cache->editframe= cfra; + pid.cache->flag |= PTCACHE_BAKE_EDIT_ACTIVE; + Mat4Invert(mat, ob->obmat); /* ob->imat is not up to date */ + } + + return 1; + } + + return 0; +} + /* turns Mesh into editmesh */ void make_editMesh() { @@ -809,10 +882,11 @@ void make_editMesh() EditFace *efa; EditEdge *eed; EditSelection *ese; - int tot, a, eekadoodle= 0, cloth_enabled = 0; - ClothModifierData *clmd = NULL; - Cloth *cloth = NULL; - float temp[3]; + PTCacheID pid; + Cloth *cloth; + SoftBody *sb; + float cacheco[3], cachemat[4][4], *co; + int tot, a, cacheedit= 0, eekadoodle= 0; #ifdef WITH_VERSE if(me->vnode){ @@ -847,49 +921,29 @@ void make_editMesh() /* make editverts */ CustomData_copy(&me->vdata, &em->vdata, CD_MASK_EDITMESH, CD_CALLOC, 0); mvert= me->mvert; - - /* lots of checks to be sure if we have nice cloth object */ - if(modifiers_isClothEnabled(G.obedit)) - { - clmd = (ClothModifierData *) modifiers_findByType(G.obedit, eModifierType_Cloth); - cloth = clmd->clothObject; - - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_EDITMODE; - - /* just to be sure also check vertcount */ - /* also check if we have a protected cache */ - if(cloth && (tot == cloth->numverts) && (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) - { - /* check if we have cache for this frame */ - int stack_index = modifiers_indexInObject(G.obedit, (ModifierData *)clmd); - - if(BKE_ptcache_id_exist((ID *)G.obedit, G.scene->r.cfra, stack_index)) - { - cloth_enabled = 1; - - clmd->sim_parms->editedframe = G.scene->r.cfra; - - /* inverse matrix is not uptodate... */ - Mat4Invert ( G.obedit->imat, G.obedit->obmat ); - if(G.rt > 0) - printf("make_editmesh --> cloth_enabled\n"); - } - } - } + + cacheedit= editmesh_pointcache_edit(G.obedit, tot, &pid, cachemat, 0); evlist= (EditVert **)MEM_mallocN(tot*sizeof(void *),"evlist"); for(a=0; a<tot; a++, mvert++) { - if(cloth_enabled) - { - VECCOPY(temp, cloth->verts[a].x); - Mat4MulVecfl ( G.obedit->imat, temp ); - eve= addvertlist(temp, NULL); - - /* TODO: what about normals? */ + if(cacheedit) { + if(pid.type == PTCACHE_TYPE_CLOTH) { + cloth= ((ClothModifierData*)pid.data)->clothObject; + VECCOPY(cacheco, cloth->verts[a].x) + } + else if(pid.type == PTCACHE_TYPE_SOFTBODY) { + sb= (SoftBody*)pid.data; + VECCOPY(cacheco, sb->bpoint[a].pos) + } + + Mat4MulVecfl(cachemat, cacheco); + co= cacheco; } - else - eve= addvertlist(mvert->co, NULL); + else + co= mvert->co; + + eve= addvertlist(co, NULL); evlist[a]= eve; // face select sets selection in next loop @@ -1008,9 +1062,12 @@ void make_editMesh() EM_hide_reset(); /* sets helper flags which arent saved */ EM_fgon_flags(); + + /* vertex coordinates change with cache edit, need to recalc */ + if(cacheedit) + recalc_editnormals(); countall(); - } /* makes Mesh out of editmesh */ @@ -1026,11 +1083,12 @@ void load_editMesh(void) EditFace *efa, *efa_act; EditEdge *eed; EditSelection *ese; - float *fp, *newkey, *oldkey, nor[3]; - int i, a, ototvert, totedge=0, cloth_enabled = 0; - ClothModifierData *clmd = NULL; - Cloth *cloth = NULL; - float temp[3], dt = 0.0; + SoftBody *sb; + Cloth *cloth; + ClothModifierData *clmd; + PTCacheID pid; + float *fp, *newkey, *oldkey, nor[3], cacheco[3], cachemat[4][4]; + int i, a, ototvert, totedge=0, cacheedit= 0; #ifdef WITH_VERSE if(em->vnode) { @@ -1097,60 +1155,50 @@ void load_editMesh(void) /* the vertices, use ->tmp.l as counter */ eve= em->verts.first; a= 0; - - /* lots of checks to be sure if we have nice cloth object */ - if(modifiers_isClothEnabled(G.obedit)) - { - clmd = (ClothModifierData *) modifiers_findByType(G.obedit, eModifierType_Cloth); - cloth = clmd->clothObject; - - /* just to be sure also check vertcount */ - /* also check if we have a protected cache */ - if(cloth && (G.totvert == cloth->numverts) && (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_CCACHE_PROTECT)) - { - /* check if we have cache for this frame */ - int stack_index = modifiers_indexInObject(G.obedit, (ModifierData *)clmd); - - if(BKE_ptcache_id_exist((ID *)G.obedit, clmd->sim_parms->editedframe, stack_index)) - { - cloth_enabled = 1; - - /* inverse matrix is not uptodate... */ - Mat4Invert ( G.obedit->imat, G.obedit->obmat ); - dt = 1.0f / clmd->sim_parms->stepsPerFrame; - } - if(G.rt > 0) - printf("loadmesh --> tot: %d, num: %d\n", G.totvert, cloth->numverts); - } - } - - i=0; + + /* check for point cache editing */ + cacheedit= editmesh_pointcache_edit(G.obedit, G.totvert, &pid, cachemat, 1); + while(eve) { - - if(cloth_enabled) - { - if(G.rt > 0) - printf("loadmesh --> cloth_enabled\n"); - - VECCOPY(temp, cloth->verts[i].x); - VECCOPY(cloth->verts[i].x, eve->co); - Mat4MulVecfl ( G.obedit->obmat, cloth->verts[i].x ); - - - // not physical correct but gives nicer results when commented - VECSUB(temp, cloth->verts[i].x, temp); - VecMulf(temp, 1.0f / (dt*10.0)); - VECADD(cloth->verts[i].v, cloth->verts[i].v, temp); - - if(oldverts) { - VECCOPY(mvert->co, oldverts[i].co); - if(G.rt > 0) - printf("loadmesh --> cloth_enabled oldverts\n"); + if(cacheedit) { + if(pid.type == PTCACHE_TYPE_CLOTH) { + clmd= (ClothModifierData*)pid.data; + cloth= clmd->clothObject; + + /* assign position */ + VECCOPY(cacheco, cloth->verts[a].x) + VECCOPY(cloth->verts[a].x, eve->co); + Mat4MulVecfl(cachemat, cloth->verts[a].x); + + /* find plausible velocity, not physical correct but gives + * nicer results when commented */ + VECSUB(cacheco, cloth->verts[a].x, cacheco); + VecMulf(cacheco, clmd->sim_parms->stepsPerFrame*10.0f); + VECADD(cloth->verts[a].v, cloth->verts[a].v, cacheco); + } + else if(pid.type == PTCACHE_TYPE_SOFTBODY) { + sb= (SoftBody*)pid.data; + + /* assign position */ + VECCOPY(cacheco, sb->bpoint[a].pos) + VECCOPY(sb->bpoint[a].pos, eve->co); + Mat4MulVecfl(cachemat, sb->bpoint[a].pos); + + /* changing velocity for softbody doesn't seem to give + * good results? */ +#if 0 + VECSUB(cacheco, sb->bpoint[a].pos, cacheco); + VecMulf(cacheco, sb->minloops*10.0f); + VECADD(sb->bpoint[a].vec, sb->bpoint[a].pos, cacheco); +#endif } - i++; + + if(oldverts) + VECCOPY(mvert->co, oldverts[a].co) } - else + else VECCOPY(mvert->co, eve->co); + mvert->mat_nr= 255; /* what was this for, halos? */ /* vertex normal */ @@ -1180,34 +1228,12 @@ void load_editMesh(void) mvert++; } - /* burn changes to cache */ - if(cloth_enabled) - { - if(G.rt > 0) - printf("loadmesh --> cloth_enabled cloth_write_cache\n"); - cloth_write_cache(G.obedit, clmd, clmd->sim_parms->editedframe); - - if(G.scene->r.cfra != clmd->sim_parms->editedframe) - { - if(cloth_read_cache(G.obedit, clmd, G.scene->r.cfra)) - implicit_set_positions(clmd); - } - else - implicit_set_positions(clmd); - - clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_EDITMODE; - } - else - { - if(modifiers_isClothEnabled(G.obedit)) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(G.obedit, eModifierType_Cloth); - if(G.rt > 0) - printf("loadmesh --> CLOTH_SIMSETTINGS_FLAG_RESET\n"); - /* only reset cloth when no cache was used */ - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_CCACHE_FFREE; - clmd->sim_parms->flags &= ~CLOTH_SIMSETTINGS_FLAG_EDITMODE; - } + /* write changes to cache */ + if(cacheedit) { + if(pid.type == PTCACHE_TYPE_CLOTH) + cloth_write_cache(G.obedit, pid.data, pid.cache->editframe); + else if(pid.type == PTCACHE_TYPE_SOFTBODY) + sbWriteCache(G.obedit, pid.cache->editframe); } /* the edges */ @@ -1469,12 +1495,9 @@ void load_editMesh(void) /* remake softbody of all users */ if(me->id.us>1) { Base *base; - for(base= G.scene->base.first; base; base= base->next) { - if(base->object->data==me) { - base->object->softflag |= OB_SB_REDO; + for(base= G.scene->base.first; base; base= base->next) + if(base->object->data==me) base->object->recalc |= OB_RECALC_DATA; - } - } } mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL); diff --git a/source/blender/src/editnla.c b/source/blender/src/editnla.c index 0fc8baae154..6d9adda85d0 100644 --- a/source/blender/src/editnla.c +++ b/source/blender/src/editnla.c @@ -2052,6 +2052,6 @@ void copy_action_modifiers(void) BIF_undo_push("Copy Action Modifiers"); allqueue(REDRAWNLA, 0); - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); } diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 07973926503..34b69bc1e64 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -339,6 +339,7 @@ void delete_obj(int ok) allqueue(REDRAWNLA, 0); DAG_scene_sort(G.scene); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); BIF_undo_push("Delete object(s)"); } @@ -964,7 +965,7 @@ void clear_parent(void) } DAG_scene_sort(G.scene); - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWOOPS, 0); @@ -1125,7 +1126,7 @@ void clear_object(char mode) allqueue(REDRAWVIEW3D, 0); if(armature_clear==0) /* in this case flush was done */ - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); BIF_undo_push(str); } @@ -1625,7 +1626,7 @@ void make_parent(void) allqueue(REDRAWOOPS, 0); DAG_scene_sort(G.scene); - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); BIF_undo_push("make Parent"); } @@ -1787,20 +1788,6 @@ void exit_editmode(int flag) /* freedata==0 at render, 1= freedata, 2= do undo b /* for example; displist make is different in editmode */ if(freedata) G.obedit= NULL; - /* total remake of softbody data */ - if(modifiers_isSoftbodyEnabled(ob)) { - if (ob->soft && ob->soft->keys) { - notice("Erase Baked SoftBody"); - } - - sbObjectToSoftbody(ob); - } - - if(modifiers_isClothEnabled(ob)) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; - } - if(ob->type==OB_MESH && get_mesh(ob)->mr) multires_edge_level_update(ob, get_mesh(ob)); @@ -2106,7 +2093,7 @@ void docenter(int centermode) base= base->next; } if (tot_change) { - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); allqueue(REDRAWVIEW3D, 0); BIF_undo_push("Do Center"); } @@ -3148,7 +3135,7 @@ void flip_subdivison(int level) allqueue(REDRAWOOPS, 0); allqueue(REDRAWBUTSEDIT, 0); allqueue(REDRAWBUTSOBJECT, 0); - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); if(particles) BIF_undo_push("Switch particles on/off"); @@ -3657,7 +3644,7 @@ void copy_attr(short event) if(do_scene_sort) DAG_scene_sort(G.scene); - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); if(event==20) { allqueue(REDRAWBUTSOBJECT, 0); @@ -3904,7 +3891,7 @@ void make_links(short event) allqueue(REDRAWOOPS, 0); allqueue(REDRAWBUTSHEAD, 0); - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); BIF_undo_push("Create links"); } @@ -5292,7 +5279,7 @@ void adduplicate(int mode, int dupflag) copy_object_set_idnew(dupflag); DAG_scene_sort(G.scene); - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); countall(); if(mode==0) { diff --git a/source/blender/src/editparticle.c b/source/blender/src/editparticle.c index 6543b3fa017..af323c9df9c 100644 --- a/source/blender/src/editparticle.c +++ b/source/blender/src/editparticle.c @@ -1126,9 +1126,6 @@ void PE_set_particle_edit(void) } else{ G.f &= ~G_PARTICLEEDIT; - - if(psys->soft) - psys->softflag |= OB_SB_REDO; } DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA); diff --git a/source/blender/src/fluidsim.c b/source/blender/src/fluidsim.c index ac90d3ed119..43d692a99c9 100644 --- a/source/blender/src/fluidsim.c +++ b/source/blender/src/fluidsim.c @@ -1129,6 +1129,11 @@ void fluidsimBake(struct Object *ob) } } +void fluidsimFreeBake(struct Object *ob) +{ + /* not implemented yet */ +} + #else /* DISABLE_ELBEEM */ @@ -1149,5 +1154,8 @@ FluidsimSettings* fluidsimSettingsCopy(FluidsimSettings *fss) { void fluidsimBake(struct Object *ob) { } +void fluidsimFreeBake(struct Object *ob) { +} + #endif /* DISABLE_ELBEEM */ diff --git a/source/blender/src/header_time.c b/source/blender/src/header_time.c index 7b98d2f5f4c..748dcac9233 100644 --- a/source/blender/src/header_time.c +++ b/source/blender/src/header_time.c @@ -56,6 +56,7 @@ #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_pointcache.h" #include "BSE_drawipo.h" #include "BSE_drawview.h" @@ -69,6 +70,24 @@ #include "butspace.h" #include "mydevice.h" +static void start_animated_screen(SpaceTime *stime) +{ + add_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM, stime->redraws); + + if(stime->redraws & TIME_WITH_SEQ_AUDIO) + audiostream_start( CFRA ); + + BKE_ptcache_set_continue_physics((stime->redraws & TIME_CONTINUE_PHYSICS)); +} + +static void end_animated_screen(SpaceTime *stime) +{ + rem_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM); + + audiostream_stop(); + BKE_ptcache_set_continue_physics(0); +} + void do_time_buttons(ScrArea *sa, unsigned short event) { SpaceTime *stime= sa->spacedata.first; @@ -80,17 +99,11 @@ void do_time_buttons(ScrArea *sa, unsigned short event) update_for_newframe(); break; case B_TL_PLAY: - add_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM, stime->redraws); - if(stime->redraws & TIME_WITH_SEQ_AUDIO) - audiostream_start( CFRA ); - + start_animated_screen(stime); break; case B_TL_STOP: - rem_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM); - if(stime->redraws & TIME_WITH_SEQ_AUDIO) - audiostream_stop(); + end_animated_screen(stime); allqueue(REDRAWALL, 0); - break; case B_TL_FF: /* end frame */ @@ -132,7 +145,7 @@ static void do_time_redrawmenu(void *arg, int event) stime->redraws ^= event; /* update handler when it's running */ if(has_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM)) - add_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM, stime->redraws); + start_animated_screen(stime); } else { if(event==1001) { @@ -182,6 +195,12 @@ static uiBlock *time_redrawmenu(void *arg_unused) sprintf(str, "Set Frames/Sec (%d/%f)", G.scene->r.frs_sec, G.scene->r.frs_sec_base); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, str, 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1001, ""); + + uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + + if(stime->redraws & TIME_CONTINUE_PHYSICS) icon= ICON_CHECKBOX_HLT; + else icon= ICON_CHECKBOX_DEHLT; + uiDefIconTextBut(block, BUTM, 1, icon, "Continue Physics", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, TIME_CONTINUE_PHYSICS, "During playblack, continue physics simulations regardless of the frame number"); if(curarea->headertype==HEADERTOP) { @@ -204,7 +223,8 @@ static void do_time_viewmenu(void *arg, int event) switch(event) { case 2: /* Play Back Animation */ - add_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM, stime->redraws); + if(!has_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM)) + start_animated_screen(stime); break; case 3: /* View All */ first= G.scene->r.sfra; diff --git a/source/blender/src/interface_panel.c b/source/blender/src/interface_panel.c index de1e70caeec..05a84ed301e 100644 --- a/source/blender/src/interface_panel.c +++ b/source/blender/src/interface_panel.c @@ -876,8 +876,8 @@ static void ui_draw_panel_header(uiBlock *block) Panel *pa, *panel= block->panel; float width; int a, nr= 1, pnl_icons; - char *panelname= panel->drawname[0]?panel->drawname:panel->panelname; - char *str; + char *activename= panel->drawname[0]?panel->drawname:panel->panelname; + char *panelname, *str; /* count */ pa= curarea->panels.first; @@ -901,7 +901,7 @@ static void ui_draw_panel_header(uiBlock *block) /* draw text label */ BIF_ThemeColor(TH_TEXT_HI); ui_rasterpos_safe(4.0f+block->minx+pnl_icons, block->maxy+5.0f, block->aspect); - BIF_DrawString(block->curfont, panelname, (U.transopts & USER_TR_BUTTONS)); + BIF_DrawString(block->curfont, activename, (U.transopts & USER_TR_BUTTONS)); return; } @@ -915,6 +915,8 @@ static void ui_draw_panel_header(uiBlock *block) pa= curarea->panels.first; while(pa) { panelname= pa->drawname[0]?pa->drawname:pa->panelname; + if(a == 0) + activename= panelname; if(pa->active==0); else if(pa==panel) { @@ -928,7 +930,10 @@ static void ui_draw_panel_header(uiBlock *block) /* draw the active text label */ BIF_ThemeColor(TH_TEXT); ui_rasterpos_safe(16+pnl_icons+a*width, panel->sizey+4, block->aspect); - str= ui_block_cut_str(block, panelname, (short)(width-10)); + if(panelname != activename && strstr(panelname, activename) == panelname) + str= ui_block_cut_str(block, panelname+strlen(activename), (short)(width-10)); + else + str= ui_block_cut_str(block, panelname, (short)(width-10)); BIF_DrawString(block->curfont, str, (U.transopts & USER_TR_BUTTONS)); a++; @@ -942,7 +947,10 @@ static void ui_draw_panel_header(uiBlock *block) /* draw an inactive tab label */ BIF_ThemeColorShade(TH_TEXT_HI, -40); ui_rasterpos_safe(16+pnl_icons+a*width, panel->sizey+4, block->aspect); - str= ui_block_cut_str(block, panelname, (short)(width-10)); + if(panelname != activename && strstr(panelname, activename) == panelname) + str= ui_block_cut_str(block, panelname+strlen(activename), (short)(width-10)); + else + str= ui_block_cut_str(block, panelname, (short)(width-10)); BIF_DrawString(block->curfont, str, (U.transopts & USER_TR_BUTTONS)); a++; diff --git a/source/blender/src/poselib.c b/source/blender/src/poselib.c index 14b3286c03b..769e83d7a2d 100644 --- a/source/blender/src/poselib.c +++ b/source/blender/src/poselib.c @@ -1144,7 +1144,6 @@ static void poselib_preview_init_data (tPoseLib_PreviewData *pld, Object *ob, sh /* After previewing poses */ static void poselib_preview_cleanup (tPoseLib_PreviewData *pld) { - Base *base; Object *ob= pld->ob; bPose *pose= pld->pose; bArmature *arm= pld->arm; @@ -1161,17 +1160,8 @@ static void poselib_preview_cleanup (tPoseLib_PreviewData *pld) /* old optimize trick... this enforces to bypass the depgraph * - note: code copied from transform_generics.c -> recalcData() */ - if ((arm->flag & ARM_DELAYDEFORM)==0) { + if ((arm->flag & ARM_DELAYDEFORM)==0) DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); /* sets recalc flags */ - - /* bah, softbody exception... recalcdata doesnt reset */ - for (base= FIRSTBASE; base; base= base->next) { - if (base->object->recalc & OB_RECALC_DATA) - if (modifiers_isSoftbodyEnabled(base->object)) { - base->object->softflag |= OB_SB_REDO; - } - } - } else where_is_pose(ob); @@ -1222,7 +1212,6 @@ static void poselib_preview_cleanup (tPoseLib_PreviewData *pld) void poselib_preview_poses (Object *ob, short apply_active) { tPoseLib_PreviewData pld; - Base *base; unsigned short event; short val=0; @@ -1252,17 +1241,8 @@ void poselib_preview_poses (Object *ob, short apply_active) /* old optimize trick... this enforces to bypass the depgraph * - note: code copied from transform_generics.c -> recalcData() */ - if ((pld.arm->flag & ARM_DELAYDEFORM)==0) { + if ((pld.arm->flag & ARM_DELAYDEFORM)==0) DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); /* sets recalc flags */ - - /* bah, softbody exception... recalcdata doesnt reset */ - for (base= FIRSTBASE; base; base= base->next) { - if (base->object->recalc & OB_RECALC_DATA) - if (modifiers_isSoftbodyEnabled(base->object)) { - base->object->softflag |= OB_SB_REDO; - } - } - } else where_is_pose(ob); } diff --git a/source/blender/src/space.c b/source/blender/src/space.c index ab6c2b0533a..94781693b68 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -88,6 +88,7 @@ #include "BKE_mesh.h" #include "BKE_multires.h" #include "BKE_node.h" +#include "BKE_pointcache.h" #include "BKE_scene.h" #include "BKE_sculpt.h" #include "BKE_texture.h" @@ -1841,12 +1842,26 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) view3d_border_zoom(); } else if(G.qual==LR_CTRLKEY) { - if(okee("Bake all selected")) { - extern void softbody_bake(Object *ob); - extern void fluidsimBake(Object *ob); - softbody_bake(NULL); - /* also bake first domain of selected objects... */ - fluidsimBake(NULL); + extern void pointcache_bake(PTCacheID *pid, int startframe); + extern void pointcache_free(PTCacheID *pid, int cacheonly); + extern void fluidsimBake(Object *ob); + extern void fluidsimFreeBake(Object *ob); + int pupval; + + pupval= pupmenu("Physics Baking%t|Bake selected %x1|Free bake selected %x2|Free cache selected %x3"); + + if(pupval > 0) { + if(pupval == 1) { + pointcache_bake(NULL, 0); + /* also bake first domain of selected objects... */ + fluidsimBake(NULL); + } + else if(pupval == 2) { + pointcache_free(NULL, 0); + fluidsimFreeBake(NULL); + } + else if(pupval == 3) + pointcache_free(NULL, 1); } } else if(G.qual== (LR_ALTKEY|LR_CTRLKEY)) diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c index 230e8b69de9..c8f8b158c3b 100644 --- a/source/blender/src/toets.c +++ b/source/blender/src/toets.c @@ -66,6 +66,8 @@ #include "BKE_image.h" #include "BKE_ipo.h" #include "BKE_key.h" +#include "BKE_object.h" +#include "BKE_pointcache.h" #include "BKE_scene.h" #include "BKE_utildefines.h" @@ -76,7 +78,6 @@ #include "BIF_imasel.h" #include "BIF_editparticle.h" #include "BIF_interface.h" -#include "BKE_object.h" #include "BIF_poseobject.h" #include "BIF_previewrender.h" #include "BIF_renderwin.h" @@ -701,6 +702,7 @@ int blenderqread(unsigned short event, short val) /* stop playback on ESC always */ rem_screenhandler(G.curscreen, SCREEN_HANDLER_ANIM); audiostream_stop(); + BKE_ptcache_set_continue_physics(0); allqueue(REDRAWALL, 0); break; diff --git a/source/blender/src/transform.c b/source/blender/src/transform.c index c153516705d..d92be2ec174 100644 --- a/source/blender/src/transform.c +++ b/source/blender/src/transform.c @@ -79,12 +79,13 @@ #include "BIF_editaction.h" #include "BKE_action.h" /* get_action_frame */ +#include "BKE_bad_level_calls.h"/* popmenu and error */ +#include "BKE_bmesh.h" #include "BKE_constraint.h" #include "BKE_global.h" -#include "BKE_utildefines.h" -#include "BKE_bad_level_calls.h"/* popmenu and error */ #include "BKE_particle.h" -#include "BKE_bmesh.h" +#include "BKE_pointcache.h" +#include "BKE_utildefines.h" #include "BSE_drawipo.h" #include "BSE_editnla_types.h" /* for NLAWIDTH */ @@ -1134,6 +1135,11 @@ void Transform() event= extern_qread(&val); transformEvent(event, val); } + + if(BKE_ptcache_get_continue_physics()) { + do_screenhandlers(G.curscreen); + Trans.redraw= 1; + } } diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 8d64aa16d7a..7efcdb93cbc 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -95,6 +95,7 @@ #include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_particle.h" +#include "BKE_pointcache.h" #include "BKE_softbody.h" #include "BKE_utildefines.h" #include "BKE_bmesh.h" @@ -3104,8 +3105,9 @@ static void set_trans_object_base_flags(TransInfo *t) ob->recalc |= OB_RECALC_OB; } } + /* all recalc flags get flushed to all layers, so a layer flip later on works fine */ - DAG_scene_flush_update(G.scene, -1); + DAG_scene_flush_update(G.scene, -1, 0); /* and we store them temporal in base (only used for transform code) */ /* this because after doing updates, the object->recalc is cleared */ @@ -3419,7 +3421,7 @@ static void recalc_all_ipos(void) } } -/* inserting keys, refresh ipo-keys, softbody, redraw events... (ton) */ +/* inserting keys, refresh ipo-keys, pointcache, redraw events... (ton) */ /* note: transdata has been freed already! */ void special_aftertrans_update(TransInfo *t) { @@ -3569,16 +3571,13 @@ void special_aftertrans_update(TransInfo *t) ob= base->object; - if (modifiers_isSoftbodyEnabled(ob)) ob->softflag |= OB_SB_REDO; - else if((ob == OBACT) && modifiers_isClothEnabled(ob)) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - if(clmd) - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; - } - - /* Set autokey if necessary */ - if ((!cancelled) && (t->mode != TFM_DUMMY) && (base->flag & SELECT)) { - autokeyframe_ob_cb_func(ob, t->mode); + if(base->flag & SELECT && (t->mode != TFM_DUMMY)) { + if(BKE_ptcache_object_reset(ob, PTCACHE_RESET_DEPSGRAPH)) + ob->recalc |= OB_RECALC_DATA; + + /* Set autokey if necessary */ + if (!cancelled) + autokeyframe_ob_cb_func(ob, t->mode); } base= base->next; diff --git a/source/blender/src/transform_generics.c b/source/blender/src/transform_generics.c index f5fc3ce517b..1e28b3076ba 100644 --- a/source/blender/src/transform_generics.c +++ b/source/blender/src/transform_generics.c @@ -308,7 +308,7 @@ void recalcData(TransInfo *t) base->object->ctime= -1234567.0f; // eveil! } - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); } } else if (t->spacetype == SPACE_IPO) { @@ -370,7 +370,7 @@ void recalcData(TransInfo *t) } base= base->next; } - DAG_scene_flush_update(G.scene, screen_view3d_layers()); + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); } } } @@ -475,21 +475,6 @@ void recalcData(TransInfo *t) /* old optimize trick... this enforces to bypass the depgraph */ if (!(arm->flag & ARM_DELAYDEFORM)) { DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); /* sets recalc flags */ - - /* bah, softbody exception... recalcdata doesnt reset */ - for(base= FIRSTBASE; base; base= base->next) { - if(base->object->recalc & OB_RECALC_DATA) - { - if(modifiers_isSoftbodyEnabled(base->object)) { - base->object->softflag |= OB_SB_REDO; - } - else if(modifiers_isClothEnabled(base->object)) { - ClothModifierData *clmd = (ClothModifierData *) modifiers_findByType(base->object, eModifierType_Cloth); - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; - } - - } - } } else where_is_pose(ob); @@ -501,12 +486,12 @@ void recalcData(TransInfo *t) for(base= FIRSTBASE; base; base= base->next) { Object *ob= base->object; - /* this flag is from depgraph, was stored in nitialize phase, handled in drawview.c */ + /* this flag is from depgraph, was stored in initialize phase, handled in drawview.c */ if(base->flag & BA_HAS_RECALC_OB) ob->recalc |= OB_RECALC_OB; if(base->flag & BA_HAS_RECALC_DATA) ob->recalc |= OB_RECALC_DATA; - + /* thanks to ob->ctime usage, ipos are not called in where_is_object, unless we edit ipokeys */ if(base->flag & BA_DO_IPO) { @@ -523,18 +508,6 @@ void recalcData(TransInfo *t) } } - /* softbody & cloth exception */ - if(ob->recalc & OB_RECALC_DATA) - { - if(modifiers_isSoftbodyEnabled(ob)) { - ob->softflag |= OB_SB_REDO; - } - else if(modifiers_isClothEnabled(ob)) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; - } - } - /* proxy exception */ if(ob->proxy) ob->proxy->recalc |= ob->recalc; @@ -557,7 +530,6 @@ void recalcData(TransInfo *t) /* update shaded drawmode while transform */ if(t->spacetype==SPACE_VIEW3D && G.vd->drawtype == OB_SHADED) reshadeall_displist(); - } void initTransModeFlags(TransInfo *t, int mode) diff --git a/source/blender/src/vpaint.c b/source/blender/src/vpaint.c index 63ab0616162..95ddade3de9 100644 --- a/source/blender/src/vpaint.c +++ b/source/blender/src/vpaint.c @@ -1347,23 +1347,6 @@ void weight_paint(void) copy_wpaint_prev(&Gwp, NULL, 0); DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); - /* this flag is event for softbody to refresh weightpaint values */ - if(ob->soft) ob->softflag |= OB_SB_REDO; - - /* same goes for cloth */ - if(modifiers_isClothEnabled(ob)) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - if(clmd) - { - /* check if we use the edited vertex group at all */ - if((clmd->sim_parms->vgroup_mass==ob->actdef) || - (clmd->sim_parms->vgroup_struct==ob->actdef)|| - (clmd->sim_parms->vgroup_bend==ob->actdef)) - { - clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESET; - } - } - } /* and particles too */ if(ob->particlesystem.first) { |