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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/io')
-rw-r--r--source/blender/io/CMakeLists.txt2
-rw-r--r--source/blender/io/alembic/ABC_alembic.h6
-rw-r--r--source/blender/io/alembic/CMakeLists.txt52
-rw-r--r--source/blender/io/alembic/exporter/abc_archive.cc265
-rw-r--r--source/blender/io/alembic/exporter/abc_archive.h87
-rw-r--r--source/blender/io/alembic/exporter/abc_export_capi.cc220
-rw-r--r--source/blender/io/alembic/exporter/abc_hierarchy_iterator.cc261
-rw-r--r--source/blender/io/alembic/exporter/abc_hierarchy_iterator.h90
-rw-r--r--source/blender/io/alembic/exporter/abc_subdiv_disabler.cc107
-rw-r--r--source/blender/io/alembic/exporter/abc_subdiv_disabler.h55
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_abstract.cc101
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_abstract.h77
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_camera.cc110
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_camera.h52
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_curves.cc (renamed from source/blender/io/alembic/intern/abc_writer_curves.cc)89
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_curves.h (renamed from source/blender/io/alembic/intern/abc_writer_curves.h)44
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_hair.cc (renamed from source/blender/io/alembic/intern/abc_writer_hair.cc)125
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_hair.h (renamed from source/blender/io/alembic/intern/abc_writer_hair.h)48
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_mball.cc90
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_mball.h (renamed from source/blender/io/alembic/intern/abc_writer_camera.h)36
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_mesh.cc (renamed from source/blender/io/alembic/intern/abc_writer_mesh.cc)588
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_mesh.h95
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_nurbs.cc (renamed from source/blender/io/alembic/intern/abc_writer_nurbs.cc)96
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_nurbs.h57
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_points.cc148
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_points.h (renamed from source/blender/io/alembic/intern/abc_writer_archive.h)38
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_transform.cc115
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_transform.h (renamed from source/blender/io/alembic/intern/abc_writer_nurbs.h)35
-rw-r--r--source/blender/io/alembic/intern/abc_axis_conversion.cc15
-rw-r--r--source/blender/io/alembic/intern/abc_axis_conversion.h22
-rw-r--r--source/blender/io/alembic/intern/abc_customdata.cc7
-rw-r--r--source/blender/io/alembic/intern/abc_customdata.h11
-rw-r--r--source/blender/io/alembic/intern/abc_exporter.cc673
-rw-r--r--source/blender/io/alembic/intern/abc_exporter.h127
-rw-r--r--source/blender/io/alembic/intern/abc_reader_archive.cc8
-rw-r--r--source/blender/io/alembic/intern/abc_reader_archive.h12
-rw-r--r--source/blender/io/alembic/intern/abc_reader_camera.cc8
-rw-r--r--source/blender/io/alembic/intern/abc_reader_camera.h12
-rw-r--r--source/blender/io/alembic/intern/abc_reader_curves.cc8
-rw-r--r--source/blender/io/alembic/intern/abc_reader_curves.h12
-rw-r--r--source/blender/io/alembic/intern/abc_reader_mesh.cc13
-rw-r--r--source/blender/io/alembic/intern/abc_reader_mesh.h12
-rw-r--r--source/blender/io/alembic/intern/abc_reader_nurbs.cc8
-rw-r--r--source/blender/io/alembic/intern/abc_reader_nurbs.h12
-rw-r--r--source/blender/io/alembic/intern/abc_reader_object.cc8
-rw-r--r--source/blender/io/alembic/intern/abc_reader_object.h12
-rw-r--r--source/blender/io/alembic/intern/abc_reader_points.cc8
-rw-r--r--source/blender/io/alembic/intern/abc_reader_points.h12
-rw-r--r--source/blender/io/alembic/intern/abc_reader_transform.cc8
-rw-r--r--source/blender/io/alembic/intern/abc_reader_transform.h12
-rw-r--r--source/blender/io/alembic/intern/abc_util.cc22
-rw-r--r--source/blender/io/alembic/intern/abc_util.h25
-rw-r--r--source/blender/io/alembic/intern/abc_writer_archive.cc98
-rw-r--r--source/blender/io/alembic/intern/abc_writer_camera.cc79
-rw-r--r--source/blender/io/alembic/intern/abc_writer_mball.cc95
-rw-r--r--source/blender/io/alembic/intern/abc_writer_mball.h56
-rw-r--r--source/blender/io/alembic/intern/abc_writer_mesh.h91
-rw-r--r--source/blender/io/alembic/intern/abc_writer_object.cc77
-rw-r--r--source/blender/io/alembic/intern/abc_writer_object.h69
-rw-r--r--source/blender/io/alembic/intern/abc_writer_points.cc121
-rw-r--r--source/blender/io/alembic/intern/abc_writer_points.h49
-rw-r--r--source/blender/io/alembic/intern/abc_writer_transform.cc119
-rw-r--r--source/blender/io/alembic/intern/abc_writer_transform.h60
-rw-r--r--source/blender/io/alembic/intern/alembic_capi.cc234
-rw-r--r--source/blender/io/collada/AnimationImporter.cpp6
-rw-r--r--source/blender/io/collada/BCMath.cpp2
-rw-r--r--source/blender/io/collada/ImageExporter.cpp4
-rw-r--r--source/blender/io/common/CMakeLists.txt45
-rw-r--r--source/blender/io/common/IO_abstract_hierarchy_iterator.h (renamed from source/blender/io/usd/intern/abstract_hierarchy_iterator.h)80
-rw-r--r--source/blender/io/common/intern/abstract_hierarchy_iterator.cc (renamed from source/blender/io/usd/intern/abstract_hierarchy_iterator.cc)123
-rw-r--r--source/blender/io/usd/CMakeLists.txt10
-rw-r--r--source/blender/io/usd/intern/usd_capi.cc22
-rw-r--r--source/blender/io/usd/intern/usd_exporter_context.h8
-rw-r--r--source/blender/io/usd/intern/usd_hierarchy_iterator.cc8
-rw-r--r--source/blender/io/usd/intern/usd_hierarchy_iterator.h14
-rw-r--r--source/blender/io/usd/intern/usd_writer_abstract.cc8
-rw-r--r--source/blender/io/usd/intern/usd_writer_abstract.h13
-rw-r--r--source/blender/io/usd/intern/usd_writer_camera.cc8
-rw-r--r--source/blender/io/usd/intern/usd_writer_camera.h8
-rw-r--r--source/blender/io/usd/intern/usd_writer_hair.cc8
-rw-r--r--source/blender/io/usd/intern/usd_writer_hair.h8
-rw-r--r--source/blender/io/usd/intern/usd_writer_light.cc8
-rw-r--r--source/blender/io/usd/intern/usd_writer_light.h8
-rw-r--r--source/blender/io/usd/intern/usd_writer_mesh.cc8
-rw-r--r--source/blender/io/usd/intern/usd_writer_mesh.h8
-rw-r--r--source/blender/io/usd/intern/usd_writer_metaball.cc8
-rw-r--r--source/blender/io/usd/intern/usd_writer_metaball.h8
-rw-r--r--source/blender/io/usd/intern/usd_writer_transform.cc8
-rw-r--r--source/blender/io/usd/intern/usd_writer_transform.h8
89 files changed, 3102 insertions, 2641 deletions
diff --git a/source/blender/io/CMakeLists.txt b/source/blender/io/CMakeLists.txt
index bc2f8d628e2..360cacc4360 100644
--- a/source/blender/io/CMakeLists.txt
+++ b/source/blender/io/CMakeLists.txt
@@ -18,6 +18,8 @@
# All rights reserved.
# ***** END GPL LICENSE BLOCK *****
+add_subdirectory(common)
+
if(WITH_ALEMBIC)
add_subdirectory(alembic)
endif()
diff --git a/source/blender/io/alembic/ABC_alembic.h b/source/blender/io/alembic/ABC_alembic.h
index ba430752b29..ddf75aa3258 100644
--- a/source/blender/io/alembic/ABC_alembic.h
+++ b/source/blender/io/alembic/ABC_alembic.h
@@ -13,14 +13,12 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_ALEMBIC_H__
-#define __ABC_ALEMBIC_H__
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -133,5 +131,3 @@ struct CacheReader *CacheReader_open_alembic_object(struct AbcArchiveHandle *han
#ifdef __cplusplus
}
#endif
-
-#endif /* __ABC_ALEMBIC_H__ */
diff --git a/source/blender/io/alembic/CMakeLists.txt b/source/blender/io/alembic/CMakeLists.txt
index 16f2d944876..da36272b850 100644
--- a/source/blender/io/alembic/CMakeLists.txt
+++ b/source/blender/io/alembic/CMakeLists.txt
@@ -20,6 +20,7 @@
set(INC
.
+ ../common
../../blenkernel
../../blenlib
../../blenloader
@@ -29,6 +30,7 @@ set(INC
../../makesdna
../../makesrna
../../windowmanager
+ ../../../../intern/clog
../../../../intern/guardedalloc
../../../../intern/utfconv
)
@@ -42,7 +44,6 @@ set(INC_SYS
set(SRC
intern/abc_axis_conversion.cc
intern/abc_customdata.cc
- intern/abc_exporter.cc
intern/abc_reader_archive.cc
intern/abc_reader_camera.cc
intern/abc_reader_curves.cc
@@ -52,22 +53,25 @@ set(SRC
intern/abc_reader_points.cc
intern/abc_reader_transform.cc
intern/abc_util.cc
- intern/abc_writer_archive.cc
- intern/abc_writer_camera.cc
- intern/abc_writer_curves.cc
- intern/abc_writer_hair.cc
- intern/abc_writer_mball.cc
- intern/abc_writer_mesh.cc
- intern/abc_writer_nurbs.cc
- intern/abc_writer_object.cc
- intern/abc_writer_points.cc
- intern/abc_writer_transform.cc
intern/alembic_capi.cc
+ exporter/abc_archive.cc
+ exporter/abc_export_capi.cc
+ exporter/abc_hierarchy_iterator.cc
+ exporter/abc_subdiv_disabler.cc
+ exporter/abc_writer_abstract.cc
+ exporter/abc_writer_camera.cc
+ exporter/abc_writer_curves.cc
+ exporter/abc_writer_hair.cc
+ exporter/abc_writer_mesh.cc
+ exporter/abc_writer_mball.cc
+ exporter/abc_writer_nurbs.cc
+ exporter/abc_writer_points.cc
+ exporter/abc_writer_transform.cc
+
ABC_alembic.h
intern/abc_axis_conversion.h
intern/abc_customdata.h
- intern/abc_exporter.h
intern/abc_reader_archive.h
intern/abc_reader_camera.h
intern/abc_reader_curves.h
@@ -77,21 +81,25 @@ set(SRC
intern/abc_reader_points.h
intern/abc_reader_transform.h
intern/abc_util.h
- intern/abc_writer_archive.h
- intern/abc_writer_camera.h
- intern/abc_writer_curves.h
- intern/abc_writer_hair.h
- intern/abc_writer_mball.h
- intern/abc_writer_mesh.h
- intern/abc_writer_nurbs.h
- intern/abc_writer_object.h
- intern/abc_writer_points.h
- intern/abc_writer_transform.h
+
+ exporter/abc_archive.h
+ exporter/abc_hierarchy_iterator.h
+ exporter/abc_subdiv_disabler.h
+ exporter/abc_writer_abstract.h
+ exporter/abc_writer_camera.h
+ exporter/abc_writer_curves.h
+ exporter/abc_writer_hair.h
+ exporter/abc_writer_mesh.h
+ exporter/abc_writer_mball.h
+ exporter/abc_writer_nurbs.h
+ exporter/abc_writer_points.h
+ exporter/abc_writer_transform.h
)
set(LIB
bf_blenkernel
bf_blenlib
+ bf_io_common
${ALEMBIC_LIBRARIES}
${OPENEXR_LIBRARIES}
diff --git a/source/blender/io/alembic/exporter/abc_archive.cc b/source/blender/io/alembic/exporter/abc_archive.cc
new file mode 100644
index 00000000000..5fbf74f0705
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_archive.cc
@@ -0,0 +1,265 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+#include "abc_archive.h"
+
+#include "BKE_blender_version.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "DNA_scene_types.h"
+
+#include <Alembic/AbcCoreOgawa/All.h>
+#include <Alembic/AbcGeom/All.h>
+
+#ifdef WIN32
+# include "BLI_path_util.h"
+# include "BLI_string.h"
+
+# include "utfconv.h"
+#endif
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+using Alembic::Abc::ErrorHandler;
+using Alembic::Abc::kWrapExisting;
+using Alembic::Abc::MetaData;
+using Alembic::Abc::OArchive;
+using Alembic::Abc::TimeSampling;
+using Alembic::Abc::TimeSamplingPtr;
+using Alembic::Abc::TimeSamplingType;
+
+static MetaData create_abc_metadata(const Main *bmain, double scene_fps)
+{
+ MetaData abc_metadata;
+
+ std::string abc_user_description(bmain->name);
+ if (abc_user_description.empty()) {
+ abc_user_description = "unknown";
+ }
+
+ abc_metadata.set(Alembic::Abc::kApplicationNameKey, "Blender");
+ abc_metadata.set(Alembic::Abc::kUserDescriptionKey, abc_user_description);
+ abc_metadata.set("blender_version", std::string("v") + BKE_blender_version_string());
+ abc_metadata.set("FramesPerTimeUnit", std::to_string(scene_fps));
+
+ 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';
+ }
+
+ abc_metadata.set(Alembic::Abc::kDateWrittenKey, buffer);
+ return abc_metadata;
+}
+
+static OArchive *create_archive(std::ofstream *abc_ostream,
+ const std::string &filename,
+ MetaData &abc_metadata)
+{
+ /* Use stream to support unicode character paths on Windows. */
+#ifdef WIN32
+ char filename_cstr[FILE_MAX];
+ BLI_strncpy(filename_cstr, filename.c_str(), FILE_MAX);
+
+ UTF16_ENCODE(filename_cstr);
+ std::wstring wstr(filename_cstr_16);
+ abc_ostream->open(wstr.c_str(), std::ios::out | std::ios::binary);
+ UTF16_UN_ENCODE(filename_cstr);
+#else
+ abc_ostream->open(filename, std::ios::out | std::ios::binary);
+#endif
+
+ ErrorHandler::Policy policy = ErrorHandler::kThrowPolicy;
+
+ Alembic::AbcCoreOgawa::WriteArchive archive_writer;
+ return new OArchive(archive_writer(abc_ostream, abc_metadata), kWrapExisting, policy);
+}
+
+/* Construct list of shutter samples.
+ *
+ * These are taken from the interval [shutter open, shutter close),
+ * uniformly sampled with 'nr_of_samples' samples.
+ *
+ * TODO(Sybren): test that the above interval is indeed half-open.
+ *
+ * If 'time_relative' is true, samples are returned as time (in seconds) from params.frame_start.
+ * If 'time_relative' is false, samples are returned as fractional frames from 0.
+ * */
+static void get_shutter_samples(double scene_fps,
+ const AlembicExportParams &params,
+ int nr_of_samples,
+ bool time_relative,
+ std::vector<double> &r_samples)
+{
+ int frame_offset = time_relative ? params.frame_start : 0;
+ double time_factor = time_relative ? scene_fps : 1.0;
+ double shutter_open = params.shutter_open;
+ double shutter_close = params.shutter_close;
+ double time_inc = (shutter_close - shutter_open) / nr_of_samples;
+
+ /* sample between shutter open & close */
+ for (int sample = 0; sample < nr_of_samples; sample++) {
+ double sample_time = shutter_open + time_inc * sample;
+ double time = (frame_offset + sample_time) / time_factor;
+
+ r_samples.push_back(time);
+ }
+}
+
+static TimeSamplingPtr create_time_sampling(double scene_fps,
+ const AlembicExportParams &params,
+ int nr_of_samples)
+{
+ std::vector<double> samples;
+
+ if (params.frame_start == params.frame_end) {
+ return TimeSamplingPtr(new TimeSampling());
+ }
+
+ get_shutter_samples(scene_fps, params, nr_of_samples, true, samples);
+
+ TimeSamplingType ts(static_cast<uint32_t>(samples.size()), 1.0 / scene_fps);
+ return TimeSamplingPtr(new TimeSampling(ts, samples));
+}
+
+static void get_frames(double scene_fps,
+ const AlembicExportParams &params,
+ unsigned int nr_of_samples,
+ std::set<double> &r_frames)
+{
+ /* Get one set of shutter samples, then add those around each frame to export. */
+ std::vector<double> shutter_samples;
+ get_shutter_samples(scene_fps, params, nr_of_samples, false, shutter_samples);
+
+ for (double frame = params.frame_start; frame <= params.frame_end; frame += 1.0) {
+ for (size_t j = 0; j < nr_of_samples; j++) {
+ r_frames.insert(frame + shutter_samples[j]);
+ }
+ }
+}
+
+/* ****************************************************************** */
+
+ABCArchive::ABCArchive(const Main *bmain,
+ const Scene *scene,
+ AlembicExportParams params,
+ std::string filename)
+ : archive(nullptr)
+{
+ double scene_fps = FPS;
+ MetaData abc_metadata = create_abc_metadata(bmain, scene_fps);
+
+ // Create the Archive.
+ archive = create_archive(&abc_ostream_, filename, abc_metadata);
+
+ // Create time samples for transforms and shapes.
+ TimeSamplingPtr ts_xform;
+ TimeSamplingPtr ts_shapes;
+
+ ts_xform = create_time_sampling(scene_fps, params, params.frame_samples_xform);
+ time_sampling_index_transforms_ = archive->addTimeSampling(*ts_xform);
+
+ const bool export_animation = params.frame_start != params.frame_end;
+ if (!export_animation || params.frame_samples_shape == params.frame_samples_xform) {
+ ts_shapes = ts_xform;
+ time_sampling_index_shapes_ = time_sampling_index_transforms_;
+ }
+ else {
+ ts_shapes = create_time_sampling(scene_fps, params, params.frame_samples_shape);
+ time_sampling_index_shapes_ = archive->addTimeSampling(*ts_shapes);
+ }
+
+ // Construct the frames to export.
+ get_frames(scene_fps, params, params.frame_samples_xform, xform_frames_);
+ get_frames(scene_fps, params, params.frame_samples_shape, shape_frames_);
+
+ // Merge all frames to get the final set of frames to export.
+ export_frames_.insert(xform_frames_.begin(), xform_frames_.end());
+ export_frames_.insert(shape_frames_.begin(), shape_frames_.end());
+
+ abc_archive_bbox_ = Alembic::AbcGeom::CreateOArchiveBounds(*archive,
+ time_sampling_index_transforms_);
+}
+
+ABCArchive::~ABCArchive()
+{
+ delete archive;
+}
+
+uint32_t ABCArchive::time_sampling_index_transforms() const
+{
+ return time_sampling_index_transforms_;
+}
+
+uint32_t ABCArchive::time_sampling_index_shapes() const
+{
+ return time_sampling_index_shapes_;
+}
+
+ABCArchive::Frames::const_iterator ABCArchive::frames_begin() const
+{
+ return export_frames_.begin();
+}
+ABCArchive::Frames::const_iterator ABCArchive::frames_end() const
+{
+ return export_frames_.end();
+}
+size_t ABCArchive::total_frame_count() const
+{
+ return export_frames_.size();
+}
+
+bool ABCArchive::is_xform_frame(double frame) const
+{
+ return xform_frames_.find(frame) != xform_frames_.end();
+}
+bool ABCArchive::is_shape_frame(double frame) const
+{
+ return shape_frames_.find(frame) != shape_frames_.end();
+}
+ExportSubset ABCArchive::export_subset_for_frame(double frame) const
+{
+ ExportSubset subset;
+ subset.transforms = is_xform_frame(frame);
+ subset.shapes = is_shape_frame(frame);
+ return subset;
+}
+
+void ABCArchive::update_bounding_box(const Imath::Box3d &bounds)
+{
+ abc_archive_bbox_.set(bounds);
+}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/exporter/abc_archive.h b/source/blender/io/alembic/exporter/abc_archive.h
new file mode 100644
index 00000000000..43d0acf2520
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_archive.h
@@ -0,0 +1,87 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup Alembic
+ */
+
+#pragma once
+
+#include "ABC_alembic.h"
+#include "IO_abstract_hierarchy_iterator.h"
+
+#include <Alembic/Abc/OArchive.h>
+#include <Alembic/Abc/OTypedScalarProperty.h>
+
+#include <fstream>
+#include <set>
+#include <string>
+
+struct Main;
+struct Scene;
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+/* Container for an Alembic archive and time sampling info.
+ *
+ * Constructor arguments are used to create the correct output stream and to set the archive's
+ * metadata. */
+class ABCArchive {
+ public:
+ typedef std::set<double> Frames;
+
+ Alembic::Abc::OArchive *archive;
+
+ ABCArchive(const Main *bmain,
+ const Scene *scene,
+ AlembicExportParams params,
+ std::string filename);
+ ~ABCArchive();
+
+ uint32_t time_sampling_index_transforms() const;
+ uint32_t time_sampling_index_shapes() const;
+
+ Frames::const_iterator frames_begin() const;
+ Frames::const_iterator frames_end() const;
+ size_t total_frame_count() const;
+
+ bool is_xform_frame(double frame) const;
+ bool is_shape_frame(double frame) const;
+
+ ExportSubset export_subset_for_frame(double frame) const;
+
+ void update_bounding_box(const Imath::Box3d &bounds);
+
+ private:
+ std::ofstream abc_ostream_;
+ uint32_t time_sampling_index_transforms_;
+ uint32_t time_sampling_index_shapes_;
+
+ Frames xform_frames_;
+ Frames shape_frames_;
+ Frames export_frames_;
+
+ Alembic::Abc::OBox3dProperty abc_archive_bbox_;
+};
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/exporter/abc_export_capi.cc b/source/blender/io/alembic/exporter/abc_export_capi.cc
new file mode 100644
index 00000000000..fbc5b2d5c02
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_export_capi.cc
@@ -0,0 +1,220 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+#include "ABC_alembic.h"
+#include "abc_archive.h"
+#include "abc_hierarchy_iterator.h"
+#include "abc_subdiv_disabler.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
+
+#include "DNA_modifier_types.h"
+#include "DNA_scene_types.h"
+
+#include "BKE_blender_version.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "BLI_fileops.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "CLG_log.h"
+static CLG_LogRef LOG = {"io.alembic"};
+
+#include <algorithm>
+
+struct ExportJobData {
+ Main *bmain;
+ Depsgraph *depsgraph;
+ wmWindowManager *wm;
+
+ char filename[FILE_MAX];
+ AlembicExportParams params;
+
+ bool was_canceled;
+ bool export_ok;
+};
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+// Construct the depsgraph for exporting.
+static void build_depsgraph(Depsgraph *depsgraph, Main *bmain)
+{
+ Scene *scene = DEG_get_input_scene(depsgraph);
+ ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
+ DEG_graph_build_from_view_layer(depsgraph, bmain, scene, view_layer);
+}
+
+static void export_startjob(void *customdata, short *stop, short *do_update, float *progress)
+{
+ ExportJobData *data = static_cast<ExportJobData *>(customdata);
+ data->was_canceled = false;
+
+ G.is_rendering = true;
+ WM_set_locked_interface(data->wm, true);
+ G.is_break = false;
+
+ *progress = 0.0f;
+ *do_update = true;
+
+ build_depsgraph(data->depsgraph, data->bmain);
+ SubdivModifierDisabler subdiv_disabler(data->depsgraph);
+ if (!data->params.apply_subdiv) {
+ subdiv_disabler.disable_modifiers();
+ }
+ BKE_scene_graph_update_tagged(data->depsgraph, data->bmain);
+
+ // For restoring the current frame after exporting animation is done.
+ Scene *scene = DEG_get_input_scene(data->depsgraph);
+ const int orig_frame = CFRA;
+ const bool export_animation = (data->params.frame_start != data->params.frame_end);
+
+ // Create the Alembic archive.
+ ABCArchive abc_archive(data->bmain, scene, data->params, std::string(data->filename));
+
+ ABCHierarchyIterator iter(data->depsgraph, &abc_archive, data->params);
+
+ if (export_animation) {
+ CLOG_INFO(&LOG, 2, "Exporting animation");
+
+ // Writing the animated frames is not 100% of the work, but it's our best guess.
+ const float progress_per_frame = 1.0f / std::max(size_t(1), abc_archive.total_frame_count());
+ ABCArchive::Frames::const_iterator frame_it = abc_archive.frames_begin();
+ const ABCArchive::Frames::const_iterator frames_end = abc_archive.frames_end();
+
+ for (; frame_it != frames_end; frame_it++) {
+ double frame = *frame_it;
+
+ if (G.is_break || (stop != nullptr && *stop)) {
+ break;
+ }
+
+ // Update the scene for the next frame to render.
+ scene->r.cfra = static_cast<int>(frame);
+ scene->r.subframe = frame - scene->r.cfra;
+ BKE_scene_graph_update_for_newframe(data->depsgraph, data->bmain);
+
+ CLOG_INFO(&LOG, 2, "Exporting frame %.2f", frame);
+ ExportSubset export_subset = abc_archive.export_subset_for_frame(frame);
+ iter.set_export_subset(export_subset);
+ iter.iterate_and_write();
+
+ *progress += progress_per_frame;
+ *do_update = true;
+ }
+ }
+ else {
+ // If we're not animating, a single iteration over all objects is enough.
+ iter.iterate_and_write();
+ }
+
+ iter.release_writers();
+
+ // Finish up by going back to the keyframe that was current before we started.
+ if (CFRA != orig_frame) {
+ CFRA = orig_frame;
+ BKE_scene_graph_update_for_newframe(data->depsgraph, data->bmain);
+ }
+
+ data->export_ok = !data->was_canceled;
+
+ *progress = 1.0f;
+ *do_update = true;
+}
+
+static void export_endjob(void *customdata)
+{
+ ExportJobData *data = static_cast<ExportJobData *>(customdata);
+
+ DEG_graph_free(data->depsgraph);
+
+ if (data->was_canceled && BLI_exists(data->filename)) {
+ BLI_delete(data->filename, false, false);
+ }
+
+ G.is_rendering = false;
+ WM_set_locked_interface(data->wm, false);
+}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
+
+bool ABC_export(Scene *scene,
+ bContext *C,
+ const char *filepath,
+ const AlembicExportParams *params,
+ bool as_background_job)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ ExportJobData *job = static_cast<ExportJobData *>(
+ MEM_mallocN(sizeof(ExportJobData), "ExportJobData"));
+
+ job->bmain = CTX_data_main(C);
+ job->wm = CTX_wm_manager(C);
+ job->export_ok = false;
+ BLI_strncpy(job->filename, filepath, sizeof(job->filename));
+
+ job->depsgraph = DEG_graph_new(
+ job->bmain, scene, view_layer, DAG_EVAL_RENDER /* TODO(Sybren): params->evaluation_mode */);
+ job->params = *params;
+
+ bool export_ok = false;
+ if (as_background_job) {
+ wmJob *wm_job = WM_jobs_get(
+ job->wm, CTX_wm_window(C), scene, "Alembic Export", WM_JOB_PROGRESS, WM_JOB_TYPE_ALEMBIC);
+
+ /* setup job */
+ WM_jobs_customdata_set(wm_job, job, MEM_freeN);
+ WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME);
+ WM_jobs_callbacks(wm_job,
+ blender::io::alembic::export_startjob,
+ NULL,
+ NULL,
+ blender::io::alembic::export_endjob);
+
+ WM_jobs_start(CTX_wm_manager(C), wm_job);
+ }
+ else {
+ /* Fake a job context, so that we don't need NULL pointer checks while exporting. */
+ short stop = 0, do_update = 0;
+ float progress = 0.f;
+
+ blender::io::alembic::export_startjob(job, &stop, &do_update, &progress);
+ blender::io::alembic::export_endjob(job);
+ export_ok = job->export_ok;
+
+ MEM_freeN(job);
+ }
+
+ return export_ok;
+}
diff --git a/source/blender/io/alembic/exporter/abc_hierarchy_iterator.cc b/source/blender/io/alembic/exporter/abc_hierarchy_iterator.cc
new file mode 100644
index 00000000000..90004c0e85b
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_hierarchy_iterator.cc
@@ -0,0 +1,261 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+
+#include "abc_hierarchy_iterator.h"
+#include "abc_writer_abstract.h"
+#include "abc_writer_camera.h"
+#include "abc_writer_curves.h"
+#include "abc_writer_hair.h"
+#include "abc_writer_mball.h"
+#include "abc_writer_mesh.h"
+#include "abc_writer_nurbs.h"
+#include "abc_writer_points.h"
+#include "abc_writer_transform.h"
+
+#include <memory>
+#include <string>
+
+#include "BLI_assert.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "DNA_ID.h"
+#include "DNA_layer_types.h"
+#include "DNA_object_types.h"
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+ABCHierarchyIterator::ABCHierarchyIterator(Depsgraph *depsgraph,
+ ABCArchive *abc_archive,
+ const AlembicExportParams &params)
+ : AbstractHierarchyIterator(depsgraph), abc_archive_(abc_archive), params_(params)
+{
+}
+
+void ABCHierarchyIterator::iterate_and_write()
+{
+ AbstractHierarchyIterator::iterate_and_write();
+ update_archive_bounding_box();
+}
+
+void ABCHierarchyIterator::update_archive_bounding_box()
+{
+ Imath::Box3d bounds;
+ update_bounding_box_recursive(bounds, HierarchyContext::root());
+ abc_archive_->update_bounding_box(bounds);
+}
+
+void ABCHierarchyIterator::update_bounding_box_recursive(Imath::Box3d &bounds,
+ const HierarchyContext *context)
+{
+ if (context != nullptr) {
+ AbstractHierarchyWriter *abstract_writer = writers_[context->export_path];
+ ABCAbstractWriter *abc_writer = static_cast<ABCAbstractWriter *>(abstract_writer);
+
+ if (abc_writer != nullptr) {
+ bounds.extendBy(abc_writer->bounding_box());
+ }
+ }
+
+ for (HierarchyContext *child_context : graph_children(context)) {
+ update_bounding_box_recursive(bounds, child_context);
+ }
+}
+
+bool ABCHierarchyIterator::mark_as_weak_export(const Object *object) const
+{
+ if (params_.selected_only && (object->base_flag & BASE_SELECTED) == 0) {
+ return true;
+ }
+ /* TODO(Sybren): handle other flags too? */
+ return false;
+}
+
+void ABCHierarchyIterator::delete_object_writer(AbstractHierarchyWriter *writer)
+{
+ delete writer;
+}
+
+std::string ABCHierarchyIterator::make_valid_name(const std::string &name) const
+{
+ std::string abc_name(name);
+ std::replace(abc_name.begin(), abc_name.end(), ' ', '_');
+ std::replace(abc_name.begin(), abc_name.end(), '.', '_');
+ std::replace(abc_name.begin(), abc_name.end(), ':', '_');
+ return abc_name;
+}
+
+AbstractHierarchyIterator::ExportGraph::key_type ABCHierarchyIterator::
+ determine_graph_index_object(const HierarchyContext *context)
+{
+ if (params_.flatten_hierarchy) {
+ return std::make_pair(nullptr, nullptr);
+ }
+
+ return AbstractHierarchyIterator::determine_graph_index_object(context);
+}
+
+AbstractHierarchyIterator::ExportGraph::key_type ABCHierarchyIterator::determine_graph_index_dupli(
+ const HierarchyContext *context, const std::set<Object *> &dupli_set)
+{
+ if (params_.flatten_hierarchy) {
+ return std::make_pair(nullptr, nullptr);
+ }
+
+ return AbstractHierarchyIterator::determine_graph_index_dupli(context, dupli_set);
+}
+
+Alembic::Abc::OObject ABCHierarchyIterator::get_alembic_parent(
+ const HierarchyContext *context) const
+{
+ Alembic::Abc::OObject parent;
+
+ if (!context->higher_up_export_path.empty()) {
+ AbstractHierarchyWriter *writer = get_writer(context->higher_up_export_path);
+ ABCAbstractWriter *abc_writer = static_cast<ABCAbstractWriter *>(writer);
+ parent = abc_writer->get_alembic_object();
+ }
+
+ if (!parent.valid()) {
+ /* An invalid parent object means "no parent", which should be translated to Alembic's top
+ * archive object. */
+ return abc_archive_->archive->getTop();
+ }
+
+ return parent;
+}
+
+ABCWriterConstructorArgs ABCHierarchyIterator::writer_constructor_args(
+ const HierarchyContext *context) const
+{
+ ABCWriterConstructorArgs constructor_args;
+ constructor_args.depsgraph = depsgraph_;
+ constructor_args.abc_archive = abc_archive_;
+ constructor_args.abc_parent = get_alembic_parent(context);
+ constructor_args.abc_name = context->export_name;
+ constructor_args.abc_path = context->export_path;
+ constructor_args.hierarchy_iterator = this;
+ constructor_args.export_params = &params_;
+ return constructor_args;
+}
+
+AbstractHierarchyWriter *ABCHierarchyIterator::create_transform_writer(
+ const HierarchyContext *context)
+{
+ ABCAbstractWriter *transform_writer = new ABCTransformWriter(writer_constructor_args(context));
+ transform_writer->create_alembic_objects(context);
+ return transform_writer;
+}
+
+AbstractHierarchyWriter *ABCHierarchyIterator::create_data_writer(const HierarchyContext *context)
+{
+ const ABCWriterConstructorArgs writer_args = writer_constructor_args(context);
+ ABCAbstractWriter *data_writer = nullptr;
+
+ switch (context->object->type) {
+ case OB_MESH:
+ data_writer = new ABCMeshWriter(writer_args);
+ break;
+ case OB_CAMERA:
+ data_writer = new ABCCameraWriter(writer_args);
+ break;
+ case OB_CURVE:
+ if (params_.curves_as_mesh) {
+ data_writer = new ABCCurveMeshWriter(writer_args);
+ }
+ else {
+ data_writer = new ABCCurveWriter(writer_args);
+ }
+ break;
+ case OB_SURF:
+ if (params_.curves_as_mesh) {
+ data_writer = new ABCCurveMeshWriter(writer_args);
+ }
+ else {
+ data_writer = new ABCNurbsWriter(writer_args);
+ }
+ break;
+ case OB_MBALL:
+ data_writer = new ABCMetaballWriter(writer_args);
+ break;
+
+ case OB_EMPTY:
+ case OB_LAMP:
+ case OB_FONT:
+ case OB_SPEAKER:
+ case OB_LIGHTPROBE:
+ case OB_LATTICE:
+ case OB_ARMATURE:
+ case OB_GPENCIL:
+ return nullptr;
+ case OB_TYPE_MAX:
+ BLI_assert(!"OB_TYPE_MAX should not be used");
+ return nullptr;
+ }
+
+ if (!data_writer->is_supported(context)) {
+ delete data_writer;
+ return nullptr;
+ }
+
+ data_writer->create_alembic_objects(context);
+ return data_writer;
+}
+
+AbstractHierarchyWriter *ABCHierarchyIterator::create_hair_writer(const HierarchyContext *context)
+{
+ if (!params_.export_hair) {
+ return nullptr;
+ }
+
+ const ABCWriterConstructorArgs writer_args = writer_constructor_args(context);
+ ABCAbstractWriter *hair_writer = new ABCHairWriter(writer_args);
+
+ if (!hair_writer->is_supported(context)) {
+ delete hair_writer;
+ return nullptr;
+ }
+
+ hair_writer->create_alembic_objects(context);
+ return hair_writer;
+}
+
+AbstractHierarchyWriter *ABCHierarchyIterator::create_particle_writer(
+ const HierarchyContext *context)
+{
+ if (!params_.export_particles) {
+ return nullptr;
+ }
+
+ const ABCWriterConstructorArgs writer_args = writer_constructor_args(context);
+ std::unique_ptr<ABCPointsWriter> particle_writer(std::make_unique<ABCPointsWriter>(writer_args));
+
+ if (!particle_writer->is_supported(context)) {
+ return nullptr;
+ }
+
+ particle_writer->create_alembic_objects(context);
+ return particle_writer.release();
+}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/exporter/abc_hierarchy_iterator.h b/source/blender/io/alembic/exporter/abc_hierarchy_iterator.h
new file mode 100644
index 00000000000..edcb31806ba
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_hierarchy_iterator.h
@@ -0,0 +1,90 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+#pragma once
+
+#include "ABC_alembic.h"
+#include "abc_archive.h"
+
+#include "IO_abstract_hierarchy_iterator.h"
+
+#include <string>
+
+#include <Alembic/Abc/OArchive.h>
+#include <Alembic/Abc/OObject.h>
+
+struct Depsgraph;
+struct ID;
+struct Object;
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+class ABCHierarchyIterator;
+
+struct ABCWriterConstructorArgs {
+ Depsgraph *depsgraph;
+ ABCArchive *abc_archive;
+ Alembic::Abc::OObject abc_parent;
+ std::string abc_name;
+ std::string abc_path;
+ const ABCHierarchyIterator *hierarchy_iterator;
+ const AlembicExportParams *export_params;
+};
+
+class ABCHierarchyIterator : public AbstractHierarchyIterator {
+ private:
+ ABCArchive *abc_archive_;
+ const AlembicExportParams &params_;
+
+ public:
+ ABCHierarchyIterator(Depsgraph *depsgraph,
+ ABCArchive *abc_archive_,
+ const AlembicExportParams &params);
+
+ virtual void iterate_and_write() override;
+ virtual std::string make_valid_name(const std::string &name) const override;
+
+ protected:
+ virtual bool mark_as_weak_export(const Object *object) const override;
+
+ virtual ExportGraph::key_type determine_graph_index_object(
+ const HierarchyContext *context) override;
+ virtual AbstractHierarchyIterator::ExportGraph::key_type determine_graph_index_dupli(
+ const HierarchyContext *context, const std::set<Object *> &dupli_set) override;
+
+ virtual AbstractHierarchyWriter *create_transform_writer(
+ const HierarchyContext *context) override;
+ virtual AbstractHierarchyWriter *create_data_writer(const HierarchyContext *context) override;
+ virtual AbstractHierarchyWriter *create_hair_writer(const HierarchyContext *context) override;
+ virtual AbstractHierarchyWriter *create_particle_writer(
+ const HierarchyContext *context) override;
+
+ virtual void delete_object_writer(AbstractHierarchyWriter *writer) override;
+
+ private:
+ Alembic::Abc::OObject get_alembic_parent(const HierarchyContext *context) const;
+ ABCWriterConstructorArgs writer_constructor_args(const HierarchyContext *context) const;
+ void update_archive_bounding_box();
+ void update_bounding_box_recursive(Imath::Box3d &bounds, const HierarchyContext *context);
+};
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/exporter/abc_subdiv_disabler.cc b/source/blender/io/alembic/exporter/abc_subdiv_disabler.cc
new file mode 100644
index 00000000000..7c147076975
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_subdiv_disabler.cc
@@ -0,0 +1,107 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+#include "abc_subdiv_disabler.h"
+
+#include <stdio.h>
+
+#include "BLI_listbase.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "DNA_layer_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_modifier.h"
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+SubdivModifierDisabler::SubdivModifierDisabler(Depsgraph *depsgraph) : depsgraph_(depsgraph)
+{
+}
+
+SubdivModifierDisabler::~SubdivModifierDisabler()
+{
+ for (ModifierData *modifier : disabled_modifiers_) {
+ modifier->mode &= ~eModifierMode_DisableTemporary;
+ }
+}
+
+void SubdivModifierDisabler::disable_modifiers()
+{
+ Scene *scene = DEG_get_input_scene(depsgraph_);
+ ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph_);
+
+ LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
+ Object *object = base->object;
+
+ if (object->type != OB_MESH) {
+ continue;
+ }
+
+ ModifierData *subdiv = get_subdiv_modifier(scene, object);
+ if (subdiv == nullptr) {
+ continue;
+ }
+
+ /* This disables more modifiers than necessary, as it doesn't take restrictions like
+ * "export selected objects only" into account. However, with the subsurfs disabled,
+ * moving to a different frame is also going to be faster, so in the end this is probably
+ * a good thing to do. */
+ subdiv->mode |= eModifierMode_DisableTemporary;
+ disabled_modifiers_.insert(subdiv);
+ DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY);
+ }
+}
+
+/* Check if the mesh is a subsurf, ignoring disabled modifiers and
+ * displace if it's after subsurf. */
+ModifierData *SubdivModifierDisabler::get_subdiv_modifier(Scene *scene, Object *ob)
+{
+ ModifierData *md = static_cast<ModifierData *>(ob->modifiers.last);
+
+ for (; md; md = md->prev) {
+ if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Render)) {
+ continue;
+ }
+
+ if (md->type == eModifierType_Subsurf) {
+ SubsurfModifierData *smd = reinterpret_cast<SubsurfModifierData *>(md);
+
+ if (smd->subdivType == ME_CC_SUBSURF) {
+ return md;
+ }
+ }
+
+ /* mesh is not a subsurf. break */
+ if ((md->type != eModifierType_Displace) && (md->type != eModifierType_ParticleSystem)) {
+ return nullptr;
+ }
+ }
+
+ return nullptr;
+}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/exporter/abc_subdiv_disabler.h b/source/blender/io/alembic/exporter/abc_subdiv_disabler.h
new file mode 100644
index 00000000000..677847f3f63
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_subdiv_disabler.h
@@ -0,0 +1,55 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+#pragma once
+
+#include <set>
+
+struct Depsgraph;
+struct ModifierData;
+struct Object;
+struct Scene;
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+/**
+ * Temporarily all subdivision modifiers on mesh objects.
+ * The destructor restores all disabled modifiers.
+ *
+ * This is used to export unsubdivided meshes to Alembic. It is done in a separate step before the
+ * exporter starts iterating over all the frames, so that it only has to happen once per export.
+ */
+class SubdivModifierDisabler final {
+ private:
+ Depsgraph *depsgraph_;
+ std::set<ModifierData *> disabled_modifiers_;
+
+ public:
+ explicit SubdivModifierDisabler(Depsgraph *depsgraph);
+ ~SubdivModifierDisabler();
+
+ void disable_modifiers();
+
+ static ModifierData *get_subdiv_modifier(Scene *scene, Object *ob);
+};
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/exporter/abc_writer_abstract.cc b/source/blender/io/alembic/exporter/abc_writer_abstract.cc
new file mode 100644
index 00000000000..e43b394e27f
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_writer_abstract.cc
@@ -0,0 +1,101 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+#include "abc_writer_abstract.h"
+#include "abc_hierarchy_iterator.h"
+
+#include "BKE_animsys.h"
+#include "BKE_key.h"
+#include "BKE_object.h"
+
+#include "DNA_modifier_types.h"
+
+#include "CLG_log.h"
+static CLG_LogRef LOG = {"io.alembic"};
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+using Alembic::Abc::OObject;
+using Alembic::Abc::TimeSamplingPtr;
+
+ABCAbstractWriter::ABCAbstractWriter(const ABCWriterConstructorArgs &args)
+ : args_(args),
+ frame_has_been_written_(false),
+ is_animated_(false),
+ timesample_index_(args_.abc_archive->time_sampling_index_shapes())
+{
+}
+
+ABCAbstractWriter::~ABCAbstractWriter()
+{
+}
+
+bool ABCAbstractWriter::is_supported(const HierarchyContext * /*context*/) const
+{
+ return true;
+}
+
+void ABCAbstractWriter::write(HierarchyContext &context)
+{
+ if (!frame_has_been_written_) {
+ is_animated_ = (args_.export_params->frame_start != args_.export_params->frame_end) &&
+ check_is_animated(context);
+ }
+ else if (!is_animated_) {
+ /* A frame has already been written, and without animation one frame is enough. */
+ return;
+ }
+
+ do_write(context);
+
+ frame_has_been_written_ = true;
+}
+
+const Imath::Box3d &ABCAbstractWriter::bounding_box() const
+{
+ return bounding_box_;
+}
+
+void ABCAbstractWriter::update_bounding_box(Object *object)
+{
+ BoundBox *bb = BKE_object_boundbox_get(object);
+
+ if (!bb) {
+ if (object->type != OB_CAMERA) {
+ CLOG_WARN(&LOG, "Bounding box is null!\n");
+ }
+ bounding_box_.min.x = bounding_box_.min.y = bounding_box_.min.z = 0;
+ bounding_box_.max.x = bounding_box_.max.y = bounding_box_.max.z = 0;
+ return;
+ }
+
+ /* Convert Z-up to Y-up. This also changes which vector goes into which min/max property. */
+ bounding_box_.min.x = bb->vec[0][0];
+ bounding_box_.min.y = bb->vec[0][2];
+ bounding_box_.min.z = -bb->vec[6][1];
+
+ bounding_box_.max.x = bb->vec[6][0];
+ bounding_box_.max.y = bb->vec[6][2];
+ bounding_box_.max.z = -bb->vec[0][1];
+}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/exporter/abc_writer_abstract.h b/source/blender/io/alembic/exporter/abc_writer_abstract.h
new file mode 100644
index 00000000000..a83373a567a
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_writer_abstract.h
@@ -0,0 +1,77 @@
+/*
+ * 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) 2020 Blender Foundation.
+ * All rights reserved.
+ */
+#pragma once
+
+#include "IO_abstract_hierarchy_iterator.h"
+#include "abc_hierarchy_iterator.h"
+
+#include <Alembic/Abc/OObject.h>
+#include <vector>
+
+#include "DEG_depsgraph_query.h"
+#include "DNA_material_types.h"
+
+struct Material;
+struct Object;
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+class ABCAbstractWriter : public AbstractHierarchyWriter {
+ protected:
+ const ABCWriterConstructorArgs args_;
+
+ bool frame_has_been_written_;
+ bool is_animated_;
+ uint32_t timesample_index_;
+ Imath::Box3d bounding_box_;
+
+ public:
+ explicit ABCAbstractWriter(const ABCWriterConstructorArgs &args);
+ virtual ~ABCAbstractWriter();
+
+ virtual void write(HierarchyContext &context) override;
+
+ /* Returns true if the data to be written is actually supported. This would, for example, allow a
+ * hypothetical camera writer accept a perspective camera but reject an orthogonal one.
+ *
+ * Returning false from a transform writer will prevent the object and all its descendants from
+ * being exported. Returning false from a data writer (object data, hair, or particles) will
+ * only prevent that data from being written (and thus cause the object to be exported as an
+ * Empty). */
+ virtual bool is_supported(const HierarchyContext *context) const;
+
+ const Imath::Box3d &bounding_box() const;
+
+ /* Called by AlembicHierarchyCreator after checking that the data is supported via
+ * is_supported(). */
+ virtual void create_alembic_objects(const HierarchyContext *context) = 0;
+
+ virtual const Alembic::Abc::OObject get_alembic_object() const = 0;
+
+ protected:
+ virtual void do_write(HierarchyContext &context) = 0;
+
+ virtual void update_bounding_box(Object *object);
+};
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/exporter/abc_writer_camera.cc b/source/blender/io/alembic/exporter/abc_writer_camera.cc
new file mode 100644
index 00000000000..7e7277cb4ea
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_writer_camera.cc
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup balembic
+ */
+
+#include "abc_writer_camera.h"
+#include "abc_hierarchy_iterator.h"
+
+#include "BKE_camera.h"
+
+#include "BLI_assert.h"
+
+#include "DNA_camera_types.h"
+#include "DNA_scene_types.h"
+
+#include "CLG_log.h"
+static CLG_LogRef LOG = {"io.alembic"};
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+using Alembic::AbcGeom::CameraSample;
+using Alembic::AbcGeom::OCamera;
+using Alembic::AbcGeom::OFloatProperty;
+
+ABCCameraWriter::ABCCameraWriter(const ABCWriterConstructorArgs &args) : ABCAbstractWriter(args)
+{
+}
+
+bool ABCCameraWriter::is_supported(const HierarchyContext *context) const
+{
+ Camera *camera = static_cast<Camera *>(context->object->data);
+ return camera->type == CAM_PERSP;
+}
+
+void ABCCameraWriter::create_alembic_objects(const HierarchyContext * /*context*/)
+{
+ CLOG_INFO(&LOG, 2, "exporting %s", args_.abc_path.c_str());
+ abc_camera_ = OCamera(args_.abc_parent, args_.abc_name, timesample_index_);
+ abc_camera_schema_ = abc_camera_.getSchema();
+
+ abc_custom_data_container_ = abc_camera_schema_.getUserProperties();
+ abc_stereo_distance_ = OFloatProperty(
+ abc_custom_data_container_, "stereoDistance", timesample_index_);
+ abc_eye_separation_ = OFloatProperty(
+ abc_custom_data_container_, "eyeSeparation", timesample_index_);
+}
+
+const Alembic::Abc::OObject ABCCameraWriter::get_alembic_object() const
+{
+ return abc_camera_;
+}
+
+void ABCCameraWriter::do_write(HierarchyContext &context)
+{
+ Camera *cam = static_cast<Camera *>(context.object->data);
+
+ abc_stereo_distance_.set(cam->stereo.convergence_distance);
+ abc_eye_separation_.set(cam->stereo.interocular_distance);
+
+ const double apperture_x = cam->sensor_x / 10.0;
+ const double apperture_y = cam->sensor_y / 10.0;
+ const double film_aspect = apperture_x / apperture_y;
+
+ CameraSample camera_sample;
+ camera_sample.setFocalLength(cam->lens);
+ camera_sample.setHorizontalAperture(apperture_x);
+ camera_sample.setVerticalAperture(apperture_y);
+ camera_sample.setHorizontalFilmOffset(apperture_x * cam->shiftx);
+ camera_sample.setVerticalFilmOffset(apperture_y * cam->shifty * film_aspect);
+ camera_sample.setNearClippingPlane(cam->clip_start);
+ camera_sample.setFarClippingPlane(cam->clip_end);
+
+ if (cam->dof.focus_object) {
+ Imath::V3f v(context.object->loc[0] - cam->dof.focus_object->loc[0],
+ context.object->loc[1] - cam->dof.focus_object->loc[1],
+ context.object->loc[2] - cam->dof.focus_object->loc[2]);
+ camera_sample.setFocusDistance(v.length());
+ }
+ else {
+ camera_sample.setFocusDistance(cam->dof.focus_distance);
+ }
+
+ /* Blender camera does not have an fstop param, so try to find a custom prop
+ * instead. */
+ camera_sample.setFStop(cam->dof.aperture_fstop);
+
+ camera_sample.setLensSqueezeRatio(1.0);
+ abc_camera_schema_.set(camera_sample);
+}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/exporter/abc_writer_camera.h b/source/blender/io/alembic/exporter/abc_writer_camera.h
new file mode 100644
index 00000000000..a72cfa2f357
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_writer_camera.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+#pragma once
+
+/** \file
+ * \ingroup balembic
+ */
+
+#include "abc_writer_abstract.h"
+
+#include <Alembic/AbcGeom/OCamera.h>
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+class ABCCameraWriter : public ABCAbstractWriter {
+ private:
+ Alembic::AbcGeom::OCamera abc_camera_;
+ Alembic::AbcGeom::OCameraSchema abc_camera_schema_;
+
+ Alembic::AbcGeom::OCompoundProperty abc_custom_data_container_;
+ Alembic::AbcGeom::OFloatProperty abc_stereo_distance_;
+ Alembic::AbcGeom::OFloatProperty abc_eye_separation_;
+
+ public:
+ explicit ABCCameraWriter(const ABCWriterConstructorArgs &args);
+
+ virtual void create_alembic_objects(const HierarchyContext *context) override;
+ virtual const Alembic::Abc::OObject get_alembic_object() const override;
+
+ protected:
+ virtual bool is_supported(const HierarchyContext *context) const override;
+ virtual void do_write(HierarchyContext &context) override;
+};
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_writer_curves.cc b/source/blender/io/alembic/exporter/abc_writer_curves.cc
index db93ac1920e..f2a46c5e4fe 100644
--- a/source/blender/io/alembic/intern/abc_writer_curves.cc
+++ b/source/blender/io/alembic/exporter/abc_writer_curves.cc
@@ -22,9 +22,7 @@
*/
#include "abc_writer_curves.h"
-#include "abc_axis_conversion.h"
-#include "abc_reader_curves.h"
-#include "abc_writer_transform.h"
+#include "intern/abc_axis_conversion.h"
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
@@ -33,6 +31,9 @@
#include "BKE_mesh.h"
#include "BKE_object.h"
+#include "CLG_log.h"
+static CLG_LogRef LOG = {"io.alembic"};
+
using Alembic::AbcGeom::OCompoundProperty;
using Alembic::AbcGeom::OCurves;
using Alembic::AbcGeom::OCurvesSchema;
@@ -40,24 +41,36 @@ using Alembic::AbcGeom::OInt16Property;
using Alembic::AbcGeom::ON3fGeomParam;
using Alembic::AbcGeom::OV2fGeomParam;
-AbcCurveWriter::AbcCurveWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings)
- : AbcObjectWriter(ob, time_sampling, settings, parent)
+namespace blender {
+namespace io {
+namespace alembic {
+
+const std::string ABC_CURVE_RESOLUTION_U_PROPNAME("blender:resolution");
+
+ABCCurveWriter::ABCCurveWriter(const ABCWriterConstructorArgs &args) : ABCAbstractWriter(args)
+{
+}
+
+void ABCCurveWriter::create_alembic_objects(const HierarchyContext *context)
{
- OCurves curves(parent->alembicXform(), m_name, m_time_sampling);
- m_schema = curves.getSchema();
+ CLOG_INFO(&LOG, 2, "exporting %s", args_.abc_path.c_str());
+ abc_curve_ = OCurves(args_.abc_parent, args_.abc_name, timesample_index_);
+ abc_curve_schema_ = abc_curve_.getSchema();
- Curve *cu = static_cast<Curve *>(m_object->data);
- OCompoundProperty user_props = m_schema.getUserProperties();
+ Curve *cu = static_cast<Curve *>(context->object->data);
+ OCompoundProperty user_props = abc_curve_schema_.getUserProperties();
OInt16Property user_prop_resolu(user_props, ABC_CURVE_RESOLUTION_U_PROPNAME);
user_prop_resolu.set(cu->resolu);
}
-void AbcCurveWriter::do_write()
+const Alembic::Abc::OObject ABCCurveWriter::get_alembic_object() const
{
- Curve *curve = static_cast<Curve *>(m_object->data);
+ return abc_curve_;
+}
+
+void ABCCurveWriter::do_write(HierarchyContext &context)
+{
+ Curve *curve = static_cast<Curve *>(context.object->data);
std::vector<Imath::V3f> verts;
std::vector<int32_t> vert_counts;
@@ -148,35 +161,31 @@ void AbcCurveWriter::do_write()
Alembic::AbcGeom::OFloatGeomParam::Sample width_sample;
width_sample.setVals(widths);
- m_sample = OCurvesSchema::Sample(verts,
- vert_counts,
- curve_type,
- periodicity,
- width_sample,
- OV2fGeomParam::Sample(), /* UVs */
- ON3fGeomParam::Sample(), /* normals */
- curve_basis,
- weights,
- orders,
- knots);
-
- m_sample.setSelfBounds(bounds());
- m_schema.set(m_sample);
+ OCurvesSchema::Sample sample(verts,
+ vert_counts,
+ curve_type,
+ periodicity,
+ width_sample,
+ OV2fGeomParam::Sample(), /* UVs */
+ ON3fGeomParam::Sample(), /* normals */
+ curve_basis,
+ weights,
+ orders,
+ knots);
+
+ update_bounding_box(context.object);
+ sample.setSelfBounds(bounding_box_);
+ abc_curve_schema_.set(sample);
}
-AbcCurveMeshWriter::AbcCurveMeshWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings)
- : AbcGenericMeshWriter(ob, parent, time_sampling, settings)
+ABCCurveMeshWriter::ABCCurveMeshWriter(const ABCWriterConstructorArgs &args)
+ : ABCGenericMeshWriter(args)
{
}
-Mesh *AbcCurveMeshWriter::getEvaluatedMesh(Scene * /*scene_eval*/,
- Object *ob_eval,
- bool &r_needsfree)
+Mesh *ABCCurveMeshWriter::get_export_mesh(Object *object_eval, bool &r_needsfree)
{
- Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
+ Mesh *mesh_eval = BKE_object_get_evaluated_mesh(object_eval);
if (mesh_eval != NULL) {
/* Mesh_eval only exists when generative modifiers are in use. */
r_needsfree = false;
@@ -184,5 +193,9 @@ Mesh *AbcCurveMeshWriter::getEvaluatedMesh(Scene * /*scene_eval*/,
}
r_needsfree = true;
- return BKE_mesh_new_nomain_from_curve(ob_eval);
+ return BKE_mesh_new_nomain_from_curve(object_eval);
}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_writer_curves.h b/source/blender/io/alembic/exporter/abc_writer_curves.h
index 83f0289dd2d..12a909761f5 100644
--- a/source/blender/io/alembic/intern/abc_writer_curves.h
+++ b/source/blender/io/alembic/exporter/abc_writer_curves.h
@@ -16,40 +16,46 @@
* The Original Code is Copyright (C) 2016 Kévin Dietrich.
* All rights reserved.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_WRITER_CURVES_H__
-#define __ABC_WRITER_CURVES_H__
-
+#include "abc_writer_abstract.h"
#include "abc_writer_mesh.h"
-#include "abc_writer_object.h"
-class AbcCurveWriter : public AbcObjectWriter {
- Alembic::AbcGeom::OCurvesSchema m_schema;
- Alembic::AbcGeom::OCurvesSchema::Sample m_sample;
+#include <Alembic/AbcGeom/OCurves.h>
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+extern const std::string ABC_CURVE_RESOLUTION_U_PROPNAME;
+
+class ABCCurveWriter : public ABCAbstractWriter {
+ private:
+ Alembic::AbcGeom::OCurves abc_curve_;
+ Alembic::AbcGeom::OCurvesSchema abc_curve_schema_;
public:
- AbcCurveWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings);
+ explicit ABCCurveWriter(const ABCWriterConstructorArgs &args);
+
+ virtual void create_alembic_objects(const HierarchyContext *context) override;
+ virtual const Alembic::Abc::OObject get_alembic_object() const override;
protected:
- void do_write();
+ virtual void do_write(HierarchyContext &context) override;
};
-class AbcCurveMeshWriter : public AbcGenericMeshWriter {
+class ABCCurveMeshWriter : public ABCGenericMeshWriter {
public:
- AbcCurveMeshWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings);
+ ABCCurveMeshWriter(const ABCWriterConstructorArgs &args);
protected:
- Mesh *getEvaluatedMesh(Scene *scene_eval, Object *ob_eval, bool &r_needsfree);
+ virtual Mesh *get_export_mesh(Object *object_eval, bool &r_needsfree) override;
};
-#endif /* __ABC_WRITER_CURVES_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_writer_hair.cc b/source/blender/io/alembic/exporter/abc_writer_hair.cc
index ed62889b03d..ac4deddd9b4 100644
--- a/source/blender/io/alembic/intern/abc_writer_hair.cc
+++ b/source/blender/io/alembic/exporter/abc_writer_hair.cc
@@ -19,8 +19,7 @@
*/
#include "abc_writer_hair.h"
-#include "abc_axis_conversion.h"
-#include "abc_writer_transform.h"
+#include "intern/abc_axis_conversion.h"
#include <cstdio>
@@ -35,35 +34,46 @@
#include "BKE_mesh_runtime.h"
#include "BKE_particle.h"
-using Alembic::Abc::P3fArraySamplePtr;
+#include "CLG_log.h"
+static CLG_LogRef LOG = {"io.alembic"};
+using Alembic::Abc::P3fArraySamplePtr;
using Alembic::AbcGeom::OCurves;
using Alembic::AbcGeom::OCurvesSchema;
using Alembic::AbcGeom::ON3fGeomParam;
using Alembic::AbcGeom::OV2fGeomParam;
-/* ************************************************************************** */
+namespace blender {
+namespace io {
+namespace alembic {
-AbcHairWriter::AbcHairWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings,
- ParticleSystem *psys)
- : AbcObjectWriter(ob, time_sampling, settings, parent), m_uv_warning_shown(false)
+ABCHairWriter::ABCHairWriter(const ABCWriterConstructorArgs &args)
+ : ABCAbstractWriter(args), uv_warning_shown_(false)
{
- m_psys = psys;
+}
- OCurves curves(parent->alembicXform(), psys->name, m_time_sampling);
- m_schema = curves.getSchema();
+void ABCHairWriter::create_alembic_objects(const HierarchyContext * /*context*/)
+{
+ CLOG_INFO(&LOG, 2, "exporting %s", args_.abc_path.c_str());
+ abc_curves_ = OCurves(args_.abc_parent, args_.abc_name, timesample_index_);
+ abc_curves_schema_ = abc_curves_.getSchema();
}
-void AbcHairWriter::do_write()
+const Alembic::Abc::OObject ABCHairWriter::get_alembic_object() const
{
- if (!m_psys) {
- return;
- }
- Mesh *mesh = mesh_get_eval_final(
- m_settings.depsgraph, m_settings.scene, m_object, &CD_MASK_MESH);
+ return abc_curves_;
+}
+
+bool ABCHairWriter::check_is_animated(const HierarchyContext & /*context*/) const
+{
+ /* We assume that hair particles are always animated. */
+ return true;
+}
+
+void ABCHairWriter::do_write(HierarchyContext &context)
+{
+ Scene *scene_eval = DEG_get_evaluated_scene(args_.depsgraph);
+ Mesh *mesh = mesh_get_eval_final(args_.depsgraph, scene_eval, context.object, &CD_MASK_MESH);
BKE_mesh_tessface_ensure(mesh);
std::vector<Imath::V3f> verts;
@@ -71,44 +81,45 @@ void AbcHairWriter::do_write()
std::vector<Imath::V2f> uv_values;
std::vector<Imath::V3f> norm_values;
- if (m_psys->pathcache) {
- ParticleSettings *part = m_psys->part;
- bool export_children = m_settings.export_child_hairs && m_psys->childcache &&
- part->childtype != 0;
+ ParticleSystem *psys = context.particle_system;
+ if (psys->pathcache) {
+ ParticleSettings *part = psys->part;
+ bool export_children = psys->childcache && part->childtype != 0;
if (!export_children || part->draw & PART_DRAW_PARENT) {
- write_hair_sample(mesh, part, verts, norm_values, uv_values, hvertices);
+ write_hair_sample(context, mesh, verts, norm_values, uv_values, hvertices);
}
if (export_children) {
- write_hair_child_sample(mesh, part, verts, norm_values, uv_values, hvertices);
+ write_hair_child_sample(context, mesh, verts, norm_values, uv_values, hvertices);
}
}
Alembic::Abc::P3fArraySample iPos(verts);
- m_sample = OCurvesSchema::Sample(iPos, hvertices);
- m_sample.setBasis(Alembic::AbcGeom::kNoBasis);
- m_sample.setType(Alembic::AbcGeom::kLinear);
- m_sample.setWrap(Alembic::AbcGeom::kNonPeriodic);
+ OCurvesSchema::Sample sample(iPos, hvertices);
+ sample.setBasis(Alembic::AbcGeom::kNoBasis);
+ sample.setType(Alembic::AbcGeom::kLinear);
+ sample.setWrap(Alembic::AbcGeom::kNonPeriodic);
if (!uv_values.empty()) {
OV2fGeomParam::Sample uv_smp;
uv_smp.setVals(uv_values);
- m_sample.setUVs(uv_smp);
+ sample.setUVs(uv_smp);
}
if (!norm_values.empty()) {
ON3fGeomParam::Sample norm_smp;
norm_smp.setVals(norm_values);
- m_sample.setNormals(norm_smp);
+ sample.setNormals(norm_smp);
}
- m_sample.setSelfBounds(bounds());
- m_schema.set(m_sample);
+ update_bounding_box(context.object);
+ sample.setSelfBounds(bounding_box_);
+ abc_curves_schema_.set(sample);
}
-void AbcHairWriter::write_hair_sample(Mesh *mesh,
- ParticleSettings *part,
+void ABCHairWriter::write_hair_sample(const HierarchyContext &context,
+ Mesh *mesh,
std::vector<Imath::V3f> &verts,
std::vector<Imath::V3f> &norm_values,
std::vector<Imath::V2f> &uv_values,
@@ -116,28 +127,30 @@ void AbcHairWriter::write_hair_sample(Mesh *mesh,
{
/* Get untransformed vertices, there's a xform under the hair. */
float inv_mat[4][4];
- invert_m4_m4_safe(inv_mat, m_object->obmat);
+ invert_m4_m4_safe(inv_mat, context.object->obmat);
MTFace *mtface = mesh->mtface;
MFace *mface = mesh->mface;
MVert *mverts = mesh->mvert;
- if ((!mtface || !mface) && !m_uv_warning_shown) {
+ if ((!mtface || !mface) && !uv_warning_shown_) {
std::fprintf(stderr,
"Warning, no UV set found for underlying geometry of %s.\n",
- m_object->id.name + 2);
- m_uv_warning_shown = true;
+ context.object->id.name + 2);
+ uv_warning_shown_ = true;
}
- ParticleData *pa = m_psys->particles;
+ ParticleSystem *psys = context.particle_system;
+ ParticleSettings *part = psys->part;
+ ParticleData *pa = psys->particles;
int k;
- ParticleCacheKey **cache = m_psys->pathcache;
+ ParticleCacheKey **cache = psys->pathcache;
ParticleCacheKey *path;
float normal[3];
Imath::V3f tmp_nor;
- for (int p = 0; p < m_psys->totpart; p++, pa++) {
+ for (int p = 0; p < psys->totpart; p++, pa++) {
/* underlying info for faces-only emission */
path = cache[p];
@@ -219,8 +232,8 @@ void AbcHairWriter::write_hair_sample(Mesh *mesh,
}
}
-void AbcHairWriter::write_hair_child_sample(Mesh *mesh,
- ParticleSettings *part,
+void ABCHairWriter::write_hair_child_sample(const HierarchyContext &context,
+ Mesh *mesh,
std::vector<Imath::V3f> &verts,
std::vector<Imath::V3f> &norm_values,
std::vector<Imath::V2f> &uv_values,
@@ -228,26 +241,30 @@ void AbcHairWriter::write_hair_child_sample(Mesh *mesh,
{
/* Get untransformed vertices, there's a xform under the hair. */
float inv_mat[4][4];
- invert_m4_m4_safe(inv_mat, m_object->obmat);
+ invert_m4_m4_safe(inv_mat, context.object->obmat);
MTFace *mtface = mesh->mtface;
MVert *mverts = mesh->mvert;
- ParticleCacheKey **cache = m_psys->childcache;
+ ParticleSystem *psys = context.particle_system;
+ ParticleSettings *part = psys->part;
+ ParticleCacheKey **cache = psys->childcache;
ParticleCacheKey *path;
- ChildParticle *pc = m_psys->child;
+ ChildParticle *pc = psys->child;
- for (int p = 0; p < m_psys->totchild; p++, pc++) {
+ for (int p = 0; p < psys->totchild; p++, pc++) {
path = cache[p];
if (part->from == PART_FROM_FACE && part->childtype != PART_CHILD_PARTICLES && mtface) {
const int num = pc->num;
if (num < 0) {
- ABC_LOG(m_settings.logger)
- << "Warning, child particle of hair system " << m_psys->name
- << " has unknown face index of geometry of " << (m_object->id.name + 2)
- << ", skipping child hair." << std::endl;
+ CLOG_WARN(
+ &LOG,
+ "Child particle of hair system %s has unknown face index of geometry of %s, skipping "
+ "child hair.",
+ psys->name,
+ context.object->id.name + 2);
continue;
}
@@ -288,3 +305,7 @@ void AbcHairWriter::write_hair_child_sample(Mesh *mesh,
}
}
}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_writer_hair.h b/source/blender/io/alembic/exporter/abc_writer_hair.h
index 67d1b7b3d23..af1372a08f3 100644
--- a/source/blender/io/alembic/intern/abc_writer_hair.h
+++ b/source/blender/io/alembic/exporter/abc_writer_hair.h
@@ -13,50 +13,56 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_WRITER_HAIR_H__
-#define __ABC_WRITER_HAIR_H__
-
-#include "abc_writer_object.h"
+#include "abc_writer_abstract.h"
+#include <Alembic/AbcGeom/OCurves.h>
+#include <vector>
struct ParticleSettings;
struct ParticleSystem;
-class AbcHairWriter : public AbcObjectWriter {
- ParticleSystem *m_psys;
+namespace blender {
+namespace io {
+namespace alembic {
- Alembic::AbcGeom::OCurvesSchema m_schema;
- Alembic::AbcGeom::OCurvesSchema::Sample m_sample;
+class ABCHairWriter : public ABCAbstractWriter {
+ private:
+ Alembic::AbcGeom::OCurves abc_curves_;
+ Alembic::AbcGeom::OCurvesSchema abc_curves_schema_;
- bool m_uv_warning_shown;
+ bool uv_warning_shown_;
public:
- AbcHairWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings,
- ParticleSystem *psys);
+ explicit ABCHairWriter(const ABCWriterConstructorArgs &args);
- private:
- virtual void do_write();
+ virtual void create_alembic_objects(const HierarchyContext *context) override;
+ virtual const Alembic::Abc::OObject get_alembic_object() const override;
- void write_hair_sample(struct Mesh *mesh,
- ParticleSettings *part,
+ protected:
+ virtual void do_write(HierarchyContext &context) override;
+ virtual bool check_is_animated(const HierarchyContext &context) const override;
+
+ private:
+ void write_hair_sample(const HierarchyContext &context,
+ struct Mesh *mesh,
std::vector<Imath::V3f> &verts,
std::vector<Imath::V3f> &norm_values,
std::vector<Imath::V2f> &uv_values,
std::vector<int32_t> &hvertices);
- void write_hair_child_sample(struct Mesh *mesh,
- ParticleSettings *part,
+ void write_hair_child_sample(const HierarchyContext &context,
+ struct Mesh *mesh,
std::vector<Imath::V3f> &verts,
std::vector<Imath::V3f> &norm_values,
std::vector<Imath::V2f> &uv_values,
std::vector<int32_t> &hvertices);
};
-#endif /* __ABC_WRITER_HAIR_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/exporter/abc_writer_mball.cc b/source/blender/io/alembic/exporter/abc_writer_mball.cc
new file mode 100644
index 00000000000..167e392eb96
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_writer_mball.cc
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup balembic
+ */
+
+#include "abc_writer_mball.h"
+#include "abc_hierarchy_iterator.h"
+
+#include "BLI_assert.h"
+
+#include "BKE_displist.h"
+#include "BKE_lib_id.h"
+#include "BKE_mball.h"
+#include "BKE_mesh.h"
+#include "BKE_object.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+ABCMetaballWriter::ABCMetaballWriter(const ABCWriterConstructorArgs &args)
+ : ABCGenericMeshWriter(args)
+{
+}
+
+bool ABCMetaballWriter::is_supported(const HierarchyContext *context) const
+{
+ Scene *scene = DEG_get_input_scene(args_.depsgraph);
+ bool supported = is_basis_ball(scene, context->object) &&
+ ABCGenericMeshWriter::is_supported(context);
+ return supported;
+}
+
+bool ABCMetaballWriter::check_is_animated(const HierarchyContext & /*context*/) const
+{
+ /* We assume that metaballs are always animated, as the current object may
+ * not be animated but another ball in the same group may be. */
+ return true;
+}
+
+bool ABCMetaballWriter::export_as_subdivision_surface(Object * /*ob_eval*/) const
+{
+ /* Metaballs should be exported to subdivision surfaces, if the export options allow. */
+ return true;
+}
+
+Mesh *ABCMetaballWriter::get_export_mesh(Object *object_eval, bool &r_needsfree)
+{
+ Mesh *mesh_eval = BKE_object_get_evaluated_mesh(object_eval);
+ if (mesh_eval != nullptr) {
+ /* Mesh_eval only exists when generative modifiers are in use. */
+ r_needsfree = false;
+ return mesh_eval;
+ }
+ r_needsfree = true;
+ return BKE_mesh_new_from_object(args_.depsgraph, object_eval, false);
+}
+
+void ABCMetaballWriter::free_export_mesh(Mesh *mesh)
+{
+ BKE_id_free(nullptr, mesh);
+}
+
+bool ABCMetaballWriter::is_basis_ball(Scene *scene, Object *ob) const
+{
+ Object *basis_ob = BKE_mball_basis_find(scene, ob);
+ return ob == basis_ob;
+}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_writer_camera.h b/source/blender/io/alembic/exporter/abc_writer_mball.h
index 3b515911a48..90d8c4d4b15 100644
--- a/source/blender/io/alembic/intern/abc_writer_camera.h
+++ b/source/blender/io/alembic/exporter/abc_writer_mball.h
@@ -13,33 +13,33 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_WRITER_CAMERA_H__
-#define __ABC_WRITER_CAMERA_H__
+#include "abc_writer_mesh.h"
-#include "abc_writer_object.h"
-
-/* ************************************************************************** */
-
-class AbcCameraWriter : public AbcObjectWriter {
- Alembic::AbcGeom::OCameraSchema m_camera_schema;
- Alembic::AbcGeom::CameraSample m_camera_sample;
- Alembic::AbcGeom::OCompoundProperty m_custom_data_container;
- Alembic::AbcGeom::OFloatProperty m_stereo_distance;
- Alembic::AbcGeom::OFloatProperty m_eye_separation;
+namespace blender {
+namespace io {
+namespace alembic {
+class ABCMetaballWriter : public ABCGenericMeshWriter {
public:
- AbcCameraWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings);
+ explicit ABCMetaballWriter(const ABCWriterConstructorArgs &args);
+
+ protected:
+ virtual Mesh *get_export_mesh(Object *object_eval, bool &r_needsfree) override;
+ virtual void free_export_mesh(Mesh *mesh) override;
+ virtual bool is_supported(const HierarchyContext *context) const override;
+ virtual bool check_is_animated(const HierarchyContext &context) const override;
+ virtual bool export_as_subdivision_surface(Object *ob_eval) const override;
private:
- virtual void do_write();
+ bool is_basis_ball(Scene *scene, Object *ob) const;
};
-#endif /* __ABC_WRITER_CAMERA_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc
index df1734c9de1..07196f2b81f 100644
--- a/source/blender/io/alembic/intern/abc_writer_mesh.cc
+++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc
@@ -19,29 +19,37 @@
*/
#include "abc_writer_mesh.h"
-#include "abc_axis_conversion.h"
-#include "abc_writer_transform.h"
+#include "abc_hierarchy_iterator.h"
+#include "intern/abc_axis_conversion.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meshdata_types.h"
-#include "DNA_object_fluidsim_types.h"
+#include "BLI_assert.h"
+#include "BLI_math_vector.h"
-#include "BKE_anim_data.h"
-#include "BKE_key.h"
+#include "BKE_customdata.h"
#include "BKE_lib_id.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
-#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
+#include "BKE_object.h"
#include "bmesh.h"
#include "bmesh_tools.h"
-#include "DEG_depsgraph_query.h"
+#include "DEG_depsgraph.h"
+
+#include "DNA_layer_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_object_fluidsim_types.h"
+#include "DNA_particle_types.h"
+
+#include "CLG_log.h"
+static CLG_LogRef LOG = {"io.alembic"};
using Alembic::Abc::FloatArraySample;
using Alembic::Abc::Int32ArraySample;
+using Alembic::Abc::OObject;
using Alembic::Abc::V2fArraySample;
using Alembic::Abc::V3fArraySample;
@@ -58,138 +66,83 @@ using Alembic::AbcGeom::OSubDSchema;
using Alembic::AbcGeom::OV2fGeomParam;
using Alembic::AbcGeom::UInt32ArraySample;
-/* NOTE: Alembic's polygon winding order is clockwise, to match with Renderman. */
-
-static void get_vertices(struct Mesh *mesh, std::vector<Imath::V3f> &points)
-{
- points.clear();
- points.resize(mesh->totvert);
+namespace blender {
+namespace io {
+namespace alembic {
- MVert *verts = mesh->mvert;
-
- for (int i = 0, e = mesh->totvert; i < e; i++) {
- copy_yup_from_zup(points[i].getValue(), verts[i].co);
- }
-}
+/* NOTE: Alembic's polygon winding order is clockwise, to match with Renderman. */
+static void get_vertices(struct Mesh *mesh, std::vector<Imath::V3f> &points);
static void get_topology(struct Mesh *mesh,
std::vector<int32_t> &poly_verts,
std::vector<int32_t> &loop_counts,
- bool &r_has_flat_shaded_poly)
-{
- const int num_poly = mesh->totpoly;
- const int num_loops = mesh->totloop;
- MLoop *mloop = mesh->mloop;
- MPoly *mpoly = mesh->mpoly;
- r_has_flat_shaded_poly = false;
-
- poly_verts.clear();
- loop_counts.clear();
- poly_verts.reserve(num_loops);
- loop_counts.reserve(num_poly);
-
- /* NOTE: data needs to be written in the reverse order. */
- for (int i = 0; i < num_poly; i++) {
- MPoly &poly = mpoly[i];
- loop_counts.push_back(poly.totloop);
-
- r_has_flat_shaded_poly |= (poly.flag & ME_SMOOTH) == 0;
-
- MLoop *loop = mloop + poly.loopstart + (poly.totloop - 1);
-
- for (int j = 0; j < poly.totloop; j++, loop--) {
- poly_verts.push_back(loop->v);
- }
- }
-}
-
+ bool &r_has_flat_shaded_poly);
static void get_creases(struct Mesh *mesh,
std::vector<int32_t> &indices,
std::vector<int32_t> &lengths,
- std::vector<float> &sharpnesses)
-{
- const float factor = 1.0f / 255.0f;
+ std::vector<float> &sharpnesses);
+static void get_loop_normals(struct Mesh *mesh,
+ std::vector<Imath::V3f> &normals,
+ bool has_flat_shaded_poly);
- indices.clear();
- lengths.clear();
- sharpnesses.clear();
+ABCGenericMeshWriter::ABCGenericMeshWriter(const ABCWriterConstructorArgs &args)
+ : ABCAbstractWriter(args), is_subd_(false)
+{
+}
- MEdge *edge = mesh->medge;
+void ABCGenericMeshWriter::create_alembic_objects(const HierarchyContext *context)
+{
+ if (!args_.export_params->apply_subdiv && export_as_subdivision_surface(context->object)) {
+ is_subd_ = args_.export_params->use_subdiv_schema;
+ }
- for (int i = 0, e = mesh->totedge; i < e; i++) {
- const float sharpness = static_cast<float>(edge[i].crease) * factor;
+ if (is_subd_) {
+ CLOG_INFO(&LOG, 2, "exporting OSubD %s", args_.abc_path.c_str());
+ abc_subdiv_ = OSubD(args_.abc_parent, args_.abc_name, timesample_index_);
+ abc_subdiv_schema_ = abc_subdiv_.getSchema();
+ }
+ else {
+ CLOG_INFO(&LOG, 2, "exporting OPolyMesh %s", args_.abc_path.c_str());
+ abc_poly_mesh_ = OPolyMesh(args_.abc_parent, args_.abc_name, timesample_index_);
+ abc_poly_mesh_schema_ = abc_poly_mesh_.getSchema();
- if (sharpness != 0.0f) {
- indices.push_back(edge[i].v1);
- indices.push_back(edge[i].v2);
- sharpnesses.push_back(sharpness);
- }
+ OCompoundProperty typeContainer = abc_poly_mesh_.getSchema().getUserProperties();
+ OBoolProperty type(typeContainer, "meshtype");
+ type.set(subsurf_modifier_ == nullptr);
}
- lengths.resize(sharpnesses.size(), 2);
+ Scene *scene_eval = DEG_get_evaluated_scene(args_.depsgraph);
+ liquid_sim_modifier_ = get_liquid_sim_modifier(scene_eval, context->object);
}
-static void get_loop_normals(struct Mesh *mesh,
- std::vector<Imath::V3f> &normals,
- bool has_flat_shaded_poly)
+ABCGenericMeshWriter::~ABCGenericMeshWriter()
{
- normals.clear();
-
- /* If all polygons are smooth shaded, and there are no custom normals, we don't need to export
- * normals at all. This is also done by other software, see T71246. */
- if (!has_flat_shaded_poly && !CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL) &&
- (mesh->flag & ME_AUTOSMOOTH) == 0) {
- return;
- }
-
- BKE_mesh_calc_normals_split(mesh);
- const float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL));
- BLI_assert(lnors != NULL || !"BKE_mesh_calc_normals_split() should have computed CD_NORMAL");
-
- normals.resize(mesh->totloop);
+}
- /* NOTE: data needs to be written in the reverse order. */
- int abc_index = 0;
- MPoly *mp = mesh->mpoly;
- for (int i = 0, e = mesh->totpoly; i < e; i++, mp++) {
- for (int j = mp->totloop - 1; j >= 0; j--, abc_index++) {
- int blender_index = mp->loopstart + j;
- copy_yup_from_zup(normals[abc_index].getValue(), lnors[blender_index]);
- }
+const Alembic::Abc::OObject ABCGenericMeshWriter::get_alembic_object() const
+{
+ if (is_subd_) {
+ return abc_subdiv_;
}
+ return abc_poly_mesh_;
}
-/* *************** Modifiers *************** */
-
-/* check if the mesh is a subsurf, ignoring disabled modifiers and
- * displace if it's after subsurf. */
-static ModifierData *get_subsurf_modifier(Scene *scene, Object *ob)
+bool ABCGenericMeshWriter::export_as_subdivision_surface(Object *ob_eval) const
{
- ModifierData *md = static_cast<ModifierData *>(ob->modifiers.last);
+ ModifierData *md = static_cast<ModifierData *>(ob_eval->modifiers.last);
for (; md; md = md->prev) {
- if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Render)) {
- continue;
- }
-
- if (md->type == eModifierType_Subsurf) {
- SubsurfModifierData *smd = reinterpret_cast<SubsurfModifierData *>(md);
-
- if (smd->subdivType == ME_CC_SUBSURF) {
- return md;
- }
- }
-
- /* mesh is not a subsurf. break */
- if ((md->type != eModifierType_Displace) && (md->type != eModifierType_ParticleSystem)) {
- return NULL;
+ /* This modifier has been temporarily disabled by SubdivModifierDisabler,
+ * so this indicates this is to be exported as subdivision surface. */
+ if (md->type == eModifierType_Subsurf && (md->mode & eModifierMode_DisableTemporary)) {
+ return true;
}
}
- return NULL;
+ return false;
}
-static ModifierData *get_liquid_sim_modifier(Scene *scene, Object *ob)
+ModifierData *ABCGenericMeshWriter::get_liquid_sim_modifier(Scene *scene, Object *ob)
{
ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluidsim);
@@ -201,122 +154,99 @@ static ModifierData *get_liquid_sim_modifier(Scene *scene, Object *ob)
}
}
- return NULL;
+ return nullptr;
}
-/* ************************************************************************** */
-
-AbcGenericMeshWriter::AbcGenericMeshWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings)
- : AbcObjectWriter(ob, time_sampling, settings, parent)
+bool ABCGenericMeshWriter::is_supported(const HierarchyContext *context) const
{
- m_is_animated = isAnimated();
- m_subsurf_mod = NULL;
- m_is_subd = false;
-
- /* If the object is static, use the default static time sampling. */
- if (!m_is_animated) {
- time_sampling = 0;
- }
+ Object *object = context->object;
+ bool is_dupli = context->duplicator != nullptr;
+ int base_flag;
- if (!m_settings.apply_subdiv) {
- m_subsurf_mod = get_subsurf_modifier(m_settings.scene, m_object);
- m_is_subd = (m_subsurf_mod != NULL);
+ if (is_dupli) {
+ /* Construct the object's base flags from its dupli-parent, just like is done in
+ * deg_objects_dupli_iterator_next(). Without this, the visibility check below will fail. Doing
+ * this here, instead of a more suitable location in AbstractHierarchyIterator, prevents
+ * copying the Object for every dupli. */
+ base_flag = object->base_flag;
+ object->base_flag = context->duplicator->base_flag | BASE_FROM_DUPLI;
}
- m_is_liquid = (get_liquid_sim_modifier(m_settings.scene, m_object) != NULL);
+ int visibility = BKE_object_visibility(
+ object, DAG_EVAL_RENDER /* TODO(Sybren): add evaluation mode to export options? */);
- while (parent->alembicXform().getChildHeader(m_name)) {
- m_name.append("_");
+ if (is_dupli) {
+ object->base_flag = base_flag;
}
- if (m_settings.use_subdiv_schema && m_is_subd) {
- OSubD subd(parent->alembicXform(), m_name, m_time_sampling);
- m_subdiv_schema = subd.getSchema();
- }
- else {
- OPolyMesh mesh(parent->alembicXform(), m_name, m_time_sampling);
- m_mesh_schema = mesh.getSchema();
-
- OCompoundProperty typeContainer = m_mesh_schema.getUserProperties();
- OBoolProperty type(typeContainer, "meshtype");
- type.set(m_is_subd);
- }
+ return (visibility & OB_VISIBLE_SELF) != 0;
}
-AbcGenericMeshWriter::~AbcGenericMeshWriter()
+void ABCGenericMeshWriter::do_write(HierarchyContext &context)
{
- if (m_subsurf_mod) {
- m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary;
- }
-}
+ Object *object = context.object;
+ bool needsfree = false;
-bool AbcGenericMeshWriter::isAnimated() const
-{
- if (BKE_animdata_id_is_animated(static_cast<ID *>(m_object->data))) {
- return true;
- }
- if (BKE_key_from_object(m_object) != NULL) {
- return true;
- }
+ Mesh *mesh = get_export_mesh(object, needsfree);
- /* Test modifiers. */
- ModifierData *md = static_cast<ModifierData *>(m_object->modifiers.first);
- while (md) {
+ if (mesh == nullptr) {
+ return;
+ }
- if (md->type != eModifierType_Subsurf) {
- return true;
- }
+ if (args_.export_params->triangulate) {
+ const bool tag_only = false;
+ const int quad_method = args_.export_params->quad_method;
+ const int ngon_method = args_.export_params->ngon_method;
- md = md->next;
- }
+ struct BMeshCreateParams bmcp = {false};
+ struct BMeshFromMeshParams bmfmp = {true, false, false, 0};
+ BMesh *bm = BKE_mesh_to_bmesh_ex(mesh, &bmcp, &bmfmp);
- return false;
-}
+ BM_mesh_triangulate(bm, quad_method, ngon_method, 4, tag_only, nullptr, nullptr, nullptr);
-void AbcGenericMeshWriter::setIsAnimated(bool is_animated)
-{
- m_is_animated = is_animated;
-}
+ Mesh *triangulated_mesh = BKE_mesh_from_bmesh_for_eval_nomain(bm, nullptr, mesh);
+ BM_mesh_free(bm);
-void AbcGenericMeshWriter::do_write()
-{
- /* We have already stored a sample for this object. */
- if (!m_first_frame && !m_is_animated) {
- return;
+ if (needsfree) {
+ free_export_mesh(mesh);
+ }
+ mesh = triangulated_mesh;
+ needsfree = true;
}
- bool needsfree;
- struct Mesh *mesh = getFinalMesh(needsfree);
+ m_custom_data_config.pack_uvs = args_.export_params->packuv;
+ m_custom_data_config.mpoly = mesh->mpoly;
+ m_custom_data_config.mloop = mesh->mloop;
+ m_custom_data_config.totpoly = mesh->totpoly;
+ m_custom_data_config.totloop = mesh->totloop;
+ m_custom_data_config.totvert = mesh->totvert;
try {
- if (m_settings.use_subdiv_schema && m_subdiv_schema.valid()) {
- writeSubD(mesh);
+ if (is_subd_) {
+ write_subd(context, mesh);
}
else {
- writeMesh(mesh);
+ write_mesh(context, mesh);
}
if (needsfree) {
- freeEvaluatedMesh(mesh);
+ free_export_mesh(mesh);
}
}
catch (...) {
if (needsfree) {
- freeEvaluatedMesh(mesh);
+ free_export_mesh(mesh);
}
throw;
}
}
-void AbcGenericMeshWriter::freeEvaluatedMesh(struct Mesh *mesh)
+void ABCGenericMeshWriter::free_export_mesh(Mesh *mesh)
{
- BKE_id_free(NULL, mesh);
+ BKE_id_free(nullptr, mesh);
}
-void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh)
+void ABCGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh)
{
std::vector<Imath::V3f> points, normals;
std::vector<int32_t> poly_verts, loop_counts;
@@ -326,32 +256,33 @@ void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh)
get_vertices(mesh, points);
get_topology(mesh, poly_verts, loop_counts, has_flat_shaded_poly);
- if (m_first_frame && m_settings.export_face_sets) {
- writeFaceSets(mesh, m_mesh_schema);
+ if (!frame_has_been_written_ && args_.export_params->face_sets) {
+ write_face_sets(context.object, mesh, abc_poly_mesh_schema_);
}
- m_mesh_sample = OPolyMeshSchema::Sample(
+ OPolyMeshSchema::Sample mesh_sample = OPolyMeshSchema::Sample(
V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts));
- UVSample sample;
- if (m_settings.export_uvs) {
- const char *name = get_uv_sample(sample, m_custom_data_config, &mesh->ldata);
+ UVSample uvs_and_indices;
- if (!sample.indices.empty() && !sample.uvs.empty()) {
+ if (!frame_has_been_written_ && args_.export_params->uvs) {
+ const char *name = get_uv_sample(uvs_and_indices, m_custom_data_config, &mesh->ldata);
+
+ if (!uvs_and_indices.indices.empty() && !uvs_and_indices.uvs.empty()) {
OV2fGeomParam::Sample uv_sample;
- uv_sample.setVals(V2fArraySample(sample.uvs));
- uv_sample.setIndices(UInt32ArraySample(sample.indices));
+ uv_sample.setVals(V2fArraySample(uvs_and_indices.uvs));
+ uv_sample.setIndices(UInt32ArraySample(uvs_and_indices.indices));
uv_sample.setScope(kFacevaryingScope);
- m_mesh_schema.setUVSourceName(name);
- m_mesh_sample.setUVs(uv_sample);
+ abc_poly_mesh_schema_.setUVSourceName(name);
+ mesh_sample.setUVs(uv_sample);
}
write_custom_data(
- m_mesh_schema.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
+ abc_poly_mesh_schema_.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
}
- if (m_settings.export_normals) {
+ if (args_.export_params->normals) {
get_loop_normals(mesh, normals, has_flat_shaded_poly);
ON3fGeomParam::Sample normals_sample;
@@ -360,22 +291,23 @@ void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh)
normals_sample.setVals(V3fArraySample(normals));
}
- m_mesh_sample.setNormals(normals_sample);
+ mesh_sample.setNormals(normals_sample);
}
- if (m_is_liquid) {
- getVelocities(mesh, velocities);
- m_mesh_sample.setVelocities(V3fArraySample(velocities));
+ if (liquid_sim_modifier_ != nullptr) {
+ get_velocities(mesh, velocities);
+ mesh_sample.setVelocities(V3fArraySample(velocities));
}
- m_mesh_sample.setSelfBounds(bounds());
+ update_bounding_box(context.object);
+ mesh_sample.setSelfBounds(bounding_box_);
- m_mesh_schema.set(m_mesh_sample);
+ abc_poly_mesh_schema_.set(mesh_sample);
- writeArbGeoParams(mesh);
+ write_arb_geo_params(mesh);
}
-void AbcGenericMeshWriter::writeSubD(struct Mesh *mesh)
+void ABCGenericMeshWriter::write_subd(HierarchyContext &context, struct Mesh *mesh)
{
std::vector<float> crease_sharpness;
std::vector<Imath::V3f> points;
@@ -387,15 +319,15 @@ void AbcGenericMeshWriter::writeSubD(struct Mesh *mesh)
get_topology(mesh, poly_verts, loop_counts, has_flat_poly);
get_creases(mesh, crease_indices, crease_lengths, crease_sharpness);
- if (m_first_frame && m_settings.export_face_sets) {
- writeFaceSets(mesh, m_subdiv_schema);
+ if (!frame_has_been_written_ && args_.export_params->face_sets) {
+ write_face_sets(context.object, mesh, abc_subdiv_schema_);
}
- m_subdiv_sample = OSubDSchema::Sample(
+ OSubDSchema::Sample subdiv_sample = OSubDSchema::Sample(
V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts));
UVSample sample;
- if (m_first_frame && m_settings.export_uvs) {
+ if (!frame_has_been_written_ && args_.export_params->uvs) {
const char *name = get_uv_sample(sample, m_custom_data_config, &mesh->ldata);
if (!sample.indices.empty() && !sample.uvs.empty()) {
@@ -404,30 +336,32 @@ void AbcGenericMeshWriter::writeSubD(struct Mesh *mesh)
uv_sample.setIndices(UInt32ArraySample(sample.indices));
uv_sample.setScope(kFacevaryingScope);
- m_subdiv_schema.setUVSourceName(name);
- m_subdiv_sample.setUVs(uv_sample);
+ abc_subdiv_schema_.setUVSourceName(name);
+ subdiv_sample.setUVs(uv_sample);
}
write_custom_data(
- m_subdiv_schema.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
+ abc_subdiv_schema_.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
}
if (!crease_indices.empty()) {
- m_subdiv_sample.setCreaseIndices(Int32ArraySample(crease_indices));
- m_subdiv_sample.setCreaseLengths(Int32ArraySample(crease_lengths));
- m_subdiv_sample.setCreaseSharpnesses(FloatArraySample(crease_sharpness));
+ subdiv_sample.setCreaseIndices(Int32ArraySample(crease_indices));
+ subdiv_sample.setCreaseLengths(Int32ArraySample(crease_lengths));
+ subdiv_sample.setCreaseSharpnesses(FloatArraySample(crease_sharpness));
}
- m_subdiv_sample.setSelfBounds(bounds());
- m_subdiv_schema.set(m_subdiv_sample);
+ update_bounding_box(context.object);
+ subdiv_sample.setSelfBounds(bounding_box_);
+ abc_subdiv_schema_.set(subdiv_sample);
- writeArbGeoParams(mesh);
+ write_arb_geo_params(mesh);
}
-template<typename Schema> void AbcGenericMeshWriter::writeFaceSets(struct Mesh *me, Schema &schema)
+template<typename Schema>
+void ABCGenericMeshWriter::write_face_sets(Object *object, struct Mesh *mesh, Schema &schema)
{
std::map<std::string, std::vector<int32_t>> geo_groups;
- getGeoGroups(me, geo_groups);
+ get_geo_groups(object, mesh, geo_groups);
std::map<std::string, std::vector<int32_t>>::iterator it;
for (it = geo_groups.begin(); it != geo_groups.end(); ++it) {
@@ -438,83 +372,35 @@ template<typename Schema> void AbcGenericMeshWriter::writeFaceSets(struct Mesh *
}
}
-Mesh *AbcGenericMeshWriter::getFinalMesh(bool &r_needsfree)
+void ABCGenericMeshWriter::write_arb_geo_params(struct Mesh *me)
{
- /* We don't want subdivided mesh data */
- if (m_subsurf_mod) {
- m_subsurf_mod->mode |= eModifierMode_DisableTemporary;
- }
-
- r_needsfree = false;
-
- Scene *scene = DEG_get_evaluated_scene(m_settings.depsgraph);
- Object *ob_eval = DEG_get_evaluated_object(m_settings.depsgraph, m_object);
- struct Mesh *mesh = getEvaluatedMesh(scene, ob_eval, r_needsfree);
-
- if (m_subsurf_mod) {
- 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;
-
- struct BMeshCreateParams bmcp = {false};
- struct BMeshFromMeshParams bmfmp = {true, false, false, 0};
- BMesh *bm = BKE_mesh_to_bmesh_ex(mesh, &bmcp, &bmfmp);
-
- BM_mesh_triangulate(bm, quad_method, ngon_method, 4, tag_only, NULL, NULL, NULL);
-
- Mesh *result = BKE_mesh_from_bmesh_for_eval_nomain(bm, NULL, mesh);
- BM_mesh_free(bm);
-
- if (r_needsfree) {
- BKE_id_free(NULL, mesh);
- }
-
- mesh = result;
- r_needsfree = true;
+ if (liquid_sim_modifier_ != nullptr) {
+ /* We don't need anything more for liquid meshes. */
+ return;
}
- m_custom_data_config.pack_uvs = m_settings.pack_uv;
- m_custom_data_config.mpoly = mesh->mpoly;
- m_custom_data_config.mloop = mesh->mloop;
- m_custom_data_config.totpoly = mesh->totpoly;
- m_custom_data_config.totloop = mesh->totloop;
- m_custom_data_config.totvert = mesh->totvert;
-
- return mesh;
-}
-
-void AbcGenericMeshWriter::writeArbGeoParams(struct Mesh *me)
-{
- if (m_is_liquid) {
- /* We don't need anything more for liquid meshes. */
+ if (frame_has_been_written_ || !args_.export_params->vcolors) {
return;
}
- if (m_first_frame && m_settings.export_vcols) {
- if (m_subdiv_schema.valid()) {
- write_custom_data(
- m_subdiv_schema.getArbGeomParams(), m_custom_data_config, &me->ldata, CD_MLOOPCOL);
- }
- else {
- write_custom_data(
- m_mesh_schema.getArbGeomParams(), m_custom_data_config, &me->ldata, CD_MLOOPCOL);
- }
+ OCompoundProperty arb_geom_params;
+ if (is_subd_) {
+ arb_geom_params = abc_subdiv_.getSchema().getArbGeomParams();
}
+ else {
+ arb_geom_params = abc_poly_mesh_.getSchema().getArbGeomParams();
+ }
+ write_custom_data(arb_geom_params, m_custom_data_config, &me->ldata, CD_MLOOPCOL);
}
-void AbcGenericMeshWriter::getVelocities(struct Mesh *mesh, std::vector<Imath::V3f> &vels)
+void ABCGenericMeshWriter::get_velocities(struct Mesh *mesh, std::vector<Imath::V3f> &vels)
{
const int totverts = mesh->totvert;
vels.clear();
vels.resize(totverts);
- ModifierData *md = get_liquid_sim_modifier(m_settings.scene, m_object);
- FluidsimModifierData *fmd = reinterpret_cast<FluidsimModifierData *>(md);
+ FluidsimModifierData *fmd = reinterpret_cast<FluidsimModifierData *>(liquid_sim_modifier_);
FluidsimSettings *fss = fmd->fss;
if (fss->meshVelocities) {
@@ -530,8 +416,9 @@ void AbcGenericMeshWriter::getVelocities(struct Mesh *mesh, std::vector<Imath::V
}
}
-void AbcGenericMeshWriter::getGeoGroups(struct Mesh *mesh,
- std::map<std::string, std::vector<int32_t>> &geo_groups)
+void ABCGenericMeshWriter::get_geo_groups(Object *object,
+ struct Mesh *mesh,
+ std::map<std::string, std::vector<int32_t>> &geo_groups)
{
const int num_poly = mesh->totpoly;
MPoly *polygons = mesh->mpoly;
@@ -540,13 +427,13 @@ void AbcGenericMeshWriter::getGeoGroups(struct Mesh *mesh,
MPoly &current_poly = polygons[i];
short mnr = current_poly.mat_nr;
- Material *mat = BKE_object_material_get(m_object, mnr + 1);
+ Material *mat = BKE_object_material_get(object, mnr + 1);
if (!mat) {
continue;
}
- std::string name = get_id_name(&mat->id);
+ std::string name = args_.hierarchy_iterator->get_id_name(&mat->id);
if (geo_groups.find(name) == geo_groups.end()) {
std::vector<int32_t> faceArray;
@@ -557,9 +444,9 @@ void AbcGenericMeshWriter::getGeoGroups(struct Mesh *mesh,
}
if (geo_groups.size() == 0) {
- Material *mat = BKE_object_material_get(m_object, 1);
+ Material *mat = BKE_object_material_get(object, 1);
- std::string name = (mat) ? get_id_name(&mat->id) : "default";
+ std::string name = (mat) ? args_.hierarchy_iterator->get_id_name(&mat->id) : "default";
std::vector<int32_t> faceArray;
@@ -571,21 +458,116 @@ void AbcGenericMeshWriter::getGeoGroups(struct Mesh *mesh,
}
}
-AbcMeshWriter::AbcMeshWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings)
- : AbcGenericMeshWriter(ob, parent, time_sampling, settings)
+/* NOTE: Alembic's polygon winding order is clockwise, to match with Renderman. */
+
+static void get_vertices(struct Mesh *mesh, std::vector<Imath::V3f> &points)
{
+ points.clear();
+ points.resize(mesh->totvert);
+
+ MVert *verts = mesh->mvert;
+
+ for (int i = 0, e = mesh->totvert; i < e; i++) {
+ copy_yup_from_zup(points[i].getValue(), verts[i].co);
+ }
}
-AbcMeshWriter::~AbcMeshWriter()
+static void get_topology(struct Mesh *mesh,
+ std::vector<int32_t> &poly_verts,
+ std::vector<int32_t> &loop_counts,
+ bool &r_has_flat_shaded_poly)
{
+ const int num_poly = mesh->totpoly;
+ const int num_loops = mesh->totloop;
+ MLoop *mloop = mesh->mloop;
+ MPoly *mpoly = mesh->mpoly;
+ r_has_flat_shaded_poly = false;
+
+ poly_verts.clear();
+ loop_counts.clear();
+ poly_verts.reserve(num_loops);
+ loop_counts.reserve(num_poly);
+
+ /* NOTE: data needs to be written in the reverse order. */
+ for (int i = 0; i < num_poly; i++) {
+ MPoly &poly = mpoly[i];
+ loop_counts.push_back(poly.totloop);
+
+ r_has_flat_shaded_poly |= (poly.flag & ME_SMOOTH) == 0;
+
+ MLoop *loop = mloop + poly.loopstart + (poly.totloop - 1);
+
+ for (int j = 0; j < poly.totloop; j++, loop--) {
+ poly_verts.push_back(loop->v);
+ }
+ }
+}
+
+static void get_creases(struct Mesh *mesh,
+ std::vector<int32_t> &indices,
+ std::vector<int32_t> &lengths,
+ std::vector<float> &sharpnesses)
+{
+ const float factor = 1.0f / 255.0f;
+
+ indices.clear();
+ lengths.clear();
+ sharpnesses.clear();
+
+ MEdge *edge = mesh->medge;
+
+ for (int i = 0, e = mesh->totedge; i < e; i++) {
+ const float sharpness = static_cast<float>(edge[i].crease) * factor;
+
+ if (sharpness != 0.0f) {
+ indices.push_back(edge[i].v1);
+ indices.push_back(edge[i].v2);
+ sharpnesses.push_back(sharpness);
+ }
+ }
+
+ lengths.resize(sharpnesses.size(), 2);
}
-Mesh *AbcMeshWriter::getEvaluatedMesh(Scene *scene_eval,
- Object *ob_eval,
- bool &UNUSED(r_needsfree))
+static void get_loop_normals(struct Mesh *mesh,
+ std::vector<Imath::V3f> &normals,
+ bool has_flat_shaded_poly)
+{
+ normals.clear();
+
+ /* If all polygons are smooth shaded, and there are no custom normals, we don't need to export
+ * normals at all. This is also done by other software, see T71246. */
+ if (!has_flat_shaded_poly && !CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL) &&
+ (mesh->flag & ME_AUTOSMOOTH) == 0) {
+ return;
+ }
+
+ BKE_mesh_calc_normals_split(mesh);
+ const float(*lnors)[3] = static_cast<float(*)[3]>(CustomData_get_layer(&mesh->ldata, CD_NORMAL));
+ BLI_assert(lnors != nullptr || !"BKE_mesh_calc_normals_split() should have computed CD_NORMAL");
+
+ normals.resize(mesh->totloop);
+
+ /* NOTE: data needs to be written in the reverse order. */
+ int abc_index = 0;
+ MPoly *mp = mesh->mpoly;
+ for (int i = 0, e = mesh->totpoly; i < e; i++, mp++) {
+ for (int j = mp->totloop - 1; j >= 0; j--, abc_index++) {
+ int blender_index = mp->loopstart + j;
+ copy_yup_from_zup(normals[abc_index].getValue(), lnors[blender_index]);
+ }
+ }
+}
+
+ABCMeshWriter::ABCMeshWriter(const ABCWriterConstructorArgs &args) : ABCGenericMeshWriter(args)
{
- return mesh_get_eval_final(m_settings.depsgraph, scene_eval, ob_eval, &CD_MASK_MESH);
}
+
+Mesh *ABCMeshWriter::get_export_mesh(Object *object_eval, bool & /*r_needsfree*/)
+{
+ return BKE_object_get_evaluated_mesh(object_eval);
+}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.h b/source/blender/io/alembic/exporter/abc_writer_mesh.h
new file mode 100644
index 00000000000..bf4d4e9b9d8
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_writer_mesh.h
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+#pragma once
+
+/** \file
+ * \ingroup balembic
+ */
+
+#include "abc_writer_abstract.h"
+#include "intern/abc_customdata.h"
+
+#include <Alembic/AbcGeom/OPolyMesh.h>
+#include <Alembic/AbcGeom/OSubD.h>
+
+struct ModifierData;
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+/* Writer for Alembic geometry. Does not assume the object is a mesh object. */
+class ABCGenericMeshWriter : public ABCAbstractWriter {
+ private:
+ /* Either polymesh or subd is used, depending on is_subd_.
+ * References to the schema must be kept, or Alembic will not properly write. */
+ Alembic::AbcGeom::OPolyMesh abc_poly_mesh_;
+ Alembic::AbcGeom::OPolyMeshSchema abc_poly_mesh_schema_;
+
+ Alembic::AbcGeom::OSubD abc_subdiv_;
+ Alembic::AbcGeom::OSubDSchema abc_subdiv_schema_;
+
+ /* Determines whether a poly mesh or a subdivision surface is exported.
+ * The value is set by an export option but only true if there is a subdivision modifier on the
+ * exported object. */
+ bool is_subd_;
+ ModifierData *subsurf_modifier_;
+ ModifierData *liquid_sim_modifier_;
+
+ CDStreamConfig m_custom_data_config;
+
+ public:
+ explicit ABCGenericMeshWriter(const ABCWriterConstructorArgs &args);
+ virtual ~ABCGenericMeshWriter();
+
+ virtual void create_alembic_objects(const HierarchyContext *context) override;
+ virtual const Alembic::Abc::OObject get_alembic_object() const;
+
+ protected:
+ virtual bool is_supported(const HierarchyContext *context) const override;
+ virtual void do_write(HierarchyContext &context) override;
+
+ virtual Mesh *get_export_mesh(Object *object_eval, bool &r_needsfree) = 0;
+ virtual void free_export_mesh(Mesh *mesh);
+
+ virtual bool export_as_subdivision_surface(Object *ob_eval) const;
+
+ private:
+ void write_mesh(HierarchyContext &context, Mesh *mesh);
+ void write_subd(HierarchyContext &context, Mesh *mesh);
+ template<typename Schema> void write_face_sets(Object *object, Mesh *mesh, Schema &schema);
+
+ ModifierData *get_liquid_sim_modifier(Scene *scene_eval, Object *ob_eval);
+
+ void write_arb_geo_params(Mesh *me);
+ void get_velocities(Mesh *mesh, std::vector<Imath::V3f> &vels);
+ void get_geo_groups(Object *object,
+ Mesh *mesh,
+ std::map<std::string, std::vector<int32_t>> &geo_groups);
+};
+
+/* Writer for Alembic geometry of Blender Mesh objects. */
+class ABCMeshWriter : public ABCGenericMeshWriter {
+ public:
+ ABCMeshWriter(const ABCWriterConstructorArgs &args);
+
+ protected:
+ virtual Mesh *get_export_mesh(Object *object_eval, bool &r_needsfree) override;
+};
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_writer_nurbs.cc b/source/blender/io/alembic/exporter/abc_writer_nurbs.cc
index 8b4a1050d33..1fd382214a6 100644
--- a/source/blender/io/alembic/intern/abc_writer_nurbs.cc
+++ b/source/blender/io/alembic/exporter/abc_writer_nurbs.cc
@@ -19,8 +19,7 @@
*/
#include "abc_writer_nurbs.h"
-#include "abc_axis_conversion.h"
-#include "abc_writer_transform.h"
+#include "intern/abc_axis_conversion.h"
#include "DNA_curve_types.h"
#include "DNA_object_types.h"
@@ -29,48 +28,70 @@
#include "BKE_curve.h"
+#include "CLG_log.h"
+static CLG_LogRef LOG = {"io.alembic"};
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+using Alembic::Abc::OObject;
using Alembic::AbcGeom::FloatArraySample;
using Alembic::AbcGeom::OBoolProperty;
using Alembic::AbcGeom::OCompoundProperty;
using Alembic::AbcGeom::ONuPatch;
using Alembic::AbcGeom::ONuPatchSchema;
-AbcNurbsWriter::AbcNurbsWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings)
- : AbcObjectWriter(ob, time_sampling, settings, parent)
+ABCNurbsWriter::ABCNurbsWriter(const ABCWriterConstructorArgs &args) : ABCAbstractWriter(args)
{
- m_is_animated = isAnimated();
-
- /* if the object is static, use the default static time sampling */
- if (!m_is_animated) {
- m_time_sampling = 0;
- }
+}
- Curve *curve = static_cast<Curve *>(m_object->data);
- size_t numNurbs = BLI_listbase_count(&curve->nurb);
+void ABCNurbsWriter::create_alembic_objects(const HierarchyContext *context)
+{
+ Curve *curve = static_cast<Curve *>(context->object->data);
+ size_t num_nurbs = BLI_listbase_count(&curve->nurb);
+ OObject abc_parent = args_.abc_parent;
+ const char *abc_parent_path = abc_parent.getFullName().c_str();
- for (size_t i = 0; i < numNurbs; i++) {
- std::stringstream str;
- str << m_name << '_' << i;
+ for (size_t i = 0; i < num_nurbs; i++) {
+ std::stringstream patch_name_stream;
+ patch_name_stream << args_.abc_name << '_' << i;
- while (parent->alembicXform().getChildHeader(str.str())) {
- str << "_";
+ while (abc_parent.getChildHeader(patch_name_stream.str())) {
+ patch_name_stream << "_";
}
- ONuPatch nurbs(parent->alembicXform(), str.str().c_str(), m_time_sampling);
- m_nurbs_schema.push_back(nurbs.getSchema());
+ std::string patch_name = patch_name_stream.str();
+ CLOG_INFO(&LOG, 2, "exporting %s/%s", abc_parent_path, patch_name.c_str());
+
+ ONuPatch nurbs(abc_parent, patch_name.c_str(), timesample_index_);
+ abc_nurbs_.push_back(nurbs);
+ abc_nurbs_schemas_.push_back(nurbs.getSchema());
+ }
+}
+
+const OObject ABCNurbsWriter::get_alembic_object() const
+{
+ if (abc_nurbs_.empty()) {
+ return OObject();
}
+ /* For parenting purposes within the Alembic file, all NURBS patches are equal, so just use the
+ * first one. */
+ return abc_nurbs_[0];
}
-bool AbcNurbsWriter::isAnimated() const
+bool ABCNurbsWriter::check_is_animated(const HierarchyContext &context) const
{
- /* check if object has shape keys */
- Curve *cu = static_cast<Curve *>(m_object->data);
+ /* Check if object has shape keys. */
+ Curve *cu = static_cast<Curve *>(context.object->data);
return (cu->key != NULL);
}
+bool ABCNurbsWriter::is_supported(const HierarchyContext *context) const
+{
+ return ELEM(context->object->type, OB_SURF, OB_CURVE);
+}
+
static void get_knots(std::vector<float> &knots, const int num_knots, float *nu_knots)
{
if (num_knots <= 1) {
@@ -91,22 +112,13 @@ static void get_knots(std::vector<float> &knots, const int num_knots, float *nu_
knots.push_back(2.0f * knots[num_knots] - knots[num_knots - 1]);
}
-void AbcNurbsWriter::do_write()
+void ABCNurbsWriter::do_write(HierarchyContext &context)
{
- /* we have already stored a sample for this object. */
- if (!m_first_frame && !m_is_animated) {
- return;
- }
-
- if (!ELEM(m_object->type, OB_SURF, OB_CURVE)) {
- return;
- }
-
- Curve *curve = static_cast<Curve *>(m_object->data);
+ Curve *curve = static_cast<Curve *>(context.object->data);
ListBase *nulb;
- if (m_object->runtime.curve_cache->deformed_nurbs.first != NULL) {
- nulb = &m_object->runtime.curve_cache->deformed_nurbs;
+ if (context.object->runtime.curve_cache->deformed_nurbs.first != NULL) {
+ nulb = &context.object->runtime.curve_cache->deformed_nurbs;
}
else {
nulb = BKE_curve_nurbs_get(curve);
@@ -143,7 +155,7 @@ void AbcNurbsWriter::do_write()
/* TODO(kevin): to accommodate other software we should duplicate control
* points to indicate that a NURBS is cyclic. */
- OCompoundProperty user_props = m_nurbs_schema[count].getUserProperties();
+ OCompoundProperty user_props = abc_nurbs_schemas_[count].getUserProperties();
if ((nu->flagu & CU_NURB_ENDPOINT) != 0) {
OBoolProperty prop(user_props, "endpoint_u");
@@ -165,6 +177,10 @@ void AbcNurbsWriter::do_write()
prop.set(true);
}
- m_nurbs_schema[count].set(sample);
+ abc_nurbs_schemas_[count].set(sample);
}
}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/exporter/abc_writer_nurbs.h b/source/blender/io/alembic/exporter/abc_writer_nurbs.h
new file mode 100644
index 00000000000..23af4c40556
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_writer_nurbs.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+#pragma once
+
+/** \file
+ * \ingroup balembic
+ */
+
+#include "abc_writer_abstract.h"
+#include "abc_writer_mesh.h"
+#include <vector>
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+class ABCNurbsWriter : public ABCAbstractWriter {
+ private:
+ std::vector<Alembic::AbcGeom::ONuPatch> abc_nurbs_;
+ std::vector<Alembic::AbcGeom::ONuPatchSchema> abc_nurbs_schemas_;
+
+ public:
+ explicit ABCNurbsWriter(const ABCWriterConstructorArgs &args);
+
+ virtual void create_alembic_objects(const HierarchyContext *context) override;
+ virtual const Alembic::Abc::OObject get_alembic_object() const override;
+
+ protected:
+ virtual bool is_supported(const HierarchyContext *context) const override;
+ virtual void do_write(HierarchyContext &context) override;
+ virtual bool check_is_animated(const HierarchyContext &context) const override;
+};
+
+class ABCNurbsMeshWriter : public ABCGenericMeshWriter {
+ public:
+ explicit ABCNurbsMeshWriter(const ABCWriterConstructorArgs &args);
+
+ protected:
+ virtual Mesh *get_export_mesh(Object *object_eval, bool &r_needsfree) override;
+};
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/exporter/abc_writer_points.cc b/source/blender/io/alembic/exporter/abc_writer_points.cc
new file mode 100644
index 00000000000..19870e39a90
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_writer_points.cc
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup balembic
+ */
+
+#include "abc_writer_points.h"
+
+#include "DNA_object_types.h"
+#include "DNA_particle_types.h"
+
+#include "BKE_lattice.h"
+#include "BKE_particle.h"
+
+#include "BLI_math.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "CLG_log.h"
+static CLG_LogRef LOG = {"io.alembic"};
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+using Alembic::AbcGeom::kVertexScope;
+using Alembic::AbcGeom::OPoints;
+using Alembic::AbcGeom::OPointsSchema;
+
+ABCPointsWriter::ABCPointsWriter(const ABCWriterConstructorArgs &args) : ABCAbstractWriter(args)
+{
+}
+
+void ABCPointsWriter::create_alembic_objects(const HierarchyContext * /*context*/)
+{
+ CLOG_INFO(&LOG, 2, "exporting OPoints %s", args_.abc_path.c_str());
+ abc_points_ = OPoints(args_.abc_parent, args_.abc_name, timesample_index_);
+ abc_points_schema_ = abc_points_.getSchema();
+}
+
+const Alembic::Abc::OObject ABCPointsWriter::get_alembic_object() const
+{
+ return abc_points_;
+}
+
+bool ABCPointsWriter::is_supported(const HierarchyContext *context) const
+{
+ return ELEM(context->particle_system->part->type,
+ PART_EMITTER,
+ PART_FLUID_FLIP,
+ PART_FLUID_SPRAY,
+ PART_FLUID_BUBBLE,
+ PART_FLUID_FOAM,
+ PART_FLUID_TRACER,
+ PART_FLUID_SPRAYFOAM,
+ PART_FLUID_SPRAYBUBBLE,
+ PART_FLUID_FOAMBUBBLE,
+ PART_FLUID_SPRAYFOAMBUBBLE);
+}
+
+bool ABCPointsWriter::check_is_animated(const HierarchyContext & /*context*/) const
+{
+ /* We assume that particles are always animated. */
+ return true;
+}
+
+void ABCPointsWriter::do_write(HierarchyContext &context)
+{
+ BLI_assert(context.particle_system != nullptr);
+
+ std::vector<Imath::V3f> points;
+ std::vector<Imath::V3f> velocities;
+ std::vector<float> widths;
+ std::vector<uint64_t> ids;
+
+ ParticleSystem *psys = context.particle_system;
+ ParticleKey state;
+ ParticleSimulationData sim;
+ sim.depsgraph = args_.depsgraph;
+ sim.scene = DEG_get_evaluated_scene(args_.depsgraph);
+ sim.ob = context.object;
+ sim.psys = psys;
+
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
+
+ uint64_t index = 0;
+ for (int p = 0; p < psys->totpart; p++) {
+ float pos[3], vel[3];
+
+ if (psys->particles[p].flag & (PARS_NO_DISP | PARS_UNEXIST)) {
+ continue;
+ }
+
+ state.time = DEG_get_ctime(args_.depsgraph);
+ if (psys_get_particle_state(&sim, p, &state, 0) == 0) {
+ continue;
+ }
+
+ /* location */
+ mul_v3_m4v3(pos, context.object->imat, state.co);
+
+ /* velocity */
+ sub_v3_v3v3(vel, state.co, psys->particles[p].prev_state.co);
+
+ /* Convert Z-up to Y-up. */
+ points.push_back(Imath::V3f(pos[0], pos[2], -pos[1]));
+ velocities.push_back(Imath::V3f(vel[0], vel[2], -vel[1]));
+ widths.push_back(psys->particles[p].size);
+ ids.push_back(index++);
+ }
+
+ if (psys->lattice_deform_data) {
+ BKE_lattice_deform_data_destroy(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
+ }
+
+ Alembic::Abc::P3fArraySample psample(points);
+ Alembic::Abc::UInt64ArraySample idsample(ids);
+ Alembic::Abc::V3fArraySample vsample(velocities);
+ Alembic::Abc::FloatArraySample wsample_array(widths);
+ Alembic::AbcGeom::OFloatGeomParam::Sample wsample(wsample_array, kVertexScope);
+
+ OPointsSchema::Sample sample(psample, idsample, vsample, wsample);
+ update_bounding_box(context.object);
+ sample.setSelfBounds(bounding_box_);
+ abc_points_schema_.set(sample);
+}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_writer_archive.h b/source/blender/io/alembic/exporter/abc_writer_points.h
index 737717c1710..03800b80acf 100644
--- a/source/blender/io/alembic/intern/abc_writer_archive.h
+++ b/source/blender/io/alembic/exporter/abc_writer_points.h
@@ -16,35 +16,37 @@
* The Original Code is Copyright (C) 2016 Kévin Dietrich.
* All rights reserved.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_WRITER_ARCHIVE_H__
-#define __ABC_WRITER_ARCHIVE_H__
+#include "abc_writer_abstract.h"
-#include <Alembic/Abc/All.h>
-#include <Alembic/AbcCoreOgawa/All.h>
+#include <Alembic/AbcGeom/OPoints.h>
-#include <fstream>
+namespace blender {
+namespace io {
+namespace alembic {
-struct Main;
-struct Scene;
+class ABCPointsWriter : public ABCAbstractWriter {
+ Alembic::AbcGeom::OPoints abc_points_;
+ Alembic::AbcGeom::OPointsSchema abc_points_schema_;
-/* 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.
- */
+ public:
+ explicit ABCPointsWriter(const ABCWriterConstructorArgs &args);
-class ArchiveWriter {
- std::ofstream m_outfile;
- Alembic::Abc::OArchive m_archive;
+ virtual void create_alembic_objects(const HierarchyContext *context) override;
+ virtual const Alembic::Abc::OObject get_alembic_object() const override;
- public:
- ArchiveWriter(const char *filename, const std::string &abc_scene_name, const Scene *scene);
+ virtual bool is_supported(const HierarchyContext *context) const override;
- Alembic::Abc::OArchive &archive();
+ protected:
+ virtual bool check_is_animated(const HierarchyContext &context) const override;
+ virtual void do_write(HierarchyContext &context) override;
};
-#endif /* __ABC_WRITER_ARCHIVE_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/exporter/abc_writer_transform.cc b/source/blender/io/alembic/exporter/abc_writer_transform.cc
new file mode 100644
index 00000000000..65d6b7c5b41
--- /dev/null
+++ b/source/blender/io/alembic/exporter/abc_writer_transform.cc
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup balembic
+ */
+
+#include "abc_writer_transform.h"
+#include "abc_hierarchy_iterator.h"
+#include "intern/abc_axis_conversion.h"
+#include "intern/abc_util.h"
+
+#include "BKE_object.h"
+
+#include "BLI_math_matrix.h"
+#include "BLI_math_rotation.h"
+
+#include "DNA_layer_types.h"
+
+#include "CLG_log.h"
+static CLG_LogRef LOG = {"io.alembic"};
+
+namespace blender {
+namespace io {
+namespace alembic {
+
+using Alembic::Abc::OObject;
+using Alembic::AbcGeom::OXform;
+using Alembic::AbcGeom::OXformSchema;
+using Alembic::AbcGeom::XformSample;
+
+ABCTransformWriter::ABCTransformWriter(const ABCWriterConstructorArgs &args)
+ : ABCAbstractWriter(args)
+{
+ timesample_index_ = args_.abc_archive->time_sampling_index_transforms();
+}
+
+void ABCTransformWriter::create_alembic_objects(const HierarchyContext * /*context*/)
+{
+ CLOG_INFO(&LOG, 2, "exporting %s", args_.abc_path.c_str());
+ abc_xform_ = OXform(args_.abc_parent, args_.abc_name, timesample_index_);
+ abc_xform_schema_ = abc_xform_.getSchema();
+}
+
+void ABCTransformWriter::do_write(HierarchyContext &context)
+{
+ float parent_relative_matrix[4][4]; // The object matrix relative to the parent.
+ mul_m4_m4m4(parent_relative_matrix, context.parent_matrix_inv_world, context.matrix_world);
+
+ // After this, parent_relative_matrix uses Y=up.
+ copy_m44_axis_swap(parent_relative_matrix, parent_relative_matrix, ABC_YUP_FROM_ZUP);
+
+ /* If the parent is a camera, undo its to-Maya rotation (see below). */
+ bool is_root_object = context.export_parent == nullptr;
+ if (!is_root_object && context.export_parent->type == OB_CAMERA) {
+ float rot_mat[4][4];
+ axis_angle_to_mat4_single(rot_mat, 'X', M_PI_2);
+ mul_m4_m4m4(parent_relative_matrix, rot_mat, parent_relative_matrix);
+ }
+
+ /* If the object is a camera, apply an extra rotation to Maya camera orientation. */
+ if (context.object->type == OB_CAMERA) {
+ float rot_mat[4][4];
+ axis_angle_to_mat4_single(rot_mat, 'X', -M_PI_2);
+ mul_m4_m4m4(parent_relative_matrix, parent_relative_matrix, rot_mat);
+ }
+
+ if (is_root_object) {
+ /* Only apply scaling to root objects, parenting will propagate it. */
+ float scale_mat[4][4];
+ scale_m4_fl(scale_mat, args_.export_params->global_scale);
+ scale_mat[3][3] = args_.export_params->global_scale; /* also scale translation */
+ mul_m4_m4m4(parent_relative_matrix, parent_relative_matrix, scale_mat);
+ parent_relative_matrix[3][3] /=
+ args_.export_params->global_scale; /* normalise the homogeneous component */
+ }
+
+ XformSample xform_sample;
+ xform_sample.setMatrix(convert_matrix_datatype(parent_relative_matrix));
+ xform_sample.setInheritsXforms(true);
+ abc_xform_schema_.set(xform_sample);
+}
+
+const OObject ABCTransformWriter::get_alembic_object() const
+{
+ return abc_xform_;
+}
+
+bool ABCTransformWriter::check_is_animated(const HierarchyContext &context) const
+{
+ if (context.duplicator != NULL) {
+ /* This object is being duplicated, so could be emitted by a particle system and thus
+ * influenced by forces. TODO(Sybren): Make this more strict. Probably better to get from the
+ * depsgraph whether this object instance has a time source. */
+ return true;
+ }
+ return BKE_object_moves_in_time(context.object, context.animation_check_include_parent);
+}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_writer_nurbs.h b/source/blender/io/alembic/exporter/abc_writer_transform.h
index c6a3c399b66..950bff39c29 100644
--- a/source/blender/io/alembic/intern/abc_writer_nurbs.h
+++ b/source/blender/io/alembic/exporter/abc_writer_transform.h
@@ -13,30 +13,35 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_WRITER_NURBS_H__
-#define __ABC_WRITER_NURBS_H__
+#include "abc_writer_abstract.h"
-#include "abc_writer_object.h"
+#include <Alembic/AbcGeom/OXform.h>
-class AbcNurbsWriter : public AbcObjectWriter {
- std::vector<Alembic::AbcGeom::ONuPatchSchema> m_nurbs_schema;
- bool m_is_animated;
-
- public:
- AbcNurbsWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings);
+namespace blender {
+namespace io {
+namespace alembic {
+class ABCTransformWriter : public ABCAbstractWriter {
private:
- virtual void do_write();
+ Alembic::AbcGeom::OXform abc_xform_;
+ Alembic::AbcGeom::OXformSchema abc_xform_schema_;
+
+ public:
+ explicit ABCTransformWriter(const ABCWriterConstructorArgs &args);
+ virtual void create_alembic_objects(const HierarchyContext *context) override;
- bool isAnimated() const;
+ protected:
+ virtual void do_write(HierarchyContext &context) override;
+ virtual bool check_is_animated(const HierarchyContext &context) const override;
+ virtual const Alembic::Abc::OObject get_alembic_object() const override;
};
-#endif /* __ABC_WRITER_NURBS_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_axis_conversion.cc b/source/blender/io/alembic/intern/abc_axis_conversion.cc
index 17db5e9c99f..cebab1f2e41 100644
--- a/source/blender/io/alembic/intern/abc_axis_conversion.cc
+++ b/source/blender/io/alembic/intern/abc_axis_conversion.cc
@@ -20,12 +20,14 @@
#include "abc_axis_conversion.h"
-extern "C" {
#include "BLI_assert.h"
+#include "BLI_math_geom.h"
+
#include "DNA_object_types.h"
-#include "BLI_math_geom.h"
-}
+namespace blender {
+namespace io {
+namespace alembic {
void create_swapped_rotation_matrix(float rot_x_mat[3][3],
float rot_y_mat[3][3],
@@ -72,7 +74,8 @@ void create_swapped_rotation_matrix(float rot_x_mat[3][3],
rot_z_mat[1][0] = -sin(rz);
rot_z_mat[0][1] = sin(rz);
rot_z_mat[1][1] = cos(rz);
-}
+} // namespace
+ // alembicvoidcreate_swapped_rotation_matrix(floatrot_x_mat[3][3],floatrot_y_mat[3][3],floatrot_z_mat[3][3],constfloateuler[3],AbcAxisSwapModemode)
/* Convert matrix from Z=up to Y=up or vice versa.
* Use yup_mat = zup_mat for in-place conversion. */
@@ -164,3 +167,7 @@ void create_transform_matrix(Object *obj,
copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP);
}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender \ No newline at end of file
diff --git a/source/blender/io/alembic/intern/abc_axis_conversion.h b/source/blender/io/alembic/intern/abc_axis_conversion.h
index 7fde0e92ea4..9a19e9116be 100644
--- a/source/blender/io/alembic/intern/abc_axis_conversion.h
+++ b/source/blender/io/alembic/intern/abc_axis_conversion.h
@@ -22,13 +22,13 @@
* \ingroup Alembic
*/
+#include "BLI_compiler_compat.h"
+
struct Object;
-#ifdef _MSC_VER
-# define ABC_INLINE static __forceinline
-#else
-# define ABC_INLINE static inline
-#endif
+namespace blender {
+namespace io {
+namespace alembic {
/* TODO(kevin): for now keeping these transformations hardcoded to make sure
* everything works properly, and also because Alembic is almost exclusively
@@ -37,7 +37,7 @@ struct Object;
/* Copy from Y-up to Z-up. */
-ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3])
+BLI_INLINE void copy_zup_from_yup(float zup[3], const float yup[3])
{
const float old_yup1 = yup[1]; /* in case zup == yup */
zup[0] = yup[0];
@@ -45,7 +45,7 @@ ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3])
zup[2] = old_yup1;
}
-ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3])
+BLI_INLINE void copy_zup_from_yup(short zup[3], const short yup[3])
{
const short old_yup1 = yup[1]; /* in case zup == yup */
zup[0] = yup[0];
@@ -55,7 +55,7 @@ ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3])
/* Copy from Z-up to Y-up. */
-ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3])
+BLI_INLINE void copy_yup_from_zup(float yup[3], const float zup[3])
{
const float old_zup1 = zup[1]; /* in case yup == zup */
yup[0] = zup[0];
@@ -63,7 +63,7 @@ ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3])
yup[2] = -old_zup1;
}
-ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3])
+BLI_INLINE void copy_yup_from_zup(short yup[3], const short zup[3])
{
const short old_zup1 = zup[1]; /* in case yup == zup */
yup[0] = zup[0];
@@ -97,3 +97,7 @@ void create_transform_matrix(Object *obj,
float r_transform_mat[4][4],
AbcMatrixMode mode,
Object *proxy_from);
+
+} // namespace alembic
+} // namespace io
+} // namespace blender \ No newline at end of file
diff --git a/source/blender/io/alembic/intern/abc_customdata.cc b/source/blender/io/alembic/intern/abc_customdata.cc
index 62f6a52f7cf..f3e2342e844 100644
--- a/source/blender/io/alembic/intern/abc_customdata.cc
+++ b/source/blender/io/alembic/intern/abc_customdata.cc
@@ -50,6 +50,9 @@ using Alembic::Abc::V2fArraySample;
using Alembic::AbcGeom::OC4fGeomParam;
using Alembic::AbcGeom::OV2fGeomParam;
+namespace blender {
+namespace io {
+namespace alembic {
static void get_uvs(const CDStreamConfig &config,
std::vector<Imath::V2f> &uvs,
@@ -485,3 +488,7 @@ void read_custom_data(const std::string &iobject_full_name,
}
}
}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_customdata.h b/source/blender/io/alembic/intern/abc_customdata.h
index 96b57b08681..8f4accb70dc 100644
--- a/source/blender/io/alembic/intern/abc_customdata.h
+++ b/source/blender/io/alembic/intern/abc_customdata.h
@@ -16,14 +16,12 @@
* The Original Code is Copyright (C) 2016 Kévin Dietrich.
* All rights reserved.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_CUSTOMDATA_H__
-#define __ABC_CUSTOMDATA_H__
-
#include <Alembic/Abc/All.h>
#include <Alembic/AbcGeom/All.h>
@@ -38,6 +36,9 @@ struct Mesh;
using Alembic::Abc::ICompoundProperty;
using Alembic::Abc::OCompoundProperty;
+namespace blender {
+namespace io {
+namespace alembic {
struct UVSample {
std::vector<Imath::V2f> uvs;
@@ -112,4 +113,6 @@ void read_custom_data(const std::string &iobject_full_name,
const CDStreamConfig &config,
const Alembic::Abc::ISampleSelector &iss);
-#endif /* __ABC_CUSTOMDATA_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_exporter.cc b/source/blender/io/alembic/intern/abc_exporter.cc
deleted file mode 100644
index 8dad8dff199..00000000000
--- a/source/blender/io/alembic/intern/abc_exporter.cc
+++ /dev/null
@@ -1,673 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup balembic
- */
-
-#include "abc_exporter.h"
-
-#include <cmath>
-
-#include "abc_util.h"
-#include "abc_writer_archive.h"
-#include "abc_writer_camera.h"
-#include "abc_writer_curves.h"
-#include "abc_writer_hair.h"
-#include "abc_writer_mball.h"
-#include "abc_writer_mesh.h"
-#include "abc_writer_nurbs.h"
-#include "abc_writer_points.h"
-#include "abc_writer_transform.h"
-
-#include "DNA_camera_types.h"
-#include "DNA_curve_types.h"
-#include "DNA_fluid_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_meta_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_object_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_space_types.h" /* for FILE_MAX */
-
-#include "BLI_string.h"
-
-#ifdef WIN32
-/* needed for MSCV because of snprintf from BLI_string */
-# include "BLI_winstuff.h"
-#endif
-
-#include "BKE_duplilist.h"
-#include "BKE_global.h"
-#include "BKE_idprop.h"
-#include "BKE_layer.h"
-#include "BKE_main.h"
-#include "BKE_mball.h"
-#include "BKE_modifier.h"
-#include "BKE_particle.h"
-#include "BKE_scene.h"
-
-#include "DEG_depsgraph_query.h"
-
-using Alembic::Abc::OBox3dProperty;
-using Alembic::Abc::TimeSamplingPtr;
-
-/* ************************************************************************** */
-
-ExportSettings::ExportSettings()
- : scene(NULL),
- view_layer(NULL),
- depsgraph(NULL),
- logger(),
- selected_only(false),
- visible_objects_only(false),
- renderable_only(false),
- frame_start(1),
- frame_end(1),
- frame_samples_xform(1),
- frame_samples_shape(1),
- shutter_open(0.0),
- shutter_close(1.0),
- global_scale(1.0f),
- flatten_hierarchy(false),
- export_normals(false),
- export_uvs(false),
- export_vcols(false),
- export_face_sets(false),
- export_vweigths(false),
- export_hair(true),
- export_particles(true),
- apply_subdiv(false),
- use_subdiv_schema(false),
- export_child_hairs(true),
- pack_uv(false),
- triangulate(false),
- quad_method(0),
- ngon_method(0)
-{
-}
-
-static bool object_is_smoke_sim(Object *ob)
-{
- ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluid);
-
- if (md) {
- FluidModifierData *smd = reinterpret_cast<FluidModifierData *>(md);
- return (smd->type == MOD_FLUID_TYPE_DOMAIN && smd->domain &&
- smd->domain->type == FLUID_DOMAIN_TYPE_GAS);
- }
-
- return false;
-}
-
-static bool object_type_is_exportable(Scene *scene, Object *ob)
-{
- switch (ob->type) {
- case OB_MESH:
- if (object_is_smoke_sim(ob)) {
- return false;
- }
-
- return true;
- case OB_EMPTY:
- case OB_CURVE:
- case OB_SURF:
- case OB_CAMERA:
- return true;
- case OB_MBALL:
- return AbcMBallWriter::isBasisBall(scene, ob);
- default:
- return false;
- }
-}
-
-/**
- * Returns whether this object should be exported into the Alembic file.
- *
- * \param settings: export settings, used for options like 'selected only'.
- * \param ob: the object's base in question.
- * \param is_duplicated: Normally false; true when the object is instanced
- * into the scene by a dupli-object (e.g. part of a dupligroup).
- * This ignores selection and layer visibility,
- * and assumes that the dupli-object itself (e.g. the group-instantiating empty) is exported.
- */
-static bool export_object(const ExportSettings *const settings,
- const Base *const base,
- bool is_duplicated)
-{
- if (!is_duplicated) {
- View3D *v3d = NULL;
-
- /* These two tests only make sense when the object isn't being instanced
- * into the scene. When it is, its exportability is determined by
- * its dupli-object and the DupliObject::no_draw property. */
- if (settings->selected_only && !BASE_SELECTED(v3d, base)) {
- return false;
- }
- // FIXME Sybren: handle these cleanly (maybe just remove code),
- // now using active scene layer instead.
- if (settings->visible_objects_only && !BASE_VISIBLE(v3d, base)) {
- return false;
- }
- }
-
- Object *ob_eval = DEG_get_evaluated_object(settings->depsgraph, base->object);
- if ((ob_eval->id.tag & LIB_TAG_COPIED_ON_WRITE) == 0) {
- /* XXX fix after 2.80: the object was not part of the depsgraph, and thus we cannot get the
- * evaluated copy to export. This will be handled more elegantly in the new
- * AbstractHierarchyIterator that Sybren is working on. This condition is temporary, and avoids
- * a BLI_assert() failure getting the evaluated mesh of this object. */
- return false;
- }
-
- // if (settings->renderable_only && (ob->restrictflag & OB_RESTRICT_RENDER)) {
- // return false;
- // }
-
- return true;
-}
-
-/* ************************************************************************** */
-
-AbcExporter::AbcExporter(Main *bmain, const char *filename, ExportSettings &settings)
- : m_bmain(bmain),
- m_settings(settings),
- m_filename(filename),
- m_trans_sampling_index(0),
- m_shape_sampling_index(0),
- m_writer(NULL)
-{
-}
-
-AbcExporter::~AbcExporter()
-{
- /* Free xforms map */
- m_xforms_type::iterator it_x, e_x;
- for (it_x = m_xforms.begin(), e_x = m_xforms.end(); it_x != e_x; ++it_x) {
- delete it_x->second;
- }
-
- /* Free shapes vector */
- for (int i = 0, e = m_shapes.size(); i != e; i++) {
- delete m_shapes[i];
- }
-
- delete m_writer;
-}
-
-void AbcExporter::getShutterSamples(unsigned int nr_of_samples,
- bool time_relative,
- std::vector<double> &samples)
-{
- Scene *scene = m_settings.scene; /* for use in the FPS macro */
- samples.clear();
-
- unsigned int frame_offset = time_relative ? m_settings.frame_start : 0;
- double time_factor = time_relative ? FPS : 1.0;
- double shutter_open = m_settings.shutter_open;
- double shutter_close = m_settings.shutter_close;
- double time_inc = (shutter_close - shutter_open) / nr_of_samples;
-
- /* sample between shutter open & close */
- for (int sample = 0; sample < nr_of_samples; sample++) {
- double sample_time = shutter_open + time_inc * sample;
- double time = (frame_offset + sample_time) / time_factor;
-
- samples.push_back(time);
- }
-}
-
-Alembic::Abc::TimeSamplingPtr AbcExporter::createTimeSampling(double step)
-{
- std::vector<double> samples;
-
- if (m_settings.frame_start == m_settings.frame_end) {
- return TimeSamplingPtr(new Alembic::Abc::TimeSampling());
- }
-
- getShutterSamples(step, true, samples);
-
- /* TODO(Sybren): shouldn't we use the FPS macro here? */
- Alembic::Abc::TimeSamplingType ts(static_cast<uint32_t>(samples.size()),
- 1.0 / m_settings.scene->r.frs_sec);
-
- return TimeSamplingPtr(new Alembic::Abc::TimeSampling(ts, samples));
-}
-
-void AbcExporter::getFrameSet(unsigned int nr_of_samples, std::set<double> &frames)
-{
- frames.clear();
-
- std::vector<double> shutter_samples;
-
- getShutterSamples(nr_of_samples, false, shutter_samples);
-
- for (double frame = m_settings.frame_start; frame <= m_settings.frame_end; frame += 1.0) {
- for (size_t j = 0; j < nr_of_samples; j++) {
- frames.insert(frame + shutter_samples[j]);
- }
- }
-}
-
-void AbcExporter::operator()(short *do_update, float *progress, bool *was_canceled)
-{
- std::string abc_scene_name;
-
- if (m_bmain->name[0] != '\0') {
- char scene_file_name[FILE_MAX];
- BLI_strncpy(scene_file_name, m_bmain->name, FILE_MAX);
- abc_scene_name = scene_file_name;
- }
- else {
- abc_scene_name = "untitled";
- }
-
- m_writer = new ArchiveWriter(m_filename, abc_scene_name, m_settings.scene);
-
- /* Create time samplings for transforms and shapes. */
-
- TimeSamplingPtr trans_time = createTimeSampling(m_settings.frame_samples_xform);
-
- m_trans_sampling_index = m_writer->archive().addTimeSampling(*trans_time);
-
- TimeSamplingPtr shape_time;
-
- if ((m_settings.frame_samples_shape == m_settings.frame_samples_xform) ||
- (m_settings.frame_start == m_settings.frame_end)) {
- shape_time = trans_time;
- m_shape_sampling_index = m_trans_sampling_index;
- }
- else {
- shape_time = createTimeSampling(m_settings.frame_samples_shape);
- m_shape_sampling_index = m_writer->archive().addTimeSampling(*shape_time);
- }
-
- OBox3dProperty archive_bounds_prop = Alembic::AbcGeom::CreateOArchiveBounds(
- m_writer->archive(), m_trans_sampling_index);
-
- createTransformWritersHierarchy();
- createShapeWriters();
-
- /* Make a list of frames to export. */
-
- std::set<double> xform_frames;
- getFrameSet(m_settings.frame_samples_xform, xform_frames);
-
- std::set<double> shape_frames;
- getFrameSet(m_settings.frame_samples_shape, shape_frames);
-
- /* Merge all frames needed. */
- std::set<double> frames(xform_frames);
- frames.insert(shape_frames.begin(), shape_frames.end());
-
- /* Export all frames. */
-
- std::set<double>::const_iterator begin = frames.begin();
- std::set<double>::const_iterator end = frames.end();
-
- const float size = static_cast<float>(frames.size());
- size_t i = 0;
-
- for (; begin != end; ++begin) {
- *progress = (++i / size);
- *do_update = 1;
-
- if (G.is_break) {
- *was_canceled = true;
- break;
- }
-
- const double frame = *begin;
-
- /* 'frame' is offset by start frame, so need to cancel the offset. */
- setCurrentFrame(m_bmain, frame);
-
- if (shape_frames.count(frame) != 0) {
- for (int i = 0, e = m_shapes.size(); i != e; i++) {
- m_shapes[i]->write();
- }
- }
-
- if (xform_frames.count(frame) == 0) {
- continue;
- }
-
- m_xforms_type::iterator xit, xe;
- for (xit = m_xforms.begin(), xe = m_xforms.end(); xit != xe; ++xit) {
- xit->second->write();
- }
-
- /* Save the archive 's bounding box. */
- Imath::Box3d bounds;
-
- for (xit = m_xforms.begin(), xe = m_xforms.end(); xit != xe; ++xit) {
- Imath::Box3d box = xit->second->bounds();
- bounds.extendBy(box);
- }
-
- archive_bounds_prop.set(bounds);
- }
-}
-
-void AbcExporter::createTransformWritersHierarchy()
-{
- for (Base *base = static_cast<Base *>(m_settings.view_layer->object_bases.first); base;
- base = base->next) {
- Object *ob = base->object;
-
- if (export_object(&m_settings, base, false)) {
- switch (ob->type) {
- case OB_LAMP:
- case OB_LATTICE:
- case OB_SPEAKER:
- /* We do not export transforms for objects of these classes. */
- break;
- default:
- exploreTransform(base, ob, ob->parent, NULL);
- }
- }
- }
-}
-
-void AbcExporter::exploreTransform(Base *base,
- Object *object,
- Object *parent,
- Object *dupliObParent)
-{
- /* If an object isn't exported itself, its duplilist shouldn't be
- * exported either. */
- if (!export_object(&m_settings, base, dupliObParent != NULL)) {
- return;
- }
-
- Object *ob = DEG_get_evaluated_object(m_settings.depsgraph, object);
- if (object_type_is_exportable(m_settings.scene, ob)) {
- createTransformWriter(ob, parent, dupliObParent);
- }
-
- ListBase *lb = object_duplilist(m_settings.depsgraph, m_settings.scene, ob);
-
- if (lb) {
- DupliObject *link = static_cast<DupliObject *>(lb->first);
- Object *dupli_ob = NULL;
- Object *dupli_parent = NULL;
-
- for (; link; link = link->next) {
- /* This skips things like custom bone shapes. */
- if (m_settings.renderable_only && link->no_draw) {
- continue;
- }
-
- if (link->type == OB_DUPLICOLLECTION) {
- dupli_ob = link->ob;
- dupli_parent = (dupli_ob->parent) ? dupli_ob->parent : ob;
-
- exploreTransform(base, dupli_ob, dupli_parent, ob);
- }
- }
-
- free_object_duplilist(lb);
- }
-}
-
-AbcTransformWriter *AbcExporter::createTransformWriter(Object *ob,
- Object *parent,
- Object *dupliObParent)
-{
- /* An object should not be its own parent, or we'll get infinite loops. */
- BLI_assert(ob != parent);
- BLI_assert(ob != dupliObParent);
-
- std::string name;
- if (m_settings.flatten_hierarchy) {
- name = get_id_name(ob);
- }
- else {
- name = get_object_dag_path_name(ob, dupliObParent);
- }
-
- /* check if we have already created a transform writer for this object */
- AbcTransformWriter *my_writer = getXForm(name);
- if (my_writer != NULL) {
- return my_writer;
- }
-
- AbcTransformWriter *parent_writer = NULL;
- Alembic::Abc::OObject alembic_parent;
-
- if (m_settings.flatten_hierarchy || parent == NULL) {
- /* Parentless objects still have the "top object" as parent
- * in Alembic. */
- alembic_parent = m_writer->archive().getTop();
- }
- else {
- /* Since there are so many different ways to find parents (as evident
- * in the number of conditions below), we can't really look up the
- * parent by name. We'll just call createTransformWriter(), which will
- * return the parent's AbcTransformWriter pointer. */
- if (parent->parent) {
- if (parent == dupliObParent) {
- parent_writer = createTransformWriter(parent, parent->parent, NULL);
- }
- else {
- parent_writer = createTransformWriter(parent, parent->parent, dupliObParent);
- }
- }
- else if (parent == dupliObParent) {
- if (dupliObParent->parent == NULL) {
- parent_writer = createTransformWriter(parent, NULL, NULL);
- }
- else {
- parent_writer = createTransformWriter(
- parent, dupliObParent->parent, dupliObParent->parent);
- }
- }
- else {
- parent_writer = createTransformWriter(parent, dupliObParent, dupliObParent);
- }
-
- BLI_assert(parent_writer);
- alembic_parent = parent_writer->alembicXform();
- }
-
- my_writer = new AbcTransformWriter(
- ob, alembic_parent, parent_writer, m_trans_sampling_index, m_settings);
-
- /* When flattening, the matrix of the dupliobject has to be added. */
- if (m_settings.flatten_hierarchy && dupliObParent) {
- my_writer->m_proxy_from = dupliObParent;
- }
-
- m_xforms[name] = my_writer;
- return my_writer;
-}
-
-void AbcExporter::createShapeWriters()
-{
- for (Base *base = static_cast<Base *>(m_settings.view_layer->object_bases.first); base;
- base = base->next) {
- exploreObject(base, base->object, NULL);
- }
-}
-
-void AbcExporter::exploreObject(Base *base, Object *object, Object *dupliObParent)
-{
- /* If an object isn't exported itself, its duplilist shouldn't be
- * exported either. */
- if (!export_object(&m_settings, base, dupliObParent != NULL)) {
- return;
- }
-
- Object *ob = DEG_get_evaluated_object(m_settings.depsgraph, object);
- createShapeWriter(ob, dupliObParent);
-
- ListBase *lb = object_duplilist(m_settings.depsgraph, m_settings.scene, ob);
-
- if (lb) {
- DupliObject *link = static_cast<DupliObject *>(lb->first);
-
- for (; link; link = link->next) {
- /* This skips things like custom bone shapes. */
- if (m_settings.renderable_only && link->no_draw) {
- continue;
- }
- if (link->type == OB_DUPLICOLLECTION) {
- exploreObject(base, link->ob, ob);
- }
- }
-
- free_object_duplilist(lb);
- }
-}
-
-void AbcExporter::createParticleSystemsWriters(Object *ob, AbcTransformWriter *xform)
-{
- if (!m_settings.export_hair && !m_settings.export_particles) {
- return;
- }
-
- ParticleSystem *psys = static_cast<ParticleSystem *>(ob->particlesystem.first);
-
- for (; psys; psys = psys->next) {
- if (!psys_check_enabled(ob, psys, G.is_rendering) || !psys->part) {
- continue;
- }
-
- if (m_settings.export_hair && psys->part->type == PART_HAIR) {
- m_settings.export_child_hairs = true;
- m_shapes.push_back(new AbcHairWriter(ob, xform, m_shape_sampling_index, m_settings, psys));
- }
- else if (m_settings.export_particles &&
- (psys->part->type == PART_EMITTER || psys->part->type == PART_FLUID_FLIP ||
- psys->part->type == PART_FLUID_SPRAY || psys->part->type == PART_FLUID_BUBBLE ||
- psys->part->type == PART_FLUID_FOAM || psys->part->type == PART_FLUID_TRACER ||
- psys->part->type == PART_FLUID_SPRAYFOAM ||
- psys->part->type == PART_FLUID_SPRAYBUBBLE ||
- psys->part->type == PART_FLUID_FOAMBUBBLE ||
- psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE)) {
- m_shapes.push_back(new AbcPointsWriter(ob, xform, m_shape_sampling_index, m_settings, psys));
- }
- }
-}
-
-void AbcExporter::createShapeWriter(Object *ob, Object *dupliObParent)
-{
- if (!object_type_is_exportable(m_settings.scene, ob)) {
- return;
- }
-
- std::string name;
-
- if (m_settings.flatten_hierarchy) {
- name = get_id_name(ob);
- }
- else {
- name = get_object_dag_path_name(ob, dupliObParent);
- }
-
- AbcTransformWriter *xform = getXForm(name);
-
- if (!xform) {
- ABC_LOG(m_settings.logger) << __func__ << ": xform " << name << " is NULL\n";
- return;
- }
-
- createParticleSystemsWriters(ob, xform);
-
- switch (ob->type) {
- case OB_MESH: {
- Mesh *me = static_cast<Mesh *>(ob->data);
-
- if (!me) {
- return;
- }
-
- m_shapes.push_back(new AbcMeshWriter(ob, xform, m_shape_sampling_index, m_settings));
- break;
- }
- case OB_SURF: {
- Curve *cu = static_cast<Curve *>(ob->data);
-
- if (!cu) {
- return;
- }
-
- AbcObjectWriter *writer;
- if (m_settings.curves_as_mesh) {
- writer = new AbcCurveMeshWriter(ob, xform, m_shape_sampling_index, m_settings);
- }
- else {
- writer = new AbcNurbsWriter(ob, xform, m_shape_sampling_index, m_settings);
- }
- m_shapes.push_back(writer);
- break;
- }
- case OB_CURVE: {
- Curve *cu = static_cast<Curve *>(ob->data);
-
- if (!cu) {
- return;
- }
-
- AbcObjectWriter *writer;
- if (m_settings.curves_as_mesh) {
- writer = new AbcCurveMeshWriter(ob, xform, m_shape_sampling_index, m_settings);
- }
- else {
- writer = new AbcCurveWriter(ob, xform, m_shape_sampling_index, m_settings);
- }
- m_shapes.push_back(writer);
- break;
- }
- case OB_CAMERA: {
- Camera *cam = static_cast<Camera *>(ob->data);
-
- if (cam->type == CAM_PERSP) {
- m_shapes.push_back(new AbcCameraWriter(ob, xform, m_shape_sampling_index, m_settings));
- }
-
- break;
- }
- case OB_MBALL: {
- MetaBall *mball = static_cast<MetaBall *>(ob->data);
- if (!mball) {
- return;
- }
-
- m_shapes.push_back(
- new AbcMBallWriter(m_bmain, ob, xform, m_shape_sampling_index, m_settings));
- break;
- }
- }
-}
-
-AbcTransformWriter *AbcExporter::getXForm(const std::string &name)
-{
- std::map<std::string, AbcTransformWriter *>::iterator it = m_xforms.find(name);
-
- if (it == m_xforms.end()) {
- return NULL;
- }
-
- return it->second;
-}
-
-void AbcExporter::setCurrentFrame(Main *bmain, double t)
-{
- m_settings.scene->r.cfra = static_cast<int>(t);
- m_settings.scene->r.subframe = static_cast<float>(t) - m_settings.scene->r.cfra;
- BKE_scene_graph_update_for_newframe(m_settings.depsgraph, bmain);
-}
diff --git a/source/blender/io/alembic/intern/abc_exporter.h b/source/blender/io/alembic/intern/abc_exporter.h
deleted file mode 100644
index 049ccb291bd..00000000000
--- a/source/blender/io/alembic/intern/abc_exporter.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup balembic
- */
-
-#ifndef __ABC_EXPORTER_H__
-#define __ABC_EXPORTER_H__
-
-#include <Alembic/Abc/All.h>
-#include <map>
-#include <set>
-#include <vector>
-
-#include "abc_util.h"
-
-class AbcObjectWriter;
-class AbcTransformWriter;
-class ArchiveWriter;
-
-struct Base;
-struct Depsgraph;
-struct Main;
-struct Object;
-struct Scene;
-struct ViewLayer;
-
-struct ExportSettings {
- ExportSettings();
-
- Scene *scene;
- /** Scene layer to export; all its objects will be exported, unless selected_only=true. */
- ViewLayer *view_layer;
- Depsgraph *depsgraph;
- SimpleLogger logger;
-
- bool selected_only;
- bool visible_objects_only;
- bool renderable_only;
-
- double frame_start, frame_end;
- double frame_samples_xform;
- double frame_samples_shape;
- double shutter_open;
- double shutter_close;
- float global_scale;
-
- bool flatten_hierarchy;
-
- bool export_normals;
- bool export_uvs;
- bool export_vcols;
- bool export_face_sets;
- bool export_vweigths;
- bool export_hair;
- bool export_particles;
-
- bool apply_subdiv;
- bool curves_as_mesh;
- bool use_subdiv_schema;
- bool export_child_hairs;
- bool pack_uv;
- bool triangulate;
-
- int quad_method;
- int ngon_method;
-};
-
-class AbcExporter {
- Main *m_bmain;
- ExportSettings &m_settings;
-
- const char *m_filename;
-
- unsigned int m_trans_sampling_index, m_shape_sampling_index;
-
- ArchiveWriter *m_writer;
-
- /* mapping from name to transform writer */
- typedef std::map<std::string, AbcTransformWriter *> m_xforms_type;
- m_xforms_type m_xforms;
-
- std::vector<AbcObjectWriter *> m_shapes;
-
- public:
- AbcExporter(Main *bmain, const char *filename, ExportSettings &settings);
- ~AbcExporter();
-
- void operator()(short *do_update, float *progress, bool *was_canceled);
-
- protected:
- void getShutterSamples(unsigned int nr_of_samples,
- bool time_relative,
- std::vector<double> &samples);
- void getFrameSet(unsigned int nr_of_samples, std::set<double> &frames);
-
- private:
- Alembic::Abc::TimeSamplingPtr createTimeSampling(double step);
-
- void createTransformWritersHierarchy();
- AbcTransformWriter *createTransformWriter(Object *ob, Object *parent, Object *dupliObParent);
- void exploreTransform(Base *base, Object *object, Object *parent, Object *dupliObParent);
- void exploreObject(Base *base, Object *object, Object *dupliObParent);
- void createShapeWriters();
- void createShapeWriter(Object *ob, Object *dupliObParent);
- void createParticleSystemsWriters(Object *ob, AbcTransformWriter *xform);
-
- AbcTransformWriter *getXForm(const std::string &name);
-
- void setCurrentFrame(Main *bmain, double t);
-};
-
-#endif /* __ABC_EXPORTER_H__ */
diff --git a/source/blender/io/alembic/intern/abc_reader_archive.cc b/source/blender/io/alembic/intern/abc_reader_archive.cc
index d55736f732a..d7f1095f0fd 100644
--- a/source/blender/io/alembic/intern/abc_reader_archive.cc
+++ b/source/blender/io/alembic/intern/abc_reader_archive.cc
@@ -39,6 +39,10 @@ using Alembic::Abc::Exception;
using Alembic::Abc::IArchive;
using Alembic::Abc::kWrapExisting;
+namespace blender {
+namespace io {
+namespace alembic {
+
static IArchive open_archive(const std::string &filename,
const std::vector<std::istream *> &input_streams)
{
@@ -103,3 +107,7 @@ Alembic::Abc::IObject ArchiveReader::getTop()
{
return m_archive.getTop();
}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_archive.h b/source/blender/io/alembic/intern/abc_reader_archive.h
index 304c876adce..aea62b46cce 100644
--- a/source/blender/io/alembic/intern/abc_reader_archive.h
+++ b/source/blender/io/alembic/intern/abc_reader_archive.h
@@ -16,14 +16,12 @@
* The Original Code is Copyright (C) 2016 Kévin Dietrich.
* All rights reserved.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_READER_ARCHIVE_H__
-#define __ABC_READER_ARCHIVE_H__
-
#include <Alembic/Abc/All.h>
#include <Alembic/AbcCoreOgawa/All.h>
@@ -32,6 +30,10 @@
struct Main;
struct Scene;
+namespace blender {
+namespace io {
+namespace alembic {
+
/* 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.
@@ -50,4 +52,6 @@ class ArchiveReader {
Alembic::Abc::IObject getTop();
};
-#endif /* __ABC_READER_ARCHIVE_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_camera.cc b/source/blender/io/alembic/intern/abc_reader_camera.cc
index 0752534f8c2..3affb35908d 100644
--- a/source/blender/io/alembic/intern/abc_reader_camera.cc
+++ b/source/blender/io/alembic/intern/abc_reader_camera.cc
@@ -37,6 +37,10 @@ using Alembic::AbcGeom::IFloatProperty;
using Alembic::AbcGeom::ISampleSelector;
using Alembic::AbcGeom::kWrapExisting;
+namespace blender {
+namespace io {
+namespace alembic {
+
AbcCameraReader::AbcCameraReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
: AbcObjectReader(object, settings)
{
@@ -109,3 +113,7 @@ void AbcCameraReader::readObjectData(Main *bmain, const ISampleSelector &sample_
m_object = BKE_object_add_only_object(bmain, OB_CAMERA, m_object_name.c_str());
m_object->data = bcam;
}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_camera.h b/source/blender/io/alembic/intern/abc_reader_camera.h
index 1d9763b0454..b733269407b 100644
--- a/source/blender/io/alembic/intern/abc_reader_camera.h
+++ b/source/blender/io/alembic/intern/abc_reader_camera.h
@@ -13,16 +13,18 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_READER_CAMERA_H__
-#define __ABC_READER_CAMERA_H__
-
#include "abc_reader_object.h"
+namespace blender {
+namespace io {
+namespace alembic {
+
class AbcCameraReader : public AbcObjectReader {
Alembic::AbcGeom::ICameraSchema m_schema;
@@ -37,4 +39,6 @@ class AbcCameraReader : public AbcObjectReader {
void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
};
-#endif /* __ABC_READER_CAMERA_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_curves.cc b/source/blender/io/alembic/intern/abc_reader_curves.cc
index d5e0b694294..a505dfd654b 100644
--- a/source/blender/io/alembic/intern/abc_reader_curves.cc
+++ b/source/blender/io/alembic/intern/abc_reader_curves.cc
@@ -54,6 +54,10 @@ using Alembic::AbcGeom::IInt16Property;
using Alembic::AbcGeom::ISampleSelector;
using Alembic::AbcGeom::kWrapExisting;
+namespace blender {
+namespace io {
+namespace alembic {
+
AbcCurveReader::AbcCurveReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
: AbcObjectReader(object, settings)
{
@@ -351,3 +355,7 @@ Mesh *AbcCurveReader::read_mesh(Mesh *existing_mesh,
return BKE_mesh_new_nomain_from_curve(m_object);
}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_curves.h b/source/blender/io/alembic/intern/abc_reader_curves.h
index eb0538308f8..7488adb9b24 100644
--- a/source/blender/io/alembic/intern/abc_reader_curves.h
+++ b/source/blender/io/alembic/intern/abc_reader_curves.h
@@ -16,14 +16,12 @@
* The Original Code is Copyright (C) 2016 Kévin Dietrich.
* All rights reserved.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_READER_CURVES_H__
-#define __ABC_READER_CURVES_H__
-
#include "abc_reader_mesh.h"
#include "abc_reader_object.h"
@@ -31,6 +29,10 @@ struct Curve;
#define ABC_CURVE_RESOLUTION_U_PROPNAME "blender:resolution"
+namespace blender {
+namespace io {
+namespace alembic {
+
class AbcCurveReader : public AbcObjectReader {
Alembic::AbcGeom::ICurvesSchema m_curves_schema;
@@ -53,4 +55,6 @@ class AbcCurveReader : public AbcObjectReader {
const Alembic::Abc::ISampleSelector &sample_selector);
};
-#endif /* __ABC_READER_CURVES_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc
index 8b79a3a0aa0..756dde3783c 100644
--- a/source/blender/io/alembic/intern/abc_reader_mesh.cc
+++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc
@@ -32,6 +32,7 @@
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
+#include "BLI_compiler_compat.h"
#include "BLI_math_geom.h"
#include "BKE_main.h"
@@ -59,6 +60,10 @@ using Alembic::AbcGeom::N3fArraySamplePtr;
using Alembic::AbcGeom::UInt32ArraySamplePtr;
using Alembic::AbcGeom::V2fArraySamplePtr;
+namespace blender {
+namespace io {
+namespace alembic {
+
/* NOTE: Alembic's polygon winding order is clockwise, to match with Renderman. */
/* Some helpers for mesh generation */
@@ -339,7 +344,7 @@ static void process_normals(CDStreamConfig &config,
}
}
-ABC_INLINE void read_uvs_params(CDStreamConfig &config,
+BLI_INLINE void read_uvs_params(CDStreamConfig &config,
AbcMeshData &abc_data,
const IV2fGeomParam &uv,
const ISampleSelector &selector)
@@ -714,7 +719,7 @@ void AbcMeshReader::readFaceSetsSample(Main *bmain, Mesh *mesh, const ISampleSel
/* ************************************************************************** */
-ABC_INLINE MEdge *find_edge(MEdge *edges, int totedge, int v1, int v2)
+BLI_INLINE MEdge *find_edge(MEdge *edges, int totedge, int v1, int v2)
{
for (int i = 0, e = totedge; i < e; i++) {
MEdge &edge = edges[i];
@@ -930,3 +935,7 @@ Mesh *AbcSubDReader::read_mesh(Mesh *existing_mesh,
return config.mesh;
}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.h b/source/blender/io/alembic/intern/abc_reader_mesh.h
index bc95c7ec134..363a74b8b5f 100644
--- a/source/blender/io/alembic/intern/abc_reader_mesh.h
+++ b/source/blender/io/alembic/intern/abc_reader_mesh.h
@@ -13,19 +13,21 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_READER_MESH_H__
-#define __ABC_READER_MESH_H__
-
#include "abc_customdata.h"
#include "abc_reader_object.h"
struct Mesh;
+namespace blender {
+namespace io {
+namespace alembic {
+
class AbcMeshReader : public AbcObjectReader {
Alembic::AbcGeom::IPolyMeshSchema m_schema;
@@ -83,4 +85,6 @@ void read_mverts(MVert *mverts,
CDStreamConfig get_config(struct Mesh *mesh);
-#endif /* __ABC_READER_MESH_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_nurbs.cc b/source/blender/io/alembic/intern/abc_reader_nurbs.cc
index 5b9954b3ff6..3ca3f6229ab 100644
--- a/source/blender/io/alembic/intern/abc_reader_nurbs.cc
+++ b/source/blender/io/alembic/intern/abc_reader_nurbs.cc
@@ -44,6 +44,10 @@ using Alembic::AbcGeom::INuPatch;
using Alembic::AbcGeom::INuPatchSchema;
using Alembic::AbcGeom::IObject;
+namespace blender {
+namespace io {
+namespace alembic {
+
AbcNurbsReader::AbcNurbsReader(const IObject &object, ImportSettings &settings)
: AbcObjectReader(object, settings)
{
@@ -222,3 +226,7 @@ void AbcNurbsReader::getNurbsPatches(const IObject &obj)
getNurbsPatches(child);
}
}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_nurbs.h b/source/blender/io/alembic/intern/abc_reader_nurbs.h
index f4284c136fb..738da82885d 100644
--- a/source/blender/io/alembic/intern/abc_reader_nurbs.h
+++ b/source/blender/io/alembic/intern/abc_reader_nurbs.h
@@ -13,16 +13,18 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_READER_NURBS_H__
-#define __ABC_READER_NURBS_H__
-
#include "abc_reader_object.h"
+namespace blender {
+namespace io {
+namespace alembic {
+
class AbcNurbsReader : public AbcObjectReader {
std::vector<std::pair<Alembic::AbcGeom::INuPatchSchema, Alembic::Abc::IObject>> m_schemas;
@@ -37,4 +39,6 @@ class AbcNurbsReader : public AbcObjectReader {
void getNurbsPatches(const Alembic::Abc::IObject &obj);
};
-#endif /* __ABC_READER_NURBS_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_object.cc b/source/blender/io/alembic/intern/abc_reader_object.cc
index e5bd0771a42..39b9cd4c161 100644
--- a/source/blender/io/alembic/intern/abc_reader_object.cc
+++ b/source/blender/io/alembic/intern/abc_reader_object.cc
@@ -41,6 +41,10 @@ using Alembic::AbcGeom::IObject;
using Alembic::AbcGeom::IXform;
using Alembic::AbcGeom::IXformSchema;
+namespace blender {
+namespace io {
+namespace alembic {
+
AbcObjectReader::AbcObjectReader(const IObject &object, ImportSettings &settings)
: m_name(""),
m_object_name(""),
@@ -330,3 +334,7 @@ void AbcObjectReader::decref()
m_refcount--;
BLI_assert(m_refcount >= 0);
}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_object.h b/source/blender/io/alembic/intern/abc_reader_object.h
index dcc2697e0b5..0bde60b06b5 100644
--- a/source/blender/io/alembic/intern/abc_reader_object.h
+++ b/source/blender/io/alembic/intern/abc_reader_object.h
@@ -13,14 +13,12 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_READER_OBJECT_H__
-#define __ABC_READER_OBJECT_H__
-
#include <Alembic/Abc/All.h>
#include <Alembic/AbcGeom/All.h>
@@ -33,6 +31,10 @@ struct Object;
using Alembic::AbcCoreAbstract::chrono_t;
+namespace blender {
+namespace io {
+namespace alembic {
+
struct ImportSettings {
bool do_convert_mat;
float conversion_mat[4][4];
@@ -166,4 +168,6 @@ class AbcObjectReader {
Imath::M44d get_matrix(const Alembic::AbcGeom::IXformSchema &schema, const float time);
-#endif /* __ABC_READER_OBJECT_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_points.cc b/source/blender/io/alembic/intern/abc_reader_points.cc
index c5d08693176..b805da4daa3 100644
--- a/source/blender/io/alembic/intern/abc_reader_points.cc
+++ b/source/blender/io/alembic/intern/abc_reader_points.cc
@@ -43,6 +43,10 @@ using Alembic::AbcGeom::IPoints;
using Alembic::AbcGeom::IPointsSchema;
using Alembic::AbcGeom::ISampleSelector;
+namespace blender {
+namespace io {
+namespace alembic {
+
AbcPointsReader::AbcPointsReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
: AbcObjectReader(object, settings)
{
@@ -153,3 +157,7 @@ struct Mesh *AbcPointsReader::read_mesh(struct Mesh *existing_mesh,
return new_mesh ? new_mesh : existing_mesh;
}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_points.h b/source/blender/io/alembic/intern/abc_reader_points.h
index 99881e091f9..8a970ac35b3 100644
--- a/source/blender/io/alembic/intern/abc_reader_points.h
+++ b/source/blender/io/alembic/intern/abc_reader_points.h
@@ -16,17 +16,19 @@
* The Original Code is Copyright (C) 2016 Kévin Dietrich.
* All rights reserved.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_READER_POINTS_H__
-#define __ABC_READER_POINTS_H__
-
#include "abc_customdata.h"
#include "abc_reader_object.h"
+namespace blender {
+namespace io {
+namespace alembic {
+
class AbcPointsReader : public AbcObjectReader {
Alembic::AbcGeom::IPointsSchema m_schema;
Alembic::AbcGeom::IPointsSchema::Sample m_sample;
@@ -51,4 +53,6 @@ void read_points_sample(const Alembic::AbcGeom::IPointsSchema &schema,
const Alembic::AbcGeom::ISampleSelector &selector,
CDStreamConfig &config);
-#endif /* __ABC_READER_POINTS_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_transform.cc b/source/blender/io/alembic/intern/abc_reader_transform.cc
index 3df391f8432..456d1da2c68 100644
--- a/source/blender/io/alembic/intern/abc_reader_transform.cc
+++ b/source/blender/io/alembic/intern/abc_reader_transform.cc
@@ -29,6 +29,10 @@
using Alembic::Abc::ISampleSelector;
+namespace blender {
+namespace io {
+namespace alembic {
+
AbcEmptyReader::AbcEmptyReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
: AbcObjectReader(object, settings)
{
@@ -72,3 +76,7 @@ void AbcEmptyReader::readObjectData(Main *bmain, const ISampleSelector &UNUSED(s
m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_object_name.c_str());
m_object->data = NULL;
}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_reader_transform.h b/source/blender/io/alembic/intern/abc_reader_transform.h
index 6b4d23c1884..812d3bdfc92 100644
--- a/source/blender/io/alembic/intern/abc_reader_transform.h
+++ b/source/blender/io/alembic/intern/abc_reader_transform.h
@@ -13,18 +13,20 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_READER_TRANSFORM_H__
-#define __ABC_READER_TRANSFORM_H__
-
#include "abc_reader_object.h"
#include <Alembic/AbcGeom/All.h>
+namespace blender {
+namespace io {
+namespace alembic {
+
class AbcEmptyReader : public AbcObjectReader {
Alembic::AbcGeom::IXformSchema m_schema;
@@ -39,4 +41,6 @@ class AbcEmptyReader : public AbcObjectReader {
void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
};
-#endif /* __ABC_READER_TRANSFORM_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_util.cc b/source/blender/io/alembic/intern/abc_util.cc
index 1f3bd2a1aaa..04febd7bfcb 100644
--- a/source/blender/io/alembic/intern/abc_util.cc
+++ b/source/blender/io/alembic/intern/abc_util.cc
@@ -38,6 +38,10 @@
#include "PIL_time.h"
+namespace blender {
+namespace io {
+namespace alembic {
+
std::string get_id_name(const Object *const ob)
{
if (!ob) {
@@ -49,12 +53,16 @@ std::string get_id_name(const Object *const ob)
std::string get_id_name(const ID *const id)
{
- std::string name(id->name + 2);
- std::replace(name.begin(), name.end(), ' ', '_');
- std::replace(name.begin(), name.end(), '.', '_');
- std::replace(name.begin(), name.end(), ':', '_');
+ return get_valid_abc_name(id->name + 2);
+}
- return name;
+std::string get_valid_abc_name(const char *name)
+{
+ std::string name_string(name);
+ std::replace(name_string.begin(), name_string.end(), ' ', '_');
+ std::replace(name_string.begin(), name_string.end(), '.', '_');
+ std::replace(name_string.begin(), name_string.end(), ':', '_');
+ return name_string;
}
/**
@@ -252,3 +260,7 @@ std::ostream &operator<<(std::ostream &os, const SimpleLogger &logger)
os << logger.str();
return os;
}
+
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_util.h b/source/blender/io/alembic/intern/abc_util.h
index 57b4d9800a5..4689173ab5f 100644
--- a/source/blender/io/alembic/intern/abc_util.h
+++ b/source/blender/io/alembic/intern/abc_util.h
@@ -13,23 +13,15 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#pragma once
/** \file
* \ingroup balembic
*/
-#ifndef __ABC_UTIL_H__
-#define __ABC_UTIL_H__
-
#include <Alembic/Abc/All.h>
#include <Alembic/AbcGeom/All.h>
-#ifdef _MSC_VER
-# define ABC_INLINE static __forceinline
-#else
-# define ABC_INLINE static inline
-#endif
-
/**
* \brief The CacheReader struct is only used for anonymous pointers,
* to interface between C and C++ code. This library only creates
@@ -41,14 +33,19 @@ struct CacheReader {
using Alembic::Abc::chrono_t;
-class AbcObjectReader;
-struct ImportSettings;
-
struct ID;
struct Object;
+namespace blender {
+namespace io {
+namespace alembic {
+
+class AbcObjectReader;
+struct ImportSettings;
+
std::string get_id_name(const ID *const id);
std::string get_id_name(const Object *const ob);
+std::string get_valid_abc_name(const char *name);
std::string get_object_dag_path_name(const Object *const ob, Object *dupli_parent);
/* Convert from float to Alembic matrix representations. Does NOT convert from Z-up to Y-up. */
@@ -164,4 +161,6 @@ class SimpleLogger {
*/
std::ostream &operator<<(std::ostream &os, const SimpleLogger &logger);
-#endif /* __ABC_UTIL_H__ */
+} // namespace alembic
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/alembic/intern/abc_writer_archive.cc b/source/blender/io/alembic/intern/abc_writer_archive.cc
deleted file mode 100644
index 40926532f85..00000000000
--- a/source/blender/io/alembic/intern/abc_writer_archive.cc
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup balembic
- */
-
-#include "abc_writer_archive.h"
-
-#include "BKE_blender_version.h"
-
-#include "BLI_path_util.h"
-#include "BLI_string.h"
-
-#include "DNA_scene_types.h"
-
-#ifdef WIN32
-# include "utfconv.h"
-#endif
-
-#include <fstream>
-
-using Alembic::Abc::ErrorHandler;
-using Alembic::Abc::kWrapExisting;
-using Alembic::Abc::OArchive;
-
-/* 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 &scene_name,
- double scene_fps)
-{
- Alembic::Abc::MetaData abc_metadata;
-
- abc_metadata.set(Alembic::Abc::kApplicationNameKey, "Blender");
- abc_metadata.set(Alembic::Abc::kUserDescriptionKey, scene_name);
- abc_metadata.set("blender_version", std::string("v") + BKE_blender_version_string());
- abc_metadata.set("FramesPerTimeUnit", std::to_string(scene_fps));
-
- 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';
- }
-
- abc_metadata.set(Alembic::Abc::kDateWrittenKey, buffer);
-
- ErrorHandler::Policy policy = ErrorHandler::kThrowPolicy;
- Alembic::AbcCoreOgawa::WriteArchive archive_writer;
- return OArchive(archive_writer(ostream, abc_metadata), kWrapExisting, policy);
-}
-
-ArchiveWriter::ArchiveWriter(const char *filename,
- const std::string &abc_scene_name,
- const Scene *scene)
-{
- /* Use stream to support unicode character paths on Windows. */
-#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, abc_scene_name, FPS);
-}
-
-OArchive &ArchiveWriter::archive()
-{
- return m_archive;
-}
diff --git a/source/blender/io/alembic/intern/abc_writer_camera.cc b/source/blender/io/alembic/intern/abc_writer_camera.cc
deleted file mode 100644
index 07ae81e584f..00000000000
--- a/source/blender/io/alembic/intern/abc_writer_camera.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup balembic
- */
-
-#include "abc_writer_camera.h"
-#include "abc_writer_transform.h"
-
-#include "DNA_camera_types.h"
-#include "DNA_object_types.h"
-
-using Alembic::AbcGeom::OCamera;
-using Alembic::AbcGeom::OFloatProperty;
-
-AbcCameraWriter::AbcCameraWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings)
- : AbcObjectWriter(ob, time_sampling, settings, parent)
-{
- OCamera camera(parent->alembicXform(), m_name, m_time_sampling);
- m_camera_schema = camera.getSchema();
-
- m_custom_data_container = m_camera_schema.getUserProperties();
- m_stereo_distance = OFloatProperty(m_custom_data_container, "stereoDistance", m_time_sampling);
- m_eye_separation = OFloatProperty(m_custom_data_container, "eyeSeparation", m_time_sampling);
-}
-
-void AbcCameraWriter::do_write()
-{
- Camera *cam = static_cast<Camera *>(m_object->data);
-
- m_stereo_distance.set(cam->stereo.convergence_distance);
- m_eye_separation.set(cam->stereo.interocular_distance);
-
- const double apperture_x = cam->sensor_x / 10.0;
- const double apperture_y = cam->sensor_y / 10.0;
- const double film_aspect = apperture_x / apperture_y;
-
- m_camera_sample.setFocalLength(cam->lens);
- m_camera_sample.setHorizontalAperture(apperture_x);
- m_camera_sample.setVerticalAperture(apperture_y);
- m_camera_sample.setHorizontalFilmOffset(apperture_x * cam->shiftx);
- m_camera_sample.setVerticalFilmOffset(apperture_y * cam->shifty * film_aspect);
- m_camera_sample.setNearClippingPlane(cam->clip_start);
- m_camera_sample.setFarClippingPlane(cam->clip_end);
-
- if (cam->dof.focus_object) {
- Imath::V3f v(m_object->loc[0] - cam->dof.focus_object->loc[0],
- m_object->loc[1] - cam->dof.focus_object->loc[1],
- m_object->loc[2] - cam->dof.focus_object->loc[2]);
- m_camera_sample.setFocusDistance(v.length());
- }
- else {
- m_camera_sample.setFocusDistance(cam->dof.focus_distance);
- }
-
- /* Blender camera does not have an fstop param, so try to find a custom prop
- * instead. */
- m_camera_sample.setFStop(cam->dof.aperture_fstop);
-
- m_camera_sample.setLensSqueezeRatio(1.0);
- m_camera_schema.set(m_camera_sample);
-}
diff --git a/source/blender/io/alembic/intern/abc_writer_mball.cc b/source/blender/io/alembic/intern/abc_writer_mball.cc
deleted file mode 100644
index 3593acf18b0..00000000000
--- a/source/blender/io/alembic/intern/abc_writer_mball.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup balembic
- */
-
-#include "abc_writer_mball.h"
-#include "abc_writer_mesh.h"
-
-#include "DNA_mesh_types.h"
-#include "DNA_meta_types.h"
-#include "DNA_object_types.h"
-
-#include "BKE_displist.h"
-#include "BKE_lib_id.h"
-#include "BKE_mball.h"
-#include "BKE_mesh.h"
-#include "BKE_object.h"
-
-#include "BLI_utildefines.h"
-
-AbcMBallWriter::AbcMBallWriter(Main *bmain,
- Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings)
- : AbcGenericMeshWriter(ob, parent, time_sampling, settings), m_bmain(bmain)
-{
- m_is_animated = isAnimated();
-}
-
-AbcMBallWriter::~AbcMBallWriter()
-{
-}
-
-bool AbcMBallWriter::isAnimated() const
-{
- return true;
-}
-
-Mesh *AbcMBallWriter::getEvaluatedMesh(Scene * /*scene_eval*/, Object *ob_eval, bool &r_needsfree)
-{
- Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
- if (mesh_eval != NULL) {
- /* Mesh_eval only exists when generative modifiers are in use. */
- r_needsfree = false;
- return mesh_eval;
- }
- r_needsfree = true;
-
- /* The approach below is copied from BKE_mesh_new_from_object() */
- Mesh *tmpmesh = BKE_mesh_add(m_bmain, ((ID *)m_object->data)->name + 2);
- BLI_assert(tmpmesh != NULL);
-
- /* BKE_mesh_add gives us a user count we don't need */
- id_us_min(&tmpmesh->id);
-
- ListBase disp = {NULL, NULL};
- /* TODO(sergey): This is gonna to work for until Depsgraph
- * only contains for_render flag. As soon as CoW is
- * implemented, this is to be rethought.
- */
- BKE_displist_make_mball_forRender(m_settings.depsgraph, m_settings.scene, m_object, &disp);
- BKE_mesh_from_metaball(&disp, tmpmesh);
- BKE_displist_free(&disp);
-
- BKE_mesh_texspace_copy_from_object(tmpmesh, m_object);
-
- return tmpmesh;
-}
-
-void AbcMBallWriter::freeEvaluatedMesh(struct Mesh *mesh)
-{
- BKE_id_free(m_bmain, mesh);
-}
-
-bool AbcMBallWriter::isBasisBall(Scene *scene, Object *ob)
-{
- Object *basis_ob = BKE_mball_basis_find(scene, ob);
- return ob == basis_ob;
-}
diff --git a/source/blender/io/alembic/intern/abc_writer_mball.h b/source/blender/io/alembic/intern/abc_writer_mball.h
deleted file mode 100644
index e3ac1e69cae..00000000000
--- a/source/blender/io/alembic/intern/abc_writer_mball.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup balembic
- */
-
-#ifndef __ABC_WRITER_MBALL_H__
-#define __ABC_WRITER_MBALL_H__
-
-#include "abc_writer_mesh.h"
-#include "abc_writer_object.h"
-
-struct Main;
-struct Object;
-
-/* AbcMBallWriter converts the metaballs to meshes at every frame,
- * and defers to AbcGenericMeshWriter to perform the writing
- * to the Alembic file. Only the basis balls are exported, as this
- * results in the entire shape as one mesh. */
-class AbcMBallWriter : public AbcGenericMeshWriter {
- Main *m_bmain;
-
- public:
- explicit AbcMBallWriter(Main *bmain,
- Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings);
-
- ~AbcMBallWriter();
-
- static bool isBasisBall(Scene *scene, Object *ob);
-
- protected:
- Mesh *getEvaluatedMesh(Scene *scene_eval, Object *ob_eval, bool &r_needsfree) override;
- void freeEvaluatedMesh(struct Mesh *mesh) override;
-
- private:
- bool isAnimated() const override;
-};
-
-#endif /* __ABC_WRITER_MBALL_H__ */
diff --git a/source/blender/io/alembic/intern/abc_writer_mesh.h b/source/blender/io/alembic/intern/abc_writer_mesh.h
deleted file mode 100644
index 9152a370e4f..00000000000
--- a/source/blender/io/alembic/intern/abc_writer_mesh.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup balembic
- */
-
-#ifndef __ABC_WRITER_MESH_H__
-#define __ABC_WRITER_MESH_H__
-
-#include "abc_customdata.h"
-#include "abc_writer_object.h"
-
-struct Mesh;
-struct ModifierData;
-
-/* Writer for Alembic meshes. Does not assume the object is a mesh object. */
-class AbcGenericMeshWriter : public AbcObjectWriter {
- protected:
- Alembic::AbcGeom::OPolyMeshSchema m_mesh_schema;
- Alembic::AbcGeom::OPolyMeshSchema::Sample m_mesh_sample;
-
- Alembic::AbcGeom::OSubDSchema m_subdiv_schema;
- Alembic::AbcGeom::OSubDSchema::Sample m_subdiv_sample;
-
- Alembic::Abc::OArrayProperty m_mat_indices;
-
- bool m_is_animated;
- ModifierData *m_subsurf_mod;
-
- CDStreamConfig m_custom_data_config;
-
- bool m_is_liquid;
- bool m_is_subd;
-
- public:
- AbcGenericMeshWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings);
-
- ~AbcGenericMeshWriter();
- void setIsAnimated(bool is_animated);
-
- protected:
- virtual void do_write();
- virtual bool isAnimated() const;
- virtual Mesh *getEvaluatedMesh(Scene *scene_eval, Object *ob_eval, bool &r_needsfree) = 0;
- virtual void freeEvaluatedMesh(struct Mesh *mesh);
-
- Mesh *getFinalMesh(bool &r_needsfree);
-
- void writeMesh(struct Mesh *mesh);
- void writeSubD(struct Mesh *mesh);
-
- void writeArbGeoParams(struct Mesh *mesh);
- void getGeoGroups(struct Mesh *mesh, std::map<std::string, std::vector<int32_t>> &geoGroups);
-
- /* fluid surfaces support */
- void getVelocities(struct Mesh *mesh, std::vector<Imath::V3f> &vels);
-
- template<typename Schema> void writeFaceSets(struct Mesh *mesh, Schema &schema);
-};
-
-class AbcMeshWriter : public AbcGenericMeshWriter {
- public:
- AbcMeshWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings);
-
- ~AbcMeshWriter();
-
- protected:
- virtual Mesh *getEvaluatedMesh(Scene *scene_eval, Object *ob_eval, bool &r_needsfree) override;
-};
-
-#endif /* __ABC_WRITER_MESH_H__ */
diff --git a/source/blender/io/alembic/intern/abc_writer_object.cc b/source/blender/io/alembic/intern/abc_writer_object.cc
deleted file mode 100644
index f4a3587f54d..00000000000
--- a/source/blender/io/alembic/intern/abc_writer_object.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup balembic
- */
-
-#include "abc_writer_object.h"
-
-#include "DNA_object_types.h"
-
-#include "BKE_object.h"
-
-AbcObjectWriter::AbcObjectWriter(Object *ob,
- uint32_t time_sampling,
- ExportSettings &settings,
- AbcObjectWriter *parent)
- : m_object(ob), m_settings(settings), m_time_sampling(time_sampling), m_first_frame(true)
-{
- m_name = get_id_name(m_object) + "Shape";
-
- if (parent) {
- parent->addChild(this);
- }
-}
-
-AbcObjectWriter::~AbcObjectWriter()
-{
-}
-
-void AbcObjectWriter::addChild(AbcObjectWriter *child)
-{
- m_children.push_back(child);
-}
-
-Imath::Box3d AbcObjectWriter::bounds()
-{
- BoundBox *bb = BKE_object_boundbox_get(this->m_object);
-
- if (!bb) {
- if (this->m_object->type != OB_CAMERA) {
- ABC_LOG(m_settings.logger) << "Bounding box is null!\n";
- }
-
- return Imath::Box3d();
- }
-
- /* Convert Z-up to Y-up. This also changes which vector goes into which min/max property. */
- this->m_bounds.min.x = bb->vec[0][0];
- this->m_bounds.min.y = bb->vec[0][2];
- this->m_bounds.min.z = -bb->vec[6][1];
-
- this->m_bounds.max.x = bb->vec[6][0];
- this->m_bounds.max.y = bb->vec[6][2];
- this->m_bounds.max.z = -bb->vec[0][1];
-
- return this->m_bounds;
-}
-
-void AbcObjectWriter::write()
-{
- do_write();
- m_first_frame = false;
-}
diff --git a/source/blender/io/alembic/intern/abc_writer_object.h b/source/blender/io/alembic/intern/abc_writer_object.h
deleted file mode 100644
index 830c4aee903..00000000000
--- a/source/blender/io/alembic/intern/abc_writer_object.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup balembic
- */
-
-#ifndef __ABC_WRITER_OBJECT_H__
-#define __ABC_WRITER_OBJECT_H__
-
-#include <Alembic/Abc/All.h>
-#include <Alembic/AbcGeom/All.h>
-
-#include "abc_exporter.h"
-
-#include "DNA_ID.h"
-
-class AbcTransformWriter;
-
-struct Main;
-struct Object;
-
-class AbcObjectWriter {
- protected:
- Object *m_object;
- ExportSettings &m_settings;
-
- uint32_t m_time_sampling;
-
- Imath::Box3d m_bounds;
- std::vector<AbcObjectWriter *> m_children;
-
- std::vector<std::pair<std::string, IDProperty *>> m_props;
-
- bool m_first_frame;
- std::string m_name;
-
- public:
- AbcObjectWriter(Object *ob,
- uint32_t time_sampling,
- ExportSettings &settings,
- AbcObjectWriter *parent = NULL);
-
- virtual ~AbcObjectWriter();
-
- void addChild(AbcObjectWriter *child);
-
- virtual Imath::Box3d bounds();
-
- void write();
-
- private:
- virtual void do_write() = 0;
-};
-
-#endif /* __ABC_WRITER_OBJECT_H__ */
diff --git a/source/blender/io/alembic/intern/abc_writer_points.cc b/source/blender/io/alembic/intern/abc_writer_points.cc
deleted file mode 100644
index ac663b62693..00000000000
--- a/source/blender/io/alembic/intern/abc_writer_points.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup balembic
- */
-
-#include "abc_writer_points.h"
-#include "abc_util.h"
-#include "abc_writer_mesh.h"
-#include "abc_writer_transform.h"
-
-#include "DNA_object_types.h"
-#include "DNA_particle_types.h"
-
-#include "BKE_lattice.h"
-#include "BKE_particle.h"
-
-#include "BLI_math.h"
-
-#include "DEG_depsgraph_query.h"
-
-using Alembic::AbcGeom::kVertexScope;
-using Alembic::AbcGeom::OPoints;
-using Alembic::AbcGeom::OPointsSchema;
-
-/* ************************************************************************** */
-
-AbcPointsWriter::AbcPointsWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings,
- ParticleSystem *psys)
- : AbcObjectWriter(ob, time_sampling, settings, parent)
-{
- m_psys = psys;
-
- OPoints points(parent->alembicXform(), psys->name, m_time_sampling);
- m_schema = points.getSchema();
-}
-
-void AbcPointsWriter::do_write()
-{
- if (!m_psys) {
- return;
- }
-
- std::vector<Imath::V3f> points;
- std::vector<Imath::V3f> velocities;
- std::vector<float> widths;
- std::vector<uint64_t> ids;
-
- ParticleKey state;
-
- ParticleSimulationData sim;
- sim.depsgraph = m_settings.depsgraph;
- sim.scene = m_settings.scene;
- sim.ob = m_object;
- sim.psys = m_psys;
-
- m_psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
-
- uint64_t index = 0;
- for (int p = 0; p < m_psys->totpart; p++) {
- float pos[3], vel[3];
-
- if (m_psys->particles[p].flag & (PARS_NO_DISP | PARS_UNEXIST)) {
- continue;
- }
-
- state.time = DEG_get_ctime(m_settings.depsgraph);
-
- if (psys_get_particle_state(&sim, p, &state, 0) == 0) {
- continue;
- }
-
- /* location */
- mul_v3_m4v3(pos, m_object->imat, state.co);
-
- /* velocity */
- sub_v3_v3v3(vel, state.co, m_psys->particles[p].prev_state.co);
-
- /* Convert Z-up to Y-up. */
- points.push_back(Imath::V3f(pos[0], pos[2], -pos[1]));
- velocities.push_back(Imath::V3f(vel[0], vel[2], -vel[1]));
- widths.push_back(m_psys->particles[p].size);
- ids.push_back(index++);
- }
-
- if (m_psys->lattice_deform_data) {
- BKE_lattice_deform_data_destroy(m_psys->lattice_deform_data);
- m_psys->lattice_deform_data = NULL;
- }
-
- Alembic::Abc::P3fArraySample psample(points);
- Alembic::Abc::UInt64ArraySample idsample(ids);
- Alembic::Abc::V3fArraySample vsample(velocities);
- Alembic::Abc::FloatArraySample wsample_array(widths);
- Alembic::AbcGeom::OFloatGeomParam::Sample wsample(wsample_array, kVertexScope);
-
- m_sample = OPointsSchema::Sample(psample, idsample, vsample, wsample);
- m_sample.setSelfBounds(bounds());
-
- m_schema.set(m_sample);
-}
diff --git a/source/blender/io/alembic/intern/abc_writer_points.h b/source/blender/io/alembic/intern/abc_writer_points.h
deleted file mode 100644
index 184a363ae6b..00000000000
--- a/source/blender/io/alembic/intern/abc_writer_points.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup balembic
- */
-
-#ifndef __ABC_WRITER_POINTS_H__
-#define __ABC_WRITER_POINTS_H__
-
-#include "abc_customdata.h"
-#include "abc_writer_object.h"
-
-struct ParticleSystem;
-
-/* ************************************************************************** */
-
-class AbcPointsWriter : public AbcObjectWriter {
- Alembic::AbcGeom::OPointsSchema m_schema;
- Alembic::AbcGeom::OPointsSchema::Sample m_sample;
- ParticleSystem *m_psys;
-
- public:
- AbcPointsWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings,
- ParticleSystem *psys);
-
- void do_write();
-};
-
-#endif /* __ABC_WRITER_POINTS_H__ */
diff --git a/source/blender/io/alembic/intern/abc_writer_transform.cc b/source/blender/io/alembic/intern/abc_writer_transform.cc
deleted file mode 100644
index 1ec7db0a1c6..00000000000
--- a/source/blender/io/alembic/intern/abc_writer_transform.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup balembic
- */
-
-#include "abc_writer_transform.h"
-#include "abc_axis_conversion.h"
-
-#include <OpenEXR/ImathBoxAlgo.h>
-
-#include "DNA_object_types.h"
-
-#include "BLI_math.h"
-
-#include "DEG_depsgraph_query.h"
-
-using Alembic::AbcGeom::OObject;
-using Alembic::AbcGeom::OXform;
-
-AbcTransformWriter::AbcTransformWriter(Object *ob,
- const OObject &abc_parent,
- AbcTransformWriter *parent,
- unsigned int time_sampling,
- ExportSettings &settings)
- : AbcObjectWriter(ob, time_sampling, settings, parent), m_proxy_from(NULL)
-{
- m_is_animated = hasAnimation(m_object);
-
- if (!m_is_animated) {
- time_sampling = 0;
- }
-
- m_xform = OXform(abc_parent, get_id_name(m_object), time_sampling);
- m_schema = m_xform.getSchema();
-
- /* Blender objects can't have a parent without inheriting the transform. */
- m_inherits_xform = parent != NULL;
-}
-
-void AbcTransformWriter::do_write()
-{
- Object *ob_eval = DEG_get_evaluated_object(m_settings.depsgraph, m_object);
-
- if (m_first_frame) {
- m_visibility = Alembic::AbcGeom::CreateVisibilityProperty(
- m_xform, m_xform.getSchema().getTimeSampling());
- }
-
- m_visibility.set(!(ob_eval->restrictflag & OB_RESTRICT_VIEWPORT));
-
- if (!m_first_frame && !m_is_animated) {
- return;
- }
-
- float yup_mat[4][4];
- create_transform_matrix(
- ob_eval, yup_mat, m_inherits_xform ? ABC_MATRIX_LOCAL : ABC_MATRIX_WORLD, m_proxy_from);
-
- /* If the parent is a camera, undo its to-Maya rotation (see below). */
- bool is_root_object = !m_inherits_xform || ob_eval->parent == nullptr;
- if (!is_root_object && ob_eval->parent->type == OB_CAMERA) {
- float rot_mat[4][4];
- axis_angle_to_mat4_single(rot_mat, 'X', M_PI_2);
- mul_m4_m4m4(yup_mat, rot_mat, yup_mat);
- }
-
- /* If the object is a camera, apply an extra rotation to Maya camera orientation. */
- if (ob_eval->type == OB_CAMERA) {
- float rot_mat[4][4];
- axis_angle_to_mat4_single(rot_mat, 'X', -M_PI_2);
- mul_m4_m4m4(yup_mat, yup_mat, rot_mat);
- }
-
- if (is_root_object) {
- /* Only apply scaling to root objects, parenting will propagate it. */
- float scale_mat[4][4];
- scale_m4_fl(scale_mat, m_settings.global_scale);
- scale_mat[3][3] = m_settings.global_scale; /* also scale translation */
- mul_m4_m4m4(yup_mat, yup_mat, scale_mat);
- yup_mat[3][3] /= m_settings.global_scale; /* normalise the homogeneous component */
- }
-
- m_matrix = convert_matrix_datatype(yup_mat);
- m_sample.setMatrix(m_matrix);
- m_sample.setInheritsXforms(m_inherits_xform);
- m_schema.set(m_sample);
-}
-
-Imath::Box3d AbcTransformWriter::bounds()
-{
- Imath::Box3d bounds;
-
- for (int i = 0; i < m_children.size(); i++) {
- Imath::Box3d box(m_children[i]->bounds());
- bounds.extendBy(box);
- }
-
- return Imath::transform(bounds, m_matrix);
-}
-
-bool AbcTransformWriter::hasAnimation(Object * /*ob*/) const
-{
- return true;
-}
diff --git a/source/blender/io/alembic/intern/abc_writer_transform.h b/source/blender/io/alembic/intern/abc_writer_transform.h
deleted file mode 100644
index 4397b220761..00000000000
--- a/source/blender/io/alembic/intern/abc_writer_transform.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.
- */
-
-/** \file
- * \ingroup balembic
- */
-
-#ifndef __ABC_WRITER_TRANSFORM_H__
-#define __ABC_WRITER_TRANSFORM_H__
-
-#include "abc_writer_object.h"
-
-#include <Alembic/AbcGeom/All.h>
-
-class AbcTransformWriter : public AbcObjectWriter {
- Alembic::AbcGeom::OXform m_xform;
- Alembic::AbcGeom::OXformSchema m_schema;
- Alembic::AbcGeom::XformSample m_sample;
- Alembic::AbcGeom::OVisibilityProperty m_visibility;
- Alembic::Abc::M44d m_matrix;
-
- bool m_is_animated;
- bool m_inherits_xform;
-
- public:
- Object *m_proxy_from;
-
- public:
- AbcTransformWriter(Object *ob,
- const Alembic::AbcGeom::OObject &abc_parent,
- AbcTransformWriter *parent,
- unsigned int time_sampling,
- ExportSettings &settings);
-
- Alembic::AbcGeom::OXform &alembicXform()
- {
- return m_xform;
- }
- virtual Imath::Box3d bounds();
-
- private:
- virtual void do_write();
-
- bool hasAnimation(Object *ob) const;
-};
-
-#endif /* __ABC_WRITER_TRANSFORM_H__ */
diff --git a/source/blender/io/alembic/intern/alembic_capi.cc b/source/blender/io/alembic/intern/alembic_capi.cc
index a30b15fee5f..5932791ecf4 100644
--- a/source/blender/io/alembic/intern/alembic_capi.cc
+++ b/source/blender/io/alembic/intern/alembic_capi.cc
@@ -30,13 +30,6 @@
#include "abc_reader_points.h"
#include "abc_reader_transform.h"
#include "abc_util.h"
-#include "abc_writer_camera.h"
-#include "abc_writer_curves.h"
-#include "abc_writer_hair.h"
-#include "abc_writer_mesh.h"
-#include "abc_writer_nurbs.h"
-#include "abc_writer_points.h"
-#include "abc_writer_transform.h"
#include "MEM_guardedalloc.h"
@@ -58,12 +51,15 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+#include "ED_undo.h"
+
/* SpaceType struct has a member called 'new' which obviously conflicts with C++
* so temporarily redefining the new keyword to make it compile. */
#define new extern_new
#include "BKE_screen.h"
#undef new
+#include "BLI_compiler_compat.h"
#include "BLI_fileops.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
@@ -74,48 +70,33 @@
#include "WM_api.h"
#include "WM_types.h"
-using Alembic::Abc::Int32ArraySamplePtr;
using Alembic::Abc::ObjectHeader;
-
-using Alembic::AbcGeom::kWrapExisting;
-using Alembic::AbcGeom::MetaData;
-using Alembic::AbcGeom::P3fArraySamplePtr;
-
using Alembic::AbcGeom::ICamera;
-using Alembic::AbcGeom::ICompoundProperty;
using Alembic::AbcGeom::ICurves;
-using Alembic::AbcGeom::ICurvesSchema;
using Alembic::AbcGeom::IFaceSet;
using Alembic::AbcGeom::ILight;
-using Alembic::AbcGeom::IN3fArrayProperty;
-using Alembic::AbcGeom::IN3fGeomParam;
using Alembic::AbcGeom::INuPatch;
using Alembic::AbcGeom::IObject;
using Alembic::AbcGeom::IPoints;
-using Alembic::AbcGeom::IPointsSchema;
using Alembic::AbcGeom::IPolyMesh;
-using Alembic::AbcGeom::IPolyMeshSchema;
using Alembic::AbcGeom::ISampleSelector;
using Alembic::AbcGeom::ISubD;
-using Alembic::AbcGeom::IV2fGeomParam;
using Alembic::AbcGeom::IXform;
-using Alembic::AbcGeom::IXformSchema;
-using Alembic::AbcGeom::N3fArraySamplePtr;
-using Alembic::AbcGeom::V3fArraySamplePtr;
-using Alembic::AbcGeom::XformSample;
-
+using Alembic::AbcGeom::MetaData;
using Alembic::AbcMaterial::IMaterial;
+using namespace blender::io::alembic;
+
struct AbcArchiveHandle {
int unused;
};
-ABC_INLINE ArchiveReader *archive_from_handle(AbcArchiveHandle *handle)
+BLI_INLINE ArchiveReader *archive_from_handle(AbcArchiveHandle *handle)
{
return reinterpret_cast<ArchiveReader *>(handle);
}
-ABC_INLINE AbcArchiveHandle *handle_from_archive(ArchiveReader *archive)
+BLI_INLINE AbcArchiveHandle *handle_from_archive(ArchiveReader *archive)
{
return reinterpret_cast<AbcArchiveHandle *>(archive);
}
@@ -225,195 +206,6 @@ static void find_iobject(const IObject &object, IObject &ret, const std::string
ret = tmp;
}
-struct ExportJobData {
- ViewLayer *view_layer;
- Main *bmain;
- wmWindowManager *wm;
-
- char filename[1024];
- ExportSettings settings;
-
- short *stop;
- short *do_update;
- float *progress;
-
- bool was_canceled;
- bool export_ok;
-};
-
-static void export_startjob(void *customdata, short *stop, short *do_update, float *progress)
-{
- ExportJobData *data = static_cast<ExportJobData *>(customdata);
-
- data->stop = stop;
- data->do_update = do_update;
- data->progress = progress;
-
- /* XXX annoying hack: needed to prevent data corruption when changing
- * scene frame in separate threads
- */
- G.is_rendering = true;
- WM_set_locked_interface(data->wm, true);
- G.is_break = false;
-
- DEG_graph_build_from_view_layer(
- data->settings.depsgraph, data->bmain, data->settings.scene, data->view_layer);
- BKE_scene_graph_update_tagged(data->settings.depsgraph, data->bmain);
-
- try {
- AbcExporter exporter(data->bmain, data->filename, data->settings);
-
- Scene *scene = data->settings.scene; /* for the CFRA macro */
- const int orig_frame = CFRA;
-
- data->was_canceled = false;
- exporter(do_update, progress, &data->was_canceled);
-
- if (CFRA != orig_frame) {
- CFRA = orig_frame;
-
- BKE_scene_graph_update_for_newframe(data->settings.depsgraph, data->bmain);
- }
-
- data->export_ok = !data->was_canceled;
- }
- catch (const std::exception &e) {
- ABC_LOG(data->settings.logger) << "Abc Export error: " << e.what() << '\n';
- }
- catch (...) {
- ABC_LOG(data->settings.logger) << "Abc Export: unknown error...\n";
- }
-}
-
-static void export_endjob(void *customdata)
-{
- ExportJobData *data = static_cast<ExportJobData *>(customdata);
-
- DEG_graph_free(data->settings.depsgraph);
-
- if (data->was_canceled && BLI_exists(data->filename)) {
- BLI_delete(data->filename, false, false);
- }
-
- std::string log = data->settings.logger.str();
- if (!log.empty()) {
- std::cerr << log;
- WM_report(RPT_ERROR, "Errors occurred during the export, look in the console to know more...");
- }
-
- G.is_rendering = false;
- WM_set_locked_interface(data->wm, false);
-}
-
-bool ABC_export(Scene *scene,
- bContext *C,
- const char *filepath,
- const struct AlembicExportParams *params,
- bool as_background_job)
-{
- ExportJobData *job = static_cast<ExportJobData *>(
- MEM_mallocN(sizeof(ExportJobData), "ExportJobData"));
-
- job->view_layer = CTX_data_view_layer(C);
- job->bmain = CTX_data_main(C);
- job->wm = CTX_wm_manager(C);
- job->export_ok = false;
- BLI_strncpy(job->filename, filepath, 1024);
-
- /* Alright, alright, alright....
- *
- * ExportJobData contains an ExportSettings containing a SimpleLogger.
- *
- * Since ExportJobData is a C-style struct dynamically allocated with
- * MEM_mallocN (see above), its constructor is never called, therefore the
- * ExportSettings constructor is not called which implies that the
- * SimpleLogger one is not called either. SimpleLogger in turn does not call
- * the constructor of its data members which ultimately means that its
- * std::ostringstream member has a NULL pointer. To be able to properly use
- * the stream's operator<<, the pointer needs to be set, therefore we have
- * to properly construct everything. And this is done using the placement
- * new operator as here below. It seems hackish, but I'm too lazy to
- * do bigger refactor and maybe there is a better way which does not involve
- * hardcore refactoring. */
- new (&job->settings) ExportSettings();
- job->settings.scene = scene;
- job->settings.depsgraph = DEG_graph_new(job->bmain, scene, job->view_layer, DAG_EVAL_RENDER);
-
- /* TODO(Sybren): for now we only export the active scene layer.
- * Later in the 2.8 development process this may be replaced by using
- * a specific collection for Alembic I/O, which can then be toggled
- * between "real" objects and cached Alembic files. */
- job->settings.view_layer = job->view_layer;
-
- job->settings.frame_start = params->frame_start;
- job->settings.frame_end = params->frame_end;
- job->settings.frame_samples_xform = params->frame_samples_xform;
- job->settings.frame_samples_shape = params->frame_samples_shape;
- job->settings.shutter_open = params->shutter_open;
- job->settings.shutter_close = params->shutter_close;
-
- /* TODO(Sybren): For now this is ignored, until we can get selection
- * detection working through Base pointers (instead of ob->flags). */
- job->settings.selected_only = params->selected_only;
-
- job->settings.export_face_sets = params->face_sets;
- job->settings.export_normals = params->normals;
- job->settings.export_uvs = params->uvs;
- job->settings.export_vcols = params->vcolors;
- job->settings.export_hair = params->export_hair;
- job->settings.export_particles = params->export_particles;
- job->settings.apply_subdiv = params->apply_subdiv;
- job->settings.curves_as_mesh = params->curves_as_mesh;
- job->settings.flatten_hierarchy = params->flatten_hierarchy;
-
- /* TODO(Sybren): visible_layer & renderable only is ignored for now,
- * to be replaced with collections later in the 2.8 dev process
- * (also see note above). */
- job->settings.visible_objects_only = params->visible_objects_only;
- job->settings.renderable_only = params->renderable_only;
-
- job->settings.use_subdiv_schema = params->use_subdiv_schema;
- 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);
- }
-
- bool export_ok = false;
- if (as_background_job) {
- wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
- CTX_wm_window(C),
- job->settings.scene,
- "Alembic Export",
- WM_JOB_PROGRESS,
- WM_JOB_TYPE_ALEMBIC);
-
- /* setup job */
- WM_jobs_customdata_set(wm_job, job, MEM_freeN);
- WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME);
- WM_jobs_callbacks(wm_job, export_startjob, NULL, NULL, export_endjob);
-
- WM_jobs_start(CTX_wm_manager(C), wm_job);
- }
- else {
- /* Fake a job context, so that we don't need NULL pointer checks while exporting. */
- short stop = 0, do_update = 0;
- float progress = 0.f;
-
- export_startjob(job, &stop, &do_update, &progress);
- export_endjob(job);
- export_ok = job->export_ok;
-
- MEM_freeN(job);
- }
-
- return export_ok;
-}
-
/* ********************** Import file ********************** */
/**
@@ -622,6 +414,7 @@ enum {
};
struct ImportJobData {
+ bContext *C;
Main *bmain;
Scene *scene;
ViewLayer *view_layer;
@@ -640,6 +433,7 @@ struct ImportJobData {
char error_code;
bool was_cancelled;
bool import_ok;
+ bool is_background_job;
};
static void import_startjob(void *user_data, short *stop, short *do_update, float *progress)
@@ -823,6 +617,12 @@ static void import_endjob(void *user_data)
DEG_id_tag_update(&data->scene->id, ID_RECALC_BASE_FLAGS);
DEG_relations_tag_update(data->bmain);
+
+ if (data->is_background_job) {
+ /* Blender already returned from the import operator, so we need to store our own extra undo
+ * step. */
+ ED_undo_push(data->C, "Alembic Import Finished");
+ }
}
for (iter = data->readers.begin(); iter != data->readers.end(); ++iter) {
@@ -868,6 +668,7 @@ bool ABC_import(bContext *C,
{
/* Using new here since MEM_* functions do not call constructor to properly initialize data. */
ImportJobData *job = new ImportJobData();
+ job->C = C;
job->bmain = CTX_data_main(C);
job->scene = CTX_data_scene(C);
job->view_layer = CTX_data_view_layer(C);
@@ -884,6 +685,7 @@ bool ABC_import(bContext *C,
job->error_code = ABC_NO_ERROR;
job->was_cancelled = false;
job->archive = NULL;
+ job->is_background_job = as_background_job;
G.is_break = false;
diff --git a/source/blender/io/collada/AnimationImporter.cpp b/source/blender/io/collada/AnimationImporter.cpp
index edac84e2aaa..1de86425521 100644
--- a/source/blender/io/collada/AnimationImporter.cpp
+++ b/source/blender/io/collada/AnimationImporter.cpp
@@ -344,9 +344,11 @@ bool AnimationImporter::write_animation_list(const COLLADAFW::AnimationList *ani
return true;
}
-/* \todo refactor read_node_transform to not automatically apply anything,
+/**
+ * \todo refactor read_node_transform to not automatically apply anything,
* but rather return the transform matrix, so caller can do with it what is
- * necessary. Same for \ref get_node_mat */
+ * necessary. Same for \ref get_node_mat
+ */
void AnimationImporter::read_node_transform(COLLADAFW::Node *node, Object *ob)
{
float mat[4][4];
diff --git a/source/blender/io/collada/BCMath.cpp b/source/blender/io/collada/BCMath.cpp
index ec9977c1469..e8765fa2bcd 100644
--- a/source/blender/io/collada/BCMath.cpp
+++ b/source/blender/io/collada/BCMath.cpp
@@ -17,6 +17,8 @@
* All rights reserved.
*/
+#include "BLI_utildefines.h"
+
#include "BCMath.h"
#include "BlenderContext.h"
diff --git a/source/blender/io/collada/ImageExporter.cpp b/source/blender/io/collada/ImageExporter.cpp
index 1c897e37a4a..51d753db03f 100644
--- a/source/blender/io/collada/ImageExporter.cpp
+++ b/source/blender/io/collada/ImageExporter.cpp
@@ -55,7 +55,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
ImBuf *imbuf = BKE_image_acquire_ibuf(image, NULL, NULL);
if (!imbuf) {
- fprintf(stderr, "Collada export: image does not exist:\n%s\n", image->name);
+ fprintf(stderr, "Collada export: image does not exist:\n%s\n", image->filepath);
return;
}
@@ -104,7 +104,7 @@ void ImagesExporter::export_UV_Image(Image *image, bool use_copies)
else {
/* make absolute source path */
- BLI_strncpy(source_path, image->name, sizeof(source_path));
+ BLI_strncpy(source_path, image->filepath, sizeof(source_path));
BLI_path_abs(source_path, ID_BLEND_PATH_FROM_GLOBAL(&image->id));
BLI_path_normalize(NULL, source_path);
diff --git a/source/blender/io/common/CMakeLists.txt b/source/blender/io/common/CMakeLists.txt
new file mode 100644
index 00000000000..4ed6f12762e
--- /dev/null
+++ b/source/blender/io/common/CMakeLists.txt
@@ -0,0 +1,45 @@
+# ***** 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) 2020, Blender Foundation
+# All rights reserved.
+# ***** END GPL LICENSE BLOCK *****
+
+set(INC
+ .
+ ../../blenkernel
+ ../../blenlib
+ ../../depsgraph
+ ../../makesdna
+)
+
+set(INC_SYS
+)
+
+set(SRC
+ intern/abstract_hierarchy_iterator.cc
+
+ IO_abstract_hierarchy_iterator.h
+)
+
+set(LIB
+ bf_blenkernel
+ bf_blenlib
+)
+
+blender_add_lib(bf_io_common "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
+
+target_link_libraries(bf_io_common INTERFACE)
diff --git a/source/blender/io/usd/intern/abstract_hierarchy_iterator.h b/source/blender/io/common/IO_abstract_hierarchy_iterator.h
index e31d5c91252..5f84fd48b71 100644
--- a/source/blender/io/usd/intern/abstract_hierarchy_iterator.h
+++ b/source/blender/io/common/IO_abstract_hierarchy_iterator.h
@@ -48,7 +48,8 @@ struct Object;
struct ParticleSystem;
struct ViewLayer;
-namespace USD {
+namespace blender {
+namespace io {
class AbstractHierarchyWriter;
@@ -90,6 +91,14 @@ struct HierarchyContext {
* exported objects, in which case this string is empty even though 'duplicator' is set. */
std::string original_export_path;
+ /* Export path of the higher-up exported data. For transforms, this is the export path of the
+ * parent object. For object data, this is the export path of that object's transform.
+ *
+ * From the exported file's point of view, this is the path to the parent in that file. The term
+ * "parent" is not used here to avoid confusion with Blender's meaning of the word (which always
+ * refers to a different object). */
+ std::string higher_up_export_path;
+
bool operator<(const HierarchyContext &other) const;
/* Return a HierarchyContext representing the root of the export hierarchy. */
@@ -119,6 +128,39 @@ class AbstractHierarchyWriter {
virtual bool check_is_animated(const HierarchyContext &context) const;
};
+/* Determines which subset of the writers actually gets to write. */
+struct ExportSubset {
+ bool transforms : 1;
+ bool shapes : 1;
+};
+
+/* EnsuredWriter represents an AbstractHierarchyWriter* combined with information whether it was
+ * newly created or not. It's returned by AbstractHierarchyIterator::ensure_writer(). */
+class EnsuredWriter {
+ private:
+ AbstractHierarchyWriter *writer_;
+
+ /* Is set to truth when ensure_writer() did not find existing writer and created a new one.
+ * Is set to false when writer has been re-used or when allocation of the new one has failed
+ * (`writer` will be `nullptr` in that case and bool(ensured_writer) will be false). */
+ bool newly_created_;
+
+ EnsuredWriter(AbstractHierarchyWriter *writer, bool newly_created);
+
+ public:
+ EnsuredWriter();
+
+ static EnsuredWriter empty();
+ static EnsuredWriter existing(AbstractHierarchyWriter *writer);
+ static EnsuredWriter newly_created(AbstractHierarchyWriter *writer);
+
+ bool is_newly_created() const;
+
+ /* These operators make an EnsuredWriter* act as an AbstractHierarchyWriter* */
+ operator bool() const;
+ AbstractHierarchyWriter *operator->();
+};
+
/* AbstractHierarchyIterator iterates over objects in a dependency graph, and constructs export
* writers. These writers are then called to perform the actual writing to a USD or Alembic file.
*
@@ -147,6 +189,7 @@ class AbstractHierarchyIterator {
ExportPathMap duplisource_export_path_;
Depsgraph *depsgraph_;
WriterMap writers_;
+ ExportSubset export_subset_;
public:
explicit AbstractHierarchyIterator(Depsgraph *depsgraph);
@@ -154,12 +197,21 @@ class AbstractHierarchyIterator {
/* Iterate over the depsgraph, create writers, and tell the writers to write.
* Main entry point for the AbstractHierarchyIterator, must be called for every to-be-exported
- * frame. */
- void iterate_and_write();
+ * (sub)frame. */
+ virtual void iterate_and_write();
/* Release all writers. Call after all frames have been exported. */
void release_writers();
+ /* Determine which subset of writers is used for exporting.
+ * Set this before calling iterate_and_write().
+ *
+ * Note that writers are created for each iterated object, regardless of this option. When a
+ * writer is created it will also write the current iteration, to ensure the hierarchy is
+ * complete. The `export_subset` option is only in effect when the writer already existed from a
+ * previous iteration. */
+ void set_export_subset(ExportSubset export_subset_);
+
/* Convert the given name to something that is valid for the exported file format.
* This base implementation is a no-op; override in a concrete subclass. */
virtual std::string make_valid_name(const std::string &name) const;
@@ -187,7 +239,6 @@ class AbstractHierarchyIterator {
Object *duplicator,
const std::set<Object *> &dupli_set);
- ExportChildren &graph_children(const HierarchyContext *parent_context);
void context_update_for_graph_index(HierarchyContext *context,
const ExportGraph::key_type &graph_index) const;
@@ -200,18 +251,21 @@ class AbstractHierarchyIterator {
void make_writer_object_data(const HierarchyContext *context);
void make_writers_particle_systems(const HierarchyContext *context);
+ /* Return the appropriate HierarchyContext for the data of the object represented by
+ * object_context. */
+ HierarchyContext context_for_object_data(const HierarchyContext *object_context) const;
+
/* Convenience wrappers around get_id_name(). */
std::string get_object_name(const Object *object) const;
std::string get_object_data_name(const Object *object) const;
- AbstractHierarchyWriter *get_writer(const std::string &export_path) const;
-
typedef AbstractHierarchyWriter *(AbstractHierarchyIterator::*create_writer_func)(
const HierarchyContext *);
- /* Ensure that a writer exists; if it doesn't, call create_func(context). The create_func
- * function should be one of the create_XXXX_writer(context) functions declared below. */
- AbstractHierarchyWriter *ensure_writer(HierarchyContext *context,
- create_writer_func create_func);
+ /* Ensure that a writer exists; if it doesn't, call create_func(context).
+ *
+ * The create_func function should be one of the create_XXXX_writer(context) functions declared
+ * below. */
+ EnsuredWriter ensure_writer(HierarchyContext *context, create_writer_func create_func);
protected:
/* Construct a valid path for the export file format. This class concatenates by using '/' as a
@@ -256,8 +310,12 @@ class AbstractHierarchyIterator {
/* Called by release_writers() to free what the create_XXX_writer() functions allocated. */
virtual void delete_object_writer(AbstractHierarchyWriter *writer) = 0;
+
+ AbstractHierarchyWriter *get_writer(const std::string &export_path) const;
+ ExportChildren &graph_children(const HierarchyContext *parent_context);
};
-} // namespace USD
+} // namespace io
+} // namespace blender
#endif /* __ABSTRACT_HIERARCHY_ITERATOR_H__ */
diff --git a/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc
index ab83ea2c3c4..9a456bfaf69 100644
--- a/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc
+++ b/source/blender/io/common/intern/abstract_hierarchy_iterator.cc
@@ -16,7 +16,7 @@
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
-#include "abstract_hierarchy_iterator.h"
+#include "IO_abstract_hierarchy_iterator.h"
#include <iostream>
#include <limits.h>
@@ -41,7 +41,8 @@
#include "DEG_depsgraph_query.h"
-namespace USD {
+namespace blender {
+namespace io {
const HierarchyContext *HierarchyContext::root()
{
@@ -74,6 +75,43 @@ void HierarchyContext::mark_as_not_instanced()
original_export_path.clear();
}
+EnsuredWriter::EnsuredWriter() : writer_(nullptr), newly_created_(false)
+{
+}
+
+EnsuredWriter::EnsuredWriter(AbstractHierarchyWriter *writer, bool newly_created)
+ : writer_(writer), newly_created_(newly_created)
+{
+}
+
+EnsuredWriter EnsuredWriter::empty()
+{
+ return EnsuredWriter(nullptr, false);
+}
+EnsuredWriter EnsuredWriter::existing(AbstractHierarchyWriter *writer)
+{
+ return EnsuredWriter(writer, false);
+}
+EnsuredWriter EnsuredWriter::newly_created(AbstractHierarchyWriter *writer)
+{
+ return EnsuredWriter(writer, true);
+}
+
+bool EnsuredWriter::is_newly_created() const
+{
+ return newly_created_;
+}
+
+EnsuredWriter::operator bool() const
+{
+ return writer_ != nullptr;
+}
+
+AbstractHierarchyWriter *EnsuredWriter::operator->()
+{
+ return writer_;
+}
+
AbstractHierarchyWriter::~AbstractHierarchyWriter()
{
}
@@ -104,7 +142,7 @@ bool AbstractHierarchyWriter::check_is_animated(const HierarchyContext &context)
}
AbstractHierarchyIterator::AbstractHierarchyIterator(Depsgraph *depsgraph)
- : depsgraph_(depsgraph), writers_()
+ : depsgraph_(depsgraph), writers_(), export_subset_({true, true})
{
}
@@ -131,6 +169,11 @@ void AbstractHierarchyIterator::release_writers()
writers_.clear();
}
+void AbstractHierarchyIterator::set_export_subset(ExportSubset export_subset)
+{
+ export_subset_ = export_subset;
+}
+
std::string AbstractHierarchyIterator::make_valid_name(const std::string &name) const
{
return name;
@@ -341,6 +384,8 @@ void AbstractHierarchyIterator::visit_object(Object *object,
context->animation_check_include_parent = false;
context->export_path = "";
context->original_export_path = "";
+ context->higher_up_export_path = "";
+
copy_m4_m4(context->matrix_world, object->obmat);
ExportGraph::key_type graph_index = determine_graph_index_object(context);
@@ -494,7 +539,6 @@ void AbstractHierarchyIterator::determine_duplication_references(
void AbstractHierarchyIterator::make_writers(const HierarchyContext *parent_context)
{
- AbstractHierarchyWriter *transform_writer = nullptr;
float parent_matrix_inv_world[4][4];
if (parent_context) {
@@ -507,20 +551,27 @@ void AbstractHierarchyIterator::make_writers(const HierarchyContext *parent_cont
for (HierarchyContext *context : graph_children(parent_context)) {
// Update the context so that it is correct for this parent-child relation.
copy_m4_m4(context->parent_matrix_inv_world, parent_matrix_inv_world);
+ if (parent_context != nullptr) {
+ context->higher_up_export_path = parent_context->export_path;
+ }
// Get or create the transform writer.
- transform_writer = ensure_writer(context, &AbstractHierarchyIterator::create_transform_writer);
- if (transform_writer == nullptr) {
+ EnsuredWriter transform_writer = ensure_writer(
+ context, &AbstractHierarchyIterator::create_transform_writer);
+
+ if (!transform_writer) {
// Unable to export, so there is nothing to attach any children to; just abort this entire
// branch of the export hierarchy.
return;
}
BLI_assert(DEG_is_evaluated_object(context->object));
- /* XXX This can lead to too many XForms being written. For example, a camera writer can refuse
- * to write an orthographic camera. By the time that this is known, the XForm has already been
- * written. */
- transform_writer->write(*context);
+ if (transform_writer.is_newly_created() || export_subset_.transforms) {
+ /* XXX This can lead to too many XForms being written. For example, a camera writer can
+ * refuse to write an orthographic camera. By the time that this is known, the XForm has
+ * already been written. */
+ transform_writer->write(*context);
+ }
if (!context->weak_export) {
make_writers_particle_systems(context);
@@ -534,17 +585,24 @@ void AbstractHierarchyIterator::make_writers(const HierarchyContext *parent_cont
// TODO(Sybren): iterate over all unused writers and call unused_during_iteration() or something.
}
+HierarchyContext AbstractHierarchyIterator::context_for_object_data(
+ const HierarchyContext *object_context) const
+{
+ HierarchyContext data_context = *object_context;
+ data_context.higher_up_export_path = object_context->export_path;
+ data_context.export_name = get_object_data_name(data_context.object);
+ data_context.export_path = path_concatenate(data_context.higher_up_export_path,
+ data_context.export_name);
+ return data_context;
+}
+
void AbstractHierarchyIterator::make_writer_object_data(const HierarchyContext *context)
{
if (context->object->data == nullptr) {
return;
}
- HierarchyContext data_context = *context;
- data_context.export_path = get_object_data_path(context);
-
- /* data_context.original_export_path is just a copy from the context. It points to the object,
- * but needs to point to the object data. */
+ HierarchyContext data_context = context_for_object_data(context);
if (data_context.is_instance()) {
ID *object_data = static_cast<ID *>(context->object->data);
data_context.original_export_path = duplisource_export_path_[object_data];
@@ -553,13 +611,16 @@ void AbstractHierarchyIterator::make_writer_object_data(const HierarchyContext *
BLI_assert(data_context.is_instance());
}
- AbstractHierarchyWriter *data_writer;
- data_writer = ensure_writer(&data_context, &AbstractHierarchyIterator::create_data_writer);
- if (data_writer == nullptr) {
+ /* Always write upon creation, otherwise depend on which subset is active. */
+ EnsuredWriter data_writer = ensure_writer(&data_context,
+ &AbstractHierarchyIterator::create_data_writer);
+ if (!data_writer) {
return;
}
- data_writer->write(data_context);
+ if (data_writer.is_newly_created() || export_subset_.shapes) {
+ data_writer->write(data_context);
+ }
}
void AbstractHierarchyIterator::make_writers_particle_systems(
@@ -573,11 +634,13 @@ void AbstractHierarchyIterator::make_writers_particle_systems(
}
HierarchyContext hair_context = *transform_context;
+ hair_context.export_name = make_valid_name(psys->name);
hair_context.export_path = path_concatenate(transform_context->export_path,
- make_valid_name(psys->name));
+ hair_context.export_name);
+ hair_context.higher_up_export_path = transform_context->export_path;
hair_context.particle_system = psys;
- AbstractHierarchyWriter *writer = nullptr;
+ EnsuredWriter writer;
switch (psys->part->type) {
case PART_HAIR:
writer = ensure_writer(&hair_context, &AbstractHierarchyIterator::create_hair_writer);
@@ -586,8 +649,12 @@ void AbstractHierarchyIterator::make_writers_particle_systems(
writer = ensure_writer(&hair_context, &AbstractHierarchyIterator::create_particle_writer);
break;
}
+ if (!writer) {
+ continue;
+ }
- if (writer != nullptr) {
+ /* Always write upon creation, otherwise depend on which subset is active. */
+ if (writer.is_newly_created() || export_subset_.shapes) {
writer->write(hair_context);
}
}
@@ -615,22 +682,21 @@ AbstractHierarchyWriter *AbstractHierarchyIterator::get_writer(
return it->second;
}
-AbstractHierarchyWriter *AbstractHierarchyIterator::ensure_writer(
+EnsuredWriter AbstractHierarchyIterator::ensure_writer(
HierarchyContext *context, AbstractHierarchyIterator::create_writer_func create_func)
{
AbstractHierarchyWriter *writer = get_writer(context->export_path);
if (writer != nullptr) {
- return writer;
+ return EnsuredWriter::existing(writer);
}
writer = (this->*create_func)(context);
if (writer == nullptr) {
- return nullptr;
+ return EnsuredWriter::empty();
}
writers_[context->export_path] = writer;
-
- return writer;
+ return EnsuredWriter::newly_created(writer);
}
std::string AbstractHierarchyIterator::path_concatenate(const std::string &parent_path,
@@ -649,4 +715,5 @@ bool AbstractHierarchyIterator::should_visit_dupli_object(const DupliObject *dup
return !dupli_object->no_draw;
}
-} // namespace USD
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/usd/CMakeLists.txt b/source/blender/io/usd/CMakeLists.txt
index 732a638a255..19e16a5b328 100644
--- a/source/blender/io/usd/CMakeLists.txt
+++ b/source/blender/io/usd/CMakeLists.txt
@@ -32,6 +32,7 @@ add_definitions(-DPXR_STATIC)
set(INC
.
+ ../common
../../blenkernel
../../blenlib
../../blenloader
@@ -52,7 +53,6 @@ set(INC_SYS
)
set(SRC
- intern/abstract_hierarchy_iterator.cc
intern/usd_capi.cc
intern/usd_hierarchy_iterator.cc
intern/usd_writer_abstract.cc
@@ -64,7 +64,6 @@ set(SRC
intern/usd_writer_transform.cc
usd.h
- intern/abstract_hierarchy_iterator.h
intern/usd_exporter_context.h
intern/usd_hierarchy_iterator.h
intern/usd_writer_abstract.h
@@ -79,6 +78,7 @@ set(SRC
set(LIB
bf_blenkernel
bf_blenlib
+ bf_io_common
)
list(APPEND LIB
@@ -100,10 +100,10 @@ endif()
# Source: https://github.com/PixarAnimationStudios/USD/blob/master/BUILDING.md#linking-whole-archives
if(WIN32)
target_link_libraries(bf_usd INTERFACE ${USD_LIBRARIES})
-elseif(CMAKE_COMPILER_IS_GNUCXX)
- target_link_libraries(bf_usd INTERFACE "-Wl,--whole-archive ${USD_LIBRARIES} -Wl,--no-whole-archive ${TBB_LIBRARIES}")
-elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
+elseif(APPLE)
target_link_libraries(bf_usd INTERFACE -Wl,-force_load ${USD_LIBRARIES})
+elseif(UNIX)
+ target_link_libraries(bf_usd INTERFACE "-Wl,--whole-archive ${USD_LIBRARIES} -Wl,--no-whole-archive ${TBB_LIBRARIES}")
else()
message(FATAL_ERROR "Unknown how to link USD with your compiler ${CMAKE_CXX_COMPILER_ID}")
endif()
diff --git a/source/blender/io/usd/intern/usd_capi.cc b/source/blender/io/usd/intern/usd_capi.cc
index cf962446d04..2d3972410a4 100644
--- a/source/blender/io/usd/intern/usd_capi.cc
+++ b/source/blender/io/usd/intern/usd_capi.cc
@@ -44,7 +44,9 @@
#include "WM_api.h"
#include "WM_types.h"
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
struct ExportJobData {
Main *bmain;
@@ -157,7 +159,9 @@ static void export_endjob(void *customdata)
WM_set_locked_interface(data->wm, false);
}
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
bool USD_export(bContext *C,
const char *filepath,
@@ -167,8 +171,8 @@ bool USD_export(bContext *C,
ViewLayer *view_layer = CTX_data_view_layer(C);
Scene *scene = CTX_data_scene(C);
- USD::ExportJobData *job = static_cast<USD::ExportJobData *>(
- MEM_mallocN(sizeof(USD::ExportJobData), "ExportJobData"));
+ blender::io::usd::ExportJobData *job = static_cast<blender::io::usd::ExportJobData *>(
+ MEM_mallocN(sizeof(blender::io::usd::ExportJobData), "ExportJobData"));
job->bmain = CTX_data_main(C);
job->wm = CTX_wm_manager(C);
@@ -186,7 +190,11 @@ bool USD_export(bContext *C,
/* setup job */
WM_jobs_customdata_set(wm_job, job, MEM_freeN);
WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_FRAME, NC_SCENE | ND_FRAME);
- WM_jobs_callbacks(wm_job, USD::export_startjob, nullptr, nullptr, USD::export_endjob);
+ WM_jobs_callbacks(wm_job,
+ blender::io::usd::export_startjob,
+ nullptr,
+ nullptr,
+ blender::io::usd::export_endjob);
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
@@ -195,8 +203,8 @@ bool USD_export(bContext *C,
short stop = 0, do_update = 0;
float progress = 0.f;
- USD::export_startjob(job, &stop, &do_update, &progress);
- USD::export_endjob(job);
+ blender::io::usd::export_startjob(job, &stop, &do_update, &progress);
+ blender::io::usd::export_endjob(job);
export_ok = job->export_ok;
MEM_freeN(job);
diff --git a/source/blender/io/usd/intern/usd_exporter_context.h b/source/blender/io/usd/intern/usd_exporter_context.h
index 4ae415b3d34..07a9d0fc0c5 100644
--- a/source/blender/io/usd/intern/usd_exporter_context.h
+++ b/source/blender/io/usd/intern/usd_exporter_context.h
@@ -27,7 +27,9 @@
struct Depsgraph;
struct Object;
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
class USDHierarchyIterator;
@@ -39,6 +41,8 @@ struct USDExporterContext {
const USDExportParams &export_params;
};
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
#endif /* __USD_EXPORTER_CONTEXT_H__ */
diff --git a/source/blender/io/usd/intern/usd_hierarchy_iterator.cc b/source/blender/io/usd/intern/usd_hierarchy_iterator.cc
index 56e367dd877..388b588b331 100644
--- a/source/blender/io/usd/intern/usd_hierarchy_iterator.cc
+++ b/source/blender/io/usd/intern/usd_hierarchy_iterator.cc
@@ -41,7 +41,9 @@
#include "DNA_layer_types.h"
#include "DNA_object_types.h"
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
USDHierarchyIterator::USDHierarchyIterator(Depsgraph *depsgraph,
pxr::UsdStageRefPtr stage,
@@ -145,4 +147,6 @@ AbstractHierarchyWriter *USDHierarchyIterator::create_particle_writer(const Hier
return nullptr;
}
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/usd/intern/usd_hierarchy_iterator.h b/source/blender/io/usd/intern/usd_hierarchy_iterator.h
index a608012a390..7d750bff0cb 100644
--- a/source/blender/io/usd/intern/usd_hierarchy_iterator.h
+++ b/source/blender/io/usd/intern/usd_hierarchy_iterator.h
@@ -19,7 +19,7 @@
#ifndef __USD_HIERARCHY_ITERATOR_H__
#define __USD_HIERARCHY_ITERATOR_H__
-#include "abstract_hierarchy_iterator.h"
+#include "IO_abstract_hierarchy_iterator.h"
#include "usd.h"
#include "usd_exporter_context.h"
@@ -32,7 +32,13 @@ struct Depsgraph;
struct ID;
struct Object;
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
+
+using blender::io::AbstractHierarchyIterator;
+using blender::io::AbstractHierarchyWriter;
+using blender::io::HierarchyContext;
class USDHierarchyIterator : public AbstractHierarchyIterator {
private:
@@ -66,6 +72,8 @@ class USDHierarchyIterator : public AbstractHierarchyIterator {
USDExporterContext create_usd_export_context(const HierarchyContext *context);
};
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
#endif /* __USD_HIERARCHY_ITERATOR_H__ */
diff --git a/source/blender/io/usd/intern/usd_writer_abstract.cc b/source/blender/io/usd/intern/usd_writer_abstract.cc
index 76a2436ee92..a416941fb4d 100644
--- a/source/blender/io/usd/intern/usd_writer_abstract.cc
+++ b/source/blender/io/usd/intern/usd_writer_abstract.cc
@@ -32,7 +32,9 @@ static const pxr::TfToken roughness("roughness", pxr::TfToken::Immortal);
static const pxr::TfToken surface("surface", pxr::TfToken::Immortal);
} // namespace usdtokens
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
USDAbstractWriter::USDAbstractWriter(const USDExporterContext &usd_export_context)
: usd_export_context_(usd_export_context),
@@ -112,4 +114,6 @@ pxr::UsdShadeMaterial USDAbstractWriter::ensure_usd_material(Material *material)
return usd_material;
}
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/usd/intern/usd_writer_abstract.h b/source/blender/io/usd/intern/usd_writer_abstract.h
index 01b53f4c916..f81cf5197af 100644
--- a/source/blender/io/usd/intern/usd_writer_abstract.h
+++ b/source/blender/io/usd/intern/usd_writer_abstract.h
@@ -19,7 +19,7 @@
#ifndef __USD_WRITER_ABSTRACT_H__
#define __USD_WRITER_ABSTRACT_H__
-#include "abstract_hierarchy_iterator.h"
+#include "IO_abstract_hierarchy_iterator.h"
#include "usd_exporter_context.h"
#include <pxr/usd/sdf/path.h>
@@ -36,7 +36,12 @@
struct Material;
struct Object;
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
+
+using blender::io::AbstractHierarchyWriter;
+using blender::io::HierarchyContext;
class USDAbstractWriter : public AbstractHierarchyWriter {
protected:
@@ -70,6 +75,8 @@ class USDAbstractWriter : public AbstractHierarchyWriter {
pxr::UsdShadeMaterial ensure_usd_material(Material *material);
};
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
#endif /* __USD_WRITER_ABSTRACT_H__ */
diff --git a/source/blender/io/usd/intern/usd_writer_camera.cc b/source/blender/io/usd/intern/usd_writer_camera.cc
index ea551a43c9f..d51eb32d3fd 100644
--- a/source/blender/io/usd/intern/usd_writer_camera.cc
+++ b/source/blender/io/usd/intern/usd_writer_camera.cc
@@ -28,7 +28,9 @@
#include "DNA_camera_types.h"
#include "DNA_scene_types.h"
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
USDCameraWriter::USDCameraWriter(const USDExporterContext &ctx) : USDAbstractWriter(ctx)
{
@@ -106,4 +108,6 @@ void USDCameraWriter::do_write(HierarchyContext &context)
}
}
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/usd/intern/usd_writer_camera.h b/source/blender/io/usd/intern/usd_writer_camera.h
index 971264ef11e..8b5795d7d9f 100644
--- a/source/blender/io/usd/intern/usd_writer_camera.h
+++ b/source/blender/io/usd/intern/usd_writer_camera.h
@@ -21,7 +21,9 @@
#include "usd_writer_abstract.h"
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
/* Writer for writing camera data to UsdGeomCamera. */
class USDCameraWriter : public USDAbstractWriter {
@@ -33,6 +35,8 @@ class USDCameraWriter : public USDAbstractWriter {
virtual void do_write(HierarchyContext &context) override;
};
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
#endif /* __USD_WRITER_CAMERA_H__ */
diff --git a/source/blender/io/usd/intern/usd_writer_hair.cc b/source/blender/io/usd/intern/usd_writer_hair.cc
index d38c1032969..0e0256bdb69 100644
--- a/source/blender/io/usd/intern/usd_writer_hair.cc
+++ b/source/blender/io/usd/intern/usd_writer_hair.cc
@@ -26,7 +26,9 @@
#include "DNA_particle_types.h"
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
USDHairWriter::USDHairWriter(const USDExporterContext &ctx) : USDAbstractWriter(ctx)
{
@@ -85,4 +87,6 @@ bool USDHairWriter::check_is_animated(const HierarchyContext &) const
return true;
}
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/usd/intern/usd_writer_hair.h b/source/blender/io/usd/intern/usd_writer_hair.h
index 1e882fa1654..cecacd0a355 100644
--- a/source/blender/io/usd/intern/usd_writer_hair.h
+++ b/source/blender/io/usd/intern/usd_writer_hair.h
@@ -21,7 +21,9 @@
#include "usd_writer_abstract.h"
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
/* Writer for writing hair particle data as USD curves. */
class USDHairWriter : public USDAbstractWriter {
@@ -33,6 +35,8 @@ class USDHairWriter : public USDAbstractWriter {
virtual bool check_is_animated(const HierarchyContext &context) const override;
};
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
#endif /* __USD_WRITER_HAIR_H__ */
diff --git a/source/blender/io/usd/intern/usd_writer_light.cc b/source/blender/io/usd/intern/usd_writer_light.cc
index 0ce3ee5f8ce..19115dd1a4e 100644
--- a/source/blender/io/usd/intern/usd_writer_light.cc
+++ b/source/blender/io/usd/intern/usd_writer_light.cc
@@ -30,7 +30,9 @@
#include "DNA_light_types.h"
#include "DNA_object_types.h"
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
USDLightWriter::USDLightWriter(const USDExporterContext &ctx) : USDAbstractWriter(ctx)
{
@@ -107,4 +109,6 @@ void USDLightWriter::do_write(HierarchyContext &context)
usd_light.CreateSpecularAttr().Set(light->spec_fac, timecode);
}
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/usd/intern/usd_writer_light.h b/source/blender/io/usd/intern/usd_writer_light.h
index 349c034b6bc..73666622af1 100644
--- a/source/blender/io/usd/intern/usd_writer_light.h
+++ b/source/blender/io/usd/intern/usd_writer_light.h
@@ -21,7 +21,9 @@
#include "usd_writer_abstract.h"
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
class USDLightWriter : public USDAbstractWriter {
public:
@@ -32,6 +34,8 @@ class USDLightWriter : public USDAbstractWriter {
virtual void do_write(HierarchyContext &context) override;
};
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
#endif /* __USD_WRITER_LIGHT_H__ */
diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc
index 61337beff20..29a9734f876 100644
--- a/source/blender/io/usd/intern/usd_writer_mesh.cc
+++ b/source/blender/io/usd/intern/usd_writer_mesh.cc
@@ -42,7 +42,9 @@
#include "DNA_object_fluidsim_types.h"
#include "DNA_particle_types.h"
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
USDGenericMeshWriter::USDGenericMeshWriter(const USDExporterContext &ctx) : USDAbstractWriter(ctx)
{
@@ -484,4 +486,6 @@ Mesh *USDMeshWriter::get_export_mesh(Object *object_eval, bool & /*r_needsfree*/
return BKE_object_get_evaluated_mesh(object_eval);
}
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/usd/intern/usd_writer_mesh.h b/source/blender/io/usd/intern/usd_writer_mesh.h
index 4175e2b7e27..a14ceecfa53 100644
--- a/source/blender/io/usd/intern/usd_writer_mesh.h
+++ b/source/blender/io/usd/intern/usd_writer_mesh.h
@@ -23,7 +23,9 @@
#include <pxr/usd/usdGeom/mesh.h>
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
struct USDMeshData;
@@ -61,6 +63,8 @@ class USDMeshWriter : public USDGenericMeshWriter {
virtual Mesh *get_export_mesh(Object *object_eval, bool &r_needsfree) override;
};
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
#endif /* __USD_WRITER_MESH_H__ */
diff --git a/source/blender/io/usd/intern/usd_writer_metaball.cc b/source/blender/io/usd/intern/usd_writer_metaball.cc
index 96bf854d327..f003fba18a4 100644
--- a/source/blender/io/usd/intern/usd_writer_metaball.cc
+++ b/source/blender/io/usd/intern/usd_writer_metaball.cc
@@ -34,7 +34,9 @@
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
USDMetaballWriter::USDMetaballWriter(const USDExporterContext &ctx) : USDGenericMeshWriter(ctx)
{
@@ -76,4 +78,6 @@ bool USDMetaballWriter::is_basis_ball(Scene *scene, Object *ob) const
return ob == basis_ob;
}
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/usd/intern/usd_writer_metaball.h b/source/blender/io/usd/intern/usd_writer_metaball.h
index 1a86daae2ae..9f51a3314a5 100644
--- a/source/blender/io/usd/intern/usd_writer_metaball.h
+++ b/source/blender/io/usd/intern/usd_writer_metaball.h
@@ -21,7 +21,9 @@
#include "usd_writer_mesh.h"
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
class USDMetaballWriter : public USDGenericMeshWriter {
public:
@@ -37,6 +39,8 @@ class USDMetaballWriter : public USDGenericMeshWriter {
bool is_basis_ball(Scene *scene, Object *ob) const;
};
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
#endif /* __USD_WRITER_METABALL_H__ */
diff --git a/source/blender/io/usd/intern/usd_writer_transform.cc b/source/blender/io/usd/intern/usd_writer_transform.cc
index 0694d873002..643f1a8f4b1 100644
--- a/source/blender/io/usd/intern/usd_writer_transform.cc
+++ b/source/blender/io/usd/intern/usd_writer_transform.cc
@@ -28,7 +28,9 @@
#include "DNA_layer_types.h"
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
USDTransformWriter::USDTransformWriter(const USDExporterContext &ctx) : USDAbstractWriter(ctx)
{
@@ -59,4 +61,6 @@ bool USDTransformWriter::check_is_animated(const HierarchyContext &context) cons
return BKE_object_moves_in_time(context.object, context.animation_check_include_parent);
}
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
diff --git a/source/blender/io/usd/intern/usd_writer_transform.h b/source/blender/io/usd/intern/usd_writer_transform.h
index 52c4a657f33..8b4741f1177 100644
--- a/source/blender/io/usd/intern/usd_writer_transform.h
+++ b/source/blender/io/usd/intern/usd_writer_transform.h
@@ -23,7 +23,9 @@
#include <pxr/usd/usdGeom/xform.h>
-namespace USD {
+namespace blender {
+namespace io {
+namespace usd {
class USDTransformWriter : public USDAbstractWriter {
private:
@@ -37,6 +39,8 @@ class USDTransformWriter : public USDAbstractWriter {
bool check_is_animated(const HierarchyContext &context) const override;
};
-} // namespace USD
+} // namespace usd
+} // namespace io
+} // namespace blender
#endif /* __USD_WRITER_TRANSFORM_H__ */