diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2011-01-02 21:34:32 +0300 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2011-01-02 21:34:32 +0300 |
commit | ddcb91fc213cb9d9f87558f88a4831cd4c8e2791 (patch) | |
tree | b3a266754610fff89abadfc3971721f432f2001f /source/blender/blenkernel | |
parent | 3ead3c4ff3a438202a9838843ed4000b26de62a7 (diff) | |
parent | fe44c6596d6de906f1534f139b980e6d0a205bac (diff) |
Merged changes in the trunk up to revision 34010.
Diffstat (limited to 'source/blender/blenkernel')
28 files changed, 1502 insertions, 989 deletions
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 4d3f000c863..1c75387ba5d 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -117,6 +117,8 @@ void action_groups_remove_channel(struct bAction *act, struct FCurve *fcu); /* Find a group with the given name */ struct bActionGroup *action_groups_find_named(struct bAction *act, const char name[]); +/* Clear all 'temp' flags on all groups */ +void action_groups_clear_tempflags(struct bAction *act); /* Pose API ----------------- */ diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index 3952b6066d3..500210d2fcd 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -100,6 +100,14 @@ void BKE_animdata_fix_paths_rename(struct ID *owner_id, struct AnimData *adt, co /* Fix all the paths for the entire database... */ void BKE_all_animdata_fix_paths_rename(char *prefix, char *oldName, char *newName); +/* -------------------------------------- */ + +/* Move animation data from src to destination if it's paths are based on basepaths */ +void BKE_animdata_separate_by_basepath(struct ID *srcID, struct ID *dstID, struct ListBase *basepaths); + +/* Move F-Curves from src to destination if it's path is based on basepath */ +void action_move_fcurves_by_basepath(struct bAction *srcAct, struct bAction *dstAct, const char basepath[]); + /* ************************************* */ /* Batch AnimData API */ diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index a97c5fd8d9e..886a11b126e 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -44,8 +44,8 @@ struct ReportList; struct Scene; struct Main; -#define BLENDER_VERSION 255 -#define BLENDER_SUBVERSION 1 +#define BLENDER_VERSION 256 +#define BLENDER_SUBVERSION 0 #define BLENDER_MINVERSION 250 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index fb079d44bb5..e9118323682 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -144,6 +144,7 @@ void CustomData_em_copy_data(const struct CustomData *source, void CustomData_bmesh_copy_data(const struct CustomData *source, struct CustomData *dest,void *src_block, void **dest_block); +void CustomData_em_validate_data(struct CustomData *data, void *block, int sub_elements); /* frees data in a CustomData object * return 1 on success, 0 on failure diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 39df877f67b..52051712ff0 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -52,7 +52,7 @@ void defgroup_unique_name(struct bDeformGroup *dg, struct Object *ob); struct MDeformWeight *defvert_find_index(const struct MDeformVert *dv, const int defgroup); struct MDeformWeight *defvert_verify_index(struct MDeformVert *dv, const int defgroup); -float defvert_find_weight(const struct MDeformVert *dvert, int group_num); +float defvert_find_weight(const struct MDeformVert *dvert, const int group_num); float defvert_array_find_weight_safe(const struct MDeformVert *dvert, int index, int group_num); void defvert_copy(struct MDeformVert *dvert_r, const struct MDeformVert *dvert); diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 934c39505cc..fcd61539b23 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -51,6 +51,7 @@ typedef struct Main { char name[240]; short versionfile, subversionfile; short minversionfile, minsubversionfile; + int revision; /* svn revision of binary that saved file */ struct Library *curlib; ListBase scene; diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 8fb80292ffb..5bdea166cce 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -81,5 +81,13 @@ void multires_mdisp_smooth_bounds(struct MDisps *disps); /* update multires data after topology changing */ void multires_topology_changed(struct Object *ob); +/**** interpolation stuff ****/ +void old_mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float v); +void mdisp_rot_crn_to_face(int S, int corners, int face_side, float x, float y, float *u, float *v); +int mdisp_rot_face_to_crn(int corners, int face_side, float u, float v, float *x, float *y); +void mdisp_apply_weight(int S, int corners, int x, int y, int face_side, float crn_weight[4][2], float *u_r, float *v_r); +void mdisp_flip_disp(int S, int corners, float axis_x[2], float axis_y[2], float disp[3]); +void mdisp_join_tris(struct MDisps *dst, struct MDisps *tri1, struct MDisps *tri2); + #endif diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index a7ad95b8ffc..f3548888168 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -63,6 +63,13 @@ #define PTCACHE_TYPE_SMOKE_DOMAIN 3 #define PTCACHE_TYPE_SMOKE_HIGHRES 4 +/* high bits reserved for flags that need to be stored in file */ +#define PTCACHE_TYPEFLAG_COMPRESS (1<<16) +#define PTCACHE_TYPEFLAG_EXTRADATA (1<<17) + +#define PTCACHE_TYPEFLAG_TYPEMASK 0x0000FFFF +#define PTCACHE_TYPEFLAG_FLAGMASK 0xFFFF0000 + /* PTCache read return code */ #define PTCACHE_READ_EXACT 1 #define PTCACHE_READ_INTERPOLATED 2 @@ -96,7 +103,7 @@ typedef struct PTCacheFile { FILE *fp; int totpoint, type, frame, old_format; - unsigned int data_types; + unsigned int data_types, flag; struct PTCacheData data; void *cur[BPHYS_TOT_DATA]; @@ -118,15 +125,23 @@ typedef struct PTCacheID { unsigned int data_types, info_types; /* copies point data to cache data */ - int (*write_elem)(int index, void *calldata, void **data, int cfra); + int (*write_point)(int index, void *calldata, void **data, int cfra); + /* copies cache cata to point data */ + void (*read_point)(int index, void *calldata, void **data, float cfra, float *old_data); + /* interpolated between previously read point data and cache data */ + void (*interpolate_point)(int index, void *calldata, void **data, float cfra, float cfra1, float cfra2, float *old_data); + /* copies point data to cache data */ int (*write_stream)(PTCacheFile *pf, void *calldata); /* copies cache cata to point data */ - void (*read_elem)(int index, void *calldata, void **data, float frs_sec, float cfra, float *old_data); - /* copies cache cata to point data */ void (*read_stream)(PTCacheFile *pf, void *calldata); - /* interpolated between previously read point data and cache data */ - void (*interpolate_elem)(int index, void *calldata, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data); + + /* copies custom extradata to cache data */ + int (*write_extra_data)(void *calldata, struct PTCacheMem *pm, int cfra); + /* copies custom extradata to cache data */ + int (*read_extra_data)(void *calldata, struct PTCacheMem *pm, float cfra); + /* copies custom extradata to cache data */ + int (*interpolate_extra_data)(void *calldata, struct PTCacheMem *pm, float cfra, float cfra1, float cfra2); /* total number of simulated points (the cfra parameter is just for using same function pointer with totwrite) */ int (*totpoint)(void *calldata, int cfra); @@ -267,7 +282,7 @@ void BKE_ptcache_data_get(void **data, int type, int index, void *to); void BKE_ptcache_data_set(void **data, int type, void *from); /* Main cache reading call. */ -int BKE_ptcache_read(PTCacheID *pid, float cfra, float frs_sec); +int BKE_ptcache_read(PTCacheID *pid, float cfra); /* Main cache writing call. */ int BKE_ptcache_write(PTCacheID *pid, int cfra); diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 227f2eadf4c..fdd51dd207f 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -96,7 +96,6 @@ void make_local_action(bAction *act) if (act->id.us==1) { act->id.lib= 0; act->id.flag= LIB_LOCAL; - //make_local_action_channels(act); new_id(0, (ID *)act, 0); return; } @@ -376,6 +375,20 @@ bActionGroup *action_groups_find_named (bAction *act, const char name[]) return BLI_findstring(&act->groups, name, offsetof(bActionGroup, name)); } +/* Clear all 'temp' flags on all groups */ +void action_groups_clear_tempflags (bAction *act) +{ + bActionGroup *agrp; + + /* sanity checks */ + if (ELEM(NULL, act, act->groups.first)) + return; + + /* flag clearing loop */ + for (agrp = act->groups.first; agrp; agrp = agrp->next) + agrp->flag &= ~AGRP_TEMP; +} + /* *************** Pose channels *************** */ /* usually used within a loop, so we got a N^2 slowdown */ diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 0e5763e3034..49d3ca833dd 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -277,6 +277,176 @@ void BKE_animdata_make_local(AnimData *adt) make_local_strips(&nlt->strips); } +/* Sub-ID Regrouping ------------------------------------------- */ + +/* helper heuristic for determining if a path is compatible with the basepath + * < path: (str) full RNA-path from some data (usually an F-Curve) to compare + * < basepath: (str) shorter path fragment to look for + * > returns (bool) whether there is a match + */ +static short animpath_matches_basepath (const char path[], const char basepath[]) +{ + /* we need start of path to be basepath */ + return (path && basepath) && (strstr(path, basepath) == path); +} + +/* Move F-Curves in src action to dst action, setting up all the necessary groups + * for this to happen, but only if the F-Curves being moved have the appropriate + * "base path". + * - This is used when data moves from one datablock to another, causing the + * F-Curves to need to be moved over too + */ +void action_move_fcurves_by_basepath (bAction *srcAct, bAction *dstAct, const char basepath[]) +{ + FCurve *fcu, *fcn=NULL; + + /* sanity checks */ + if ELEM3(NULL, srcAct, dstAct, basepath) { + if (G.f & G_DEBUG) { + printf("ERROR: action_partition_fcurves_by_basepath(%p, %p, %p) has insufficient info to work with\n", + srcAct, dstAct, basepath); + } + return; + } + + /* clear 'temp' flags on all groups in src, as we'll be needing them later + * to identify groups that we've managed to empty out here + */ + action_groups_clear_tempflags(srcAct); + + /* iterate over all src F-Curves, moving over the ones that need to be moved */ + for (fcu = srcAct->curves.first; fcu; fcu = fcn) { + /* store next pointer in case we move stuff */ + fcn = fcu->next; + + /* should F-Curve be moved over? + * - we only need the start of the path to match basepath + */ + if (animpath_matches_basepath(fcu->rna_path, basepath)) { + bActionGroup *agrp = NULL; + + /* if grouped... */ + if (fcu->grp) { + /* make sure there will be a matching group on the other side for the migrants */ + agrp = action_groups_find_named(dstAct, fcu->grp->name); + + if (agrp == NULL) { + /* add a new one with a similar name (usually will be the same though) */ + agrp = action_groups_add_new(dstAct, fcu->grp->name); + } + + /* old groups should be tagged with 'temp' flags so they can be removed later + * if we remove everything from them + */ + fcu->grp->flag |= AGRP_TEMP; + } + + /* perform the migration now */ + action_groups_remove_channel(srcAct, fcu); + + if (agrp) + action_groups_add_channel(dstAct, agrp, fcu); + else + BLI_addtail(&dstAct->curves, fcu); + } + } + + /* cleanup groups (if present) */ + if (srcAct->groups.first) { + bActionGroup *agrp, *grp=NULL; + + for (agrp = srcAct->groups.first; agrp; agrp = grp) { + grp = agrp->next; + + /* only tagged groups need to be considered - clearing these tags or removing them */ + if (agrp->flag & AGRP_TEMP) { + /* if group is empty and tagged, then we can remove as this operation + * moved out all the channels that were formerly here + */ + if (agrp->channels.first == NULL) + BLI_freelinkN(&srcAct->groups, agrp); + else + agrp->flag &= ~AGRP_TEMP; + } + } + } +} + +/* Transfer the animation data from srcID to dstID where the srcID + * animation data is based off "basepath", creating new AnimData and + * associated data as necessary + */ +void BKE_animdata_separate_by_basepath (ID *srcID, ID *dstID, ListBase *basepaths) +{ + AnimData *srcAdt=NULL, *dstAdt=NULL; + LinkData *ld; + + /* sanity checks */ + if ELEM(NULL, srcID, dstID) { + if (G.f & G_DEBUG) + printf("ERROR: no source or destination ID to separate AnimData with\n"); + return; + } + + /* get animdata from src, and create for destination (if needed) */ + srcAdt = BKE_animdata_from_id(srcID); + dstAdt = BKE_id_add_animdata(dstID); + + if ELEM(NULL, srcAdt, dstAdt) { + if (G.f & G_DEBUG) + printf("ERROR: no AnimData for this pair of ID's\n"); + return; + } + + /* active action */ + if (srcAdt->action) { + /* set up an action if necessary, and name it in a similar way so that it can be easily found again */ + if (dstAdt->action == NULL) { + dstAdt->action = add_empty_action(srcAdt->action->id.name+2); + } + else if (dstAdt->action == srcAdt->action) { + printf("Argh! Source and Destination share animation! ('%s' and '%s' both use '%s') Making new empty action\n", + srcID->name, dstID->name, srcAdt->action->id.name); + + // TODO: review this... + id_us_min(&dstAdt->action->id); + dstAdt->action = add_empty_action(dstAdt->action->id.name+2); + } + + /* loop over base paths, trying to fix for each one... */ + for (ld = basepaths->first; ld; ld = ld->next) { + const char *basepath = (const char *)ld->data; + action_move_fcurves_by_basepath(srcAdt->action, dstAdt->action, basepath); + } + } + + /* drivers */ + if (srcAdt->drivers.first) { + FCurve *fcu, *fcn=NULL; + + /* check each driver against all the base paths to see if any should go */ + for (fcu = srcAdt->drivers.first; fcu; fcu = fcn) { + fcn = fcu->next; + + /* try each basepath in turn, but stop on the first one which works */ + for (ld = basepaths->first; ld; ld = ld->next) { + const char *basepath = (const char *)ld->data; + + if (animpath_matches_basepath(fcu->rna_path, basepath)) { + /* just need to change lists */ + BLI_remlink(&srcAdt->drivers, fcu); + BLI_addtail(&dstAdt->drivers, fcu); + + // TODO: add depsgraph flushing calls? + + /* can stop now, as moved already */ + break; + } + } + } + } +} + /* Path Validation -------------------------------------------- */ /* Check if a given RNA Path is valid, by tracing it from the given ID, and seeing if we can resolve it */ @@ -466,46 +636,77 @@ void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, const char *pre /* Whole Database Ops -------------------------------------------- */ /* apply the given callback function on all data in main database */ -void BKE_animdata_main_cb (Main *main, ID_AnimData_Edit_Callback func, void *user_data) +void BKE_animdata_main_cb (Main *mainptr, ID_AnimData_Edit_Callback func, void *user_data) { ID *id; + /* standard data version */ #define ANIMDATA_IDS_CB(first) \ for (id= first; id; id= id->next) { \ AnimData *adt= BKE_animdata_from_id(id); \ if (adt) func(id, adt, user_data); \ } - ANIMDATA_IDS_CB(main->nodetree.first); /* nodes */ - ANIMDATA_IDS_CB(main->tex.first); /* textures */ - ANIMDATA_IDS_CB(main->lamp.first); /* lamps */ - ANIMDATA_IDS_CB(main->mat.first); /* materials */ - ANIMDATA_IDS_CB(main->camera.first); /* cameras */ - ANIMDATA_IDS_CB(main->key.first); /* shapekeys */ - ANIMDATA_IDS_CB(main->mball.first); /* metaballs */ - ANIMDATA_IDS_CB(main->curve.first); /* curves */ - ANIMDATA_IDS_CB(main->armature.first); /* armatures */ - ANIMDATA_IDS_CB(main->mesh.first); /* meshes */ - ANIMDATA_IDS_CB(main->particle.first); /* particles */ - ANIMDATA_IDS_CB(main->object.first); /* objects */ - ANIMDATA_IDS_CB(main->world.first); /* worlds */ - ANIMDATA_IDS_CB(main->linestyle.first); /* linestyles */ + /* "embedded" nodetree cases (i.e. scene/material/texture->nodetree) */ +#define ANIMDATA_NODETREE_IDS_CB(first, NtId_Type) \ + for (id= first; id; id= id->next) { \ + AnimData *adt= BKE_animdata_from_id(id); \ + NtId_Type *ntp= (NtId_Type *)id; \ + if (ntp->nodetree) { \ + AnimData *adt2= BKE_animdata_from_id((ID *)ntp); \ + if (adt2) func(id, adt2, user_data); \ + } \ + if (adt) func(id, adt, user_data); \ + } - /* scenes */ - for (id= main->scene.first; id; id= id->next) { - AnimData *adt= BKE_animdata_from_id(id); - Scene *scene= (Scene *)id; + /* nodes */ + ANIMDATA_IDS_CB(mainptr->nodetree.first); - /* do compositing nodes first (since these aren't included in main tree) */ - if (scene->nodetree) { - AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree); - if (adt2) func(id, adt2, user_data); - } + /* textures */ + ANIMDATA_NODETREE_IDS_CB(mainptr->tex.first, Tex); - /* now fix scene animation data as per normal */ - if (adt) func((ID *)id, adt, user_data); + /* lamps */ + ANIMDATA_IDS_CB(mainptr->lamp.first); + + /* materials */ + ANIMDATA_NODETREE_IDS_CB(mainptr->mat.first, Material); + + /* cameras */ + ANIMDATA_IDS_CB(mainptr->camera.first); + + /* shapekeys */ + ANIMDATA_IDS_CB(mainptr->key.first); + + /* metaballs */ + ANIMDATA_IDS_CB(mainptr->mball.first); + + /* curves */ + ANIMDATA_IDS_CB(mainptr->curve.first); + + /* armatures */ + ANIMDATA_IDS_CB(mainptr->armature.first); + + /* lattices */ + ANIMDATA_IDS_CB(mainptr->latt.first); + + /* meshes */ + ANIMDATA_IDS_CB(mainptr->mesh.first); + + /* particles */ + ANIMDATA_IDS_CB(mainptr->particle.first); + + /* objects */ + ANIMDATA_IDS_CB(mainptr->object.first); + + /* worlds */ + ANIMDATA_IDS_CB(mainptr->world.first); + + /* scenes */ + ANIMDATA_NODETREE_IDS_CB(mainptr->scene.first, Scene); + + /* line styles */ + ANIMDATA_IDS_CB(mainptr->linestyle.first); } -} /* Fix all RNA-Paths throughout the database (directly access the Global.main version) * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]> @@ -527,17 +728,29 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa BKE_animdata_fix_paths_rename(id, adt, prefix, oldName, newName, 0, 0, 1);\ } + /* another version of this macro for nodetrees */ +#define RENAMEFIX_ANIM_NODETREE_IDS(first, NtId_Type) \ + for (id= first; id; id= id->next) { \ + AnimData *adt= BKE_animdata_from_id(id); \ + NtId_Type *ntp= (NtId_Type *)id; \ + if (ntp->nodetree) { \ + AnimData *adt2= BKE_animdata_from_id((ID *)ntp); \ + BKE_animdata_fix_paths_rename((ID *)ntp, adt2, prefix, oldName, newName, 0, 0, 1);\ + } \ + BKE_animdata_fix_paths_rename(id, adt, prefix, oldName, newName, 0, 0, 1);\ + } + /* nodes */ RENAMEFIX_ANIM_IDS(mainptr->nodetree.first); /* textures */ - RENAMEFIX_ANIM_IDS(mainptr->tex.first); + RENAMEFIX_ANIM_NODETREE_IDS(mainptr->tex.first, Tex); /* lamps */ RENAMEFIX_ANIM_IDS(mainptr->lamp.first); /* materials */ - RENAMEFIX_ANIM_IDS(mainptr->mat.first); + RENAMEFIX_ANIM_NODETREE_IDS(mainptr->mat.first, Material); /* cameras */ RENAMEFIX_ANIM_IDS(mainptr->camera.first); @@ -554,8 +767,11 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa /* armatures */ RENAMEFIX_ANIM_IDS(mainptr->armature.first); + /* lattices */ + RENAMEFIX_ANIM_IDS(mainptr->latt.first); + /* meshes */ - // TODO... + RENAMEFIX_ANIM_IDS(mainptr->mesh.first); /* particles */ RENAMEFIX_ANIM_IDS(mainptr->particle.first); @@ -570,21 +786,9 @@ void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newNa RENAMEFIX_ANIM_IDS(mainptr->linestyle.first); /* scenes */ - for (id= mainptr->scene.first; id; id= id->next) { - AnimData *adt= BKE_animdata_from_id(id); - Scene *scene= (Scene *)id; - - /* do compositing nodes first (since these aren't included in main tree) */ - if (scene->nodetree) { - AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree); - BKE_animdata_fix_paths_rename((ID *)scene->nodetree, adt2, prefix, oldName, newName, 0, 0, 1); + RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene); } - /* now fix scene animation data as per normal */ - BKE_animdata_fix_paths_rename((ID *)id, adt, prefix, oldName, newName, 0, 0, 1); - } -} - /* *********************************** */ /* KeyingSet API */ @@ -689,7 +893,7 @@ KS_Path *BKE_keyingset_add_path (KeyingSet *ks, ID *id, const char group_name[], /* just store absolute info */ ksp->id= id; if (group_name) - BLI_snprintf(ksp->group, 64, group_name); + BLI_strncpy(ksp->group, group_name, sizeof(ksp->group)); else ksp->group[0]= '\0'; @@ -1906,7 +2110,6 @@ void BKE_animsys_evaluate_all_animation (Main *main, float ctime) EVAL_ANIM_IDS(main->camera.first, ADT_RECALC_ANIM); /* shapekeys */ - // TODO: we probably need the same hack as for curves (ctime-hack) EVAL_ANIM_IDS(main->key.first, ADT_RECALC_ANIM); /* metaballs */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 22d27dc2fde..6b21e45ddd9 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -936,19 +936,15 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, dvert = NULL; if(armature_def_nr >= 0 && dvert) { - armature_weight = 0.0f; /* a def group was given, so default to 0 */ - for(j = 0; j < dvert->totweight; j++) { - if(dvert->dw[j].def_nr == armature_def_nr) { - armature_weight = dvert->dw[j].weight; - break; - } + armature_weight= defvert_find_weight(dvert, armature_def_nr); + + if(invert_vgroup) { + armature_weight= 1.0f-armature_weight; } + /* hackish: the blending factor can be used for blending with prevCos too */ if(prevCos) { - if(invert_vgroup) - prevco_weight= 1.0f-armature_weight; - else - prevco_weight= armature_weight; + prevco_weight= armature_weight; armature_weight= 1.0f; } } diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index f644b28b137..b283120249e 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -504,7 +504,7 @@ DerivedMesh *clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, } /* try to read from cache */ - cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, scene->r.frs_sec); + cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe); if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { implicit_set_positions(clmd); diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index e178beaaa50..f7606a344c9 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -104,6 +104,11 @@ typedef struct LayerTypeInfo { /* a function to determine file size */ size_t (*filesize)(CDataFile *cdf, void *data, int count); + + /* a function to validate layer contents depending on + * sub-elements count + */ + void (*validate)(void *source, int sub_elements); } LayerTypeInfo; static void layerCopy_mdeformvert(const void *source, void *dest, @@ -396,52 +401,6 @@ static void layerDefault_origspace_face(void *data, int count) osf[i] = default_osf; } -/* Adapted from sculptmode.c */ -static void mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float v) -{ - int x, y, x2, y2; - const int st_max = st - 1; - float urat, vrat, uopp; - float d[4][3], d2[2][3]; - - if(u < 0) - u = 0; - else if(u >= st) - u = st_max; - if(v < 0) - v = 0; - else if(v >= st) - v = st_max; - - x = floor(u); - y = floor(v); - x2 = x + 1; - y2 = y + 1; - - if(x2 >= st) x2 = st_max; - if(y2 >= st) y2 = st_max; - - urat = u - x; - vrat = v - y; - uopp = 1 - urat; - - copy_v3_v3(d[0], disps[y * st + x]); - copy_v3_v3(d[1], disps[y * st + x2]); - copy_v3_v3(d[2], disps[y2 * st + x]); - copy_v3_v3(d[3], disps[y2 * st + x2]); - mul_v3_fl(d[0], uopp); - mul_v3_fl(d[1], urat); - mul_v3_fl(d[2], uopp); - mul_v3_fl(d[3], urat); - - add_v3_v3v3(d2[0], d[0], d[1]); - add_v3_v3v3(d2[1], d[2], d[3]); - mul_v3_fl(d2[0], 1 - vrat); - mul_v3_fl(d2[1], vrat); - - add_v3_v3v3(out, d2[0], d2[1]); -} - static void layerSwap_mdisps(void *data, const int *ci) { MDisps *s = data; @@ -473,211 +432,6 @@ static void layerSwap_mdisps(void *data, const int *ci) } } -static void mdisp_get_crn_rect(int face_side, float crn[3][4][2]) -{ - float offset = face_side*0.5f - 0.5f; - float mid[2]; - - mid[0] = offset * 4 / 3; - mid[1] = offset * 2 / 3; - - crn[0][0][0] = mid[0]; crn[0][0][1] = mid[1]; - crn[0][1][0] = offset; crn[0][1][1] = 0; - crn[0][2][0] = 0; crn[0][2][1] = 0; - crn[0][3][0] = offset; crn[0][3][1] = offset; - - crn[1][0][0] = mid[0]; crn[1][0][1] = mid[1]; - crn[1][1][0] = offset * 2; crn[1][1][1] = offset; - crn[1][2][0] = offset * 2; crn[1][2][1] = 0; - crn[1][3][0] = offset; crn[1][3][1] = 0; - - crn[2][0][0] = mid[0]; crn[2][0][1] = mid[1]; - crn[2][1][0] = offset; crn[2][1][1] = offset; - crn[2][2][0] = offset * 2; crn[2][2][1] = offset * 2; - crn[2][3][0] = offset * 2; crn[2][3][1] = offset; -} - -static void mdisp_rot_crn_to_face(int S, int corners, int face_side, float x, float y, float *u, float *v) -{ - float offset = face_side*0.5f - 0.5f; - - if(corners == 4) { - if(S == 1) { *u= offset + x; *v = offset - y; } - if(S == 2) { *u= offset + y; *v = offset + x; } - if(S == 3) { *u= offset - x; *v = offset + y; } - if(S == 0) { *u= offset - y; *v = offset - x; } - } else { - float crn[3][4][2], vec[4][2]; - float p[2]; - - mdisp_get_crn_rect(face_side, crn); - - interp_v2_v2v2(vec[0], crn[S][0], crn[S][1], x / offset); - interp_v2_v2v2(vec[1], crn[S][3], crn[S][2], x / offset); - interp_v2_v2v2(vec[2], crn[S][0], crn[S][3], y / offset); - interp_v2_v2v2(vec[3], crn[S][1], crn[S][2], y / offset); - - isect_seg_seg_v2_point(vec[0], vec[1], vec[2], vec[3], p); - - (*u) = p[0]; - (*v) = p[1]; - } -} - -static int mdisp_pt_in_crn(float p[2], float crn[4][2]) -{ - float v[2][2]; - float a[2][2]; - - sub_v2_v2v2(v[0], crn[1], crn[0]); - sub_v2_v2v2(v[1], crn[3], crn[0]); - - sub_v2_v2v2(a[0], p, crn[0]); - sub_v2_v2v2(a[1], crn[2], crn[0]); - - if(cross_v2v2(a[0], v[0]) * cross_v2v2(a[1], v[0]) < 0) - return 0; - - if(cross_v2v2(a[0], v[1]) * cross_v2v2(a[1], v[1]) < 0) - return 0; - - return 1; -} - -static void face_to_crn_interp(float u, float v, float v1[2], float v2[2], float v3[2], float v4[2], float *x) -{ - float a = (v4[1]-v3[1])*v2[0]+(-v4[1]+v3[1])*v1[0]+(-v2[1]+v1[1])*v4[0]+(v2[1]-v1[1])*v3[0]; - float b = (v3[1]-v)*v2[0]+(v4[1]-2*v3[1]+v)*v1[0]+(-v4[1]+v3[1]+v2[1]-v1[1])*u+(v4[0]-v3[0])*v-v1[1]*v4[0]+(-v2[1]+2*v1[1])*v3[0]; - float c = (v3[1]-v)*v1[0]+(-v3[1]+v1[1])*u+v3[0]*v-v1[1]*v3[0]; - float d = b * b - 4 * a * c; - float x1, x2; - - if(a == 0) { - *x = -c / b; - return; - } - - x1 = (-b - sqrtf(d)) / (2 * a); - x2 = (-b + sqrtf(d)) / (2 * a); - - *x = maxf(x1, x2); -} - -static int mdisp_rot_face_to_crn(int corners, int face_side, float u, float v, float *x, float *y) -{ - float offset = face_side*0.5f - 0.5f; - int S; - - if (corners == 4) { - if(u <= offset && v <= offset) S = 0; - else if(u > offset && v <= offset) S = 1; - else if(u > offset && v > offset) S = 2; - else if(u <= offset && v >= offset) S = 3; - - if(S == 0) { - *y = offset - u; - *x = offset - v; - } else if(S == 1) { - *x = u - offset; - *y = offset - v; - } else if(S == 2) { - *y = u - offset; - *x = v - offset; - } else if(S == 3) { - *x= offset - u; - *y = v - offset; - } - } else { - float crn[3][4][2]; - float p[2] = {u, v}; - - mdisp_get_crn_rect(face_side, crn); - - for (S = 0; S < 3; ++S) { - if (mdisp_pt_in_crn(p, crn[S])) - break; - } - - face_to_crn_interp(u, v, crn[S][0], crn[S][1], crn[S][3], crn[S][2], &p[0]); - face_to_crn_interp(u, v, crn[S][0], crn[S][3], crn[S][1], crn[S][2], &p[1]); - - *x = p[0] * offset; - *y = p[1] * offset; - } - - return S; -} - -static void mdisp_apply_weight(int S, int corners, int x, int y, int face_side, - float crn_weight[4][2], float *u_r, float *v_r) -{ - float u, v, xl, yl; - float mid1[2], mid2[2], mid3[2]; - - mdisp_rot_crn_to_face(S, corners, face_side, x, y, &u, &v); - - if(corners == 4) { - xl = u / (face_side - 1); - yl = v / (face_side - 1); - - mid1[0] = crn_weight[0][0] * (1 - xl) + crn_weight[1][0] * xl; - mid1[1] = crn_weight[0][1] * (1 - xl) + crn_weight[1][1] * xl; - mid2[0] = crn_weight[3][0] * (1 - xl) + crn_weight[2][0] * xl; - mid2[1] = crn_weight[3][1] * (1 - xl) + crn_weight[2][1] * xl; - mid3[0] = mid1[0] * (1 - yl) + mid2[0] * yl; - mid3[1] = mid1[1] * (1 - yl) + mid2[1] * yl; - } else { - yl = v / (face_side - 1); - - if(v == face_side - 1) xl = 1; - else xl = 1 - (face_side - 1 - u) / (face_side - 1 - v); - - mid1[0] = crn_weight[0][0] * (1 - xl) + crn_weight[1][0] * xl; - mid1[1] = crn_weight[0][1] * (1 - xl) + crn_weight[1][1] * xl; - mid3[0] = mid1[0] * (1 - yl) + crn_weight[2][0] * yl; - mid3[1] = mid1[1] * (1 - yl) + crn_weight[2][1] * yl; - } - - *u_r = mid3[0]; - *v_r = mid3[1]; -} - -static void mdisp_flip_disp(int S, int corners, float axis_x[2], float axis_y[2], float disp[3]) -{ - float crn_x[2], crn_y[2]; - float vx[2], vy[2], coord[2]; - - if (corners == 4) { - float x[4][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}}; - float y[4][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; - - copy_v2_v2(crn_x, x[S]); - copy_v2_v2(crn_y, y[S]); - - mul_v2_v2fl(vx, crn_x, disp[0]); - mul_v2_v2fl(vy, crn_y, disp[1]); - add_v2_v2v2(coord, vx, vy); - - project_v2_v2v2(vx, coord, axis_x); - project_v2_v2v2(vy, coord, axis_y); - - disp[0] = len_v2(vx); - disp[1] = len_v2(vy); - - if(dot_v2v2(vx, axis_x) < 0) - disp[0] = -disp[0]; - - if(dot_v2v2(vy, axis_y) < 0) - disp[1] = -disp[1]; - } else { - /* XXX: it was very overhead code to support displacement flipping - for case of tris without visible profit. - Maybe its not really big limitation? for now? (nazgul) */ - disp[0] = 0; - disp[1] = 0; - } -} - static void layerInterp_mdisps(void **sources, float *UNUSED(weights), float *sub_weights, int count, void *dest) { @@ -687,16 +441,55 @@ static void layerInterp_mdisps(void **sources, float *UNUSED(weights), int i, x, y; int side, S, dst_corners, src_corners; float crn_weight[4][2]; - float (*sw)[4] = NULL; + float (*sw)[4] = (void*)sub_weights; float (*disps)[3], (*out)[3]; s = sources[0]; dst_corners = multires_mdisp_corners(d); src_corners = multires_mdisp_corners(s); - /* XXX: For now, some restrictions on the input - should be implemented to allow quad<->tris face conversion */ - if(count != 1 || !sub_weights || dst_corners != src_corners) { + if(sub_weights && count == 2 && src_corners == 3) { + src_corners = multires_mdisp_corners(sources[1]); + + /* special case -- converting two triangles to quad */ + if(src_corners == 3 && dst_corners == 4) { + MDisps tris[2]; + int vindex[4] = {0}; + + S = 0; + for(i = 0; i < 2; i++) + for(y = 0; y < 4; y++) + for(x = 0; x < 4; x++) + if(sw[x+i*4][y]) + vindex[x] = y; + + for(i = 0; i < 2; i++) { + float sw[4][4] = {{0}}; + int a = 7 & ~(1 << vindex[i*2] | 1 << vindex[i*2+1]); + + sw[0][vindex[i*2+1]] = 1; + sw[1][vindex[i*2]] = 1; + + for(x = 0; x < 3; x++) + if(a & (1 << x)) + sw[2][x] = 1; + + tris[i] = *((MDisps*)sources[i]); + tris[i].disps = MEM_dupallocN(tris[i].disps); + layerInterp_mdisps(&sources[i], NULL, (float*)sw, 1, &tris[i]); + } + + mdisp_join_tris(d, &tris[0], &tris[1]); + + for(i = 0; i < 2; i++) + MEM_freeN(tris[i].disps); + + return; + } + } + + /* For now, some restrictions on the input */ + if(count != 1 || !sub_weights) { for(i = 0; i < d->totdisp; ++i) zero_v3(d->disps[i]); @@ -739,7 +532,7 @@ static void layerInterp_mdisps(void **sources, float *UNUSED(weights), mdisp_apply_weight(S, dst_corners, x, y, st, crn_weight, &face_u, &face_v); crn = mdisp_rot_face_to_crn(src_corners, st, face_u, face_v, &crn_u, &crn_v); - mdisps_bilinear((*out), &s->disps[crn*side*side], side, crn_u, crn_v); + old_mdisps_bilinear((*out), &s->disps[crn*side*side], side, crn_u, crn_v); mdisp_flip_disp(crn, dst_corners, axis_x, axis_y, *out); } } @@ -768,6 +561,20 @@ static void layerCopy_mdisps(const void *source, void *dest, int count) } } +static void layerValidate_mdisps(void *data, int sub_elements) +{ + MDisps *disps = data; + if(disps->disps) { + int corners = multires_mdisp_corners(disps); + + if(corners != sub_elements) { + MEM_freeN(disps->disps); + disps->totdisp = disps->totdisp / corners * sub_elements; + disps->disps = MEM_callocN(3*disps->totdisp*sizeof(float), "layerValidate_mdisps"); + } + } +} + static void layerFree_mdisps(void *data, int count, int UNUSED(size)) { int i; @@ -1019,7 +826,8 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(MLoopCol), "MLoopCol", 1, "Col", NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol}, {sizeof(float)*3*4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, {sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps, - layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps}, + layerFree_mdisps, layerInterp_mdisps, layerSwap_mdisps, NULL, layerRead_mdisps, layerWrite_mdisps, + layerFilesize_mdisps, layerValidate_mdisps}, {sizeof(MCol)*4, "MCol", 4, "WeightCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, {sizeof(MCol)*4, "MCol", 4, "IDCol", NULL, NULL, layerInterp_mcol, @@ -1942,6 +1750,18 @@ void CustomData_em_copy_data(const CustomData *source, CustomData *dest, } } +void CustomData_em_validate_data(CustomData *data, void *block, int sub_elements) +{ + int i; + for(i = 0; i < data->totlayer; i++) { + const LayerTypeInfo *typeInfo = layerType_getInfo(data->layers[i].type); + char *leayer_data = (char*)block + data->layers[i].offset; + + if(typeInfo->validate) + typeInfo->validate(leayer_data, sub_elements); + } +} + void *CustomData_em_get(const CustomData *data, void *block, int type) { int layer_index; diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index ad797736a85..937681fcdc3 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -448,7 +448,7 @@ void flip_side_name (char *name, const char *from_name, int strip_number) sprintf (name, "%s%s%s%s", prefix, replace, suffix, number); } -float defvert_find_weight(const struct MDeformVert *dvert, int group_num) +float defvert_find_weight(const struct MDeformVert *dvert, const int group_num) { MDeformWeight *dw= defvert_find_index(dvert, group_num); return dw ? dw->weight : 0.0f; diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 325e64bf768..f2bc586f15c 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1329,7 +1329,7 @@ DriverVar *driver_add_new_variable (ChannelDriver *driver) #ifdef WITH_PYTHON /* since driver variables are cached, the expression needs re-compiling too */ - if(driver->type==DRIVER_TYPE_PYTHON) + if (driver->type==DRIVER_TYPE_PYTHON) driver->flag |= DRIVER_FLAG_RENAMEVAR; #endif diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index 1ed8241325e..0376d75d651 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -1009,9 +1009,13 @@ FModifier *add_fmodifier (ListBase *modifiers, int type) fcm->flag = FMODIFIER_FLAG_EXPANDED; BLI_addtail(modifiers, fcm); + /* tag modifier as "active" if no other modifiers exist in the stack yet */ + if (modifiers->first == modifiers->last) + fcm->flag |= FMODIFIER_FLAG_ACTIVE; + /* add modifier's data */ fcm->data= MEM_callocN(fmi->size, fmi->structName); - + /* init custom settings if necessary */ if (fmi->new_data) fmi->new_data(fcm->data); diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 500ccf0781b..ec63975a3c0 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -670,7 +670,7 @@ struct chartrans *BKE_text_to_curve(Scene *scene, Object *ob, int mode) VFont *vfont, *oldvfont; VFontData *vfd= NULL; Curve *cu; - CharInfo *info, *custrinfo; + CharInfo *info = NULL, *custrinfo; TextBox *tb; VChar *che; struct chartrans *chartransdata=NULL, *ct; diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index c18085b2d73..8cdfbaf9e2a 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -1191,7 +1191,7 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot) if(key->slurph && key->type!=KEY_RELATIVE) { Nurb *nu; - int mode, i= 0, remain= 0, estep, count; + int mode=0, i= 0, remain= 0, estep=0, count=0; delta= (float)key->slurph / tot; diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 03cbd9e41fd..8658d7e482f 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -737,7 +737,7 @@ void accum_mballfaces(int i1, int i2, int i3, int i4) void *new_pgn_element(int size) { /* during polygonize 1000s of elements are allocated - * and never freed inbetween. Freeing only done at the end. + * and never freed in between. Freeing only done at the end. */ int blocksize= 16384; static int offs= 0; /* the current free address */ diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 2224b3d8d49..84350127968 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -837,7 +837,7 @@ DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int loca ***************************/ /* Adapted from sculptmode.c */ -static void old_mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float v) +void old_mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, float v) { int x, y, x2, y2; const int st_max = st - 1; @@ -1774,3 +1774,254 @@ void multires_mdisp_smooth_bounds(MDisps *disps) } } } + +/***************** Multires interpolation stuff *****************/ + +static void mdisp_get_crn_rect(int face_side, float crn[3][4][2]) +{ + float offset = face_side*0.5f - 0.5f; + float mid[2]; + + mid[0] = offset * 4 / 3; + mid[1] = offset * 2 / 3; + + crn[0][0][0] = mid[0]; crn[0][0][1] = mid[1]; + crn[0][1][0] = offset; crn[0][1][1] = 0; + crn[0][2][0] = 0; crn[0][2][1] = 0; + crn[0][3][0] = offset; crn[0][3][1] = offset; + + crn[1][0][0] = mid[0]; crn[1][0][1] = mid[1]; + crn[1][1][0] = offset * 2; crn[1][1][1] = offset; + crn[1][2][0] = offset * 2; crn[1][2][1] = 0; + crn[1][3][0] = offset; crn[1][3][1] = 0; + + crn[2][0][0] = mid[0]; crn[2][0][1] = mid[1]; + crn[2][1][0] = offset; crn[2][1][1] = offset; + crn[2][2][0] = offset * 2; crn[2][2][1] = offset * 2; + crn[2][3][0] = offset * 2; crn[2][3][1] = offset; +} + +static int mdisp_pt_in_crn(float p[2], float crn[4][2]) +{ + float v[2][2]; + float a[2][2]; + + sub_v2_v2v2(v[0], crn[1], crn[0]); + sub_v2_v2v2(v[1], crn[3], crn[0]); + + sub_v2_v2v2(a[0], p, crn[0]); + sub_v2_v2v2(a[1], crn[2], crn[0]); + + if(cross_v2v2(a[0], v[0]) * cross_v2v2(a[1], v[0]) < 0) + return 0; + + if(cross_v2v2(a[0], v[1]) * cross_v2v2(a[1], v[1]) < 0) + return 0; + + return 1; +} + +static void face_to_crn_interp(float u, float v, float v1[2], float v2[2], float v3[2], float v4[2], float *x) +{ + float a = (v4[1]-v3[1])*v2[0]+(-v4[1]+v3[1])*v1[0]+(-v2[1]+v1[1])*v4[0]+(v2[1]-v1[1])*v3[0]; + float b = (v3[1]-v)*v2[0]+(v4[1]-2*v3[1]+v)*v1[0]+(-v4[1]+v3[1]+v2[1]-v1[1])*u+(v4[0]-v3[0])*v-v1[1]*v4[0]+(-v2[1]+2*v1[1])*v3[0]; + float c = (v3[1]-v)*v1[0]+(-v3[1]+v1[1])*u+v3[0]*v-v1[1]*v3[0]; + float d = b * b - 4 * a * c; + float x1, x2; + + if(a == 0) { + *x = -c / b; + return; + } + + x1 = (-b - sqrtf(d)) / (2 * a); + x2 = (-b + sqrtf(d)) / (2 * a); + + *x = maxf(x1, x2); +} + +void mdisp_rot_crn_to_face(int S, int corners, int face_side, float x, float y, float *u, float *v) +{ + float offset = face_side*0.5f - 0.5f; + + if(corners == 4) { + if(S == 1) { *u= offset + x; *v = offset - y; } + if(S == 2) { *u= offset + y; *v = offset + x; } + if(S == 3) { *u= offset - x; *v = offset + y; } + if(S == 0) { *u= offset - y; *v = offset - x; } + } else { + float crn[3][4][2], vec[4][2]; + float p[2]; + + mdisp_get_crn_rect(face_side, crn); + + interp_v2_v2v2(vec[0], crn[S][0], crn[S][1], x / offset); + interp_v2_v2v2(vec[1], crn[S][3], crn[S][2], x / offset); + interp_v2_v2v2(vec[2], crn[S][0], crn[S][3], y / offset); + interp_v2_v2v2(vec[3], crn[S][1], crn[S][2], y / offset); + + isect_seg_seg_v2_point(vec[0], vec[1], vec[2], vec[3], p); + + (*u) = p[0]; + (*v) = p[1]; + } +} + +int mdisp_rot_face_to_crn(int corners, int face_side, float u, float v, float *x, float *y) +{ + float offset = face_side*0.5f - 0.5f; + int S; + + if (corners == 4) { + if(u <= offset && v <= offset) S = 0; + else if(u > offset && v <= offset) S = 1; + else if(u > offset && v > offset) S = 2; + else if(u <= offset && v >= offset) S = 3; + + if(S == 0) { + *y = offset - u; + *x = offset - v; + } else if(S == 1) { + *x = u - offset; + *y = offset - v; + } else if(S == 2) { + *y = u - offset; + *x = v - offset; + } else if(S == 3) { + *x= offset - u; + *y = v - offset; + } + } else { + float crn[3][4][2]; + float p[2] = {u, v}; + + mdisp_get_crn_rect(face_side, crn); + + for (S = 0; S < 3; ++S) { + if (mdisp_pt_in_crn(p, crn[S])) + break; + } + + face_to_crn_interp(u, v, crn[S][0], crn[S][1], crn[S][3], crn[S][2], &p[0]); + face_to_crn_interp(u, v, crn[S][0], crn[S][3], crn[S][1], crn[S][2], &p[1]); + + *x = p[0] * offset; + *y = p[1] * offset; + } + + return S; +} + +void mdisp_apply_weight(int S, int corners, int x, int y, int face_side, + float crn_weight[4][2], float *u_r, float *v_r) +{ + float u, v, xl, yl; + float mid1[2], mid2[2], mid3[2]; + + mdisp_rot_crn_to_face(S, corners, face_side, x, y, &u, &v); + + if(corners == 4) { + xl = u / (face_side - 1); + yl = v / (face_side - 1); + + mid1[0] = crn_weight[0][0] * (1 - xl) + crn_weight[1][0] * xl; + mid1[1] = crn_weight[0][1] * (1 - xl) + crn_weight[1][1] * xl; + mid2[0] = crn_weight[3][0] * (1 - xl) + crn_weight[2][0] * xl; + mid2[1] = crn_weight[3][1] * (1 - xl) + crn_weight[2][1] * xl; + mid3[0] = mid1[0] * (1 - yl) + mid2[0] * yl; + mid3[1] = mid1[1] * (1 - yl) + mid2[1] * yl; + } else { + yl = v / (face_side - 1); + + if(v == face_side - 1) xl = 1; + else xl = 1 - (face_side - 1 - u) / (face_side - 1 - v); + + mid1[0] = crn_weight[0][0] * (1 - xl) + crn_weight[1][0] * xl; + mid1[1] = crn_weight[0][1] * (1 - xl) + crn_weight[1][1] * xl; + mid3[0] = mid1[0] * (1 - yl) + crn_weight[2][0] * yl; + mid3[1] = mid1[1] * (1 - yl) + crn_weight[2][1] * yl; + } + + *u_r = mid3[0]; + *v_r = mid3[1]; +} + +void mdisp_flip_disp(int S, int corners, float axis_x[2], float axis_y[2], float disp[3]) +{ + float crn_x[2], crn_y[2]; + float vx[2], vy[2], coord[2]; + + if (corners == 4) { + float x[4][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}}; + float y[4][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}}; + + copy_v2_v2(crn_x, x[S]); + copy_v2_v2(crn_y, y[S]); + + mul_v2_v2fl(vx, crn_x, disp[0]); + mul_v2_v2fl(vy, crn_y, disp[1]); + add_v2_v2v2(coord, vx, vy); + + project_v2_v2v2(vx, coord, axis_x); + project_v2_v2v2(vy, coord, axis_y); + + disp[0] = len_v2(vx); + disp[1] = len_v2(vy); + + if(dot_v2v2(vx, axis_x) < 0) + disp[0] = -disp[0]; + + if(dot_v2v2(vy, axis_y) < 0) + disp[1] = -disp[1]; + } else { + /* XXX: it was very overhead code to support displacement flipping + for case of tris without visible profit. + Maybe its not really big limitation? for now? (nazgul) */ + disp[0] = 0; + disp[1] = 0; + } +} + +/* Join two triangular displacements into one quad + Corners mapping: + 2 -------- 3 + | \ tri2 | + | \ | + | tri1 \ | + 0 -------- 1 */ +void mdisp_join_tris(MDisps *dst, MDisps *tri1, MDisps *tri2) +{ + int side, st; + int S, x, y, crn; + float face_u, face_v, crn_u, crn_v; + float (*out)[3]; + MDisps *src; + + if(dst->disps) + MEM_freeN(dst->disps); + + side = sqrt(tri1->totdisp / 3); + st = (side<<1)-1; + + dst->totdisp = 4 * side * side; + out = dst->disps = MEM_callocN(3*dst->totdisp*sizeof(float), "join disps"); + + for(S = 0; S < 4; S++) + for(y = 0; y < side; ++y) + for(x = 0; x < side; ++x, ++out) { + mdisp_rot_crn_to_face(S, 4, st, x, y, &face_u, &face_v); + face_u = st - 1 - face_u; + + if(face_v > face_u) { + src = tri2; + face_u = st - 1 - face_u; + face_v = st - 1 - face_v; + } else src = tri1; + + crn = mdisp_rot_face_to_crn(3, st, face_u, face_v, &crn_u, &crn_v); + + old_mdisps_bilinear((*out), &src->disps[crn*side*side], side, crn_u, crn_v); + (*out)[0] = 0; + (*out)[1] = 0; + } +} diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index f52a538cc00..db11b42ee1e 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -36,11 +36,13 @@ #include <string.h> #include "DNA_anim_types.h" +#include "DNA_action_types.h" #include "RNA_access.h" +#include "BKE_animsys.h" +#include "BKE_action.h" #include "BKE_fcurve.h" -#include "BKE_animsys.h" /* BKE_free_animdata only */ #include "PIL_time.h" @@ -460,6 +462,7 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree) bNode *node, *gnode, *nextn; bNodeSocket *sock; bNodeTree *ngroup; + ListBase anim_basepaths = {NULL, NULL}; float min[2], max[2]; int totnode=0; @@ -502,11 +505,27 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree) for(node= ntree->nodes.first; node; node= nextn) { nextn= node->next; if(node->flag & NODE_SELECT) { + /* keep track of this node's RNA "base" path (the part of the pat identifying the node) + * if the old nodetree has animation data which potentially covers this node + */ + if (ntree->adt) { + PointerRNA ptr; + char *path; + + RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr); + path = RNA_path_from_ID_to_struct(&ptr); + + if (path) + BLI_addtail(&anim_basepaths, BLI_genericNodeN(path)); + } + + /* change node-collection membership */ BLI_remlink(&ntree->nodes, node); BLI_addtail(&ngroup->nodes, node); + node->locx-= 0.5f*(min[0]+max[0]); node->locy-= 0.5f*(min[1]+max[1]); - + /* set socket own_index to zero since it can still have a value * from being in a group before, otherwise it doesn't get a unique * index in group_verify_own_indices */ @@ -526,6 +545,21 @@ bNode *nodeMakeGroupFromSelected(bNodeTree *ntree) } } + /* move animation data over */ + if (ntree->adt) { + LinkData *ld, *ldn=NULL; + + BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths); + + /* paths + their wrappers need to be freed */ + for (ld = anim_basepaths.first; ld; ld = ld->next) { + ldn = ld->next; + + MEM_freeN(ld->data); + BLI_freelinkN(&anim_basepaths, ld); + } + } + /* now we can make own group typeinfo */ ntreeMakeOwnType(ngroup); @@ -771,6 +805,7 @@ int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode) bNodeLink *link, *linkn; bNode *node, *nextn; bNodeTree *ngroup, *wgroup; + ListBase anim_basepaths = {NULL, NULL}; int index; ngroup= (bNodeTree *)gnode->id; @@ -779,16 +814,38 @@ int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode) /* clear new pointers, set in copytree */ for(node= ntree->nodes.first; node; node= node->next) node->new_node= NULL; - + + /* wgroup is a temporary copy of the NodeTree we're merging in + * - all of wgroup's nodes are transferred across to their new home + * - ngroup (i.e. the source NodeTree) is left unscathed + */ wgroup= ntreeCopyTree(ngroup, 0); /* add the nodes into the ntree */ for(node= wgroup->nodes.first; node; node= nextn) { nextn= node->next; + + /* keep track of this node's RNA "base" path (the part of the pat identifying the node) + * if the old nodetree has animation data which potentially covers this node + */ + if (wgroup->adt) { + PointerRNA ptr; + char *path; + + RNA_pointer_create(&wgroup->id, &RNA_Node, node, &ptr); + path = RNA_path_from_ID_to_struct(&ptr); + + if (path) + BLI_addtail(&anim_basepaths, BLI_genericNodeN(path)); + } + + /* migrate node */ BLI_remlink(&wgroup->nodes, node); BLI_addtail(&ntree->nodes, node); + node->locx+= gnode->locx; node->locy+= gnode->locy; + node->flag |= NODE_SELECT; } /* and the internal links */ @@ -797,6 +854,29 @@ int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode) BLI_remlink(&wgroup->links, link); BLI_addtail(&ntree->links, link); } + + /* and copy across the animation */ + if (wgroup->adt) { + LinkData *ld, *ldn=NULL; + bAction *waction; + + /* firstly, wgroup needs to temporary dummy action that can be destroyed, as it shares copies */ + waction = wgroup->adt->action = copy_action(wgroup->adt->action); + + /* now perform the moving */ + BKE_animdata_separate_by_basepath(&wgroup->id, &ntree->id, &anim_basepaths); + + /* paths + their wrappers need to be freed */ + for (ld = anim_basepaths.first; ld; ld = ld->next) { + ldn = ld->next; + + MEM_freeN(ld->data); + BLI_freelinkN(&anim_basepaths, ld); + } + + /* free temp action too */ + free_libblock(&G.main->action, waction); + } /* restore links to and from the gnode */ for(link= ntree->links.first; link; link= link->next) { @@ -2474,6 +2554,25 @@ static bNode *getExecutableNode(bNodeTree *ntree) return NULL; } +/* check if texture nodes need exec or end */ +static void ntree_composite_texnode(bNodeTree *ntree, int init) +{ + bNode *node; + + for(node= ntree->nodes.first; node; node= node->next) { + if(node->type==CMP_NODE_TEXTURE && node->id) { + Tex *tex= (Tex *)node->id; + if(tex->nodetree && tex->use_nodes) { + /* has internal flag to detect it only does it once */ + if(init) + ntreeBeginExecTree(tex->nodetree); + else + ntreeEndExecTree(tex->nodetree); + } + } + } + +} /* optimized tree execute test for compositing */ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) @@ -2489,6 +2588,7 @@ void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview) ntreeInitPreview(ntree, 0, 0); ntreeBeginExecTree(ntree); + ntree_composite_texnode(ntree, 1); /* prevent unlucky accidents */ if(G.background) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index a7506f2114b..95e14542e28 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1158,7 +1158,7 @@ static void init_particle_interpolation(Object *ob, ParticleSystem *psys, Partic pind->dietime = (key + pa->totkey - 1)->time; } else if(pind->cache) { - float start, end; + float start=0.0f, end=0.0f; get_pointcache_keys_for_time(ob, pind->cache, &pind->pm, -1, 0.0f, NULL, NULL); pind->birthtime = pa ? pa->time : pind->cache->startframe; pind->dietime = pa ? pa->dietime : pind->cache->endframe; @@ -2807,7 +2807,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra) float birthtime = 0.0, dietime = 0.0; float t, time = 0.0, dfra = 1.0, frs_sec = sim->scene->r.frs_sec; float col[4] = {0.5f, 0.5f, 0.5f, 1.0f}; - float prev_tangent[3], hairmat[4][4]; + float prev_tangent[3] = {0.0f, 0.0f, 0.0f}, hairmat[4][4]; float rotmat[3][3]; int k; int steps = (int)pow(2.0, (double)(psys->renderdata ? part->ren_step : part->draw_step)); @@ -3025,7 +3025,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf float birthtime = 0.0, dietime = 0.0; float t, time = 0.0, keytime = 0.0, frs_sec; - float hairmat[4][4], rotmat[3][3], prev_tangent[3]; + float hairmat[4][4], rotmat[3][3], prev_tangent[3] = {0.0f, 0.0f, 0.0f}; int k, i; int steps = (int)pow(2.0, (double)pset->draw_step); int totpart = edit->totpoint, recalc_set=0; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 1f36f0845a2..f0af7e8684b 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -350,7 +350,7 @@ void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) pa->num_dmcache= GET_INT_FROM_POINTER(nodearray[pa->num]->link); } else { /* FROM_FACE/FROM_VOLUME */ - /* Note that somtimes the pa->num is over the nodearray size, this is bad, maybe there is a better place to fix this, + /* Note that sometimes the pa->num is over the nodearray size, this is bad, maybe there is a better place to fix this, * but for now passing NULL is OK. every face will be searched for the particle so its slower - Campbell */ pa->num_dmcache= psys_particle_dm_face_lookup(ob, dm, pa->num, pa->fuv, pa->num < totelem ? nodearray[pa->num] : NULL); } @@ -2244,7 +2244,9 @@ void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys) if(cache->flag & PTCACHE_DISK_CACHE && cache->mem_cache.first == NULL) { PTCacheID pid; BKE_ptcache_id_from_particles(&pid, ob, psys); + cache->flag &= ~PTCACHE_DISK_CACHE; BKE_ptcache_disk_to_mem(&pid); + cache->flag |= PTCACHE_DISK_CACHE; } } static void psys_clear_temp_pointcache(ParticleSystem *psys) @@ -3795,7 +3797,7 @@ static void system_step(ParticleSimulationData *sim, float cfra) /* 2. try to read from the cache */ if(pid) { - int cache_result = BKE_ptcache_read(pid, cache_cfra, sim->scene->r.frs_sec); + int cache_result = BKE_ptcache_read(pid, cache_cfra); if(ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) { cached_step(sim, cfra); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 7a8d3a8b19c..b8e8508da26 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -96,7 +96,7 @@ #define DURIAN_POINTCACHE_LIB_OK 1 int ptcache_data_size[] = { - sizeof(int), // BPHYS_DATA_INDEX + sizeof(uint32_t), // BPHYS_DATA_INDEX 3 * sizeof(float), // BPHYS_DATA_LOCATION: 3 * sizeof(float), // BPHYS_DATA_VELOCITY: 4 * sizeof(float), // BPHYS_DATA_ROTATION: @@ -107,30 +107,38 @@ int ptcache_data_size[] = { }; /* forward declerations */ -static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size); -static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size); +static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, size_t len); +static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, size_t in_len, unsigned char *out, int mode); +static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, size_t size); +static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, size_t size); /* Common functions */ static int ptcache_basic_header_read(PTCacheFile *pf) { + uint32_t totpoint, data_types; int error=0; /* Custom functions should read these basic elements too! */ - if(!error && !fread(&pf->totpoint, sizeof(int), 1, pf->fp)) + if(!error && !fread(&totpoint, sizeof(int), 1, pf->fp)) error = 1; + pf->totpoint = totpoint; - if(!error && !fread(&pf->data_types, sizeof(int), 1, pf->fp)) + if(!error && !fread(&data_types, sizeof(int), 1, pf->fp)) error = 1; + pf->data_types = data_types; return !error; } static int ptcache_basic_header_write(PTCacheFile *pf) { + uint32_t totpoint = pf->totpoint; + uint32_t data_types = pf->data_types; + /* Custom functions should write these basic elements too! */ - if(!fwrite(&pf->totpoint, sizeof(int), 1, pf->fp)) + if(!fwrite(&totpoint, sizeof(int), 1, pf->fp)) return 0; - if(!fwrite(&pf->data_types, sizeof(int), 1, pf->fp)) + if(!fwrite(&data_types, sizeof(int), 1, pf->fp)) return 0; return 1; @@ -146,7 +154,7 @@ static int ptcache_softbody_write(int index, void *soft_v, void **data, int UNU return 1; } -static void ptcache_softbody_read(int index, void *soft_v, void **data, float UNUSED(frs_sec), float UNUSED(cfra), float *old_data) +static void ptcache_softbody_read(int index, void *soft_v, void **data, float UNUSED(cfra), float *old_data) { SoftBody *soft= soft_v; BodyPoint *bp = soft->bpoint + index; @@ -160,7 +168,7 @@ static void ptcache_softbody_read(int index, void *soft_v, void **data, float UN PTCACHE_DATA_TO(data, BPHYS_DATA_VELOCITY, 0, bp->vec); } } -static void ptcache_softbody_interpolate(int index, void *soft_v, void **data, float UNUSED(frs_sec), float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_softbody_interpolate(int index, void *soft_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) { SoftBody *soft= soft_v; BodyPoint *bp = soft->bpoint + index; @@ -244,11 +252,12 @@ static int ptcache_particle_write(int index, void *psys_v, void **data, int cfr /* return flag 1+1=2 for newly born particles to copy exact birth location to previously cached frame */ return 1 + (pa->state.time >= pa->time && pa->prev_state.time <= pa->time); } -static void ptcache_particle_read(int index, void *psys_v, void **data, float frs_sec, float cfra, float *old_data) +static void ptcache_particle_read(int index, void *psys_v, void **data, float cfra, float *old_data) { ParticleSystem *psys= psys_v; ParticleData *pa; BoidParticle *boid; + float timestep = 0.04f*psys->part->timetweak; if(index >= psys->totpart) return; @@ -289,11 +298,11 @@ static void ptcache_particle_read(int index, void *psys_v, void **data, float fr if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { if(cfra > pa->prev_state.time) { sub_v3_v3v3(pa->state.vel, pa->state.co, pa->prev_state.co); - mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) / frs_sec); + mul_v3_fl(pa->state.vel, (cfra - pa->prev_state.time) * timestep); } else { sub_v3_v3v3(pa->state.vel, pa->prev_state.co, pa->state.co); - mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) / frs_sec); + mul_v3_fl(pa->state.vel, (pa->prev_state.time - cfra) * timestep); } } @@ -302,12 +311,12 @@ static void ptcache_particle_read(int index, void *psys_v, void **data, float fr vec_to_quat( pa->state.rot,pa->state.vel, OB_NEGX, OB_POSZ); } } -static void ptcache_particle_interpolate(int index, void *psys_v, void **data, float frs_sec, float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_particle_interpolate(int index, void *psys_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) { ParticleSystem *psys= psys_v; ParticleData *pa; ParticleKey keys[4]; - float dfra; + float dfra, timestep = 0.04f*psys->part->timetweak; if(index >= psys->totpart) return; @@ -335,11 +344,11 @@ static void ptcache_particle_interpolate(int index, void *psys_v, void **data, f if(data[BPHYS_DATA_LOCATION] && !data[BPHYS_DATA_VELOCITY]) { if(keys[1].time > keys[2].time) { sub_v3_v3v3(keys[2].vel, keys[1].co, keys[2].co); - mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) / frs_sec); + mul_v3_fl(keys[2].vel, (keys[1].time - keys[2].time) * timestep); } else { sub_v3_v3v3(keys[2].vel, keys[2].co, keys[1].co); - mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) / frs_sec); + mul_v3_fl(keys[2].vel, (keys[2].time - keys[1].time) * timestep); } } @@ -353,13 +362,13 @@ static void ptcache_particle_interpolate(int index, void *psys_v, void **data, f dfra = cfra2 - cfra1; - mul_v3_fl(keys[1].vel, dfra / frs_sec); - mul_v3_fl(keys[2].vel, dfra / frs_sec); + mul_v3_fl(keys[1].vel, dfra * timestep); + mul_v3_fl(keys[2].vel, dfra * timestep); psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &pa->state, 1); interp_qt_qtqt(pa->state.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra); - mul_v3_fl(pa->state.vel, frs_sec / dfra); + mul_v3_fl(pa->state.vel, 1.f / (dfra * timestep)); pa->state.time = cfra; } @@ -376,6 +385,9 @@ static int ptcache_particle_totwrite(void *psys_v, int cfra) int p, step = psys->pointcache->step; int totwrite = 0; + if(cfra == 0) + return psys->totpart; + for(p=0; p<psys->totpart; p++,pa++) totwrite += (cfra >= pa->time - step && cfra <= pa->dietime + step); @@ -395,7 +407,7 @@ static int ptcache_cloth_write(int index, void *cloth_v, void **data, int UNUSE return 1; } -static void ptcache_cloth_read(int index, void *cloth_v, void **data, float UNUSED(frs_sec), float UNUSED(cfra), float *old_data) +static void ptcache_cloth_read(int index, void *cloth_v, void **data, float UNUSED(cfra), float *old_data) { ClothModifierData *clmd= cloth_v; Cloth *cloth= clmd->clothObject; @@ -412,7 +424,7 @@ static void ptcache_cloth_read(int index, void *cloth_v, void **data, float UNUS PTCACHE_DATA_TO(data, BPHYS_DATA_XCONST, 0, vert->xconst); } } -static void ptcache_cloth_interpolate(int index, void *cloth_v, void **data, float UNUSED(frs_sec), float cfra, float cfra1, float cfra2, float *old_data) +static void ptcache_cloth_interpolate(int index, void *cloth_v, void **data, float cfra, float cfra1, float cfra2, float *old_data) { ClothModifierData *clmd= cloth_v; Cloth *cloth= clmd->clothObject; @@ -455,106 +467,6 @@ static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra)) } /* Smoke functions */ -static int ptcache_compress_write(PTCacheFile *pf, unsigned char *in, unsigned int in_len, unsigned char *out, int mode) -{ - int r = 0; - unsigned char compressed = 0; - unsigned int out_len= 0; - unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); - size_t sizeOfIt = 5; - - (void)mode; /* unused when building w/o compression */ - -#ifdef WITH_LZO - out_len= LZO_OUT_LEN(in_len); - if(mode == 1) { - LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS); - - r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem); - if (!(r == LZO_E_OK) || (out_len >= in_len)) - compressed = 0; - else - compressed = 1; - } -#endif -#ifdef WITH_LZMA - if(mode == 2) { - - r = LzmaCompress(out, (size_t *)&out_len, in, in_len,//assume sizeof(char)==1.... - props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2); - - if(!(r == SZ_OK) || (out_len >= in_len)) - compressed = 0; - else - compressed = 2; - } -#endif - - ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char)); - if(compressed) { - ptcache_file_write(pf, &out_len, 1, sizeof(unsigned int)); - ptcache_file_write(pf, out, out_len, sizeof(unsigned char)); - } - else - ptcache_file_write(pf, in, in_len, sizeof(unsigned char)); - - if(compressed == 2) - { - ptcache_file_write(pf, &sizeOfIt, 1, sizeof(unsigned int)); - ptcache_file_write(pf, props, sizeOfIt, sizeof(unsigned char)); - } - - MEM_freeN(props); - - return r; -} - -static int ptcache_compress_read(PTCacheFile *pf, unsigned char *result, unsigned int len) -{ - int r = 0; - unsigned char compressed = 0; - unsigned int in_len; -#ifdef WITH_LZO - unsigned int out_len = len; - size_t sizeOfIt = 5; -#endif - unsigned char *in; - unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); - - ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char)); - if(compressed) { - ptcache_file_read(pf, &in_len, 1, sizeof(unsigned int)); - if(in_len==0) { - /* do nothing */ - } - else { - in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer"); - ptcache_file_read(pf, in, in_len, sizeof(unsigned char)); -#ifdef WITH_LZO - if(compressed == 1) - r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL); -#endif -#ifdef WITH_LZMA - if(compressed == 2) - { - size_t leni = in_len, leno = out_len; - ptcache_file_read(pf, &sizeOfIt, 1, sizeof(unsigned int)); - ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char)); - r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt); - } -#endif - MEM_freeN(in); - } - } - else { - ptcache_file_read(pf, result, len, sizeof(unsigned char)); - } - - MEM_freeN(props); - - return r; -} - static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra)) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; @@ -566,8 +478,6 @@ static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra)) else return 0; } - - static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; @@ -586,18 +496,18 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v) smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles); - ptcache_compress_write(pf, (unsigned char *)sds->shadow, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)dens, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)densold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)heat, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)heatold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vx, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vy, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vz, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vxold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vyold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)vzold, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)sds->shadow, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)heat, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)heatold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vx, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vy, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vz, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vxold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vyold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)vzold, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)obstacles, (unsigned int)res, out, mode); ptcache_file_write(pf, &dt, 1, sizeof(float)); ptcache_file_write(pf, &dx, 1, sizeof(float)); @@ -627,14 +537,14 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v) smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len_big), "pointcache_lzo_buffer"); - ptcache_compress_write(pf, (unsigned char *)dens, in_len_big, out, mode); - ptcache_compress_write(pf, (unsigned char *)densold, in_len_big, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)dens, in_len_big, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)densold, in_len_big, out, mode); MEM_freeN(out); out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len), "pointcache_lzo_buffer"); - ptcache_compress_write(pf, (unsigned char *)tcu, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)tcv, in_len, out, mode); - ptcache_compress_write(pf, (unsigned char *)tcw, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)tcu, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)tcv, in_len, out, mode); + ptcache_file_compressed_write(pf, (unsigned char *)tcw, in_len, out, mode); MEM_freeN(out); ret = 1; @@ -642,9 +552,6 @@ static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v) return ret; } - - - static void ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) { SmokeModifierData *smd= (SmokeModifierData *)smoke_v; @@ -658,18 +565,18 @@ static void ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) smoke_export(sds->fluid, &dt, &dx, &dens, &densold, &heat, &heatold, &vx, &vy, &vz, &vxold, &vyold, &vzold, &obstacles); - ptcache_compress_read(pf, (unsigned char *)sds->shadow, out_len); - ptcache_compress_read(pf, (unsigned char*)dens, out_len); - ptcache_compress_read(pf, (unsigned char*)densold, out_len); - ptcache_compress_read(pf, (unsigned char*)heat, out_len); - ptcache_compress_read(pf, (unsigned char*)heatold, out_len); - ptcache_compress_read(pf, (unsigned char*)vx, out_len); - ptcache_compress_read(pf, (unsigned char*)vy, out_len); - ptcache_compress_read(pf, (unsigned char*)vz, out_len); - ptcache_compress_read(pf, (unsigned char*)vxold, out_len); - ptcache_compress_read(pf, (unsigned char*)vyold, out_len); - ptcache_compress_read(pf, (unsigned char*)vzold, out_len); - ptcache_compress_read(pf, (unsigned char*)obstacles, (unsigned int)res); + ptcache_file_compressed_read(pf, (unsigned char *)sds->shadow, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)heat, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)heatold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vx, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vy, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vz, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vxold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vyold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)vzold, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)obstacles, (unsigned int)res); ptcache_file_read(pf, &dt, 1, sizeof(float)); ptcache_file_read(pf, &dx, 1, sizeof(float)); @@ -686,12 +593,12 @@ static void ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) smoke_turbulence_export(sds->wt, &dens, &densold, &tcu, &tcv, &tcw); - ptcache_compress_read(pf, (unsigned char*)dens, out_len_big); - ptcache_compress_read(pf, (unsigned char*)densold, out_len_big); + ptcache_file_compressed_read(pf, (unsigned char*)dens, out_len_big); + ptcache_file_compressed_read(pf, (unsigned char*)densold, out_len_big); - ptcache_compress_read(pf, (unsigned char*)tcu, out_len); - ptcache_compress_read(pf, (unsigned char*)tcv, out_len); - ptcache_compress_read(pf, (unsigned char*)tcw, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tcu, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tcv, out_len); + ptcache_file_compressed_read(pf, (unsigned char*)tcw, out_len); } } } @@ -709,21 +616,25 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) pid->ptcaches= &sb->ptcaches; pid->totpoint= pid->totwrite= ptcache_softbody_totpoint; - pid->write_elem= ptcache_softbody_write; - pid->write_stream = NULL; - pid->read_stream = NULL; - pid->read_elem= ptcache_softbody_read; - pid->interpolate_elem= ptcache_softbody_interpolate; + pid->write_point = ptcache_softbody_write; + pid->read_point = ptcache_softbody_read; + pid->interpolate_point = ptcache_softbody_interpolate; + + pid->write_stream = NULL; + pid->read_stream = NULL; - pid->write_header= ptcache_basic_header_write; - pid->read_header= ptcache_basic_header_read; + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; + + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY); pid->info_types= 0; pid->stack_index = pid->cache->index; } - void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *psys) { memset(pid, 0, sizeof(PTCacheID)); @@ -739,19 +650,24 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p if(psys->part->type != PART_HAIR) pid->flag |= PTCACHE_VEL_PER_SEC; - pid->write_elem= ptcache_particle_write; - pid->write_stream = NULL; - pid->read_stream = NULL; - pid->read_elem= ptcache_particle_read; - pid->interpolate_elem= ptcache_particle_interpolate; + pid->totpoint = ptcache_particle_totpoint; + pid->totwrite = ptcache_particle_totwrite; + + pid->write_point = ptcache_particle_write; + pid->read_point = ptcache_particle_read; + pid->interpolate_point = ptcache_particle_interpolate; - pid->totpoint= ptcache_particle_totpoint; - pid->totwrite= ptcache_particle_totwrite; + pid->write_stream = NULL; + pid->read_stream = NULL; - pid->write_header= ptcache_basic_header_write; - pid->read_header= ptcache_basic_header_read; + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; - pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX); + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; + + pid->data_types = (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_INDEX); if(psys->part->phystype == PART_PHYS_BOIDS) pid->data_types|= (1<<BPHYS_DATA_AVELOCITY) | (1<<BPHYS_DATA_ROTATION) | (1<<BPHYS_DATA_BOIDS); @@ -765,7 +681,6 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p pid->info_types= (1<<BPHYS_DATA_TIMES); } - void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *clmd) { memset(pid, 0, sizeof(PTCacheID)); @@ -779,19 +694,23 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl pid->ptcaches= &clmd->ptcaches; pid->totpoint= pid->totwrite= ptcache_cloth_totpoint; - pid->write_elem= ptcache_cloth_write; - pid->write_stream = NULL; - pid->read_stream = NULL; - pid->read_elem= ptcache_cloth_read; - pid->interpolate_elem= ptcache_cloth_interpolate; + pid->write_point = ptcache_cloth_write; + pid->read_point = ptcache_cloth_read; + pid->interpolate_point = ptcache_cloth_interpolate; - pid->write_header= ptcache_basic_header_write; - pid->read_header= ptcache_basic_header_read; + pid->write_stream = NULL; + pid->read_stream = NULL; + + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; + + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; pid->data_types= (1<<BPHYS_DATA_LOCATION) | (1<<BPHYS_DATA_VELOCITY) | (1<<BPHYS_DATA_XCONST); pid->info_types= 0; } - void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeModifierData *smd) { SmokeDomainSettings *sds = smd->domain; @@ -810,16 +729,19 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo pid->totpoint= pid->totwrite= ptcache_smoke_totpoint; - pid->write_elem= NULL; - pid->read_elem= NULL; + pid->write_point = NULL; + pid->read_point = NULL; + pid->interpolate_point = NULL; - pid->read_stream = ptcache_smoke_read; - pid->write_stream = ptcache_smoke_write; - - pid->interpolate_elem= NULL; + pid->read_stream = ptcache_smoke_read; + pid->write_stream = ptcache_smoke_write; - pid->write_header= ptcache_basic_header_write; - pid->read_header= ptcache_basic_header_read; + pid->write_extra_data = NULL; + pid->read_extra_data = NULL; + pid->interpolate_extra_data = NULL; + + pid->write_header = ptcache_basic_header_write; + pid->read_header = ptcache_basic_header_read; pid->data_types= 0; pid->info_types= 0; @@ -829,7 +751,6 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo if(sds->wt) pid->data_types |= (1<<BPHYS_DATA_SMOKE_HIGH); } - void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis) { PTCacheID *pid; @@ -901,7 +822,6 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup } } - /* File handling */ /* Takes an Object ID and returns a unique name @@ -1035,21 +955,125 @@ static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra) pf= MEM_mallocN(sizeof(PTCacheFile), "PTCacheFile"); pf->fp= fp; pf->old_format = 0; + pf->frame = cfra; return pf; } - static void ptcache_file_close(PTCacheFile *pf) { - fclose(pf->fp); - MEM_freeN(pf); + if(pf) { + fclose(pf->fp); + MEM_freeN(pf); + } +} + +static int ptcache_file_compressed_read(PTCacheFile *pf, unsigned char *result, size_t len) +{ + int r = 0; + unsigned char compressed = 0; + size_t in_len; +#ifdef WITH_LZO + size_t out_len = len; + size_t sizeOfIt = 5; +#endif + unsigned char *in; + unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); + + ptcache_file_read(pf, &compressed, 1, sizeof(unsigned char)); + if(compressed) { + uint32_t size; + ptcache_file_read(pf, &size, 1, sizeof(uint32_t)); + in_len = (size_t)size; + if(in_len==0) { + /* do nothing */ + } + else { + in = (unsigned char *)MEM_callocN(sizeof(unsigned char)*in_len, "pointcache_compressed_buffer"); + ptcache_file_read(pf, in, in_len, sizeof(unsigned char)); +#ifdef WITH_LZO + if(compressed == 1) + r = lzo1x_decompress_safe(in, (lzo_uint)in_len, result, (lzo_uint *)&out_len, NULL); +#endif +#ifdef WITH_LZMA + if(compressed == 2) + { + size_t leni = in_len, leno = out_len; + ptcache_file_read(pf, &size, 1, sizeof(unsigned int)); + sizeOfIt = (size_t)size; + ptcache_file_read(pf, props, sizeOfIt, sizeof(unsigned char)); + r = LzmaUncompress(result, &leno, in, &leni, props, sizeOfIt); + } +#endif + MEM_freeN(in); + } + } + else { + ptcache_file_read(pf, result, len, sizeof(unsigned char)); + } + + MEM_freeN(props); + + return r; } +static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, size_t in_len, unsigned char *out, int mode) +{ + int r = 0; + unsigned char compressed = 0; + size_t out_len= 0; + unsigned char *props = MEM_callocN(16*sizeof(char), "tmp"); + size_t sizeOfIt = 5; -static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, int size) + (void)mode; /* unused when building w/o compression */ + +#ifdef WITH_LZO + out_len= LZO_OUT_LEN(in_len); + if(mode == 1) { + LZO_HEAP_ALLOC(wrkmem, LZO1X_MEM_COMPRESS); + + r = lzo1x_1_compress(in, (lzo_uint)in_len, out, (lzo_uint *)&out_len, wrkmem); + if (!(r == LZO_E_OK) || (out_len >= in_len)) + compressed = 0; + else + compressed = 1; + } +#endif +#ifdef WITH_LZMA + if(mode == 2) { + + r = LzmaCompress(out, (size_t *)&out_len, in, in_len,//assume sizeof(char)==1.... + props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2); + + if(!(r == SZ_OK) || (out_len >= in_len)) + compressed = 0; + else + compressed = 2; + } +#endif + + ptcache_file_write(pf, &compressed, 1, sizeof(unsigned char)); + if(compressed) { + uint32_t size = (uint32_t) out_len; + ptcache_file_write(pf, &size, 1, sizeof(uint32_t)); + ptcache_file_write(pf, out, out_len, sizeof(unsigned char)); + } + else + ptcache_file_write(pf, in, in_len, sizeof(unsigned char)); + + if(compressed == 2) + { + ptcache_file_write(pf, &sizeOfIt, 1, sizeof(uint32_t)); + ptcache_file_write(pf, props, sizeOfIt, sizeof(unsigned char)); + } + + MEM_freeN(props); + + return r; +} +static int ptcache_file_read(PTCacheFile *pf, void *f, size_t tot, size_t size) { return (fread(f, size, tot, pf->fp) == tot); } -static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, int size) +static int ptcache_file_write(PTCacheFile *pf, void *f, size_t tot, size_t size) { return (fwrite(f, size, tot, pf->fp) == tot); } @@ -1077,6 +1101,7 @@ static int ptcache_file_data_write(PTCacheFile *pf) } static int ptcache_file_header_begin_read(PTCacheFile *pf) { + uint32_t typeflag=0; int error=0; char bphysics[8]; @@ -1088,8 +1113,11 @@ static int ptcache_file_header_begin_read(PTCacheFile *pf) if(!error && strncmp(bphysics, "BPHYSICS", 8)) error = 1; - if(!error && !fread(&pf->type, sizeof(int), 1, pf->fp)) + if(!error && !fread(&typeflag, sizeof(uint32_t), 1, pf->fp)) error = 1; + + pf->type = (typeflag & PTCACHE_TYPEFLAG_TYPEMASK); + pf->flag = (typeflag & PTCACHE_TYPEFLAG_FLAGMASK); /* if there was an error set file as it was */ if(error) @@ -1097,22 +1125,20 @@ static int ptcache_file_header_begin_read(PTCacheFile *pf) return !error; } - - static int ptcache_file_header_begin_write(PTCacheFile *pf) { const char *bphysics = "BPHYSICS"; + uint32_t typeflag = pf->type + pf->flag; if(fwrite(bphysics, sizeof(char), 8, pf->fp) != 8) return 0; - if(!fwrite(&pf->type, sizeof(int), 1, pf->fp)) + if(!fwrite(&typeflag, sizeof(uint32_t), 1, pf->fp)) return 0; return 1; } - /* Data pointer handling */ int BKE_ptcache_data_size(int data_type) { @@ -1133,38 +1159,6 @@ static void ptcache_file_pointers_init(PTCacheFile *pf) pf->cur[BPHYS_DATA_BOIDS] = (data_types & (1<<BPHYS_DATA_BOIDS)) ? &pf->data.boids : NULL; } -static void ptcache_file_pointers_seek(int index, PTCacheFile *pf) -{ - int i, size=0; - int data_types = pf->data_types; - - if(data_types & (1<<BPHYS_DATA_INDEX)) { - int totpoint; - /* The simplest solution is to just write to the very end. This may cause - * some data duplication, but since it's on disk it's not so bad. The correct - * thing would be to search through the file for the correct index and only - * write to the end if it's not found, but this could be quite slow. - */ - fseek(pf->fp, 8 + sizeof(int), SEEK_SET); - fread(&totpoint, sizeof(int), 1, pf->fp); - - totpoint++; - - fseek(pf->fp, 8 + sizeof(int), SEEK_SET); - fwrite(&totpoint, sizeof(int), 1, pf->fp); - - fseek(pf->fp, 0, SEEK_END); - } - else { - for(i=0; i<BPHYS_TOT_DATA; i++) - size += (pf->data_types & (1<<i)) ? ptcache_data_size[i] : 0; - - /* size of default header + data up to index */ - fseek(pf->fp, 8 + 3*sizeof(int) + index * size, SEEK_SET); - } - - ptcache_file_pointers_init(pf); -} void BKE_ptcache_mem_pointers_init(PTCacheMem *pm) { int data_types = pm->data_types; @@ -1239,8 +1233,15 @@ static void ptcache_data_copy(void *from[], void *to[]) } } +static void ptcache_extra_free(PTCacheMem *pm) +{ + PTCacheExtra *extra = pm->extradata.first; - + for(; extra; extra=extra->next) { + if(extra->data) + MEM_freeN(extra->data); + } +} static int ptcache_old_elemsize(PTCacheID *pid) { if(pid->type==PTCACHE_TYPE_SOFTBODY) @@ -1253,57 +1254,33 @@ static int ptcache_old_elemsize(PTCacheID *pid) return 0; } -static void *ptcache_find_frame(PTCacheID *pid, int frame) -{ - if(pid->cache->flag & PTCACHE_DISK_CACHE) { - PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, frame); - if(pf) - pf->frame = frame; - return pf; - } - else { - PTCacheMem *pm = pid->cache->mem_cache.first; - for(; pm; pm=pm->next) { - if(pm->frame == frame) - break; - } - return (void*)pm; - } -} - -static void ptcache_find_frames_around(PTCacheID *pid, int frame, void **cache1, void **cache2) +static void ptcache_find_frames_around(PTCacheID *pid, int frame, int *fra1, int *fra2) { - int cfra1=frame, cfra2=frame; - if(pid->cache->flag & PTCACHE_DISK_CACHE) { - PTCacheFile *pf=NULL; - PTCacheFile *pf2=NULL; + int cfra1=frame-1, cfra2=frame+1; - while(cfra1 >= pid->cache->startframe && pf==NULL) { + while(cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1)) cfra1--; - pf= ptcache_file_open(pid, PTCACHE_FILE_READ, cfra1); - } - if(pf) - pf->frame = cfra1; + if(cfra1 < pid->cache->startframe) + cfra1 = 0; - while(cfra2 < pid->cache->endframe && !pf2) { + while(cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2)) cfra2++; - pf2= ptcache_file_open(pid, PTCACHE_FILE_READ, cfra2); - } - if(pf2) - pf2->frame = cfra2; + if(cfra2 > pid->cache->endframe) + cfra2 = 0; - if(pf && !pf2) { - pf2 = pf; - pf = NULL; + if(cfra1 && !cfra2) { + *fra1 = 0; + *fra2 = cfra1; + } + else { + *fra1 = cfra1; + *fra2 = cfra2; } - - *cache1 = (void*)pf; - *cache2 = (void*)pf2; } - else if(pid->cache->mem_cache.first){ + else if(pid->cache->mem_cache.first) { PTCacheMem *pm = pid->cache->mem_cache.first; PTCacheMem *pm2 = pid->cache->mem_cache.last; @@ -1318,135 +1295,340 @@ static void ptcache_find_frames_around(PTCacheID *pid, int frame, void **cache1, } if(pm && !pm2) { - pm2 = pm; - pm = NULL; + *fra1 = 0; + *fra2 = pm->frame; } + else { + *fra1 = pm->frame; + *fra2 = pm2->frame; + } + } +} +static void ptcache_make_index_array(PTCacheMem *pm, int totpoint) +{ + int i, *index; - *cache1 = (void*)pm; - *cache2 = (void*)pm2; + if(pm->index_array) { + MEM_freeN(pm->index_array); + pm->index_array = NULL; } + + if(!pm->data[BPHYS_DATA_INDEX]) + return; + + pm->index_array = MEM_callocN(totpoint * sizeof(int), "PTCacheMem index_array"); + index = pm->data[BPHYS_DATA_INDEX]; + + for(i=0; i<pm->totpoint; i++, index++) + pm->index_array[*index] = i + 1; } -static int ptcache_read_init(PTCacheID *pid, void **cache, int *totpoint) + +static PTCacheMem *ptcache_disk_frame_to_mem(PTCacheID *pid, int cfra) { - if(*cache==NULL) + PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); + PTCacheMem *pm = NULL; + int i, error = 0; + + if(pf == NULL) return 0; - if(pid->cache->flag & PTCACHE_DISK_CACHE) { - PTCacheFile *pf = (PTCacheFile *)(*cache); + if(!ptcache_file_header_begin_read(pf)) + error = 1; - if(ptcache_file_header_begin_read(pf)) { - if(pf->type != pid->type) { - /* todo report error */ - ptcache_file_close(pf); - *cache = NULL; - return 0; - } - else if(pid->read_header(pf)) { - ptcache_file_pointers_init(pf); - *totpoint = pf->totpoint; + if(!error && (pf->type != pid->type || !pid->read_header(pf))) + error = 1; + + if(!error) { + pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); + + pm->totpoint = pf->totpoint; + pm->data_types = pf->data_types; + pm->frame = pf->frame; + + ptcache_data_alloc(pm); + + if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS) { + for(i=0; i<BPHYS_TOT_DATA; i++) { + unsigned int out_len = pm->totpoint*ptcache_data_size[i]; + if(pf->data_types & (1<<i)) + ptcache_file_compressed_read(pf, (unsigned char*)(pm->data[i]), out_len); } } else { - /* fall back to old cache file format */ - pf->old_format = 1; - *totpoint = pid->totpoint(pid->calldata, (int) pf->frame); + BKE_ptcache_mem_pointers_init(pm); + ptcache_file_pointers_init(pf); + + for(i=0; i<pm->totpoint; i++) { + if(!ptcache_file_data_read(pf)) { + error = 1; + break; + } + ptcache_data_copy(pf->cur, pm->cur); + BKE_ptcache_mem_pointers_incr(pm); + } } - return pf->frame; } - else { - PTCacheMem *pm = (PTCacheMem *)(*cache); - BKE_ptcache_mem_pointers_init(pm); - *totpoint = pm->totpoint; - return pm->frame; + if(!error && pf->flag & PTCACHE_TYPEFLAG_EXTRADATA) { + uint32_t extratype = 0; + uint32_t value; + + while(ptcache_file_read(pf, &extratype, 1, sizeof(uint32_t))) { + PTCacheExtra *extra = MEM_callocN(sizeof(PTCacheExtra), "Pointcache extradata"); + + extra->type = extratype; + + ptcache_file_read(pf, &value, 1, sizeof(uint32_t)); + extra->flag = value; + ptcache_file_read(pf, &value, 1, sizeof(uint32_t)); + extra->totdata = value; + ptcache_file_read(pf, &value, 1, sizeof(uint32_t)); + extra->datasize = value; + + extra->data = MEM_callocN(extra->totdata * extra->datasize, "Pointcache extradata->data"); + + if(pf->flag & PTCACHE_TYPEFLAG_COMPRESS) + ptcache_file_compressed_read(pf, (unsigned char*)(extra->data), extra->totdata*extra->datasize); + else + ptcache_file_read(pf, extra->data, extra->totdata, extra->datasize); + + BLI_addtail(&pm->extradata, extra); + } + } + + if(!error) + ptcache_make_index_array(pm, pid->totpoint(pid->calldata, pm->frame)); + + if(error && pm) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); + pm = NULL; } + + ptcache_file_close(pf); + + if (error && G.f & G_DEBUG) + printf("Error reading from disk cache\n"); + + return pm; } -static int ptcache_read(PTCacheID *pid, void *cache, int totpoint, float frs_sec) +static int ptcache_mem_frame_to_disk(PTCacheID *pid, PTCacheMem *pm) { - int i; - int *index = &i; + PTCacheFile *pf = NULL; + int i, error = 0; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, pm->frame); - if(pid->cache->flag & PTCACHE_DISK_CACHE) { - PTCacheFile *pf = (PTCacheFile *)cache; - if(pf->old_format) { - int old_elemsize = ptcache_old_elemsize(pid); - float old_data[14]; + pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame); - for(i=0; i<totpoint; i++) { - if(ptcache_file_read(pf, (void*)old_data, 1, old_elemsize)) - pid->read_elem(i, pid->calldata, NULL, frs_sec, (float)pf->frame, old_data); - else - return 0; + if(pf==NULL) { + if (G.f & G_DEBUG) + printf("Error opening disk cache file for writing\n"); + return 0; + } + + pf->data_types = pm->data_types; + pf->totpoint = pm->totpoint; + pf->type = pid->type; + pf->flag = 0; + + if(pm->extradata.first) + pf->flag |= PTCACHE_TYPEFLAG_EXTRADATA; + + if(pid->cache->compression) + pf->flag |= PTCACHE_TYPEFLAG_COMPRESS; + + if(!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)) + error = 1; + + if(!error) { + if(pid->cache->compression) { + for(i=0; i<BPHYS_TOT_DATA; i++) { + if(pm->data[i]) { + unsigned int in_len = pm->totpoint*ptcache_data_size[i]; + unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); + ptcache_file_compressed_write(pf, (unsigned char*)(pm->data[i]), in_len, out, pid->cache->compression); + MEM_freeN(out); + } } } else { - if(pf->data_types & (1<<BPHYS_DATA_INDEX)) - index = &pf->data.index; - - for(i=0; i<totpoint; i++) { - if(ptcache_file_data_read(pf)) - pid->read_elem(*index, pid->calldata, pf->cur, frs_sec, (float)pf->frame, NULL); - else - return 0; + BKE_ptcache_mem_pointers_init(pm); + ptcache_file_pointers_init(pf); + + for(i=0; i<pm->totpoint; i++) { + ptcache_data_copy(pm->cur, pf->cur); + if(!ptcache_file_data_write(pf)) { + error = 1; + break; + } + BKE_ptcache_mem_pointers_incr(pm); } } } + + if(!error && pm->extradata.first) { + PTCacheExtra *extra = pm->extradata.first; + uint32_t value; + + for(; extra; extra=extra->next) { + if(extra->data == NULL || extra->totdata == 0) + continue; + + value = extra->type; + ptcache_file_write(pf, &value, 1, sizeof(uint32_t)); + value = extra->flag; + ptcache_file_write(pf, &value, 1, sizeof(uint32_t)); + value = extra->totdata; + ptcache_file_write(pf, &value, 1, sizeof(uint32_t)); + value = extra->datasize; + ptcache_file_write(pf, &value, 1, sizeof(uint32_t)); + + if(pid->cache->compression) { + unsigned int in_len = extra->totdata * extra->datasize; + unsigned char *out = (unsigned char *)MEM_callocN(LZO_OUT_LEN(in_len)*4, "pointcache_lzo_buffer"); + ptcache_file_compressed_write(pf, (unsigned char*)(extra->data), in_len, out, pid->cache->compression); + MEM_freeN(out); + } + else { + ptcache_file_write(pf, extra->data, extra->totdata, extra->datasize); + } + } + } + + ptcache_file_close(pf); + + if (error && G.f & G_DEBUG) + printf("Error writing to disk cache\n"); + + return error==0; +} + +static int ptcache_read_stream(PTCacheID *pid, int cfra) +{ + PTCacheFile *pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); + int error = 0; + + if(pid->read_stream == NULL) + return 0; + + if(pf == NULL) { + if (G.f & G_DEBUG) + printf("Error opening disk cache file for reading\n"); + return 0; + } + + if(!ptcache_file_header_begin_read(pf)) + error = 1; + + if(!error && (pf->type != pid->type || !pid->read_header(pf))) + error = 1; + + if(!error && pf->totpoint != pid->totpoint(pid->calldata, cfra)) + error = 1; + + if(!error) { + ptcache_file_pointers_init(pf); + + // we have stream reading here + pid->read_stream(pf, pid->calldata); + } + + ptcache_file_close(pf); + + return error == 0; +} +static int ptcache_read(PTCacheID *pid, int cfra) +{ + PTCacheMem *pm = NULL; + int i; + int *index = &i; + + /* get a memory cache to read from */ + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + pm = ptcache_disk_frame_to_mem(pid, cfra); + } else { - PTCacheMem *pm = (PTCacheMem *)cache; + pm = pid->cache->mem_cache.first; + + while(pm && pm->frame != cfra) + pm = pm->next; + } + + /* read the cache */ + if(pm) { + int totpoint = pm->totpoint; + + if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) + totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, cfra)); + + BKE_ptcache_mem_pointers_init(pm); for(i=0; i<totpoint; i++) { if(pm->data_types & (1<<BPHYS_DATA_INDEX)) index = pm->cur[BPHYS_DATA_INDEX]; - pid->read_elem(*index, pid->calldata, pm->cur, frs_sec, (float)pm->frame, NULL); + pid->read_point(*index, pid->calldata, pm->cur, (float)pm->frame, NULL); BKE_ptcache_mem_pointers_incr(pm); } + + if(pid->read_extra_data && pm->extradata.first) + pid->read_extra_data(pid->calldata, pm, (float)pm->frame); + + /* clean up temporary memory cache */ + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); + } } return 1; } -static int ptcache_interpolate(PTCacheID *pid, void *cache1, void *cache2, int totpoint, float cfra, float frs_sec) +static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2) { + PTCacheMem *pm = NULL; int i; int *index = &i; + /* get a memory cache to read from */ if(pid->cache->flag & PTCACHE_DISK_CACHE) { - PTCacheFile *pf1 = (PTCacheFile *)cache1; - PTCacheFile *pf2 = (PTCacheFile *)cache2; - if(pf2->old_format) { - int old_elemsize = ptcache_old_elemsize(pid); - float old_data[14]; - - for(i=0; i<totpoint; i++) { - if(ptcache_file_read(pf2, (void*)old_data, 1, old_elemsize)) - pid->interpolate_elem(i, pid->calldata, NULL, frs_sec, cfra, (float)pf1->frame, (float)pf2->frame, old_data); - else - return 0; - } - } - else { - if(pf2->data_types & (1<<BPHYS_DATA_INDEX)) - index = &pf2->data.index; - - for(i=0; i<totpoint; i++) { - if(ptcache_file_data_read(pf2)) - pid->interpolate_elem(*index, pid->calldata, pf2->cur, frs_sec, cfra, (float)pf1->frame, (float)pf2->frame, NULL); - else - return 0; - } - } + pm = ptcache_disk_frame_to_mem(pid, cfra2); } else { - PTCacheMem *pm1 = (PTCacheMem *)cache1; - PTCacheMem *pm2 = (PTCacheMem *)cache2; + pm = pid->cache->mem_cache.first; + + while(pm && pm->frame != cfra2) + pm = pm->next; + } + + /* read the cache */ + if(pm) { + int totpoint = pm->totpoint; + + if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) + totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int)cfra)); + + BKE_ptcache_mem_pointers_init(pm); for(i=0; i<totpoint; i++) { - if(pm2->data_types & (1<<BPHYS_DATA_INDEX)) - index = pm2->cur[BPHYS_DATA_INDEX]; + if(pm->data_types & (1<<BPHYS_DATA_INDEX)) + index = pm->cur[BPHYS_DATA_INDEX]; - pid->interpolate_elem(*index, pid->calldata, pm2->cur, frs_sec, cfra, (float)pm1->frame, (float)pm2->frame, NULL); - BKE_ptcache_mem_pointers_incr(pm2); + pid->interpolate_point(*index, pid->calldata, pm->cur, cfra, (float)cfra1, (float)cfra2, NULL); + BKE_ptcache_mem_pointers_incr(pm); + } + + if(pid->interpolate_extra_data && pm->extradata.first) + pid->interpolate_extra_data(pid->calldata, pm, cfra, (float)cfra1, (float)cfra2); + + /* clean up temporary memory cache */ + if(pid->cache->flag & PTCACHE_DISK_CACHE) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); } } @@ -1454,11 +1636,9 @@ static int ptcache_interpolate(PTCacheID *pid, void *cache1, void *cache2, int t } /* reads cache from disk or memory */ /* possible to get old or interpolated result */ -int BKE_ptcache_read(PTCacheID *pid, float cfra, float frs_sec) +int BKE_ptcache_read(PTCacheID *pid, float cfra) { - void *cache1=NULL, *cache2=NULL; int cfrai = (int)cfra, cfra1=0, cfra2=0; - int totpoint = 0, totpoint2 = 0; int ret = 0; /* nothing to read to */ @@ -1467,88 +1647,49 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra, float frs_sec) if(pid->cache->flag & PTCACHE_READ_INFO) { pid->cache->flag &= ~PTCACHE_READ_INFO; - BKE_ptcache_read(pid, 0, frs_sec); + ptcache_read(pid, 0); } /* first check if we have the actual frame cached */ - if(cfra == (float)cfrai) - cache1 = ptcache_find_frame(pid, cfrai); + if(cfra == (float)cfrai && BKE_ptcache_id_exist(pid, cfrai)) + cfra1 = cfrai; /* no exact cache frame found so try to find cached frames around cfra */ - if(cache1==NULL) - ptcache_find_frames_around(pid, cfrai, &cache1, &cache2); + if(cfra1 == 0) + ptcache_find_frames_around(pid, cfrai, &cfra1, &cfra2); - if(cache1==NULL && cache2==NULL) + if(cfra1 == 0 && cfra2 == 0) return 0; - cfra1 = ptcache_read_init(pid, &cache1, &totpoint); - cfra2 = ptcache_read_init(pid, &cache2, &totpoint2); - /* don't read old cache if already simulated past cached frame */ - if(!cache1 && cfra2 && cfra2 <= pid->cache->simframe) - goto cleanup; - if(cfra1 && cfra1==cfra2) - goto cleanup; - - if(cache1) { - if(pid->read_stream) { - if(totpoint != pid->totpoint(pid->calldata, (int) cfra)) - goto cleanup; - else - { - // we have stream reading here - pid->read_stream((PTCacheFile *)cache1, pid->calldata); - } - } - else if(pid->read_elem) { - if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) - totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int) cfra)); + if(cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe) + return 0; + if(cfra1 && cfra1 == cfra2) + return 0; - if(ptcache_read(pid, cache1, totpoint, frs_sec)==0) - goto cleanup; - } + if(cfra1) { + if(pid->read_stream) + ptcache_read_stream(pid, cfra1); + else if(pid->read_point) + ptcache_read(pid, cfra1); } - if(cache2) { - if(pid->read_stream) { - if(totpoint2 != pid->totpoint(pid->calldata, (int) cfra)) - goto cleanup; + if(cfra2) { + if(pid->read_stream) + ptcache_read_stream(pid, cfra2); + else if(pid->read_point) { + if(cfra1 && cfra2 && pid->interpolate_point) + ptcache_interpolate(pid, cfra, cfra1, cfra2); else - { - // we have stream reading here - pid->read_stream((PTCacheFile *)cache2, pid->calldata); - } - } - else if(pid->read_elem) { - if((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) - totpoint2 = MIN2(totpoint2, pid->totpoint(pid->calldata, (int) cfra)); - - if(cache1 && cache2 && pid->interpolate_elem) { - if(ptcache_interpolate(pid, cache1, cache2, totpoint2, cfra, frs_sec)==0) - goto cleanup; - } - else { - if(ptcache_read(pid, cache2, totpoint2, frs_sec)==0) - goto cleanup; - } + ptcache_read(pid, cfra2); } } - if(cache1) - ret = (cache2 ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT); - else if(cache2) { + if(cfra1) + ret = (cfra2 ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT); + else if(cfra2) { ret = PTCACHE_READ_OLD; - pid->cache->simframe = ((pid->cache->flag & PTCACHE_DISK_CACHE) ? - ((PTCacheFile*)cache2)->frame : ((PTCacheMem*)cache2)->frame); - } - -cleanup: - - if(pid->cache->flag & PTCACHE_DISK_CACHE) { - if(cache1) - ptcache_file_close((PTCacheFile*)cache1); - if(cache2) - ptcache_file_close((PTCacheFile*)cache2); + pid->cache->simframe = cfra2; } if((pid->cache->flag & PTCACHE_QUICK_CACHE)==0) { @@ -1561,31 +1702,114 @@ cleanup: if(cfra <= pid->cache->last_exact) pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED; - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai,pid->cache->last_exact)); + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, MAX2(cfrai, pid->cache->last_exact)); } } return ret; } -static void ptcache_make_index_array(PTCacheMem *pm, int totpoint) +static int ptcache_write_stream(PTCacheID *pid, int cfra, int totpoint) { - int i, *index; + PTCacheFile *pf = NULL; + int error = 0; + + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_FRAME, cfra); - if(pm->index_array) { - MEM_freeN(pm->index_array); - pm->index_array = NULL; + pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra); + + if(pf==NULL) { + if (G.f & G_DEBUG) + printf("Error opening disk cache file for writing\n"); + return 0; } - if(!pm->data[BPHYS_DATA_INDEX]) - return; + pf->data_types = pid->data_types; + pf->totpoint = totpoint; + pf->type = pid->type; + pf->flag = 0; - pm->index_array = MEM_callocN(totpoint * sizeof(int), "PTCacheMem index_array"); - index = pm->data[BPHYS_DATA_INDEX]; + if(!error && (!ptcache_file_header_begin_write(pf) || !pid->write_header(pf))) + error = 1; - for(i=0; i<pm->totpoint; i++, index++) - pm->index_array[*index] = i + 1; + if(!error && pid->write_stream) + pid->write_stream(pf, pid->calldata); + + ptcache_file_close(pf); + + if (error && G.f & G_DEBUG) + printf("Error writing to disk cache\n"); + + return error == 0; } +static int ptcache_write(PTCacheID *pid, int cfra, int overwrite) +{ + PointCache *cache = pid->cache; + PTCacheMem *pm=NULL, *pm2=NULL; + int totpoint = pid->totpoint(pid->calldata, cfra); + int i, error = 0; + + pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); + + pm->totpoint = pid->totwrite(pid->calldata, cfra); + pm->data_types = cfra ? pid->data_types : pid->info_types; + + ptcache_data_alloc(pm); + BKE_ptcache_mem_pointers_init(pm); + + if(overwrite) { + if(cache->flag & PTCACHE_DISK_CACHE) { + int fra = cfra-1; + + while(fra >= cache->startframe && !BKE_ptcache_id_exist(pid, fra)) + fra--; + + pm2 = ptcache_disk_frame_to_mem(pid, fra); + } + else + pm2 = cache->mem_cache.last; + } + + if(pid->write_point) { + for(i=0; i<totpoint; i++) { + int write = pid->write_point(i, pid->calldata, pm->cur, cfra); + if(write) { + BKE_ptcache_mem_pointers_incr(pm); + + /* newly born particles have to be copied to previous cached frame */ + if(overwrite && write == 2 && pm2 && BKE_ptcache_mem_pointers_seek(i, pm2)) + pid->write_point(i, pid->calldata, pm2->cur, cfra); + } + } + } + + if(pid->write_extra_data) + pid->write_extra_data(pid->calldata, pm, cfra); + pm->frame = cfra; + + if(cache->flag & PTCACHE_DISK_CACHE) { + error += !ptcache_mem_frame_to_disk(pid, pm); + + if(pm) { + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); + } + + if(pm2) { + error += !ptcache_mem_frame_to_disk(pid, pm2); + ptcache_data_free(pm2); + ptcache_extra_free(pm2); + MEM_freeN(pm2); + } + } + else { + ptcache_make_index_array(pm, pid->totpoint(pid->calldata, cfra)); + BLI_addtail(&cache->mem_cache, pm); + } + + return error; +} static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite) { PointCache *cache = pid->cache; @@ -1639,10 +1863,8 @@ static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite) int BKE_ptcache_write(PTCacheID *pid, int cfra) { PointCache *cache = pid->cache; - PTCacheFile *pf= NULL, *pf2= NULL; - int i, ret = 0; int totpoint = pid->totpoint(pid->calldata, cfra); - int overwrite = 0; + int overwrite = 0, error = 0; if(totpoint == 0 || (cfra ? pid->data_types == 0 : pid->info_types == 0)) return 0; @@ -1650,109 +1872,29 @@ int BKE_ptcache_write(PTCacheID *pid, int cfra) if(ptcache_write_needed(pid, cfra, &overwrite)==0) return 0; - if(cache->flag & PTCACHE_DISK_CACHE) { - pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, cfra); - if(!pf) - goto cleanup; - - pf->type = pid->type; - pf->totpoint = cfra ? pid->totwrite(pid->calldata, cfra) : totpoint; - pf->data_types = cfra ? pid->data_types : pid->info_types; - - if(!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)) - goto cleanup; - - ptcache_file_pointers_init(pf); - - if(pid->write_stream) { - // we have stream writing here - pid->write_stream(pf, pid->calldata); - } - else if(pid->write_elem){ - for(i=0; i<totpoint; i++) { - int write = pid->write_elem(i, pid->calldata, pf->cur, cfra); - if(write) { - if(!ptcache_file_data_write(pf)) - goto cleanup; - - /* newly born particles have to be copied to previous cached frame */ - if(overwrite && write == 2) { - if(!pf2) { - /* find and initialize previous frame */ - int ofra = cfra-1; - while(ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra)) - ofra--; - - pf2 = ptcache_file_open(pid, PTCACHE_FILE_UPDATE, ofra); - if(!pf2) - goto cleanup; - - pf2->type = pid->type; - pf2->totpoint = totpoint; - pf2->data_types = pid->data_types; - } - ptcache_file_pointers_seek(i, pf2); - pid->write_elem(i, pid->calldata, pf2->cur, cfra); - if(!ptcache_file_data_write(pf2)) - goto cleanup; - } - } - } - } + if(pid->write_stream) { + ptcache_write_stream(pid, cfra, totpoint); } - else { - PTCacheMem *pm; - PTCacheMem *pm2; - - pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); - - pm->totpoint = pid->totwrite(pid->calldata, cfra); - pm->data_types = cfra ? pid->data_types : pid->info_types; - - ptcache_data_alloc(pm); - BKE_ptcache_mem_pointers_init(pm); - - if(pid->write_elem) { - for(i=0; i<totpoint; i++) { - int write = pid->write_elem(i, pid->calldata, pm->cur, cfra); - if(write) { - BKE_ptcache_mem_pointers_incr(pm); - - /* newly born particles have to be copied to previous cached frame */ - if(overwrite && write == 2) { - pm2 = cache->mem_cache.last; - if(BKE_ptcache_mem_pointers_seek(i, pm2)) - pid->write_elem(i, pid->calldata, pm2->cur, cfra); - } - } - } - } - ptcache_make_index_array(pm, pid->totpoint(pid->calldata, cfra)); - - pm->frame = cfra; - BLI_addtail(&cache->mem_cache, pm); + else if(pid->write_point) { + error += ptcache_write(pid, cfra, overwrite); } + /* Mark frames skipped if more than 1 frame forwards since last non-skipped frame. */ if(cfra - cache->last_exact == 1 || cfra == cache->startframe) { cache->last_exact = cfra; cache->flag &= ~PTCACHE_FRAMES_SKIPPED; } - else + /* Don't mark skipped when writing info file (frame 0) */ + else if(cfra) cache->flag |= PTCACHE_FRAMES_SKIPPED; + /* Update timeline cache display */ if(cache->cached_frames) cache->cached_frames[cfra-cache->startframe] = 1; - ret = 1; - -cleanup: - if(pf) ptcache_file_close(pf); - - if(pf2) ptcache_file_close(pf2); - BKE_ptcache_update_info(pid); - return ret; + return !error; } /* youll need to close yourself after! * mode - PTCACHE_CLEAR_ALL, @@ -1762,7 +1904,6 @@ cleanup: void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) { int len; /* store the length of the string */ - int i; int sta, end; /* mode is same as fopen's modes */ @@ -1810,8 +1951,6 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) pid->cache->last_exact = MIN2(pid->cache->startframe, 0); BLI_join_dirfile(path_full, path, de->d_name); BLI_delete(path_full, 0, 0); - if(pid->cache->cached_frames) for(i=0; i<end-sta+1; i++) - pid->cache->cached_frames[i] = 0; } else { /* read the number of the file */ int frame, len2 = (int)strlen(de->d_name); @@ -1835,6 +1974,9 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) } } closedir(dir); + + if(mode == PTCACHE_CLEAR_ALL && pid->cache->cached_frames) + memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames)); } else { PTCacheMem *pm= pid->cache->mem_cache.first; @@ -1845,12 +1987,14 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) if(mode == PTCACHE_CLEAR_ALL) { /*we want startframe if the cache starts before zero*/ pid->cache->last_exact = MIN2(pid->cache->startframe, 0); - for(; pm; pm=pm->next) + for(; pm; pm=pm->next) { ptcache_data_free(pm); + ptcache_extra_free(pm); + } BLI_freelistN(&pid->cache->mem_cache); - if(pid->cache->cached_frames) for(i=0; i<end-sta+1; i++) - pid->cache->cached_frames[i] = 0; + if(pid->cache->cached_frames) + memset(pid->cache->cached_frames, 0, MEM_allocN_len(pid->cache->cached_frames)); } else { while(pm) { if((mode==PTCACHE_CLEAR_BEFORE && pm->frame < cfra) || @@ -1859,6 +2003,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) if(pid->cache->cached_frames && pm->frame >=sta && pm->frame <= end) pid->cache->cached_frames[pm->frame-sta] = 0; ptcache_data_free(pm); + ptcache_extra_free(pm); pm = pm->next; BLI_freelinkN(&pid->cache->mem_cache, link); } @@ -1882,6 +2027,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) for(; pm; pm=pm->next) { if(pm->frame == cfra) { ptcache_data_free(pm); + ptcache_extra_free(pm); BLI_freelinkN(&pid->cache->mem_cache, pm); break; } @@ -1894,7 +2040,6 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, int cfra) BKE_ptcache_update_info(pid); } - int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) { if(!pid->cache) @@ -1923,7 +2068,6 @@ int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) return 0; } } - void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale) { Object *ob; @@ -2030,7 +2174,6 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra } } } - int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) { PointCache *cache; @@ -2093,7 +2236,6 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) return (reset || clear || after); } - int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) { PTCacheID pid; @@ -2235,8 +2377,10 @@ void BKE_ptcache_free_mem(ListBase *mem_cache) PTCacheMem *pm = mem_cache->first; if(pm) { - for(; pm; pm=pm->next) + for(; pm; pm=pm->next) { ptcache_data_free(pm); + ptcache_extra_free(pm); + } BLI_freelistN(mem_cache); } @@ -2549,120 +2693,51 @@ void BKE_ptcache_bake(PTCacheBaker* baker) void BKE_ptcache_disk_to_mem(PTCacheID *pid) { PointCache *cache = pid->cache; - PTCacheFile *pf; - PTCacheMem *pm; - + PTCacheMem *pm = NULL; + int baked = cache->flag & PTCACHE_BAKED; int cfra, sfra = cache->startframe, efra = cache->endframe; - int i; - - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - - for(cfra=sfra; cfra <= efra; cfra++) { - pf = ptcache_file_open(pid, PTCACHE_FILE_READ, cfra); - - if(pf) { - if(!ptcache_file_header_begin_read(pf)) { - printf("Can't yet convert old cache format\n"); - cache->flag |= PTCACHE_DISK_CACHE; - ptcache_file_close(pf); - return; - } - - if(pf->type != pid->type || !pid->read_header(pf)) { - cache->flag |= PTCACHE_DISK_CACHE; - ptcache_file_close(pf); - return; - } - - pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache mem"); - - pm->totpoint = pf->totpoint; - pm->data_types = pf->data_types; - pm->frame = cfra; - ptcache_data_alloc(pm); - BKE_ptcache_mem_pointers_init(pm); - ptcache_file_pointers_init(pf); + /* Remove possible bake flag to allow clear */ + cache->flag &= ~PTCACHE_BAKED; - for(i=0; i<pm->totpoint; i++) { - if(!ptcache_file_data_read(pf)) { - printf("Error reading from disk cache\n"); - - cache->flag |= PTCACHE_DISK_CACHE; - - ptcache_data_free(pm); - MEM_freeN(pm); - ptcache_file_close(pf); + /* PTCACHE_DISK_CACHE flag was cleared already */ + BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - return; - } - ptcache_data_copy(pf->cur, pm->cur); - BKE_ptcache_mem_pointers_incr(pm); - } + /* restore possible bake flag */ + cache->flag |= baked; - ptcache_make_index_array(pm, pid->totpoint(pid->calldata, cfra)); + for(cfra=sfra; cfra <= efra; cfra++) { + pm = ptcache_disk_frame_to_mem(pid, cfra); + if(pm) BLI_addtail(&pid->cache->mem_cache, pm); - - ptcache_file_close(pf); - } } - } void BKE_ptcache_mem_to_disk(PTCacheID *pid) { PointCache *cache = pid->cache; - PTCacheFile *pf; - PTCacheMem *pm; - int i; + PTCacheMem *pm = cache->mem_cache.first; + int baked = cache->flag & PTCACHE_BAKED; - pm = cache->mem_cache.first; + /* Remove possible bake flag to allow clear */ + cache->flag &= ~PTCACHE_BAKED; + /* PTCACHE_DISK_CACHE flag was set already */ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - for(; pm; pm=pm->next) { - pf = ptcache_file_open(pid, PTCACHE_FILE_WRITE, pm->frame); - - if(pf) { - pf->data_types = pm->data_types; - pf->totpoint = pm->totpoint; - pf->type = pid->type; + /* restore possible bake flag */ + cache->flag |= baked; - BKE_ptcache_mem_pointers_init(pm); - ptcache_file_pointers_init(pf); - - if(!ptcache_file_header_begin_write(pf) || !pid->write_header(pf)) { - if (G.f & G_DEBUG) - printf("Error writing to disk cache\n"); - cache->flag &= ~PTCACHE_DISK_CACHE; - - ptcache_file_close(pf); - return; - } - - for(i=0; i<pm->totpoint; i++) { - ptcache_data_copy(pm->cur, pf->cur); - if(!ptcache_file_data_write(pf)) { - if (G.f & G_DEBUG) - printf("Error writing to disk cache\n"); - cache->flag &= ~PTCACHE_DISK_CACHE; - - ptcache_file_close(pf); - return; - } - BKE_ptcache_mem_pointers_incr(pm); - } - - ptcache_file_close(pf); - - /* write info file */ - if(cache->flag & PTCACHE_BAKED) - BKE_ptcache_write(pid, 0); + for(; pm; pm=pm->next) { + if(ptcache_mem_frame_to_disk(pid, pm)==0) { + cache->flag &= ~PTCACHE_DISK_CACHE; + break; } - else - if (G.f & G_DEBUG) - printf("Error creating disk cache file\n"); } + + /* write info file */ + if(cache->flag & PTCACHE_BAKED) + BKE_ptcache_write(pid, 0); } void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) { @@ -2676,6 +2751,11 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) return; } + if(cache->cached_frames) { + MEM_freeN(cache->cached_frames); + cache->cached_frames=NULL; + } + if(cache->flag & PTCACHE_DISK_CACHE) BKE_ptcache_mem_to_disk(pid); else @@ -2687,11 +2767,6 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) cache->last_exact = last_exact; - if(cache->cached_frames) { - MEM_freeN(cache->cached_frames); - cache->cached_frames=NULL; - } - BKE_ptcache_id_time(pid, NULL, 0.0f, NULL, NULL, NULL); BKE_ptcache_update_info(pid); @@ -2854,6 +2929,7 @@ void BKE_ptcache_load_external(PTCacheID *pid) void BKE_ptcache_update_info(PTCacheID *pid) { PointCache *cache = pid->cache; + PTCacheExtra *extra = NULL; int totframes = 0; char mem_info[64]; @@ -2903,7 +2979,16 @@ void BKE_ptcache_update_info(PTCacheID *pid) for(; pm; pm=pm->next) { for(i=0; i<BPHYS_TOT_DATA; i++) - bytes += pm->data[i] ? MEM_allocN_len(pm->data[i]) : 0.0f; + bytes += MEM_allocN_len(pm->data[i]); + + for(extra=pm->extradata.first; extra; extra=extra->next) { + bytes += MEM_allocN_len(extra->data); + bytes += sizeof(PTCacheExtra); + } + + bytes += MEM_allocN_len(pm->index_array); + bytes += sizeof(PTCacheMem); + totframes++; } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 19f872fbd40..1b5d1093373 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -642,7 +642,7 @@ void calc_sequence(Scene *scene, Sequence *seq) void reload_sequence_new_file(Scene *scene, Sequence * seq, int lock_range) { char str[FILE_MAXDIR+FILE_MAXFILE]; - int prev_startdisp, prev_enddisp; + int prev_startdisp=0, prev_enddisp=0; /* note: dont rename the strip, will break animation curves */ if (ELEM5(seq->type, SEQ_MOVIE, SEQ_IMAGE, SEQ_SOUND, SEQ_SCENE, SEQ_META)==0) { diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index babe4209a31..9a0f278bcd0 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -1376,7 +1376,7 @@ void smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedM } /* try to read from cache */ - if(BKE_ptcache_read(&pid, (float)framenr, scene->r.frs_sec) == PTCACHE_READ_EXACT) { + if(BKE_ptcache_read(&pid, (float)framenr) == PTCACHE_READ_EXACT) { BKE_ptcache_validate(cache, framenr); smd->time = framenr; return; diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 4653562e5f4..eb56331acfb 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -4134,7 +4134,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i } /* try to read from cache */ - cache_result = BKE_ptcache_read(&pid, framenr, scene->r.frs_sec); + cache_result = BKE_ptcache_read(&pid, framenr); if(cache_result == PTCACHE_READ_EXACT || cache_result == PTCACHE_READ_INTERPOLATED) { softbody_to_object(ob, vertexCos, numVerts, sb->local); diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index bbdc188d580..bb3a31a0977 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -2710,9 +2710,13 @@ int setcurr_tab_spaces (Text *text, int space) } if(strstr(text->curl->line, word)) { - //if we find a : then add a tab but not if it is in a comment + /* if we find a ':' on this line, then add a tab but not if it is: + * 1) in a comment + * 2) within an identifier + * 3) after the cursor (text->curc), i.e. when creating space before a function def [#25414] + */ int a, indent = 0; - for(a=0; text->curl->line[a] != '\0'; a++) + for(a=0; (a < text->curc) && (text->curl->line[a] != '\0'); a++) { if (text->curl->line[a]=='#') { break; |