diff options
Diffstat (limited to 'source')
99 files changed, 5677 insertions, 2164 deletions
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt index 0d309523daf..e2bf5930275 100644 --- a/source/blender/CMakeLists.txt +++ b/source/blender/CMakeLists.txt @@ -67,6 +67,7 @@ set(SRC_DNA_INC ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_outliner_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_packedFile_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_particle_types.h + ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_pointcache_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_property_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_rigidbody_types.h ${CMAKE_CURRENT_SOURCE_DIR}/makesdna/DNA_scene_types.h @@ -106,6 +107,7 @@ add_subdirectory(gpu) add_subdirectory(imbuf) add_subdirectory(nodes) add_subdirectory(modifiers) +add_subdirectory(pointcache) add_subdirectory(makesdna) add_subdirectory(makesrna) diff --git a/source/blender/SConscript b/source/blender/SConscript index de052f24c33..34de8a16cf1 100644 --- a/source/blender/SConscript +++ b/source/blender/SConscript @@ -42,7 +42,8 @@ SConscript(['avi/SConscript', 'modifiers/SConscript', 'ikplugin/SConscript', 'windowmanager/SConscript', - 'blenfont/SConscript']) + 'blenfont/SConscript', + 'pointcache/SConscript']) makesrna = SConscript('makesrna/SConscript') diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 39cf5505382..e56add721eb 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -384,7 +384,7 @@ void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short fr void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]); void psys_mat_hair_to_orco(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]); -float psys_get_dietime_from_cache(struct PointCache *cache, int index); +float psys_get_dietime_from_cache(struct ListBase *mem_cache, int index); void psys_free_pdd(struct ParticleSystem *psys); @@ -421,4 +421,8 @@ float psys_get_current_display_percentage(struct ParticleSystem *psys); #define DMCACHE_NOTFOUND -1 #define DMCACHE_ISCHILD -2 +/* Point Cache memory storage */ + + + #endif diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 99579086e25..280d85c0882 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -34,7 +34,7 @@ #include "DNA_ID.h" #include "DNA_dynamicpaint_types.h" -#include "DNA_object_force.h" +#include "DNA_pointcache_types.h" #include "DNA_boid_types.h" #include <stdio.h> /* for FILE */ @@ -165,26 +165,8 @@ typedef struct PTCacheID { int (*read_header)(PTCacheFile *pf); struct PointCache *cache; - /* used for setting the current cache from ptcaches list */ - struct PointCache **cache_ptr; - struct ListBase *ptcaches; } PTCacheID; -typedef struct PTCacheBaker { - struct Main *main; - struct Scene *scene; - int bake; - int render; - int anim_init; - int quick_step; - struct PTCacheID *pid; - int (*break_test)(void *data); - void *break_data; - void (*progressbar)(void *data, int num); - void (*progressend)(void *data); - void *progresscontext; -} PTCacheBaker; - /* PTCacheEditKey->flag */ #define PEK_SELECT 1 #define PEK_TAG 2 @@ -238,6 +220,7 @@ typedef struct PTCacheEdit { PTCacheEditPoint *points; struct PTCacheID pid; + struct ListBase mem_cache; /* particles stuff */ struct ParticleSystem *psys; @@ -300,28 +283,18 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra); int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra); /******************* Allocate & free ***************/ -struct PointCache *BKE_ptcache_add(struct ListBase *ptcaches); +struct PointCache *BKE_ptcache_new(void); void BKE_ptcache_free_mem(struct ListBase *mem_cache); void BKE_ptcache_free(struct PointCache *cache); -void BKE_ptcache_free_list(struct ListBase *ptcaches); -struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, struct ListBase *ptcaches_old, bool copy_data); +struct PointCache *BKE_ptcache_copy(struct PointCache *cache, bool copy_data); /********************** Baking *********************/ -/* Bakes cache with cache_step sized jumps in time, not accurate but very fast. */ -void BKE_ptcache_quick_cache_all(struct Main *bmain, struct Scene *scene); - -/* Bake cache or simulate to current frame with settings defined in the baker. */ -void BKE_ptcache_bake(struct PTCacheBaker *baker); - /* Convert disk cache to memory cache. */ -void BKE_ptcache_disk_to_mem(struct PTCacheID *pid); +void BKE_ptcache_to_mem(struct PTCacheID *pid, struct ListBase *mem_cache); /* Convert memory cache to disk cache. */ -void BKE_ptcache_mem_to_disk(struct PTCacheID *pid); - -/* Convert disk cache to memory cache and vice versa. Clears the cache that was converted. */ -void BKE_ptcache_toggle_disk_cache(struct PTCacheID *pid); +void BKE_ptcache_from_mem(struct PTCacheID *pid, struct ListBase *mem_cache); /* Rename all disk cache files with a new name. Doesn't touch the actual content of the files. */ void BKE_ptcache_disk_cache_rename(struct PTCacheID *pid, const char *name_src, const char *name_dst); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index c71595e7a3e..328c465f07b 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -36,6 +36,7 @@ set(INC ../bmesh ../modifiers ../nodes + ../pointcache ../render/extern/include ../../../intern/ghost ../../../intern/guardedalloc diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 3da3d647275..6de55e276a1 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -65,6 +65,7 @@ incs = [ '../makesrna', '../modifiers', '../nodes', + '../pointcache', '../render/extern/include', '../windowmanager', env['BF_ZLIB_INC'], diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 07051e30bbe..9cc99a07353 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -65,6 +65,8 @@ #include "BKE_deform.h" #include "BKE_global.h" /* For debug flag, DM_update_tessface_data() func. */ +#include "PTC_api.h" + #ifdef WITH_GAMEENGINE #include "BKE_navmesh_conversion.h" static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm); @@ -1461,6 +1463,58 @@ static void dm_ensure_display_normals(DerivedMesh *dm) CDDM_calc_normals_mapping_ex(dm, (dm->dirty & DM_DIRTY_NORMALS) ? false : true); } } + +/* Look for last point cache modifier that provides a valid derived mesh. + * This will then be used as the input for remaining modifiers, or as the + * final result if no other modifiers follow. + */ +static ModifierData *mesh_find_start_modifier(Scene *scene, Object *ob, VirtualModifierData *virtual_modifiers, int required_mode, bool useDeform) +{ + const bool skipVirtualArmature = (useDeform < 0); + + ModifierData *md; + + for (md = ob->modifiers.last; md; md = md->prev) { + if (md->type == eModifierType_PointCache) { + PointCacheModifierData *pcmd = (PointCacheModifierData *)md; + struct PTCReader *reader; + PTCReadSampleResult result; + + if (!modifier_isEnabled(scene, md, required_mode)) + continue; + + /* XXX needs a more lightweight reader stored inside the modifier, + * which can be checked quickly for valid cache samples before reading. + */ + reader = PTC_reader_point_cache(scene, ob, pcmd); + result = PTC_test_sample(reader, scene->r.cfra); + PTC_reader_free(reader); + + if (ELEM(result, PTC_READ_SAMPLE_EXACT, PTC_READ_SAMPLE_INTERPOLATED)) { + break; + } + } + } + if (md) + return md; + + /* no valid cache modifier found, + * take virtual modifiers at list start into account + */ + + if (!skipVirtualArmature) { + md = modifiers_getVirtualModifierList(ob, virtual_modifiers); + } + else { + /* game engine exception */ + md = ob->modifiers.first; + if (md && md->type == eModifierType_Armature) + md = md->next; + } + + return md; +} + /* new value for useDeform -1 (hack for the gameengine): * - apply only the modifier stack of the object, skipping the virtual modifiers, * - don't apply the key @@ -1482,7 +1536,6 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos int numVerts = me->totvert; int required_mode; bool isPrevDeform = false; - const bool skipVirtualArmature = (useDeform < 0); MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0); const bool has_multires = (mmd && mmd->sculptlvl != 0); bool multires_applied = false; @@ -1511,23 +1564,14 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos app_flags |= MOD_APPLY_USECACHE; if (useDeform) deform_app_flags |= MOD_APPLY_USECACHE; - - if (!skipVirtualArmature) { - firstmd = modifiers_getVirtualModifierList(ob, &virtualModifierData); - } - else { - /* game engine exception */ - firstmd = ob->modifiers.first; - if (firstmd && firstmd->type == eModifierType_Armature) - firstmd = firstmd->next; - } - - md = firstmd; - - modifiers_clearErrors(ob); - + if (useRenderParams) required_mode = eModifierMode_Render; else required_mode = eModifierMode_Realtime; + + modifiers_clearErrors(ob); + + firstmd = mesh_find_start_modifier(scene, ob, &virtualModifierData, required_mode, useDeform); + md = firstmd; if (do_mod_wmcol || do_mod_mcol) { /* Find the last active modifier generating a preview, or NULL if none. */ diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 3cd26dacebd..964d876a9a0 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -55,6 +55,7 @@ #include "DNA_object_fluidsim.h" #include "DNA_object_force.h" #include "DNA_object_types.h" +#include "DNA_pointcache_types.h" #include "DNA_particle_types.h" #include "DNA_sequence_types.h" #include "DNA_sound_types.h" @@ -449,17 +450,14 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int ModifierData *md; ParticleSystem *psys; -#define BPATH_TRAVERSE_POINTCACHE(ptcaches) \ - { \ - PointCache *cache; \ - for (cache = (ptcaches).first; cache; cache = cache->next) { \ - if (cache->flag & PTCACHE_DISK_CACHE) { \ - rewrite_path_fixed(cache->path, \ - visit_cb, \ - absbase, \ - bpath_user_data); \ - } \ - } \ +#define BPATH_TRAVERSE_POINTCACHE(cache) \ + { \ + if (cache) { \ + rewrite_path_fixed(cache->path, \ + visit_cb, \ + absbase, \ + bpath_user_data); \ + } \ } (void)0 /* do via modifiers instead */ @@ -475,16 +473,17 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int if (fluidmd->fss) { rewrite_path_fixed(fluidmd->fss->surfdataPath, visit_cb, absbase, bpath_user_data); } + BPATH_TRAVERSE_POINTCACHE(fluidmd->point_cache); } else if (md->type == eModifierType_Smoke) { SmokeModifierData *smd = (SmokeModifierData *)md; if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { - BPATH_TRAVERSE_POINTCACHE(smd->domain->ptcaches[0]); + BPATH_TRAVERSE_POINTCACHE(smd->domain->point_cache[0]); } } else if (md->type == eModifierType_Cloth) { ClothModifierData *clmd = (ClothModifierData *) md; - BPATH_TRAVERSE_POINTCACHE(clmd->ptcaches); + BPATH_TRAVERSE_POINTCACHE(clmd->point_cache); } else if (md->type == eModifierType_Ocean) { OceanModifierData *omd = (OceanModifierData *) md; @@ -497,11 +496,11 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int } if (ob->soft) { - BPATH_TRAVERSE_POINTCACHE(ob->soft->ptcaches); + BPATH_TRAVERSE_POINTCACHE(ob->soft->pointcache); } for (psys = ob->particlesystem.first; psys; psys = psys->next) { - BPATH_TRAVERSE_POINTCACHE(psys->ptcaches); + BPATH_TRAVERSE_POINTCACHE(psys->pointcache); } #undef BPATH_TRAVERSE_POINTCACHE diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 3932a8ead2f..e1b5dd6d39d 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -474,11 +474,13 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived (clmd->clothObject && dm->getNumVerts(dm) != clmd->clothObject->numverts)) { clmd->sim_parms->reset = 0; - cache->flag |= PTCACHE_OUTDATED; + cloth_free_modifier(clmd); + + cache->state.flag |= PTC_STATE_OUTDATED; BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); BKE_ptcache_validate(cache, 0); - cache->last_exact= 0; - cache->flag &= ~PTCACHE_REDO_NEEDED; + cache->state.last_exact= 0; + cache->state.flag &= ~PTC_STATE_REDO_NEEDED; } // unused in the moment, calculated separately in implicit.c @@ -514,10 +516,13 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived return; if ((framenr == startframe) && (clmd->sim_parms->preroll == 0)) { + cloth_free_modifier(clmd); + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); - do_init_cloth(ob, clmd, dm, framenr); BKE_ptcache_validate(cache, framenr); - cache->flag &= ~PTCACHE_REDO_NEEDED; + cache->state.flag &= ~PTC_STATE_REDO_NEEDED; + + do_init_cloth(ob, clmd, dm, framenr); clmd->clothObject->last_frame= framenr; return; } @@ -531,7 +536,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived BKE_ptcache_validate(cache, framenr); - if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) + if (cache_result == PTCACHE_READ_INTERPOLATED && cache->state.flag & PTC_STATE_REDO_NEEDED) BKE_ptcache_write(&pid, framenr); clmd->clothObject->last_frame= framenr; @@ -541,20 +546,15 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived else if (cache_result==PTCACHE_READ_OLD) { implicit_set_positions(clmd); } - else if ( /*ob->id.lib ||*/ (cache->flag & PTCACHE_BAKED)) { /* 2.4x disabled lib, but this can be used in some cases, testing further - campbell */ - /* if baked and nothing in cache, do nothing */ - BKE_ptcache_invalidate(cache); - return; - } if (framenr!=clmd->clothObject->last_frame+1) return; /* if on second frame, write cache for first frame */ - if (cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) + if (cache->state.simframe == startframe && (cache->state.flag & PTC_STATE_OUTDATED || cache->state.last_exact==0)) BKE_ptcache_write(&pid, startframe); - clmd->sim_parms->timescale *= framenr - cache->simframe; + clmd->sim_parms->timescale *= framenr - cache->state.simframe; /* do simulation */ BKE_ptcache_validate(cache, framenr); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 566aa6657b9..1f3f31c3220 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -53,6 +53,8 @@ #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_node_types.h" +#include "DNA_object_force.h" +#include "DNA_pointcache_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_windowmanager_types.h" diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index e3fa4733e6c..58a7702828c 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -47,6 +47,8 @@ #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_pointcache_types.h" #include "DNA_scene_types.h" #include "DNA_texture_types.h" @@ -495,9 +497,9 @@ static void object_cacheIgnoreClear(Object *ob, int state) for (pid = pidlist.first; pid; pid = pid->next) { if (pid->cache) { if (state) - pid->cache->flag |= PTCACHE_IGNORE_CLEAR; + pid->cache->flag |= PTC_IGNORE_CLEAR; else - pid->cache->flag &= ~PTCACHE_IGNORE_CLEAR; + pid->cache->flag &= ~PTC_IGNORE_CLEAR; } } @@ -928,8 +930,7 @@ static void surface_freeUnusedData(DynamicPaintSurface *surface) if (!surface->data) return; /* free bakedata if not active or surface is baked */ - if (!(surface->flags & MOD_DPAINT_ACTIVE) || - (surface->pointcache && surface->pointcache->flag & PTCACHE_BAKED)) + if (!(surface->flags & MOD_DPAINT_ACTIVE)) { free_bakeData(surface->data); } @@ -963,7 +964,7 @@ void dynamicPaint_freeSurfaceData(DynamicPaintSurface *surface) void dynamicPaint_freeSurface(DynamicPaintSurface *surface) { /* point cache */ - BKE_ptcache_free_list(&(surface->ptcaches)); + BKE_ptcache_free(surface->pointcache); surface->pointcache = NULL; if (surface->effector_weights) @@ -1027,8 +1028,7 @@ DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSettings *c surface->type = MOD_DPAINT_SURFACE_T_PAINT; /* cache */ - surface->pointcache = BKE_ptcache_add(&(surface->ptcaches)); - surface->pointcache->flag |= PTCACHE_DISK_CACHE; + surface->pointcache = BKE_ptcache_new(); surface->pointcache->step = 1; /* Set initial values */ @@ -1969,10 +1969,12 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene BKE_ptcache_id_time(&pid, scene, (float)scene->r.cfra, NULL, NULL, NULL); /* reset non-baked cache at first frame */ - if ((int)scene->r.cfra == surface->start_frame && !(cache->flag & PTCACHE_BAKED)) { - cache->flag |= PTCACHE_REDO_NEEDED; + if ((int)scene->r.cfra == surface->start_frame) { + dynamicPaint_clearSurface(scene, surface); + + cache->state.flag |= PTC_STATE_REDO_NEEDED; BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); - cache->flag &= ~PTCACHE_REDO_NEEDED; + cache->state.flag &= ~PTC_STATE_REDO_NEEDED; } /* try to read from cache */ @@ -1980,7 +1982,7 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene BKE_ptcache_validate(cache, (int)scene->r.cfra); } /* if read failed and we're on surface range do recalculate */ - else if ((int)scene->r.cfra == current_frame && !(cache->flag & PTCACHE_BAKED)) { + else if ((int)scene->r.cfra == current_frame) { /* calculate surface frame */ canvas->flags |= MOD_DPAINT_BAKING; dynamicPaint_calculateFrame(surface, scene, ob, current_frame); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index ccbce205b01..41f7721d59f 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -49,6 +49,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_movieclip_types.h" +#include "DNA_object_force.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_sequence_types.h" @@ -1177,7 +1178,7 @@ struct Object *BKE_object_lod_matob_get(Object *ob, Scene *scene) #endif /* WITH_GAMEENGINE */ -SoftBody *copy_softbody(SoftBody *sb, bool copy_caches) +SoftBody *copy_softbody(SoftBody *sb, bool copy_cache) { SoftBody *sbn; @@ -1185,7 +1186,7 @@ SoftBody *copy_softbody(SoftBody *sb, bool copy_caches) sbn = MEM_dupallocN(sb); - if (copy_caches == false) { + if (copy_cache == false) { sbn->totspring = sbn->totpoint = 0; sbn->bpoint = NULL; sbn->bspring = NULL; @@ -1214,7 +1215,7 @@ SoftBody *copy_softbody(SoftBody *sb, bool copy_caches) sbn->scratch = NULL; - sbn->pointcache = BKE_ptcache_copy_list(&sbn->ptcaches, &sb->ptcaches, copy_caches); + sbn->pointcache = BKE_ptcache_copy(sb->pointcache, copy_cache); if (sb->effector_weights) sbn->effector_weights = MEM_dupallocN(sb->effector_weights); @@ -1288,7 +1289,7 @@ static ParticleSystem *copy_particlesystem(ParticleSystem *psys) BLI_listbase_clear(&psysn->childcachebufs); psysn->renderdata = NULL; - psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, false); + psysn->pointcache = BKE_ptcache_copy(psys->pointcache, false); /* XXX - from reading existing code this seems correct but intended usage of * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */ diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 4868feab017..78a54e5c6ac 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -42,7 +42,9 @@ #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_object_force.h" #include "DNA_particle_types.h" +#include "DNA_pointcache_types.h" #include "DNA_smoke_types.h" #include "DNA_scene_types.h" #include "DNA_dynamicpaint_types.h" @@ -405,14 +407,12 @@ void free_hair(Object *UNUSED(ob), ParticleSystem *psys, int dynamics) if (psys->clmd) { if (dynamics) { - BKE_ptcache_free_list(&psys->ptcaches); - psys->clmd->point_cache = psys->pointcache = NULL; - BLI_listbase_clear(&psys->clmd->ptcaches); + BKE_ptcache_free(psys->pointcache); modifier_free((ModifierData *)psys->clmd); psys->clmd = NULL; - psys->pointcache = BKE_ptcache_add(&psys->ptcaches); + psys->pointcache = BKE_ptcache_new(); } else { cloth_free_modifier(psys->clmd); @@ -562,7 +562,7 @@ void psys_free(Object *ob, ParticleSystem *psys) psys->part = NULL; } - BKE_ptcache_free_list(&psys->ptcaches); + BKE_ptcache_free(psys->pointcache); psys->pointcache = NULL; BLI_freelistN(&psys->targets); @@ -1091,15 +1091,15 @@ typedef struct ParticleInterpolationData { float birthtime, dietime; int bspline; } ParticleInterpolationData; -/* Assumes pointcache->mem_cache exists, so for disk cached particles call psys_make_temp_pointcache() before use */ +/* Assumes mem_cache exists, so call psys_make_temp_pointcache() before use */ /* It uses ParticleInterpolationData->pm to store the current memory cache frame so it's thread safe. */ -static void get_pointcache_keys_for_time(Object *UNUSED(ob), PointCache *cache, PTCacheMem **cur, int index, float t, ParticleKey *key1, ParticleKey *key2) +static void get_pointcache_keys_for_time(Object *UNUSED(ob), ListBase *mem_cache, PTCacheMem **cur, int index, float t, ParticleKey *key1, ParticleKey *key2) { static PTCacheMem *pm = NULL; int index1, index2; if (index < 0) { /* initialize */ - *cur = cache->mem_cache.first; + *cur = mem_cache->first; if (*cur) *cur = (*cur)->next; @@ -1120,20 +1120,20 @@ static void get_pointcache_keys_for_time(Object *UNUSED(ob), PointCache *cache, else BKE_ptcache_make_particle_key(key1, index1, pm->prev->data, (float)pm->prev->frame); } - else if (cache->mem_cache.first) { - pm = cache->mem_cache.first; + else if (mem_cache->first) { + pm = mem_cache->first; index2 = BKE_ptcache_mem_index_find(pm, index); BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame); copy_particle_key(key1, key2, 1); } } } -static int get_pointcache_times_for_particle(PointCache *cache, int index, float *start, float *end) +static int get_pointcache_times_for_particle(ListBase *mem_cache, int index, float *start, float *end) { PTCacheMem *pm; int ret = 0; - for (pm = cache->mem_cache.first; pm; pm = pm->next) { + for (pm = mem_cache->first; pm; pm = pm->next) { if (BKE_ptcache_mem_index_find(pm, index) >= 0) { *start = pm->frame; ret++; @@ -1141,7 +1141,7 @@ static int get_pointcache_times_for_particle(PointCache *cache, int index, float } } - for (pm = cache->mem_cache.last; pm; pm = pm->prev) { + for (pm = mem_cache->last; pm; pm = pm->prev) { if (BKE_ptcache_mem_index_find(pm, index) >= 0) { *end = pm->frame; ret++; @@ -1152,12 +1152,12 @@ static int get_pointcache_times_for_particle(PointCache *cache, int index, float return ret == 2; } -float psys_get_dietime_from_cache(PointCache *cache, int index) +float psys_get_dietime_from_cache(ListBase *mem_cache, int index) { PTCacheMem *pm; int dietime = 10000000; /* some max value so that we can default to pa->time+lifetime */ - for (pm = cache->mem_cache.last; pm; pm = pm->prev) { + for (pm = mem_cache->last; pm; pm = pm->prev) { if (BKE_ptcache_mem_index_find(pm, index) >= 0) return (float)pm->frame; } @@ -1187,11 +1187,11 @@ static void init_particle_interpolation(Object *ob, ParticleSystem *psys, Partic } else if (pind->cache) { float start = 0.0f, end = 0.0f; - get_pointcache_keys_for_time(ob, pind->cache, &pind->pm, -1, 0.0f, NULL, NULL); + get_pointcache_keys_for_time(ob, &psys->mem_pointcache, &pind->pm, -1, 0.0f, NULL, NULL); pind->birthtime = pa ? pa->time : pind->cache->startframe; pind->dietime = pa ? pa->dietime : pind->cache->endframe; - if (get_pointcache_times_for_particle(pind->cache, pa - psys->particles, &start, &end)) { + if (get_pointcache_times_for_particle(&psys->mem_pointcache, pa - psys->particles, &start, &end)) { pind->birthtime = MAX2(pind->birthtime, start); pind->dietime = MIN2(pind->dietime, end); } @@ -1324,7 +1324,7 @@ static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData memcpy(keys + 2, pind->kkey[1], sizeof(ParticleKey)); } else if (pind->cache) { - get_pointcache_keys_for_time(NULL, pind->cache, &pind->pm, p, real_t, keys + 1, keys + 2); + get_pointcache_keys_for_time(NULL, &psys->mem_pointcache, &pind->pm, p, real_t, keys + 1, keys + 2); } else { hair_to_particle(keys + 1, pind->hkey[0]); @@ -2975,7 +2975,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra) return; keyed = psys->flag & PSYS_KEYED; - baked = psys->pointcache->mem_cache.first && psys->part->type != PART_HAIR; + baked = psys->mem_pointcache.first && psys->part->type != PART_HAIR; /* clear out old and create new empty path cache */ psys_free_path_cache(psys, psys->edit); @@ -3509,7 +3509,7 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n psys->flag &= ~PSYS_CURRENT; psys = MEM_callocN(sizeof(ParticleSystem), "particle_system"); - psys->pointcache = BKE_ptcache_add(&psys->ptcaches); + psys->pointcache = BKE_ptcache_new(); BLI_addtail(&ob->particlesystem, psys); psys->part = psys_new_settings(DATA_("ParticleSettings"), NULL); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 3705fb11125..2a71cf2780f 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -52,6 +52,7 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" +#include "DNA_pointcache_types.h" #include "DNA_object_force.h" #include "DNA_object_types.h" #include "DNA_curve_types.h" @@ -84,12 +85,13 @@ #include "BKE_material.h" #include "BKE_cloth.h" #include "BKE_lattice.h" -#include "BKE_pointcache.h" #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_scene.h" #include "BKE_bvhutils.h" +#include "PTC_api.h" + #include "PIL_time.h" #include "RE_shader_ext.h" @@ -111,9 +113,6 @@ static ThreadRWMutex psys_bvhtree_rwlock = BLI_RWLOCK_INITIALIZER; static int particles_are_dynamic(ParticleSystem *psys) { - if (psys->pointcache->flag & PTCACHE_BAKED) - return 0; - if (psys->part->type == PART_HAIR) return psys->flag & PSYS_HAIR_DYNAMICS; else @@ -126,7 +125,7 @@ float psys_get_current_display_percentage(ParticleSystem *psys) if ((psys->renderdata && !particles_are_dynamic(psys)) || /* non-dynamic particles can be rendered fully */ (part->child_nbr && part->childtype) || /* display percentage applies to children */ - (psys->pointcache->flag & PTCACHE_BAKING)) /* baking is always done with full amount */ + (psys->pointcache->state.flag & PTC_STATE_BAKING)) /* baking is always done with full amount */ { return 1.0f; } @@ -134,11 +133,9 @@ float psys_get_current_display_percentage(ParticleSystem *psys) return psys->part->disp/100.0f; } -static int tot_particles(ParticleSystem *psys, PTCacheID *pid) +static int tot_particles(ParticleSystem *psys) { - if (pid && psys->pointcache->flag & PTCACHE_EXTERNAL) - return pid->cache->totpoint; - else if (psys->part->distr == PART_DISTR_GRID && psys->part->from != PART_FROM_VERT) + if (psys->part->distr == PART_DISTR_GRID && psys->part->from != PART_FROM_VERT) return psys->part->grid_res * psys->part->grid_res * psys->part->grid_res - psys->totunexist; else return psys->part->totpart - psys->totunexist; @@ -151,7 +148,7 @@ void psys_reset(ParticleSystem *psys, int mode) if (ELEM(mode, PSYS_RESET_ALL, PSYS_RESET_DEPSGRAPH)) { if (mode == PSYS_RESET_ALL || !(psys->flag & PSYS_EDITED)) { /* don't free if not absolutely necessary */ - if (psys->totpart != tot_particles(psys, NULL)) { + if (psys->totpart != tot_particles(psys)) { psys_free_particles(psys); psys->totpart= 0; } @@ -184,7 +181,7 @@ void psys_reset(ParticleSystem *psys, int mode) psys_free_path_cache(psys, psys->edit); /* reset point cache */ - BKE_ptcache_invalidate(psys->pointcache); + PTC_invalidate(psys->pointcache); if (psys->fluid_springs) { MEM_freeN(psys->fluid_springs); @@ -2050,12 +2047,6 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, pa->dietime = pa->time + pa->lifetime; - if (sim->psys->pointcache && sim->psys->pointcache->flag & PTCACHE_BAKED && - sim->psys->pointcache->mem_cache.first) { - float dietime = psys_get_dietime_from_cache(sim->psys->pointcache, p); - pa->dietime = MIN2(pa->dietime, dietime); - } - if (pa->time > cfra) pa->alive = PARS_UNBORN; else if (pa->dietime <= cfra) @@ -2195,20 +2186,17 @@ static void set_keyed_keys(ParticleSimulationData *sim) /************************************************/ void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys) { - PointCache *cache = psys->pointcache; - - if (cache->flag & PTCACHE_DISK_CACHE && BLI_listbase_is_empty(&cache->mem_cache)) { - 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; + if (psys->mem_pointcache.first == NULL) { + /* XXX TODO */ +// PTCacheID pid; +// BKE_ptcache_id_from_particles(&pid, ob, psys); +// BKE_ptcache_to_mem(&pid, &psys->mem_pointcache); } } static void psys_clear_temp_pointcache(ParticleSystem *psys) { - if (psys->pointcache->flag & PTCACHE_DISK_CACHE) - BKE_ptcache_free_mem(&psys->pointcache->mem_cache); + /* XXX TODO */ +// BKE_ptcache_free_mem(&psys->mem_pointcache); } void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra) { @@ -3928,19 +3916,19 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra) psys_free_children(psys); } - if ((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0) - skip = 1; /* only hair, keyed and baked stuff can have paths */ + if ((part->type==PART_HAIR || psys->flag&PSYS_KEYED)==0) + skip = 1; /* only hair and keyed can have paths */ else if (part->ren_as != PART_DRAW_PATH && !(part->type==PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))) skip = 1; /* particle visualization must be set as path */ else if (!psys->renderdata) { if (part->draw_as != PART_DRAW_REND) skip = 1; /* draw visualization */ - else if (psys->pointcache->flag & PTCACHE_BAKING) + else if (psys->pointcache->state.flag & PTC_STATE_BAKING) skip = 1; /* no need to cache paths while baking dynamics */ else if (psys_in_edit_mode(sim->scene, psys)) { if ((pset->flag & PE_DRAW_PART)==0) skip = 1; - else if (part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0) + else if (part->childtype==0 && !(psys->flag & PSYS_HAIR_DYNAMICS)) skip = 1; /* in edit mode paths are needed for child particles and dynamic hair */ } } @@ -4520,7 +4508,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra) /* update alive status and push events */ if (pa->time > cfra) { pa->alive = PARS_UNBORN; - if (part->flag & PART_UNBORN && (psys->pointcache->flag & PTCACHE_EXTERNAL) == 0) + if (part->flag & PART_UNBORN && (psys->pointcache->flag & PTC_EXTERNAL) == 0) reset_particle(sim, pa, 0.0f, cfra); } else if (dietime <= cfra) @@ -4647,11 +4635,11 @@ static void particles_fluid_step(ParticleSimulationData *sim, int UNUSED(cfra)) #endif // WITH_MOD_FLUID } -static int emit_particles(ParticleSimulationData *sim, PTCacheID *pid, float UNUSED(cfra)) +static int emit_particles(ParticleSimulationData *sim, struct PTCReader *cache_reader, float UNUSED(cfra)) { ParticleSystem *psys = sim->psys; int oldtotpart = psys->totpart; - int totpart = tot_particles(psys, pid); + int totpart = (cache_reader && psys->pointcache->flag & PTC_EXTERNAL) ? PTC_reader_particles_totpoint(cache_reader) : tot_particles(psys); if (totpart != oldtotpart) realloc_particles(sim, totpart); @@ -4670,7 +4658,7 @@ static void system_step(ParticleSimulationData *sim, float cfra) ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; PointCache *cache = psys->pointcache; - PTCacheID ptcacheid, *pid = NULL; + struct PTCReader *cache_reader = NULL; PARTICLE_P; float disp, cache_cfra = cfra; /*, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; */ int startframe = 0, endframe = 100, oldtotpart = 0; @@ -4680,19 +4668,20 @@ static void system_step(ParticleSimulationData *sim, float cfra) psys_clear_temp_pointcache(psys); /* set suitable cache range automatically */ - if ((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0) + if ((cache->state.flag & PTC_STATE_BAKING)==0) psys_get_pointcache_start_end(sim->scene, psys, &cache->startframe, &cache->endframe); - pid = &ptcacheid; - BKE_ptcache_id_from_particles(pid, sim->ob, psys); + cache_reader = PTC_reader_particles(sim->scene, sim->ob, psys); - BKE_ptcache_id_time(pid, sim->scene, 0.0f, &startframe, &endframe, NULL); + PTC_reader_get_frame_range(cache_reader, &startframe, &endframe); - /* clear everythin on start frame */ + /* clear everything on start frame */ if (cfra == startframe) { - BKE_ptcache_id_reset(sim->scene, pid, PTCACHE_RESET_OUTDATED); - BKE_ptcache_validate(cache, startframe); - cache->flag &= ~PTCACHE_REDO_NEEDED; + /* XXX anything to do here? */ + psys_reset(psys, PSYS_RESET_DEPSGRAPH); +// BKE_ptcache_id_reset(sim->scene, pid, PTCACHE_RESET_OUTDATED); + PTC_validate(cache, startframe); + cache->state.flag &= ~PTC_STATE_REDO_NEEDED; } CLAMP(cache_cfra, startframe, endframe); @@ -4700,7 +4689,7 @@ static void system_step(ParticleSimulationData *sim, float cfra) /* 1. emit particles and redo particles if needed */ oldtotpart = psys->totpart; - if (emit_particles(sim, pid, cfra) || psys->recalc & PSYS_RECALC_RESET) { + if (emit_particles(sim, cache_reader, cfra) || psys->recalc & PSYS_RECALC_RESET) { distribute_particles(sim, part->from); initialize_all_particles(sim); /* reset only just created particles (on startframe all particles are recreated) */ @@ -4716,41 +4705,39 @@ static void system_step(ParticleSimulationData *sim, float cfra) /* flag for possible explode modifiers after this system */ sim->psmd->flag |= eParticleSystemFlag_Pars; - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra); + /* XXX needs stitcher implementation to copy over previous samples */ +// BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra); } /* 2. try to read from the cache */ - if (pid) { - int cache_result = BKE_ptcache_read(pid, cache_cfra); + if (cache_reader) { + PTCReadSampleResult cache_result = PTC_read_sample(cache_reader, cache_cfra); - if (ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) { + if (ELEM(cache_result, PTC_READ_SAMPLE_EXACT, PTC_READ_SAMPLE_INTERPOLATED)) { cached_step(sim, cfra); update_children(sim); psys_update_path_cache(sim, cfra); - BKE_ptcache_validate(cache, (int)cache_cfra); + PTC_validate(cache, (int)cache_cfra); - if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) - BKE_ptcache_write(pid, (int)cache_cfra); + /* XXX TODO */ +// if (cache_result == PTC_READ_SAMPLE_INTERPOLATED && cache->state.flag & PTC_STATE_REDO_NEEDED) +// BKE_ptcache_write(pid, (int)cache_cfra); return; } - /* Cache is supposed to be baked, but no data was found so bail out */ - else if (cache->flag & PTCACHE_BAKED) { - psys_reset(psys, PSYS_RESET_CACHE_MISS); - return; - } - else if (cache_result == PTCACHE_READ_OLD) { - psys->cfra = (float)cache->simframe; + else if (cache_result == PTC_READ_SAMPLE_EARLY) { + psys->cfra = (float)cache->state.simframe; cached_step(sim, psys->cfra); } /* if on second frame, write cache for first frame */ - if (psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) - BKE_ptcache_write(pid, startframe); + /* XXX TODO */ +// if (psys->cfra == startframe && (cache->state.flag & PTC_STATE_OUTDATED || cache->last_exact==0)) +// BKE_ptcache_write(pid, startframe); } else - BKE_ptcache_invalidate(cache); + PTC_invalidate(cache); /* 3. do dynamics */ /* set particles to be not calculated TODO: can't work with pointcache */ @@ -4802,11 +4789,11 @@ static void system_step(ParticleSimulationData *sim, float cfra) } /* 4. only write cache starting from second frame */ - if (pid) { - BKE_ptcache_validate(cache, (int)cache_cfra); - if ((int)cache_cfra != startframe) - BKE_ptcache_write(pid, (int)cache_cfra); - } +// if (pid) { +// BKE_ptcache_validate(cache, (int)cache_cfra); +// if ((int)cache_cfra != startframe) +// BKE_ptcache_write(pid, (int)cache_cfra); +// } update_children(sim); @@ -4821,9 +4808,9 @@ static void system_step(ParticleSimulationData *sim, float cfra) void psys_changed_type(Object *ob, ParticleSystem *psys) { ParticleSettings *part = psys->part; - PTCacheID pid; +// PTCacheID pid; - BKE_ptcache_id_from_particles(&pid, ob, psys); +// BKE_ptcache_id_from_particles(&pid, ob, spsys); if (part->phystype != PART_PHYS_KEYED) psys->flag &= ~PSYS_KEYED; @@ -4841,7 +4828,8 @@ void psys_changed_type(Object *ob, ParticleSystem *psys) CLAMP(part->path_start, 0.0f, 100.0f); CLAMP(part->path_end, 0.0f, 100.0f); - BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); + /* XXX TODO */ +// BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); } else { free_hair(ob, psys, 1); @@ -4900,9 +4888,10 @@ static void psys_prepare_physics(ParticleSimulationData *sim) ParticleSettings *part = sim->psys->part; if (ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) { - PTCacheID pid; - BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys); - BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); + /* XXX TODO */ +// PTCacheID pid; +// BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys); +// BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); } else { free_keyed_keys(sim->psys); @@ -4933,7 +4922,9 @@ static void psys_prepare_physics(ParticleSimulationData *sim) } static int hair_needs_recalc(ParticleSystem *psys) { - if (!(psys->flag & PSYS_EDITED) && (!psys->edit || !psys->edit->edited) && + /* XXX TODO */ +// if (!(psys->flag & PSYS_EDITED) && (!psys->edit || !psys->edit->edited) && + if (!(psys->flag & PSYS_EDITED) && (!psys->edit || true) && ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET || (psys->part->flag & PART_HAIR_REGROW && !psys->edit))) { return 1; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 19ed49c727a..75301471fca 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -74,6 +74,8 @@ #include "BIK_api.h" +#include "PTC_api.h" + #ifdef WITH_BULLET # include "RBI_api.h" #endif @@ -1100,8 +1102,6 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) pid->calldata= sb; pid->type= PTCACHE_TYPE_SOFTBODY; pid->cache= sb->pointcache; - pid->cache_ptr= &sb->pointcache; - pid->ptcaches= &sb->ptcaches; pid->totpoint= pid->totwrite= ptcache_softbody_totpoint; pid->error = ptcache_softbody_error; @@ -1136,8 +1136,6 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p pid->type= PTCACHE_TYPE_PARTICLES; pid->stack_index= psys->pointcache->index; pid->cache= psys->pointcache; - pid->cache_ptr= &psys->pointcache; - pid->ptcaches= &psys->ptcaches; if (psys->part->type != PART_HAIR) pid->flag |= PTCACHE_VEL_PER_SEC; @@ -1194,8 +1192,6 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl pid->type= PTCACHE_TYPE_CLOTH; pid->stack_index= clmd->point_cache->index; pid->cache= clmd->point_cache; - pid->cache_ptr= &clmd->point_cache; - pid->ptcaches= &clmd->ptcaches; pid->totpoint= pid->totwrite= ptcache_cloth_totpoint; pid->error = ptcache_cloth_error; @@ -1232,8 +1228,6 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo pid->stack_index= sds->point_cache[0]->index; pid->cache= sds->point_cache[0]; - pid->cache_ptr= &(sds->point_cache[0]); - pid->ptcaches= &(sds->ptcaches[0]); pid->totpoint= pid->totwrite= ptcache_smoke_totpoint; pid->error = ptcache_smoke_error; @@ -1273,8 +1267,6 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSu pid->calldata= surface; pid->type= PTCACHE_TYPE_DYNAMICPAINT; pid->cache= surface->pointcache; - pid->cache_ptr= &surface->pointcache; - pid->ptcaches= &surface->ptcaches; pid->totpoint= pid->totwrite= ptcache_dynamicpaint_totpoint; pid->error = ptcache_dynamicpaint_error; @@ -1310,8 +1302,6 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r pid->calldata= rbw; pid->type= PTCACHE_TYPE_RIGIDBODY; pid->cache= rbw->pointcache; - pid->cache_ptr= &rbw->pointcache; - pid->ptcaches= &rbw->ptcaches; pid->totpoint= pid->totwrite= ptcache_rigidbody_totpoint; pid->error = ptcache_rigidbody_error; @@ -1437,14 +1427,16 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup #define MAX_PTCACHE_PATH FILE_MAX #define MAX_PTCACHE_FILE (FILE_MAX * 2) -static int ptcache_path(PTCacheID *pid, char *filename) +static int ptcache_path(PointCache *cache, Object *ob, char *filename) { - Library *lib = (pid->ob) ? pid->ob->id.lib : NULL; - const char *blendfilename= (lib && (pid->cache->flag & PTCACHE_IGNORE_LIBPATH)==0) ? lib->filepath: G.main->name; + bool is_external = cache && (cache->flag & PTC_EXTERNAL); + bool ignore_libpath = cache && (cache->flag & PTC_IGNORE_LIBPATH); + Library *lib = ob ? ob->id.lib : NULL; + const char *blendfilename= (lib && !ignore_libpath) ? lib->filepath: G.main->name; size_t i; - if (pid->cache->flag & PTCACHE_EXTERNAL) { - strcpy(filename, pid->cache->path); + if (cache && is_external) { + strcpy(filename, cache->path); if (BLI_path_is_rel(filename)) { BLI_path_abs(filename, blendfilename); @@ -1476,20 +1468,22 @@ static int ptcache_path(PTCacheID *pid, char *filename) static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_path, short do_ext) { + PointCache *cache = pid->cache; + bool is_external = (cache->flag & PTC_EXTERNAL); int len=0; char *idname; char *newname; filename[0] = '\0'; newname = filename; - if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return 0; /* save blend file before using disk pointcache */ + if (!G.relbase_valid && !is_external) return 0; /* save blend file before using disk pointcache */ /* start with temp dir */ if (do_path) { - len = ptcache_path(pid, filename); + len = ptcache_path(pid->cache, pid->ob, filename); newname += len; } - if (pid->cache->name[0] == '\0' && (pid->cache->flag & PTCACHE_EXTERNAL)==0) { + if (cache->name[0] == '\0' && !is_external) { idname = (pid->ob->id.name + 2); /* convert chars to hex so they are always a valid filename */ while ('\0' != *idname) { @@ -1499,19 +1493,19 @@ static int ptcache_filename(PTCacheID *pid, char *filename, int cfra, short do_p } } else { - int temp = (int)strlen(pid->cache->name); - strcpy(newname, pid->cache->name); + int temp = (int)strlen(cache->name); + strcpy(newname, cache->name); newname+=temp; len += temp; } if (do_ext) { - if (pid->cache->index < 0) - pid->cache->index = pid->stack_index = BKE_object_insert_ptcache(pid->ob); + if (cache->index < 0) + cache->index = pid->stack_index = BKE_object_insert_ptcache(pid->ob); - if (pid->cache->flag & PTCACHE_EXTERNAL) { - if (pid->cache->index >= 0) + if (is_external) { + if (cache->index >= 0) BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d_%02u"PTCACHE_EXT, cfra, pid->stack_index); /* always 6 chars */ else BLI_snprintf(newname, MAX_PTCACHE_FILE, "_%06d"PTCACHE_EXT, cfra); /* always 6 chars */ @@ -1537,7 +1531,7 @@ static PTCacheFile *ptcache_file_open(PTCacheID *pid, int mode, int cfra) if (pid->ob->id.lib && mode == PTCACHE_FILE_WRITE) return NULL; #endif - if (!G.relbase_valid && (pid->cache->flag & PTCACHE_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */ + if (!G.relbase_valid && (pid->cache->flag & PTC_EXTERNAL)==0) return NULL; /* save blend file before using disk pointcache */ ptcache_filename(pid, filename, cfra, 1, 1); @@ -1893,54 +1887,27 @@ static int ptcache_old_elemsize(PTCacheID *pid) static void ptcache_find_frames_around(PTCacheID *pid, unsigned int frame, int *fra1, int *fra2) { - if (pid->cache->flag & PTCACHE_DISK_CACHE) { - int cfra1=frame, cfra2=frame+1; - - while (cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1)) - cfra1--; - - if (cfra1 < pid->cache->startframe) - cfra1 = 0; - - while (cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2)) - cfra2++; - - if (cfra2 > pid->cache->endframe) - cfra2 = 0; - - if (cfra1 && !cfra2) { - *fra1 = 0; - *fra2 = cfra1; - } - else { - *fra1 = cfra1; - *fra2 = cfra2; - } + int cfra1=frame, cfra2=frame+1; + + while (cfra1 >= pid->cache->startframe && !BKE_ptcache_id_exist(pid, cfra1)) + cfra1--; + + if (cfra1 < pid->cache->startframe) + cfra1 = 0; + + while (cfra2 <= pid->cache->endframe && !BKE_ptcache_id_exist(pid, cfra2)) + cfra2++; + + if (cfra2 > pid->cache->endframe) + cfra2 = 0; + + if (cfra1 && !cfra2) { + *fra1 = 0; + *fra2 = cfra1; } - else if (pid->cache->mem_cache.first) { - PTCacheMem *pm = pid->cache->mem_cache.first; - PTCacheMem *pm2 = pid->cache->mem_cache.last; - - while (pm->next && pm->next->frame <= frame) - pm= pm->next; - - if (pm2->frame < frame) { - pm2 = NULL; - } - else { - while (pm2->prev && pm2->prev->frame > frame) { - pm2= pm2->prev; - } - } - - if (!pm2) { - *fra1 = 0; - *fra2 = pm->frame; - } - else { - *fra1 = pm->frame; - *fra2 = pm2->frame; - } + else { + *fra1 = cfra1; + *fra2 = cfra2; } } @@ -2162,15 +2129,7 @@ static int ptcache_read(PTCacheID *pid, int cfra) 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 { - pm = pid->cache->mem_cache.first; - - while (pm && pm->frame != cfra) - pm = pm->next; - } + pm = ptcache_disk_frame_to_mem(pid, cfra); /* read the cache */ if (pm) { @@ -2200,11 +2159,9 @@ static int ptcache_read(PTCacheID *pid, int cfra) 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); - } + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); } return 1; @@ -2216,15 +2173,7 @@ static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2) int *index = &i; /* get a memory cache to read from */ - if (pid->cache->flag & PTCACHE_DISK_CACHE) { - pm = ptcache_disk_frame_to_mem(pid, cfra2); - } - else { - pm = pid->cache->mem_cache.first; - - while (pm && pm->frame != cfra2) - pm = pm->next; - } + pm = ptcache_disk_frame_to_mem(pid, cfra2); /* read the cache */ if (pm) { @@ -2253,11 +2202,9 @@ static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2) 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); - } + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); } return 1; @@ -2266,6 +2213,7 @@ static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2) /* possible to get old or interpolated result */ int BKE_ptcache_read(PTCacheID *pid, float cfra) { + PointCache *cache = pid->cache; int cfrai = (int)floor(cfra), cfra1=0, cfra2=0; int ret = 0; @@ -2273,8 +2221,8 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra) if (pid->totpoint(pid->calldata, cfrai) == 0) return 0; - if (pid->cache->flag & PTCACHE_READ_INFO) { - pid->cache->flag &= ~PTCACHE_READ_INFO; + if (cache->state.flag & PTC_STATE_READ_INFO) { + cache->state.flag &= ~PTC_STATE_READ_INFO; ptcache_read(pid, 0); } @@ -2290,7 +2238,7 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra) return 0; /* don't read old cache if already simulated past cached frame */ - if (cfra1 == 0 && cfra2 && cfra2 <= pid->cache->simframe) + if (cfra1 == 0 && cfra2 && cfra2 <= cache->state.simframe) return 0; if (cfra1 && cfra1 == cfra2) return 0; @@ -2323,19 +2271,19 @@ int BKE_ptcache_read(PTCacheID *pid, float cfra) ret = (cfra2 ? PTCACHE_READ_INTERPOLATED : PTCACHE_READ_EXACT); else if (cfra2) { ret = PTCACHE_READ_OLD; - pid->cache->simframe = cfra2; + cache->state.simframe = cfra2; } cfrai = (int)cfra; /* clear invalid cache frames so that better stuff can be simulated */ - if (pid->cache->flag & PTCACHE_OUTDATED) { + if (cache->state.flag & PTC_STATE_OUTDATED) { BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfrai); } - else if (pid->cache->flag & PTCACHE_FRAMES_SKIPPED) { - if (cfra <= pid->cache->last_exact) - pid->cache->flag &= ~PTCACHE_FRAMES_SKIPPED; + else if (cache->state.flag & PTC_STATE_FRAMES_SKIPPED) { + if (cfra <= cache->state.last_exact) + cache->state.flag &= ~PTC_STATE_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, cache->state.last_exact)); } return ret; @@ -2389,16 +2337,12 @@ static int ptcache_write(PTCacheID *pid, int cfra, int overwrite) 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; + int fra = cfra-1; + + while (fra >= cache->startframe && !BKE_ptcache_id_exist(pid, fra)) + fra--; + + pm2 = ptcache_disk_frame_to_mem(pid, fra); } if (pid->write_point) { @@ -2419,25 +2363,20 @@ static int ptcache_write(PTCacheID *pid, int cfra, int overwrite) pm->frame = cfra; - if (cache->flag & PTCACHE_DISK_CACHE) { - error += !ptcache_mem_frame_to_disk(pid, pm); - - // if (pm) /* pm is always set */ - { - 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); - } + error += !ptcache_mem_frame_to_disk(pid, pm); + + // if (pm) /* pm is always set */ + { + ptcache_data_free(pm); + ptcache_extra_free(pm); + MEM_freeN(pm); } - else { - BLI_addtail(&cache->mem_cache, pm); + + if (pm2) { + error += !ptcache_mem_frame_to_disk(pid, pm2); + ptcache_data_free(pm2); + ptcache_extra_free(pm2); + MEM_freeN(pm2); } return error; @@ -2450,35 +2389,21 @@ static int ptcache_write_needed(PTCacheID *pid, int cfra, int *overwrite) /* allways start from scratch on the first frame */ if (cfra && cfra == cache->startframe) { BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, cfra); - cache->flag &= ~PTCACHE_REDO_NEEDED; + cache->state.flag &= ~PTC_STATE_REDO_NEEDED; return 1; } - if (pid->cache->flag & PTCACHE_DISK_CACHE) { - if (cfra==0 && cache->startframe > 0) - return 1; - - /* find last cached frame */ - while (efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra)) - efra--; - - /* find second last cached frame */ - ofra = efra-1; - while (ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra)) - ofra--; - } - else { - PTCacheMem *pm = cache->mem_cache.last; - /* don't write info file in memory */ - if (cfra == 0) - return 0; - - if (pm == NULL) - return 1; - - efra = pm->frame; - ofra = (pm->prev ? pm->prev->frame : efra - cache->step); - } + if (cfra==0 && cache->startframe > 0) + return 1; + + /* find last cached frame */ + while (efra > cache->startframe && !BKE_ptcache_id_exist(pid, efra)) + efra--; + + /* find second last cached frame */ + ofra = efra-1; + while (ofra > cache->startframe && !BKE_ptcache_id_exist(pid, ofra)) + ofra--; if (efra >= cache->startframe && cfra > efra) { if (ofra >= cache->startframe && efra - ofra < cache->step) { @@ -2512,17 +2437,17 @@ int BKE_ptcache_write(PTCacheID *pid, unsigned int cfra) } /* 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; + if (cfra - cache->state.last_exact == 1 || cfra == cache->startframe) { + cache->state.last_exact = cfra; + cache->state.flag &= ~PTC_STATE_FRAMES_SKIPPED; } /* Don't mark skipped when writing info file (frame 0) */ else if (cfra) - cache->flag |= PTCACHE_FRAMES_SKIPPED; + cache->state.flag |= PTC_STATE_FRAMES_SKIPPED; /* Update timeline cache display */ - if (cfra && cache->cached_frames) - cache->cached_frames[cfra-cache->startframe] = 1; + if (cfra && cache->state.cached_frames) + cache->state.cached_frames[cfra-cache->startframe] = 1; BKE_ptcache_update_info(pid); @@ -2546,10 +2471,10 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) char path_full[MAX_PTCACHE_FILE]; char ext[MAX_PTCACHE_PATH]; - if (!pid || !pid->cache || pid->cache->flag & PTCACHE_BAKED) + if (!pid || !pid->cache) return; - if (pid->cache->flag & PTCACHE_IGNORE_CLEAR) + if (pid->cache->flag & PTC_IGNORE_CLEAR) return; sta = pid->cache->startframe; @@ -2568,117 +2493,67 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) case PTCACHE_CLEAR_ALL: case PTCACHE_CLEAR_BEFORE: case PTCACHE_CLEAR_AFTER: - if (pid->cache->flag & PTCACHE_DISK_CACHE) { - ptcache_path(pid, path); - - dir = opendir(path); - if (dir==NULL) - return; - - len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */ - /* append underscore terminator to ensure we don't match similar names - * from objects whose names start with the same prefix - */ - if (len < sizeof(filename) - 2) { - BLI_strncpy(filename + len, "_", sizeof(filename) - 2 - len); - len += 1; - } - - BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index); + ptcache_path(pid->cache, pid->ob, path); + + dir = opendir(path); + if (dir==NULL) + return; - while ((de = readdir(dir)) != NULL) { - if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ - if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ - if (mode == PTCACHE_CLEAR_ALL) { - pid->cache->last_exact = MIN2(pid->cache->startframe, 0); - BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); - BLI_delete(path_full, false, false); - } - else { - /* read the number of the file */ - unsigned int frame, len2 = (int)strlen(de->d_name); - char num[7]; - - if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ - BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); - frame = atoi(num); + len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */ + /* append underscore terminator to ensure we don't match similar names + * from objects whose names start with the same prefix + */ + if (len < sizeof(filename) - 2) { + BLI_strncpy(filename + len, "_", sizeof(filename) - 2 - len); + len += 1; + } + + BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index); + + while ((de = readdir(dir)) != NULL) { + if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ + if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ + if (mode == PTCACHE_CLEAR_ALL) { + pid->cache->state.last_exact = MIN2(pid->cache->startframe, 0); + BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); + BLI_delete(path_full, false, false); + } + else { + /* read the number of the file */ + unsigned int frame, len2 = (int)strlen(de->d_name); + char num[7]; + + if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ + BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); + frame = atoi(num); + + if ((mode == PTCACHE_CLEAR_BEFORE && frame < cfra) || + (mode == PTCACHE_CLEAR_AFTER && frame > cfra)) + { - if ((mode == PTCACHE_CLEAR_BEFORE && frame < cfra) || - (mode == PTCACHE_CLEAR_AFTER && frame > cfra)) - { - - BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); - BLI_delete(path_full, false, false); - if (pid->cache->cached_frames && frame >=sta && frame <= end) - pid->cache->cached_frames[frame-sta] = 0; - } + BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); + BLI_delete(path_full, false, false); + if (pid->cache->state.cached_frames && frame >=sta && frame <= end) + pid->cache->state.cached_frames[frame-sta] = 0; } } } } } - 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; - PTCacheMem *link= NULL; - - 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) { - ptcache_data_free(pm); - ptcache_extra_free(pm); - } - BLI_freelistN(&pid->cache->mem_cache); - - 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) || - (mode == PTCACHE_CLEAR_AFTER && pm->frame > cfra)) - { - link = pm; - 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); - } - else - pm = pm->next; - } - } } + closedir(dir); + + if (mode == PTCACHE_CLEAR_ALL && pid->cache->state.cached_frames) + memset(pid->cache->state.cached_frames, 0, MEM_allocN_len(pid->cache->state.cached_frames)); break; case PTCACHE_CLEAR_FRAME: - if (pid->cache->flag & PTCACHE_DISK_CACHE) { - if (BKE_ptcache_id_exist(pid, cfra)) { - ptcache_filename(pid, filename, cfra, 1, 1); /* no path */ - BLI_delete(filename, false, false); - } - } - else { - PTCacheMem *pm = pid->cache->mem_cache.first; - - 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; - } - } + if (BKE_ptcache_id_exist(pid, cfra)) { + ptcache_filename(pid, filename, cfra, 1, 1); /* no path */ + BLI_delete(filename, false, false); } - if (pid->cache->cached_frames && cfra >= sta && cfra <= end) - pid->cache->cached_frames[cfra-sta] = 0; + if (pid->cache->state.cached_frames && cfra >= sta && cfra <= end) + pid->cache->state.cached_frames[cfra-sta] = 0; break; } @@ -2686,31 +2561,20 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) } int BKE_ptcache_id_exist(PTCacheID *pid, int cfra) { + char filename[MAX_PTCACHE_FILE]; + if (!pid->cache) return 0; - + if (cfra<pid->cache->startframe || cfra > pid->cache->endframe) return 0; - - if (pid->cache->cached_frames && pid->cache->cached_frames[cfra-pid->cache->startframe]==0) - return 0; - if (pid->cache->flag & PTCACHE_DISK_CACHE) { - char filename[MAX_PTCACHE_FILE]; - - ptcache_filename(pid, filename, cfra, 1, 1); - - return BLI_exists(filename); - } - else { - PTCacheMem *pm = pid->cache->mem_cache.first; - - for (; pm; pm=pm->next) { - if (pm->frame==cfra) - return 1; - } + if (pid->cache->state.cached_frames && pid->cache->state.cached_frames[cfra-pid->cache->startframe]==0) return 0; - } + + ptcache_filename(pid, filename, cfra, 1, 1); + + return BLI_exists(filename); } void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startframe, int *endframe, float *timescale) { @@ -2760,66 +2624,54 @@ void BKE_ptcache_id_time(PTCacheID *pid, Scene *scene, float cfra, int *startfra } /* verify cached_frames array is up to date */ - if (cache->cached_frames) { - if (MEM_allocN_len(cache->cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) { - MEM_freeN(cache->cached_frames); - cache->cached_frames = NULL; + if (cache->state.cached_frames) { + if (MEM_allocN_len(cache->state.cached_frames) != sizeof(char) * (cache->endframe-cache->startframe+1)) { + MEM_freeN(cache->state.cached_frames); + cache->state.cached_frames = NULL; } } - if (cache->cached_frames==NULL && cache->endframe > cache->startframe) { + if (cache->state.cached_frames==NULL && cache->endframe > cache->startframe) { unsigned int sta=cache->startframe; unsigned int end=cache->endframe; - - cache->cached_frames = MEM_callocN(sizeof(char) * (cache->endframe-cache->startframe+1), "cached frames array"); - - if (pid->cache->flag & PTCACHE_DISK_CACHE) { - /* mode is same as fopen's modes */ - DIR *dir; - struct dirent *de; - char path[MAX_PTCACHE_PATH]; - char filename[MAX_PTCACHE_FILE]; - char ext[MAX_PTCACHE_PATH]; - unsigned int len; /* store the length of the string */ - - ptcache_path(pid, path); - - len = ptcache_filename(pid, filename, (int)cfra, 0, 0); /* no path */ - - dir = opendir(path); - if (dir==NULL) - return; - - BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index); - - while ((de = readdir(dir)) != NULL) { - if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ - if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ - /* read the number of the file */ - unsigned int frame, len2 = (int)strlen(de->d_name); - char num[7]; - - if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ - BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); - frame = atoi(num); - - if (frame >= sta && frame <= end) - cache->cached_frames[frame-sta] = 1; - } + /* mode is same as fopen's modes */ + DIR *dir; + struct dirent *de; + char path[MAX_PTCACHE_PATH]; + char filename[MAX_PTCACHE_FILE]; + char ext[MAX_PTCACHE_PATH]; + unsigned int len; /* store the length of the string */ + + cache->state.cached_frames = MEM_callocN(sizeof(char) * (cache->endframe-cache->startframe+1), "cached frames array"); + + ptcache_path(pid->cache, pid->ob, path); + + len = ptcache_filename(pid, filename, (int)cfra, 0, 0); /* no path */ + + dir = opendir(path); + if (dir==NULL) + return; + + BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index); + + while ((de = readdir(dir)) != NULL) { + if (strstr(de->d_name, ext)) { /* do we have the right extension?*/ + if (strncmp(filename, de->d_name, len ) == 0) { /* do we have the right prefix */ + /* read the number of the file */ + unsigned int frame, len2 = (int)strlen(de->d_name); + char num[7]; + + if (len2 > 15) { /* could crash if trying to copy a string out of this range*/ + BLI_strncpy(num, de->d_name + (strlen(de->d_name) - 15), sizeof(num)); + frame = atoi(num); + + if (frame >= sta && frame <= end) + cache->state.cached_frames[frame-sta] = 1; } } } - closedir(dir); - } - else { - PTCacheMem *pm= pid->cache->mem_cache.first; - - while (pm) { - if (pm->frame >= sta && pm->frame <= end) - cache->cached_frames[pm->frame-sta] = 1; - pm = pm->next; - } } + closedir(dir); } } int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) @@ -2836,44 +2688,27 @@ int BKE_ptcache_id_reset(Scene *scene, PTCacheID *pid, int mode) after= 0; if (mode == PTCACHE_RESET_DEPSGRAPH) { - if (!(cache->flag & PTCACHE_BAKED)) { + after= 1; - after= 1; - } - - cache->flag |= PTCACHE_OUTDATED; + cache->state.flag |= PTC_STATE_OUTDATED; } else if (mode == PTCACHE_RESET_BAKED) { - cache->flag |= PTCACHE_OUTDATED; + cache->state.flag |= PTC_STATE_OUTDATED; } else if (mode == PTCACHE_RESET_OUTDATED) { reset = 1; - if (cache->flag & PTCACHE_OUTDATED && !(cache->flag & PTCACHE_BAKED)) { + if (cache->state.flag & PTC_STATE_OUTDATED) { clear= 1; - cache->flag &= ~PTCACHE_OUTDATED; + cache->state.flag &= ~PTC_STATE_OUTDATED; } } if (reset) { BKE_ptcache_invalidate(cache); - cache->flag &= ~PTCACHE_REDO_NEEDED; - - if (pid->type == PTCACHE_TYPE_CLOTH) - cloth_free_modifier(pid->calldata); - else if (pid->type == PTCACHE_TYPE_SOFTBODY) - sbFreeSimulation(pid->calldata); - else if (pid->type == PTCACHE_TYPE_PARTICLES) - psys_reset(pid->calldata, PSYS_RESET_DEPSGRAPH); -#if 0 - else if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) - smokeModifier_reset(pid->calldata); - else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) - smokeModifier_reset_turbulence(pid->calldata); -#endif - else if (pid->type == PTCACHE_TYPE_DYNAMICPAINT) - dynamicPaint_clearSurface(scene, (DynamicPaintSurface*)pid->calldata); + cache->state.flag &= ~PTC_STATE_REDO_NEEDED; } + if (clear) BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); else if (after) @@ -2892,6 +2727,9 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) skip= 0; if (ob->soft) { + if (mode & PTCACHE_RESET_OUTDATED) + sbFreeSimulation(ob->soft); + BKE_ptcache_id_from_softbody(&pid, ob, ob->soft); reset |= BKE_ptcache_id_reset(scene, &pid, mode); } @@ -2903,14 +2741,21 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) /* Baked cloth hair has to be checked too, because we don't want to reset */ /* particles or cloth in that case -jahka */ else if (psys->clmd) { - BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd); - if (mode == PSYS_RESET_ALL || !(psys->part->type == PART_HAIR && (pid.cache->flag & PTCACHE_BAKED))) + if (mode == PSYS_RESET_ALL || psys->part->type != PART_HAIR) { + if (mode & PTCACHE_RESET_OUTDATED) + cloth_free_modifier(psys->clmd); + + BKE_ptcache_id_from_cloth(&pid, ob, psys->clmd); reset |= BKE_ptcache_id_reset(scene, &pid, mode); + } else skip = 1; } if (skip == 0 && psys->part) { + if (mode & PTCACHE_RESET_OUTDATED) + psys_reset(psys, PSYS_RESET_DEPSGRAPH); + BKE_ptcache_id_from_particles(&pid, ob, psys); reset |= BKE_ptcache_id_reset(scene, &pid, mode); } @@ -2918,7 +2763,11 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) for (md=ob->modifiers.first; md; md=md->next) { if (md->type == eModifierType_Cloth) { - BKE_ptcache_id_from_cloth(&pid, ob, (ClothModifierData*)md); + ClothModifierData *clmd = (ClothModifierData*)md; + if (mode & PTCACHE_RESET_OUTDATED) + cloth_free_modifier(clmd); + + BKE_ptcache_id_from_cloth(&pid, ob, clmd); reset |= BKE_ptcache_id_reset(scene, &pid, mode); } if (md->type == eModifierType_Smoke) { @@ -2932,8 +2781,10 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; if (pmd->canvas) { DynamicPaintSurface *surface = pmd->canvas->surfaces.first; - for (; surface; surface=surface->next) { + if (mode & PTCACHE_RESET_OUTDATED) + dynamicPaint_clearSurface(scene, surface); + BKE_ptcache_id_from_dynamicpaint(&pid, ob, surface); reset |= BKE_ptcache_id_reset(scene, &pid, mode); } @@ -2944,9 +2795,10 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) if (scene->rigidbody_world && (ob->rigidbody_object || ob->rigidbody_constraint)) { if (ob->rigidbody_object) ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_RESHAPE; + BKE_ptcache_id_from_rigidbody(&pid, ob, scene->rigidbody_world); /* only flag as outdated, resetting should happen on start frame */ - pid.cache->flag |= PTCACHE_OUTDATED; + pid.cache->state.flag |= PTC_STATE_OUTDATED; } if (ob->type == OB_ARMATURE) @@ -2962,7 +2814,7 @@ void BKE_ptcache_remove(void) char path_full[MAX_PTCACHE_PATH]; int rmdir = 1; - ptcache_path(NULL, path); + ptcache_path(NULL, NULL, path); if (BLI_exists(path)) { /* The pointcache dir exists? - remove all pointcache */ @@ -3000,7 +2852,7 @@ void BKE_ptcache_remove(void) /* Point Cache handling */ -PointCache *BKE_ptcache_add(ListBase *ptcaches) +PointCache *BKE_ptcache_new(void) { PointCache *cache; @@ -3010,8 +2862,6 @@ PointCache *BKE_ptcache_add(ListBase *ptcaches) cache->step = 1; cache->index = -1; - BLI_addtail(ptcaches, cache); - return cache; } @@ -3030,56 +2880,29 @@ void BKE_ptcache_free_mem(ListBase *mem_cache) } void BKE_ptcache_free(PointCache *cache) { - BKE_ptcache_free_mem(&cache->mem_cache); if (cache->edit && cache->free_edit) cache->free_edit(cache->edit); - if (cache->cached_frames) - MEM_freeN(cache->cached_frames); - MEM_freeN(cache); -} -void BKE_ptcache_free_list(ListBase *ptcaches) -{ - PointCache *cache; + if (cache->state.cached_frames) + MEM_freeN(cache->state.cached_frames); - while ((cache = BLI_pophead(ptcaches))) { - BKE_ptcache_free(cache); - } + MEM_freeN(cache); } -static PointCache *ptcache_copy(PointCache *cache, bool copy_data) +PointCache *BKE_ptcache_copy(PointCache *cache, bool copy_data) { PointCache *ncache; ncache= MEM_dupallocN(cache); - BLI_listbase_clear(&ncache->mem_cache); - if (copy_data == false) { - ncache->cached_frames = NULL; + ncache->state.cached_frames = NULL; - /* flag is a mix of user settings and simulator/baking state */ - ncache->flag= ncache->flag & (PTCACHE_DISK_CACHE|PTCACHE_EXTERNAL|PTCACHE_IGNORE_LIBPATH); - ncache->simframe= 0; + ncache->flag= ncache->flag & (PTC_EXTERNAL|PTC_IGNORE_LIBPATH); + ncache->state.simframe= 0; } else { - PTCacheMem *pm; - - for (pm = cache->mem_cache.first; pm; pm = pm->next) { - PTCacheMem *pmn = MEM_dupallocN(pm); - int i; - - for (i = 0; i < BPHYS_TOT_DATA; i++) { - if (pmn->data[i]) - pmn->data[i] = MEM_dupallocN(pm->data[i]); - } - - BKE_ptcache_mem_pointers_init(pm); - - BLI_addtail(&ncache->mem_cache, pmn); - } - - if (ncache->cached_frames) - ncache->cached_frames = MEM_dupallocN(cache->cached_frames); + if (ncache->state.cached_frames) + ncache->state.cached_frames = MEM_dupallocN(cache->state.cached_frames); } /* hmm, should these be copied over instead? */ @@ -3088,412 +2911,33 @@ static PointCache *ptcache_copy(PointCache *cache, bool copy_data) return ncache; } -/* returns first point cache */ -PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, ListBase *ptcaches_old, bool copy_data) -{ - PointCache *cache = ptcaches_old->first; - - BLI_listbase_clear(ptcaches_new); - - for (; cache; cache=cache->next) - BLI_addtail(ptcaches_new, ptcache_copy(cache, copy_data)); - - return ptcaches_new->first; -} - -/* Disabled this code; this is being called on scene_update_tagged, and that in turn gets called on - * every user action changing stuff, and then it runs a complete bake??? (ton) */ - -/* Baking */ -void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene) -{ - PTCacheBaker baker; - - baker.bake=0; - baker.break_data=NULL; - baker.break_test=NULL; - baker.pid=NULL; - baker.progressbar=NULL; - baker.progressend=NULL; - baker.progresscontext=NULL; - baker.render=0; - baker.anim_init = 0; - baker.main=bmain; - baker.scene=scene; - baker.quick_step=scene->physics_settings.quick_cache_step; - - BKE_ptcache_bake(&baker); -} - -/* Simulation thread, no need for interlocks as data written in both threads - * are only unitary integers (I/O assumed to be atomic for them) */ -typedef struct { - int break_operation; - int thread_ended; - int endframe; - int step; - int *cfra_ptr; - Main *main; - Scene *scene; -} ptcache_bake_data; - -static void ptcache_dt_to_str(char *str, double dtime) -{ - if (dtime > 60.0) { - if (dtime > 3600.0) - sprintf(str, "%ih %im %is", (int)(dtime/3600), ((int)(dtime/60))%60, ((int)dtime) % 60); - else - sprintf(str, "%im %is", ((int)(dtime/60))%60, ((int)dtime) % 60); - } - else - sprintf(str, "%is", ((int)dtime) % 60); -} - -static void *ptcache_bake_thread(void *ptr) -{ - bool use_timer = false; - int sfra, efra; - double stime, ptime, ctime, fetd; - char run[32], cur[32], etd[32]; - - ptcache_bake_data *data = (ptcache_bake_data*)ptr; - - stime = ptime = PIL_check_seconds_timer(); - sfra = *data->cfra_ptr; - efra = data->endframe; - - for (; (*data->cfra_ptr <= data->endframe) && !data->break_operation; *data->cfra_ptr+=data->step) { - BKE_scene_update_for_newframe(G.main->eval_ctx, data->main, data->scene, data->scene->lay); - if (G.background) { - printf("bake: frame %d :: %d\n", (int)*data->cfra_ptr, data->endframe); - } - else { - ctime = PIL_check_seconds_timer(); - - fetd = (ctime-ptime)*(efra-*data->cfra_ptr)/data->step; - - if (use_timer || fetd > 60.0) { - use_timer = true; - - ptcache_dt_to_str(cur, ctime-ptime); - ptcache_dt_to_str(run, ctime-stime); - ptcache_dt_to_str(etd, fetd); - - printf("Baked for %s, current frame: %i/%i (%.3fs), ETC: %s\r", run, *data->cfra_ptr-sfra+1, efra-sfra+1, ctime-ptime, etd); - } - ptime = ctime; - } - } - - if (use_timer) { - /* start with newline because of \r above */ - ptcache_dt_to_str(run, PIL_check_seconds_timer()-stime); - printf("\nBake %s %s (%i frames simulated).\n", (data->break_operation ? "canceled after" : "finished in"), run, *data->cfra_ptr-sfra); - } - - data->thread_ended = true; - return NULL; -} - -/* if bake is not given run simulations to current frame */ -void BKE_ptcache_bake(PTCacheBaker *baker) -{ - Main *bmain = baker->main; - Scene *scene = baker->scene; - Scene *sce_iter; /* SETLOOPER macro only */ - Base *base; - ListBase pidlist; - PTCacheID *pid = baker->pid; - PointCache *cache = NULL; - float frameleno = scene->r.framelen; - int cfrao = CFRA; - int startframe = MAXFRAME; - int bake = baker->bake; - int render = baker->render; - ListBase threads; - ptcache_bake_data thread_data; - int progress, old_progress; - - thread_data.endframe = baker->anim_init ? scene->r.sfra : CFRA; - thread_data.step = baker->quick_step; - thread_data.cfra_ptr = &CFRA; - thread_data.scene = baker->scene; - thread_data.main = baker->main; - - G.is_break = false; - - /* set caches to baking mode and figure out start frame */ - if (pid) { - /* cache/bake a single object */ - cache = pid->cache; - if ((cache->flag & PTCACHE_BAKED)==0) { - if (pid->type==PTCACHE_TYPE_PARTICLES) { - ParticleSystem *psys= pid->calldata; - - /* a bit confusing, could make this work better in the UI */ - if (psys->part->type == PART_EMITTER) - psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe); - } - else if (pid->type == PTCACHE_TYPE_SMOKE_HIGHRES) { - /* get all pids from the object and search for smoke low res */ - ListBase pidlist2; - PTCacheID *pid2; - BKE_ptcache_ids_from_object(&pidlist2, pid->ob, scene, MAX_DUPLI_RECUR); - for (pid2=pidlist2.first; pid2; pid2=pid2->next) { - if (pid2->type == PTCACHE_TYPE_SMOKE_DOMAIN) { - if (pid2->cache && !(pid2->cache->flag & PTCACHE_BAKED)) { - if (bake || pid2->cache->flag & PTCACHE_REDO_NEEDED) - BKE_ptcache_id_clear(pid2, PTCACHE_CLEAR_ALL, 0); - if (bake) { - pid2->cache->flag |= PTCACHE_BAKING; - pid2->cache->flag &= ~PTCACHE_BAKED; - } - } - } - } - BLI_freelistN(&pidlist2); - } - - if (bake || cache->flag & PTCACHE_REDO_NEEDED) - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - - startframe = MAX2(cache->last_exact, cache->startframe); - - if (bake) { - thread_data.endframe = cache->endframe; - cache->flag |= PTCACHE_BAKING; - } - else { - thread_data.endframe = MIN2(thread_data.endframe, cache->endframe); - } - - cache->flag &= ~PTCACHE_BAKED; - } - } - else { - for (SETLOOPER(scene, sce_iter, base)) { - /* cache/bake everything in the scene */ - BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR); - - for (pid=pidlist.first; pid; pid=pid->next) { - cache = pid->cache; - if ((cache->flag & PTCACHE_BAKED)==0) { - if (pid->type==PTCACHE_TYPE_PARTICLES) { - ParticleSystem *psys = (ParticleSystem*)pid->calldata; - /* skip hair & keyed particles */ - if (psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED) - continue; - - psys_get_pointcache_start_end(scene, pid->calldata, &cache->startframe, &cache->endframe); - } - - if ((cache->flag & PTCACHE_REDO_NEEDED || (cache->flag & PTCACHE_SIMULATION_VALID)==0) && - (render || bake)) - { - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - } - - startframe = MIN2(startframe, cache->startframe); - - if (bake || render) { - cache->flag |= PTCACHE_BAKING; - - if (bake) - thread_data.endframe = MAX2(thread_data.endframe, cache->endframe); - } - - cache->flag &= ~PTCACHE_BAKED; - - } - } - BLI_freelistN(&pidlist); - } - } - - CFRA = startframe; - scene->r.framelen = 1.0; - thread_data.break_operation = false; - thread_data.thread_ended = false; - old_progress = -1; - - WM_cursor_wait(1); - - if (G.background) { - ptcache_bake_thread((void*)&thread_data); - } - else { - BLI_init_threads(&threads, ptcache_bake_thread, 1); - BLI_insert_thread(&threads, (void*)&thread_data); - - while (thread_data.thread_ended == false) { - - if (bake) - progress = (int)(100.0f * (float)(CFRA - startframe)/(float)(thread_data.endframe-startframe)); - else - progress = CFRA; - - /* NOTE: baking should not redraw whole ui as this slows things down */ - if ((baker->progressbar) && (progress != old_progress)) { - baker->progressbar(baker->progresscontext, progress); - old_progress = progress; - } - - /* Delay to lessen CPU load from UI thread */ - PIL_sleep_ms(200); - - /* NOTE: breaking baking should leave calculated frames in cache, not clear it */ - if (blender_test_break() && !thread_data.break_operation) { - thread_data.break_operation = true; - if (baker->progressend) - baker->progressend(baker->progresscontext); - WM_cursor_wait(1); - } - } - - BLI_end_threads(&threads); - } - /* clear baking flag */ - if (pid) { - cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED); - cache->flag |= PTCACHE_SIMULATION_VALID; - if (bake) { - cache->flag |= PTCACHE_BAKED; - /* write info file */ - if (cache->flag & PTCACHE_DISK_CACHE) - BKE_ptcache_write(pid, 0); - } - } - else { - for (SETLOOPER(scene, sce_iter, base)) { - BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR); - - for (pid=pidlist.first; pid; pid=pid->next) { - /* skip hair particles */ - if (pid->type==PTCACHE_TYPE_PARTICLES && ((ParticleSystem*)pid->calldata)->part->type == PART_HAIR) - continue; - - cache = pid->cache; - - if (thread_data.step > 1) - cache->flag &= ~(PTCACHE_BAKING|PTCACHE_OUTDATED); - else - cache->flag &= ~(PTCACHE_BAKING|PTCACHE_REDO_NEEDED); - - cache->flag |= PTCACHE_SIMULATION_VALID; - - if (bake) { - cache->flag |= PTCACHE_BAKED; - if (cache->flag & PTCACHE_DISK_CACHE) - BKE_ptcache_write(pid, 0); - } - } - BLI_freelistN(&pidlist); - } - } - - scene->r.framelen = frameleno; - CFRA = cfrao; - - if (bake) { /* already on cfra unless baking */ - BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay); - } - - if (thread_data.break_operation) - WM_cursor_wait(0); - else if (baker->progressend) - baker->progressend(baker->progresscontext); - - WM_cursor_wait(0); - - /* TODO: call redraw all windows somehow */ -} /* Helpers */ -void BKE_ptcache_disk_to_mem(PTCacheID *pid) +void BKE_ptcache_to_mem(PTCacheID *pid, ListBase *mem_cache) { PointCache *cache = pid->cache; PTCacheMem *pm = NULL; - int baked = cache->flag & PTCACHE_BAKED; int cfra, sfra = cache->startframe, efra = cache->endframe; - /* Remove possible bake flag to allow clear */ - cache->flag &= ~PTCACHE_BAKED; - /* PTCACHE_DISK_CACHE flag was cleared already */ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - /* restore possible bake flag */ - cache->flag |= baked; - for (cfra=sfra; cfra <= efra; cfra++) { pm = ptcache_disk_frame_to_mem(pid, cfra); if (pm) - BLI_addtail(&pid->cache->mem_cache, pm); + BLI_addtail(mem_cache, pm); } } -void BKE_ptcache_mem_to_disk(PTCacheID *pid) +void BKE_ptcache_from_mem(PTCacheID *pid, ListBase *mem_cache) { - PointCache *cache = pid->cache; - PTCacheMem *pm = cache->mem_cache.first; - int baked = cache->flag & PTCACHE_BAKED; - - /* Remove possible bake flag to allow clear */ - cache->flag &= ~PTCACHE_BAKED; + PTCacheMem *pm = mem_cache->first; /* PTCACHE_DISK_CACHE flag was set already */ BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - /* restore possible bake flag */ - cache->flag |= baked; - for (; pm; pm=pm->next) { - if (ptcache_mem_frame_to_disk(pid, pm)==0) { - cache->flag &= ~PTCACHE_DISK_CACHE; + if (ptcache_mem_frame_to_disk(pid, pm)==0) break; - } - } - - /* write info file */ - if (cache->flag & PTCACHE_BAKED) - BKE_ptcache_write(pid, 0); -} -void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) -{ - PointCache *cache = pid->cache; - int last_exact = cache->last_exact; - - if (!G.relbase_valid) { - cache->flag &= ~PTCACHE_DISK_CACHE; - if (G.debug & G_DEBUG) - printf("File must be saved before using disk cache!\n"); - 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 - BKE_ptcache_disk_to_mem(pid); - - cache->flag ^= PTCACHE_DISK_CACHE; - BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_ALL, 0); - cache->flag ^= PTCACHE_DISK_CACHE; - - cache->last_exact = last_exact; - - BKE_ptcache_id_time(pid, NULL, 0.0f, NULL, NULL, NULL); - - BKE_ptcache_update_info(pid); - - if ((cache->flag & PTCACHE_DISK_CACHE) == 0) { - if (cache->index) { - BKE_object_delete_ptcache(pid->ob, cache->index); - cache->index = -1; - } } } @@ -3518,7 +2962,7 @@ void BKE_ptcache_disk_cache_rename(PTCacheID *pid, const char *name_src, const c len = ptcache_filename(pid, old_filename, 0, 0, 0); /* no path */ - ptcache_path(pid, path); + ptcache_path(pid->cache, pid->ob, path); dir = opendir(path); if (dir==NULL) { BLI_strncpy(pid->cache->name, old_name, sizeof(pid->cache->name)); @@ -3572,7 +3016,7 @@ void BKE_ptcache_load_external(PTCacheID *pid) if (!cache) return; - ptcache_path(pid, path); + ptcache_path(pid->cache, pid->ob, path); len = ptcache_filename(pid, filename, 1, 0, 0); /* no path */ @@ -3613,7 +3057,7 @@ void BKE_ptcache_load_external(PTCacheID *pid) cache->startframe = start; cache->endframe = end; - cache->totpoint = 0; + cache->state.totpoint = 0; if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) { /* necessary info in every file */ @@ -3625,11 +3069,11 @@ void BKE_ptcache_load_external(PTCacheID *pid) if (pf) { if (ptcache_file_header_begin_read(pf)) { if (pf->type == pid->type && pid->read_header(pf)) { - cache->totpoint = pf->totpoint; - cache->flag |= PTCACHE_READ_INFO; + cache->state.totpoint = pf->totpoint; + cache->state.flag |= PTC_STATE_READ_INFO; } else { - cache->totpoint = 0; + cache->state.totpoint = 0; } } ptcache_file_close(pf); @@ -3643,19 +3087,18 @@ void BKE_ptcache_load_external(PTCacheID *pid) if (pf) { while (ptcache_file_read(pf, old_data, 1, elemsize)) - cache->totpoint++; + cache->state.totpoint++; ptcache_file_close(pf); } } - cache->flag |= (PTCACHE_BAKED|PTCACHE_DISK_CACHE|PTCACHE_SIMULATION_VALID); - cache->flag &= ~(PTCACHE_OUTDATED|PTCACHE_FRAMES_SKIPPED); + cache->state.flag &= ~(PTC_STATE_OUTDATED|PTC_STATE_FRAMES_SKIPPED); } /* make sure all new frames are loaded */ - if (cache->cached_frames) { - MEM_freeN(cache->cached_frames); - cache->cached_frames=NULL; + if (cache->state.cached_frames) { + MEM_freeN(cache->state.cached_frames); + cache->state.cached_frames=NULL; } BKE_ptcache_update_info(pid); } @@ -3663,11 +3106,10 @@ 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]; - if (cache->flag & PTCACHE_EXTERNAL) { + if (cache->flag & PTC_EXTERNAL) { int cfra = cache->startframe; for (; cfra <= cache->endframe; cfra++) { @@ -3677,85 +3119,55 @@ void BKE_ptcache_update_info(PTCacheID *pid) /* smoke doesn't use frame 0 as info frame so can't check based on totpoint */ if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN && totframes) - BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%i frames found!"), totframes); - else if (totframes && cache->totpoint) - BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%i points found!"), cache->totpoint); + BLI_snprintf(cache->state.info, sizeof(cache->state.info), IFACE_("%i frames found!"), totframes); + else if (totframes && cache->state.totpoint) + BLI_snprintf(cache->state.info, sizeof(cache->state.info), IFACE_("%i points found!"), cache->state.totpoint); else - BLI_strncpy(cache->info, IFACE_("No valid data to read!"), sizeof(cache->info)); + BLI_strncpy(cache->state.info, IFACE_("No valid data to read!"), sizeof(cache->state.info)); return; } - if (cache->flag & PTCACHE_DISK_CACHE) { - if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) { - int totpoint = pid->totpoint(pid->calldata, 0); - - if (cache->totpoint > totpoint) - BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i cells + High Resolution cached"), totpoint); - else - BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i cells cached"), totpoint); - } - else { - int cfra = cache->startframe; - - for (; cfra <= cache->endframe; cfra++) { - if (BKE_ptcache_id_exist(pid, cfra)) - totframes++; - } - - BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames on disk"), totframes); - } + if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) { + int totpoint = pid->totpoint(pid->calldata, 0); + + if (cache->state.totpoint > totpoint) + BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i cells + High Resolution cached"), totpoint); + else + BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i cells cached"), totpoint); } else { - PTCacheMem *pm = cache->mem_cache.first; - float bytes = 0.0f; - int i, mb; + int cfra = cache->startframe; - for (; pm; pm=pm->next) { - for (i=0; i<BPHYS_TOT_DATA; i++) - 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 += sizeof(PTCacheMem); - - totframes++; + for (; cfra <= cache->endframe; cfra++) { + if (BKE_ptcache_id_exist(pid, cfra)) + totframes++; } - - mb = (bytes > 1024.0f * 1024.0f); - - BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames in memory (%.1f %s)"), - totframes, - bytes / (mb ? 1024.0f * 1024.0f : 1024.0f), - mb ? IFACE_("Mb") : IFACE_("kb")); + + BLI_snprintf(mem_info, sizeof(mem_info), IFACE_("%i frames on disk"), totframes); } - if (cache->flag & PTCACHE_OUTDATED) { - BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%s, cache is outdated!"), mem_info); + if (cache->state.flag & PTC_STATE_OUTDATED) { + BLI_snprintf(cache->state.info, sizeof(cache->state.info), IFACE_("%s, cache is outdated!"), mem_info); } - else if (cache->flag & PTCACHE_FRAMES_SKIPPED) { - BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%s, not exact since frame %i"), - mem_info, cache->last_exact); + else if (cache->state.flag & PTC_STATE_FRAMES_SKIPPED) { + BLI_snprintf(cache->state.info, sizeof(cache->state.info), IFACE_("%s, not exact since frame %i"), + mem_info, cache->state.last_exact); } else { - BLI_snprintf(cache->info, sizeof(cache->info), "%s.", mem_info); + BLI_snprintf(cache->state.info, sizeof(cache->state.info), "%s.", mem_info); } } void BKE_ptcache_validate(PointCache *cache, int framenr) { if (cache) { - cache->flag |= PTCACHE_SIMULATION_VALID; - cache->simframe = framenr; + cache->state.simframe = framenr; } } void BKE_ptcache_invalidate(PointCache *cache) { if (cache) { - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe = 0; - cache->last_exact = MIN2(cache->startframe, 0); + cache->state.simframe = 0; + cache->state.last_exact = MIN2(cache->startframe, 0); } } diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 3bf5c4cc47e..4bd3b6bd8dd 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -106,7 +106,7 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw) free(rbw->objects); /* free cache */ - BKE_ptcache_free_list(&(rbw->ptcaches)); + BKE_ptcache_free(rbw->pointcache); rbw->pointcache = NULL; /* free effector weights */ @@ -917,7 +917,7 @@ RigidBodyWorld *BKE_rigidbody_create_world(Scene *scene) rbw->steps_per_second = 60; /* Bullet default (60 Hz) */ rbw->num_solver_iterations = 10; /* 10 is bullet default */ - rbw->pointcache = BKE_ptcache_add(&(rbw->ptcaches)); + rbw->pointcache = BKE_ptcache_new(); rbw->pointcache->step = 1; /* return this sim world */ @@ -935,7 +935,7 @@ RigidBodyWorld *BKE_rigidbody_world_copy(RigidBodyWorld *rbw) if (rbwn->constraints) id_us_plus(&rbwn->constraints->id); - rbwn->pointcache = BKE_ptcache_copy_list(&rbwn->ptcaches, &rbw->ptcaches, false); + rbwn->pointcache = BKE_ptcache_copy(rbw->pointcache, false); rbwn->objects = NULL; rbwn->physics_world = NULL; @@ -1478,7 +1478,7 @@ void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], flo void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) { if (rbw) - rbw->pointcache->flag |= PTCACHE_OUTDATED; + rbw->pointcache->state.flag |= PTC_STATE_OUTDATED; } /* ------------------ */ @@ -1498,16 +1498,17 @@ void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) /* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */ if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&rbw->group->gobject)) { - cache->flag |= PTCACHE_OUTDATED; + cache->state.flag |= PTC_STATE_OUTDATED; } if (ctime == startframe + 1 && rbw->ltime == startframe) { - if (cache->flag & PTCACHE_OUTDATED) { - BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + if (cache->state.flag & PTC_STATE_OUTDATED) { rigidbody_update_simulation(scene, rbw, true); + + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); BKE_ptcache_validate(cache, (int)ctime); - cache->last_exact = 0; - cache->flag &= ~PTCACHE_REDO_NEEDED; + cache->state.last_exact = 0; + cache->state.flag &= ~PTC_STATE_REDO_NEEDED; } } } @@ -1535,7 +1536,7 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) } /* don't try to run the simulation if we don't have a world yet but allow reading baked cache */ - if (rbw->physics_world == NULL && !(cache->flag & PTCACHE_BAKED)) + if (rbw->physics_world == NULL) return; else if (rbw->objects == NULL) rigidbody_update_ob_array(rbw); @@ -1549,9 +1550,9 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) } /* advance simulation, we can only step one frame forward */ - if (ctime == rbw->ltime + 1 && !(cache->flag & PTCACHE_BAKED)) { + if (ctime == rbw->ltime + 1) { /* write cache for first frame when on second frame */ - if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) { + if (rbw->ltime == startframe && (cache->state.flag & PTC_STATE_OUTDATED || cache->state.last_exact == 0)) { BKE_ptcache_write(&pid, startframe); } diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 4c46875bd48..a996da5915e 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -55,8 +55,10 @@ #include "DNA_lamp_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" +#include "DNA_object_force.h" #include "DNA_object_types.h" #include "DNA_particle_types.h" +#include "DNA_pointcache_types.h" #include "DNA_scene_types.h" #include "DNA_smoke_types.h" @@ -392,7 +394,7 @@ static void smokeModifier_freeDomain(SmokeModifierData *smd) MEM_freeN(smd->domain->effector_weights); smd->domain->effector_weights = NULL; - BKE_ptcache_free_list(&(smd->domain->ptcaches[0])); + BKE_ptcache_free(smd->domain->point_cache[0]); smd->domain->point_cache[0] = NULL; MEM_freeN(smd->domain); @@ -519,13 +521,11 @@ void smokeModifier_createType(struct SmokeModifierData *smd) smd->domain->smd = smd; - smd->domain->point_cache[0] = BKE_ptcache_add(&(smd->domain->ptcaches[0])); - smd->domain->point_cache[0]->flag |= PTCACHE_DISK_CACHE; + smd->domain->point_cache[0] = BKE_ptcache_new(); smd->domain->point_cache[0]->step = 1; /* Deprecated */ smd->domain->point_cache[1] = NULL; - BLI_listbase_clear(&smd->domain->ptcaches[1]); /* set some standard values */ smd->domain->fluid = NULL; smd->domain->fluid_mutex = BLI_rw_mutex_alloc(); @@ -938,9 +938,9 @@ static void object_cacheIgnoreClear(Object *ob, bool state) for (pid = pidlist.first; pid; pid = pid->next) { if (pid->cache) { if (state) - pid->cache->flag |= PTCACHE_IGNORE_CLEAR; + pid->cache->flag |= PTC_IGNORE_CLEAR; else - pid->cache->flag &= ~PTCACHE_IGNORE_CLEAR; + pid->cache->flag &= ~PTC_IGNORE_CLEAR; } } @@ -2670,13 +2670,14 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object * if (!smd->domain->fluid || framenr == startframe) { - BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); smokeModifier_reset_ex(smd, false); + + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); BKE_ptcache_validate(cache, framenr); - cache->flag &= ~PTCACHE_REDO_NEEDED; + cache->state.flag &= ~PTC_STATE_REDO_NEEDED; } - if (!smd->domain->fluid && (framenr != startframe) && (smd->domain->flags & MOD_SMOKE_FILE_LOAD) == 0 && (cache->flag & PTCACHE_BAKED) == 0) + if (!smd->domain->fluid && (framenr != startframe) && (smd->domain->flags & MOD_SMOKE_FILE_LOAD) == 0) return; smd->domain->flags &= ~MOD_SMOKE_FILE_LOAD; @@ -2710,7 +2711,7 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object * tstart(); /* if on second frame, write cache for first frame */ - if ((int)smd->time == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) { + if ((int)smd->time == startframe && (cache->state.flag & PTC_STATE_OUTDATED || cache->state.last_exact == 0)) { BKE_ptcache_write(&pid, startframe); } diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 941344cf21e..d11c87b8551 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -63,6 +63,8 @@ variables on the UI for now #include "DNA_curve_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_object_force.h" +#include "DNA_pointcache_types.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -3720,7 +3722,7 @@ SoftBody *sbNew(Scene *scene) sb->shearstiff = 1.0f; sb->solverflags |= SBSO_OLDERR; - sb->pointcache = BKE_ptcache_add(&sb->ptcaches); + sb->pointcache = BKE_ptcache_new(); if (!sb->effector_weights) sb->effector_weights = BKE_add_effector_weights(NULL); @@ -3734,7 +3736,7 @@ SoftBody *sbNew(Scene *scene) void sbFree(SoftBody *sb) { free_softbody_intern(sb); - BKE_ptcache_free_list(&sb->ptcaches); + BKE_ptcache_free(sb->pointcache); sb->pointcache = NULL; if (sb->effector_weights) MEM_freeN(sb->effector_weights); @@ -4051,7 +4053,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i cache= sb->pointcache; framenr= (int)cfra; - framedelta= framenr - cache->simframe; + framedelta= framenr - cache->state.simframe; BKE_ptcache_id_from_softbody(&pid, ob, sb); BKE_ptcache_id_time(&pid, scene, framenr, &startframe, &endframe, ×cale); @@ -4102,14 +4104,14 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i return; } if (framenr == startframe) { + sbFreeSimulation(sb); + BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); + BKE_ptcache_validate(cache, framenr); + cache->state.flag &= ~PTC_STATE_REDO_NEEDED; /* first frame, no simulation to do, just set the positions */ softbody_update_positions(ob, sb, vertexCos, numVerts); - - BKE_ptcache_validate(cache, framenr); - cache->flag &= ~PTCACHE_REDO_NEEDED; - sb->last_frame = framenr; return; @@ -4123,7 +4125,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i BKE_ptcache_validate(cache, framenr); - if (cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) + if (cache_result == PTCACHE_READ_INTERPOLATED && cache->state.flag & PTC_STATE_REDO_NEEDED) BKE_ptcache_write(&pid, framenr); sb->last_frame = framenr; @@ -4133,17 +4135,12 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i else if (cache_result==PTCACHE_READ_OLD) { ; /* do nothing */ } - else if (/*ob->id.lib || */(cache->flag & PTCACHE_BAKED)) { /* "library linking & pointcaches" has to be solved properly at some point */ - /* if baked and nothing in cache, do nothing */ - BKE_ptcache_invalidate(cache); - return; - } if (framenr!=sb->last_frame+1) return; /* if on second frame, write cache for first frame */ - if (cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) + if (cache->state.simframe == startframe && (cache->state.flag & PTC_STATE_OUTDATED || cache->state.last_exact==0)) BKE_ptcache_write(&pid, startframe); softbody_update_positions(ob, sb, vertexCos, numVerts); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 7e10bff49a4..d31167976ed 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -80,9 +80,11 @@ #include "DNA_nla_types.h" #include "DNA_node_types.h" #include "DNA_object_fluidsim.h" // NT +#include "DNA_object_force.h" #include "DNA_object_types.h" #include "DNA_packedFile_types.h" #include "DNA_particle_types.h" +#include "DNA_pointcache_types.h" #include "DNA_property_types.h" #include "DNA_rigidbody_types.h" #include "DNA_text_types.h" @@ -3617,83 +3619,17 @@ static void direct_link_material(FileData *fd, Material *ma) } /* ************ READ PARTICLE SETTINGS ***************** */ -/* update this also to writefile.c */ -static const char *ptcache_data_struct[] = { - "", // BPHYS_DATA_INDEX - "", // BPHYS_DATA_LOCATION - "", // BPHYS_DATA_VELOCITY - "", // BPHYS_DATA_ROTATION - "", // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */ - "", // BPHYS_DATA_SIZE: - "", // BPHYS_DATA_TIMES: - "BoidData" // case BPHYS_DATA_BOIDS: -}; -static void direct_link_pointcache(FileData *fd, PointCache *cache) +static void direct_link_pointcache(FileData *UNUSED(fd), PointCache *cache) { - if ((cache->flag & PTCACHE_DISK_CACHE)==0) { - PTCacheMem *pm; - PTCacheExtra *extra; - int i; - - link_list(fd, &cache->mem_cache); - - pm = cache->mem_cache.first; - - for (; pm; pm=pm->next) { - for (i=0; i<BPHYS_TOT_DATA; i++) { - pm->data[i] = newdataadr(fd, pm->data[i]); - - /* the cache saves non-struct data without DNA */ - if (pm->data[i] && ptcache_data_struct[i][0]=='\0' && (fd->flags & FD_FLAGS_SWITCH_ENDIAN)) { - int tot = (BKE_ptcache_data_size (i) * pm->totpoint) / sizeof(int); /* data_size returns bytes */ - int *poin = pm->data[i]; - - BLI_endian_switch_int32_array(poin, tot); - } - } - - link_list(fd, &pm->extradata); - - for (extra=pm->extradata.first; extra; extra=extra->next) - extra->data = newdataadr(fd, extra->data); - } - } - else - BLI_listbase_clear(&cache->mem_cache); + if (!cache) + return; - cache->flag &= ~PTCACHE_SIMULATION_VALID; - cache->simframe = 0; + cache->state.simframe = 0; cache->edit = NULL; cache->free_edit = NULL; - cache->cached_frames = NULL; -} - -static void direct_link_pointcache_list(FileData *fd, ListBase *ptcaches, PointCache **ocache, int force_disk) -{ - if (ptcaches->first) { - PointCache *cache= NULL; - link_list(fd, ptcaches); - for (cache=ptcaches->first; cache; cache=cache->next) { - direct_link_pointcache(fd, cache); - if (force_disk) { - cache->flag |= PTCACHE_DISK_CACHE; - cache->step = 1; - } - } - - *ocache = newdataadr(fd, *ocache); - } - else if (*ocache) { - /* old "single" caches need to be linked too */ - *ocache = newdataadr(fd, *ocache); - direct_link_pointcache(fd, *ocache); - if (force_disk) { - (*ocache)->flag |= PTCACHE_DISK_CACHE; - (*ocache)->step = 1; - } - - ptcaches->first = ptcaches->last = *ocache; - } + cache->state.cached_frames = NULL; + /* XXX previously could have memory cache with step != 1, remove */ + cache->step = 1; } static void lib_link_partdeflect(FileData *fd, ID *id, PartDeflect *pd) @@ -3860,7 +3796,6 @@ static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase /* XXX - from reading existing code this seems correct but intended usage of * pointcache should /w cloth should be added in 'ParticleSystem' - campbell */ psys->clmd->point_cache = psys->pointcache; - psys->clmd->ptcaches.first = psys->clmd->ptcaches.last= NULL; psys->clmd->coll_parms->group = newlibadr(fd, id->lib, psys->clmd->coll_parms->group); psys->clmd->modifier.error = NULL; } @@ -3926,7 +3861,8 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles) psys->pdd = NULL; psys->renderdata = NULL; - direct_link_pointcache_list(fd, &psys->ptcaches, &psys->pointcache, 0); + psys->pointcache = newdataadr(fd, psys->pointcache); + direct_link_pointcache(fd, psys->pointcache); if (psys->clmd) { psys->clmd = newdataadr(fd, psys->clmd); @@ -4660,7 +4596,8 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) clmd->sim_parms= newdataadr(fd, clmd->sim_parms); clmd->coll_parms= newdataadr(fd, clmd->coll_parms); - direct_link_pointcache_list(fd, &clmd->ptcaches, &clmd->point_cache, 0); + clmd->point_cache = newdataadr(fd, clmd->point_cache); + direct_link_pointcache(fd, clmd->point_cache); if (clmd->sim_parms) { if (clmd->sim_parms->presets > 10) @@ -4705,13 +4642,15 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) if (!smd->domain->effector_weights) smd->domain->effector_weights = BKE_add_effector_weights(NULL); - direct_link_pointcache_list(fd, &(smd->domain->ptcaches[0]), &(smd->domain->point_cache[0]), 1); + smd->domain->point_cache[0] = newdataadr(fd, smd->domain->point_cache[0]); + direct_link_pointcache(fd, smd->domain->point_cache[0]); + smd->domain->ptcaches[0].first = smd->domain->ptcaches[0].last = smd->domain->point_cache[0]; /* Smoke uses only one cache from now on, so store pointer convert */ if (smd->domain->ptcaches[1].first || smd->domain->point_cache[1]) { if (smd->domain->point_cache[1]) { PointCache *cache = newdataadr(fd, smd->domain->point_cache[1]); - if (cache->flag & PTCACHE_FAKE_SMOKE) { + if (cache->state.flag & PTC_STATE_FAKE_SMOKE) { /* Smoke was already saved in "new format" and this cache is a fake one. */ } else { @@ -4767,7 +4706,9 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) for (surface=pmd->canvas->surfaces.first; surface; surface=surface->next) { surface->canvas = pmd->canvas; surface->data = NULL; - direct_link_pointcache_list(fd, &(surface->ptcaches), &(surface->pointcache), 1); + + surface->pointcache = newdataadr(fd, surface->pointcache); + direct_link_pointcache(fd, surface->pointcache); if (!(surface->effector_weights = newdataadr(fd, surface->effector_weights))) surface->effector_weights = BKE_add_effector_weights(NULL); @@ -4888,6 +4829,13 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) } lmd->cache_system = NULL; } + else if (md->type == eModifierType_PointCache) { + PointCacheModifierData *pcmd = (PointCacheModifierData *)md; + + pcmd->point_cache = newdataadr(fd, pcmd->point_cache); + pcmd->reader = NULL; + pcmd->writer = NULL; + } } } @@ -5018,7 +4966,8 @@ static void direct_link_object(FileData *fd, Object *ob) if (!sb->effector_weights) sb->effector_weights = BKE_add_effector_weights(NULL); - direct_link_pointcache_list(fd, &sb->ptcaches, &sb->pointcache, 0); + sb->pointcache = newdataadr(fd, sb->pointcache); + direct_link_pointcache(fd, sb->pointcache); } ob->bsoft = newdataadr(fd, ob->bsoft); ob->fluidsimSettings= newdataadr(fd, ob->fluidsimSettings); /* NT */ @@ -5660,7 +5609,8 @@ static void direct_link_scene(FileData *fd, Scene *sce) rbw->effector_weights = BKE_add_effector_weights(NULL); /* link cache */ - direct_link_pointcache_list(fd, &rbw->ptcaches, &rbw->pointcache, false); + rbw->pointcache = newdataadr(fd, rbw->pointcache); + direct_link_pointcache(fd, rbw->pointcache); /* make sure simulation starts from the beginning after loading file */ if (rbw->pointcache) { rbw->ltime = (float)rbw->pointcache->startframe; diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index b71a4029690..8eb54c30cb1 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -53,7 +53,9 @@ #include "DNA_meshdata_types.h" #include "DNA_node_types.h" #include "DNA_object_fluidsim.h" // NT +#include "DNA_object_force.h" #include "DNA_object_types.h" +#include "DNA_pointcache_types.h" #include "DNA_view3d_types.h" #include "DNA_screen_types.h" #include "DNA_sdna_types.h" diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index e6e43758e11..0ff953e7420 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -37,20 +37,26 @@ #include "DNA_brush_types.h" #include "DNA_cloth_types.h" #include "DNA_constraint_types.h" +#include "DNA_dynamicpaint_types.h" +#include "DNA_pointcache_types.h" #include "DNA_sdna_types.h" +#include "DNA_smoke_types.h" #include "DNA_space_types.h" #include "DNA_screen_types.h" +#include "DNA_object_force.h" #include "DNA_object_types.h" #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_particle_types.h" #include "DNA_linestyle_types.h" #include "DNA_actuator_types.h" +#include "DNA_rigidbody_types.h" #include "DNA_genfile.h" #include "BKE_main.h" #include "BKE_node.h" +#include "BKE_pointcache.h" #include "BLI_math.h" #include "BLI_listbase.h" @@ -125,6 +131,28 @@ static void do_version_constraints_stretch_to_limits(ListBase *lb) } } +static void do_versions_pointcache(ID *UNUSED(id), PointCache *cache) +{ + int oldflag = cache->flag; + int cache_flag = 0, cache_state_flag = 0; + + if (oldflag & _PTCACHE_EXTERNAL_DEPRECATED) cache_flag |= PTC_EXTERNAL; + if (oldflag & _PTCACHE_IGNORE_LIBPATH_DEPRECATED) cache_flag |= PTC_IGNORE_LIBPATH; + if (oldflag & _PTCACHE_IGNORE_CLEAR_DEPRECATED) cache_flag |= PTC_IGNORE_CLEAR; + /* BAKED used to set locking instead */ + if (oldflag & _PTCACHE_BAKED_DEPRECATED) cache_flag |= PTC_LOCK_SETTINGS; + + /* REDO_NEEDED is combination of OUTDATED and FRAMES_SKIPPED, no need to copy */ + if (oldflag & _PTCACHE_OUTDATED_DEPRECATED) cache_state_flag |= PTC_STATE_OUTDATED; + if (oldflag & _PTCACHE_BAKING_DEPRECATED) cache_state_flag |= PTC_STATE_BAKING; + if (oldflag & _PTCACHE_FRAMES_SKIPPED_DEPRECATED) cache_state_flag |= PTC_STATE_FRAMES_SKIPPED; + if (oldflag & _PTCACHE_READ_INFO_DEPRECATED) cache_state_flag |= PTC_STATE_READ_INFO; + if (oldflag & _PTCACHE_FAKE_SMOKE_DEPRECATED) cache_state_flag |= PTC_STATE_FAKE_SMOKE; + + cache->flag = cache_flag; + cache->state.flag = cache_state_flag; +} + void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) { if (!MAIN_VERSION_ATLEAST(main, 270, 0)) { @@ -435,6 +463,53 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + /* memcache has been removed, clear BAKED flags to enforce rebaking */ + if (!PTCACHE_DO_VERSIONS(main)) { + Object *ob; + Scene *sce; + for (ob = main->object.first; ob; ob = ob->id.next) { + ModifierData *md; + ParticleSystem *psys; + for (md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Fluidsim) { + FluidsimModifierData *fluidmd = (FluidsimModifierData *)md; + do_versions_pointcache(&ob->id, fluidmd->point_cache); + } + else if (md->type == eModifierType_Smoke) { + SmokeModifierData *smd = (SmokeModifierData *)md; + if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { + do_versions_pointcache(&ob->id, smd->domain->point_cache[0]); + } + } + else if (md->type == eModifierType_Cloth) { + ClothModifierData *clmd = (ClothModifierData *) md; + do_versions_pointcache(&ob->id, clmd->point_cache); + } + else if (md->type == eModifierType_DynamicPaint) { + DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; + if (pmd->canvas) { + DynamicPaintSurface *surface; + for (surface=pmd->canvas->surfaces.first; surface; surface=surface->next) + do_versions_pointcache(&ob->id, surface->pointcache); + } + } + } + + if (ob->soft) { + do_versions_pointcache(&ob->id, ob->soft->pointcache); + } + + for (psys = ob->particlesystem.first; psys; psys = psys->next) { + do_versions_pointcache(&ob->id, psys->pointcache); + } + } + for (sce = main->scene.first; sce; sce = sce->id.next) { + RigidBodyWorld *rbw = sce->rigidbody_world; + if (rbw) + do_versions_pointcache(&sce->id, rbw->pointcache); + } + } if (!MAIN_VERSION_ATLEAST(main, 273, 1)) { #define BRUSH_RAKE (1 << 7) diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 6f298923397..27e49522be4 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -59,7 +59,9 @@ #include "DNA_nla_types.h" #include "DNA_node_types.h" #include "DNA_object_fluidsim.h" // NT +#include "DNA_object_force.h" #include "DNA_object_types.h" +#include "DNA_pointcache_types.h" #include "DNA_property_types.h" #include "DNA_view3d_types.h" #include "DNA_screen_types.h" @@ -2792,24 +2794,18 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) /* add point caches */ for (ob = main->object.first; ob; ob = ob->id.next) { if (ob->soft && !ob->soft->pointcache) - ob->soft->pointcache = BKE_ptcache_add(&ob->soft->ptcaches); + ob->soft->pointcache = BKE_ptcache_new(); for (psys = ob->particlesystem.first; psys; psys = psys->next) { - if (psys->pointcache) { - if (psys->pointcache->flag & PTCACHE_BAKED && (psys->pointcache->flag & PTCACHE_DISK_CACHE) == 0) { - printf("Old memory cache isn't supported for particles, so re-bake the simulation!\n"); - psys->pointcache->flag &= ~PTCACHE_BAKED; - } - } - else - psys->pointcache = BKE_ptcache_add(&psys->ptcaches); + if (!psys->pointcache) + psys->pointcache = BKE_ptcache_new(); } for (md = ob->modifiers.first; md; md = md->next) { if (md->type == eModifierType_Cloth) { ClothModifierData *clmd = (ClothModifierData*) md; if (!clmd->point_cache) { - clmd->point_cache = BKE_ptcache_add(&clmd->ptcaches); + clmd->point_cache = BKE_ptcache_new(); clmd->point_cache->step = 1; } } @@ -3041,7 +3037,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) /* create new particle system */ psys = MEM_callocN(sizeof(ParticleSystem), "particle_system"); - psys->pointcache = BKE_ptcache_add(&psys->ptcaches); + psys->pointcache = BKE_ptcache_new(); part = psys->part = psys_new_settings("ParticleSettings", main); diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index b32460d39f9..f4c08149e05 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1040,55 +1040,9 @@ static void write_boid_state(WriteData *wd, BoidState *state) // writestruct(wd, DATA, "BoidCondition", 1, cond); } -/* update this also to readfile.c */ -static const char *ptcache_data_struct[] = { - "", // BPHYS_DATA_INDEX - "", // BPHYS_DATA_LOCATION - "", // BPHYS_DATA_VELOCITY - "", // BPHYS_DATA_ROTATION - "", // BPHYS_DATA_AVELOCITY / BPHYS_DATA_XCONST */ - "", // BPHYS_DATA_SIZE: - "", // BPHYS_DATA_TIMES: - "BoidData" // case BPHYS_DATA_BOIDS: -}; -static const char *ptcache_extra_struct[] = { - "", - "ParticleSpring" -}; -static void write_pointcaches(WriteData *wd, ListBase *ptcaches) +static void write_pointcache(WriteData *wd, PointCache *cache) { - PointCache *cache = ptcaches->first; - int i; - - for (; cache; cache=cache->next) { - writestruct(wd, DATA, "PointCache", 1, cache); - - if ((cache->flag & PTCACHE_DISK_CACHE)==0) { - PTCacheMem *pm = cache->mem_cache.first; - - for (; pm; pm=pm->next) { - PTCacheExtra *extra = pm->extradata.first; - - writestruct(wd, DATA, "PTCacheMem", 1, pm); - - for (i=0; i<BPHYS_TOT_DATA; i++) { - if (pm->data[i] && pm->data_types & (1<<i)) { - if (ptcache_data_struct[i][0]=='\0') - writedata(wd, DATA, MEM_allocN_len(pm->data[i]), pm->data[i]); - else - writestruct(wd, DATA, ptcache_data_struct[i], pm->totpoint, pm->data[i]); - } - } - - for (; extra; extra=extra->next) { - if (ptcache_extra_struct[extra->type][0]=='\0') - continue; - writestruct(wd, DATA, "PTCacheExtra", 1, extra); - writestruct(wd, DATA, ptcache_extra_struct[extra->type], extra->totdata, extra->data); - } - } - } - } + writestruct(wd, DATA, "PointCache", 1, cache); } static void write_particlesettings(WriteData *wd, ListBase *idbase) { @@ -1178,7 +1132,7 @@ static void write_particlesystems(WriteData *wd, ListBase *particles) writestruct(wd, DATA, "ClothCollSettings", 1, psys->clmd->coll_parms); } - write_pointcaches(wd, &psys->ptcaches); + write_pointcache(wd, psys->pointcache); } } @@ -1488,28 +1442,28 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) writestruct(wd, DATA, "ClothSimSettings", 1, clmd->sim_parms); writestruct(wd, DATA, "ClothCollSettings", 1, clmd->coll_parms); writestruct(wd, DATA, "EffectorWeights", 1, clmd->sim_parms->effector_weights); - write_pointcaches(wd, &clmd->ptcaches); + write_pointcache(wd, clmd->point_cache); } else if (md->type==eModifierType_Smoke) { SmokeModifierData *smd = (SmokeModifierData*) md; if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { if (smd->domain) { - write_pointcaches(wd, &(smd->domain->ptcaches[0])); + write_pointcache(wd, smd->domain->point_cache[0]); /* create fake pointcache so that old blender versions can read it */ - smd->domain->point_cache[1] = BKE_ptcache_add(&smd->domain->ptcaches[1]); - smd->domain->point_cache[1]->flag |= PTCACHE_DISK_CACHE|PTCACHE_FAKE_SMOKE; + smd->domain->point_cache[1] = BKE_ptcache_new(); + smd->domain->point_cache[1]->state.flag |= PTC_STATE_FAKE_SMOKE; smd->domain->point_cache[1]->step = 1; - write_pointcaches(wd, &(smd->domain->ptcaches[1])); + write_pointcache(wd, smd->domain->point_cache[1]); } writestruct(wd, DATA, "SmokeDomainSettings", 1, smd->domain); if (smd->domain) { /* cleanup the fake pointcache */ - BKE_ptcache_free_list(&smd->domain->ptcaches[1]); + BKE_ptcache_free(smd->domain->point_cache[1]); smd->domain->point_cache[1] = NULL; writestruct(wd, DATA, "EffectorWeights", 1, smd->domain->effector_weights); @@ -1537,7 +1491,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) writestruct(wd, DATA, "DynamicPaintSurface", 1, surface); /* write caches and effector weights */ for (surface=pmd->canvas->surfaces.first; surface; surface=surface->next) { - write_pointcaches(wd, &(surface->ptcaches)); + write_pointcache(wd, surface->pointcache); writestruct(wd, DATA, "EffectorWeights", 1, surface->effector_weights); } @@ -1588,6 +1542,11 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) writedata(wd, DATA, sizeof(float)*lmd->total_verts * 3, lmd->vertexco); } + else if (md->type==eModifierType_PointCache) { + PointCacheModifierData *pcmd = (PointCacheModifierData *)md; + + writestruct(wd, DATA, "PointCache", 1, pcmd->point_cache); + } } } @@ -1631,7 +1590,7 @@ static void write_objects(WriteData *wd, ListBase *idbase) writestruct(wd, DATA, "PartDeflect", 1, ob->pd); writestruct(wd, DATA, "SoftBody", 1, ob->soft); if (ob->soft) { - write_pointcaches(wd, &ob->soft->ptcaches); + write_pointcache(wd, ob->soft->pointcache); writestruct(wd, DATA, "EffectorWeights", 1, ob->soft->effector_weights); } writestruct(wd, DATA, "BulletSoftBody", 1, ob->bsoft); @@ -2445,7 +2404,7 @@ static void write_scenes(WriteData *wd, ListBase *scebase) if (sce->rigidbody_world) { writestruct(wd, DATA, "RigidBodyWorld", 1, sce->rigidbody_world); writestruct(wd, DATA, "EffectorWeights", 1, sce->rigidbody_world->effector_weights); - write_pointcaches(wd, &(sce->rigidbody_world->ptcaches)); + write_pointcache(wd, sce->rigidbody_world->pointcache); } sce= sce->id.next; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 93956128b84..0a053d771df 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -408,7 +408,7 @@ void ED_object_editmode_exit(bContext *C, int flag) BKE_ptcache_ids_from_object(&pidlist, obedit, scene, 0); for (pid = pidlist.first; pid; pid = pid->next) { if (pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */ - pid->cache->flag |= PTCACHE_OUTDATED; + pid->cache->state.flag |= PTC_STATE_OUTDATED; } BLI_freelistN(&pidlist); diff --git a/source/blender/editors/physics/CMakeLists.txt b/source/blender/editors/physics/CMakeLists.txt index 40d555226f3..e8ded8c9146 100644 --- a/source/blender/editors/physics/CMakeLists.txt +++ b/source/blender/editors/physics/CMakeLists.txt @@ -26,6 +26,7 @@ set(INC ../../gpu ../../makesdna ../../makesrna + ../../pointcache ../../windowmanager ../../../../intern/elbeem/extern ../../../../intern/guardedalloc diff --git a/source/blender/editors/physics/SConscript b/source/blender/editors/physics/SConscript index 983d1c4b4ba..aa0bb260a31 100644 --- a/source/blender/editors/physics/SConscript +++ b/source/blender/editors/physics/SConscript @@ -36,6 +36,7 @@ incs = [ '#/intern/rigidbody', '#/intern/elbeem/extern', '../include', + '../../pointcache', '../../blenfont', '../../blenkernel', '../../blenlib', diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 9a3433b0ccf..5e30ca4ed2f 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -83,7 +83,8 @@ #include "physics_intern.h" -static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys); +static void PE_create_particle_edit_from_psys(Scene *scene, Object *ob, ParticleSystem *psys); +static void PE_create_particle_edit_from_cache(Scene *scene, Object *ob, PointCache *cache, ListBase *mem_cache); static void PTCacheUndo_clear(PTCacheEdit *edit); static void recalc_emitter_field(Object *ob, ParticleSystem *psys); @@ -246,20 +247,20 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create) if (psys->flag & PSYS_CURRENT) { if (psys->part && psys->part->type == PART_HAIR) { - if (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) { + if (psys->flag & PSYS_HAIR_DYNAMICS) { if (create && !psys->pointcache->edit) - PE_create_particle_edit(scene, ob, pid->cache, NULL); + PE_create_particle_edit_from_cache(scene, ob, pid->cache, &psys->mem_pointcache); edit = pid->cache->edit; } else { if (create && !psys->edit && psys->flag & PSYS_HAIR_DONE) - PE_create_particle_edit(scene, ob, NULL, psys); + PE_create_particle_edit_from_psys(scene, ob, psys); edit = psys->edit; } } else { - if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) - PE_create_particle_edit(scene, ob, pid->cache, psys); + if (create && !pid->cache->edit) + PE_create_particle_edit_from_cache(scene, ob, pid->cache, &psys->mem_pointcache); edit = pid->cache->edit; } @@ -267,19 +268,25 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create) } } else if (pset->edittype == PE_TYPE_SOFTBODY && pid->type == PTCACHE_TYPE_SOFTBODY) { - if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) { + if (create && !pid->cache->edit) { pset->flag |= PE_FADE_TIME; // NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB; - PE_create_particle_edit(scene, ob, pid->cache, NULL); + /* XXX passing NULL for mem_cache will always fail, leaving it here + * until point cache edit is reworked + */ + PE_create_particle_edit_from_cache(scene, ob, pid->cache, NULL); } edit = pid->cache->edit; break; } else if (pset->edittype == PE_TYPE_CLOTH && pid->type == PTCACHE_TYPE_CLOTH) { - if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) { + if (create && !pid->cache->edit) { pset->flag |= PE_FADE_TIME; // NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB; - PE_create_particle_edit(scene, ob, pid->cache, NULL); + /* XXX passing NULL for mem_cache will always fail, leaving it here + * until point cache edit is reworked + */ + PE_create_particle_edit_from_cache(scene, ob, pid->cache, NULL); } edit = pid->cache->edit; break; @@ -4074,7 +4081,7 @@ static void make_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo) else { PTCacheMem *pm; - BLI_duplicatelist(&undo->mem_cache, &edit->pid.cache->mem_cache); + BLI_duplicatelist(&undo->mem_cache, &edit->mem_cache); pm = undo->mem_cache.first; for (; pm; pm=pm->next) { @@ -4144,11 +4151,11 @@ static void get_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo) PTCacheMem *pm; int i; - BKE_ptcache_free_mem(&edit->pid.cache->mem_cache); + BKE_ptcache_free_mem(&edit->mem_cache); - BLI_duplicatelist(&edit->pid.cache->mem_cache, &undo->mem_cache); + BLI_duplicatelist(&edit->mem_cache, &undo->mem_cache); - pm = edit->pid.cache->mem_cache.first; + pm = edit->mem_cache.first; for (; pm; pm=pm->next) { for (i=0; i<BPHYS_TOT_DATA; i++) @@ -4359,8 +4366,20 @@ int PE_minmax(Scene *scene, float min[3], float max[3]) /************************ particle edit toggle operator ************************/ +static void PE_create_particle_edit_common(PTCacheEdit *edit, Scene *scene, Object *ob) +{ + UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col); + UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col); + + recalc_lengths(edit); + PE_update_object(scene, ob, 1); + + PTCacheUndo_clear(edit); + PE_undo_push(scene, "Original"); +} + /* initialize needed data for bake edit */ -static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys) +static void PE_create_particle_edit_from_psys(Scene *scene, Object *ob, ParticleSystem *psys) { PTCacheEdit *edit; ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL; @@ -4370,101 +4389,109 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, int totpoint; /* no psmd->dm happens in case particle system modifier is not enabled */ - if (!(psys && psmd && psmd->dm) && !cache) - return; - - if (cache && cache->flag & PTCACHE_DISK_CACHE) + if (!(psys && psmd && psmd->dm)) return; - if (psys == NULL && (cache && BLI_listbase_is_empty(&cache->mem_cache))) - return; - - edit = (psys) ? psys->edit : cache->edit; + edit = psys->edit; if (!edit) { - totpoint = psys ? psys->totpart : (int)((PTCacheMem *)cache->mem_cache.first)->totpoint; + totpoint = psys->totpart; edit= MEM_callocN(sizeof(PTCacheEdit), "PE_create_particle_edit"); edit->points=MEM_callocN(totpoint*sizeof(PTCacheEditPoint), "PTCacheEditPoints"); edit->totpoint = totpoint; - if (psys && !cache) { - psys->edit= edit; - edit->psys = psys; - - psys->free_edit= PE_free_ptcache_edit; - - edit->pathcache = NULL; - BLI_listbase_clear(&edit->pathcachebufs); - - pa = psys->particles; - LOOP_POINTS { - point->totkey = pa->totkey; - point->keys= MEM_callocN(point->totkey*sizeof(PTCacheEditKey), "ParticleEditKeys"); - point->flag |= PEP_EDIT_RECALC; - - hkey = pa->hair; - LOOP_KEYS { - key->co= hkey->co; - key->time= &hkey->time; - key->flag= hkey->editflag; - if (!(psys->flag & PSYS_GLOBAL_HAIR)) { - key->flag |= PEK_USE_WCO; - hkey->editflag |= PEK_USE_WCO; - } - - hkey++; + psys->edit= edit; + edit->psys = psys; + + psys->free_edit= PE_free_ptcache_edit; + + edit->pathcache = NULL; + BLI_listbase_clear(&edit->pathcachebufs); + + pa = psys->particles; + LOOP_POINTS { + point->totkey = pa->totkey; + point->keys= MEM_callocN(point->totkey*sizeof(PTCacheEditKey), "ParticleEditKeys"); + point->flag |= PEP_EDIT_RECALC; + + hkey = pa->hair; + LOOP_KEYS { + key->co= hkey->co; + key->time= &hkey->time; + key->flag= hkey->editflag; + if (!(psys->flag & PSYS_GLOBAL_HAIR)) { + key->flag |= PEK_USE_WCO; + hkey->editflag |= PEK_USE_WCO; } - pa++; + + hkey++; } - update_world_cos(ob, edit); + pa++; } - else { - PTCacheMem *pm; - int totframe=0; + update_world_cos(ob, edit); + + recalc_emitter_field(ob, psys); + + PE_create_particle_edit_common(edit, scene, ob); + } +} - cache->edit= edit; - cache->free_edit= PE_free_ptcache_edit; - edit->psys = NULL; - for (pm=cache->mem_cache.first; pm; pm=pm->next) - totframe++; +/* initialize needed data for bake edit */ +static void PE_create_particle_edit_from_cache(Scene *scene, Object *ob, PointCache *cache, ListBase *mem_cache) +{ + PTCacheEdit *edit; + POINT_P; PTCacheEditKey *key; + int totpoint; + + if (!(cache && mem_cache && mem_cache->first)) + return; - for (pm=cache->mem_cache.first; pm; pm=pm->next) { - LOOP_POINTS { - if (BKE_ptcache_mem_pointers_seek(p, pm) == 0) - continue; + edit = cache->edit; - if (!point->totkey) { - key = point->keys = MEM_callocN(totframe*sizeof(PTCacheEditKey), "ParticleEditKeys"); - point->flag |= PEP_EDIT_RECALC; - } - else - key = point->keys + point->totkey; + if (!edit) { + PTCacheMem *pm; + int totframe=0; - key->co = pm->cur[BPHYS_DATA_LOCATION]; - key->vel = pm->cur[BPHYS_DATA_VELOCITY]; - key->rot = pm->cur[BPHYS_DATA_ROTATION]; - key->ftime = (float)pm->frame; - key->time = &key->ftime; - BKE_ptcache_mem_pointers_incr(pm); + totpoint = (int)((PTCacheMem *)mem_cache->first)->totpoint; - point->totkey++; + edit= MEM_callocN(sizeof(PTCacheEdit), "PE_create_particle_edit"); + edit->points=MEM_callocN(totpoint*sizeof(PTCacheEditPoint), "PTCacheEditPoints"); + edit->totpoint = totpoint; + + cache->edit= edit; + cache->free_edit= PE_free_ptcache_edit; + edit->mem_cache = *mem_cache; + edit->psys = NULL; + + for (pm=mem_cache->first; pm; pm=pm->next) + totframe++; + + for (pm=mem_cache->first; pm; pm=pm->next) { + LOOP_POINTS { + if (BKE_ptcache_mem_pointers_seek(p, pm) == 0) + continue; + + if (!point->totkey) { + key = point->keys = MEM_callocN(totframe*sizeof(PTCacheEditKey), "ParticleEditKeys"); + point->flag |= PEP_EDIT_RECALC; } + else + key = point->keys + point->totkey; + + key->co = pm->cur[BPHYS_DATA_LOCATION]; + key->vel = pm->cur[BPHYS_DATA_VELOCITY]; + key->rot = pm->cur[BPHYS_DATA_ROTATION]; + key->ftime = (float)pm->frame; + key->time = &key->ftime; + BKE_ptcache_mem_pointers_incr(pm); + + point->totkey++; } - psys = NULL; } - UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col); - UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col); - - recalc_lengths(edit); - if (psys && !cache) - recalc_emitter_field(ob, psys); - PE_update_object(scene, ob, 1); - - PTCacheUndo_clear(edit); - PE_undo_push(scene, "Original"); + PE_create_particle_edit_common(edit, scene, ob); } } diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h index b8955c8c397..8c49bf21191 100644 --- a/source/blender/editors/physics/physics_intern.h +++ b/source/blender/editors/physics/physics_intern.h @@ -98,13 +98,7 @@ void DPAINT_OT_type_toggle(struct wmOperatorType *ot); void DPAINT_OT_output_toggle(struct wmOperatorType *ot); /* physics_pointcache.c */ -void PTCACHE_OT_bake_all(struct wmOperatorType *ot); -void PTCACHE_OT_free_bake_all(struct wmOperatorType *ot); -void PTCACHE_OT_bake(struct wmOperatorType *ot); -void PTCACHE_OT_free_bake(struct wmOperatorType *ot); -void PTCACHE_OT_bake_from_cache(struct wmOperatorType *ot); -void PTCACHE_OT_add(struct wmOperatorType *ot); -void PTCACHE_OT_remove(struct wmOperatorType *ot); +void PTCACHE_OT_export(struct wmOperatorType *ot); /* rigidbody_object.c */ void RIGIDBODY_OT_object_add(struct wmOperatorType *ot); diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c index 03d32bc052d..37cf95e5c2d 100644 --- a/source/blender/editors/physics/physics_ops.c +++ b/source/blender/editors/physics/physics_ops.c @@ -179,13 +179,7 @@ static void operatortypes_fluid(void) static void operatortypes_pointcache(void) { - WM_operatortype_append(PTCACHE_OT_bake_all); - WM_operatortype_append(PTCACHE_OT_free_bake_all); - WM_operatortype_append(PTCACHE_OT_bake); - WM_operatortype_append(PTCACHE_OT_free_bake); - WM_operatortype_append(PTCACHE_OT_bake_from_cache); - WM_operatortype_append(PTCACHE_OT_add); - WM_operatortype_append(PTCACHE_OT_remove); + WM_operatortype_append(PTCACHE_OT_export); } /********************************* dynamic paint ***********************************/ diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c index 71e5e23b5f1..56dc089357f 100644 --- a/source/blender/editors/physics/physics_pointcache.c +++ b/source/blender/editors/physics/physics_pointcache.c @@ -30,17 +30,27 @@ */ #include <stdlib.h> +#include <string.h> + +#include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "DNA_modifier_types.h" #include "DNA_scene_types.h" #include "BKE_context.h" +#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_particle.h" #include "BKE_pointcache.h" +#include "BKE_report.h" +#include "BKE_scene.h" +#include "BKE_screen.h" + +#include "PTC_api.h" #include "ED_particle.h" @@ -52,348 +62,160 @@ #include "physics_intern.h" -static int cache_break_test(void *UNUSED(cbd)) -{ - return (G.is_break == true); -} -static int ptcache_bake_all_poll(bContext *C) -{ - Scene *scene= CTX_data_scene(C); - - if (!scene) - return 0; - - return 1; -} - static int ptcache_poll(bContext *C) { PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); return (ptr.data && ptr.id.data); } -static void bake_console_progress(void *UNUSED(arg), int nr) -{ - printf("\rbake: %3i%%", nr); - fflush(stdout); -} +typedef struct PTCacheExportJob { + short *stop, *do_update; + float *progress; + + struct Main *bmain; + struct Scene *scene; + EvaluationContext eval_ctx; + + PointerRNA user_ptr; + struct PointCache *cache; + struct PTCWriter *writer; + + int origfra; /* original frame to reset scene after export */ + float origframelen; /* original frame length to reset scene after export */ +} PTCacheExportJob; -static void bake_console_progress_end(void *UNUSED(arg)) +static void ptcache_export_freejob(void *customdata) { - printf("\rbake: done!\n"); + PTCacheExportJob *data= (PTCacheExportJob *)customdata; + MEM_freeN(data); } -static void ptcache_free_bake(PointCache *cache) +static void ptcache_export_startjob(void *customdata, short *stop, short *do_update, float *progress) { - if (cache->edit) { - if (!cache->edit->edited || 1) {// XXX okee("Lose changes done in particle mode?")) { - PE_free_ptcache_edit(cache->edit); - cache->edit = NULL; - cache->flag &= ~PTCACHE_BAKED; - } - } - else { - cache->flag &= ~PTCACHE_BAKED; - } + PTCacheExportJob *data= (PTCacheExportJob *)customdata; + Scene *scene = data->scene; + int start_frame, end_frame; + + data->stop = stop; + data->do_update = do_update; + data->progress = progress; + + data->origfra = scene->r.cfra; + data->origframelen = scene->r.framelen; + scene->r.framelen = 1.0f; + memset(&data->eval_ctx, 0, sizeof(EvaluationContext)); + data->eval_ctx.mode = DAG_EVAL_RENDER; + + G.is_break = false; + + /* XXX where to get this from? */ + start_frame = scene->r.sfra; + end_frame = scene->r.efra; + PTC_bake(data->bmain, scene, &data->eval_ctx, data->writer, start_frame, end_frame, stop, do_update, progress); + + *do_update = true; + *stop = 0; } -static int ptcache_bake_all_exec(bContext *C, wmOperator *op) +static void ptcache_export_endjob(void *customdata) { - Main *bmain = CTX_data_main(C); - Scene *scene= CTX_data_scene(C); - wmWindow *win = G.background ? NULL : CTX_wm_window(C); - PTCacheBaker baker; - - baker.main = bmain; - baker.scene = scene; - baker.pid = NULL; - baker.bake = RNA_boolean_get(op->ptr, "bake"); - baker.render = 0; - baker.anim_init = 0; - baker.quick_step = 1; - baker.break_test = cache_break_test; - baker.break_data = NULL; - - /* Disabled for now as this doesn't work properly, - * and pointcache baking will be reimplemented with - * the job system soon anyways. */ - if (win) { - baker.progressbar = (void (*)(void *, int))WM_cursor_time; - baker.progressend = (void (*)(void *))WM_cursor_modal_restore; - baker.progresscontext = win; + PTCacheExportJob *data = (PTCacheExportJob *)customdata; + Scene *scene = data->scene; + + G.is_rendering = false; + BKE_spacedata_draw_locks(false); + + /* free the cache writer (closes output file) */ + if (RNA_struct_is_a(data->user_ptr.type, &RNA_PointCacheModifier)) { + Object *ob = (Object *)data->user_ptr.id.data; + PointCacheModifierData *pcmd = (PointCacheModifierData *)data->user_ptr.data; + + PTC_mod_point_cache_set_mode(scene, ob, pcmd, MOD_POINTCACHE_MODE_NONE); } else { - baker.progressbar = bake_console_progress; - baker.progressend = bake_console_progress_end; - baker.progresscontext = NULL; - } - - BKE_ptcache_bake(&baker); - - WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); - WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, NULL); - - return OPERATOR_FINISHED; -} -static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Scene *scene= CTX_data_scene(C); - Base *base; - PTCacheID *pid; - ListBase pidlist; - - for (base=scene->base.first; base; base= base->next) { - BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR); - - for (pid=pidlist.first; pid; pid=pid->next) { - ptcache_free_bake(pid->cache); - } - - BLI_freelistN(&pidlist); - - WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, base->object); + PTC_writer_free(data->writer); } - - WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); - - return OPERATOR_FINISHED; -} - -void PTCACHE_OT_bake_all(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Bake All Physics"; - ot->description = "Bake all physics"; - ot->idname = "PTCACHE_OT_bake_all"; - /* api callbacks */ - ot->exec = ptcache_bake_all_exec; - ot->poll = ptcache_bake_all_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_boolean(ot->srna, "bake", 1, "Bake", ""); + /* reset scene frame */ + scene->r.cfra = data->origfra; + scene->r.framelen = data->origframelen; + BKE_scene_update_for_newframe(&data->eval_ctx, data->bmain, scene, scene->lay); } -void PTCACHE_OT_free_bake_all(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Free All Physics Bakes"; - ot->idname = "PTCACHE_OT_free_bake_all"; - ot->description = "Free all baked caches of all objects in the current scene"; - - /* api callbacks */ - ot->exec = ptcache_free_bake_all_exec; - ot->poll = ptcache_bake_all_poll; - /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; -} -static int ptcache_bake_exec(bContext *C, wmOperator *op) +static int ptcache_export_exec(bContext *C, wmOperator *op) { + PointerRNA ptcache_ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); + PointerRNA user_ptr = CTX_data_pointer_get(C, "point_cache_user"); Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - wmWindow *win = G.background ? NULL : CTX_wm_window(C); - PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); - Object *ob= ptr.id.data; - PointCache *cache= ptr.data; - PTCacheBaker baker; - PTCacheID *pid; - ListBase pidlist; - - BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR); + PointCache *cache = ptcache_ptr.data; + struct PTCWriter *writer = NULL; + PTCacheExportJob *data; + wmJob *wm_job; - for (pid=pidlist.first; pid; pid=pid->next) { - if (pid->cache == cache) - break; + if (!user_ptr.data) { + BKE_reportf(op->reports, RPT_ERROR_INVALID_INPUT, "Missing point cache user info"); + return OPERATOR_CANCELLED; } - - baker.main = bmain; - baker.scene = scene; - baker.pid = pid; - baker.bake = RNA_boolean_get(op->ptr, "bake"); - baker.render = 0; - baker.anim_init = 0; - baker.quick_step = 1; - baker.break_test = cache_break_test; - baker.break_data = NULL; - - /* Disabled for now as this doesn't work properly, - * and pointcache baking will be reimplemented with - * the job system soon anyways. */ - if (win) { - baker.progressbar = (void (*)(void *, int))WM_cursor_time; - baker.progressend = (void (*)(void *))WM_cursor_modal_restore; - baker.progresscontext = win; + + /* special case: point cache modifier uses internal writer + * and needs to be set up for baking. + */ + if (RNA_struct_is_a(user_ptr.type, &RNA_PointCacheModifier)) { + Object *ob = (Object *)user_ptr.id.data; + PointCacheModifierData *pcmd = (PointCacheModifierData *)user_ptr.data; + + PTC_mod_point_cache_set_mode(scene, ob, pcmd, MOD_POINTCACHE_MODE_WRITE); } else { - printf("\n"); /* empty first line before console reports */ - baker.progressbar = bake_console_progress; - baker.progressend = bake_console_progress_end; - baker.progresscontext = NULL; + writer = PTC_writer_from_rna(scene, &user_ptr); + if (!writer) { + BKE_reportf(op->reports, RPT_ERROR_INVALID_INPUT, "%s is not a valid point cache user type", RNA_struct_identifier(user_ptr.type)); + return OPERATOR_CANCELLED; + } } - - BKE_ptcache_bake(&baker); - - BLI_freelistN(&pidlist); - - WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); - WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob); - - return OPERATOR_FINISHED; -} -static int ptcache_free_bake_exec(bContext *C, wmOperator *UNUSED(op)) -{ - PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); - PointCache *cache= ptr.data; - Object *ob= ptr.id.data; - - ptcache_free_bake(cache); - WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob); - - return OPERATOR_FINISHED; -} -static int ptcache_bake_from_cache_exec(bContext *C, wmOperator *UNUSED(op)) -{ - PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); - PointCache *cache= ptr.data; - Object *ob= ptr.id.data; + /* XXX annoying hack: needed to prevent data corruption when changing + * scene frame in separate threads + */ + G.is_rendering = true; + BKE_spacedata_draw_locks(true); - cache->flag |= PTCACHE_BAKED; - - WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob); - - return OPERATOR_FINISHED; -} -void PTCACHE_OT_bake(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Bake Physics"; - ot->description = "Bake physics"; - ot->idname = "PTCACHE_OT_bake"; + /* XXX set WM_JOB_EXCL_RENDER to prevent conflicts with render jobs, + * since we need to set G.is_rendering + */ + wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Point Cache Export", + WM_JOB_PROGRESS | WM_JOB_EXCL_RENDER, WM_JOB_TYPE_PTCACHE_EXPORT); - /* api callbacks */ - ot->exec = ptcache_bake_exec; - ot->poll = ptcache_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; - - RNA_def_boolean(ot->srna, "bake", 0, "Bake", ""); -} -void PTCACHE_OT_free_bake(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Free Physics Bake"; - ot->description = "Free physics bake"; - ot->idname = "PTCACHE_OT_free_bake"; + /* setup job */ + data = MEM_callocN(sizeof(PTCacheExportJob), "Point Cache Export Job"); + data->bmain = bmain; + data->scene = scene; + data->user_ptr = user_ptr; + data->cache = cache; + data->writer = writer; - /* api callbacks */ - ot->exec = ptcache_free_bake_exec; - ot->poll = ptcache_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; -} -void PTCACHE_OT_bake_from_cache(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Bake From Cache"; - ot->description = "Bake from cache"; - ot->idname = "PTCACHE_OT_bake_from_cache"; + WM_jobs_customdata_set(wm_job, data, ptcache_export_freejob); + WM_jobs_timer(wm_job, 0.1, NC_SCENE|ND_FRAME, NC_SCENE|ND_FRAME); + WM_jobs_callbacks(wm_job, ptcache_export_startjob, NULL, NULL, ptcache_export_endjob); - /* api callbacks */ - ot->exec = ptcache_bake_from_cache_exec; - ot->poll = ptcache_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; -} - -static int ptcache_add_new_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Scene *scene = CTX_data_scene(C); - PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); - Object *ob= ptr.id.data; - PointCache *cache= ptr.data; - PTCacheID *pid; - ListBase pidlist; - - BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR); - - for (pid=pidlist.first; pid; pid=pid->next) { - if (pid->cache == cache) { - PointCache *cache_new = BKE_ptcache_add(pid->ptcaches); - cache_new->step = pid->default_step; - *(pid->cache_ptr) = cache_new; - break; - } - } - - BLI_freelistN(&pidlist); - - WM_event_add_notifier(C, NC_SCENE|ND_FRAME, scene); - WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob); + WM_jobs_start(CTX_wm_manager(C), wm_job); return OPERATOR_FINISHED; } -static int ptcache_remove_exec(bContext *C, wmOperator *UNUSED(op)) -{ - PointerRNA ptr= CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache); - Scene *scene= CTX_data_scene(C); - Object *ob= ptr.id.data; - PointCache *cache= ptr.data; - PTCacheID *pid; - ListBase pidlist; - - BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR); - - for (pid=pidlist.first; pid; pid=pid->next) { - if (pid->cache == cache) { - if (pid->ptcaches->first == pid->ptcaches->last) - continue; /* don't delete last cache */ - BLI_remlink(pid->ptcaches, pid->cache); - BKE_ptcache_free(pid->cache); - *(pid->cache_ptr) = pid->ptcaches->first; - - break; - } - } - - BLI_freelistN(&pidlist); - - WM_event_add_notifier(C, NC_OBJECT|ND_POINTCACHE, ob); - - return OPERATOR_FINISHED; -} -void PTCACHE_OT_add(wmOperatorType *ot) +void PTCACHE_OT_export(wmOperatorType *ot) { /* identifiers */ - ot->name = "Add New Cache"; - ot->description = "Add new cache"; - ot->idname = "PTCACHE_OT_add"; - - /* api callbacks */ - ot->exec = ptcache_add_new_exec; - ot->poll = ptcache_poll; // ptcache_bake_all_poll; + ot->name = "Export"; + ot->description = "Export point data"; + ot->idname = "PTCACHE_OT_export"; - /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; -} -void PTCACHE_OT_remove(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Delete Current Cache"; - ot->description = "Delete current cache"; - ot->idname = "PTCACHE_OT_remove"; - /* api callbacks */ - ot->exec = ptcache_remove_exec; + ot->exec = ptcache_export_exec; ot->poll = ptcache_poll; /* flags */ - ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + /* no undo for this operator, cannot restore old cache files anyway */ + ot->flag = OPTYPE_REGISTER; } - diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index a963f422cb7..9bc043b384e 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1020,6 +1020,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */ case eModifierType_DataTransfer: UI_icon_draw(x, y, ICON_MOD_DATA_TRANSFER); break; + case eModifierType_PointCache: + UI_icon_draw(x, y, ICON_MOD_MESHDEFORM); break; /* XXX, needs own icon */ /* Default */ case eModifierType_None: case eModifierType_ShapeKey: diff --git a/source/blender/editors/space_time/space_time.c b/source/blender/editors/space_time/space_time.c index 7709980d12e..820d1d68f8d 100644 --- a/source/blender/editors/space_time/space_time.c +++ b/source/blender/editors/space_time/space_time.c @@ -133,7 +133,7 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) break; } - if (pid->cache->cached_frames == NULL) + if (pid->cache->state.cached_frames == NULL) continue; /* make sure we have stc with correct array length */ @@ -151,7 +151,7 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) /* fill the vertex array with a quad for each cached frame */ for (i = sta, fp = stc->array; i <= end; i++) { - if (pid->cache->cached_frames[i - sta]) { + if (pid->cache->state.cached_frames[i - sta]) { fp[0] = (float)i - 0.5f; fp[1] = 0.0; fp += 2; @@ -213,10 +213,7 @@ static void time_draw_cache(SpaceTime *stime, Object *ob, Scene *scene) glRectf((float)sta, 0.0, (float)end, 1.0); col[3] = 0.4f; - if (pid->cache->flag & PTCACHE_BAKED) { - col[0] -= 0.4f; col[1] -= 0.4f; col[2] -= 0.4f; - } - else if (pid->cache->flag & PTCACHE_OUTDATED) { + if (pid->cache->state.flag & PTC_STATE_OUTDATED) { col[0] += 0.4f; col[1] += 0.4f; col[2] += 0.4f; } glColor4fv(col); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 55b621d5aba..1cbc8e5567c 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -37,6 +37,7 @@ #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meta_types.h" +#include "DNA_object_force.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_smoke_types.h" diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 5dc34d2a31a..c1350b1f076 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5966,7 +5966,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) BKE_ptcache_ids_from_object(&pidlist, ob, t->scene, MAX_DUPLI_RECUR); for (pid = pidlist.first; pid; pid = pid->next) { if (pid->type != PTCACHE_TYPE_PARTICLES) /* particles don't need reset on geometry change */ - pid->cache->flag |= PTCACHE_OUTDATED; + pid->cache->state.flag |= PTC_STATE_OUTDATED; } BLI_freelistN(&pidlist); diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index afff97a8409..2648c662156 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -86,7 +86,7 @@ struct IK_Data { typedef float Vector3[3]; typedef float Vector4[4]; struct IK_Target; -typedef void (*ErrorCallback)(const iTaSC::ConstraintValues *values, unsigned int nvalues, IK_Target *iktarget); +typedef void (*PTCErrorCallback)(const iTaSC::ConstraintValues *values, unsigned int nvalues, IK_Target *iktarget); // one structure for each target in the scene struct IK_Target @@ -97,7 +97,7 @@ struct IK_Target struct bConstraint* blenderConstraint; struct bPoseChannel* rootChannel; Object* owner; //for auto IK - ErrorCallback errorCallback; + PTCErrorCallback errorCallback; std::string targetName; std::string constraintName; unsigned short controlType; diff --git a/source/blender/makesdna/DNA_dynamicpaint_types.h b/source/blender/makesdna/DNA_dynamicpaint_types.h index dece93af122..939b14a5d32 100644 --- a/source/blender/makesdna/DNA_dynamicpaint_types.h +++ b/source/blender/makesdna/DNA_dynamicpaint_types.h @@ -28,6 +28,7 @@ #ifndef __DNA_DYNAMICPAINT_TYPES_H__ #define __DNA_DYNAMICPAINT_TYPES_H__ +#include "DNA_defs.h" #include "DNA_listBase.h" struct CurveMapping; struct PaintSurfaceData; @@ -110,7 +111,7 @@ typedef struct DynamicPaintSurface { /* cache */ struct PointCache *pointcache; - struct ListBase ptcaches; + struct ListBase ptcaches DNA_DEPRECATED; int current_frame; /* surface */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index b1e9fd254e1..7b1a9bba3a2 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -83,6 +83,7 @@ typedef enum ModifierType { eModifierType_LaplacianDeform = 47, eModifierType_Wireframe = 48, eModifierType_DataTransfer = 49, + eModifierType_PointCache = 50, NUM_MODIFIER_TYPES } ModifierType; @@ -563,7 +564,7 @@ typedef struct ClothModifierData { struct ClothSimSettings *sim_parms; /* definition is in DNA_cloth_types.h */ struct ClothCollSettings *coll_parms; /* definition is in DNA_cloth_types.h */ struct PointCache *point_cache; /* definition is in DNA_object_force.h */ - struct ListBase ptcaches; + struct ListBase ptcaches DNA_DEPRECATED; } ClothModifierData; typedef struct CollisionModifierData { @@ -1410,5 +1411,19 @@ enum { MOD_DATATRANSFER_USE_POLY = 1 << 31, }; +/* point cache modifier */ +typedef struct PointCacheModifierData { + ModifierData modifier; + + int flag; + int pad; + + struct PointCache *point_cache; + + struct PTCReader *reader; + struct PTCWriter *writer; + struct DerivedMesh *output_dm; +} PointCacheModifierData; + #endif /* __DNA_MODIFIER_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index 5cc56d861a3..6f85acdcfe6 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -36,6 +36,7 @@ extern "C" { #endif +#include "DNA_defs.h" #include "DNA_listBase.h" /* pd->forcefield: Effector Fields types */ @@ -127,87 +128,6 @@ typedef struct EffectorWeights { /* EffectorWeights->flag */ #define EFF_WEIGHT_DO_HAIR 1 -/* Point cache file data types: - * - used as (1<<flag) so poke jahka if you reach the limit of 15 - * - to add new data types update: - * * BKE_ptcache_data_size() - * * ptcache_file_init_pointers() - */ -#define BPHYS_DATA_INDEX 0 -#define BPHYS_DATA_LOCATION 1 -#define BPHYS_DATA_SMOKE_LOW 1 -#define BPHYS_DATA_VELOCITY 2 -#define BPHYS_DATA_SMOKE_HIGH 2 -#define BPHYS_DATA_ROTATION 3 -#define BPHYS_DATA_DYNAMICPAINT 3 -#define BPHYS_DATA_AVELOCITY 4 /* used for particles */ -#define BPHYS_DATA_XCONST 4 /* used for cloth */ -#define BPHYS_DATA_SIZE 5 -#define BPHYS_DATA_TIMES 6 -#define BPHYS_DATA_BOIDS 7 - -#define BPHYS_TOT_DATA 8 - -#define BPHYS_EXTRA_FLUID_SPRINGS 1 - -typedef struct PTCacheExtra { - struct PTCacheExtra *next, *prev; - unsigned int type, totdata; - void *data; -} PTCacheExtra; - -typedef struct PTCacheMem { - struct PTCacheMem *next, *prev; - unsigned int frame, totpoint; - unsigned int data_types, flag; - - void *data[8]; /* BPHYS_TOT_DATA */ - void *cur[8]; /* BPHYS_TOT_DATA */ - - struct ListBase extradata; -} PTCacheMem; - -typedef struct PointCache { - struct PointCache *next, *prev; - int flag; /* generic flag */ - - int step; /* The number of frames between cached frames. - * This should probably be an upper bound for a per point adaptive step in the future, - * buf for now it's the same for all points. Without adaptivity this can effect the perceived - * simulation quite a bit though. If for example particles are colliding with a horizontal - * plane (with high damping) they quickly come to a stop on the plane, however there are still - * forces acting on the particle (gravity and collisions), so the particle velocity isn't necessarily - * zero for the whole duration of the frame even if the particle seems stationary. If all simulation - * frames aren't cached (step > 1) these velocities are interpolated into movement for the non-cached - * frames. The result will look like the point is oscillating around the collision location. So for - * now cache step should be set to 1 for accurate reproduction of collisions. - */ - - int simframe; /* current frame of simulation (only if SIMULATION_VALID) */ - int startframe; /* simulation start frame */ - int endframe; /* simulation end frame */ - int editframe; /* frame being edited (runtime only) */ - int last_exact; /* last exact frame that's cached */ - int last_valid; /* used for editing cache - what is the last baked frame */ - int pad; - - /* for external cache files */ - int totpoint; /* number of cached points */ - int index; /* modifier stack index */ - short compression, rt; - - char name[64]; - char prev_name[64]; - char info[64]; - char path[1024]; /* file path, 1024 = FILE_MAX */ - char *cached_frames; /* array of length endframe-startframe+1 with flags to indicate cached frames */ - /* can be later used for other per frame flags too if needed */ - struct ListBase mem_cache; - - struct PTCacheEdit *edit; - void (*free_edit)(struct PTCacheEdit *edit); /* free callback */ -} PointCache; - typedef struct SBVertex { float vec[4]; } SBVertex; @@ -337,7 +257,7 @@ typedef struct SoftBody { float inpush; struct PointCache *pointcache; - struct ListBase ptcaches; + struct ListBase ptcaches DNA_DEPRECATED; struct EffectorWeights *effector_weights; /* reverse esimated obmatrix .. no need to store in blend file .. how ever who cares */ @@ -392,31 +312,6 @@ typedef struct SoftBody { #define PFIELD_Z_POS 1 #define PFIELD_Z_NEG 2 -/* pointcache->flag */ -#define PTCACHE_BAKED 1 -#define PTCACHE_OUTDATED 2 -#define PTCACHE_SIMULATION_VALID 4 -#define PTCACHE_BAKING 8 -//#define PTCACHE_BAKE_EDIT 16 -//#define PTCACHE_BAKE_EDIT_ACTIVE 32 -#define PTCACHE_DISK_CACHE 64 -//#define PTCACHE_QUICK_CACHE 128 /* removed since 2.64 - [#30974], could be added back in a more useful way */ -#define PTCACHE_FRAMES_SKIPPED 256 -#define PTCACHE_EXTERNAL 512 -#define PTCACHE_READ_INFO 1024 -/* don't use the filename of the blendfile the data is linked from (write a local cache) */ -#define PTCACHE_IGNORE_LIBPATH 2048 -/* high resolution cache is saved for smoke for backwards compatibility, so set this flag to know it's a "fake" cache */ -#define PTCACHE_FAKE_SMOKE (1<<12) -#define PTCACHE_IGNORE_CLEAR (1<<13) - -/* PTCACHE_OUTDATED + PTCACHE_FRAMES_SKIPPED */ -#define PTCACHE_REDO_NEEDED 258 - -#define PTCACHE_COMPRESS_NO 0 -#define PTCACHE_COMPRESS_LZO 1 -#define PTCACHE_COMPRESS_LZMA 2 - /* ob->softflag */ #define OB_SB_ENABLE 1 /* deprecated, use modifier */ #define OB_SB_GOAL 2 diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index dd25a49c476..af8f0b87454 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -297,7 +297,8 @@ typedef struct ParticleSystem { /* point cache */ struct PointCache *pointcache; - struct ListBase ptcaches; + struct ListBase ptcaches DNA_DEPRECATED; + struct ListBase mem_pointcache; struct ListBase *effectors; diff --git a/source/blender/makesdna/DNA_pointcache_types.h b/source/blender/makesdna/DNA_pointcache_types.h new file mode 100644 index 00000000000..808f4a7fefa --- /dev/null +++ b/source/blender/makesdna/DNA_pointcache_types.h @@ -0,0 +1,192 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2004-2005 by Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file DNA_pointcache_types.h + * \ingroup DNA + */ + +#ifndef __DNA_POINTCACHE_TYPES_H__ +#define __DNA_POINTCACHE_TYPES_H__ + +#include "DNA_defs.h" +#include "DNA_listBase.h" /* XXX only needed for deprecated PTCacheMem, remove once that is replaced */ + +/* XXX TODO point cache do_versions + * This needs to be updated until officially included in master + */ +#define PTCACHE_DO_VERSIONS(main) MAIN_VERSION_ATLEAST(main, 269, 6) + +/* Point cache file data types: + * - used as (1<<flag) so poke jahka if you reach the limit of 15 + * - to add new data types update: + * * BKE_ptcache_data_size() + * * ptcache_file_init_pointers() + */ +#define BPHYS_DATA_INDEX 0 +#define BPHYS_DATA_LOCATION 1 +#define BPHYS_DATA_SMOKE_LOW 1 +#define BPHYS_DATA_VELOCITY 2 +#define BPHYS_DATA_SMOKE_HIGH 2 +#define BPHYS_DATA_ROTATION 3 +#define BPHYS_DATA_DYNAMICPAINT 3 +#define BPHYS_DATA_AVELOCITY 4 /* used for particles */ +#define BPHYS_DATA_XCONST 4 /* used for cloth */ +#define BPHYS_DATA_SIZE 5 +#define BPHYS_DATA_TIMES 6 +#define BPHYS_DATA_BOIDS 7 + +#define BPHYS_TOT_DATA 8 + +#define BPHYS_EXTRA_FLUID_SPRINGS 1 + +typedef struct PTCacheExtra { + struct PTCacheExtra *next, *prev; + unsigned int type, totdata; + void *data; +} PTCacheExtra; + +typedef struct PTCacheMem { + struct PTCacheMem *next, *prev; + unsigned int frame, totpoint; + unsigned int data_types, flag; + + void *data[8]; /* BPHYS_TOT_DATA */ + void *cur[8]; /* BPHYS_TOT_DATA */ + + struct ListBase extradata; +} PTCacheMem; + +typedef struct PointCacheState { + int flag; + + int simframe; /* current frame of simulation (only if SIMULATION_VALID) */ + int last_exact; /* last exact frame that's cached */ + int last_valid; /* used for editing cache - what is the last baked frame */ + + /* for external cache files */ + int totpoint; /* number of cached points */ + int pad; + + char info[64]; + char *cached_frames; /* array of length endframe-startframe+1 with flags to indicate cached frames */ + /* can be later used for other per frame flags too if needed */ +} PointCacheState; + +typedef enum ePointCacheStateFlag { + PTC_STATE_OUTDATED = 1, + /* XXX remove BAKING flag! only used for overriding display percentage in particles + * to cache data with full particle amount. This should be based on some contextual info, + * not a flag in the cache state + */ + PTC_STATE_BAKING = 2, + PTC_STATE_FRAMES_SKIPPED = 4, + PTC_STATE_READ_INFO = 8, + PTC_STATE_REDO_NEEDED = PTC_STATE_OUTDATED | PTC_STATE_FRAMES_SKIPPED, + + /* high resolution cache is saved for smoke for backwards compatibility, so set this flag to know it's a "fake" cache */ + /* XXX compatibility flag, remove later */ + PTC_STATE_FAKE_SMOKE = (1<<16) +} ePointCacheStateFlag; + +typedef struct PointCache { + int flag; /* generic flag */ + + int step; /* The number of frames between cached frames. + * This should probably be an upper bound for a per point adaptive step in the future, + * buf for now it's the same for all points. Without adaptivity this can effect the perceived + * simulation quite a bit though. If for example particles are colliding with a horizontal + * plane (with high damping) they quickly come to a stop on the plane, however there are still + * forces acting on the particle (gravity and collisions), so the particle velocity isn't necessarily + * zero for the whole duration of the frame even if the particle seems stationary. If all simulation + * frames aren't cached (step > 1) these velocities are interpolated into movement for the non-cached + * frames. The result will look like the point is oscillating around the collision location. So for + * now cache step should be set to 1 for accurate reproduction of collisions. + */ + + int startframe; /* simulation start frame */ + int endframe; /* simulation end frame */ + int editframe; /* frame being edited (runtime only) */ + + /* for external cache files */ + int index; /* modifier stack index */ + short compression, rt; + int pad; + + char name[64]; + char prev_name[64]; + char path[1024]; /* file path, 1024 = FILE_MAX */ + + PointCacheState state; + + struct PTCacheEdit *edit; + void (*free_edit)(struct PTCacheEdit *edit); /* free callback */ + + /**** NEW POINTCACHE ****/ + char cachedir[768]; /* FILE_MAXDIR length */ +} PointCache; + +typedef enum ePointCacheFlag { + PTC_EXTERNAL = 1, + /* don't use the filename of the blendfile the data is linked from (write a local cache) */ + PTC_IGNORE_LIBPATH = 2, + PTC_IGNORE_CLEAR = 4, + /* lock the simulation settings and use the cache read-only + * XXX this should perhaps be moved out of the cache entirely, + * but for now provides a flag for keeping UI functionality + */ + PTC_LOCK_SETTINGS = 8 +} ePointCacheFlag; + +typedef enum ePointCacheCompression { + PTC_COMPRESS_NO = 0, + PTC_COMPRESS_LZO = 1, + PTC_COMPRESS_LZMA = 2 +} ePointCacheCompression; + +/* pointcache->flag */ +#define _PTCACHE_BAKED_DEPRECATED 1 +#define _PTCACHE_OUTDATED_DEPRECATED 2 +#define _PTCACHE_SIMULATION_VALID_DEPRECATED 4 +#define _PTCACHE_BAKING_DEPRECATED 8 +//#define PTCACHE_BAKE_EDIT 16 +//#define PTCACHE_BAKE_EDIT_ACTIVE 32 +//#define PTCACHE_DISK_CACHE 64 /* DEPRECATED all caches are disk-based now (with optional packing in blend files) */ +//#define PTCACHE_QUICK_CACHE 128 /* removed since 2.64 - [#30974], could be added back in a more useful way */ +#define _PTCACHE_FRAMES_SKIPPED_DEPRECATED 256 +#define _PTCACHE_EXTERNAL_DEPRECATED 512 +#define _PTCACHE_READ_INFO_DEPRECATED 1024 +/* don't use the filename of the blendfile the data is linked from (write a local cache) */ +#define _PTCACHE_IGNORE_LIBPATH_DEPRECATED 2048 +/* high resolution cache is saved for smoke for backwards compatibility, so set this flag to know it's a "fake" cache */ +#define _PTCACHE_FAKE_SMOKE_DEPRECATED (1<<12) +#define _PTCACHE_IGNORE_CLEAR_DEPRECATED (1<<13) + +/* PTCACHE_OUTDATED + PTCACHE_FRAMES_SKIPPED */ +#define _PTCACHE_REDO_NEEDED_DEPRECATED 258 + +#endif + diff --git a/source/blender/makesdna/DNA_rigidbody_types.h b/source/blender/makesdna/DNA_rigidbody_types.h index 5d76ffe57b5..ce4001fc7eb 100644 --- a/source/blender/makesdna/DNA_rigidbody_types.h +++ b/source/blender/makesdna/DNA_rigidbody_types.h @@ -33,6 +33,7 @@ #ifndef __DNA_RIGIDBODY_TYPES_H__ #define __DNA_RIGIDBODY_TYPES_H__ +#include "DNA_defs.h" #include "DNA_listBase.h" struct Group; @@ -60,7 +61,7 @@ typedef struct RigidBodyWorld { /* cache */ struct PointCache *pointcache; - struct ListBase ptcaches; + struct ListBase ptcaches DNA_DEPRECATED; int numbodies; /* number of objects in rigid body group */ short steps_per_second; /* number of simulation steps thaken per second */ diff --git a/source/blender/makesdna/DNA_smoke_types.h b/source/blender/makesdna/DNA_smoke_types.h index 25c98b4f07e..6cf34f7619a 100644 --- a/source/blender/makesdna/DNA_smoke_types.h +++ b/source/blender/makesdna/DNA_smoke_types.h @@ -32,6 +32,8 @@ #ifndef __DNA_SMOKE_TYPES_H__ #define __DNA_SMOKE_TYPES_H__ +#include "DNA_defs.h" + /* flags */ enum { MOD_SMOKE_HIGHRES = (1 << 1), /* enable high resolution */ @@ -136,7 +138,7 @@ typedef struct SmokeDomainSettings { /* Smoke uses only one cache from now on (index [0]), but keeping the array for now for reading old files. */ struct PointCache *point_cache[2]; /* definition is in DNA_object_force.h */ - struct ListBase ptcaches[2]; + struct ListBase ptcaches[2] DNA_DEPRECATED; struct EffectorWeights *effector_weights; int border_collisions; /* How domain border collisions are handled */ float time_scale; diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index ca8f56289ca..5f5714ec831 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -90,6 +90,7 @@ static const char *includefiles[] = { "DNA_object_types.h", "DNA_object_force.h", "DNA_object_fluidsim.h", + "DNA_pointcache_types.h", "DNA_world_types.h", "DNA_scene_types.h", "DNA_view3d_types.h", @@ -1286,4 +1287,5 @@ int main(int argc, char **argv) #include "DNA_rigidbody_types.h" #include "DNA_freestyle_types.h" #include "DNA_linestyle_types.h" +#include "DNA_pointcache_types.h" /* end of list */ diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 6167164a7ac..3e1a029567d 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -449,6 +449,7 @@ extern StructRNA RNA_ParticleSystemModifier; extern StructRNA RNA_ParticleTarget; extern StructRNA RNA_PivotConstraint; extern StructRNA RNA_PointCache; +extern StructRNA RNA_PointCacheModifier; extern StructRNA RNA_PointDensity; extern StructRNA RNA_PointDensityTexture; extern StructRNA RNA_PointLamp; diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript index 0d215fbcf81..2600f55bbc6 100644 --- a/source/blender/makesrna/SConscript +++ b/source/blender/makesrna/SConscript @@ -53,6 +53,7 @@ incs = [ '../imbuf', '../makesdna', '../nodes', + '../pointcache', '../render/extern/include', '../windowmanager', ] diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index e64743c5536..c6c5b54f989 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -70,6 +70,7 @@ set(DEFSRC rna_object_force.c rna_packedfile.c rna_particle.c + rna_pointcache.c rna_pose.c rna_property.c rna_render.c @@ -280,6 +281,10 @@ if(WITH_FREESTYLE) add_definitions(-DWITH_FREESTYLE) endif() +if(WITH_ALEMBIC) + add_definitions(-DWITH_ALEMBIC) +endif() + # Build makesrna executable blender_include_dirs( . @@ -293,6 +298,7 @@ blender_include_dirs( ../../ikplugin ../../makesdna ../../nodes/ + ../../pointcache/ ../../windowmanager ../../editors/include ../../render/extern/include diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript index 28151fe5db1..7ff671a0e9b 100644 --- a/source/blender/makesrna/intern/SConscript +++ b/source/blender/makesrna/intern/SConscript @@ -72,6 +72,7 @@ incs = [ '../../imbuf', '../../makesdna', '../../makesrna', + '../../pointcache', '../../render/extern/include', '../../windowmanager', ] diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 92a509d4d56..0c1701f6089 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -3310,6 +3310,7 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_object_force.c", NULL, RNA_def_object_force}, {"rna_packedfile.c", NULL, RNA_def_packedfile}, {"rna_particle.c", NULL, RNA_def_particle}, + {"rna_pointcache.c", NULL, RNA_def_pointcache}, {"rna_pose.c", "rna_pose_api.c", RNA_def_pose}, {"rna_property.c", NULL, RNA_def_gameproperty}, {"rna_render.c", NULL, RNA_def_render}, diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c index 01feb3cb748..5e2bee12c00 100644 --- a/source/blender/makesrna/intern/rna_fluidsim.c +++ b/source/blender/makesrna/intern/rna_fluidsim.c @@ -141,7 +141,7 @@ static void rna_FluidSettings_update_type(Main *bmain, Scene *scene, PointerRNA part->type = PART_FLUID; psys->part = part; - psys->pointcache = BKE_ptcache_add(&psys->ptcaches); + psys->pointcache = BKE_ptcache_new(); BLI_strncpy(psys->name, "FluidParticles", sizeof(psys->name)); BLI_addtail(&ob->particlesystem, psys); diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 64a50d42144..2c00b70d1a9 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -165,6 +165,7 @@ void RNA_def_object(struct BlenderRNA *brna); void RNA_def_object_force(struct BlenderRNA *brna); void RNA_def_packedfile(struct BlenderRNA *brna); void RNA_def_particle(struct BlenderRNA *brna); +void RNA_def_pointcache(struct BlenderRNA *brna); void RNA_def_pose(struct BlenderRNA *brna); void RNA_def_render(struct BlenderRNA *brna); void RNA_def_rigidbody(struct BlenderRNA *brna); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index c412fd460b3..d8d27a06bb5 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -64,6 +64,7 @@ EnumPropertyItem modifier_type_items[] = { {0, "", 0, N_("Modify"), ""}, {eModifierType_DataTransfer, "DATA_TRANSFER", ICON_MOD_DATA_TRANSFER, "Data Transfer", ""}, {eModifierType_MeshCache, "MESH_CACHE", ICON_MOD_MESHDEFORM, "Mesh Cache", ""}, + {eModifierType_PointCache, "POINT_CACHE", ICON_MOD_MESHDEFORM, "Point Cache", ""}, {eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""}, {eModifierType_UVWarp, "UV_WARP", ICON_MOD_UVPROJECT, "UV Warp", ""}, {eModifierType_WeightVGEdit, "VERTEX_WEIGHT_EDIT", ICON_MOD_VERTEX_WEIGHT, "Vertex Weight Edit", ""}, @@ -357,6 +358,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr) return &RNA_WireframeModifier; case eModifierType_DataTransfer: return &RNA_DataTransferModifier; + case eModifierType_PointCache: + return &RNA_PointCacheModifier; /* Default */ case eModifierType_None: case eModifierType_ShapeKey: @@ -4317,6 +4320,23 @@ static void rna_def_modifier_datatransfer(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); } +static void rna_def_modifier_pointcache(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "PointCacheModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Point Cache Modifier", "Write and Read mesh results to/from point cache"); + RNA_def_struct_sdna(srna, "PointCacheModifierData"); + RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); /* XXX, needs own icon */ + + prop = RNA_def_property(srna, "point_cache", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "point_cache"); + RNA_def_property_struct_type(prop, "PointCache"); + RNA_def_property_ui_text(prop, "Point Cache", ""); +} + void RNA_def_modifier(BlenderRNA *brna) { StructRNA *srna; @@ -4431,6 +4451,7 @@ void RNA_def_modifier(BlenderRNA *brna) rna_def_modifier_laplaciandeform(brna); rna_def_modifier_wireframe(brna); rna_def_modifier_datatransfer(brna); + rna_def_modifier_pointcache(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index cd28c608667..6170d33cced 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -100,221 +100,6 @@ static EnumPropertyItem empty_vortex_shape_items[] = { #include "ED_object.h" -static void rna_Cache_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -{ - Object *ob = (Object *)ptr->id.data; - PointCache *cache = (PointCache *)ptr->data; - PTCacheID *pid = NULL; - ListBase pidlist; - - if (!ob) - return; - - cache->flag |= PTCACHE_OUTDATED; - - BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); - - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - - for (pid = pidlist.first; pid; pid = pid->next) { - if (pid->cache == cache) - break; - } - - if (pid) { - /* Just make sure this wasn't changed. */ - if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) - cache->step = 1; - BKE_ptcache_update_info(pid); - } - - BLI_freelistN(&pidlist); -} - -static void rna_Cache_toggle_disk_cache(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -{ - Object *ob = (Object *)ptr->id.data; - PointCache *cache = (PointCache *)ptr->data; - PTCacheID *pid = NULL; - ListBase pidlist; - - if (!ob) - return; - - BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); - - for (pid = pidlist.first; pid; pid = pid->next) { - if (pid->cache == cache) - break; - } - - /* smoke can only use disk cache */ - if (pid && pid->type != PTCACHE_TYPE_SMOKE_DOMAIN) - BKE_ptcache_toggle_disk_cache(pid); - else - cache->flag ^= PTCACHE_DISK_CACHE; - - BLI_freelistN(&pidlist); -} - -static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) -{ - Object *ob = (Object *)ptr->id.data; - PointCache *cache = (PointCache *)ptr->data; - PTCacheID *pid = NULL, *pid2 = NULL; - ListBase pidlist; - int new_name = 1; - - if (!ob) - return; - - /* TODO: check for proper characters */ - - BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); - - if (cache->flag & PTCACHE_EXTERNAL) { - for (pid = pidlist.first; pid; pid = pid->next) { - if (pid->cache == cache) - break; - } - - if (!pid) - return; - - BKE_ptcache_load_external(pid); - - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); - WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, ob); - } - else { - for (pid = pidlist.first; pid; pid = pid->next) { - if (pid->cache == cache) - pid2 = pid; - else if (cache->name[0] != '\0' && strcmp(cache->name, pid->cache->name) == 0) { - /*TODO: report "name exists" to user */ - BLI_strncpy(cache->name, cache->prev_name, sizeof(cache->name)); - new_name = 0; - } - } - - if (new_name) { - if (pid2 && cache->flag & PTCACHE_DISK_CACHE) { - char old_name[80]; - char new_name[80]; - - BLI_strncpy(old_name, cache->prev_name, sizeof(old_name)); - BLI_strncpy(new_name, cache->name, sizeof(new_name)); - - BKE_ptcache_disk_cache_rename(pid2, old_name, new_name); - } - - BLI_strncpy(cache->prev_name, cache->name, sizeof(cache->prev_name)); - } - } - - BLI_freelistN(&pidlist); -} - -static void rna_Cache_list_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) -{ - PointCache *cache = ptr->data; - ListBase lb; - - while (cache->prev) - cache = cache->prev; - - lb.first = cache; - lb.last = NULL; /* not used by listbase_begin */ - - rna_iterator_listbase_begin(iter, &lb, NULL); -} -static void rna_Cache_active_point_cache_index_range(PointerRNA *ptr, int *min, int *max, - int *UNUSED(softmin), int *UNUSED(softmax)) -{ - Object *ob = ptr->id.data; - PointCache *cache = ptr->data; - PTCacheID *pid; - ListBase pidlist; - - BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); - - *min = 0; - *max = 0; - - for (pid = pidlist.first; pid; pid = pid->next) { - if (pid->cache == cache) { - *max = max_ii(0, BLI_listbase_count(pid->ptcaches) - 1); - break; - } - } - - BLI_freelistN(&pidlist); -} - -static int rna_Cache_active_point_cache_index_get(PointerRNA *ptr) -{ - Object *ob = ptr->id.data; - PointCache *cache = ptr->data; - PTCacheID *pid; - ListBase pidlist; - int num = 0; - - BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); - - for (pid = pidlist.first; pid; pid = pid->next) { - if (pid->cache == cache) { - num = BLI_findindex(pid->ptcaches, cache); - break; - } - } - - BLI_freelistN(&pidlist); - - return num; -} - -static void rna_Cache_active_point_cache_index_set(struct PointerRNA *ptr, int value) -{ - Object *ob = ptr->id.data; - PointCache *cache = ptr->data; - PTCacheID *pid; - ListBase pidlist; - - BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); - - for (pid = pidlist.first; pid; pid = pid->next) { - if (pid->cache == cache) { - *(pid->cache_ptr) = BLI_findlink(pid->ptcaches, value); - break; - } - } - - BLI_freelistN(&pidlist); -} - -static void rna_PointCache_frame_step_range(PointerRNA *ptr, int *min, int *max, - int *UNUSED(softmin), int *UNUSED(softmax)) -{ - Object *ob = ptr->id.data; - PointCache *cache = ptr->data; - PTCacheID *pid; - ListBase pidlist; - - *min = 1; - *max = 20; - - BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); - - for (pid = pidlist.first; pid; pid = pid->next) { - if (pid->cache == cache) { - *max = pid->max_step; - break; - } - } - - BLI_freelistN(&pidlist); -} - static char *rna_CollisionSettings_path(PointerRNA *UNUSED(ptr)) { /* both methods work ok, but return the shorter path */ @@ -760,140 +545,6 @@ static EnumPropertyItem *rna_Effector_shape_itemf(bContext *UNUSED(C), PointerRN #else -/* ptcache.point_caches */ -static void rna_def_ptcache_point_caches(BlenderRNA *brna, PropertyRNA *cprop) -{ - StructRNA *srna; - PropertyRNA *prop; - - /* FunctionRNA *func; */ - /* PropertyRNA *parm; */ - - RNA_def_property_srna(cprop, "PointCaches"); - srna = RNA_def_struct(brna, "PointCaches", NULL); - RNA_def_struct_sdna(srna, "PointCache"); - RNA_def_struct_ui_text(srna, "Point Caches", "Collection of point caches"); - - prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED); - RNA_def_property_int_funcs(prop, "rna_Cache_active_point_cache_index_get", - "rna_Cache_active_point_cache_index_set", - "rna_Cache_active_point_cache_index_range"); - RNA_def_property_ui_text(prop, "Active Point Cache Index", ""); - RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change"); -} - -static void rna_def_pointcache(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - - static EnumPropertyItem point_cache_compress_items[] = { - {PTCACHE_COMPRESS_NO, "NO", 0, "No", "No compression"}, - {PTCACHE_COMPRESS_LZO, "LIGHT", 0, "Light", "Fast but not so effective compression"}, - {PTCACHE_COMPRESS_LZMA, "HEAVY", 0, "Heavy", "Effective but slow compression"}, - {0, NULL, 0, NULL, NULL} - }; - - srna = RNA_def_struct(brna, "PointCache", NULL); - RNA_def_struct_ui_text(srna, "Point Cache", "Point cache for physics simulations"); - RNA_def_struct_ui_icon(srna, ICON_PHYSICS); - - prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME); - RNA_def_property_int_sdna(prop, NULL, "startframe"); - RNA_def_property_range(prop, -MAXFRAME, MAXFRAME); - RNA_def_property_ui_range(prop, 1, MAXFRAME, 1, 1); - RNA_def_property_ui_text(prop, "Start", "Frame on which the simulation starts"); - - prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_TIME); - RNA_def_property_int_sdna(prop, NULL, "endframe"); - RNA_def_property_range(prop, 1, MAXFRAME); - RNA_def_property_ui_text(prop, "End", "Frame on which the simulation stops"); - - prop = RNA_def_property(srna, "frame_step", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "step"); - RNA_def_property_range(prop, 1, 20); - RNA_def_property_int_funcs(prop, NULL, NULL, "rna_PointCache_frame_step_range"); - RNA_def_property_ui_text(prop, "Cache Step", "Number of frames between cached frames"); - RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change"); - - prop = RNA_def_property(srna, "index", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "index"); - RNA_def_property_range(prop, -1, 100); - RNA_def_property_ui_text(prop, "Cache Index", "Index number of cache files"); - RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change"); - - prop = RNA_def_property(srna, "compression", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, point_cache_compress_items); - RNA_def_property_ui_text(prop, "Cache Compression", "Compression method to be used"); - - /* flags */ - prop = RNA_def_property(srna, "is_baked", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_BAKED); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - - prop = RNA_def_property(srna, "is_baking", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_BAKING); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - - prop = RNA_def_property(srna, "use_disk_cache", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_DISK_CACHE); - RNA_def_property_ui_text(prop, "Disk Cache", "Save cache files to disk (.blend file must be saved first)"); - RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_toggle_disk_cache"); - - prop = RNA_def_property(srna, "is_outdated", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_OUTDATED); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Cache is outdated", ""); - - prop = RNA_def_property(srna, "frames_skipped", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_FRAMES_SKIPPED); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - - prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "name"); - RNA_def_property_ui_text(prop, "Name", "Cache name"); - RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change"); - RNA_def_struct_name_property(srna, prop); - - prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_DIRPATH); - RNA_def_property_string_sdna(prop, NULL, "path"); - RNA_def_property_ui_text(prop, "File Path", "Cache file path"); - RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change"); - - /* removed, see PTCACHE_QUICK_CACHE */ -#if 0 - prop = RNA_def_property(srna, "use_quick_cache", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_QUICK_CACHE); - RNA_def_property_ui_text(prop, "Quick Cache", "Update simulation with cache steps"); - RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change"); -#endif - - prop = RNA_def_property(srna, "info", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "info"); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Cache Info", "Info on current cache status"); - - prop = RNA_def_property(srna, "use_external", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_EXTERNAL); - RNA_def_property_ui_text(prop, "External", "Read cache from an external location"); - RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change"); - - prop = RNA_def_property(srna, "use_library_path", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", PTCACHE_IGNORE_LIBPATH); - RNA_def_property_ui_text(prop, "Library Path", - "Use this file's path for the disk cache when library linked into another file " - "(for local bakes per scene file, disable this option)"); - RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change"); - - prop = RNA_def_property(srna, "point_caches", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_funcs(prop, "rna_Cache_list_begin", "rna_iterator_listbase_next", - "rna_iterator_listbase_end", "rna_iterator_listbase_get", - NULL, NULL, NULL, NULL); - RNA_def_property_struct_type(prop, "PointCache"); - RNA_def_property_ui_text(prop, "Point Cache List", "Point cache list"); - rna_def_ptcache_point_caches(brna, prop); -} - static void rna_def_collision(BlenderRNA *brna) { StructRNA *srna; @@ -1865,7 +1516,6 @@ static void rna_def_softbody(BlenderRNA *brna) void RNA_def_object_force(BlenderRNA *brna) { - rna_def_pointcache(brna); rna_def_collision(brna); rna_def_effector_weight(brna); rna_def_field(brna); diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index dd32bb189e2..5c5f0c1ec36 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -978,12 +978,6 @@ static char *rna_SPHFluidSettings_path(PointerRNA *ptr) return NULL; } -static int rna_ParticleSystem_multiple_caches_get(PointerRNA *ptr) -{ - ParticleSystem *psys = (ParticleSystem *)ptr->data; - - return (psys->ptcaches.first != psys->ptcaches.last); -} static int rna_ParticleSystem_editable_get(PointerRNA *ptr) { ParticleSystem *psys = (ParticleSystem *)ptr->data; @@ -3349,11 +3343,6 @@ static void rna_def_particle_system(BlenderRNA *brna) RNA_def_property_struct_type(prop, "PointCache"); RNA_def_property_ui_text(prop, "Point Cache", ""); - prop = RNA_def_property(srna, "has_multiple_caches", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_funcs(prop, "rna_ParticleSystem_multiple_caches_get", NULL); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Multiple Caches", "Particle system has multiple point caches"); - /* offset ob */ prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "parent"); diff --git a/source/blender/makesrna/intern/rna_pointcache.c b/source/blender/makesrna/intern/rna_pointcache.c new file mode 100644 index 00000000000..6422013f469 --- /dev/null +++ b/source/blender/makesrna/intern/rna_pointcache.c @@ -0,0 +1,294 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/makesrna/intern/rna_pointcache.c + * \ingroup RNA + */ + +/* XXX hack, remove later */ +#define POINTCACHE_OLD + +#include "DNA_object_force.h" +#include "DNA_pointcache_types.h" +#include "DNA_scene_types.h" + +#include "RNA_define.h" +#include "RNA_types.h" + +#include "rna_internal.h" + +#include "PTC_api.h" + +#include "WM_api.h" +#include "WM_types.h" + +#ifdef RNA_RUNTIME + +#ifdef POINTCACHE_OLD +#include "BLI_math_base.h" + +#include "DNA_object_types.h" + +#include "BKE_depsgraph.h" +#include "BKE_pointcache.h" + +static void rna_Cache_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + Object *ob = (Object *)ptr->id.data; + PointCache *cache = (PointCache *)ptr->data; + PTCacheID *pid = NULL; + ListBase pidlist; + + if (!ob) + return; + + cache->state.flag |= PTC_STATE_OUTDATED; + + BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); + + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + + for (pid = pidlist.first; pid; pid = pid->next) { + if (pid->cache == cache) + break; + } + + if (pid) { + /* Just make sure this wasn't changed. */ + if (pid->type == PTCACHE_TYPE_SMOKE_DOMAIN) + cache->step = 1; + BKE_ptcache_update_info(pid); + } + + BLI_freelistN(&pidlist); +} + +static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + Object *ob = (Object *)ptr->id.data; + PointCache *cache = (PointCache *)ptr->data; + PTCacheID *pid = NULL, *pid2 = NULL; + ListBase pidlist; + int new_name = 1; + + if (!ob) + return; + + /* TODO: check for proper characters */ + + BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); + + if (cache->flag & PTC_EXTERNAL) { + for (pid = pidlist.first; pid; pid = pid->next) { + if (pid->cache == cache) + break; + } + + if (!pid) + return; + + BKE_ptcache_load_external(pid); + + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_main_add_notifier(NC_OBJECT | ND_POINTCACHE, ob); + } + else { + for (pid = pidlist.first; pid; pid = pid->next) { + if (pid->cache == cache) + pid2 = pid; + else if (cache->name[0] != '\0' && strcmp(cache->name, pid->cache->name) == 0) { + /*TODO: report "name exists" to user */ + BLI_strncpy(cache->name, cache->prev_name, sizeof(cache->name)); + new_name = 0; + } + } + + if (new_name) { + if (pid2) { + char old_name[80]; + char new_name[80]; + + BLI_strncpy(old_name, cache->prev_name, sizeof(old_name)); + BLI_strncpy(new_name, cache->name, sizeof(new_name)); + + BKE_ptcache_disk_cache_rename(pid2, old_name, new_name); + } + + BLI_strncpy(cache->prev_name, cache->name, sizeof(cache->prev_name)); + } + } + + BLI_freelistN(&pidlist); +} + +static void rna_PointCache_frame_step_range(PointerRNA *ptr, int *min, int *max, + int *UNUSED(softmin), int *UNUSED(softmax)) +{ + Object *ob = ptr->id.data; + PointCache *cache = ptr->data; + PTCacheID *pid; + ListBase pidlist; + + *min = 1; + *max = 20; + + BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0); + + for (pid = pidlist.first; pid; pid = pid->next) { + if (pid->cache == cache) { + *max = pid->max_step; + break; + } + } + + BLI_freelistN(&pidlist); +} +#endif /*POINTCACHE_OLD*/ + +#else + +static void rna_def_pointcache_state(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "PointCacheState", NULL); + RNA_def_struct_ui_text(srna, "Point Cache State", "State information about point cache data"); + RNA_def_struct_ui_icon(srna, ICON_PHYSICS); + + prop = RNA_def_property(srna, "is_baking", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PTC_STATE_BAKING); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "is_outdated", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PTC_STATE_OUTDATED); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Cache is outdated", ""); + + prop = RNA_def_property(srna, "frames_skipped", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PTC_STATE_FRAMES_SKIPPED); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + prop = RNA_def_property(srna, "info", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "info"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Cache Info", "Info on current cache status"); +} + +static void rna_def_pointcache(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + +#ifdef POINTCACHE_OLD + static EnumPropertyItem point_cache_compress_items[] = { + {PTC_COMPRESS_NO, "NO", 0, "No", "No compression"}, + {PTC_COMPRESS_LZO, "LIGHT", 0, "Light", "Fast but not so effective compression"}, + {PTC_COMPRESS_LZMA, "HEAVY", 0, "Heavy", "Effective but slow compression"}, + {0, NULL, 0, NULL, NULL} + }; +#endif /*POINTCACHE_OLD*/ + + srna = RNA_def_struct(brna, "PointCache", NULL); + RNA_def_struct_ui_text(srna, "Point Cache", "Point cache for physics simulations"); + RNA_def_struct_ui_icon(srna, ICON_PHYSICS); + +#ifdef POINTCACHE_OLD + prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME); + RNA_def_property_int_sdna(prop, NULL, "startframe"); + RNA_def_property_range(prop, -MAXFRAME, MAXFRAME); + RNA_def_property_ui_range(prop, 1, MAXFRAME, 1, 1); + RNA_def_property_ui_text(prop, "Start", "Frame on which the simulation starts"); + + prop = RNA_def_property(srna, "frame_end", PROP_INT, PROP_TIME); + RNA_def_property_int_sdna(prop, NULL, "endframe"); + RNA_def_property_range(prop, 1, MAXFRAME); + RNA_def_property_ui_text(prop, "End", "Frame on which the simulation stops"); + + prop = RNA_def_property(srna, "frame_step", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "step"); + RNA_def_property_range(prop, 1, 20); + RNA_def_property_int_funcs(prop, NULL, NULL, "rna_PointCache_frame_step_range"); + RNA_def_property_ui_text(prop, "Cache Step", "Number of frames between cached frames"); + RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change"); + + prop = RNA_def_property(srna, "index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "index"); + RNA_def_property_range(prop, -1, 100); + RNA_def_property_ui_text(prop, "Cache Index", "Index number of cache files"); + RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change"); + + prop = RNA_def_property(srna, "compression", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, point_cache_compress_items); + RNA_def_property_ui_text(prop, "Cache Compression", "Compression method to be used"); + + /* flags */ + prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "name"); + RNA_def_property_ui_text(prop, "Name", "Cache name"); + RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change"); + RNA_def_struct_name_property(srna, prop); + + prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_DIRPATH); + RNA_def_property_string_sdna(prop, NULL, "path"); + RNA_def_property_ui_text(prop, "File Path", "Cache file path"); + RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change"); + + /* removed, see PTCACHE_QUICK_CACHE */ +#if 0 + prop = RNA_def_property(srna, "use_quick_cache", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PTCACHE_QUICK_CACHE); + RNA_def_property_ui_text(prop, "Quick Cache", "Update simulation with cache steps"); + RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_change"); +#endif + + prop = RNA_def_property(srna, "use_external", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PTC_EXTERNAL); + RNA_def_property_ui_text(prop, "External", "Read cache from an external location"); + RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change"); + + prop = RNA_def_property(srna, "use_library_path", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", PTC_IGNORE_LIBPATH); + RNA_def_property_ui_text(prop, "Library Path", + "Use this file's path for the disk cache when library linked into another file " + "(for local bakes per scene file, disable this option)"); + RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change"); +#endif /*POINTCACHE_OLD*/ + + prop = RNA_def_property(srna, "lock_settings", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", PTC_LOCK_SETTINGS); + RNA_def_property_ui_text(prop, "Lock", "Lock simulation settings to prevent overwriting the cache"); + + prop = RNA_def_property(srna, "state", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "PointCacheState"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "State", "State information about the point cache data"); +} + +void RNA_def_pointcache(BlenderRNA *brna) +{ + rna_def_pointcache_state(brna); + rna_def_pointcache(brna); +} + +#endif diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c index 55262a98b2e..7189fa260b4 100644 --- a/source/blender/makesrna/intern/rna_smoke.c +++ b/source/blender/makesrna/intern/rna_smoke.c @@ -41,6 +41,7 @@ #include "DNA_modifier_types.h" #include "DNA_object_force.h" #include "DNA_object_types.h" +#include "DNA_pointcache_types.h" #include "DNA_scene_types.h" #include "DNA_smoke_types.h" @@ -71,7 +72,7 @@ static void rna_Smoke_resetCache(Main *UNUSED(bmain), Scene *UNUSED(scene), Poin { SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data; if (settings->smd && settings->smd->domain) - settings->point_cache[0]->flag |= PTCACHE_OUTDATED; + settings->point_cache[0]->state.flag |= PTC_STATE_OUTDATED; DAG_id_tag_update(ptr->id.data, OB_RECALC_DATA); } @@ -92,7 +93,7 @@ static void rna_Smoke_reset_dependency(Main *bmain, Scene *scene, PointerRNA *pt smokeModifier_reset(settings->smd); if (settings->smd && settings->smd->domain) - settings->smd->domain->point_cache[0]->flag |= PTCACHE_OUTDATED; + settings->smd->domain->point_cache[0]->state.flag |= PTC_STATE_OUTDATED; rna_Smoke_dependency_update(bmain, scene, ptr); } diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index a93dc76a655..876a95d8d8c 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -33,6 +33,7 @@ set(INC ../makesdna ../makesrna ../bmesh + ../pointcache ../render/extern/include ../../../intern/elbeem/extern ../../../intern/guardedalloc @@ -76,6 +77,7 @@ set(SRC intern/MOD_ocean.c intern/MOD_particleinstance.c intern/MOD_particlesystem.c + intern/MOD_pointcache.c intern/MOD_remesh.c intern/MOD_screw.c intern/MOD_shapekey.c diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h index aceee441098..8edcb7e0380 100644 --- a/source/blender/modifiers/MOD_modifiertypes.h +++ b/source/blender/modifiers/MOD_modifiertypes.h @@ -82,6 +82,7 @@ extern ModifierTypeInfo modifierType_MeshCache; extern ModifierTypeInfo modifierType_LaplacianDeform; extern ModifierTypeInfo modifierType_Wireframe; extern ModifierTypeInfo modifierType_DataTransfer; +extern ModifierTypeInfo modifierType_PointCache; /* MOD_util.c */ void modifier_type_init(ModifierTypeInfo *types[]); diff --git a/source/blender/modifiers/SConscript b/source/blender/modifiers/SConscript index b4c8299250e..7087b59a017 100644 --- a/source/blender/modifiers/SConscript +++ b/source/blender/modifiers/SConscript @@ -44,6 +44,7 @@ incs = [ '../makesrna', '../blenkernel', '../gpu', + '../pointcache', env['BF_ZLIB_INC'], ] diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 1561fd1a981..11455a6461f 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -37,7 +37,9 @@ #include "DNA_cloth_types.h" #include "DNA_key_types.h" #include "DNA_scene_types.h" +#include "DNA_object_force.h" #include "DNA_object_types.h" +#include "DNA_pointcache_types.h" #include "MEM_guardedalloc.h" @@ -61,7 +63,7 @@ static void initData(ModifierData *md) clmd->sim_parms = MEM_callocN(sizeof(ClothSimSettings), "cloth sim parms"); clmd->coll_parms = MEM_callocN(sizeof(ClothCollSettings), "cloth coll parms"); - clmd->point_cache = BKE_ptcache_add(&clmd->ptcaches); + clmd->point_cache = BKE_ptcache_new(); /* check for alloc failing */ if (!clmd->sim_parms || !clmd->coll_parms || !clmd->point_cache) @@ -165,14 +167,14 @@ static void copyData(ModifierData *md, ModifierData *target) if (tclmd->coll_parms) MEM_freeN(tclmd->coll_parms); - BKE_ptcache_free_list(&tclmd->ptcaches); + BKE_ptcache_free(tclmd->point_cache); tclmd->point_cache = NULL; tclmd->sim_parms = MEM_dupallocN(clmd->sim_parms); if (clmd->sim_parms->effector_weights) tclmd->sim_parms->effector_weights = MEM_dupallocN(clmd->sim_parms->effector_weights); tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms); - tclmd->point_cache = BKE_ptcache_add(&tclmd->ptcaches); + tclmd->point_cache = BKE_ptcache_new(); tclmd->point_cache->step = 1; tclmd->clothObject = NULL; } @@ -200,7 +202,7 @@ static void freeData(ModifierData *md) if (clmd->coll_parms) MEM_freeN(clmd->coll_parms); - BKE_ptcache_free_list(&clmd->ptcaches); + BKE_ptcache_free(clmd->point_cache); clmd->point_cache = NULL; } } diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index 130e332ef69..491b3deef01 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -32,7 +32,9 @@ * \ingroup modifiers */ +#include "DNA_object_force.h" #include "DNA_object_types.h" +#include "DNA_pointcache_types.h" #include "DNA_meshdata_types.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index 768bed19102..56197bfcca8 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -257,7 +257,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); - if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) { + if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED)) { float min[3], max[3]; INIT_MINMAX(min, max); dm->getMinMax(dm, min, max); @@ -297,7 +297,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3]; /* get particle state */ - if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && + if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED)) && (pimd->flag & eParticleInstanceFlag_Path)) { float ran = 0.0f; diff --git a/source/blender/modifiers/intern/MOD_pointcache.c b/source/blender/modifiers/intern/MOD_pointcache.c new file mode 100644 index 00000000000..1b7ba001a4e --- /dev/null +++ b/source/blender/modifiers/intern/MOD_pointcache.c @@ -0,0 +1,171 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Lukas Toenne + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/modifiers/intern/MOD_pointcache.c + * \ingroup modifiers + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "BLI_utildefines.h" +#include "BLI_string.h" + +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BKE_cdderivedmesh.h" +#include "BKE_DerivedMesh.h" +#include "BKE_scene.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_main.h" +#include "BKE_pointcache.h" + +#include "PTC_api.h" + +#include "MEM_guardedalloc.h" + +#include "MOD_modifiertypes.h" + +#include "MOD_util.h" + +struct BMEditMesh; + +static void initData(ModifierData *md) +{ + PointCacheModifierData *pcmd = (PointCacheModifierData *)md; + + pcmd->flag = 0; + pcmd->point_cache = BKE_ptcache_new(); +} + +static void copyData(ModifierData *md, ModifierData *target) +{ + PointCacheModifierData *pcmd = (PointCacheModifierData *)md; + PointCacheModifierData *tpcmd = (PointCacheModifierData *)target; + + modifier_copyData_generic(md, target); + + tpcmd->point_cache = BKE_ptcache_copy(pcmd->point_cache, false); +} + +static void freeData(ModifierData *md) +{ + PointCacheModifierData *pcmd = (PointCacheModifierData *)md; + + if (pcmd->reader) + PTC_reader_free(pcmd->reader); + if (pcmd->writer) + PTC_writer_free(pcmd->writer); + + BKE_ptcache_free(pcmd->point_cache); +} + +static bool dependsOnTime(ModifierData *md) +{ + PointCacheModifierData *pcmd = (PointCacheModifierData *)md; + + /* considered time-dependent when reading from cache file */ + /* TODO check cache frame range here to optimize */ + return PTC_mod_point_cache_get_mode(pcmd) == MOD_POINTCACHE_MODE_READ; +} + +static DerivedMesh *pointcache_do(PointCacheModifierData *pcmd, Object *ob, DerivedMesh *dm) +{ + Scene *scene = pcmd->modifier.scene; + const float cfra = BKE_scene_frame_get(scene); + ePointCacheModifierMode mode = PTC_mod_point_cache_get_mode(pcmd); + + DerivedMesh *finaldm = dm; + + if (mode == MOD_POINTCACHE_MODE_NONE) { + mode = PTC_mod_point_cache_set_mode(scene, ob, pcmd, MOD_POINTCACHE_MODE_READ); + } + + if (mode == MOD_POINTCACHE_MODE_WRITE) { + pcmd->output_dm = dm; + PTC_write_sample(pcmd->writer); + pcmd->output_dm = NULL; + } + else if (mode == MOD_POINTCACHE_MODE_READ) { + if (PTC_read_sample(pcmd->reader, cfra) == PTC_READ_SAMPLE_INVALID) { + modifier_setError(&pcmd->modifier, "%s", "Cannot read cache file"); + } + else { + DerivedMesh *result = PTC_reader_point_cache_acquire_result(pcmd->reader); + if (result) + finaldm = result; + } + } + + return finaldm; +} + +static DerivedMesh *applyModifier(ModifierData *md, Object *ob, + DerivedMesh *dm, + ModifierApplyFlag UNUSED(flag)) +{ + PointCacheModifierData *pcmd = (PointCacheModifierData *)md; + + return pointcache_do(pcmd, ob, dm); +} + +static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob, + struct BMEditMesh *UNUSED(editData), + DerivedMesh *dm, + ModifierApplyFlag UNUSED(flag)) +{ + PointCacheModifierData *pcmd = (PointCacheModifierData *)md; + + return pointcache_do(pcmd, ob, dm); +} + +ModifierTypeInfo modifierType_PointCache = { + /* name */ "Point Cache", + /* structName */ "PointCacheModifierData", + /* structSize */ sizeof(PointCacheModifierData), + /* type */ eModifierTypeType_Constructive, + /* flags */ eModifierTypeFlag_AcceptsMesh | + eModifierTypeFlag_AcceptsCVs | + eModifierTypeFlag_SupportsEditmode, + + /* copyData */ copyData, + /* deformVerts */ NULL, + /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, + /* deformMatricesEM */ NULL, + /* applyModifier */ applyModifier, + /* applyModifierEM */ applyModifierEM, + /* initData */ initData, + /* requiredDataMask */ NULL, + /* freeData */ freeData, + /* isDisabled */ NULL, + /* updateDepgraph */ NULL, + /* dependsOnTime */ dependsOnTime, + /* dependsOnNormals */ NULL, + /* foreachObjectLink */ NULL, + /* foreachIDLink */ NULL, + /* foreachTexLink */ NULL, +}; diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index 62a7ddefdf3..228c42e526c 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -305,5 +305,6 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(LaplacianDeform); INIT_TYPE(Wireframe); INIT_TYPE(DataTransfer); + INIT_TYPE(PointCache); #undef INIT_TYPE } diff --git a/source/blender/pointcache/CMakeLists.txt b/source/blender/pointcache/CMakeLists.txt new file mode 100644 index 00000000000..eb03e26a210 --- /dev/null +++ b/source/blender/pointcache/CMakeLists.txt @@ -0,0 +1,87 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2013, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . + intern + util + ../blenkernel + ../blenlib + ../makesdna + ../makesrna + ../../../intern/guardedalloc +) + +set(INC_SYS + ${BOOST_INCLUDE_DIR} +) + +set(SRC + util/util_error_handler.h + util/util_error_handler.cpp + util/util_frame_mapper.h + util/util_frame_mapper.cpp + util/util_path.h + util/util_path.cpp + util/util_types.h + + PTC_api.h + PTC_api.cpp +) + +if(WITH_ALEMBIC) + list(APPEND INC_SYS + ${ALEMBIC_INCLUDE_DIRS} + ${OPENEXR_INCLUDE_DIR}/OpenEXR + ) + + list(APPEND SRC + intern/export.h + intern/export.cpp + intern/reader.h + intern/reader.cpp + intern/schema.h + intern/thread.h + intern/writer.h + intern/writer.cpp + + intern/particles.h + intern/particles.cpp + intern/cloth.h + intern/cloth.cpp + intern/dynamicpaint.h + intern/dynamicpaint.cpp + intern/mesh.h + intern/mesh.cpp + intern/rigidbody.h + intern/rigidbody.cpp + intern/softbody.h + intern/softbody.cpp + intern/smoke.h + intern/smoke.cpp + ) + + add_definitions(-DWITH_ALEMBIC) +endif() + +blender_add_lib(bf_pointcache "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/pointcache/PTC_api.cpp b/source/blender/pointcache/PTC_api.cpp new file mode 100644 index 00000000000..7f2a769cdc7 --- /dev/null +++ b/source/blender/pointcache/PTC_api.cpp @@ -0,0 +1,246 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "PTC_api.h" + +#ifdef WITH_ALEMBIC + +#include "util/util_error_handler.h" + +#include "reader.h" +#include "writer.h" +#include "export.h" + +extern "C" { +#include "BLI_math.h" + +#include "DNA_modifier_types.h" +#include "DNA_pointcache_types.h" + +#include "BKE_modifier.h" +#include "BKE_report.h" + +#include "RNA_access.h" +} + +using namespace PTC; + +void PTC_error_handler_std(void) +{ + ErrorHandler::clear_default_handler(); +} + +void PTC_error_handler_callback(PTCErrorCallback cb, void *userdata) +{ + ErrorHandler::set_default_handler(new CallbackErrorHandler(cb, userdata)); +} + +static ReportType report_type_from_error_level(PTCErrorLevel level) +{ + switch (level) { + case PTC_ERROR_NONE: return RPT_DEBUG; + case PTC_ERROR_INFO: return RPT_INFO; + case PTC_ERROR_WARNING: return RPT_WARNING; + case PTC_ERROR_CRITICAL: return RPT_ERROR; + } + return RPT_ERROR; +} + +static void error_handler_reports_cb(void *vreports, PTCErrorLevel level, const char *message) +{ + ReportList *reports = (ReportList *)vreports; + + BKE_report(reports, report_type_from_error_level(level), message); +} + +void PTC_error_handler_reports(struct ReportList *reports) +{ + ErrorHandler::set_default_handler(new CallbackErrorHandler(error_handler_reports_cb, reports)); +} + +static void error_handler_modifier_cb(void *vmd, PTCErrorLevel UNUSED(level), const char *message) +{ + ModifierData *md = (ModifierData *)vmd; + + modifier_setError(md, "%s", message); +} + +void PTC_error_handler_modifier(struct ModifierData *md) +{ + ErrorHandler::set_default_handler(new CallbackErrorHandler(error_handler_modifier_cb, md)); +} + + +void PTC_validate(PointCache *cache, int framenr) +{ + if (cache) { + cache->state.simframe = framenr; + } +} + +void PTC_invalidate(PointCache *cache) +{ + if (cache) { + cache->state.simframe = 0; + cache->state.last_exact = min_ii(cache->startframe, 0); + } +} + + +void PTC_writer_free(PTCWriter *_writer) +{ + PTC::Writer *writer = (PTC::Writer *)_writer; + delete writer; +} + +void PTC_write_sample(struct PTCWriter *_writer) +{ + PTC::Writer *writer = (PTC::Writer *)_writer; + writer->write_sample(); +} + +void PTC_bake(struct Main *bmain, struct Scene *scene, struct EvaluationContext *evalctx, struct PTCWriter *_writer, int start_frame, int end_frame, + short *stop, short *do_update, float *progress) +{ + PTC::Writer *writer = (PTC::Writer *)_writer; + PTC::Exporter exporter(bmain, scene, evalctx, stop, do_update, progress); + exporter.bake(writer, start_frame, end_frame); +} + + +void PTC_reader_free(PTCReader *_reader) +{ + PTC::Reader *reader = (PTC::Reader *)_reader; + delete reader; +} + +void PTC_reader_get_frame_range(PTCReader *_reader, int *start_frame, int *end_frame) +{ + PTC::Reader *reader = (PTC::Reader *)_reader; + int sfra, efra; + reader->get_frame_range(sfra, efra); + if (start_frame) *start_frame = sfra; + if (end_frame) *end_frame = efra; +} + +PTCReadSampleResult PTC_read_sample(PTCReader *_reader, float frame) +{ + PTC::Reader *reader = (PTC::Reader *)_reader; + return reader->read_sample(frame); +} + +PTCReadSampleResult PTC_test_sample(PTCReader *_reader, float frame) +{ + PTC::Reader *reader = (PTC::Reader *)_reader; + return reader->test_sample(frame); +} + +/* get writer/reader from RNA type */ +PTCWriter *PTC_writer_from_rna(Scene *scene, PointerRNA *ptr) +{ + if (RNA_struct_is_a(ptr->type, &RNA_ParticleSystem)) { + Object *ob = (Object *)ptr->id.data; + ParticleSystem *psys = (ParticleSystem *)ptr->data; + return PTC_writer_particles(scene, ob, psys); + } + if (RNA_struct_is_a(ptr->type, &RNA_ClothModifier)) { + Object *ob = (Object *)ptr->id.data; + ClothModifierData *clmd = (ClothModifierData *)ptr->data; + return PTC_writer_cloth(scene, ob, clmd); + } + if (RNA_struct_is_a(ptr->type, &RNA_SoftBodySettings)) { + Object *ob = (Object *)ptr->id.data; + SoftBody *softbody = (SoftBody *)ptr->data; + return PTC_writer_softbody(scene, ob, softbody); + } + if (RNA_struct_is_a(ptr->type, &RNA_RigidBodyWorld)) { + BLI_assert((Scene *)ptr->id.data == scene); + RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data; + return PTC_writer_rigidbody(scene, rbw); + } + if (RNA_struct_is_a(ptr->type, &RNA_SmokeDomainSettings)) { + Object *ob = (Object *)ptr->id.data; + SmokeDomainSettings *domain = (SmokeDomainSettings *)ptr->data; + return PTC_writer_smoke(scene, ob, domain); + } + if (RNA_struct_is_a(ptr->type, &RNA_DynamicPaintSurface)) { + Object *ob = (Object *)ptr->id.data; + DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data; + return PTC_writer_dynamicpaint(scene, ob, surface); + } +#if 0 /* modifier uses internal writer during scene update */ + if (RNA_struct_is_a(ptr->type, &RNA_PointCacheModifier)) { + Object *ob = (Object *)ptr->id.data; + PointCacheModifierData *pcmd = (PointCacheModifierData *)ptr->data; + return PTC_writer_point_cache(scene, ob, pcmd); + } +#endif + return NULL; +} + +PTCReader *PTC_reader_from_rna(Scene *scene, PointerRNA *ptr) +{ + if (RNA_struct_is_a(ptr->type, &RNA_ParticleSystem)) { + Object *ob = (Object *)ptr->id.data; + ParticleSystem *psys = (ParticleSystem *)ptr->data; + return PTC_reader_particles(scene, ob, psys); + } + if (RNA_struct_is_a(ptr->type, &RNA_ClothModifier)) { + Object *ob = (Object *)ptr->id.data; + ClothModifierData *clmd = (ClothModifierData *)ptr->data; + return PTC_reader_cloth(scene, ob, clmd); + } + if (RNA_struct_is_a(ptr->type, &RNA_SoftBodySettings)) { + Object *ob = (Object *)ptr->id.data; + SoftBody *softbody = (SoftBody *)ptr->data; + return PTC_reader_softbody(scene, ob, softbody); + } + if (RNA_struct_is_a(ptr->type, &RNA_RigidBodyWorld)) { + BLI_assert((Scene *)ptr->id.data == scene); + RigidBodyWorld *rbw = (RigidBodyWorld *)ptr->data; + return PTC_reader_rigidbody(scene, rbw); + } + if (RNA_struct_is_a(ptr->type, &RNA_SmokeDomainSettings)) { + Object *ob = (Object *)ptr->id.data; + SmokeDomainSettings *domain = (SmokeDomainSettings *)ptr->data; + return PTC_reader_smoke(scene, ob, domain); + } + if (RNA_struct_is_a(ptr->type, &RNA_DynamicPaintSurface)) { + Object *ob = (Object *)ptr->id.data; + DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data; + return PTC_reader_dynamicpaint(scene, ob, surface); + } + if (RNA_struct_is_a(ptr->type, &RNA_PointCacheModifier)) { + Object *ob = (Object *)ptr->id.data; + PointCacheModifierData *pcmd = (PointCacheModifierData *)ptr->data; + return PTC_reader_point_cache(scene, ob, pcmd); + } + return NULL; +} + +#else + +void PTC_writer_free(PTCWriter *_writer) +{ +} + +void PTC_write(struct PTCWriter *_writer) +{ +} + +#endif diff --git a/source/blender/pointcache/PTC_api.h b/source/blender/pointcache/PTC_api.h new file mode 100644 index 00000000000..5ea7cd8021d --- /dev/null +++ b/source/blender/pointcache/PTC_api.h @@ -0,0 +1,119 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_API_H +#define PTC_API_H + +#include "util/util_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Main; +struct Scene; +struct EvaluationContext; +struct PointCache; +struct PointerRNA; +struct ReportList; + +struct ClothModifierData; +struct DerivedMesh; +struct DynamicPaintSurface; +struct ModifierData; +struct Object; +struct ParticleSystem; +struct PointCacheModifierData; +struct RigidBodyWorld; +struct SmokeDomainSettings; +struct SoftBody; + +struct PTCWriter; +struct PTCReader; + +/*** Error Handling ***/ +void PTC_error_handler_std(void); +void PTC_error_handler_callback(PTCErrorCallback cb, void *userdata); +void PTC_error_handler_reports(struct ReportList *reports); +void PTC_error_handler_modifier(struct ModifierData *md); + +void PTC_validate(struct PointCache *cache, int framenr); +void PTC_invalidate(struct PointCache *cache); + +void PTC_bake(struct Main *bmain, struct Scene *scene, struct EvaluationContext *evalctx, struct PTCWriter *writer, int start_frame, int end_frame, + short *stop, short *do_update, float *progress); + +/*** Reader/Writer Interface ***/ + +void PTC_writer_free(struct PTCWriter *writer); +void PTC_write_sample(struct PTCWriter *writer); + +void PTC_reader_free(struct PTCReader *reader); +void PTC_reader_get_frame_range(struct PTCReader *reader, int *start_frame, int *end_frame); +PTCReadSampleResult PTC_read_sample(struct PTCReader *reader, float frame); +PTCReadSampleResult PTC_test_sample(struct PTCReader *reader, float frame); + +/* get writer/reader from RNA type */ +struct PTCWriter *PTC_writer_from_rna(struct Scene *scene, struct PointerRNA *ptr); +struct PTCReader *PTC_reader_from_rna(struct Scene *scene, struct PointerRNA *ptr); + +/* Particles */ +struct PTCWriter *PTC_writer_particles(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys); +struct PTCReader *PTC_reader_particles(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys); +int PTC_reader_particles_totpoint(struct PTCReader *reader); + +/* Cloth */ +struct PTCWriter *PTC_writer_cloth(struct Scene *scene, struct Object *ob, struct ClothModifierData *clmd); +struct PTCReader *PTC_reader_cloth(struct Scene *scene, struct Object *ob, struct ClothModifierData *clmd); + +/* SoftBody */ +struct PTCWriter *PTC_writer_softbody(struct Scene *scene, struct Object *ob, struct SoftBody *softbody); +struct PTCReader *PTC_reader_softbody(struct Scene *scene, struct Object *ob, struct SoftBody *softbody); + +/* Rigid Bodies */ +struct PTCWriter *PTC_writer_rigidbody(struct Scene *scene, struct RigidBodyWorld *rbw); +struct PTCReader *PTC_reader_rigidbody(struct Scene *scene, struct RigidBodyWorld *rbw); + +/* Smoke */ +struct PTCWriter *PTC_writer_smoke(struct Scene *scene, struct Object *ob, struct SmokeDomainSettings *domain); +struct PTCReader *PTC_reader_smoke(struct Scene *scene, struct Object *ob, struct SmokeDomainSettings *domain); + +/* Dynamic Paint */ +struct PTCWriter *PTC_writer_dynamicpaint(struct Scene *scene, struct Object *ob, struct DynamicPaintSurface *surface); +struct PTCReader *PTC_reader_dynamicpaint(struct Scene *scene, struct Object *ob, struct DynamicPaintSurface *surface); + +/* Modifier Stack */ +typedef enum ePointCacheModifierMode { + MOD_POINTCACHE_MODE_NONE, + MOD_POINTCACHE_MODE_READ, + MOD_POINTCACHE_MODE_WRITE, +} ePointCacheModifierMode; + +struct PTCWriter *PTC_writer_point_cache(struct Scene *scene, struct Object *ob, struct PointCacheModifierData *pcmd); +struct PTCReader *PTC_reader_point_cache(struct Scene *scene, struct Object *ob, struct PointCacheModifierData *pcmd); +struct DerivedMesh *PTC_reader_point_cache_acquire_result(struct PTCReader *reader); +void PTC_reader_point_cache_discard_result(struct PTCReader *reader); +ePointCacheModifierMode PTC_mod_point_cache_get_mode(struct PointCacheModifierData *pcmd); +/* returns the actual new mode, in case a change didn't succeed */ +ePointCacheModifierMode PTC_mod_point_cache_set_mode(struct Scene *scene, struct Object *ob, struct PointCacheModifierData *pcmd, ePointCacheModifierMode mode); + +#ifdef __cplusplus +} /* extern C */ +#endif + +#endif /* PTC_API_H */ diff --git a/source/blender/pointcache/SConscript b/source/blender/pointcache/SConscript new file mode 100644 index 00000000000..5da7209ba60 --- /dev/null +++ b/source/blender/pointcache/SConscript @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2014, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Lukas Toenne. +# +# ***** END GPL LICENSE BLOCK ***** + +Import ('env') + +sources = env.Glob('intern/*.cpp') + env.Glob('util/*.cpp') + env.Glob('*.cpp') + +incs = [ + '.', + 'intern', + 'util', + '../blenkernel', + '../blenlib', + '../makesdna', + '../makesrna', + '../../../intern/guardedalloc', + '/opt/lib/openexr/include/OpenEXR' + ] + +defs = [] + +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): + incs.append(env['BF_PTHREADS_INC']) + +if env['WITH_BF_ALEMBIC']: + incs.append(env['BF_OPENEXR_INC']) + incs.append(env['BF_ALEMBIC_INC']) + + defs.append('WITH_ALEMBIC') + +env.BlenderLib('bf_pointcache', sources, incs, defines=defs, libtype=['core'], priority=[900]) diff --git a/source/blender/pointcache/intern/cloth.cpp b/source/blender/pointcache/intern/cloth.cpp new file mode 100644 index 00000000000..4fbc23d8fa3 --- /dev/null +++ b/source/blender/pointcache/intern/cloth.cpp @@ -0,0 +1,86 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "cloth.h" + +extern "C" { +#include "DNA_object_types.h" +#include "DNA_modifier_types.h" +} + +#include "PTC_api.h" + +namespace PTC { + +using namespace Abc; +using namespace AbcGeom; + +ClothWriter::ClothWriter(Scene *scene, Object *ob, ClothModifierData *clmd) : + Writer(scene, &ob->id, clmd->point_cache), + m_ob(ob), + m_clmd(clmd) +{ + uint32_t fs = add_frame_sampling(); + + OObject root = m_archive.getTop(); +// m_points = OPoints(root, m_psys->name, fs); +} + +ClothWriter::~ClothWriter() +{ +} + +void ClothWriter::write_sample() +{ +} + + +ClothReader::ClothReader(Scene *scene, Object *ob, ClothModifierData *clmd) : + Reader(scene, &ob->id, clmd->point_cache), + m_ob(ob), + m_clmd(clmd) +{ + if (m_archive.valid()) { + IObject root = m_archive.getTop(); +// m_points = IPoints(root, m_psys->name); + } +} + +ClothReader::~ClothReader() +{ +} + +PTCReadSampleResult ClothReader::read_sample(float frame) +{ + return PTC_READ_SAMPLE_INVALID; +} + +} /* namespace PTC */ + + +/* ==== C API ==== */ + +PTCWriter *PTC_writer_cloth(Scene *scene, Object *ob, ClothModifierData *clmd) +{ + return (PTCWriter *)(new PTC::ClothWriter(scene, ob, clmd)); +} + +PTCReader *PTC_reader_cloth(Scene *scene, Object *ob, ClothModifierData *clmd) +{ + return (PTCReader *)(new PTC::ClothReader(scene, ob, clmd)); +} diff --git a/source/blender/pointcache/intern/cloth.h b/source/blender/pointcache/intern/cloth.h new file mode 100644 index 00000000000..89f2d42c106 --- /dev/null +++ b/source/blender/pointcache/intern/cloth.h @@ -0,0 +1,64 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_CLOTH_H +#define PTC_CLOTH_H + +//#include <Alembic/AbcGeom/IPoints.h> +//#include <Alembic/AbcGeom/OPoints.h> + +#include "reader.h" +#include "schema.h" +#include "writer.h" + +struct Object; +struct ClothModifierData; + +namespace PTC { + +class ClothWriter : public Writer { +public: + ClothWriter(Scene *scene, Object *ob, ClothModifierData *clmd); + ~ClothWriter(); + + void write_sample(); + +private: + Object *m_ob; + ClothModifierData *m_clmd; + +// AbcGeom::OPoints m_points; +}; + +class ClothReader : public Reader { +public: + ClothReader(Scene *scene, Object *ob, ClothModifierData *clmd); + ~ClothReader(); + + PTCReadSampleResult read_sample(float frame); + +private: + Object *m_ob; + ClothModifierData *m_clmd; + +// AbcGeom::IPoints m_points; +}; + +} /* namespace PTC */ + +#endif /* PTC_CLOTH_H */ diff --git a/source/blender/pointcache/intern/dynamicpaint.cpp b/source/blender/pointcache/intern/dynamicpaint.cpp new file mode 100644 index 00000000000..8422e7f1cc7 --- /dev/null +++ b/source/blender/pointcache/intern/dynamicpaint.cpp @@ -0,0 +1,86 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "dynamicpaint.h" + +extern "C" { +#include "DNA_object_types.h" +#include "DNA_dynamicpaint_types.h" +} + +#include "PTC_api.h" + +namespace PTC { + +using namespace Abc; +using namespace AbcGeom; + +DynamicPaintWriter::DynamicPaintWriter(Scene *scene, Object *ob, DynamicPaintSurface *surface) : + Writer(scene, &ob->id, surface->pointcache), + m_ob(ob), + m_surface(surface) +{ + uint32_t fs = add_frame_sampling(); + + OObject root = m_archive.getTop(); +// m_points = OPoints(root, m_psys->name, fs); +} + +DynamicPaintWriter::~DynamicPaintWriter() +{ +} + +void DynamicPaintWriter::write_sample() +{ +} + + +DynamicPaintReader::DynamicPaintReader(Scene *scene, Object *ob, DynamicPaintSurface *surface) : + Reader(scene, &ob->id, surface->pointcache), + m_ob(ob), + m_surface(surface) +{ + if (m_archive.valid()) { + IObject root = m_archive.getTop(); +// m_points = IPoints(root, m_psys->name); + } +} + +DynamicPaintReader::~DynamicPaintReader() +{ +} + +PTCReadSampleResult DynamicPaintReader::read_sample(float frame) +{ + return PTC_READ_SAMPLE_INVALID; +} + +} /* namespace PTC */ + + +/* ==== C API ==== */ + +PTCWriter *PTC_writer_dynamicpaint(Scene *scene, Object *ob, DynamicPaintSurface *surface) +{ + return (PTCWriter *)(new PTC::DynamicPaintWriter(scene, ob, surface)); +} + +PTCReader *PTC_reader_dynamicpaint(Scene *scene, Object *ob, DynamicPaintSurface *surface) +{ + return (PTCReader *)(new PTC::DynamicPaintReader(scene, ob, surface)); +} diff --git a/source/blender/pointcache/intern/dynamicpaint.h b/source/blender/pointcache/intern/dynamicpaint.h new file mode 100644 index 00000000000..6872ac0ddb3 --- /dev/null +++ b/source/blender/pointcache/intern/dynamicpaint.h @@ -0,0 +1,64 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_DYNAMICPAINT_H +#define PTC_DYNAMICPAINT_H + +//#include <Alembic/AbcGeom/IPoints.h> +//#include <Alembic/AbcGeom/OPoints.h> + +#include "reader.h" +#include "schema.h" +#include "writer.h" + +struct Object; +struct DynamicPaintSurface; + +namespace PTC { + +class DynamicPaintWriter : public Writer { +public: + DynamicPaintWriter(Scene *scene, Object *ob, DynamicPaintSurface *surface); + ~DynamicPaintWriter(); + + void write_sample(); + +private: + Object *m_ob; + DynamicPaintSurface *m_surface; + +// AbcGeom::OPoints m_points; +}; + +class DynamicPaintReader : public Reader { +public: + DynamicPaintReader(Scene *scene, Object *ob, DynamicPaintSurface *surface); + ~DynamicPaintReader(); + + PTCReadSampleResult read_sample(float frame); + +private: + Object *m_ob; + DynamicPaintSurface *m_surface; + +// AbcGeom::IPoints m_points; +}; + +} /* namespace PTC */ + +#endif /* PTC_DYNAMICPAINT_H */ diff --git a/source/blender/pointcache/intern/export.cpp b/source/blender/pointcache/intern/export.cpp new file mode 100644 index 00000000000..b7df49666a7 --- /dev/null +++ b/source/blender/pointcache/intern/export.cpp @@ -0,0 +1,76 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "export.h" +#include "writer.h" + +extern "C" { +#include "DNA_scene_types.h" + +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_scene.h" +} + +namespace PTC { + +Exporter::Exporter(Main *bmain, Scene *scene, EvaluationContext *evalctx, short *stop, short *do_update, float *progress) : + m_bmain(bmain), + m_scene(scene), + m_evalctx(evalctx), + m_stop(stop), + m_do_update(do_update), + m_progress(progress) +{ +} + +void Exporter::bake(Writer *writer, int start_frame, int end_frame) +{ +// thread_scoped_lock(m_mutex); + + set_progress(0.0f); + + for (int cfra = start_frame; cfra <= end_frame; ++cfra) { + m_scene->r.cfra = cfra; + BKE_scene_update_for_newframe(m_evalctx, m_bmain, m_scene, m_scene->lay); + + if (writer) + writer->write_sample(); + + set_progress((float)(cfra - start_frame + 1) / (float)(end_frame - start_frame + 1)); + + if (stop()) + break; + } +} + +bool Exporter::stop() const +{ + if (*m_stop) + return true; + + return (G.is_break); +} + +void Exporter::set_progress(float progress) +{ + *m_do_update = 1; + *m_progress = progress; +} + +} /* namespace PTC */ diff --git a/source/blender/pointcache/intern/export.h b/source/blender/pointcache/intern/export.h new file mode 100644 index 00000000000..34736b2e649 --- /dev/null +++ b/source/blender/pointcache/intern/export.h @@ -0,0 +1,57 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_EXPORT_H +#define PTC_EXPORT_H + +#include "thread.h" + +struct Main; +struct Scene; +struct EvaluationContext; + +namespace PTC { + +class Writer; + +class Exporter +{ +public: + Exporter(Main *bmain, Scene *scene, EvaluationContext *evalctx, short *stop, short *do_update, float *progress); + + void bake(Writer *writer, int start_frame, int end_frame); + + bool stop() const; + + void set_progress(float progress); + +private: + thread_mutex m_mutex; + + Main *m_bmain; + Scene *m_scene; + EvaluationContext *m_evalctx; + + short *m_stop; + short *m_do_update; + float *m_progress; +}; + +} /* namespace PTC */ + +#endif /* PTC_EXPORT_H */ diff --git a/source/blender/pointcache/intern/mesh.cpp b/source/blender/pointcache/intern/mesh.cpp new file mode 100644 index 00000000000..facf8e02bdd --- /dev/null +++ b/source/blender/pointcache/intern/mesh.cpp @@ -0,0 +1,674 @@ +/* + * Copyright 2014, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mesh.h" + +extern "C" { +#include "BLI_math.h" + +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" + +#include "BKE_DerivedMesh.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_mesh.h" + +#include "PIL_time.h" +} + +#include "PTC_api.h" + +//#define USE_TIMING + +namespace PTC { + +using namespace Abc; +using namespace AbcGeom; + +PointCacheWriter::PointCacheWriter(Scene *scene, Object *ob, PointCacheModifierData *pcmd) : + Writer(scene, &ob->id, pcmd->point_cache), + m_ob(ob), + m_pcmd(pcmd) +{ + set_error_handler(new ModifierErrorHandler(&pcmd->modifier)); + + uint32_t fs = add_frame_sampling(); + + OObject root = m_archive.getTop(); + m_mesh = OPolyMesh(root, m_pcmd->modifier.name, fs); + + OPolyMeshSchema &schema = m_mesh.getSchema(); + OCompoundProperty geom_props = schema.getArbGeomParams(); + OCompoundProperty user_props = schema.getUserProperties(); + + m_param_smooth = OBoolGeomParam(geom_props, "smooth", false, kUniformScope, 1, 0); + m_prop_edges = OInt32ArrayProperty(user_props, "edges", 0); + m_prop_edges_index = OInt32ArrayProperty(user_props, "edges_index", 0); + m_param_poly_normals = ON3fGeomParam(geom_props, "poly_normals", false, kUniformScope, 1, 0); + m_param_vertex_normals = ON3fGeomParam(geom_props, "vertex_normals", false, kVertexScope, 1, 0); +} + +PointCacheWriter::~PointCacheWriter() +{ +} + +/* XXX modifiers are not allowed to generate poly normals on their own! + * see assert in DerivedMesh.c : dm_ensure_display_normals + */ +#if 0 +static void ensure_normal_data(DerivedMesh *dm) +{ + MVert *mverts = dm->getVertArray(dm); + MLoop *mloops = dm->getLoopArray(dm); + MPoly *mpolys = dm->getPolyArray(dm); + CustomData *cdata = dm->getPolyDataLayout(dm); + float (*polynors)[3]; + int totvert = dm->getNumVerts(dm); + int totloop = dm->getNumLoops(dm); + int totpoly = dm->getNumPolys(dm); + + if (CustomData_has_layer(cdata, CD_NORMAL)) + polynors = (float (*)[3])CustomData_get_layer(cdata, CD_NORMAL); + else + polynors = (float (*)[3])CustomData_add_layer(cdata, CD_NORMAL, CD_CALLOC, NULL, totpoly); + + BKE_mesh_calc_normals_poly(mverts, totvert, mloops, mpolys, totloop, totpoly, polynors, false); +} +#endif + +static P3fArraySample create_sample_positions(DerivedMesh *dm, std::vector<V3f> &data) +{ + MVert *mv, *mverts = dm->getVertArray(dm); + int i, totvert = dm->getNumVerts(dm); + + data.reserve(totvert); + for (i = 0, mv = mverts; i < totvert; ++i, ++mv) { + float *co = mv->co; + data.push_back(V3f(co[0], co[1], co[2])); + } + + return P3fArraySample(data); +} + +static Int32ArraySample create_sample_vertex_indices(DerivedMesh *dm, std::vector<int> &data) +{ + MLoop *ml, *mloops = dm->getLoopArray(dm); + int i, totloop = dm->getNumLoops(dm); + + data.reserve(totloop); + for (i = 0, ml = mloops; i < totloop; ++i, ++ml) { + data.push_back(ml->v); + } + + return Int32ArraySample(data); +} + +static Int32ArraySample create_sample_loop_counts(DerivedMesh *dm, std::vector<int> &data) +{ + MPoly *mp, *mpolys = dm->getPolyArray(dm); + int i, totpoly = dm->getNumPolys(dm); + + data.reserve(totpoly); + for (i = 0, mp = mpolys; i < totpoly; ++i, ++mp) { + data.push_back(mp->totloop); + } + + return Int32ArraySample(data); +} + +static OBoolGeomParam::Sample create_sample_poly_smooth(DerivedMesh *dm, std::vector<bool_t> &data) +{ + MPoly *mp, *mpolys = dm->getPolyArray(dm); + int i, totpoly = dm->getNumPolys(dm); + + data.reserve(totpoly); + for (i = 0, mp = mpolys; i < totpoly; ++i, ++mp) { + data.push_back((bool)(mp->flag & ME_SMOOTH)); + } + + OBoolGeomParam::Sample sample; + sample.setVals(BoolArraySample(data)); + sample.setScope(kUniformScope); + return sample; +} + +static OInt32ArrayProperty::sample_type create_sample_edge_vertices(DerivedMesh *dm, std::vector<int> &data) +{ + MEdge *me, *medges = dm->getEdgeArray(dm); + int i, totedge = dm->getNumEdges(dm); + + data.reserve(totedge * 2); + for (i = 0, me = medges; i < totedge; ++i, ++me) { + data.push_back(me->v1); + data.push_back(me->v2); + } + + return OInt32ArrayProperty::sample_type(data); +} + +static OInt32ArrayProperty::sample_type create_sample_edge_indices(DerivedMesh *dm, std::vector<int> &data) +{ + MLoop *ml, *mloops = dm->getLoopArray(dm); + int i, totloop = dm->getNumLoops(dm); + + data.reserve(totloop); + for (i = 0, ml = mloops; i < totloop; ++i, ++ml) { + data.push_back(ml->e); + } + + return OInt32ArrayProperty::sample_type(data); +} + +static N3fArraySample create_sample_loop_normals(DerivedMesh *dm, std::vector<N3f> &data) +{ + CustomData *cdata = dm->getLoopDataLayout(dm); + float (*nor)[3], (*loopnors)[3]; + int i, totloop = dm->getNumLoops(dm); + + if (!CustomData_has_layer(cdata, CD_NORMAL)) + return N3fArraySample(); + + loopnors = (float (*)[3])CustomData_get_layer(cdata, CD_NORMAL); + + data.reserve(totloop); + for (i = 0, nor = loopnors; i < totloop; ++i, ++nor) { + float *vec = *nor; + data.push_back(N3f(vec[0], vec[1], vec[2])); + } + + return N3fArraySample(data); +} + +static N3fArraySample create_sample_poly_normals(DerivedMesh *dm, std::vector<N3f> &data) +{ + CustomData *cdata = dm->getPolyDataLayout(dm); + float (*nor)[3], (*polynors)[3]; + int i, totpoly = dm->getNumPolys(dm); + + if (!CustomData_has_layer(cdata, CD_NORMAL)) + return N3fArraySample(); + + polynors = (float (*)[3])CustomData_get_layer(cdata, CD_NORMAL); + + data.reserve(totpoly); + for (i = 0, nor = polynors; i < totpoly; ++i, ++nor) { + float *vec = *nor; + data.push_back(N3f(vec[0], vec[1], vec[2])); + } + + return N3fArraySample(data); +} + +static N3fArraySample create_sample_vertex_normals(DerivedMesh *dm, std::vector<N3f> &data) +{ + MVert *mv, *mverts = dm->getVertArray(dm); + int i, totvert = dm->getNumVerts(dm); + + data.reserve(totvert); + for (i = 0, mv = mverts; i < totvert; ++i, ++mv) { + float nor[3]; + + normal_short_to_float_v3(nor, mv->no); + data.push_back(N3f(nor[0], nor[1], nor[2])); + } + + return N3fArraySample(data); +} + +void PointCacheWriter::write_sample() +{ + DerivedMesh *output_dm = m_pcmd->output_dm; + if (!output_dm) + return; + + /* TODO make this optional by a flag? */ + /* XXX does not work atm, see comment above */ + /*ensure_normal_data(output_dm);*/ + + OPolyMeshSchema &schema = m_mesh.getSchema(); + + std::vector<V3f> positions_buffer; + std::vector<int> indices_buffer; + std::vector<int> counts_buffer; + std::vector<bool_t> smooth_buffer; + std::vector<int> edges_buffer; + std::vector<int> edges_index_buffer; + std::vector<N3f> loop_normals_buffer; + std::vector<N3f> poly_normals_buffer; + std::vector<N3f> vertex_normals_buffer; +// std::vector<V2f> uvs; +// V2fArraySample() + + // TODO decide how to handle vertex/face normals, in caching vs. export ... +// std::vector<V2f> uvs; +// OV2fGeomParam::Sample uvs(V2fArraySample(uvs), kFacevaryingScope ); + + P3fArraySample positions = create_sample_positions(output_dm, positions_buffer); + Int32ArraySample indices = create_sample_vertex_indices(output_dm, indices_buffer); + Int32ArraySample counts = create_sample_loop_counts(output_dm, counts_buffer); + OBoolGeomParam::Sample smooth = create_sample_poly_smooth(output_dm, smooth_buffer); + OInt32ArrayProperty::sample_type edges = create_sample_edge_vertices(output_dm, edges_buffer); + OInt32ArrayProperty::sample_type edges_index = create_sample_edge_indices(output_dm, edges_index_buffer); + N3fArraySample lnormals = create_sample_loop_normals(output_dm, loop_normals_buffer); + N3fArraySample pnormals = create_sample_poly_normals(output_dm, poly_normals_buffer); + N3fArraySample vnormals = create_sample_vertex_normals(output_dm, vertex_normals_buffer); + + OPolyMeshSchema::Sample sample = OPolyMeshSchema::Sample( + positions, + indices, + counts, + OV2fGeomParam::Sample(), /* XXX define how/which UV map should be considered primary for the alembic schema */ + ON3fGeomParam::Sample(lnormals, kFacevaryingScope) + ); + schema.set(sample); + + if (pnormals.valid()) + m_param_poly_normals.set(ON3fGeomParam::Sample(pnormals, kUniformScope)); + if (vnormals.valid()) + m_param_vertex_normals.set(ON3fGeomParam::Sample(vnormals, kVertexScope)); + + m_param_smooth.set(smooth); + + m_prop_edges.set(edges); + m_prop_edges_index.set(edges_index); +} + + +PointCacheReader::PointCacheReader(Scene *scene, Object *ob, PointCacheModifierData *pcmd) : + Reader(scene, &ob->id, pcmd->point_cache), + m_ob(ob), + m_pcmd(pcmd), + m_result(NULL) +{ + set_error_handler(new ModifierErrorHandler(&pcmd->modifier)); + + if (m_archive.valid()) { + IObject root = m_archive.getTop(); + if (root.valid() && root.getChild(m_pcmd->modifier.name)) { + m_mesh = IPolyMesh(root, m_pcmd->modifier.name); + + IPolyMeshSchema &schema = m_mesh.getSchema(); + ICompoundProperty geom_props = schema.getArbGeomParams(); + ICompoundProperty user_props = schema.getUserProperties(); + + m_param_loop_normals = schema.getNormalsParam(); + m_param_poly_normals = IN3fGeomParam(geom_props, "poly_normals", 0); + m_param_vertex_normals = IN3fGeomParam(geom_props, "vertex_normals", 0); + m_param_smooth = IBoolGeomParam(geom_props, "smooth", 0); + m_prop_edges = IInt32ArrayProperty(user_props, "edges", 0); + m_prop_edges_index = IInt32ArrayProperty(user_props, "edges_index", 0); + } + } +} + +PointCacheReader::~PointCacheReader() +{ +} + +static void apply_sample_positions(DerivedMesh *dm, P3fArraySamplePtr sample) +{ + MVert *mv, *mverts = dm->getVertArray(dm); + int i, totvert = dm->getNumVerts(dm); + + BLI_assert(sample->size() == totvert); + + const V3f *data = sample->get(); + for (i = 0, mv = mverts; i < totvert; ++i, ++mv) { + const V3f &co = data[i]; + copy_v3_v3(mv->co, co.getValue()); + } +} + +static void apply_sample_vertex_indices(DerivedMesh *dm, Int32ArraySamplePtr sample) +{ + MLoop *ml, *mloops = dm->getLoopArray(dm); + int i, totloop = dm->getNumLoops(dm); + + BLI_assert(sample->size() == totloop); + + const int32_t *data = sample->get(); + for (i = 0, ml = mloops; i < totloop; ++i, ++ml) { + ml->v = data[i]; + } +} + +static void apply_sample_loop_counts(DerivedMesh *dm, Int32ArraySamplePtr sample) +{ + MPoly *mp, *mpolys = dm->getPolyArray(dm); + int i, totpoly = dm->getNumPolys(dm); + + BLI_assert(sample->size() == totpoly); + + const int32_t *data = sample->get(); + int loopstart = 0; + for (i = 0, mp = mpolys; i < totpoly; ++i, ++mp) { + mp->totloop = data[i]; + mp->loopstart = loopstart; + + loopstart += mp->totloop; + } +} + +static void apply_sample_loop_normals(DerivedMesh *dm, N3fArraySamplePtr sample) +{ + CustomData *cdata = dm->getLoopDataLayout(dm); + float (*nor)[3], (*loopnors)[3]; + int i, totloop = dm->getNumLoops(dm); + + BLI_assert(sample->size() == totloop); + + if (CustomData_has_layer(cdata, CD_NORMAL)) + loopnors = (float (*)[3])CustomData_get_layer(cdata, CD_NORMAL); + else + loopnors = (float (*)[3])CustomData_add_layer(cdata, CD_NORMAL, CD_CALLOC, NULL, totloop); + + const N3f *data = sample->get(); + for (i = 0, nor = loopnors; i < totloop; ++i, ++nor) { + copy_v3_v3(*nor, data[i].getValue()); + } +} + +static void apply_sample_poly_normals(DerivedMesh *dm, N3fArraySamplePtr sample) +{ + CustomData *cdata = dm->getPolyDataLayout(dm); + float (*nor)[3], (*polynors)[3]; + int i, totpoly = dm->getNumPolys(dm); + + BLI_assert(sample->size() == totpoly); + + if (CustomData_has_layer(cdata, CD_NORMAL)) + polynors = (float (*)[3])CustomData_get_layer(cdata, CD_NORMAL); + else + polynors = (float (*)[3])CustomData_add_layer(cdata, CD_NORMAL, CD_CALLOC, NULL, totpoly); + + const N3f *data = sample->get(); + for (i = 0, nor = polynors; i < totpoly; ++i, ++nor) { + copy_v3_v3(*nor, data[i].getValue()); + } +} + +static void apply_sample_vertex_normals(DerivedMesh *dm, N3fArraySamplePtr sample) +{ + MVert *mv, *mverts = dm->getVertArray(dm); + int i, totvert = dm->getNumVerts(dm); + + BLI_assert(sample->size() == totvert); + + const N3f *data = sample->get(); + for (i = 0, mv = mverts; i < totvert; ++i, ++mv) { + normal_float_to_short_v3(mv->no, data[i].getValue()); + } +} + +static void apply_sample_poly_smooth(DerivedMesh *dm, BoolArraySamplePtr sample) +{ + MPoly *mp, *mpolys = dm->getPolyArray(dm); + int i, totpoly = dm->getNumPolys(dm); + + BLI_assert(sample->size() == totpoly); + + const bool_t *data = sample->get(); + for (i = 0, mp = mpolys; i < totpoly; ++i, ++mp) { + if (data[i]) { + mp->flag |= ME_SMOOTH; + } + } +} + +static void apply_sample_edge_vertices(DerivedMesh *dm, Int32ArraySamplePtr sample) +{ + MEdge *me, *medges = dm->getEdgeArray(dm); + int i, totedge = dm->getNumEdges(dm); + + BLI_assert(sample->size() == totedge * 2); + + const int32_t *data = sample->get(); + for (i = 0, me = medges; i < totedge; ++i, ++me) { + me->v1 = data[(i << 1)]; + me->v2 = data[(i << 1) + 1]; + } +} + +static void apply_sample_edge_indices(DerivedMesh *dm, Int32ArraySamplePtr sample) +{ + MLoop *ml, *mloops = dm->getLoopArray(dm); + int i, totloop = dm->getNumLoops(dm); + + BLI_assert(sample->size() == totloop); + + const int32_t *data = sample->get(); + for (i = 0, ml = mloops; i < totloop; ++i, ++ml) { + ml->e = data[i]; + } +} + +PTCReadSampleResult PointCacheReader::read_sample(float frame) +{ +#ifdef USE_TIMING + double start_time; + double time_get_sample, time_build_mesh, time_calc_edges, time_calc_normals; + +#define PROFILE_START \ + start_time = PIL_check_seconds_timer(); +#define PROFILE_END(var) \ + var = PIL_check_seconds_timer() - start_time; +#else +#define PROFILE_START ; +#define PROFILE_END(var) ; +#endif + + /* discard existing result data */ + discard_result(); + + if (!m_mesh.valid()) + return PTC_READ_SAMPLE_INVALID; + + IPolyMeshSchema &schema = m_mesh.getSchema(); + if (!schema.valid() || schema.getPositionsProperty().getNumSamples() == 0) + return PTC_READ_SAMPLE_INVALID; + + ISampleSelector ss = get_frame_sample_selector(frame); + + PROFILE_START; + IPolyMeshSchema::Sample sample; + schema.get(sample, ss); + + bool has_normals = false; + P3fArraySamplePtr positions = sample.getPositions(); + Int32ArraySamplePtr indices = sample.getFaceIndices(); + Int32ArraySamplePtr counts = sample.getFaceCounts(); + N3fArraySamplePtr lnormals, pnormals, vnormals; + if (m_param_poly_normals && m_param_poly_normals.getNumSamples() > 0 + && m_param_vertex_normals && m_param_vertex_normals.getNumSamples() > 0) { + pnormals = m_param_poly_normals.getExpandedValue(ss).getVals(); + vnormals = m_param_vertex_normals.getExpandedValue(ss).getVals(); + + /* we need all normal properties defined, otherwise have to recalculate */ + has_normals = pnormals->valid() && vnormals->valid(); + } + if (has_normals) { + /* note: loop normals are not mandatory, but if poly/vertex normals don't exist they get recalculated anyway */ + if (m_param_loop_normals && m_param_loop_normals.getNumSamples() > 0) + lnormals = m_param_loop_normals.getExpandedValue(ss).getVals(); + } + + BoolArraySamplePtr smooth; + if (m_param_smooth && m_param_smooth.getNumSamples() > 0) { + IBoolGeomParam::Sample sample_smooth; + m_param_smooth.getExpanded(sample_smooth, ss); + smooth = sample_smooth.getVals(); + } + + bool has_edges = false; + Int32ArraySamplePtr edges, edges_index; + if (m_prop_edges && m_prop_edges.getNumSamples() > 0 + && m_prop_edges_index && m_prop_edges_index.getNumSamples() > 0) { + m_prop_edges.get(edges, ss); + m_prop_edges_index.get(edges_index, ss); + BLI_assert(edges->size() % 2 == 0); /* 2 vertex indices per edge */ + + has_edges = edges->valid() && edges_index->valid(); + } + PROFILE_END(time_get_sample); + + PROFILE_START; + int totverts = positions->size(); + int totloops = indices->size(); + int totpolys = counts->size(); + int totedges = has_edges ? edges->size() >> 1 : 0; + m_result = CDDM_new(totverts, totedges, 0, totloops, totpolys); + + apply_sample_positions(m_result, positions); + apply_sample_vertex_indices(m_result, indices); + apply_sample_loop_counts(m_result, counts); + if (has_normals) { + apply_sample_poly_normals(m_result, lnormals); + apply_sample_vertex_normals(m_result, vnormals); + + if (lnormals->valid()) + apply_sample_loop_normals(m_result, pnormals); + } + else { + /* make sure normals are recalculated if there is no sample data */ + m_result->dirty = (DMDirtyFlag)((int)m_result->dirty | DM_DIRTY_NORMALS); + } + if (has_edges) { + apply_sample_edge_vertices(m_result, edges); + apply_sample_edge_indices(m_result, edges_index); + } + if (smooth) + apply_sample_poly_smooth(m_result, smooth); + PROFILE_END(time_build_mesh); + + PROFILE_START; + if (!has_edges) + CDDM_calc_edges(m_result); + PROFILE_END(time_calc_edges); + + PROFILE_START; + DM_ensure_normals(m_result); /* only recalculates normals if no valid samples were found (has_normals == false) */ + PROFILE_END(time_calc_normals); + +// BLI_assert(DM_is_valid(m_result)); + +#ifdef USE_TIMING + printf("-------- Point Cache Timing --------\n"); + printf("read sample: %f seconds\n", time_get_sample); + printf("build mesh: %f seconds\n", time_build_mesh); + printf("calculate edges: %f seconds\n", time_calc_edges); + printf("calculate normals: %f seconds\n", time_calc_normals); + printf("------------------------------------\n"); +#endif + + return PTC_READ_SAMPLE_EXACT; +} + +DerivedMesh *PointCacheReader::acquire_result() +{ + DerivedMesh *dm = m_result; + m_result = NULL; + return dm; +} + +void PointCacheReader::discard_result() +{ + if (m_result) { + m_result->release(m_result); + m_result = NULL; + } +} + +} /* namespace PTC */ + + +/* ==== C API ==== */ + +PTCWriter *PTC_writer_point_cache(Scene *scene, Object *ob, PointCacheModifierData *pcmd) +{ + return (PTCWriter *)(new PTC::PointCacheWriter(scene, ob, pcmd)); +} + +PTCReader *PTC_reader_point_cache(Scene *scene, Object *ob, PointCacheModifierData *pcmd) +{ + return (PTCReader *)(new PTC::PointCacheReader(scene, ob, pcmd)); +} + +struct DerivedMesh *PTC_reader_point_cache_acquire_result(PTCReader *_reader) +{ + PTC::PointCacheReader *reader = (PTC::PointCacheReader *)_reader; + return reader->acquire_result(); +} + +void PTC_reader_point_cache_discard_result(PTCReader *_reader) +{ + PTC::PointCacheReader *reader = (PTC::PointCacheReader *)_reader; + reader->discard_result(); +} + +ePointCacheModifierMode PTC_mod_point_cache_get_mode(PointCacheModifierData *pcmd) +{ + /* can't have simultaneous read and write */ + if (pcmd->writer) { + BLI_assert(!pcmd->reader); + return MOD_POINTCACHE_MODE_WRITE; + } + else if (pcmd->reader) { + BLI_assert(!pcmd->writer); + return MOD_POINTCACHE_MODE_READ; + } + else + return MOD_POINTCACHE_MODE_NONE; +} + +ePointCacheModifierMode PTC_mod_point_cache_set_mode(Scene *scene, Object *ob, PointCacheModifierData *pcmd, ePointCacheModifierMode mode) +{ + switch (mode) { + case MOD_POINTCACHE_MODE_READ: + if (pcmd->writer) { + PTC_writer_free(pcmd->writer); + pcmd->writer = NULL; + } + if (!pcmd->reader) { + pcmd->reader = PTC_reader_point_cache(scene, ob, pcmd); + } + return pcmd->reader ? MOD_POINTCACHE_MODE_READ : MOD_POINTCACHE_MODE_NONE; + + case MOD_POINTCACHE_MODE_WRITE: + if (pcmd->reader) { + PTC_reader_free(pcmd->reader); + pcmd->reader = NULL; + } + if (!pcmd->writer) { + pcmd->writer = PTC_writer_point_cache(scene, ob, pcmd); + } + return pcmd->writer ? MOD_POINTCACHE_MODE_WRITE : MOD_POINTCACHE_MODE_NONE; + + default: + if (pcmd->writer) { + PTC_writer_free(pcmd->writer); + pcmd->writer = NULL; + } + if (pcmd->reader) { + PTC_reader_free(pcmd->reader); + pcmd->reader = NULL; + } + return MOD_POINTCACHE_MODE_NONE; + } +} diff --git a/source/blender/pointcache/intern/mesh.h b/source/blender/pointcache/intern/mesh.h new file mode 100644 index 00000000000..261b72b2d12 --- /dev/null +++ b/source/blender/pointcache/intern/mesh.h @@ -0,0 +1,82 @@ +/* + * Copyright 2014, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_MESH_H +#define PTC_MESH_H + +#include <Alembic/AbcGeom/IPolyMesh.h> +#include <Alembic/AbcGeom/OPolyMesh.h> + +#include "reader.h" +#include "schema.h" +#include "writer.h" + +struct Object; +struct PointCacheModifierData; +struct DerivedMesh; + +namespace PTC { + +class PointCacheWriter : public Writer { +public: + PointCacheWriter(Scene *scene, Object *ob, PointCacheModifierData *pcmd); + ~PointCacheWriter(); + + void write_sample(); + +private: + Object *m_ob; + PointCacheModifierData *m_pcmd; + + AbcGeom::OPolyMesh m_mesh; + AbcGeom::OBoolGeomParam m_param_smooth; + AbcGeom::OInt32ArrayProperty m_prop_edges; + AbcGeom::OInt32ArrayProperty m_prop_edges_index; + AbcGeom::ON3fGeomParam m_param_vertex_normals; + AbcGeom::ON3fGeomParam m_param_poly_normals; + /* note: loop normals are already defined as a parameter in the schema */ +}; + +class PointCacheReader : public Reader { +public: + PointCacheReader(Scene *scene, Object *ob, PointCacheModifierData *pcmd); + ~PointCacheReader(); + + DerivedMesh *acquire_result(); + void discard_result(); + + PTCReadSampleResult read_sample(float frame); + +private: + Object *m_ob; + PointCacheModifierData *m_pcmd; + + AbcGeom::IPolyMesh m_mesh; + AbcGeom::IBoolGeomParam m_param_smooth; + AbcGeom::IInt32ArrayProperty m_prop_edges; + AbcGeom::IInt32ArrayProperty m_prop_edges_index; + AbcGeom::IN3fGeomParam m_param_loop_normals; + AbcGeom::IN3fGeomParam m_param_vertex_normals; + AbcGeom::IN3fGeomParam m_param_poly_normals; + + DerivedMesh *m_result; +}; + +} /* namespace PTC */ + +#endif /* PTC_MESH_H */ diff --git a/source/blender/pointcache/intern/particles.cpp b/source/blender/pointcache/intern/particles.cpp new file mode 100644 index 00000000000..7d653dc4578 --- /dev/null +++ b/source/blender/pointcache/intern/particles.cpp @@ -0,0 +1,345 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "particles.h" + +extern "C" { +#include "DNA_object_types.h" +#include "DNA_particle_types.h" +} + +#include "PTC_api.h" + +namespace PTC { + +using namespace Abc; +using namespace AbcGeom; + +#if 0 +void IParticlesSchema::init(const Abc::Argument &iArg0, + const Abc::Argument &iArg1) +{ + ALEMBIC_ABC_SAFE_CALL_BEGIN("IParticlesSchema::init()"); + + Abc::Arguments args; + iArg0.setInto(args); + iArg1.setInto(args); + + AbcA::CompoundPropertyReaderPtr _this = this->getPtr(); + + // no matching so we pick up old assets written as V3f + m_positionsProperty = Abc::IP3fArrayProperty(_this, "P", kNoMatching, + args.getErrorHandlerPolicy()); + + m_idsProperty = Abc::IUInt64ArrayProperty(_this, ".pointIds", + iArg0, iArg1); + + if (_this->getPropertyHeader(".velocities") != NULL) { + m_velocitiesProperty = Abc::IV3fArrayProperty(_this, ".velocities", + iArg0, iArg1); + } + + if (_this->getPropertyHeader(".widths" ) != NULL) { + m_widthsParam = IFloatGeomParam(_this, ".widths", iArg0, iArg1); + } + + ALEMBIC_ABC_SAFE_CALL_END_RESET(); +} + + + +void OParticlesSchema::set( const Sample &iSamp ) +{ + ALEMBIC_ABC_SAFE_CALL_BEGIN("OParticlesSchema::set()"); + + // do we need to create velocities prop? + if (iSamp.getVelocities() && !m_velocitiesProperty) { + m_velocitiesProperty = Abc::OV3fArrayProperty(this->getPtr(), ".velocities", + m_positionsProperty.getTimeSampling()); + + std::vector<V3f> emptyVec; + const V3fArraySample empty(emptyVec); + const size_t numSamps = m_positionsProperty.getNumSamples(); + for (size_t i = 0 ; i < numSamps ; ++i) { + m_velocitiesProperty.set(empty); + } + } + + // do we need to create widths prop? + if (iSamp.getWidths() && !m_widthsParam) { + std::vector<float> emptyVals; + std::vector<Util::uint32_t> emptyIndices; + OFloatGeomParam::Sample empty; + + if (iSamp.getWidths().getIndices()) { + empty = OFloatGeomParam::Sample(Abc::FloatArraySample(emptyVals), + Abc::UInt32ArraySample(emptyIndices), + iSamp.getWidths().getScope()); + + // widths are indexed which is wasteful, but technically ok + m_widthsParam = OFloatGeomParam(this->getPtr(), ".widths", true, + iSamp.getWidths().getScope(), + 1, this->getTimeSampling()); + } + else { + empty = OFloatGeomParam::Sample(Abc::FloatArraySample(emptyVals), + iSamp.getWidths().getScope()); + + // widths are not indexed + m_widthsParam = OFloatGeomParam(this->getPtr(), ".widths", false, + iSamp.getWidths().getScope(), 1, + this->getTimeSampling()); + } + + size_t numSamples = m_positionsProperty.getNumSamples(); + + // set all the missing samples + for (size_t i = 0; i < numSamples; ++i) { + m_widthsParam.set( empty ); + } + } + + // We could add sample integrity checking here. + if (m_positionsProperty.getNumSamples() == 0) { + // First sample must be valid on all points. + ABCA_ASSERT(iSamp.getPositions() && + iSamp.getIds(), + "Sample 0 must have valid data for points and ids"); + m_positionsProperty.set(iSamp.getPositions()); + m_idsProperty.set(iSamp.getIds()); + + if (m_velocitiesProperty) { + m_velocitiesProperty.set(iSamp.getVelocities()); + } + + if (m_widthsParam) { + m_widthsParam.set(iSamp.getWidths()); + } + + if (iSamp.getSelfBounds().isEmpty()) { + // OTypedScalarProperty::set() is not referentially transparent, + // so we need a a placeholder variable. + Abc::Box3d bnds(ComputeBoundsFromPositions(iSamp.getPositions())); + m_selfBoundsProperty.set( bnds ); + } + else { + m_selfBoundsProperty.set(iSamp.getSelfBounds()); + } + } + else { + SetPropUsePrevIfNull(m_positionsProperty, iSamp.getPositions()); + SetPropUsePrevIfNull(m_idsProperty, iSamp.getIds()); + SetPropUsePrevIfNull(m_velocitiesProperty, iSamp.getVelocities()); + + if (iSamp.getSelfBounds().hasVolume()) { + m_selfBoundsProperty.set(iSamp.getSelfBounds()); + } + else if (iSamp.getPositions()) { + Abc::Box3d bnds(ComputeBoundsFromPositions(iSamp.getPositions())); + m_selfBoundsProperty.set(bnds); + } + else { + m_selfBoundsProperty.setFromPrevious(); + } + + if (m_widthsParam) { + m_widthsParam.set(iSamp.getWidths()); + } + } + + ALEMBIC_ABC_SAFE_CALL_END(); +} + +//-***************************************************************************** +void OParticlesSchema::setFromPrevious() +{ + ALEMBIC_ABC_SAFE_CALL_BEGIN("OParticlesSchema::setFromPrevious"); + + m_positionsProperty.setFromPrevious(); + m_idsProperty.setFromPrevious(); + + m_selfBoundsProperty.setFromPrevious(); + + if (m_widthsParam) { + m_widthsParam.setFromPrevious(); + } + + ALEMBIC_ABC_SAFE_CALL_END(); +} + +//-***************************************************************************** +void OParticlesSchema::setTimeSampling(uint32_t iIndex) +{ + ALEMBIC_ABC_SAFE_CALL_BEGIN("OParticlesSchema::setTimeSampling( uint32_t )"); + + m_positionsProperty.setTimeSampling(iIndex); + m_idsProperty.setTimeSampling(iIndex); + m_selfBoundsProperty.setTimeSampling(iIndex); + + if (m_widthsParam) + { + m_widthsParam.setTimeSampling(iIndex); + } + + ALEMBIC_ABC_SAFE_CALL_END(); +} + +//-***************************************************************************** +void OParticlesSchema::setTimeSampling( AbcA::TimeSamplingPtr iTime ) +{ + ALEMBIC_ABC_SAFE_CALL_BEGIN("OParticlesSchema::setTimeSampling( TimeSamplingPtr )"); + + if (iTime) + { + uint32_t tsIndex = getObject().getArchive().addTimeSampling(*iTime); + setTimeSampling(tsIndex); + } + + ALEMBIC_ABC_SAFE_CALL_END(); +} + +//-***************************************************************************** +void OParticlesSchema::init(uint32_t iTsIdx) +{ + ALEMBIC_ABC_SAFE_CALL_BEGIN("OParticlesSchema::init()"); + + AbcA::MetaData mdata; + SetGeometryScope(mdata, kVaryingScope); + AbcA::CompoundPropertyWriterPtr _this = this->getPtr(); + + m_positionsProperty = Abc::OP3fArrayProperty(_this, "P", mdata, iTsIdx); + + m_idsProperty = Abc::OUInt64ArrayProperty(_this, ".pointIds", mdata, + iTsIdx); + + ALEMBIC_ABC_SAFE_CALL_END_RESET(); +} +#endif + + +ParticlesWriter::ParticlesWriter(Scene *scene, Object *ob, ParticleSystem *psys) : + Writer(scene, &ob->id, psys->pointcache), + m_ob(ob), + m_psys(psys) +{ + uint32_t fs = add_frame_sampling(); + + OObject root = m_archive.getTop(); + m_points = OPoints(root, m_psys->name, fs); +} + +ParticlesWriter::~ParticlesWriter() +{ +} + +void ParticlesWriter::write_sample() +{ + OPointsSchema &schema = m_points.getSchema(); + + int totpart = m_psys->totpart; + ParticleData *pa; + int i; + + /* XXX TODO only needed for the first frame/sample */ + std::vector<Util::uint64_t> ids; + ids.reserve(totpart); + for (i = 0, pa = m_psys->particles; i < totpart; ++i, ++pa) + ids.push_back(i); + + std::vector<V3f> positions; + positions.reserve(totpart); + for (i = 0, pa = m_psys->particles; i < totpart; ++i, ++pa) { + float *co = pa->state.co; + positions.push_back(V3f(co[0], co[1], co[2])); + } + + OPointsSchema::Sample sample = OPointsSchema::Sample(V3fArraySample(positions), UInt64ArraySample(ids)); + + schema.set(sample); +} + + +ParticlesReader::ParticlesReader(Scene *scene, Object *ob, ParticleSystem *psys) : + Reader(scene, &ob->id, psys->pointcache), + m_ob(ob), + m_psys(psys), + m_totpoint(0) +{ + if (m_archive.valid()) { + IObject root = m_archive.getTop(); + m_points = IPoints(root, m_psys->name); + } + + /* XXX TODO read first sample for info on particle count and times */ + m_totpoint = 0; +} + +ParticlesReader::~ParticlesReader() +{ +} + +PTCReadSampleResult ParticlesReader::read_sample(float frame) +{ + if (!m_points.valid()) + return PTC_READ_SAMPLE_INVALID; + + IPointsSchema &schema = m_points.getSchema(); + TimeSamplingPtr ts = schema.getTimeSampling(); + + ISampleSelector ss = get_frame_sample_selector(frame); + chrono_t time = ss.getRequestedTime(); + + std::pair<index_t, chrono_t> sres = ts->getFloorIndex(time, schema.getNumSamples()); + chrono_t stime = sres.second; + float sframe = time_to_frame(stime); + + IPointsSchema::Sample sample; + schema.get(sample, ss); + + const V3f *positions = sample.getPositions()->get(); + int totpart = m_psys->totpart, i; + ParticleData *pa; + for (i = 0, pa = m_psys->particles; i < sample.getPositions()->size(); ++i, ++pa) { + pa->state.co[0] = positions[i].x; + pa->state.co[1] = positions[i].y; + pa->state.co[2] = positions[i].z; + } + + return PTC_READ_SAMPLE_EXACT; +} + +} /* namespace PTC */ + + +/* ==== C API ==== */ + +PTCWriter *PTC_writer_particles(Scene *scene, Object *ob, ParticleSystem *psys) +{ + return (PTCWriter *)(new PTC::ParticlesWriter(scene, ob, psys)); +} + +PTCReader *PTC_reader_particles(Scene *scene, Object *ob, ParticleSystem *psys) +{ + return (PTCReader *)(new PTC::ParticlesReader(scene, ob, psys)); +} + +int PTC_reader_particles_totpoint(PTCReader *_reader) +{ + PTC::ParticlesReader *reader = (PTC::ParticlesReader *)_reader; + return reader->totpoint(); +} diff --git a/source/blender/pointcache/intern/particles.h b/source/blender/pointcache/intern/particles.h new file mode 100644 index 00000000000..55125280e4f --- /dev/null +++ b/source/blender/pointcache/intern/particles.h @@ -0,0 +1,511 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_PARTICLES_H +#define PTC_PARTICLES_H + +#include <Alembic/AbcGeom/IPoints.h> +#include <Alembic/AbcGeom/OPoints.h> + +#include "reader.h" +#include "schema.h" +#include "writer.h" + +struct Object; +struct ParticleSystem; + +namespace PTC { + +#if 0 +PTC_SCHEMA_INFO("Particles", "Particles", ".particles", ParticlesSchemaInfo); + +class IParticlesSchema : public IGeomBaseSchema<ParticlesSchemaInfo> +{ +public: + class Sample + { + public: + typedef Sample this_type; + + // Users don't ever create this data directly. + Sample() { reset(); } + + P3fArraySamplePtr getPositions() const { return m_positions; } + UInt64ArraySamplePtr getIds() const { return m_ids; } + V3fArraySamplePtr getVelocities() const { return m_velocities; } + + Box3d getSelfBounds() const { return m_selfBounds; } + + bool valid() const + { + return m_positions && m_ids; + } + + void reset() + { + m_positions.reset(); + m_velocities.reset(); + m_ids.reset(); + m_selfBounds.makeEmpty(); + } + + ALEMBIC_OPERATOR_BOOL( valid() ); + + protected: + friend class IParticlesSchema; + P3fArraySamplePtr m_positions; + UInt64ArraySamplePtr m_ids; + V3fArraySamplePtr m_velocities; + + Box3d m_selfBounds; + }; + + //-************************************************************************* + // POINTS SCHEMA + //-************************************************************************* +public: + //! By convention we always define this_type in AbcGeom classes. + //! Used by unspecified-bool-type conversion below + typedef IParticlesSchema this_type; + + //-************************************************************************* + // CONSTRUCTION, DESTRUCTION, ASSIGNMENT + //-************************************************************************* + + //! The default constructor creates an empty IParticlesSchema + //! ... + IParticlesSchema() {} + + //! This templated, explicit function creates a new scalar property reader. + //! The first argument is any Abc (or AbcCoreAbstract) object + //! which can intrusively be converted to an CompoundPropertyReaderPtr + //! to use as a parent, from which the error handler policy for + //! inheritance is also derived. The remaining optional arguments + //! can be used to override the ErrorHandlerPolicy, to specify + //! MetaData, and to set TimeSamplingType. + template <class CPROP_PTR> + IParticlesSchema(CPROP_PTR iParent, + const std::string &iName, + + const Argument &iArg0 = Argument(), + const Argument &iArg1 = Argument()) + : IGeomBaseSchema<ParticlesSchemaInfo>(iParent, iName, + iArg0, iArg1) + { + init(iArg0, iArg1); + } + + //! This constructor is the same as above, but with default + //! schema name used. + template <class CPROP_PTR> + explicit IParticlesSchema(CPROP_PTR iParent, + const Argument &iArg0 = Argument(), + const Argument &iArg1 = Argument()) + : IGeomBaseSchema<ParticlesSchemaInfo>(iParent, + iArg0, iArg1) + { + init(iArg0, iArg1); + } + + //! Copy constructor. + IParticlesSchema(const IParticlesSchema& iCopy) + : IGeomBaseSchema<ParticlesSchemaInfo>() + { + *this = iCopy; + } + + //! Default assignment operator used. + + //-************************************************************************* + // SCALAR PROPERTY READER FUNCTIONALITY + //-************************************************************************* + + //! Return the number of samples contained in the property. + //! This can be any number, including zero. + //! This returns the number of samples that were written, independently + //! of whether or not they were constant. + size_t getNumSamples() const + { + return std::max(m_positionsProperty.getNumSamples(), + m_idsProperty.getNumSamples()); + } + + //! Ask if we're constant - no change in value amongst samples, + //! regardless of the time sampling. + bool isConstant() const { return m_positionsProperty.isConstant() && m_idsProperty.isConstant(); } + + //! Time sampling Information. + //! + TimeSamplingPtr getTimeSampling() const + { + if (m_positionsProperty.valid()) + { + return m_positionsProperty.getTimeSampling(); + } + return getObject().getArchive().getTimeSampling(0); + } + + //-************************************************************************* + void get(Sample &oSample, + const ISampleSelector &iSS = ISampleSelector()) const + { + ALEMBIC_ABC_SAFE_CALL_BEGIN("IParticlesSchema::get()"); + + m_positionsProperty.get(oSample.m_positions, iSS); + m_idsProperty.get(oSample.m_ids, iSS); + + m_selfBoundsProperty.get(oSample.m_selfBounds, iSS); + + if (m_velocitiesProperty && m_velocitiesProperty.getNumSamples() > 0) { + m_velocitiesProperty.get( oSample.m_velocities, iSS ); + } + + // Could error check here. + + ALEMBIC_ABC_SAFE_CALL_END(); + } + + Sample getValue(const ISampleSelector &iSS = ISampleSelector()) const + { + Sample smp; + get(smp, iSS); + return smp; + } + + IP3fArrayProperty getPositionsProperty() const { return m_positionsProperty; } + + IV3fArrayProperty getVelocitiesProperty() const { return m_velocitiesProperty; } + + IUInt64ArrayProperty getIdsProperty() const { return m_idsProperty; } + + IFloatGeomParam getWidthsParam() const { return m_widthsParam; } + + //-************************************************************************* + // ABC BASE MECHANISMS + // These functions are used by Abc to deal with errors, rewrapping, + // and so on. + //-************************************************************************* + + //! Reset returns this function set to an empty, default + //! state. + void reset() + { + m_positionsProperty.reset(); + m_velocitiesProperty.reset(); + m_idsProperty.reset(); + m_widthsParam.reset(); + + IGeomBaseSchema<ParticlesSchemaInfo>::reset(); + } + + //! Valid returns whether this function set is + //! valid. + bool valid() const + { + return (IGeomBaseSchema<ParticlesSchemaInfo>() && + m_positionsProperty.valid() && + m_idsProperty.valid()); + } + + //! unspecified-bool-type operator overload. + //! ... + ALEMBIC_OVERRIDE_OPERATOR_BOOL(IParticlesSchema::valid()); + +protected: + void init(const Argument &iArg0, + const Argument &iArg1); + + IP3fArrayProperty m_positionsProperty; + IUInt64ArrayProperty m_idsProperty; + IV3fArrayProperty m_velocitiesProperty; + IFloatGeomParam m_widthsParam; +}; + +//-***************************************************************************** +typedef ISchemaObject<IParticlesSchema> IParticles; + +typedef Util::shared_ptr< IParticles > IParticlesPtr; + + + +class OParticlesSchema : public OGeomBaseSchema<ParticlesSchemaInfo> +{ +public: + //-************************************************************************* + // POINTS SCHEMA SAMPLE TYPE + //-************************************************************************* + class Sample + { + public: + //! Creates a default sample with no data in it. + //! ... + Sample() { reset(); } + + //! Creates a sample with position data but no id + //! data. For specifying samples after the first one + Sample(const P3fArraySample &iPos, + const V3fArraySample &iVelocities = V3fArraySample(), + const OFloatGeomParam::Sample &iWidths = OFloatGeomParam::Sample()) + : m_positions( iPos ) + , m_velocities( iVelocities ) + , m_widths( iWidths ) + {} + + //! Creates a sample with position data and id data. The first + //! sample must be full like this. Subsequent samples may also + //! be full like this, which would indicate a change of topology + Sample(const P3fArraySample &iPos, + const UInt64ArraySample &iId, + const V3fArraySample &iVelocities = V3fArraySample(), + const OFloatGeomParam::Sample &iWidths = OFloatGeomParam::Sample()) + : m_positions(iPos) + , m_velocities(iVelocities) + , m_ids(iId) + , m_widths(iWidths) + {} + + // positions accessor + const P3fArraySample &getPositions() const { return m_positions; } + void setPositions(const P3fArraySample &iSmp) { m_positions = iSmp; } + + // ids accessor + const UInt64ArraySample &getIds() const { return m_ids; } + void setIds(const UInt64ArraySample &iSmp) { m_ids = iSmp; } + + // velocities accessor + const V3fArraySample &getVelocities() const { return m_velocities; } + void setVelocities(const V3fArraySample &iVelocities) { m_velocities = iVelocities; } + + // widths accessor + const OFloatGeomParam::Sample &getWidths() const { return m_widths; } + void setWidths(const OFloatGeomParam::Sample &iWidths) { m_widths = iWidths; } + + const Box3d &getSelfBounds() const { return m_selfBounds; } + void setSelfBounds(const Box3d &iBnds) { m_selfBounds = iBnds; } + + void reset() + { + m_positions.reset(); + m_velocities.reset(); + m_ids.reset(); + m_widths.reset(); + + m_selfBounds.makeEmpty(); + } + + protected: + P3fArraySample m_positions; + V3fArraySample m_velocities; + UInt64ArraySample m_ids; + OFloatGeomParam::Sample m_widths; + + Box3d m_selfBounds; + }; + + //-************************************************************************* + // POINTS SCHEMA + //-************************************************************************* +public: + //! By convention we always define this_type in AbcGeom classes. + //! Used by unspecified-bool-type conversion below + typedef OParticlesSchema this_type; + + //-************************************************************************* + // CONSTRUCTION, DESTRUCTION, ASSIGNMENT + //-************************************************************************* + + //! The default constructor creates an empty OParticlesSchema + //! ... + OParticlesSchema() {} + + //! This templated, primary constructor creates a new poly mesh writer. + //! The first argument is any Abc (or AbcCoreAbstract) object + //! which can intrusively be converted to an CompoundPropertyWriterPtr + //! to use as a parent, from which the error handler policy for + //! inheritance is also derived. The remaining optional arguments + //! can be used to override the ErrorHandlerPolicy, to specify + //! MetaData, and to set TimeSamplingType. + template <class CPROP_PTR> + OParticlesSchema(CPROP_PTR iParent, + const std::string &iName, + + const Argument &iArg0 = Argument(), + const Argument &iArg1 = Argument(), + const Argument &iArg2 = Argument()) + : OGeomBaseSchema<ParticlesSchemaInfo>( + GetCompoundPropertyWriterPtr(iParent), + iName, iArg0, iArg1, iArg2) + { + TimeSamplingPtr tsPtr = GetTimeSampling( iArg0, iArg1, iArg2 ); + uint32_t tsIndex = GetTimeSamplingIndex( iArg0, iArg1, iArg2 ); + + // if we specified a valid TimeSamplingPtr, use it to determine the + // index otherwise we'll use the index, which defaults to the intrinsic + // 0 index + if (tsPtr) + { + tsIndex = GetCompoundPropertyWriterPtr( iParent )->getObject()->getArchive()->addTimeSampling(*tsPtr); + } + + // Meta data and error handling are eaten up by + // the super type, so all that's left is time sampling. + init(tsIndex); + } + + template <class CPROP_PTR> + explicit OParticlesSchema(CPROP_PTR iParent, + const Argument &iArg0 = Argument(), + const Argument &iArg1 = Argument(), + const Argument &iArg2 = Argument()) + : OGeomBaseSchema<ParticlesSchemaInfo>( + GetCompoundPropertyWriterPtr(iParent), + iArg0, iArg1, iArg2) + { + TimeSamplingPtr tsPtr = GetTimeSampling( iArg0, iArg1, iArg2 ); + uint32_t tsIndex = GetTimeSamplingIndex( iArg0, iArg1, iArg2 ); + + // if we specified a valid TimeSamplingPtr, use it to determine the + // index otherwise we'll use the index, which defaults to the intrinsic + // 0 index + if (tsPtr) { + tsIndex = GetCompoundPropertyWriterPtr( iParent )->getObject()->getArchive()->addTimeSampling(*tsPtr); + } + + // Meta data and error handling are eaten up by + // the super type, so all that's left is time sampling. + init( tsIndex ); + } + + //! Copy constructor. + OParticlesSchema(const OParticlesSchema& iCopy) + : OGeomBaseSchema<ParticlesSchemaInfo>() + { + *this = iCopy; + } + + //! Default assignment operator used. + + //-************************************************************************* + // SCHEMA STUFF + //-************************************************************************* + + //! Return the time sampling + TimeSamplingPtr getTimeSampling() const { return m_positionsProperty.getTimeSampling(); } + + //-************************************************************************* + // SAMPLE STUFF + //-************************************************************************* + + //! Get number of samples written so far. + //! ... + size_t getNumSamples() const { return m_positionsProperty.getNumSamples(); } + + //! Set a sample + void set(const Sample &iSamp); + + //! Set from previous sample. Will apply to each of positions, + //! ids, velocities, and widths + void setFromPrevious(); + + void setTimeSampling(uint32_t iIndex); + void setTimeSampling(TimeSamplingPtr iTime); + + //-************************************************************************* + // ABC BASE MECHANISMS + // These functions are used by Abc to deal with errors, validity, + // and so on. + //-************************************************************************* + + //! Reset returns this function set to an empty, default + //! state. + void reset() + { + m_positionsProperty.reset(); + m_idsProperty.reset(); + m_velocitiesProperty.reset(); + m_widthsParam.reset(); + + OGeomBaseSchema<ParticlesSchemaInfo>::reset(); + } + + //! Valid returns whether this function set is + //! valid. + bool valid() const + { + return (OGeomBaseSchema<ParticlesSchemaInfo>::valid() && + m_positionsProperty.valid() && + m_idsProperty.valid()); + } + + //! unspecified-bool-type operator overload. + //! ... + ALEMBIC_OVERRIDE_OPERATOR_BOOL( OParticlesSchema::valid() ); + +protected: + void init(uint32_t iTsIdx); + + OP3fArrayProperty m_positionsProperty; + OUInt64ArrayProperty m_idsProperty; + OV3fArrayProperty m_velocitiesProperty; + OFloatGeomParam m_widthsParam; + +}; + +//-***************************************************************************** +// SCHEMA OBJECT +//-***************************************************************************** +typedef OSchemaObject<OParticlesSchema> OParticles; + +typedef Util::shared_ptr< OParticles > OParticlesPtr; +#endif + + +class ParticlesWriter : public Writer { +public: + ParticlesWriter(Scene *scene, Object *ob, ParticleSystem *psys); + ~ParticlesWriter(); + + void write_sample(); + +private: + Object *m_ob; + ParticleSystem *m_psys; + + AbcGeom::OPoints m_points; +}; + +class ParticlesReader : public Reader { +public: + ParticlesReader(Scene *scene, Object *ob, ParticleSystem *psys); + ~ParticlesReader(); + + int totpoint() const { return m_totpoint; } + + PTCReadSampleResult read_sample(float frame); + +private: + Object *m_ob; + ParticleSystem *m_psys; + + int m_totpoint; + AbcGeom::IPoints m_points; +}; + +} /* namespace PTC */ + +#endif /* PTC_PARTICLES_H */ diff --git a/source/blender/pointcache/intern/reader.cpp b/source/blender/pointcache/intern/reader.cpp new file mode 100644 index 00000000000..75b93c4eaeb --- /dev/null +++ b/source/blender/pointcache/intern/reader.cpp @@ -0,0 +1,109 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <Alembic/AbcCoreHDF5/ReadWrite.h> +#include <Alembic/Abc/ArchiveInfo.h> + +#include "reader.h" +#include "util_path.h" +#include "util_error_handler.h" + +extern "C" { +#include "BLI_fileops.h" + +#include "DNA_scene_types.h" +} + +namespace PTC { + +using namespace Abc; + +Reader::Reader(Scene *scene, ID *id, PointCache *cache) : + FrameMapper(scene), + m_error_handler(0), + m_scene(scene) +{ + std::string filename = ptc_archive_path(cache, id); + PTC_SAFE_CALL_BEGIN + m_archive = IArchive(AbcCoreHDF5::ReadArchive(), filename, Abc::ErrorHandler::kThrowPolicy); + PTC_SAFE_CALL_END_HANDLER(m_error_handler) +} + +Reader::~Reader() +{ + if (m_error_handler) + delete m_error_handler; +} + +void Reader::set_error_handler(ErrorHandler *handler) +{ + if (m_error_handler) + delete m_error_handler; + + m_error_handler = handler; +} + +bool Reader::valid() const +{ + return m_error_handler ? m_error_handler->max_error_level() >= PTC_ERROR_CRITICAL : true; +} + +void Reader::get_frame_range(int &start_frame, int &end_frame) +{ + if (m_archive.valid()) { + double start_time, end_time; + GetArchiveStartAndEndTime(m_archive, start_time, end_time); + start_frame = (int)time_to_frame(start_time); + end_frame = (int)time_to_frame(end_time); + } + else { + start_frame = end_frame = 1; + } +} + +ISampleSelector Reader::get_frame_sample_selector(float frame) +{ + return ISampleSelector(frame_to_time(frame), ISampleSelector::kFloorIndex); +} + +PTCReadSampleResult Reader::test_sample(float frame) +{ + if (m_archive.valid()) { + double start_time, end_time; + GetArchiveStartAndEndTime(m_archive, start_time, end_time); + float start_frame = time_to_frame(start_time); + float end_frame = time_to_frame(end_time); + + if (frame < start_frame) + return PTC_READ_SAMPLE_EARLY; + else if (frame > end_frame) + return PTC_READ_SAMPLE_LATE; + else { + /* TODO could also be EXACT, but INTERPOLATED is more general + * do we need to support this? + * checking individual time samplings is also possible, but more involved. + */ + return PTC_READ_SAMPLE_INTERPOLATED; + } + } + else { + return PTC_READ_SAMPLE_INVALID; + } +} + +} /* namespace PTC */ diff --git a/source/blender/pointcache/intern/reader.h b/source/blender/pointcache/intern/reader.h new file mode 100644 index 00000000000..73ebc4ead88 --- /dev/null +++ b/source/blender/pointcache/intern/reader.h @@ -0,0 +1,62 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_READER_H +#define PTC_READER_H + +#include <string> + +#include <Alembic/Abc/IArchive.h> +#include <Alembic/Abc/ISampleSelector.h> + +#include "util/util_error_handler.h" +#include "util/util_frame_mapper.h" +#include "util/util_types.h" + +struct ID; +struct PointCache; +struct Scene; + +namespace PTC { + +using namespace Alembic; + +class Reader : public FrameMapper { +public: + Reader(Scene *scene, ID *id, PointCache *cache); + virtual ~Reader(); + + void set_error_handler(ErrorHandler *handler); + bool valid() const; + + void get_frame_range(int &start_frame, int &end_frame); + Abc::ISampleSelector get_frame_sample_selector(float frame); + + PTCReadSampleResult test_sample(float frame); + virtual PTCReadSampleResult read_sample(float frame) = 0; + +protected: + Abc::IArchive m_archive; + ErrorHandler *m_error_handler; + + Scene *m_scene; +}; + +} /* namespace PTC */ + +#endif /* PTC_READER_H */ diff --git a/source/blender/pointcache/intern/rigidbody.cpp b/source/blender/pointcache/intern/rigidbody.cpp new file mode 100644 index 00000000000..279d3ff01a1 --- /dev/null +++ b/source/blender/pointcache/intern/rigidbody.cpp @@ -0,0 +1,84 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "rigidbody.h" + +extern "C" { +#include "DNA_scene_types.h" +#include "DNA_rigidbody_types.h" +} + +#include "PTC_api.h" + +namespace PTC { + +using namespace Abc; +using namespace AbcGeom; + +RigidBodyWriter::RigidBodyWriter(Scene *scene, RigidBodyWorld *rbw) : + Writer(scene, &scene->id, rbw->pointcache), + m_rbw(rbw) +{ + uint32_t fs = add_frame_sampling(); + + OObject root = m_archive.getTop(); +// m_points = OPoints(root, m_psys->name, fs); +} + +RigidBodyWriter::~RigidBodyWriter() +{ +} + +void RigidBodyWriter::write_sample() +{ +} + + +RigidBodyReader::RigidBodyReader(Scene *scene, RigidBodyWorld *rbw) : + Reader(scene, &scene->id, rbw->pointcache), + m_rbw(rbw) +{ + if (m_archive.valid()) { + IObject root = m_archive.getTop(); +// m_points = IPoints(root, m_psys->name); + } +} + +RigidBodyReader::~RigidBodyReader() +{ +} + +PTCReadSampleResult RigidBodyReader::read_sample(float frame) +{ + return PTC_READ_SAMPLE_INVALID; +} + +} /* namespace PTC */ + + +/* ==== C API ==== */ + +PTCWriter *PTC_writer_rigidbody(Scene *scene, RigidBodyWorld *rbw) +{ + return (PTCWriter *)(new PTC::RigidBodyWriter(scene, rbw)); +} + +PTCReader *PTC_reader_rigidbody(Scene *scene, RigidBodyWorld *rbw) +{ + return (PTCReader *)(new PTC::RigidBodyReader(scene, rbw)); +} diff --git a/source/blender/pointcache/intern/rigidbody.h b/source/blender/pointcache/intern/rigidbody.h new file mode 100644 index 00000000000..bda0e9f65d5 --- /dev/null +++ b/source/blender/pointcache/intern/rigidbody.h @@ -0,0 +1,61 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_RIGIDBODY_H +#define PTC_RIGIDBODY_H + +//#include <Alembic/AbcGeom/IPoints.h> +//#include <Alembic/AbcGeom/OPoints.h> + +#include "reader.h" +#include "schema.h" +#include "writer.h" + +struct RigidBodyWorld; + +namespace PTC { + +class RigidBodyWriter : public Writer { +public: + RigidBodyWriter(Scene *scene, RigidBodyWorld *rbw); + ~RigidBodyWriter(); + + void write_sample(); + +private: + RigidBodyWorld *m_rbw; + +// AbcGeom::OPoints m_points; +}; + +class RigidBodyReader : public Reader { +public: + RigidBodyReader(Scene *scene, RigidBodyWorld *rbw); + ~RigidBodyReader(); + + PTCReadSampleResult read_sample(float frame); + +private: + RigidBodyWorld *m_rbw; + +// AbcGeom::IPoints m_points; +}; + +} /* namespace PTC */ + +#endif /* PTC_RIGIDBODY_H */ diff --git a/source/blender/pointcache/intern/schema.h b/source/blender/pointcache/intern/schema.h new file mode 100644 index 00000000000..a65e927161a --- /dev/null +++ b/source/blender/pointcache/intern/schema.h @@ -0,0 +1,107 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_SCHEMA_H +#define PTC_SCHEMA_H + +#include <Alembic/AbcGeom/SchemaInfoDeclarations.h> +#include <Alembic/AbcGeom/IGeomBase.h> +#include <Alembic/AbcGeom/OGeomBase.h> + +namespace PTC { + +#if 0 +#define PTC_SCHEMA_INFO ALEMBIC_ABCGEOM_DECLARE_SCHEMA_INFO + +using namespace Alembic::AbcGeom; +#endif + + +#if 0 +/* XXX We define an extended schema class to implement the wrapper constructor. + * This was removed in Alembic 1.1 for some reason ... + */ +template <class SCHEMA> +class OSchemaObject : public Abc::OSchemaObject<SCHEMA> +{ +public: + //! The default constructor creates an empty OSchemaObject function set. + //! ... + OSchemaObject() : Abc::OSchemaObject<SCHEMA>() {} + + //! The primary constructor creates an OSchemaObject as a child of the + //! first argument, which is any Abc or AbcCoreAbstract (or other) + //! object which can be intrusively cast to an ObjectWriterPtr. + template <class OBJECT_PTR> + OSchemaObject(OBJECT_PTR iParentObject, + const std::string &iName, + + const Argument &iArg0 = Argument(), + const Argument &iArg1 = Argument(), + const Argument &iArg2 = Argument()) + : Abc::OSchemaObject<SCHEMA>(iParentObject, iName, iArg0, iArg1, iArg2) + {} + + //! Wrap an existing schema object. + //! ... + template <class OBJECT_PTR> + OSchemaObject(OBJECT_PTR iThisObject, + WrapExistingFlag iFlag, + const Argument &iArg0 = Argument(), + const Argument &iArg1 = Argument(), + const Argument &iArg2 = Argument() ); +}; + +//-***************************************************************************** +template<class SCHEMA> +template<class OBJECT_PTR> +inline OSchemaObject<SCHEMA>::OSchemaObject( + OBJECT_PTR iObject, + WrapExistingFlag iFlag, + const Argument &iArg0, + const Argument &iArg1, + const Argument &iArg2 ) + : OObject(iObject, + iFlag, + GetErrorHandlerPolicy(iObject, + iArg0, iArg1, iArg2)) +{ + ALEMBIC_ABC_SAFE_CALL_BEGIN("OSchemaObject::OSchemaObject( wrap )"); + + const AbcA::ObjectHeader &oheader = this->getHeader(); + + Abc::OSchemaObject<SCHEMA>::m_schema = SCHEMA( + this->getProperties().getProperty(SCHEMA::getDefaultSchemaName()).getPtr()->asCompoundPtr(), + iFlag, + this->getErrorHandlerPolicy(), + GetSchemaInterpMatching(iArg0, iArg1, iArg2)); + + /* XXX TODO gives compiler error atm */ +// ABCA_ASSERT(matches(oheader, GetSchemaInterpMatching(iArg0, iArg1, iArg2)), +// "Incorrect match of schema: " +// << oheader.getMetaData().get( "schemaObjTitle" ) +// << " to expected: " +// << getSchemaObjTitle()); + + ALEMBIC_ABC_SAFE_CALL_END_RESET(); +} +#endif + +} /* namespace PTC */ + +#endif /* PTC_SCHEMA_H */ diff --git a/source/blender/pointcache/intern/smoke.cpp b/source/blender/pointcache/intern/smoke.cpp new file mode 100644 index 00000000000..2a12258fb71 --- /dev/null +++ b/source/blender/pointcache/intern/smoke.cpp @@ -0,0 +1,86 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "smoke.h" + +extern "C" { +#include "DNA_object_types.h" +#include "DNA_smoke_types.h" +} + +#include "PTC_api.h" + +namespace PTC { + +using namespace Abc; +using namespace AbcGeom; + +SmokeWriter::SmokeWriter(Scene *scene, Object *ob, SmokeDomainSettings *domain) : + Writer(scene, &ob->id, domain->point_cache[0]), + m_ob(ob), + m_domain(domain) +{ + uint32_t fs = add_frame_sampling(); + + OObject root = m_archive.getTop(); +// m_points = OPoints(root, m_psys->name, fs); +} + +SmokeWriter::~SmokeWriter() +{ +} + +void SmokeWriter::write_sample() +{ +} + + +SmokeReader::SmokeReader(Scene *scene, Object *ob, SmokeDomainSettings *domain) : + Reader(scene, &ob->id, domain->point_cache[0]), + m_ob(ob), + m_domain(domain) +{ + if (m_archive.valid()) { + IObject root = m_archive.getTop(); +// m_points = IPoints(root, m_psys->name); + } +} + +SmokeReader::~SmokeReader() +{ +} + +PTCReadSampleResult SmokeReader::read_sample(float frame) +{ + return PTC_READ_SAMPLE_INVALID; +} + +} /* namespace PTC */ + + +/* ==== C API ==== */ + +PTCWriter *PTC_writer_smoke(Scene *scene, Object *ob, SmokeDomainSettings *domain) +{ + return (PTCWriter *)(new PTC::SmokeWriter(scene, ob, domain)); +} + +PTCReader *PTC_reader_smoke(Scene *scene, Object *ob, SmokeDomainSettings *domain) +{ + return (PTCReader *)(new PTC::SmokeReader(scene, ob, domain)); +} diff --git a/source/blender/pointcache/intern/smoke.h b/source/blender/pointcache/intern/smoke.h new file mode 100644 index 00000000000..dae41f3e334 --- /dev/null +++ b/source/blender/pointcache/intern/smoke.h @@ -0,0 +1,64 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_SMOKE_H +#define PTC_SMOKE_H + +//#include <Alembic/AbcGeom/IPoints.h> +//#include <Alembic/AbcGeom/OPoints.h> + +#include "reader.h" +#include "schema.h" +#include "writer.h" + +struct Object; +struct SmokeDomainSettings; + +namespace PTC { + +class SmokeWriter : public Writer { +public: + SmokeWriter(Scene *scene, Object *ob, SmokeDomainSettings *domain); + ~SmokeWriter(); + + void write_sample(); + +private: + Object *m_ob; + SmokeDomainSettings *m_domain; + +// AbcGeom::OPoints m_points; +}; + +class SmokeReader : public Reader { +public: + SmokeReader(Scene *scene, Object *ob, SmokeDomainSettings *domain); + ~SmokeReader(); + + PTCReadSampleResult read_sample(float frame); + +private: + Object *m_ob; + SmokeDomainSettings *m_domain; + +// AbcGeom::IPoints m_points; +}; + +} /* namespace PTC */ + +#endif /* PTC_SMOKE_H */ diff --git a/source/blender/pointcache/intern/softbody.cpp b/source/blender/pointcache/intern/softbody.cpp new file mode 100644 index 00000000000..a0cbb05e85e --- /dev/null +++ b/source/blender/pointcache/intern/softbody.cpp @@ -0,0 +1,86 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "softbody.h" + +extern "C" { +#include "DNA_object_types.h" +#include "DNA_object_force.h" +} + +#include "PTC_api.h" + +namespace PTC { + +using namespace Abc; +using namespace AbcGeom; + +SoftBodyWriter::SoftBodyWriter(Scene *scene, Object *ob, SoftBody *softbody) : + Writer(scene, &ob->id, softbody->pointcache), + m_ob(ob), + m_softbody(softbody) +{ + uint32_t fs = add_frame_sampling(); + + OObject root = m_archive.getTop(); +// m_points = OPoints(root, m_psys->name, fs); +} + +SoftBodyWriter::~SoftBodyWriter() +{ +} + +void SoftBodyWriter::write_sample() +{ +} + + +SoftBodyReader::SoftBodyReader(Scene *scene, Object *ob, SoftBody *softbody) : + Reader(scene, &ob->id, softbody->pointcache), + m_ob(ob), + m_softbody(softbody) +{ + if (m_archive.valid()) { + IObject root = m_archive.getTop(); +// m_points = IPoints(root, m_psys->name); + } +} + +SoftBodyReader::~SoftBodyReader() +{ +} + +PTCReadSampleResult SoftBodyReader::read_sample(float frame) +{ + return PTC_READ_SAMPLE_INVALID; +} + +} /* namespace PTC */ + + +/* ==== C API ==== */ + +PTCWriter *PTC_writer_softbody(Scene *scene, Object *ob, SoftBody *softbody) +{ + return (PTCWriter *)(new PTC::SoftBodyWriter(scene, ob, softbody)); +} + +PTCReader *PTC_reader_softbody(Scene *scene, Object *ob, SoftBody *softbody) +{ + return (PTCReader *)(new PTC::SoftBodyReader(scene, ob, softbody)); +} diff --git a/source/blender/pointcache/intern/softbody.h b/source/blender/pointcache/intern/softbody.h new file mode 100644 index 00000000000..85704f47a12 --- /dev/null +++ b/source/blender/pointcache/intern/softbody.h @@ -0,0 +1,64 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_SOFTBODY_H +#define PTC_SOFTBODY_H + +//#include <Alembic/AbcGeom/IPoints.h> +//#include <Alembic/AbcGeom/OPoints.h> + +#include "reader.h" +#include "schema.h" +#include "writer.h" + +struct Object; +struct SoftBody; + +namespace PTC { + +class SoftBodyWriter : public Writer { +public: + SoftBodyWriter(Scene *scene, Object *ob, SoftBody *softbody); + ~SoftBodyWriter(); + + void write_sample(); + +private: + Object *m_ob; + SoftBody *m_softbody; + +// AbcGeom::OPoints m_points; +}; + +class SoftBodyReader : public Reader { +public: + SoftBodyReader(Scene *scene, Object *ob, SoftBody *softbody); + ~SoftBodyReader(); + + PTCReadSampleResult read_sample(float frame); + +private: + Object *m_ob; + SoftBody *m_softbody; + +// AbcGeom::IPoints m_points; +}; + +} /* namespace PTC */ + +#endif /* PTC_SOFTBODY_H */ diff --git a/source/blender/pointcache/intern/thread.h b/source/blender/pointcache/intern/thread.h new file mode 100644 index 00000000000..229c0f54f59 --- /dev/null +++ b/source/blender/pointcache/intern/thread.h @@ -0,0 +1,31 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_THREAD_H +#define PTC_THREAD_H + +#include <boost/thread.hpp> + +namespace PTC { + +typedef boost::mutex thread_mutex; +typedef boost::mutex::scoped_lock thread_scoped_lock; + +} /* namespace PTC */ + +#endif /* PTC_THREAD_H */ diff --git a/source/blender/pointcache/intern/writer.cpp b/source/blender/pointcache/intern/writer.cpp new file mode 100644 index 00000000000..2a9173b0ddb --- /dev/null +++ b/source/blender/pointcache/intern/writer.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <Alembic/AbcCoreHDF5/ReadWrite.h> + +#include "writer.h" +#include "util_path.h" + +extern "C" { +#include "BLI_fileops.h" +#include "BLI_path_util.h" + +#include "DNA_scene_types.h" +} + +namespace PTC { + +using namespace Abc; + +/* make sure the file's directory exists */ +static void ensure_directory(const char *filename) +{ + char dir[FILE_MAXDIR]; + BLI_split_dir_part(filename, dir, sizeof(dir)); + BLI_dir_create_recursive(dir); +} + +Writer::Writer(Scene *scene, ID *id, PointCache *cache) : + FrameMapper(scene), + m_error_handler(0), + m_scene(scene) +{ + std::string filename = ptc_archive_path(cache, id); + ensure_directory(filename.c_str()); + PTC_SAFE_CALL_BEGIN + m_archive = OArchive(AbcCoreHDF5::WriteArchive(), filename, Abc::ErrorHandler::kThrowPolicy); + PTC_SAFE_CALL_END_HANDLER(m_error_handler) +} + +Writer::~Writer() +{ + if (m_error_handler) + delete m_error_handler; +} + +void Writer::set_error_handler(ErrorHandler *handler) +{ + if (m_error_handler) + delete m_error_handler; + + m_error_handler = handler; +} + +bool Writer::valid() const +{ + return m_error_handler ? m_error_handler->max_error_level() >= PTC_ERROR_CRITICAL : true; +} + +uint32_t Writer::add_frame_sampling() +{ + chrono_t cycle_time = seconds_per_frame(); + chrono_t start_time = 0.0f; + return m_archive.addTimeSampling(TimeSampling(cycle_time, start_time)); +} + +} /* namespace PTC */ diff --git a/source/blender/pointcache/intern/writer.h b/source/blender/pointcache/intern/writer.h new file mode 100644 index 00000000000..8a62cf665f8 --- /dev/null +++ b/source/blender/pointcache/intern/writer.h @@ -0,0 +1,58 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_WRITER_H +#define PTC_WRITER_H + +#include <string> + +#include <Alembic/Abc/OArchive.h> + +#include "util/util_error_handler.h" +#include "util/util_frame_mapper.h" + +struct ID; +struct PointCache; +struct Scene; + +namespace PTC { + +using namespace Alembic; + +class Writer : public FrameMapper { +public: + Writer(Scene *scene, ID *id, PointCache *cache); + virtual ~Writer(); + + void set_error_handler(ErrorHandler *handler); + bool valid() const; + + uint32_t add_frame_sampling(); + + virtual void write_sample() = 0; + +protected: + Abc::OArchive m_archive; + ErrorHandler *m_error_handler; + + Scene *m_scene; +}; + +} /* namespace PTC */ + +#endif /* PTC_WRITER_H */ diff --git a/source/blender/pointcache/util/util_error_handler.cpp b/source/blender/pointcache/util/util_error_handler.cpp new file mode 100644 index 00000000000..49918b1765a --- /dev/null +++ b/source/blender/pointcache/util/util_error_handler.cpp @@ -0,0 +1,100 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "util_error_handler.h" + +extern "C" { +#include "BKE_modifier.h" +} + +namespace PTC { + +ErrorHandler *ErrorHandler::m_default_handler = new StdErrorHandler(PTC_ERROR_INFO); + +ErrorHandler::ErrorHandler() : + m_max_level(PTC_ERROR_NONE) +{ +} + +ErrorHandler::~ErrorHandler() +{ +} + +void ErrorHandler::set_error_level(PTCErrorLevel level) +{ + if (level > m_max_level) + m_max_level = level; +} + +void ErrorHandler::set_default_handler(ErrorHandler *handler) +{ + if (m_default_handler) + delete m_default_handler; + + if (handler) + m_default_handler = handler; + else + m_default_handler = new StdErrorHandler(PTC_ERROR_INFO); +} + +void ErrorHandler::clear_default_handler() +{ + if (m_default_handler) + delete m_default_handler; + + m_default_handler = new StdErrorHandler(PTC_ERROR_INFO); +} + + +StdErrorHandler::StdErrorHandler(PTCErrorLevel level) : + m_verbosity(level) +{ +} + +void StdErrorHandler::handle(PTCErrorLevel level, const char *message) +{ + /* ignore levels below the verbosity setting */ + if (level >= m_verbosity) { + std::cerr << message << std::endl; + } +} + + +CallbackErrorHandler::CallbackErrorHandler(PTCErrorCallback cb, void *userdata) : + m_callback(cb), + m_userdata(userdata) +{ +} + +void CallbackErrorHandler::handle(PTCErrorLevel level, const char *message) +{ + m_callback(m_userdata, level, message); +} + + +ModifierErrorHandler::ModifierErrorHandler(ModifierData *md) : + m_modifier(md) +{ +} + +void ModifierErrorHandler::handle(PTCErrorLevel UNUSED(level), const char *message) +{ + modifier_setError(m_modifier, "%s", message); +} + +} /* namespace PTC */ diff --git a/source/blender/pointcache/util/util_error_handler.h b/source/blender/pointcache/util/util_error_handler.h new file mode 100644 index 00000000000..b70e82df04f --- /dev/null +++ b/source/blender/pointcache/util/util_error_handler.h @@ -0,0 +1,178 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_UTIL_ERROR_HANDLER_H +#define PTC_UTIL_ERROR_HANDLER_H + +#include <stdio.h> + +#include <Alembic/Abc/ErrorHandler.h> + +extern "C" { +#include "BLI_utildefines.h" +#include "BLI_string.h" +} + +#include "util/util_types.h" + +struct ModifierData; +struct ReportList; + +namespace PTC { + +class ErrorHandler +{ +public: + ErrorHandler(); + virtual ~ErrorHandler(); + + virtual void handle(PTCErrorLevel level, const char *message) = 0; + void set_error_level(PTCErrorLevel level); + PTCErrorLevel max_error_level() const { return m_max_level; } + + static ErrorHandler *get_default_handler() { return m_default_handler; } + static void set_default_handler(ErrorHandler *handler); + static void clear_default_handler(); + +private: + PTCErrorLevel m_max_level; + + static ErrorHandler *m_default_handler; +}; + + +class StdErrorHandler : public ErrorHandler +{ +public: + StdErrorHandler(PTCErrorLevel level); + + void handle(PTCErrorLevel level, const char *message); + + PTCErrorLevel get_verbosity() const { return m_verbosity; } + void set_verbosity(PTCErrorLevel level) { m_verbosity = level; } + +private: + PTCErrorLevel m_verbosity; +}; + + +/* Use Blender reports system to log Alembic errors */ +class CallbackErrorHandler : public ErrorHandler +{ +public: + CallbackErrorHandler(PTCErrorCallback cb, void *userdata); + + void handle(PTCErrorLevel level, const char *message); + +private: + PTCErrorCallback m_callback; + void *m_userdata; +}; + + +class ModifierErrorHandler : public ErrorHandler +{ +public: + ModifierErrorHandler(ModifierData *md); + + void handle(PTCErrorLevel level, const char *message); + +private: + ModifierData *m_modifier; +}; + +/* -------------------------------- */ + +/* XXX With current Alembic version 1.5 we only get a combined error message. + * This function try to extract some more information and return a nicer message format. + */ +BLI_INLINE void split_alembic_error_message(const char *msg, const char **origin, const char **base_msg) +{ + const char delim[] = {'\n', '\0'}; + char *sep, *suffix; + + BLI_str_partition(msg, delim, &sep, &suffix); + if (suffix) { + *origin = msg; + BLI_str_partition(suffix, delim, &sep, &suffix); + if (suffix) { + *base_msg = suffix; + } + else { + *base_msg = msg; + } + } + else { + *origin = *base_msg = msg; + } +} + +/* wrapper templates so the exception macro can be used with references as well as pointers */ + +template <typename T> +void handle_alembic_exception(T &handler, PTCErrorLevel level, const Alembic::Util::Exception &e) +{ + const char *origin, *msg; + split_alembic_error_message(e.what(), &origin, &msg); + + handler.set_error_level(level); + handler.handle(level, msg); +} + +template <typename T> +void handle_alembic_exception(T *handler, PTCErrorLevel level, const Alembic::Util::Exception &e) +{ + if (handler) { + const char *origin, *msg; + split_alembic_error_message(e.what(), &origin, &msg); + + handler->set_error_level(level); + handler->handle(level, msg); + } +} + +/* -------------------------------- */ + +/* macros for convenient exception handling */ + +#define PTC_SAFE_CALL_BEGIN \ + try { + +#define PTC_SAFE_CALL_END_HANDLER(handler) \ + } \ + catch (Alembic::Util::Exception e) { \ + handle_alembic_exception((handler), PTC_ERROR_CRITICAL, e); \ + } + +#define PTC_SAFE_CALL_END_HANDLER_LEVEL(handler, level) \ + } \ + catch (Alembic::Util::Exception e) { \ + handle_alembic_exception((handler), (level), e); \ + } + +#define PTC_SAFE_CALL_END \ + } \ + catch (Alembic::Util::Exception e) { \ + handle_alembic_exception(ErrorHandler::get_default_handler(), PTC_ERROR_CRITICAL, e); \ + } + +/* -------------------------------- */ + +} /* namespace PTC */ + +#endif /* PTC_UTIL_ERROR_HANDLER_H */ diff --git a/source/blender/pointcache/util/util_frame_mapper.cpp b/source/blender/pointcache/util/util_frame_mapper.cpp new file mode 100644 index 00000000000..48b1ea58f7a --- /dev/null +++ b/source/blender/pointcache/util/util_frame_mapper.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "util_frame_mapper.h" + +extern "C" { +#include "DNA_scene_types.h" +} + +namespace PTC { + +using namespace Abc; +using namespace AbcCoreAbstract; + +FrameMapper::FrameMapper(double fps) +{ + m_frames_per_sec = fps; + m_sec_per_frame = (fps == 0.0 ? 0.0 : 1.0/fps); +} + +FrameMapper::FrameMapper(Scene *scene) +{ + m_frames_per_sec = (scene->r.frs_sec_base == 0.0f ? 0.0 : (double)scene->r.frs_sec / (double)scene->r.frs_sec_base); + m_sec_per_frame = (scene->r.frs_sec == 0.0f ? 0.0 : (double)scene->r.frs_sec_base / (double)scene->r.frs_sec); +} + +chrono_t FrameMapper::frame_to_time(float frame) const +{ + return (double)(frame - 1.0f) * m_sec_per_frame; +} + +float FrameMapper::time_to_frame(chrono_t time) const +{ + return (float)(time * m_frames_per_sec) + 1.0f; +} + +} /* namespace PTC */ diff --git a/source/blender/pointcache/util/util_frame_mapper.h b/source/blender/pointcache/util/util_frame_mapper.h new file mode 100644 index 00000000000..40574ae58c6 --- /dev/null +++ b/source/blender/pointcache/util/util_frame_mapper.h @@ -0,0 +1,49 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_UTIL_FRAME_MAPPER_H +#define PTC_UTIL_FRAME_MAPPER_H + +#include <Alembic/AbcCoreAbstract/Foundation.h> +#include <Alembic/Abc/ISampleSelector.h> + +struct Scene; + +namespace PTC { + +using namespace Alembic; +using Alembic::AbcCoreAbstract::chrono_t; + +class FrameMapper { +public: + FrameMapper(double fps); + FrameMapper(Scene *scene); + + double frames_per_second() const { return m_frames_per_sec; } + double seconds_per_frame() const { return m_sec_per_frame; } + + chrono_t frame_to_time(float frame) const; + float time_to_frame(chrono_t time) const; + +private: + double m_frames_per_sec, m_sec_per_frame; +}; + +} /* namespace PTC */ + +#endif /* PTC_UTIL_FRAME_MAPPER_H */ diff --git a/source/blender/pointcache/util/util_path.cpp b/source/blender/pointcache/util/util_path.cpp new file mode 100644 index 00000000000..4d543fb87e6 --- /dev/null +++ b/source/blender/pointcache/util/util_path.cpp @@ -0,0 +1,119 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <string.h> /* XXX needed for missing type declarations in BLI ... */ + +#include "util_path.h" + +extern "C" { +#include "BLI_path_util.h" +#include "BLI_string.h" + +#include "DNA_ID.h" +#include "DNA_pointcache_types.h" + +#include "BKE_appdir.h" +#include "BKE_global.h" +#include "BKE_main.h" +} + +namespace PTC { + +/* XXX do we want to use BLI C string functions here? just copied from BKE_pointcache for now */ + +static int ptc_path(char *filename, const char *path, ID *id, bool is_external, bool ignore_libpath) +{ + Library *lib = id ? id->lib : NULL; + const char *blendfilename= (lib && !ignore_libpath) ? lib->filepath: G.main->name; + + if (path && is_external) { + strcpy(filename, path); + + if (BLI_path_is_rel(filename)) { + BLI_path_abs(filename, blendfilename); + } + } + else if (G.relbase_valid || lib) { + char file[FILE_MAXFILE]; /* we don't want the dir, only the file */ + + BLI_split_file_part(blendfilename, file, sizeof(file)); + BLI_replace_extension(file, sizeof(file), ""); /* remove extension */ + BLI_snprintf(filename, FILE_MAX, "//" PTC_DIRECTORY "%s", file); /* add blend file name to pointcache dir */ + BLI_path_abs(filename, blendfilename); + } + else { + /* use the temp path. this is weak but better then not using point cache at all */ + /* temporary directory is assumed to exist and ALWAYS has a trailing slash */ + BLI_snprintf(filename, FILE_MAX, "%s" PTC_DIRECTORY, BKE_tempdir_session()); + } + + return BLI_add_slash(filename); /* new strlen() */ +} + +static int ptc_filename(char *filename, const char *name, int index, const char *path, ID *id, + bool do_path, bool do_ext, bool is_external, bool ignore_libpath) +{ + char *newname; + int len = 0; + filename[0] = '\0'; + newname = filename; + + if (!G.relbase_valid && !is_external) + return 0; /* save blend file before using disk pointcache */ + + /* start with temp dir */ + if (do_path) { + len = ptc_path(filename, path, id, is_external, ignore_libpath); + newname += len; + } + if (name[0] == '\0' && !is_external) { + const char *idname = (id->name + 2); + /* convert chars to hex so they are always a valid filename */ + while ('\0' != *idname) { + BLI_snprintf(newname, FILE_MAX, "%02X", (char)(*idname++)); + newname += 2; + len += 2; + } + } + else { + int namelen = (int)strlen(name); + strcpy(newname, name); + newname += namelen; + len += namelen; + } + + if (do_ext) { + if (index < 0 || !is_external) { + len += BLI_snprintf(newname, FILE_MAX, PTC_EXTENSION); + } + else { + len += BLI_snprintf(newname, FILE_MAX, "_%02u" PTC_EXTENSION, index); + } + } + + return len; +} + +std::string ptc_archive_path(PointCache *cache, ID *id) +{ + char filename[FILE_MAX]; + ptc_filename(filename, cache->name, cache->index, cache->path, id, true, true, cache->flag & PTC_EXTERNAL, cache->flag & PTC_IGNORE_LIBPATH); + return std::string(filename); +} + +} /* namespace PTC */ diff --git a/source/blender/pointcache/util/util_path.h b/source/blender/pointcache/util/util_path.h new file mode 100644 index 00000000000..5cff2f7f7b5 --- /dev/null +++ b/source/blender/pointcache/util/util_path.h @@ -0,0 +1,37 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_UTIL_PATH_H +#define PTC_UTIL_PATH_H + +#include <string> + +struct ID; +struct PointCache; + +namespace PTC { + +/* XXX make these configurable, just copied from BKE_pointcache for now */ +#define PTC_EXTENSION ".abc" +#define PTC_DIRECTORY "blendcache_" + +std::string ptc_archive_path(PointCache *cache, ID *id); + +} /* namespace PTC */ + +#endif /* PTC_UTIL_PATH_H */ diff --git a/source/blender/pointcache/util/util_types.h b/source/blender/pointcache/util/util_types.h new file mode 100644 index 00000000000..bf9c97059e9 --- /dev/null +++ b/source/blender/pointcache/util/util_types.h @@ -0,0 +1,47 @@ +/* + * Copyright 2013, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PTC_UTIL_TYPES_H +#define PTC_UTIL_TYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum PTCErrorLevel { + PTC_ERROR_NONE = 0, + PTC_ERROR_INFO = 1, + PTC_ERROR_WARNING = 2, + PTC_ERROR_CRITICAL = 3, +} PTCErrorLevel; + +typedef void (*PTCErrorCallback)(void *userdata, PTCErrorLevel level, const char *message); + +typedef enum PTCReadSampleResult { + PTC_READ_SAMPLE_INVALID = 0, /* no valid result can be retrieved */ + PTC_READ_SAMPLE_EARLY, /* request time before first sample */ + PTC_READ_SAMPLE_LATE, /* request time after last sample */ + PTC_READ_SAMPLE_EXACT, /* found sample for requested frame */ + PTC_READ_SAMPLE_INTERPOLATED /* no exact sample, but found enclosing samples for interpolation */ +} PTCReadSampleResult; + +#ifdef __cplusplus +} +#endif + +#endif /* PTC_UTIL_TYPES_H */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 87961c03ed2..0c17d2dd15d 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2707,26 +2707,9 @@ static void validate_render_settings(Render *re) } } -static void update_physics_cache(Render *re, Scene *scene, int UNUSED(anim_init)) -{ - PTCacheBaker baker; - - baker.main = re->main; - baker.scene = scene; - baker.pid = NULL; - baker.bake = 0; - baker.render = 1; - baker.anim_init = 1; - baker.quick_step = 1; - baker.break_test = re->test_break; - baker.break_data = re->tbh; - baker.progressbar = NULL; - - BKE_ptcache_bake(&baker); -} /* evaluating scene options for general Blender render */ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, Scene *scene, SceneRenderLayer *srl, - Object *camera_override, unsigned int lay_override, int anim, int anim_init) + Object *camera_override, unsigned int lay_override, int anim) { int winx, winy; rcti disprect; @@ -2770,16 +2753,6 @@ static int render_initialize_from_main(Render *re, RenderData *rd, Main *bmain, /* check all scenes involved */ tag_scenes_for_render(re); - /* - * Disabled completely for now, - * can be later set as render profile option - * and default for background render. - */ - if (0) { - /* make sure dynamics are up to date */ - update_physics_cache(re, scene, anim_init); - } - if (srl || scene->r.scemode & R_SINGLE_LAYER) { BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); render_result_single_layer_begin(re); @@ -2817,7 +2790,7 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr scene->r.cfra = frame; - if (render_initialize_from_main(re, &scene->r, bmain, scene, srl, camera_override, lay_override, 0, 0)) { + if (render_initialize_from_main(re, &scene->r, bmain, scene, srl, camera_override, lay_override, 0)) { MEM_reset_peak_memory(); BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_PRE); @@ -2855,7 +2828,7 @@ void RE_BlenderFrame(Render *re, Main *bmain, Scene *scene, SceneRenderLayer *sr void RE_RenderFreestyleStrokes(Render *re, Main *bmain, Scene *scene, int render) { re->result_ok= 0; - if (render_initialize_from_main(re, &scene->r, bmain, scene, NULL, NULL, scene->lay, 0, 0)) { + if (render_initialize_from_main(re, &scene->r, bmain, scene, NULL, NULL, scene->lay, 0)) { if (render) do_render_fields_blur_3d(re); } @@ -2992,7 +2965,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri BLI_callback_exec(re->main, (ID *)scene, BLI_CB_EVT_RENDER_INIT); /* do not fully call for each frame, it initializes & pops output window */ - if (!render_initialize_from_main(re, &rd, bmain, scene, NULL, camera_override, lay_override, 0, 1)) + if (!render_initialize_from_main(re, &rd, bmain, scene, NULL, camera_override, lay_override, 0)) return; /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */ @@ -3055,7 +3028,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri char name[FILE_MAX]; /* only border now, todo: camera lens. (ton) */ - render_initialize_from_main(re, &rd, bmain, scene, NULL, camera_override, lay_override, 1, 0); + render_initialize_from_main(re, &rd, bmain, scene, NULL, camera_override, lay_override, 1); if (nfra != scene->r.cfra) { /* diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c index f21a1e5fa9b..69a1317cf7d 100644 --- a/source/blender/render/intern/source/voxeldata.c +++ b/source/blender/render/intern/source/voxeldata.c @@ -61,6 +61,7 @@ #include "DNA_texture_types.h" #include "DNA_object_force.h" #include "DNA_object_types.h" +#include "DNA_pointcache_types.h" #include "DNA_modifier_types.h" #include "DNA_smoke_types.h" diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index d2abfd419d1..b1692e44ad0 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -392,6 +392,7 @@ enum { WM_JOB_TYPE_OBJECT_SIM_FLUID, WM_JOB_TYPE_OBJECT_BAKE_TEXTURE, WM_JOB_TYPE_OBJECT_BAKE, + WM_JOB_TYPE_PTCACHE_EXPORT, WM_JOB_TYPE_FILESEL_THUMBNAIL, WM_JOB_TYPE_CLIP_BUILD_PROXY, WM_JOB_TYPE_CLIP_TRACK_MARKERS, |