diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2016-09-04 17:41:06 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2016-09-04 17:41:06 +0300 |
commit | 3c29aad787f636167319950636f1497442075df8 (patch) | |
tree | 3a993cc25296ce987893b9f58b7c794b51e77f85 /source/blender/alembic | |
parent | 498583844fb7d0adbbc91d512f98885800cdf46e (diff) | |
parent | e76e8fcdcc53455a52a6a73495881eddd346472c (diff) |
Merge branch 'master' into blender2.8
Conflicts:
intern/cycles/blender/blender_particles.cpp
source/blender/blenkernel/intern/particle.c
source/blender/gpu/intern/gpu_shader.c
Diffstat (limited to 'source/blender/alembic')
-rw-r--r-- | source/blender/alembic/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_exporter.cc | 85 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_exporter.h | 2 | ||||
-rw-r--r-- | source/blender/alembic/intern/alembic_capi.cc | 125 |
4 files changed, 160 insertions, 53 deletions
diff --git a/source/blender/alembic/CMakeLists.txt b/source/blender/alembic/CMakeLists.txt index 42bd6a9c340..0b6b2433bd0 100644 --- a/source/blender/alembic/CMakeLists.txt +++ b/source/blender/alembic/CMakeLists.txt @@ -33,6 +33,7 @@ set(INC ../makesrna ../windowmanager ../../../intern/guardedalloc + ../../../intern/utfconv ) set(INC_SYS diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc index 132c59c0cfb..57a2bdd274f 100644 --- a/source/blender/alembic/intern/abc_exporter.cc +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -30,6 +30,10 @@ #include <Alembic/AbcCoreOgawa/All.h> +#ifdef WIN32 +# include "utfconv.h" +#endif + #include "abc_camera.h" #include "abc_curves.h" #include "abc_hair.h" @@ -66,6 +70,54 @@ extern "C" { using Alembic::Abc::TimeSamplingPtr; using Alembic::Abc::OBox3dProperty; + +/* ************************************************************************** */ + +/* This kinda duplicates CreateArchiveWithInfo, but Alembic does not seem to + * have a version supporting streams. */ +static Alembic::Abc::OArchive create_archive(std::ostream *ostream, + const std::string &filename, + const std::string &scene_name, + const Alembic::Abc::Argument &arg0, + const Alembic::Abc::Argument &arg1, + bool ogawa) +{ + Alembic::Abc::MetaData md = GetMetaData(arg0, arg1); + md.set(Alembic::Abc::kApplicationNameKey, "Blender"); + md.set(Alembic::Abc::kUserDescriptionKey, scene_name); + + time_t raw_time; + time(&raw_time); + char buffer[128]; + +#if defined _WIN32 || defined _WIN64 + ctime_s(buffer, 128, &raw_time); +#else + ctime_r(&raw_time, buffer); +#endif + + const std::size_t buffer_len = strlen(buffer); + if (buffer_len > 0 && buffer[buffer_len - 1] == '\n') { + buffer[buffer_len - 1] = '\0'; + } + + md.set(Alembic::Abc::kDateWrittenKey, buffer); + + Alembic::Abc::ErrorHandler::Policy policy = GetErrorHandlerPolicyFromArgs(arg0, arg1); + +#ifdef WITH_ALEMBIC_HDF5 + if (!ogawa) { + return Alembic::Abc::OArchive(Alembic::AbcCoreHDF5::WriteArchive(), filename, md, policy); + } +#else + static_cast<void>(filename); + static_cast<void>(ogawa); +#endif + + Alembic::AbcCoreOgawa::WriteArchive archive_writer; + return Alembic::Abc::OArchive(archive_writer(ostream, md), Alembic::Abc::kWrapExisting, policy); +} + /* ************************************************************************** */ ExportSettings::ExportSettings() @@ -246,26 +298,25 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled) Alembic::Abc::Argument arg(md); -#ifdef WITH_ALEMBIC_HDF5 - if (!m_settings.export_ogawa) { - m_archive = Alembic::Abc::CreateArchiveWithInfo(Alembic::AbcCoreHDF5::WriteArchive(), - m_filename, - "Blender", - scene_name, - Alembic::Abc::ErrorHandler::kThrowPolicy, - arg); - } - else + /* Use stream to support unicode character paths on Windows. */ + if (m_settings.export_ogawa) { +#ifdef WIN32 + UTF16_ENCODE(m_filename); + std::wstring wstr(m_filename_16); + m_out_file.open(wstr.c_str(), std::ios::out | std::ios::binary); + UTF16_UN_ENCODE(m_filename); +#else + m_out_file.open(m_filename, std::ios::out | std::ios::binary); #endif - { - m_archive = Alembic::Abc::CreateArchiveWithInfo(Alembic::AbcCoreOgawa::WriteArchive(), - m_filename, - "Blender", - scene_name, - Alembic::Abc::ErrorHandler::kThrowPolicy, - arg); } + m_archive = create_archive(&m_out_file, + m_filename, + scene_name, + Alembic::Abc::ErrorHandler::kThrowPolicy, + arg, + m_settings.export_ogawa); + /* Create time samplings for transforms and shapes. */ TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_step_xform); diff --git a/source/blender/alembic/intern/abc_exporter.h b/source/blender/alembic/intern/abc_exporter.h index 070eb9ea81a..6c242f973c4 100644 --- a/source/blender/alembic/intern/abc_exporter.h +++ b/source/blender/alembic/intern/abc_exporter.h @@ -24,6 +24,7 @@ #define __ABC_EXPORTER_H__ #include <Alembic/Abc/All.h> +#include <fstream> #include <map> #include <set> #include <vector> @@ -75,6 +76,7 @@ class AbcExporter { const char *m_filename; + std::ofstream m_out_file; Alembic::Abc::OArchive m_archive; unsigned int m_trans_sampling_index, m_shape_sampling_index; diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index f42c708b4c2..d057cc341f6 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -29,6 +29,12 @@ #include <Alembic/AbcCoreOgawa/All.h> #include <Alembic/AbcMaterial/IMaterial.h> +#include <fstream> + +#ifdef WIN32 +# include "utfconv.h" +#endif + #include "abc_camera.h" #include "abc_curves.h" #include "abc_hair.h" @@ -109,49 +115,97 @@ using Alembic::AbcGeom::V3fArraySamplePtr; using Alembic::AbcMaterial::IMaterial; -struct AbcArchiveHandle { - int unused; -}; - -ABC_INLINE IArchive *archive_from_handle(AbcArchiveHandle *handle) -{ - return reinterpret_cast<IArchive *>(handle); -} - -ABC_INLINE AbcArchiveHandle *handle_from_archive(IArchive *archive) +static IArchive open_archive(const std::string &filename, + const std::vector<std::istream *> &input_streams, + bool &is_hdf5) { - return reinterpret_cast<AbcArchiveHandle *>(archive); -} - -static IArchive *open_archive(const std::string &filename) -{ - Alembic::AbcCoreAbstract::ReadArraySampleCachePtr cache_ptr; - IArchive *archive; - try { - archive = new IArchive(Alembic::AbcCoreOgawa::ReadArchive(), - filename.c_str(), ErrorHandler::kThrowPolicy, - cache_ptr); + is_hdf5 = false; + Alembic::AbcCoreOgawa::ReadArchive archive_reader(input_streams); + + return IArchive(archive_reader(filename), + kWrapExisting, + ErrorHandler::kThrowPolicy); } catch (const Exception &e) { std::cerr << e.what() << '\n'; #ifdef WITH_ALEMBIC_HDF5 try { - archive = new IArchive(Alembic::AbcCoreHDF5::ReadArchive(), - filename.c_str(), ErrorHandler::kThrowPolicy, - cache_ptr); + is_hdf5 = true; + Alembic::AbcCoreAbstract::ReadArraySampleCachePtr cache_ptr; + + return IArchive(Alembic::AbcCoreHDF5::ReadArchive(), + filename.c_str(), ErrorHandler::kThrowPolicy, + cache_ptr); } catch (const Exception &) { std::cerr << e.what() << '\n'; - return NULL; + return IArchive(); } #else - return NULL; + return IArchive(); #endif } - return archive; + return IArchive(); +} + +/* Wrapper around an archive to be able to use streams so that unicode paths + * work on Windows (T49112), and to make sure the input stream remains valid as + * long as the archive is open. */ +class ArchiveWrapper { + IArchive m_archive; + std::ifstream m_infile; + std::vector<std::istream *> m_streams; + +public: + explicit ArchiveWrapper(const char *filename) + { +#ifdef WIN32 + UTF16_ENCODE(filename); + std::wstring wstr(filename_16); + m_infile.open(wstr.c_str(), std::ios::in | std::ios::binary); + UTF16_UN_ENCODE(filename); +#else + m_infile.open(filename, std::ios::in | std::ios::binary); +#endif + + m_streams.push_back(&m_infile); + + bool is_hdf5; + m_archive = open_archive(filename, m_streams, is_hdf5); + + /* We can't open an HDF5 file from a stream, so close it. */ + if (is_hdf5) { + m_infile.close(); + m_streams.clear(); + } + } + + bool valid() const + { + return m_archive.valid(); + } + + IObject getTop() + { + return m_archive.getTop(); + } +}; + +struct AbcArchiveHandle { + int unused; +}; + +ABC_INLINE ArchiveWrapper *archive_from_handle(AbcArchiveHandle *handle) +{ + return reinterpret_cast<ArchiveWrapper *>(handle); +} + +ABC_INLINE AbcArchiveHandle *handle_from_archive(ArchiveWrapper *archive) +{ + return reinterpret_cast<AbcArchiveHandle *>(archive); } //#define USE_NURBS @@ -247,9 +301,10 @@ static void gather_objects_paths(const IObject &object, ListBase *object_paths) AbcArchiveHandle *ABC_create_handle(const char *filename, ListBase *object_paths) { - IArchive *archive = open_archive(filename); + ArchiveWrapper *archive = new ArchiveWrapper(filename); - if (!archive) { + if (!archive->valid()) { + delete archive; return NULL; } @@ -582,12 +637,10 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa data->do_update = do_update; data->progress = progress; - IArchive *archive = open_archive(data->filename); + ArchiveWrapper *archive = new ArchiveWrapper(data->filename); - if (!archive || !archive->valid()) { - if (archive) { - delete archive; - } + if (!archive->valid()) { + delete archive; data->error_code = ABC_ARCHIVE_FAIL; return; } @@ -812,7 +865,7 @@ void ABC_import(bContext *C, const char *filepath, float scale, bool is_sequence void ABC_get_transform(AbcArchiveHandle *handle, Object *ob, const char *object_path, float r_mat[4][4], float time, float scale) { - IArchive *archive = archive_from_handle(handle); + ArchiveWrapper *archive = archive_from_handle(handle); if (!archive || !archive->valid()) { return; @@ -1088,7 +1141,7 @@ DerivedMesh *ABC_read_mesh(AbcArchiveHandle *handle, const char **err_str, int read_flag) { - IArchive *archive = archive_from_handle(handle); + ArchiveWrapper *archive = archive_from_handle(handle); if (!archive || !archive->valid()) { *err_str = "Invalid archive!"; |