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
diff options
context:
space:
mode:
-rw-r--r--build_files/cmake/macros.cmake2
-rw-r--r--source/blender/CMakeLists.txt1
-rw-r--r--source/blender/SConscript3
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/SConscript1
-rw-r--r--source/blender/modifiers/CMakeLists.txt1
-rw-r--r--source/blender/modifiers/SConscript1
-rw-r--r--source/blender/pointcache/CMakeLists.txt65
-rw-r--r--source/blender/pointcache/PTC_api.cpp403
-rw-r--r--source/blender/pointcache/PTC_api.h125
-rw-r--r--source/blender/pointcache/SConscript58
-rw-r--r--source/blender/pointcache/alembic/CMakeLists.txt69
-rw-r--r--source/blender/pointcache/alembic/abc_cloth.cpp254
-rw-r--r--source/blender/pointcache/alembic/abc_cloth.h70
-rw-r--r--source/blender/pointcache/alembic/abc_dynamicpaint.cpp85
-rw-r--r--source/blender/pointcache/alembic/abc_dynamicpaint.h62
-rw-r--r--source/blender/pointcache/alembic/abc_frame_mapper.cpp56
-rw-r--r--source/blender/pointcache/alembic/abc_frame_mapper.h55
-rw-r--r--source/blender/pointcache/alembic/abc_mesh.cpp597
-rw-r--r--source/blender/pointcache/alembic/abc_mesh.h77
-rw-r--r--source/blender/pointcache/alembic/abc_particles.cpp562
-rw-r--r--source/blender/pointcache/alembic/abc_particles.h128
-rw-r--r--source/blender/pointcache/alembic/abc_reader.cpp99
-rw-r--r--source/blender/pointcache/alembic/abc_reader.h60
-rw-r--r--source/blender/pointcache/alembic/abc_rigidbody.cpp83
-rw-r--r--source/blender/pointcache/alembic/abc_rigidbody.h61
-rw-r--r--source/blender/pointcache/alembic/abc_schema.h107
-rw-r--r--source/blender/pointcache/alembic/abc_smoke.cpp87
-rw-r--r--source/blender/pointcache/alembic/abc_smoke.h62
-rw-r--r--source/blender/pointcache/alembic/abc_softbody.cpp87
-rw-r--r--source/blender/pointcache/alembic/abc_softbody.h62
-rw-r--r--source/blender/pointcache/alembic/abc_writer.cpp73
-rw-r--r--source/blender/pointcache/alembic/abc_writer.h57
-rw-r--r--source/blender/pointcache/intern/alembic.h72
-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/ptc_types.cpp42
-rw-r--r--source/blender/pointcache/intern/ptc_types.h276
-rw-r--r--source/blender/pointcache/intern/reader.cpp55
-rw-r--r--source/blender/pointcache/intern/reader.h75
-rw-r--r--source/blender/pointcache/intern/thread.h31
-rw-r--r--source/blender/pointcache/intern/writer.cpp54
-rw-r--r--source/blender/pointcache/intern/writer.h61
-rw-r--r--source/blender/pointcache/util/util_error_handler.cpp102
-rw-r--r--source/blender/pointcache/util/util_error_handler.h201
-rw-r--r--source/blender/pointcache/util/util_path.cpp101
-rw-r--r--source/blender/pointcache/util/util_path.h35
-rw-r--r--source/blender/pointcache/util/util_types.h47
-rw-r--r--source/blender/windowmanager/WM_api.h1
49 files changed, 4799 insertions, 1 deletions
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 17a1b60b266..fa29ba3d556 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -566,6 +566,8 @@ macro(SETUP_BLENDER_SORTED_LIBS)
ge_videotex
bf_dna
bf_blenfont
+ bf_pointcache
+ bf_pointcache_alembic
bf_intern_audaspace
bf_intern_mikktspace
bf_intern_dualcon
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index d87d5dfc2cc..6738edc70bc 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -108,6 +108,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 64eca6a62db..a0ad4576e57 100644
--- a/source/blender/SConscript
+++ b/source/blender/SConscript
@@ -43,7 +43,8 @@ SConscript(['avi/SConscript',
'ikplugin/SConscript',
'physics/SConscript',
'windowmanager/SConscript',
- 'blenfont/SConscript'])
+ 'blenfont/SConscript',
+ 'pointcache/SConscript'])
makesrna = SConscript('makesrna/SConscript')
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index f19c1066766..d92868edb2d 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -37,6 +37,7 @@ set(INC
../modifiers
../nodes
../physics
+ ../pointcache
../render/extern/include
../../../intern/ghost
../../../intern/guardedalloc
diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript
index 47bba5f5537..8c5d245b69c 100644
--- a/source/blender/blenkernel/SConscript
+++ b/source/blender/blenkernel/SConscript
@@ -66,6 +66,7 @@ incs = [
'../modifiers',
'../nodes',
'../physics',
+ '../pointcache',
'../render/extern/include',
'../windowmanager',
env['BF_ZLIB_INC'],
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index 57e927fffed..6a05c40bf72 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
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/pointcache/CMakeLists.txt b/source/blender/pointcache/CMakeLists.txt
new file mode 100644
index 00000000000..ed8a69c4c0f
--- /dev/null
+++ b/source/blender/pointcache/CMakeLists.txt
@@ -0,0 +1,65 @@
+# ***** 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
+)
+
+set(SRC
+ intern/alembic.h
+ intern/export.h
+ intern/export.cpp
+ intern/ptc_types.h
+ intern/ptc_types.cpp
+ intern/reader.h
+ intern/reader.cpp
+ intern/thread.h
+ intern/writer.h
+ intern/writer.cpp
+
+ util/util_error_handler.h
+ util/util_error_handler.cpp
+ util/util_path.h
+ util/util_path.cpp
+ util/util_types.h
+
+ PTC_api.h
+ PTC_api.cpp
+)
+
+if(WITH_ALEMBIC)
+ add_definitions(-DWITH_PTC_ALEMBIC)
+ add_subdirectory(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..6e3eda4184d
--- /dev/null
+++ b/source/blender/pointcache/PTC_api.cpp
@@ -0,0 +1,403 @@
+/*
+ * 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"
+
+#include "util/util_error_handler.h"
+
+#include "reader.h"
+#include "writer.h"
+#include "export.h"
+
+#include "alembic.h"
+#include "ptc_types.h"
+
+extern "C" {
+#include "BLI_math.h"
+
+#include "DNA_modifier_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_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;
+}
+
+bool PTC_reader_get_frame_range(PTCReader *_reader, int *start_frame, int *end_frame)
+{
+ PTC::Reader *reader = (PTC::Reader *)_reader;
+ int sfra, efra;
+ if (reader->get_frame_range(sfra, efra)) {
+ if (start_frame) *start_frame = sfra;
+ if (end_frame) *end_frame = efra;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+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_combined(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;
+ /* XXX particles are bad ...
+ * this can be either the actual particle cache or the hair dynamics cache,
+ * which is actually the cache of the internal cloth modifier
+ */
+ bool use_cloth_cache = psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DYNAMICS);
+ if (use_cloth_cache && psys->clmd)
+ return PTC_reader_cloth(scene, ob, psys->clmd);
+ else
+ 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;
+}
+
+
+/* ==== CLOTH ==== */
+
+PTCWriter *PTC_writer_cloth(Scene *scene, Object *ob, ClothModifierData *clmd)
+{
+ return (PTCWriter *)abc_writer_cloth(scene, ob, clmd);
+}
+
+PTCReader *PTC_reader_cloth(Scene *scene, Object *ob, ClothModifierData *clmd)
+{
+ return (PTCReader *)abc_reader_cloth(scene, ob, clmd);
+}
+
+
+/* ==== DYNAMIC PAINT ==== */
+
+PTCWriter *PTC_writer_dynamicpaint(Scene *scene, Object *ob, DynamicPaintSurface *surface)
+{
+ return (PTCWriter *)abc_writer_dynamicpaint(scene, ob, surface);
+}
+
+PTCReader *PTC_reader_dynamicpaint(Scene *scene, Object *ob, DynamicPaintSurface *surface)
+{
+ return (PTCReader *)abc_reader_dynamicpaint(scene, ob, surface);
+}
+
+
+/* ==== MESH ==== */
+
+PTCWriter *PTC_writer_point_cache(Scene *scene, Object *ob, PointCacheModifierData *pcmd)
+{
+ return (PTCWriter *)abc_writer_point_cache(scene, ob, pcmd);
+}
+
+PTCReader *PTC_reader_point_cache(Scene *scene, Object *ob, PointCacheModifierData *pcmd)
+{
+ return (PTCReader *)abc_reader_point_cache(scene, ob, pcmd);
+}
+
+struct DerivedMesh *PTC_reader_point_cache_acquire_result(PTCReader *_reader)
+{
+ PointCacheReader *reader = (PointCacheReader *)_reader;
+ return reader->acquire_result();
+}
+
+void PTC_reader_point_cache_discard_result(PTCReader *_reader)
+{
+}
+
+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;
+ }
+}
+
+
+/* ==== PARTICLES ==== */
+
+PTCWriter *PTC_writer_particles(Scene *scene, Object *ob, ParticleSystem *psys)
+{
+ return (PTCWriter *)abc_writer_particles(scene, ob, psys);
+}
+
+PTCReader *PTC_reader_particles(Scene *scene, Object *ob, ParticleSystem *psys)
+{
+ return (PTCReader *)abc_reader_particles(scene, ob, psys);
+}
+
+int PTC_reader_particles_totpoint(PTCReader *_reader)
+{
+ return ((PTC::ParticlesReader *)_reader)->totpoint();
+}
+
+//PTCWriter *PTC_writer_particle_paths(Scene *scene, Object *ob, ParticleSystem *psys)
+//{
+// return (PTCWriter *)abc_writer_particle_paths(scene, ob, psys);
+//}
+
+PTCReader *PTC_reader_particle_paths(Scene *scene, Object *ob, ParticleSystem *psys, eParticlePathsMode mode)
+{
+ return (PTCReader *)abc_reader_particle_paths(scene, ob, psys, mode);
+}
+
+PTCWriter *PTC_writer_particles_combined(Scene *scene, Object *ob, ParticleSystem *psys)
+{
+ return (PTCWriter *)abc_writer_particle_combined(scene, ob, psys);
+}
+
+
+/* ==== RIGID BODY ==== */
+
+PTCWriter *PTC_writer_rigidbody(Scene *scene, RigidBodyWorld *rbw)
+{
+ return (PTCWriter *)abc_writer_rigidbody(scene, rbw);
+}
+
+PTCReader *PTC_reader_rigidbody(Scene *scene, RigidBodyWorld *rbw)
+{
+ return (PTCReader *)abc_reader_rigidbody(scene, rbw);
+}
+
+
+/* ==== SMOKE ==== */
+
+PTCWriter *PTC_writer_smoke(Scene *scene, Object *ob, SmokeDomainSettings *domain)
+{
+ return (PTCWriter *)abc_writer_smoke(scene, ob, domain);
+}
+
+PTCReader *PTC_reader_smoke(Scene *scene, Object *ob, SmokeDomainSettings *domain)
+{
+ return (PTCReader *)abc_reader_smoke(scene, ob, domain);
+}
+
+
+/* ==== SOFT BODY ==== */
+
+PTCWriter *PTC_writer_softbody(Scene *scene, Object *ob, SoftBody *softbody)
+{
+ return (PTCWriter *)abc_writer_softbody(scene, ob, softbody);
+}
+
+PTCReader *PTC_reader_softbody(Scene *scene, Object *ob, SoftBody *softbody)
+{
+ return (PTCReader *)abc_reader_softbody(scene, ob, softbody);
+}
diff --git a/source/blender/pointcache/PTC_api.h b/source/blender/pointcache/PTC_api.h
new file mode 100644
index 00000000000..f7b952ba47c
--- /dev/null
+++ b/source/blender/pointcache/PTC_api.h
@@ -0,0 +1,125 @@
+/*
+ * 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 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_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);
+bool 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);
+
+typedef enum eParticlePathsMode {
+ PTC_PARTICLE_PATHS_PARENTS = 0,
+ PTC_PARTICLE_PATHS_CHILDREN = 1,
+} eParticlePathsMode;
+
+//struct PTCWriter *PTC_writer_particle_paths(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
+struct PTCReader *PTC_reader_particle_paths(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, eParticlePathsMode mode);
+
+struct PTCWriter *PTC_writer_particles_combined(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
+
+/* 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/alembic/CMakeLists.txt b/source/blender/pointcache/alembic/CMakeLists.txt
new file mode 100644
index 00000000000..ac5dba0c5e6
--- /dev/null
+++ b/source/blender/pointcache/alembic/CMakeLists.txt
@@ -0,0 +1,69 @@
+# ***** 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}
+ ${ALEMBIC_INCLUDE_DIRS}
+ ${OPENEXR_INCLUDE_DIR}/OpenEXR
+)
+
+set(SRC
+ abc_frame_mapper.cpp
+ abc_frame_mapper.h
+ abc_reader.cpp
+ abc_reader.h
+ abc_schema.h
+ abc_writer.cpp
+ abc_writer.h
+
+ abc_cloth.cpp
+ abc_cloth.h
+ abc_dynamicpaint.cpp
+ abc_dynamicpaint.h
+ abc_mesh.cpp
+ abc_mesh.h
+ abc_particles.cpp
+ abc_particles.h
+ abc_rigidbody.cpp
+ abc_rigidbody.h
+ abc_smoke.cpp
+ abc_smoke.h
+ abc_softbody.cpp
+ abc_softbody.h
+)
+
+add_definitions(-DWITH_ALEMBIC)
+
+blender_add_lib(bf_pointcache_alembic "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/pointcache/alembic/abc_cloth.cpp b/source/blender/pointcache/alembic/abc_cloth.cpp
new file mode 100644
index 00000000000..67fd42edbea
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_cloth.cpp
@@ -0,0 +1,254 @@
+/*
+ * 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.h"
+
+#include "abc_cloth.h"
+
+extern "C" {
+#include "BLI_math.h"
+
+#include "DNA_cloth_types.h"
+#include "DNA_object_types.h"
+#include "DNA_modifier_types.h"
+
+#include "BKE_cloth.h"
+}
+
+#include "PTC_api.h"
+
+namespace PTC {
+
+using namespace Abc;
+using namespace AbcGeom;
+
+AbcClothWriter::AbcClothWriter(Scene *scene, Object *ob, ClothModifierData *clmd) :
+ ClothWriter(scene, ob, clmd, &m_archive),
+ m_archive(scene, &ob->id, clmd->point_cache, m_error_handler)
+{
+ set_error_handler(new ModifierErrorHandler(&clmd->modifier));
+
+ if (m_archive.archive) {
+ OObject root = m_archive.archive.getTop();
+ m_points = OPoints(root, m_clmd->modifier.name, m_archive.frame_sampling_index());
+
+ OPointsSchema &schema = m_points.getSchema();
+ OCompoundProperty geom_params = schema.getArbGeomParams();
+
+ m_param_velocities = OV3fGeomParam(geom_params, "velocities", false, kVaryingScope, 1, 0);
+ m_param_goal_positions = OP3fGeomParam(geom_params, "goal_positions", false, kVaryingScope, 1, 0);
+ }
+}
+
+AbcClothWriter::~AbcClothWriter()
+{
+}
+
+static V3fArraySample create_sample_velocities(Cloth *cloth, std::vector<V3f> &data)
+{
+ ClothVertex *vert;
+ int i, totvert = cloth->numverts;
+
+ data.reserve(totvert);
+ for (i = 0, vert = cloth->verts; i < totvert; ++i, ++vert) {
+ float *co = vert->v;
+ data.push_back(V3f(co[0], co[1], co[2]));
+ }
+
+ return V3fArraySample(data);
+}
+
+static P3fArraySample create_sample_goal_positions(Cloth *cloth, std::vector<V3f> &data)
+{
+ ClothVertex *vert;
+ int i, totvert = cloth->numverts;
+
+ data.reserve(totvert);
+ for (i = 0, vert = cloth->verts; i < totvert; ++i, ++vert) {
+ float *co = vert->xconst;
+ data.push_back(V3f(co[0], co[1], co[2]));
+ }
+
+ return P3fArraySample(data);
+}
+
+void AbcClothWriter::write_sample()
+{
+ if (!m_archive.archive)
+ return;
+
+ Cloth *cloth = m_clmd->clothObject;
+ if (!cloth)
+ return;
+
+ OPointsSchema &schema = m_points.getSchema();
+
+ int totpoint = cloth->numverts;
+ ClothVertex *vert;
+ int i;
+
+ /* XXX TODO only needed for the first frame/sample */
+ std::vector<Util::uint64_t> ids;
+ ids.reserve(totpoint);
+ for (i = 0, vert = cloth->verts; i < totpoint; ++i, ++vert)
+ ids.push_back(i);
+
+ std::vector<V3f> positions;
+ positions.reserve(totpoint);
+ for (i = 0, vert = cloth->verts; i < totpoint; ++i, ++vert) {
+ float *co = vert->x;
+ positions.push_back(V3f(co[0], co[1], co[2]));
+ }
+
+ std::vector<V3f> velocities_buffer;
+ std::vector<V3f> goal_positions_buffer;
+ V3fArraySample velocities = create_sample_velocities(cloth, velocities_buffer);
+ P3fArraySample goal_positions = create_sample_goal_positions(cloth, goal_positions_buffer);
+
+ OPointsSchema::Sample sample = OPointsSchema::Sample(V3fArraySample(positions), UInt64ArraySample(ids));
+ schema.set(sample);
+
+ m_param_velocities.set(OV3fGeomParam::Sample(velocities, kVaryingScope));
+ m_param_goal_positions.set(OP3fGeomParam::Sample(goal_positions, kVaryingScope));
+}
+
+
+AbcClothReader::AbcClothReader(Scene *scene, Object *ob, ClothModifierData *clmd) :
+ ClothReader(scene, ob, clmd, &m_archive),
+ m_archive(scene, &ob->id, clmd->point_cache, m_error_handler)
+{
+ set_error_handler(new ModifierErrorHandler(&clmd->modifier));
+
+ if (m_archive.archive.valid()) {
+ IObject root = m_archive.archive.getTop();
+ if (root.valid() && root.getChild(m_clmd->modifier.name)) {
+ m_points = IPoints(root, m_clmd->modifier.name);
+
+ IPointsSchema &schema = m_points.getSchema();
+ ICompoundProperty geom_params = schema.getArbGeomParams();
+
+ m_param_velocities = IV3fGeomParam(geom_params, "velocities", 0);
+ m_param_goal_positions= IP3fGeomParam(geom_params, "goal_positions", 0);
+ }
+ }
+}
+
+AbcClothReader::~AbcClothReader()
+{
+}
+
+static void apply_sample_positions(Cloth *cloth, P3fArraySamplePtr sample)
+{
+ ClothVertex *vert;
+ int i, totvert = cloth->numverts;
+
+ BLI_assert(sample->size() == totvert);
+
+ const V3f *data = sample->get();
+ for (i = 0, vert = cloth->verts; i < totvert; ++i, ++vert) {
+ const V3f &co = data[i];
+ copy_v3_v3(vert->x, co.getValue());
+ }
+}
+
+static void apply_sample_velocities(Cloth *cloth, V3fArraySamplePtr sample)
+{
+ ClothVertex *vert;
+ int i, totvert = cloth->numverts;
+
+ BLI_assert(sample->size() == totvert);
+
+ const V3f *data = sample->get();
+ for (i = 0, vert = cloth->verts; i < totvert; ++i, ++vert) {
+ const V3f &vel = data[i];
+ copy_v3_v3(vert->v, vel.getValue());
+ }
+}
+
+static void apply_sample_goal_positions(Cloth *cloth, P3fArraySamplePtr sample)
+{
+ ClothVertex *vert;
+ int i, totvert = cloth->numverts;
+
+ BLI_assert(sample->size() == totvert);
+
+ const V3f *data = sample->get();
+ for (i = 0, vert = cloth->verts; i < totvert; ++i, ++vert) {
+ const V3f &co = data[i];
+ copy_v3_v3(vert->xconst, co.getValue());
+ }
+}
+
+PTCReadSampleResult AbcClothReader::read_sample(float frame)
+{
+ Cloth *cloth = m_clmd->clothObject;
+
+ if (!m_points.valid())
+ return PTC_READ_SAMPLE_INVALID;
+
+ IPointsSchema &schema = m_points.getSchema();
+ TimeSamplingPtr ts = schema.getTimeSampling();
+
+ ISampleSelector ss = m_archive.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 = m_archive.time_to_frame(stime);
+
+ IPointsSchema::Sample sample;
+ schema.get(sample, ss);
+
+ P3fArraySamplePtr positions = sample.getPositions();
+
+ V3fArraySamplePtr velocities;
+ if (m_param_velocities && m_param_velocities.getNumSamples() > 0) {
+ IV3fGeomParam::Sample sample_velocities;
+ m_param_velocities.getExpanded(sample_velocities, ss);
+ velocities = sample_velocities.getVals();
+ }
+
+ P3fArraySamplePtr goal_positions;
+ if (m_param_goal_positions && m_param_goal_positions.getNumSamples() > 0) {
+ IP3fGeomParam::Sample sample_goal_positions;
+ m_param_goal_positions.getExpanded(sample_goal_positions, ss);
+ goal_positions = sample_goal_positions.getVals();
+ }
+
+ apply_sample_positions(cloth, positions);
+ if (velocities)
+ apply_sample_velocities(cloth, velocities);
+ if (goal_positions)
+ apply_sample_goal_positions(cloth, goal_positions);
+
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+/* ==== API ==== */
+
+Writer *abc_writer_cloth(Scene *scene, Object *ob, ClothModifierData *clmd)
+{
+ return new AbcClothWriter(scene, ob, clmd);
+}
+
+Reader *abc_reader_cloth(Scene *scene, Object *ob, ClothModifierData *clmd)
+{
+ return new AbcClothReader(scene, ob, clmd);
+}
+
+} /* namespace PTC */
diff --git a/source/blender/pointcache/alembic/abc_cloth.h b/source/blender/pointcache/alembic/abc_cloth.h
new file mode 100644
index 00000000000..586a182efde
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_cloth.h
@@ -0,0 +1,70 @@
+/*
+ * 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_ABC_CLOTH_H
+#define PTC_ABC_CLOTH_H
+
+#include <Alembic/AbcGeom/IPoints.h>
+#include <Alembic/AbcGeom/OPoints.h>
+
+#include "ptc_types.h"
+
+#include "abc_reader.h"
+#include "abc_schema.h"
+#include "abc_writer.h"
+
+struct Object;
+struct ClothModifierData;
+
+namespace PTC {
+
+class AbcClothWriter : public ClothWriter {
+public:
+ AbcClothWriter(Scene *scene, Object *ob, ClothModifierData *clmd);
+ ~AbcClothWriter();
+
+ void write_sample();
+
+ AbcWriterArchive *archive() { return &m_archive; }
+
+private:
+ AbcWriterArchive m_archive;
+
+ AbcGeom::OPoints m_points;
+ AbcGeom::OV3fGeomParam m_param_velocities;
+ AbcGeom::OP3fGeomParam m_param_goal_positions;
+};
+
+class AbcClothReader : public ClothReader {
+public:
+ AbcClothReader(Scene *scene, Object *ob, ClothModifierData *clmd);
+ ~AbcClothReader();
+
+ PTCReadSampleResult read_sample(float frame);
+
+private:
+ AbcReaderArchive m_archive;
+
+ AbcGeom::IPoints m_points;
+ AbcGeom::IV3fGeomParam m_param_velocities;
+ AbcGeom::IP3fGeomParam m_param_goal_positions;
+};
+
+} /* namespace PTC */
+
+#endif /* PTC_CLOTH_H */
diff --git a/source/blender/pointcache/alembic/abc_dynamicpaint.cpp b/source/blender/pointcache/alembic/abc_dynamicpaint.cpp
new file mode 100644
index 00000000000..49ae62bb4de
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_dynamicpaint.cpp
@@ -0,0 +1,85 @@
+/*
+ * 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.h"
+
+#include "abc_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;
+
+AbcDynamicPaintWriter::AbcDynamicPaintWriter(Scene *scene, Object *ob, DynamicPaintSurface *surface) :
+ DynamicPaintWriter(scene, ob, surface, &m_archive),
+ m_archive(scene, &ob->id, surface->pointcache, m_error_handler)
+{
+ if (m_archive.archive) {
+ }
+}
+
+AbcDynamicPaintWriter::~AbcDynamicPaintWriter()
+{
+}
+
+void AbcDynamicPaintWriter::write_sample()
+{
+ if (!m_archive.archive)
+ return;
+}
+
+
+AbcDynamicPaintReader::AbcDynamicPaintReader(Scene *scene, Object *ob, DynamicPaintSurface *surface) :
+ DynamicPaintReader(scene, ob, surface, &m_archive),
+ m_archive(scene, &ob->id, surface->pointcache, m_error_handler)
+{
+ if (m_archive.archive.valid()) {
+ IObject root = m_archive.archive.getTop();
+// m_points = IPoints(root, m_psys->name);
+ }
+}
+
+AbcDynamicPaintReader::~AbcDynamicPaintReader()
+{
+}
+
+PTCReadSampleResult AbcDynamicPaintReader::read_sample(float frame)
+{
+ return PTC_READ_SAMPLE_INVALID;
+}
+
+/* ==== API ==== */
+
+Writer *abc_writer_dynamicpaint(Scene *scene, Object *ob, DynamicPaintSurface *surface)
+{
+ return new AbcDynamicPaintWriter(scene, ob, surface);
+}
+
+Reader *abc_reader_dynamicpaint(Scene *scene, Object *ob, DynamicPaintSurface *surface)
+{
+ return new AbcDynamicPaintReader(scene, ob, surface);
+}
+
+} /* namespace PTC */
diff --git a/source/blender/pointcache/alembic/abc_dynamicpaint.h b/source/blender/pointcache/alembic/abc_dynamicpaint.h
new file mode 100644
index 00000000000..9900f1eff91
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_dynamicpaint.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_ABC_DYNAMICPAINT_H
+#define PTC_ABC_DYNAMICPAINT_H
+
+//#include <Alembic/AbcGeom/IPoints.h>
+//#include <Alembic/AbcGeom/OPoints.h>
+
+#include "ptc_types.h"
+
+#include "abc_reader.h"
+#include "abc_schema.h"
+#include "abc_writer.h"
+
+struct Object;
+struct DynamicPaintSurface;
+
+namespace PTC {
+
+class AbcDynamicPaintWriter : public DynamicPaintWriter {
+public:
+ AbcDynamicPaintWriter(Scene *scene, Object *ob, DynamicPaintSurface *surface);
+ ~AbcDynamicPaintWriter();
+
+ void write_sample();
+
+private:
+ AbcWriterArchive m_archive;
+// AbcGeom::OPoints m_points;
+};
+
+class AbcDynamicPaintReader : public DynamicPaintReader {
+public:
+ AbcDynamicPaintReader(Scene *scene, Object *ob, DynamicPaintSurface *surface);
+ ~AbcDynamicPaintReader();
+
+ PTCReadSampleResult read_sample(float frame);
+
+private:
+ AbcReaderArchive m_archive;
+// AbcGeom::IPoints m_points;
+};
+
+} /* namespace PTC */
+
+#endif /* PTC_DYNAMICPAINT_H */
diff --git a/source/blender/pointcache/alembic/abc_frame_mapper.cpp b/source/blender/pointcache/alembic/abc_frame_mapper.cpp
new file mode 100644
index 00000000000..097e271e863
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_frame_mapper.cpp
@@ -0,0 +1,56 @@
+/*
+ * 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 "abc_frame_mapper.h"
+
+extern "C" {
+#include "DNA_scene_types.h"
+}
+
+namespace PTC {
+
+#ifdef WITH_ALEMBIC
+
+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;
+}
+
+#endif /* WITH_ALEMBIC */
+
+} /* namespace PTC */
diff --git a/source/blender/pointcache/alembic/abc_frame_mapper.h b/source/blender/pointcache/alembic/abc_frame_mapper.h
new file mode 100644
index 00000000000..f9a0e730bb5
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_frame_mapper.h
@@ -0,0 +1,55 @@
+/*
+ * 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_ABC_FRAME_MAPPER_H
+#define PTC_ABC_FRAME_MAPPER_H
+
+#ifdef WITH_ALEMBIC
+#include <Alembic/AbcCoreAbstract/Foundation.h>
+#include <Alembic/Abc/ISampleSelector.h>
+#endif
+
+struct Scene;
+
+namespace PTC {
+
+#ifdef WITH_ALEMBIC
+
+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;
+};
+
+#endif /* WITH_ALEMBIC */
+
+} /* namespace PTC */
+
+#endif /* PTC_UTIL_FRAME_MAPPER_H */
diff --git a/source/blender/pointcache/alembic/abc_mesh.cpp b/source/blender/pointcache/alembic/abc_mesh.cpp
new file mode 100644
index 00000000000..8183087bc84
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_mesh.cpp
@@ -0,0 +1,597 @@
+/*
+ * 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 "alembic.h"
+
+#include "abc_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;
+
+AbcPointCacheWriter::AbcPointCacheWriter(Scene *scene, Object *ob, PointCacheModifierData *pcmd) :
+ PointCacheWriter(scene, ob, pcmd, &m_archive),
+ m_archive(scene, &ob->id, pcmd->point_cache, m_error_handler)
+{
+ set_error_handler(new ModifierErrorHandler(&pcmd->modifier));
+
+ if (m_archive.archive) {
+ OObject root = m_archive.archive.getTop();
+ m_mesh = OPolyMesh(root, m_pcmd->modifier.name, m_archive.frame_sampling_index());
+
+ 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);
+ }
+}
+
+AbcPointCacheWriter::~AbcPointCacheWriter()
+{
+}
+
+/* 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 AbcPointCacheWriter::write_sample()
+{
+ if (!m_archive.archive)
+ return;
+
+ 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);
+}
+
+
+AbcPointCacheReader::AbcPointCacheReader(Scene *scene, Object *ob, PointCacheModifierData *pcmd) :
+ PointCacheReader(scene, ob, pcmd, &m_archive),
+ m_archive(scene, &ob->id, pcmd->point_cache, m_error_handler)
+{
+ set_error_handler(new ModifierErrorHandler(&pcmd->modifier));
+
+ if (m_archive.archive.valid()) {
+ IObject root = m_archive.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);
+ }
+ }
+}
+
+AbcPointCacheReader::~AbcPointCacheReader()
+{
+}
+
+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 AbcPointCacheReader::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 = m_archive.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;
+}
+
+/* ==== API ==== */
+
+Writer *abc_writer_point_cache(Scene *scene, Object *ob, PointCacheModifierData *pcmd)
+{
+ return new AbcPointCacheWriter(scene, ob, pcmd);
+}
+
+Reader *abc_reader_point_cache(Scene *scene, Object *ob, PointCacheModifierData *pcmd)
+{
+ return new AbcPointCacheReader(scene, ob, pcmd);
+}
+
+} /* namespace PTC */
diff --git a/source/blender/pointcache/alembic/abc_mesh.h b/source/blender/pointcache/alembic/abc_mesh.h
new file mode 100644
index 00000000000..e8c7e4a72ef
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_mesh.h
@@ -0,0 +1,77 @@
+/*
+ * 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_ABC_MESH_H
+#define PTC_ABC_MESH_H
+
+#include <Alembic/AbcGeom/IPolyMesh.h>
+#include <Alembic/AbcGeom/OPolyMesh.h>
+
+#include "ptc_types.h"
+
+#include "abc_reader.h"
+#include "abc_schema.h"
+#include "abc_writer.h"
+
+struct Object;
+struct PointCacheModifierData;
+struct DerivedMesh;
+
+namespace PTC {
+
+class AbcPointCacheWriter : public PointCacheWriter {
+public:
+ AbcPointCacheWriter(Scene *scene, Object *ob, PointCacheModifierData *pcmd);
+ ~AbcPointCacheWriter();
+
+ void write_sample();
+
+private:
+ AbcWriterArchive m_archive;
+
+ 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 AbcPointCacheReader : public PointCacheReader {
+public:
+ AbcPointCacheReader(Scene *scene, Object *ob, PointCacheModifierData *pcmd);
+ ~AbcPointCacheReader();
+
+ PTCReadSampleResult read_sample(float frame);
+
+private:
+ AbcReaderArchive m_archive;
+
+ 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;
+};
+
+} /* namespace PTC */
+
+#endif /* PTC_MESH_H */
diff --git a/source/blender/pointcache/alembic/abc_particles.cpp b/source/blender/pointcache/alembic/abc_particles.cpp
new file mode 100644
index 00000000000..1c4f721a051
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_particles.cpp
@@ -0,0 +1,562 @@
+/*
+ * 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.h"
+
+#include "abc_cloth.h"
+#include "abc_particles.h"
+
+extern "C" {
+#include "BLI_math.h"
+
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+
+#include "BKE_particle.h"
+}
+
+#include "PTC_api.h"
+
+namespace PTC {
+
+using namespace Abc;
+using namespace AbcGeom;
+
+AbcParticlesWriter::AbcParticlesWriter(Scene *scene, Object *ob, ParticleSystem *psys) :
+ ParticlesWriter(scene, ob, psys, &m_archive),
+ m_archive(scene, &ob->id, psys->pointcache, m_error_handler)
+{
+ if (m_archive.archive) {
+ OObject root = m_archive.archive.getTop();
+ m_points = OPoints(root, m_psys->name, m_archive.frame_sampling_index());
+ }
+}
+
+AbcParticlesWriter::~AbcParticlesWriter()
+{
+}
+
+void AbcParticlesWriter::write_sample()
+{
+ if (!m_archive.archive)
+ return;
+
+ 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);
+}
+
+
+AbcParticlesReader::AbcParticlesReader(Scene *scene, Object *ob, ParticleSystem *psys) :
+ ParticlesReader(scene, ob, psys, &m_archive),
+ m_archive(scene, &ob->id, psys->pointcache, m_error_handler)
+{
+ if (m_archive.archive.valid()) {
+ IObject root = m_archive.archive.getTop();
+ m_points = IPoints(root, m_psys->name);
+ }
+
+ /* XXX TODO read first sample for info on particle count and times */
+ m_totpoint = 0;
+}
+
+AbcParticlesReader::~AbcParticlesReader()
+{
+}
+
+PTCReadSampleResult AbcParticlesReader::read_sample(float frame)
+{
+ ISampleSelector ss = m_archive.get_frame_sample_selector(frame);
+
+ if (!m_points.valid())
+ return PTC_READ_SAMPLE_INVALID;
+
+ IPointsSchema &schema = m_points.getSchema();
+
+ 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;
+}
+
+
+AbcParticlePathsWriter::AbcParticlePathsWriter(Scene *scene, Object *ob, ParticleSystem *psys, ParticleCacheKey ***pathcache, int *totpath, const std::string &suffix) :
+// ParticlesWriter(scene, ob, psys, &m_archive),
+// m_archive(scene, &ob->id, psys->pointcache, m_error_handler)
+ ParticlesWriter(scene, ob, psys, NULL),
+ m_pathcache(pathcache),
+ m_totpath(totpath),
+ m_suffix(suffix),
+ m_archive(NULL)
+{
+#if 0
+ if (m_archive->archive) {
+ OObject root = m_archive.archive.getTop();
+ /* XXX non-escaped string construction here ... */
+ m_parent_curves = OCurves(root, std::string(m_psys->name) + "__parent_paths", m_archive.frame_sampling_index());
+ m_child_curves = OCurves(root, std::string(m_psys->name) + "__child_paths", m_archive.frame_sampling_index());
+ }
+#endif
+}
+
+AbcParticlePathsWriter::~AbcParticlePathsWriter()
+{
+}
+
+void AbcParticlePathsWriter::set_archive(AbcWriterArchive *archive)
+{
+ m_archive = archive;
+ OObject root = m_archive->archive.getTop();
+ /* XXX non-escaped string construction here ... */
+ m_curves = OCurves(root, std::string(m_psys->name) + m_suffix, m_archive->frame_sampling_index());
+
+ OCurvesSchema &schema = m_curves.getSchema();
+ OCompoundProperty geom_props = schema.getArbGeomParams();
+
+ m_param_velocities = OV3fGeomParam(geom_props, "velocities", false, kVertexScope, 1, 0);
+ m_param_rotations = OQuatfGeomParam(geom_props, "rotations", false, kVertexScope, 1, 0);
+ m_param_colors = OV3fGeomParam(geom_props, "colors", false, kVertexScope, 1, 0);
+ m_param_times = OFloatGeomParam(geom_props, "times", false, kVertexScope, 1, 0);
+}
+
+static int paths_count_totkeys(ParticleCacheKey **pathcache, int totpart)
+{
+ int p;
+ int totkeys = 0;
+
+ for (p = 0; p < totpart; ++p) {
+ ParticleCacheKey *keys = pathcache[p];
+ totkeys += keys->segments + 1;
+ }
+
+ return totkeys;
+}
+
+static Int32ArraySample paths_create_sample_nvertices(ParticleCacheKey **pathcache, int totpart, std::vector<int32_t> &data)
+{
+ int p;
+
+ data.reserve(totpart);
+
+ for (p = 0; p < totpart; ++p) {
+ ParticleCacheKey *keys = pathcache[p];
+
+ data.push_back(keys->segments + 1);
+ }
+
+ return Int32ArraySample(data);
+}
+
+static P3fArraySample paths_create_sample_positions(ParticleCacheKey **pathcache, int totpart, int totkeys, std::vector<V3f> &data)
+{
+ int p, k;
+
+ data.reserve(totkeys);
+
+ for (p = 0; p < totpart; ++p) {
+ ParticleCacheKey *keys = pathcache[p];
+ int numkeys = keys->segments + 1;
+
+ for (k = 0; k < numkeys; ++k) {
+ float *co = keys[k].co;
+ data.push_back(V3f(co[0], co[1], co[2]));
+ }
+ }
+
+ return P3fArraySample(data);
+}
+
+static OV3fGeomParam::Sample paths_create_sample_velocities(ParticleCacheKey **pathcache, int totpart, int totkeys, std::vector<V3f> &data)
+{
+ int p, k;
+
+ data.reserve(totkeys);
+
+ for (p = 0; p < totpart; ++p) {
+ ParticleCacheKey *keys = pathcache[p];
+ int numkeys = keys->segments + 1;
+
+ for (k = 0; k < numkeys; ++k) {
+ float *vel = keys[k].vel;
+ data.push_back(V3f(vel[0], vel[1], vel[2]));
+ }
+ }
+
+ OV3fGeomParam::Sample sample;
+ sample.setVals(V3fArraySample(data));
+ sample.setScope(kVertexScope);
+ return sample;
+}
+
+static OQuatfGeomParam::Sample paths_create_sample_rotations(ParticleCacheKey **pathcache, int totpart, int totkeys, std::vector<Quatf> &data)
+{
+ int p, k;
+
+ data.reserve(totkeys);
+
+ for (p = 0; p < totpart; ++p) {
+ ParticleCacheKey *keys = pathcache[p];
+ int numkeys = keys->segments + 1;
+
+ for (k = 0; k < numkeys; ++k) {
+ float *rot = keys[k].rot;
+ data.push_back(Quatf(rot[0], rot[1], rot[2], rot[3]));
+ }
+ }
+
+ OQuatfGeomParam::Sample sample;
+ sample.setVals(QuatfArraySample(data));
+ sample.setScope(kVertexScope);
+ return sample;
+}
+
+static OV3fGeomParam::Sample paths_create_sample_colors(ParticleCacheKey **pathcache, int totpart, int totkeys, std::vector<V3f> &data)
+{
+ int p, k;
+
+ data.reserve(totkeys);
+
+ for (p = 0; p < totpart; ++p) {
+ ParticleCacheKey *keys = pathcache[p];
+ int numkeys = keys->segments + 1;
+
+ for (k = 0; k < numkeys; ++k) {
+ float *col = keys[k].col;
+ data.push_back(V3f(col[0], col[1], col[2]));
+ }
+ }
+
+ OV3fGeomParam::Sample sample;
+ sample.setVals(V3fArraySample(data));
+ sample.setScope(kVertexScope);
+ return sample;
+}
+
+static OFloatGeomParam::Sample paths_create_sample_times(ParticleCacheKey **pathcache, int totpart, int totkeys, std::vector<float32_t> &data)
+{
+ int p, k;
+
+ data.reserve(totkeys);
+
+ for (p = 0; p < totpart; ++p) {
+ ParticleCacheKey *keys = pathcache[p];
+ int numkeys = keys->segments + 1;
+
+ for (k = 0; k < numkeys; ++k) {
+ data.push_back(keys[k].time);
+ }
+ }
+
+ OFloatGeomParam::Sample sample;
+ sample.setVals(FloatArraySample(data));
+ sample.setScope(kVertexScope);
+ return sample;
+}
+
+void AbcParticlePathsWriter::write_sample()
+{
+ if (!m_archive->archive)
+ return;
+ if (!(*m_pathcache))
+ return;
+
+ int totkeys = paths_count_totkeys(*m_pathcache, *m_totpath);
+ if (totkeys == 0)
+ return;
+
+ OCurvesSchema &schema = m_curves.getSchema();
+
+ std::vector<V3f> positions_buffer;
+ std::vector<V3f> velocities_buffer;
+ std::vector<Quatf> rotations_buffer;
+ std::vector<V3f> colors_buffer;
+ std::vector<float32_t> times_buffer;
+ V3fArraySample positions = paths_create_sample_positions(*m_pathcache, *m_totpath, totkeys, positions_buffer);
+ OV3fGeomParam::Sample velocities = paths_create_sample_velocities(*m_pathcache, *m_totpath, totkeys, velocities_buffer);
+ OQuatfGeomParam::Sample rotations = paths_create_sample_rotations(*m_pathcache, *m_totpath, totkeys, rotations_buffer);
+ OV3fGeomParam::Sample colors = paths_create_sample_colors(*m_pathcache, *m_totpath, totkeys, colors_buffer);
+ OFloatGeomParam::Sample times = paths_create_sample_times(*m_pathcache, *m_totpath, totkeys, times_buffer);
+
+ OCurvesSchema::Sample sample;
+// if (schema.getNumSamples() == 0) {
+ /* write curve sizes only first time, assuming they are constant! */
+ std::vector<int32_t> nvertices_buffer;
+ Int32ArraySample nvertices = paths_create_sample_nvertices(*m_pathcache, *m_totpath, nvertices_buffer);
+
+ sample = OCurvesSchema::Sample(positions, nvertices);
+// }
+// else {
+// sample = OCurvesSchema::Sample(positions);
+// }
+
+ schema.set(sample);
+
+ m_param_velocities.set(velocities);
+ m_param_rotations.set(rotations);
+ m_param_colors.set(colors);
+ m_param_times.set(times);
+}
+
+
+AbcParticlePathsReader::AbcParticlePathsReader(Scene *scene, Object *ob, ParticleSystem *psys, ParticleCacheKey ***pathcache, int *totpath, const std::string &suffix) :
+ ParticlesReader(scene, ob, psys, &m_archive),
+ m_pathcache(pathcache),
+ m_totpath(totpath),
+ m_suffix(suffix),
+ m_archive(scene, &ob->id, psys->pointcache, m_error_handler)
+{
+ if (m_archive.archive.valid()) {
+ IObject root = m_archive.archive.getTop();
+ if (root.valid()) {
+ /* XXX non-escaped string construction here ... */
+ std::string curves_name = std::string(m_psys->name) + suffix;
+ if (root.getChild(curves_name)) {
+ m_curves = ICurves(root, curves_name);
+ ICurvesSchema &schema = m_curves.getSchema();
+ ICompoundProperty geom_props = schema.getArbGeomParams();
+
+ m_param_velocities = IV3fGeomParam(geom_props, "velocities", 0);
+ m_param_rotations = IQuatfGeomParam(geom_props, "rotations", 0);
+ m_param_colors = IV3fGeomParam(geom_props, "colors", 0);
+ m_param_times = IFloatGeomParam(geom_props, "times", 0);
+ }
+ }
+ }
+}
+
+AbcParticlePathsReader::~AbcParticlePathsReader()
+{
+}
+
+static void paths_apply_sample_nvertices(ParticleCacheKey **pathcache, int totpart, Int32ArraySamplePtr sample)
+{
+ int p, k;
+
+ BLI_assert(sample->size() == totpart);
+
+ const int32_t *data = sample->get();
+
+ for (p = 0; p < totpart; ++p) {
+ ParticleCacheKey *keys = pathcache[p];
+ int num_keys = data[p];
+ int segments = num_keys - 1;
+
+ for (k = 0; k < num_keys; ++k) {
+ keys[k].segments = segments;
+ }
+ }
+}
+
+/* Warning: apply_sample_nvertices has to be called before this! */
+static void paths_apply_sample_data(ParticleCacheKey **pathcache, int totpart,
+ P3fArraySamplePtr sample_pos,
+ V3fArraySamplePtr sample_vel,
+ QuatfArraySamplePtr sample_rot,
+ V3fArraySamplePtr sample_col,
+ FloatArraySamplePtr sample_time)
+{
+ int p, k;
+
+// BLI_assert(sample->size() == totvert);
+
+ const V3f *data_pos = sample_pos->get();
+ const V3f *data_vel = sample_vel->get();
+ const Quatf *data_rot = sample_rot->get();
+ const V3f *data_col = sample_col->get();
+ const float32_t *data_time = sample_time->get();
+ ParticleCacheKey **pkeys = pathcache;
+
+ for (p = 0; p < totpart; ++p) {
+ ParticleCacheKey *key = *pkeys;
+ int num_keys = key->segments + 1;
+
+ for (k = 0; k < num_keys; ++k) {
+ copy_v3_v3(key->co, data_pos->getValue());
+ copy_v3_v3(key->vel, data_vel->getValue());
+ key->rot[0] = (*data_rot)[0];
+ key->rot[1] = (*data_rot)[1];
+ key->rot[2] = (*data_rot)[2];
+ key->rot[3] = (*data_rot)[3];
+ copy_v3_v3(key->col, data_col->getValue());
+ key->time = *data_time;
+
+ ++key;
+ ++data_pos;
+ ++data_vel;
+ ++data_rot;
+ ++data_col;
+ ++data_time;
+ }
+
+ ++pkeys;
+ }
+}
+
+PTCReadSampleResult AbcParticlePathsReader::read_sample(float frame)
+{
+ if (!(*m_pathcache))
+ return PTC_READ_SAMPLE_INVALID;
+
+ if (!m_curves.valid())
+ return PTC_READ_SAMPLE_INVALID;
+
+ ISampleSelector ss = m_archive.get_frame_sample_selector(frame);
+
+ ICurvesSchema &schema = m_curves.getSchema();
+ if (!schema.valid() || schema.getPositionsProperty().getNumSamples() == 0)
+ return PTC_READ_SAMPLE_INVALID;
+
+ ICurvesSchema::Sample sample;
+ schema.get(sample, ss);
+
+ P3fArraySamplePtr positions = sample.getPositions();
+ Int32ArraySamplePtr nvertices = sample.getCurvesNumVertices();
+ IV3fGeomParam::Sample sample_vel = m_param_velocities.getExpandedValue(ss);
+ IQuatfGeomParam::Sample sample_rot = m_param_rotations.getExpandedValue(ss);
+ IV3fGeomParam::Sample sample_col = m_param_colors.getExpandedValue(ss);
+ IFloatGeomParam::Sample sample_time = m_param_times.getExpandedValue(ss);
+
+// int totkeys = positions->size();
+
+ if (nvertices->valid()) {
+ BLI_assert(nvertices->size() == *m_totpath);
+ paths_apply_sample_nvertices(*m_pathcache, *m_totpath, nvertices);
+ }
+
+ paths_apply_sample_data(*m_pathcache, *m_totpath, positions, sample_vel.getVals(), sample_rot.getVals(), sample_col.getVals(), sample_time.getVals());
+
+ return PTC_READ_SAMPLE_EXACT;
+}
+
+
+AbcParticlesCombinedWriter::AbcParticlesCombinedWriter(Scene *scene, Object *ob, ParticleSystem *psys) :
+ ParticlesWriter(scene, ob, psys, NULL)
+{
+ m_particles_writer = NULL;
+ m_cloth_writer = NULL;
+ m_parent_paths_writer = NULL;
+ m_child_paths_writer = NULL;
+
+ AbcWriterArchive *archive;
+ if (psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd) {
+ m_cloth_writer = new AbcClothWriter(scene, ob, psys->clmd);
+ archive = m_cloth_writer->archive();
+ }
+ else {
+ m_particles_writer = new AbcParticlesWriter(scene, ob, psys);
+ archive = m_particles_writer->archive();
+ }
+
+ if (psys->flag & PSYS_CACHE_PATHS) {
+ if (psys->pathcache) {
+ m_parent_paths_writer = new AbcParticlePathsWriter(scene, ob, psys, &psys->pathcache, &psys->totpart, "__parent_paths");
+ m_parent_paths_writer->set_archive(archive);
+ }
+ if (psys->childcache) {
+ m_child_paths_writer = new AbcParticlePathsWriter(scene, ob, psys, &psys->childcache, &psys->totchild, "__child_paths");
+ m_child_paths_writer->set_archive(archive);
+ }
+ }
+}
+
+AbcParticlesCombinedWriter::~AbcParticlesCombinedWriter()
+{
+ if (m_particles_writer)
+ delete m_particles_writer;
+ if (m_cloth_writer)
+ delete m_cloth_writer;
+ if (m_parent_paths_writer)
+ delete m_parent_paths_writer;
+ if (m_child_paths_writer)
+ delete m_child_paths_writer;
+}
+
+void AbcParticlesCombinedWriter::write_sample()
+{
+ if (m_particles_writer)
+ m_particles_writer->write_sample();
+ if (m_cloth_writer)
+ m_cloth_writer->write_sample();
+ if (m_parent_paths_writer)
+ m_parent_paths_writer->write_sample();
+ if (m_child_paths_writer)
+ m_child_paths_writer->write_sample();
+}
+
+/* ==== API ==== */
+
+Writer *abc_writer_particles(Scene *scene, Object *ob, ParticleSystem *psys)
+{
+ return new AbcParticlesWriter(scene, ob, psys);
+}
+
+Reader *abc_reader_particles(Scene *scene, Object *ob, ParticleSystem *psys)
+{
+ return new AbcParticlesReader(scene, ob, psys);
+}
+
+//Writer *abc_writer_particle_paths(Scene *scene, Object *ob, ParticleSystem *psys)
+//{
+// return new AbcParticlePathsWriter(scene, ob, psys);
+//}
+
+Reader *abc_reader_particle_paths(Scene *scene, Object *ob, ParticleSystem *psys, eParticlePathsMode mode)
+{
+ switch (mode) {
+ case PTC_PARTICLE_PATHS_PARENTS:
+ return new AbcParticlePathsReader(scene, ob, psys, &psys->pathcache, &psys->totpart, "__parent_paths");
+ case PTC_PARTICLE_PATHS_CHILDREN:
+ return new AbcParticlePathsReader(scene, ob, psys, &psys->childcache, &psys->totchild, "__child_paths");
+ }
+ return NULL;
+}
+
+Writer *abc_writer_particle_combined(Scene *scene, Object *ob, ParticleSystem *psys)
+{
+ return new AbcParticlesCombinedWriter(scene, ob, psys);
+}
+
+} /* namespace PTC */
diff --git a/source/blender/pointcache/alembic/abc_particles.h b/source/blender/pointcache/alembic/abc_particles.h
new file mode 100644
index 00000000000..b3f77a64786
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_particles.h
@@ -0,0 +1,128 @@
+/*
+ * 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_ABC_PARTICLES_H
+#define PTC_ABC_PARTICLES_H
+
+#include <Alembic/AbcGeom/IPoints.h>
+#include <Alembic/AbcGeom/OPoints.h>
+#include <Alembic/AbcGeom/ICurves.h>
+#include <Alembic/AbcGeom/OCurves.h>
+
+#include "ptc_types.h"
+
+#include "PTC_api.h"
+
+#include "abc_reader.h"
+#include "abc_schema.h"
+#include "abc_writer.h"
+
+struct Object;
+struct ParticleSystem;
+struct ParticleCacheKey;
+
+namespace PTC {
+
+class AbcClothWriter;
+
+class AbcParticlesWriter : public ParticlesWriter {
+public:
+ AbcParticlesWriter(Scene *scene, Object *ob, ParticleSystem *psys);
+ ~AbcParticlesWriter();
+
+ void write_sample();
+
+ AbcWriterArchive *archive() { return &m_archive; }
+
+private:
+ AbcWriterArchive m_archive;
+ AbcGeom::OPoints m_points;
+};
+
+class AbcParticlesReader : public ParticlesReader {
+public:
+ AbcParticlesReader(Scene *scene, Object *ob, ParticleSystem *psys);
+ ~AbcParticlesReader();
+
+ PTCReadSampleResult read_sample(float frame);
+
+private:
+ AbcReaderArchive m_archive;
+ AbcGeom::IPoints m_points;
+};
+
+class AbcParticlePathsWriter : public ParticlesWriter {
+public:
+ AbcParticlePathsWriter(Scene *scene, Object *ob, ParticleSystem *psys, ParticleCacheKey ***pathcache, int *totpath, const std::string &suffix);
+ ~AbcParticlePathsWriter();
+
+ void set_archive(AbcWriterArchive *archive);
+
+ void write_sample();
+
+private:
+ ParticleCacheKey ***m_pathcache;
+ int *m_totpath;
+ std::string m_suffix;
+
+ AbcWriterArchive *m_archive;
+ AbcGeom::OCurves m_curves;
+
+ AbcGeom::OV3fGeomParam m_param_velocities;
+ AbcGeom::OQuatfGeomParam m_param_rotations;
+ AbcGeom::OV3fGeomParam m_param_colors;
+ AbcGeom::OFloatGeomParam m_param_times;
+};
+
+class AbcParticlePathsReader : public ParticlesReader {
+public:
+ AbcParticlePathsReader(Scene *scene, Object *ob, ParticleSystem *psys, ParticleCacheKey ***pathcache, int *totpath, const std::string &suffix);
+ ~AbcParticlePathsReader();
+
+ PTCReadSampleResult read_sample(float frame);
+
+private:
+ ParticleCacheKey ***m_pathcache;
+ int *m_totpath;
+ std::string m_suffix;
+
+ AbcReaderArchive m_archive;
+ AbcGeom::ICurves m_curves;
+
+ AbcGeom::IV3fGeomParam m_param_velocities;
+ AbcGeom::IQuatfGeomParam m_param_rotations;
+ AbcGeom::IV3fGeomParam m_param_colors;
+ AbcGeom::IFloatGeomParam m_param_times;
+};
+
+class AbcParticlesCombinedWriter : public ParticlesWriter {
+public:
+ AbcParticlesCombinedWriter(Scene *scene, Object *ob, ParticleSystem *psys);
+ ~AbcParticlesCombinedWriter();
+
+ void write_sample();
+
+private:
+ AbcParticlesWriter *m_particles_writer;
+ AbcClothWriter *m_cloth_writer;
+ AbcParticlePathsWriter *m_parent_paths_writer, *m_child_paths_writer;
+};
+
+} /* namespace PTC */
+
+#endif /* PTC_PARTICLES_H */
diff --git a/source/blender/pointcache/alembic/abc_reader.cpp b/source/blender/pointcache/alembic/abc_reader.cpp
new file mode 100644
index 00000000000..c9f88face31
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_reader.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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 "abc_reader.h"
+
+#include "util_path.h"
+#include "util_error_handler.h"
+
+extern "C" {
+#include "BLI_fileops.h"
+
+#include "DNA_pointcache_types.h"
+#include "DNA_scene_types.h"
+}
+
+namespace PTC {
+
+using namespace Abc;
+
+AbcReaderArchive::AbcReaderArchive(Scene *scene, ID *id, PointCache *cache, ErrorHandler *error_handler) :
+ FrameMapper(scene),
+ m_error_handler(error_handler)
+{
+ std::string filename;
+ if (ptc_archive_path(cache->cachelib, filename, id->lib)) {
+ PTC_SAFE_CALL_BEGIN
+ archive = IArchive(AbcCoreHDF5::ReadArchive(), filename, Abc::ErrorHandler::kThrowPolicy);
+ PTC_SAFE_CALL_END_HANDLER(m_error_handler)
+ }
+}
+
+AbcReaderArchive::~AbcReaderArchive()
+{
+}
+
+bool AbcReaderArchive::get_frame_range(int &start_frame, int &end_frame)
+{
+ if (archive.valid()) {
+ double start_time, end_time;
+ GetArchiveStartAndEndTime(archive, start_time, end_time);
+ start_frame = (int)time_to_frame(start_time);
+ end_frame = (int)time_to_frame(end_time);
+ return true;
+ }
+ else {
+ start_frame = end_frame = 1;
+ return false;
+ }
+}
+
+ISampleSelector AbcReaderArchive::get_frame_sample_selector(float frame)
+{
+ return ISampleSelector(frame_to_time(frame), ISampleSelector::kFloorIndex);
+}
+
+PTCReadSampleResult AbcReaderArchive::test_sample(float frame)
+{
+ if (archive.valid()) {
+ double start_time, end_time;
+ GetArchiveStartAndEndTime(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/alembic/abc_reader.h b/source/blender/pointcache/alembic/abc_reader.h
new file mode 100644
index 00000000000..ff43425f0aa
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_reader.h
@@ -0,0 +1,60 @@
+/*
+ * 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_ABC_READER_H
+#define PTC_ABC_READER_H
+
+#include <string>
+
+#include <Alembic/Abc/IArchive.h>
+#include <Alembic/Abc/ISampleSelector.h>
+
+#include "reader.h"
+
+#include "abc_frame_mapper.h"
+
+#include "util_error_handler.h"
+#include "util_types.h"
+
+struct ID;
+struct PointCache;
+struct Scene;
+
+namespace PTC {
+
+using namespace Alembic;
+
+class AbcReaderArchive : public ReaderArchive, public FrameMapper {
+public:
+ AbcReaderArchive(Scene *scene, ID *id, PointCache *cache, ErrorHandler *error_handler);
+ virtual ~AbcReaderArchive();
+
+ bool get_frame_range(int &start_frame, int &end_frame);
+ Abc::ISampleSelector get_frame_sample_selector(float frame);
+
+ PTCReadSampleResult test_sample(float frame);
+
+ Abc::IArchive archive;
+
+protected:
+ ErrorHandler *m_error_handler;
+};
+
+} /* namespace PTC */
+
+#endif /* PTC_READER_H */
diff --git a/source/blender/pointcache/alembic/abc_rigidbody.cpp b/source/blender/pointcache/alembic/abc_rigidbody.cpp
new file mode 100644
index 00000000000..8f9f7111750
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_rigidbody.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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.h"
+
+#include "abc_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;
+
+AbcRigidBodyWriter::AbcRigidBodyWriter(Scene *scene, RigidBodyWorld *rbw) :
+ RigidBodyWriter(scene, rbw, &m_archive),
+ m_archive(scene, &scene->id, rbw->pointcache, m_error_handler)
+{
+ if (m_archive.archive) {
+ }
+}
+
+AbcRigidBodyWriter::~AbcRigidBodyWriter()
+{
+}
+
+void AbcRigidBodyWriter::write_sample()
+{
+ if (!m_archive.archive)
+ return;
+}
+
+
+AbcRigidBodyReader::AbcRigidBodyReader(Scene *scene, RigidBodyWorld *rbw) :
+ RigidBodyReader(scene, rbw, &m_archive),
+ m_archive(scene, &scene->id, rbw->pointcache, m_error_handler)
+{
+ if (m_archive.archive.valid()) {
+ }
+}
+
+AbcRigidBodyReader::~AbcRigidBodyReader()
+{
+}
+
+PTCReadSampleResult AbcRigidBodyReader::read_sample(float frame)
+{
+ return PTC_READ_SAMPLE_INVALID;
+}
+
+/* ==== API ==== */
+
+Writer *abc_writer_rigidbody(Scene *scene, RigidBodyWorld *rbw)
+{
+ return new AbcRigidBodyWriter(scene, rbw);
+}
+
+Reader *abc_reader_rigidbody(Scene *scene, RigidBodyWorld *rbw)
+{
+ return new AbcRigidBodyReader(scene, rbw);
+}
+
+} /* namespace PTC */
diff --git a/source/blender/pointcache/alembic/abc_rigidbody.h b/source/blender/pointcache/alembic/abc_rigidbody.h
new file mode 100644
index 00000000000..4a6a4df2df9
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_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_ABC_RIGIDBODY_H
+#define PTC_ABC_RIGIDBODY_H
+
+//#include <Alembic/AbcGeom/IPoints.h>
+//#include <Alembic/AbcGeom/OPoints.h>
+
+#include "ptc_types.h"
+
+#include "abc_reader.h"
+#include "abc_schema.h"
+#include "abc_writer.h"
+
+struct RigidBodyWorld;
+
+namespace PTC {
+
+class AbcRigidBodyWriter : public RigidBodyWriter {
+public:
+ AbcRigidBodyWriter(Scene *scene, RigidBodyWorld *rbw);
+ ~AbcRigidBodyWriter();
+
+ void write_sample();
+
+private:
+ AbcWriterArchive m_archive;
+// AbcGeom::OPoints m_points;
+};
+
+class AbcRigidBodyReader : public RigidBodyReader {
+public:
+ AbcRigidBodyReader(Scene *scene, RigidBodyWorld *rbw);
+ ~AbcRigidBodyReader();
+
+ PTCReadSampleResult read_sample(float frame);
+
+private:
+ AbcReaderArchive m_archive;
+// AbcGeom::IPoints m_points;
+};
+
+} /* namespace PTC */
+
+#endif /* PTC_RIGIDBODY_H */
diff --git a/source/blender/pointcache/alembic/abc_schema.h b/source/blender/pointcache/alembic/abc_schema.h
new file mode 100644
index 00000000000..d8d70ddac05
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_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_ABC_SCHEMA_H
+#define PTC_ABC_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/alembic/abc_smoke.cpp b/source/blender/pointcache/alembic/abc_smoke.cpp
new file mode 100644
index 00000000000..c03f18ba919
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_smoke.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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.h"
+
+#include "abc_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;
+
+AbcSmokeWriter::AbcSmokeWriter(Scene *scene, Object *ob, SmokeDomainSettings *domain) :
+ SmokeWriter(scene, ob, domain, &m_archive),
+ m_archive(scene, &ob->id, domain->point_cache[0], m_error_handler)
+{
+ if (m_archive.archive) {
+// OObject root = m_archive.archive.getTop();
+// m_points = OPoints(root, m_psys->name, m_archive.frame_sampling_index());
+ }
+}
+
+AbcSmokeWriter::~AbcSmokeWriter()
+{
+}
+
+void AbcSmokeWriter::write_sample()
+{
+ if (!m_archive.archive)
+ return;
+}
+
+
+AbcSmokeReader::AbcSmokeReader(Scene *scene, Object *ob, SmokeDomainSettings *domain) :
+ SmokeReader(scene, ob, domain, &m_archive),
+ m_archive(scene, &ob->id, domain->point_cache[0], m_error_handler)
+{
+ if (m_archive.archive.valid()) {
+ IObject root = m_archive.archive.getTop();
+// m_points = IPoints(root, m_psys->name);
+ }
+}
+
+AbcSmokeReader::~AbcSmokeReader()
+{
+}
+
+PTCReadSampleResult AbcSmokeReader::read_sample(float frame)
+{
+ return PTC_READ_SAMPLE_INVALID;
+}
+
+/* ==== API ==== */
+
+Writer *abc_writer_smoke(Scene *scene, Object *ob, SmokeDomainSettings *domain)
+{
+ return new AbcSmokeWriter(scene, ob, domain);
+}
+
+Reader *abc_reader_smoke(Scene *scene, Object *ob, SmokeDomainSettings *domain)
+{
+ return new AbcSmokeReader(scene, ob, domain);
+}
+
+} /* namespace PTC */
diff --git a/source/blender/pointcache/alembic/abc_smoke.h b/source/blender/pointcache/alembic/abc_smoke.h
new file mode 100644
index 00000000000..0491c5d5cfe
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_smoke.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_ABC_SMOKE_H
+#define PTC_ABC_SMOKE_H
+
+//#include <Alembic/AbcGeom/IPoints.h>
+//#include <Alembic/AbcGeom/OPoints.h>
+
+#include "ptc_types.h"
+
+#include "abc_reader.h"
+#include "abc_schema.h"
+#include "abc_writer.h"
+
+struct Object;
+struct SmokeDomainSettings;
+
+namespace PTC {
+
+class AbcSmokeWriter : public SmokeWriter {
+public:
+ AbcSmokeWriter(Scene *scene, Object *ob, SmokeDomainSettings *domain);
+ ~AbcSmokeWriter();
+
+ void write_sample();
+
+private:
+ AbcWriterArchive m_archive;
+// AbcGeom::OPoints m_points;
+};
+
+class AbcSmokeReader : public SmokeReader {
+public:
+ AbcSmokeReader(Scene *scene, Object *ob, SmokeDomainSettings *domain);
+ ~AbcSmokeReader();
+
+ PTCReadSampleResult read_sample(float frame);
+
+private:
+ AbcReaderArchive m_archive;
+// AbcGeom::IPoints m_points;
+};
+
+} /* namespace PTC */
+
+#endif /* PTC_SMOKE_H */
diff --git a/source/blender/pointcache/alembic/abc_softbody.cpp b/source/blender/pointcache/alembic/abc_softbody.cpp
new file mode 100644
index 00000000000..f824206f01d
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_softbody.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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.h"
+
+#include "abc_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;
+
+AbcSoftBodyWriter::AbcSoftBodyWriter(Scene *scene, Object *ob, SoftBody *softbody) :
+ SoftBodyWriter(scene, ob, softbody, &m_archive),
+ m_archive(scene, &ob->id, softbody->pointcache, m_error_handler)
+{
+ if (m_archive.archive) {
+// OObject root = m_archive.archive.getTop();
+// m_points = OPoints(root, m_psys->name, m_archive.frame_sampling_index());
+ }
+}
+
+AbcSoftBodyWriter::~AbcSoftBodyWriter()
+{
+}
+
+void AbcSoftBodyWriter::write_sample()
+{
+ if (!m_archive.archive)
+ return;
+}
+
+
+AbcSoftBodyReader::AbcSoftBodyReader(Scene *scene, Object *ob, SoftBody *softbody) :
+ SoftBodyReader(scene, ob, softbody, &m_archive),
+ m_archive(scene, &ob->id, softbody->pointcache, m_error_handler)
+{
+ if (m_archive.archive.valid()) {
+ IObject root = m_archive.archive.getTop();
+// m_points = IPoints(root, m_psys->name);
+ }
+}
+
+AbcSoftBodyReader::~AbcSoftBodyReader()
+{
+}
+
+PTCReadSampleResult AbcSoftBodyReader::read_sample(float frame)
+{
+ return PTC_READ_SAMPLE_INVALID;
+}
+
+/* ==== API ==== */
+
+Writer *abc_writer_softbody(Scene *scene, Object *ob, SoftBody *softbody)
+{
+ return new AbcSoftBodyWriter(scene, ob, softbody);
+}
+
+Reader *abc_reader_softbody(Scene *scene, Object *ob, SoftBody *softbody)
+{
+ return new AbcSoftBodyReader(scene, ob, softbody);
+}
+
+} /* namespace PTC */
diff --git a/source/blender/pointcache/alembic/abc_softbody.h b/source/blender/pointcache/alembic/abc_softbody.h
new file mode 100644
index 00000000000..e13fa2c2af6
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_softbody.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_ABC_SOFTBODY_H
+#define PTC_ABC_SOFTBODY_H
+
+//#include <Alembic/AbcGeom/IPoints.h>
+//#include <Alembic/AbcGeom/OPoints.h>
+
+#include "ptc_types.h"
+
+#include "abc_reader.h"
+#include "abc_schema.h"
+#include "abc_writer.h"
+
+struct Object;
+struct SoftBody;
+
+namespace PTC {
+
+class AbcSoftBodyWriter : public SoftBodyWriter {
+public:
+ AbcSoftBodyWriter(Scene *scene, Object *ob, SoftBody *softbody);
+ ~AbcSoftBodyWriter();
+
+ void write_sample();
+
+private:
+ AbcWriterArchive m_archive;
+// AbcGeom::OPoints m_points;
+};
+
+class AbcSoftBodyReader : public SoftBodyReader {
+public:
+ AbcSoftBodyReader(Scene *scene, Object *ob, SoftBody *softbody);
+ ~AbcSoftBodyReader();
+
+ PTCReadSampleResult read_sample(float frame);
+
+private:
+ AbcReaderArchive m_archive;
+// AbcGeom::IPoints m_points;
+};
+
+} /* namespace PTC */
+
+#endif /* PTC_SOFTBODY_H */
diff --git a/source/blender/pointcache/alembic/abc_writer.cpp b/source/blender/pointcache/alembic/abc_writer.cpp
new file mode 100644
index 00000000000..8b64a3076d7
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_writer.cpp
@@ -0,0 +1,73 @@
+/*
+ * 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 "abc_writer.h"
+#include "util_path.h"
+
+extern "C" {
+#include "BLI_fileops.h"
+#include "BLI_path_util.h"
+
+#include "DNA_pointcache_types.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);
+}
+
+AbcWriterArchive::AbcWriterArchive(Scene *scene, ID *id, PointCache *cache, ErrorHandler *error_handler) :
+ FrameMapper(scene),
+ m_error_handler(error_handler)
+{
+ std::string filename;
+ if (ptc_archive_path(cache->cachelib, filename, id->lib)) {
+ ensure_directory(filename.c_str());
+
+ PTC_SAFE_CALL_BEGIN
+
+ archive = OArchive(AbcCoreHDF5::WriteArchive(), filename, Abc::ErrorHandler::kThrowPolicy);
+
+ chrono_t cycle_time = seconds_per_frame();
+ chrono_t start_time = 0.0f;
+ m_frame_sampling = archive.addTimeSampling(TimeSampling(cycle_time, start_time));
+
+ PTC_SAFE_CALL_END_HANDLER(m_error_handler)
+ }
+}
+
+AbcWriterArchive::~AbcWriterArchive()
+{
+}
+
+TimeSamplingPtr AbcWriterArchive::frame_sampling()
+{
+ return archive.getTimeSampling(m_frame_sampling);
+}
+
+} /* namespace PTC */
diff --git a/source/blender/pointcache/alembic/abc_writer.h b/source/blender/pointcache/alembic/abc_writer.h
new file mode 100644
index 00000000000..a7eee1d89e3
--- /dev/null
+++ b/source/blender/pointcache/alembic/abc_writer.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_ABC_WRITER_H
+#define PTC_ABC_WRITER_H
+
+#include <string>
+
+#include <Alembic/Abc/OArchive.h>
+
+#include "writer.h"
+
+#include "abc_frame_mapper.h"
+
+#include "util_error_handler.h"
+
+struct ID;
+struct PointCache;
+struct Scene;
+
+namespace PTC {
+
+using namespace Alembic;
+
+class AbcWriterArchive : public WriterArchive, public FrameMapper {
+public:
+ AbcWriterArchive(Scene *scene, ID *id, PointCache *cache, ErrorHandler *error_handler);
+ virtual ~AbcWriterArchive();
+
+ uint32_t frame_sampling_index() const { return m_frame_sampling; }
+ Abc::TimeSamplingPtr frame_sampling();
+
+ Abc::OArchive archive;
+
+protected:
+ ErrorHandler *m_error_handler;
+ uint32_t m_frame_sampling;
+};
+
+} /* namespace PTC */
+
+#endif /* PTC_WRITER_H */
diff --git a/source/blender/pointcache/intern/alembic.h b/source/blender/pointcache/intern/alembic.h
new file mode 100644
index 00000000000..79341566afc
--- /dev/null
+++ b/source/blender/pointcache/intern/alembic.h
@@ -0,0 +1,72 @@
+/*
+ * 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_ALEMBIC_H
+#define PTC_ALEMBIC_H
+
+#include "reader.h"
+#include "writer.h"
+
+#include "PTC_api.h"
+
+struct Object;
+struct ClothModifierData;
+struct DynamicPaintSurface;
+struct PointCacheModifierData;
+struct DerivedMesh;
+struct ParticleSystem;
+struct RigidBodyWorld;
+struct SmokeDomainSettings;
+struct SoftBody;
+
+namespace PTC {
+
+/* Particles */
+Writer *abc_writer_particles(Scene *scene, Object *ob, ParticleSystem *psys);
+Reader *abc_reader_particles(Scene *scene, Object *ob, ParticleSystem *psys);
+//Writer *abc_writer_particle_paths(Scene *scene, Object *ob, ParticleSystem *psys);
+Reader *abc_reader_particle_paths(Scene *scene, Object *ob, ParticleSystem *psys, eParticlePathsMode mode);
+Writer *abc_writer_particle_combined(Scene *scene, Object *ob, ParticleSystem *psys);
+
+/* Cloth */
+Writer *abc_writer_cloth(Scene *scene, Object *ob, ClothModifierData *clmd);
+Reader *abc_reader_cloth(Scene *scene, Object *ob, ClothModifierData *clmd);
+
+/* SoftBody */
+Writer *abc_writer_softbody(Scene *scene, Object *ob, SoftBody *softbody);
+Reader *abc_reader_softbody(Scene *scene, Object *ob, SoftBody *softbody);
+
+/* Rigid Bodies */
+Writer *abc_writer_rigidbody(Scene *scene, RigidBodyWorld *rbw);
+Reader *abc_reader_rigidbody(Scene *scene, RigidBodyWorld *rbw);
+
+/* Smoke */
+Writer *abc_writer_smoke(Scene *scene, Object *ob, SmokeDomainSettings *domain);
+Reader *abc_reader_smoke(Scene *scene, Object *ob, SmokeDomainSettings *domain);
+
+/* Dynamic Paint */
+Writer *abc_writer_dynamicpaint(Scene *scene, Object *ob, DynamicPaintSurface *surface);
+Reader *abc_reader_dynamicpaint(Scene *scene, Object *ob, DynamicPaintSurface *surface);
+
+/* Modifier Stack */
+Writer *abc_writer_point_cache(Scene *scene, Object *ob, PointCacheModifierData *pcmd);
+Reader *abc_reader_point_cache(Scene *scene, Object *ob, PointCacheModifierData *pcmd);
+
+} /* namespace PTC */
+
+#endif /* PTC_EXPORT_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/ptc_types.cpp b/source/blender/pointcache/intern/ptc_types.cpp
new file mode 100644
index 00000000000..3a012429586
--- /dev/null
+++ b/source/blender/pointcache/intern/ptc_types.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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_types.h"
+
+extern "C" {
+#include "BKE_DerivedMesh.h"
+}
+
+namespace PTC {
+
+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 */
diff --git a/source/blender/pointcache/intern/ptc_types.h b/source/blender/pointcache/intern/ptc_types.h
new file mode 100644
index 00000000000..e81c052185d
--- /dev/null
+++ b/source/blender/pointcache/intern/ptc_types.h
@@ -0,0 +1,276 @@
+/*
+ * 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_TYPES_H
+#define PTC_TYPES_H
+
+#include "reader.h"
+#include "writer.h"
+
+extern "C" {
+#include "DNA_dynamicpaint_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+#include "DNA_object_force.h"
+#include "DNA_particle_types.h"
+#include "DNA_rigidbody_types.h"
+#include "DNA_smoke_types.h"
+}
+
+namespace PTC {
+
+class ClothWriter : public Writer {
+public:
+ ClothWriter(Scene *scene, Object *ob, ClothModifierData *clmd, WriterArchive *archive) :
+ Writer(scene, (ID *)ob, archive),
+ m_ob(ob),
+ m_clmd(clmd)
+ {}
+
+ ~ClothWriter()
+ {}
+
+protected:
+ Object *m_ob;
+ ClothModifierData *m_clmd;
+};
+
+class ClothReader : public Reader {
+public:
+ ClothReader(Scene *scene, Object *ob, ClothModifierData *clmd, ReaderArchive *archive) :
+ Reader(scene, (ID *)ob, archive),
+ m_ob(ob),
+ m_clmd(clmd)
+ {}
+
+ ~ClothReader()
+ {}
+
+protected:
+ Object *m_ob;
+ ClothModifierData *m_clmd;
+};
+
+
+class DynamicPaintWriter : public Writer {
+public:
+ DynamicPaintWriter(Scene *scene, Object *ob, DynamicPaintSurface *surface, WriterArchive *archive) :
+ Writer(scene, (ID *)ob, archive),
+ m_ob(ob),
+ m_surface(surface)
+ {}
+
+ ~DynamicPaintWriter()
+ {}
+
+protected:
+ Object *m_ob;
+ DynamicPaintSurface *m_surface;
+};
+
+class DynamicPaintReader : public Reader {
+public:
+ DynamicPaintReader(Scene *scene, Object *ob, DynamicPaintSurface *surface, ReaderArchive *archive) :
+ Reader(scene, (ID *)ob, archive),
+ m_ob(ob),
+ m_surface(surface)
+ {}
+
+ ~DynamicPaintReader()
+ {}
+
+protected:
+ Object *m_ob;
+ DynamicPaintSurface *m_surface;
+};
+
+
+class PointCacheWriter : public Writer {
+public:
+ PointCacheWriter(Scene *scene, Object *ob, PointCacheModifierData *pcmd, WriterArchive *archive) :
+ Writer(scene, (ID *)ob, archive),
+ m_ob(ob),
+ m_pcmd(pcmd)
+ {}
+
+ ~PointCacheWriter()
+ {}
+
+protected:
+ Object *m_ob;
+ PointCacheModifierData *m_pcmd;
+};
+
+class PointCacheReader : public Reader {
+public:
+ PointCacheReader(Scene *scene, Object *ob, PointCacheModifierData *pcmd, ReaderArchive *archive) :
+ Reader(scene, (ID *)ob, archive),
+ m_ob(ob),
+ m_pcmd(pcmd),
+ m_result(0)
+ {}
+
+ ~PointCacheReader()
+ {}
+
+ virtual DerivedMesh *acquire_result();
+ virtual void discard_result();
+
+protected:
+ Object *m_ob;
+ PointCacheModifierData *m_pcmd;
+
+ DerivedMesh *m_result;
+};
+
+
+class ParticlesWriter : public Writer {
+public:
+ ParticlesWriter(Scene *scene, Object *ob, ParticleSystem *psys, WriterArchive *archive) :
+ Writer(scene, (ID *)ob, archive),
+ m_ob(ob),
+ m_psys(psys)
+ {}
+
+ ~ParticlesWriter()
+ {}
+
+protected:
+ Object *m_ob;
+ ParticleSystem *m_psys;
+};
+
+class ParticlesReader : public Reader {
+public:
+ ParticlesReader(Scene *scene, Object *ob, ParticleSystem *psys, ReaderArchive *archive) :
+ Reader(scene, (ID *)ob, archive),
+ m_ob(ob),
+ m_psys(psys),
+ m_totpoint(0)
+ {}
+
+ ~ParticlesReader()
+ {}
+
+ int totpoint() const { return m_totpoint; }
+
+protected:
+ Object *m_ob;
+ ParticleSystem *m_psys;
+
+ int m_totpoint;
+};
+
+
+class RigidBodyWriter : public Writer {
+public:
+ RigidBodyWriter(Scene *scene, RigidBodyWorld *rbw, WriterArchive *archive) :
+ Writer(scene, (ID *)scene, archive),
+ m_rbw(rbw)
+ {}
+
+ ~RigidBodyWriter()
+ {}
+
+protected:
+ RigidBodyWorld *m_rbw;
+};
+
+class RigidBodyReader : public Reader {
+public:
+ RigidBodyReader(Scene *scene, RigidBodyWorld *rbw, ReaderArchive *archive) :
+ Reader(scene, (ID *)scene, archive),
+ m_rbw(rbw)
+ {}
+
+ ~RigidBodyReader()
+ {}
+
+protected:
+ RigidBodyWorld *m_rbw;
+};
+
+
+class SmokeWriter : public Writer {
+public:
+ SmokeWriter(Scene *scene, Object *ob, SmokeDomainSettings *domain, WriterArchive *archive) :
+ Writer(scene, (ID *)ob, archive),
+ m_ob(ob),
+ m_domain(domain)
+ {}
+
+ ~SmokeWriter()
+ {}
+
+protected:
+ Object *m_ob;
+ SmokeDomainSettings *m_domain;
+};
+
+class SmokeReader : public Reader {
+public:
+ SmokeReader(Scene *scene, Object *ob, SmokeDomainSettings *domain, ReaderArchive *archive) :
+ Reader(scene, (ID *)ob, archive),
+ m_ob(ob),
+ m_domain(domain)
+ {}
+
+ ~SmokeReader()
+ {}
+
+protected:
+ Object *m_ob;
+ SmokeDomainSettings *m_domain;
+};
+
+
+class SoftBodyWriter : public Writer {
+public:
+ SoftBodyWriter(Scene *scene, Object *ob, SoftBody *softbody, WriterArchive *archive) :
+ Writer(scene, (ID *)ob, archive),
+ m_ob(ob),
+ m_softbody(softbody)
+ {}
+
+ ~SoftBodyWriter()
+ {}
+
+protected:
+ Object *m_ob;
+ SoftBody *m_softbody;
+};
+
+class SoftBodyReader : public Reader {
+public:
+ SoftBodyReader(Scene *scene, Object *ob, SoftBody *softbody, ReaderArchive *archive) :
+ Reader(scene, (ID *)ob, archive),
+ m_ob(ob),
+ m_softbody(softbody)
+ {}
+
+ ~SoftBodyReader()
+ {}
+
+protected:
+ Object *m_ob;
+ SoftBody *m_softbody;
+};
+
+} /* namespace PTC */
+
+#endif /* PTC_EXPORT_H */
diff --git a/source/blender/pointcache/intern/reader.cpp b/source/blender/pointcache/intern/reader.cpp
new file mode 100644
index 00000000000..829e4eb807d
--- /dev/null
+++ b/source/blender/pointcache/intern/reader.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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 "reader.h"
+#include "util_error_handler.h"
+
+extern "C" {
+#include "DNA_scene_types.h"
+}
+
+namespace PTC {
+
+Reader::Reader(Scene *scene, ID *id, ReaderArchive *archive) :
+ m_error_handler(0),
+ m_archive(archive),
+ m_scene(scene),
+ m_id(id)
+{
+}
+
+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;
+}
+
+} /* namespace PTC */
diff --git a/source/blender/pointcache/intern/reader.h b/source/blender/pointcache/intern/reader.h
new file mode 100644
index 00000000000..1c89c0c9b42
--- /dev/null
+++ b/source/blender/pointcache/intern/reader.h
@@ -0,0 +1,75 @@
+/*
+ * 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 "util_error_handler.h"
+#include "util_types.h"
+
+struct ID;
+struct Scene;
+
+namespace PTC {
+
+class ReaderArchive {
+public:
+ virtual ~ReaderArchive() {}
+
+ virtual bool get_frame_range(int &start_frame, int &end_frame) = 0;
+
+ virtual PTCReadSampleResult test_sample(float frame) = 0;
+};
+
+class Reader {
+public:
+ Reader(Scene *scene, ID *id, ReaderArchive *archive);
+ virtual ~Reader();
+
+ void set_error_handler(ErrorHandler *handler);
+ ErrorHandler *get_error_handler() const { return m_error_handler; }
+ bool valid() const;
+
+ inline bool get_frame_range(int &start_frame, int &end_frame)
+ {
+ return m_archive->get_frame_range(start_frame, end_frame);
+ }
+
+ inline PTCReadSampleResult test_sample(float frame)
+ {
+ return m_archive->test_sample(frame);
+ }
+
+ virtual PTCReadSampleResult read_sample(float frame) = 0;
+
+ Scene *scene() const { return m_scene; }
+ ID *id() const { return m_id; }
+
+protected:
+ ErrorHandler *m_error_handler;
+ ReaderArchive *m_archive;
+
+ Scene *m_scene;
+ ID *m_id;
+};
+
+} /* namespace PTC */
+
+#endif /* PTC_READER_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..cbdee4234d7
--- /dev/null
+++ b/source/blender/pointcache/intern/writer.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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 "writer.h"
+
+extern "C" {
+#include "DNA_scene_types.h"
+}
+
+namespace PTC {
+
+Writer::Writer(Scene *scene, ID *id, WriterArchive *archive) :
+ m_error_handler(0),
+ m_scene(scene),
+ m_id(id),
+ m_archive(archive)
+{
+}
+
+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;
+}
+
+} /* namespace PTC */
diff --git a/source/blender/pointcache/intern/writer.h b/source/blender/pointcache/intern/writer.h
new file mode 100644
index 00000000000..69ad2a69c24
--- /dev/null
+++ b/source/blender/pointcache/intern/writer.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_WRITER_H
+#define PTC_WRITER_H
+
+#include <string>
+
+#include "util_error_handler.h"
+
+struct ID;
+struct Scene;
+
+namespace PTC {
+
+class WriterArchive {
+public:
+ virtual ~WriterArchive() {}
+};
+
+class Writer {
+public:
+ Writer(Scene *scene, ID *id, WriterArchive *archive);
+ virtual ~Writer();
+
+ void set_error_handler(ErrorHandler *handler);
+ bool valid() const;
+
+ virtual void write_sample() = 0;
+
+ Scene *scene() const { return m_scene; }
+ ID *id() const { return m_id; }
+
+protected:
+ ErrorHandler *m_error_handler;
+
+ Scene *m_scene;
+ ID *m_id;
+
+private:
+ WriterArchive *m_archive;
+};
+
+} /* 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..e1a326e1713
--- /dev/null
+++ b/source/blender/pointcache/util/util_error_handler.cpp
@@ -0,0 +1,102 @@
+/*
+ * 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 <iostream>
+
+#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..61baa03a357
--- /dev/null
+++ b/source/blender/pointcache/util/util_error_handler.h
@@ -0,0 +1,201 @@
+/*
+ * 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>
+
+#ifdef WITH_ALEMBIC
+#include <Alembic/Abc/ErrorHandler.h>
+#endif
+
+extern "C" {
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+}
+
+#include "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;
+};
+
+/* -------------------------------- */
+
+#ifdef WITH_ALEMBIC
+
+/* 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)
+{
+ static StdErrorHandler default_handler(PTC_ERROR_WARNING);
+ if (!handler)
+ handler = &default_handler;
+
+ const char *origin, *msg;
+ split_alembic_error_message(e.what(), &origin, &msg);
+
+ handler->set_error_level(level);
+ handler->handle(level, msg);
+}
+
+#endif
+
+/* -------------------------------- */
+
+/* macros for convenient exception handling */
+
+#define PTC_SAFE_CALL_BEGIN \
+ try {
+
+#ifdef WITH_ALEMBIC
+#define PTC_SAFE_CALL_END_HANDLER(handler) \
+ } \
+ catch (Alembic::Util::Exception e) { \
+ handle_alembic_exception((handler), PTC_ERROR_CRITICAL, e); \
+ }
+#else
+#define PTC_SAFE_CALL_END_HANDLER(handler) \
+ }
+#endif
+
+#ifdef WITH_ALEMBIC
+#define PTC_SAFE_CALL_END_HANDLER_LEVEL(handler, level) \
+ } \
+ catch (Alembic::Util::Exception e) { \
+ handle_alembic_exception((handler), (level), e); \
+ }
+#else
+#define PTC_SAFE_CALL_END_HANDLER_LEVEL(handler, level) \
+ }
+#endif
+
+#ifdef WITH_ALEMBIC
+#define PTC_SAFE_CALL_END \
+ } \
+ catch (Alembic::Util::Exception e) { \
+ handle_alembic_exception(ErrorHandler::get_default_handler(), PTC_ERROR_CRITICAL, e); \
+ }
+#else
+#define PTC_SAFE_CALL_END \
+ }
+#endif
+
+/* -------------------------------- */
+
+} /* namespace PTC */
+
+#endif /* PTC_UTIL_ERROR_HANDLER_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..87fab3239c1
--- /dev/null
+++ b/source/blender/pointcache/util/util_path.cpp
@@ -0,0 +1,101 @@
+/*
+ * 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_fileops.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_ID.h"
+
+#include "BKE_appdir.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+}
+
+namespace PTC {
+
+#if 0
+BLI_INLINE bool path_is_rel(const std::string &path)
+{
+ return BLI_path_is_rel(path.c_str());
+}
+
+BLI_INLINE bool is_dir(const std::string &path)
+{
+ return BLI_is_dir(path.c_str());
+}
+
+BLI_INLINE bool path_is_dirpath(const std::string &path)
+{
+ /* last char is a slash? */
+ return *(BLI_last_slash(path.c_str()) + 1) == '\0';
+}
+
+BLI_INLINE std::string path_join_dirfile(const std::string &dir, const std::string &file)
+{
+ char path[FILE_MAX];
+ BLI_join_dirfile(path, sizeof(path), dir.c_str(), file.c_str());
+ return std::string(path);
+}
+
+BLI_INLINE std::string path_abs(const std::string &path, const std::string &basepath)
+{
+ char npath[FILE_MAX];
+ BLI_strncpy(npath, path.c_str(), sizeof(npath));
+ BLI_path_abs(npath, basepath.c_str());
+ return std::string(npath);
+}
+
+bool ptc_archive_path(CacheLibrary *cachelib, std::string &filepath, Library *lib)
+{
+ filepath = "";
+
+ if (!cachelib)
+ return false;
+
+ std::string abspath;
+ if (path_is_rel(cachelib->filepath)) {
+ if (G.relbase_valid || lib) {
+ std::string relbase = lib ? lib->filepath: G.main->name;
+ abspath = path_abs(cachelib->filepath, relbase);
+ }
+ else
+ return false;
+ }
+ else {
+ abspath = cachelib->filepath;
+ }
+
+ if (path_is_dirpath(abspath) || is_dir(abspath)) {
+ filepath = path_join_dirfile(abspath, cachelib->id.name+2);
+ }
+ else {
+ filepath = abspath;
+ }
+
+ return true;
+}
+#endif
+
+} /* 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..377235d70df
--- /dev/null
+++ b/source/blender/pointcache/util/util_path.h
@@ -0,0 +1,35 @@
+/*
+ * 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 Library;
+
+namespace PTC {
+
+#if 0
+bool ptc_archive_path(CacheLibrary *cachelib, std::string &filepath, Library *lib);
+#endif
+
+} /* 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/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,