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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/blender/CMakeLists.txt2
-rw-r--r--source/blender/SConscript3
-rw-r--r--source/blender/blenkernel/BKE_particle.h6
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h39
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/SConscript1
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c76
-rw-r--r--source/blender/blenkernel/intern/bpath.c29
-rw-r--r--source/blender/blenkernel/intern/cloth.c26
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c2
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c24
-rw-r--r--source/blender/blenkernel/intern/object.c9
-rw-r--r--source/blender/blenkernel/intern/particle.c40
-rw-r--r--source/blender/blenkernel/intern/particle_system.c137
-rw-r--r--source/blender/blenkernel/intern/pointcache.c1142
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c25
-rw-r--r--source/blender/blenkernel/intern/smoke.c21
-rw-r--r--source/blender/blenkernel/intern/softbody.c25
-rw-r--r--source/blender/blenloader/intern/readfile.c112
-rw-r--r--source/blender/blenloader/intern/versioning_250.c2
-rw-r--r--source/blender/blenloader/intern/versioning_270.c75
-rw-r--r--source/blender/blenloader/intern/versioning_legacy.c18
-rw-r--r--source/blender/blenloader/intern/writefile.c75
-rw-r--r--source/blender/editors/object/object_edit.c2
-rw-r--r--source/blender/editors/physics/CMakeLists.txt1
-rw-r--r--source/blender/editors/physics/SConscript1
-rw-r--r--source/blender/editors/physics/particle_edit.c203
-rw-r--r--source/blender/editors/physics/physics_intern.h8
-rw-r--r--source/blender/editors/physics/physics_ops.c8
-rw-r--r--source/blender/editors/physics/physics_pointcache.c422
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c2
-rw-r--r--source/blender/editors/space_time/space_time.c9
-rw-r--r--source/blender/editors/space_view3d/drawobject.c1
-rw-r--r--source/blender/editors/transform/transform_conversions.c2
-rw-r--r--source/blender/ikplugin/intern/itasc_plugin.cpp4
-rw-r--r--source/blender/makesdna/DNA_dynamicpaint_types.h3
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h17
-rw-r--r--source/blender/makesdna/DNA_object_force.h109
-rw-r--r--source/blender/makesdna/DNA_particle_types.h3
-rw-r--r--source/blender/makesdna/DNA_pointcache_types.h192
-rw-r--r--source/blender/makesdna/DNA_rigidbody_types.h3
-rw-r--r--source/blender/makesdna/DNA_smoke_types.h4
-rw-r--r--source/blender/makesdna/intern/makesdna.c2
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/SConscript1
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt6
-rw-r--r--source/blender/makesrna/intern/SConscript1
-rw-r--r--source/blender/makesrna/intern/makesrna.c1
-rw-r--r--source/blender/makesrna/intern/rna_fluidsim.c2
-rw-r--r--source/blender/makesrna/intern/rna_internal.h1
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c21
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c350
-rw-r--r--source/blender/makesrna/intern/rna_particle.c11
-rw-r--r--source/blender/makesrna/intern/rna_pointcache.c294
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c5
-rw-r--r--source/blender/modifiers/CMakeLists.txt2
-rw-r--r--source/blender/modifiers/MOD_modifiertypes.h1
-rw-r--r--source/blender/modifiers/SConscript1
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c10
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c2
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c4
-rw-r--r--source/blender/modifiers/intern/MOD_pointcache.c171
-rw-r--r--source/blender/modifiers/intern/MOD_util.c1
-rw-r--r--source/blender/pointcache/CMakeLists.txt87
-rw-r--r--source/blender/pointcache/PTC_api.cpp246
-rw-r--r--source/blender/pointcache/PTC_api.h119
-rw-r--r--source/blender/pointcache/SConscript58
-rw-r--r--source/blender/pointcache/intern/cloth.cpp86
-rw-r--r--source/blender/pointcache/intern/cloth.h64
-rw-r--r--source/blender/pointcache/intern/dynamicpaint.cpp86
-rw-r--r--source/blender/pointcache/intern/dynamicpaint.h64
-rw-r--r--source/blender/pointcache/intern/export.cpp76
-rw-r--r--source/blender/pointcache/intern/export.h57
-rw-r--r--source/blender/pointcache/intern/mesh.cpp674
-rw-r--r--source/blender/pointcache/intern/mesh.h82
-rw-r--r--source/blender/pointcache/intern/particles.cpp345
-rw-r--r--source/blender/pointcache/intern/particles.h511
-rw-r--r--source/blender/pointcache/intern/reader.cpp109
-rw-r--r--source/blender/pointcache/intern/reader.h62
-rw-r--r--source/blender/pointcache/intern/rigidbody.cpp84
-rw-r--r--source/blender/pointcache/intern/rigidbody.h61
-rw-r--r--source/blender/pointcache/intern/schema.h107
-rw-r--r--source/blender/pointcache/intern/smoke.cpp86
-rw-r--r--source/blender/pointcache/intern/smoke.h64
-rw-r--r--source/blender/pointcache/intern/softbody.cpp86
-rw-r--r--source/blender/pointcache/intern/softbody.h64
-rw-r--r--source/blender/pointcache/intern/thread.h31
-rw-r--r--source/blender/pointcache/intern/writer.cpp81
-rw-r--r--source/blender/pointcache/intern/writer.h58
-rw-r--r--source/blender/pointcache/util/util_error_handler.cpp100
-rw-r--r--source/blender/pointcache/util/util_error_handler.h178
-rw-r--r--source/blender/pointcache/util/util_frame_mapper.cpp52
-rw-r--r--source/blender/pointcache/util/util_frame_mapper.h49
-rw-r--r--source/blender/pointcache/util/util_path.cpp119
-rw-r--r--source/blender/pointcache/util/util_path.h37
-rw-r--r--source/blender/pointcache/util/util_types.h47
-rw-r--r--source/blender/render/intern/source/pipeline.c37
-rw-r--r--source/blender/render/intern/source/voxeldata.c1
-rw-r--r--source/blender/windowmanager/WM_api.h1
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, &timescale);
@@ -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,