diff options
Diffstat (limited to 'source/blender/alembic/intern')
-rw-r--r-- | source/blender/alembic/intern/abc_archive.cc | 175 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_archive.h | 66 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_customdata.h | 9 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_exporter.cc | 96 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_exporter.h | 10 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_hair.cc | 2 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_mesh.cc | 99 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_points.cc | 2 | ||||
-rw-r--r-- | source/blender/alembic/intern/alembic_capi.cc | 120 |
9 files changed, 386 insertions, 193 deletions
diff --git a/source/blender/alembic/intern/abc_archive.cc b/source/blender/alembic/intern/abc_archive.cc new file mode 100644 index 00000000000..0985a06d732 --- /dev/null +++ b/source/blender/alembic/intern/abc_archive.cc @@ -0,0 +1,175 @@ +/* + * ***** 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) 2016 Kévin Dietrich. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#include "abc_archive.h" + +#ifdef WIN32 +# include "utfconv.h" +#endif + +using Alembic::Abc::Exception; +using Alembic::Abc::ErrorHandler; +using Alembic::Abc::IArchive; +using Alembic::Abc::kWrapExisting; +using Alembic::Abc::OArchive; + +static IArchive open_archive(const std::string &filename, + const std::vector<std::istream *> &input_streams, + bool &is_hdf5) +{ + try { + 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 { + 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 IArchive(); + } +#else + return IArchive(); +#endif + } + + return IArchive(); +} + +ArchiveReader::ArchiveReader(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 ArchiveReader::valid() const +{ + return m_archive.valid(); +} + +Alembic::Abc::IObject ArchiveReader::getTop() +{ + return m_archive.getTop(); +} + +/* ************************************************************************** */ + +/* This kinda duplicates CreateArchiveWithInfo, but Alembic does not seem to + * have a version supporting streams. */ +static OArchive create_archive(std::ostream *ostream, + const std::string &filename, + const std::string &scene_name, + Alembic::Abc::MetaData &md, + bool ogawa) +{ + 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); + + ErrorHandler::Policy policy = ErrorHandler::kThrowPolicy; + +#ifdef WITH_ALEMBIC_HDF5 + if (!ogawa) { + return OArchive(Alembic::AbcCoreHDF5::WriteArchive(), filename, md, policy); + } +#else + static_cast<void>(filename); + static_cast<void>(ogawa); +#endif + + Alembic::AbcCoreOgawa::WriteArchive archive_writer; + return OArchive(archive_writer(ostream, md), kWrapExisting, policy); +} + +ArchiveWriter::ArchiveWriter(const char *filename, const char *scene, bool do_ogawa, Alembic::Abc::MetaData &md) +{ + /* Use stream to support unicode character paths on Windows. */ + if (do_ogawa) { +#ifdef WIN32 + UTF16_ENCODE(filename); + std::wstring wstr(filename_16); + m_outfile.open(wstr.c_str(), std::ios::out | std::ios::binary); + UTF16_UN_ENCODE(filename); +#else + m_outfile.open(filename, std::ios::out | std::ios::binary); +#endif + } + + m_archive = create_archive(&m_outfile, + filename, + scene, + md, + do_ogawa); +} + +OArchive &ArchiveWriter::archive() +{ + return m_archive; +} diff --git a/source/blender/alembic/intern/abc_archive.h b/source/blender/alembic/intern/abc_archive.h new file mode 100644 index 00000000000..d412574b736 --- /dev/null +++ b/source/blender/alembic/intern/abc_archive.h @@ -0,0 +1,66 @@ +/* + * ***** 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) 2016 Kévin Dietrich. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#ifndef __ABC_ARCHIVE_H__ +#define __ABC_ARCHIVE_H__ + +#include <Alembic/Abc/All.h> + +#ifdef WITH_ALEMBIC_HDF5 +# include <Alembic/AbcCoreHDF5/All.h> +#endif + +#include <Alembic/AbcCoreOgawa/All.h> + +#include <fstream> + +/* Wrappers around input and output archives. The goal is to be able to use + * streams so that unicode paths work on Windows (T49112), and to make sure that + * the stream objects remain valid as long as the archives are open. + */ + +class ArchiveReader { + Alembic::Abc::IArchive m_archive; + std::ifstream m_infile; + std::vector<std::istream *> m_streams; + +public: + explicit ArchiveReader(const char *filename); + + bool valid() const; + + Alembic::Abc::IObject getTop(); +}; + +class ArchiveWriter { + std::ofstream m_outfile; + Alembic::Abc::OArchive m_archive; + +public: + explicit ArchiveWriter(const char *filename, const char *scene, bool do_ogawa, Alembic::Abc::MetaData &md); + + Alembic::Abc::OArchive &archive(); +}; + +#endif /* __ABC_ARCHIVE_H__ */ diff --git a/source/blender/alembic/intern/abc_customdata.h b/source/blender/alembic/intern/abc_customdata.h index 3b16c0d9796..bc42e24eba1 100644 --- a/source/blender/alembic/intern/abc_customdata.h +++ b/source/blender/alembic/intern/abc_customdata.h @@ -63,6 +63,11 @@ struct CDStreamConfig { void *user_data; void *(*add_customdata_cb)(void *user_data, const char *name, int data_type); + float weight; + float time; + int index; + int ceil_index; + CDStreamConfig() : mloop(NULL) , totloop(0) @@ -72,6 +77,10 @@ struct CDStreamConfig { , pack_uvs(false) , user_data(NULL) , add_customdata_cb(NULL) + , weight(0.0f) + , time(0.0f) + , index(0) + , ceil_index(0) {} }; diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc index 764b1533309..a31122b7cd0 100644 --- a/source/blender/alembic/intern/abc_exporter.cc +++ b/source/blender/alembic/intern/abc_exporter.cc @@ -24,16 +24,7 @@ #include <cmath> -#ifdef WITH_ALEMBIC_HDF5 -# include <Alembic/AbcCoreHDF5/All.h> -#endif - -#include <Alembic/AbcCoreOgawa/All.h> - -#ifdef WIN32 -# include "utfconv.h" -#endif - +#include "abc_archive.h" #include "abc_camera.h" #include "abc_curves.h" #include "abc_hair.h" @@ -71,54 +62,6 @@ 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() @@ -145,6 +88,9 @@ ExportSettings::ExportSettings() , export_ogawa(true) , pack_uv(false) , do_convert_axis(false) + , triangulate(false) + , quad_method(0) + , ngon_method(0) {} static bool object_is_smoke_sim(Object *ob) @@ -202,6 +148,7 @@ AbcExporter::AbcExporter(Scene *scene, const char *filename, ExportSettings &set , m_trans_sampling_index(0) , m_shape_sampling_index(0) , m_scene(scene) + , m_writer(NULL) {} AbcExporter::~AbcExporter() @@ -214,6 +161,8 @@ AbcExporter::~AbcExporter() for (int i = 0, e = m_shapes.size(); i != e; ++i) { delete m_shapes[i]; } + + delete m_writer; } void AbcExporter::getShutterSamples(double step, bool time_relative, @@ -297,32 +246,13 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled) Alembic::AbcCoreAbstract::MetaData md; md.set("FramesPerTimeUnit", str_fps); - Alembic::Abc::Argument arg(md); - - /* 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 = create_archive(&m_out_file, - m_filename, - scene_name, - Alembic::Abc::ErrorHandler::kThrowPolicy, - arg, - m_settings.export_ogawa); + m_writer = new ArchiveWriter(m_filename, scene_name.c_str(), m_settings.export_ogawa, md); /* Create time samplings for transforms and shapes. */ TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_step_xform); - m_trans_sampling_index = m_archive.addTimeSampling(*trans_time); + m_trans_sampling_index = m_writer->archive().addTimeSampling(*trans_time); TimeSamplingPtr shape_time; @@ -334,10 +264,10 @@ void AbcExporter::operator()(Main *bmain, float &progress, bool &was_canceled) } else { shape_time = createTimeSampling(m_settings.frame_step_shape); - m_shape_sampling_index = m_archive.addTimeSampling(*shape_time); + m_shape_sampling_index = m_writer->archive().addTimeSampling(*shape_time); } - OBox3dProperty archive_bounds_prop = Alembic::AbcGeom::CreateOArchiveBounds(m_archive, m_trans_sampling_index); + OBox3dProperty archive_bounds_prop = Alembic::AbcGeom::CreateOArchiveBounds(m_writer->archive(), m_trans_sampling_index); if (m_settings.flatten_hierarchy) { createTransformWritersFlat(); @@ -443,7 +373,7 @@ void AbcExporter::createTransformWritersFlat() if (export_object(&m_settings, ob) && object_is_shape(ob)) { std::string name = get_id_name(ob); - m_xforms[name] = new AbcTransformWriter(ob, m_archive.getTop(), 0, m_trans_sampling_index, m_settings); + m_xforms[name] = new AbcTransformWriter(ob, m_writer->archive().getTop(), 0, m_trans_sampling_index, m_settings); } base = base->next; @@ -509,7 +439,7 @@ void AbcExporter::createTransformWriter(Object *ob, Object *parent, Object *dupl m_xforms[name]->setParent(parent); } else { - m_xforms[name] = new AbcTransformWriter(ob, m_archive.getTop(), NULL, m_trans_sampling_index, m_settings); + m_xforms[name] = new AbcTransformWriter(ob, m_writer->archive().getTop(), NULL, m_trans_sampling_index, m_settings); } } diff --git a/source/blender/alembic/intern/abc_exporter.h b/source/blender/alembic/intern/abc_exporter.h index 6c242f973c4..b0eb8e185d6 100644 --- a/source/blender/alembic/intern/abc_exporter.h +++ b/source/blender/alembic/intern/abc_exporter.h @@ -24,13 +24,13 @@ #define __ABC_EXPORTER_H__ #include <Alembic/Abc/All.h> -#include <fstream> #include <map> #include <set> #include <vector> class AbcObjectWriter; class AbcTransformWriter; +class ArchiveWriter; struct EvaluationContext; struct Main; @@ -66,6 +66,10 @@ struct ExportSettings { bool export_child_hairs; bool export_ogawa; bool pack_uv; + bool triangulate; + + int quad_method; + int ngon_method; bool do_convert_axis; float convert_matrix[3][3]; @@ -76,12 +80,12 @@ 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; Scene *m_scene; + ArchiveWriter *m_writer; + std::map<std::string, AbcTransformWriter *> m_xforms; std::vector<AbcObjectWriter *> m_shapes; diff --git a/source/blender/alembic/intern/abc_hair.cc b/source/blender/alembic/intern/abc_hair.cc index 45bf9b7ab8a..14bcf6731ea 100644 --- a/source/blender/alembic/intern/abc_hair.cc +++ b/source/blender/alembic/intern/abc_hair.cc @@ -59,7 +59,7 @@ AbcHairWriter::AbcHairWriter(Scene *scene, { m_psys = psys; - OCurves curves(parent->alembicXform(), m_name, m_time_sampling); + OCurves curves(parent->alembicXform(), psys->name, m_time_sampling); m_schema = curves.getSchema(); } diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc index b80b7c0c4c8..18b5dd9d1e0 100644 --- a/source/blender/alembic/intern/abc_mesh.cc +++ b/source/blender/alembic/intern/abc_mesh.cc @@ -37,8 +37,8 @@ extern "C" { #include "BLI_math_geom.h" #include "BLI_string.h" +#include "BKE_cdderivedmesh.h" #include "BKE_depsgraph.h" -#include "BKE_DerivedMesh.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_mesh.h" @@ -49,6 +49,9 @@ extern "C" { #include "WM_types.h" #include "ED_mesh.h" + +#include "bmesh.h" +#include "bmesh_tools.h" } using Alembic::Abc::FloatArraySample; @@ -538,6 +541,23 @@ DerivedMesh *AbcMeshWriter::getFinalMesh() m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary; } + if (m_settings.triangulate) { + const bool tag_only = false; + const int quad_method = m_settings.quad_method; + const int ngon_method = m_settings.ngon_method; + + BMesh *bm = DM_to_bmesh(dm, true); + + BM_mesh_triangulate(bm, quad_method, ngon_method, tag_only, NULL, NULL, NULL); + + DerivedMesh *result = CDDM_from_bmesh(bm, false); + BM_mesh_free(bm); + + freeMesh(dm); + + dm = result; + } + m_custom_data_config.pack_uvs = m_settings.pack_uv; m_custom_data_config.mpoly = dm->getPolyArray(dm); m_custom_data_config.mloop = dm->getLoopArray(dm); @@ -784,6 +804,7 @@ struct AbcMeshData { Int32ArraySamplePtr face_counts; P3fArraySamplePtr positions; + P3fArraySamplePtr ceil_positions; N3fArraySamplePtr vertex_normals; N3fArraySamplePtr face_normals; @@ -831,12 +852,32 @@ CDStreamConfig create_config(Mesh *mesh) return config; } +static void read_mverts_interp(MVert *mverts, const P3fArraySamplePtr &positions, const P3fArraySamplePtr &ceil_positions, const float weight) +{ + float tmp[3]; + for (int i = 0; i < positions->size(); ++i) { + MVert &mvert = mverts[i]; + const Imath::V3f &floor_pos = (*positions)[i]; + const Imath::V3f &ceil_pos = (*ceil_positions)[i]; + + interp_v3_v3v3(tmp, floor_pos.getValue(), ceil_pos.getValue(), weight); + copy_yup_zup(mvert.co, tmp); + + mvert.bweight = 0; + } +} + static void read_mverts(CDStreamConfig &config, const AbcMeshData &mesh_data) { MVert *mverts = config.mvert; const P3fArraySamplePtr &positions = mesh_data.positions; const N3fArraySamplePtr &normals = mesh_data.vertex_normals; + if (config.weight != 0.0f && mesh_data.ceil_positions) { + read_mverts_interp(mverts, positions, mesh_data.ceil_positions, config.weight); + return; + } + read_mverts(mverts, positions, normals); } @@ -1063,6 +1104,46 @@ void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, size_t poly_star utils::assign_materials(bmain, m_object, mat_map); } +typedef std::pair<Alembic::AbcCoreAbstract::index_t, float> index_time_pair_t; + +static void get_weight_and_index(CDStreamConfig &config, + Alembic::AbcCoreAbstract::TimeSamplingPtr time_sampling, + size_t samples_number) +{ + if (samples_number == 0) { + samples_number = 1; + } + + index_time_pair_t floor_index = time_sampling->getFloorIndex(config.time, samples_number); + + config.index = floor_index.first; + config.ceil_index = config.index; + + if (fabs(config.time - floor_index.second) < 0.0001f) { + config.weight = 0.0f; + return; + } + + index_time_pair_t ceil_index = time_sampling->getCeilIndex(config.time, samples_number); + + if (config.index == ceil_index.first) { + config.weight = 0.0f; + return; + } + + config.ceil_index = ceil_index.first; + + float alpha = (config.time - floor_index.second) / (ceil_index.second - floor_index.second); + + /* Since we so closely match the ceiling, we'll just use it. */ + if (fabs(1.0f - alpha) < 0.0001f) { + config.index = config.ceil_index; + alpha = 0.0f; + } + + config.weight = alpha; +} + void read_mesh_sample(ImportSettings *settings, const IPolyMeshSchema &schema, const ISampleSelector &selector, @@ -1080,6 +1161,14 @@ void read_mesh_sample(ImportSettings *settings, do_normals = (abc_mesh_data.face_normals != NULL); + get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples()); + + if (config.weight != 0.0f) { + Alembic::AbcGeom::IPolyMeshSchema::Sample ceil_sample; + schema.get(ceil_sample, Alembic::Abc::ISampleSelector(static_cast<Alembic::AbcCoreAbstract::index_t>(config.ceil_index))); + abc_mesh_data.ceil_positions = ceil_sample.getPositions(); + } + if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) { read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector); } @@ -1195,6 +1284,14 @@ void read_subd_sample(ImportSettings *settings, abc_mesh_data.face_normals = N3fArraySamplePtr(); abc_mesh_data.positions = sample.getPositions(); + get_weight_and_index(config, schema.getTimeSampling(), schema.getNumSamples()); + + if (config.weight != 0.0f) { + Alembic::AbcGeom::ISubDSchema::Sample ceil_sample; + schema.get(ceil_sample, Alembic::Abc::ISampleSelector(static_cast<Alembic::AbcCoreAbstract::index_t>(config.ceil_index))); + abc_mesh_data.ceil_positions = ceil_sample.getPositions(); + } + if ((settings->read_flag & MOD_MESHSEQ_READ_UV) != 0) { read_uvs_params(config, abc_mesh_data, schema.getUVsParam(), selector); } diff --git a/source/blender/alembic/intern/abc_points.cc b/source/blender/alembic/intern/abc_points.cc index 322bb906bf5..03014547416 100644 --- a/source/blender/alembic/intern/abc_points.cc +++ b/source/blender/alembic/intern/abc_points.cc @@ -67,7 +67,7 @@ AbcPointsWriter::AbcPointsWriter(Scene *scene, { m_psys = psys; - OPoints points(parent->alembicXform(), m_name, m_time_sampling); + OPoints points(parent->alembicXform(), psys->name, m_time_sampling); m_schema = points.getSchema(); } diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index d057cc341f6..3cc549350ea 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -22,19 +22,9 @@ #include "../ABC_alembic.h" -#ifdef WITH_ALEMBIC_HDF5 -# include <Alembic/AbcCoreHDF5/All.h> -#endif - -#include <Alembic/AbcCoreOgawa/All.h> #include <Alembic/AbcMaterial/IMaterial.h> -#include <fstream> - -#ifdef WIN32 -# include "utfconv.h" -#endif - +#include "abc_archive.h" #include "abc_camera.h" #include "abc_curves.h" #include "abc_hair.h" @@ -83,13 +73,10 @@ extern "C" { using Alembic::Abc::Int32ArraySamplePtr; using Alembic::Abc::ObjectHeader; -using Alembic::AbcGeom::ErrorHandler; -using Alembic::AbcGeom::Exception; using Alembic::AbcGeom::MetaData; using Alembic::AbcGeom::P3fArraySamplePtr; using Alembic::AbcGeom::kWrapExisting; -using Alembic::AbcGeom::IArchive; using Alembic::AbcGeom::ICamera; using Alembic::AbcGeom::ICurves; using Alembic::AbcGeom::ICurvesSchema; @@ -115,95 +102,16 @@ using Alembic::AbcGeom::V3fArraySamplePtr; using Alembic::AbcMaterial::IMaterial; -static IArchive open_archive(const std::string &filename, - const std::vector<std::istream *> &input_streams, - bool &is_hdf5) -{ - try { - 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 { - 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 IArchive(); - } -#else - return IArchive(); -#endif - } - - 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) +ABC_INLINE ArchiveReader *archive_from_handle(AbcArchiveHandle *handle) { - return reinterpret_cast<ArchiveWrapper *>(handle); + return reinterpret_cast<ArchiveReader *>(handle); } -ABC_INLINE AbcArchiveHandle *handle_from_archive(ArchiveWrapper *archive) +ABC_INLINE AbcArchiveHandle *handle_from_archive(ArchiveReader *archive) { return reinterpret_cast<AbcArchiveHandle *>(archive); } @@ -301,7 +209,7 @@ static void gather_objects_paths(const IObject &object, ListBase *object_paths) AbcArchiveHandle *ABC_create_handle(const char *filename, ListBase *object_paths) { - ArchiveWrapper *archive = new ArchiveWrapper(filename); + ArchiveReader *archive = new ArchiveReader(filename); if (!archive->valid()) { delete archive; @@ -443,6 +351,9 @@ void ABC_export( job->settings.export_ogawa = (params->compression_type == ABC_ARCHIVE_OGAWA); job->settings.pack_uv = params->packuv; job->settings.global_scale = params->global_scale; + job->settings.triangulate = params->triangulate; + job->settings.quad_method = params->quad_method; + job->settings.ngon_method = params->ngon_method; if (job->settings.frame_start > job->settings.frame_end) { std::swap(job->settings.frame_start, job->settings.frame_end); @@ -599,10 +510,6 @@ struct ImportJobData { ABC_INLINE bool is_mesh_and_strands(const IObject &object) { - if (object.getNumChildren() != 2) { - return false; - } - bool has_mesh = false; bool has_curve = false; @@ -624,6 +531,9 @@ ABC_INLINE bool is_mesh_and_strands(const IObject &object) else if (ICurves::matches(md)) { has_curve = true; } + else if (IPoints::matches(md)) { + has_curve = true; + } } return has_mesh && has_curve; @@ -637,7 +547,7 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa data->do_update = do_update; data->progress = progress; - ArchiveWrapper *archive = new ArchiveWrapper(data->filename); + ArchiveReader *archive = new ArchiveReader(data->filename); if (!archive->valid()) { delete archive; @@ -865,7 +775,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) { - ArchiveWrapper *archive = archive_from_handle(handle); + ArchiveReader *archive = archive_from_handle(handle); if (!archive || !archive->valid()) { return; @@ -988,6 +898,7 @@ static DerivedMesh *read_mesh_sample(DerivedMesh *dm, const IObject &iobject, co } CDStreamConfig config = get_config(new_dm ? new_dm : dm); + config.time = time; bool do_normals = false; read_mesh_sample(&settings, schema, sample_sel, config, do_normals); @@ -1042,6 +953,7 @@ static DerivedMesh *read_subd_sample(DerivedMesh *dm, const IObject &iobject, co /* Only read point data when streaming meshes, unless we need to create new ones. */ CDStreamConfig config = get_config(new_dm ? new_dm : dm); + config.time = time; read_subd_sample(&settings, schema, sample_sel, config); if (new_dm) { @@ -1141,7 +1053,7 @@ DerivedMesh *ABC_read_mesh(AbcArchiveHandle *handle, const char **err_str, int read_flag) { - ArchiveWrapper *archive = archive_from_handle(handle); + ArchiveReader *archive = archive_from_handle(handle); if (!archive || !archive->valid()) { *err_str = "Invalid archive!"; |