diff options
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, |