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:
authorSybren A. Stüvel <sybren@blender.org>2020-02-17 13:47:13 +0300
committerSybren A. Stüvel <sybren@blender.org>2020-02-17 13:50:28 +0300
commit2d1b05a15fa2d53894efd5198784ddde6bfa63a3 (patch)
tree0710e84c534e660135f66223af959bff7d728078
parentc498abb1032026fac3b84f3622264b34c27212af (diff)
Cleanup: Alembic, split source files into reader and writer
This separation between reader and writer code is part of Milesone 2 of T73363. In this commit the reader and writer classes are separated into their own files, any `#include` and `using` statements are cleaned up, and some separator comments have been removed. No functional changes.
-rw-r--r--source/blender/alembic/CMakeLists.txt56
-rw-r--r--source/blender/alembic/intern/abc_customdata.cc2
-rw-r--r--source/blender/alembic/intern/abc_exporter.cc18
-rw-r--r--source/blender/alembic/intern/abc_reader_archive.cc (renamed from source/blender/alembic/intern/abc_archive.cc)81
-rw-r--r--source/blender/alembic/intern/abc_reader_archive.h (renamed from source/blender/alembic/intern/abc_archive.h)19
-rw-r--r--source/blender/alembic/intern/abc_reader_camera.cc (renamed from source/blender/alembic/intern/abc_camera.cc)67
-rw-r--r--source/blender/alembic/intern/abc_reader_camera.h40
-rw-r--r--source/blender/alembic/intern/abc_reader_curves.cc (renamed from source/blender/alembic/intern/abc_curves.cc)171
-rw-r--r--source/blender/alembic/intern/abc_reader_curves.h (renamed from source/blender/alembic/intern/abc_curves.h)41
-rw-r--r--source/blender/alembic/intern/abc_reader_mesh.cc (renamed from source/blender/alembic/intern/abc_mesh.cc)596
-rw-r--r--source/blender/alembic/intern/abc_reader_mesh.h (renamed from source/blender/alembic/intern/abc_mesh.h)78
-rw-r--r--source/blender/alembic/intern/abc_reader_nurbs.cc (renamed from source/blender/alembic/intern/abc_nurbs.cc)153
-rw-r--r--source/blender/alembic/intern/abc_reader_nurbs.h (renamed from source/blender/alembic/intern/abc_nurbs.h)28
-rw-r--r--source/blender/alembic/intern/abc_reader_object.cc (renamed from source/blender/alembic/intern/abc_object.cc)74
-rw-r--r--source/blender/alembic/intern/abc_reader_object.h (renamed from source/blender/alembic/intern/abc_object.h)57
-rw-r--r--source/blender/alembic/intern/abc_reader_points.cc (renamed from source/blender/alembic/intern/abc_points.cc)102
-rw-r--r--source/blender/alembic/intern/abc_reader_points.h (renamed from source/blender/alembic/intern/abc_points.h)29
-rw-r--r--source/blender/alembic/intern/abc_reader_transform.cc76
-rw-r--r--source/blender/alembic/intern/abc_reader_transform.h42
-rw-r--r--source/blender/alembic/intern/abc_util.cc15
-rw-r--r--source/blender/alembic/intern/abc_writer_archive.cc114
-rw-r--r--source/blender/alembic/intern/abc_writer_archive.h58
-rw-r--r--source/blender/alembic/intern/abc_writer_camera.cc81
-rw-r--r--source/blender/alembic/intern/abc_writer_camera.h (renamed from source/blender/alembic/intern/abc_camera.h)24
-rw-r--r--source/blender/alembic/intern/abc_writer_curves.cc187
-rw-r--r--source/blender/alembic/intern/abc_writer_curves.h55
-rw-r--r--source/blender/alembic/intern/abc_writer_hair.cc (renamed from source/blender/alembic/intern/abc_hair.cc)12
-rw-r--r--source/blender/alembic/intern/abc_writer_hair.h (renamed from source/blender/alembic/intern/abc_hair.h)10
-rw-r--r--source/blender/alembic/intern/abc_writer_mball.cc (renamed from source/blender/alembic/intern/abc_mball.cc)11
-rw-r--r--source/blender/alembic/intern/abc_writer_mball.h (renamed from source/blender/alembic/intern/abc_mball.h)10
-rw-r--r--source/blender/alembic/intern/abc_writer_mesh.cc592
-rw-r--r--source/blender/alembic/intern/abc_writer_mesh.h91
-rw-r--r--source/blender/alembic/intern/abc_writer_nurbs.cc172
-rw-r--r--source/blender/alembic/intern/abc_writer_nurbs.h42
-rw-r--r--source/blender/alembic/intern/abc_writer_object.cc79
-rw-r--r--source/blender/alembic/intern/abc_writer_object.h71
-rw-r--r--source/blender/alembic/intern/abc_writer_points.cc123
-rw-r--r--source/blender/alembic/intern/abc_writer_points.h49
-rw-r--r--source/blender/alembic/intern/abc_writer_transform.cc (renamed from source/blender/alembic/intern/abc_transform.cc)58
-rw-r--r--source/blender/alembic/intern/abc_writer_transform.h (renamed from source/blender/alembic/intern/abc_transform.h)26
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc22
41 files changed, 2016 insertions, 1616 deletions
diff --git a/source/blender/alembic/CMakeLists.txt b/source/blender/alembic/CMakeLists.txt
index 4618246013a..8bb7051982a 100644
--- a/source/blender/alembic/CMakeLists.txt
+++ b/source/blender/alembic/CMakeLists.txt
@@ -41,35 +41,51 @@ set(INC_SYS
)
set(SRC
- intern/abc_archive.cc
- intern/abc_camera.cc
- intern/abc_curves.cc
intern/abc_customdata.cc
intern/abc_exporter.cc
- intern/abc_hair.cc
- intern/abc_mball.cc
- intern/abc_mesh.cc
- intern/abc_nurbs.cc
- intern/abc_object.cc
- intern/abc_points.cc
- intern/abc_transform.cc
+ intern/abc_reader_archive.cc
+ intern/abc_reader_camera.cc
+ intern/abc_reader_curves.cc
+ intern/abc_reader_mesh.cc
+ intern/abc_reader_nurbs.cc
+ intern/abc_reader_object.cc
+ 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
ABC_alembic.h
- intern/abc_archive.h
- intern/abc_camera.h
- intern/abc_curves.h
intern/abc_customdata.h
intern/abc_exporter.h
- intern/abc_hair.h
- intern/abc_mball.h
- intern/abc_mesh.h
- intern/abc_nurbs.h
- intern/abc_object.h
- intern/abc_points.h
- intern/abc_transform.h
+ intern/abc_reader_archive.h
+ intern/abc_reader_camera.h
+ intern/abc_reader_curves.h
+ intern/abc_reader_mesh.h
+ intern/abc_reader_nurbs.h
+ intern/abc_reader_object.h
+ 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
)
set(LIB
diff --git a/source/blender/alembic/intern/abc_customdata.cc b/source/blender/alembic/intern/abc_customdata.cc
index 7f04bb77052..c5f60ac3e29 100644
--- a/source/blender/alembic/intern/abc_customdata.cc
+++ b/source/blender/alembic/intern/abc_customdata.cc
@@ -32,6 +32,8 @@ extern "C" {
#include "DNA_meshdata_types.h"
#include "BLI_math_base.h"
+#include "BLI_utildefines.h"
+
#include "BKE_customdata.h"
}
diff --git a/source/blender/alembic/intern/abc_exporter.cc b/source/blender/alembic/intern/abc_exporter.cc
index ea76ade73e9..a58b0a29e5e 100644
--- a/source/blender/alembic/intern/abc_exporter.cc
+++ b/source/blender/alembic/intern/abc_exporter.cc
@@ -22,15 +22,15 @@
#include <cmath>
-#include "abc_archive.h"
-#include "abc_camera.h"
-#include "abc_curves.h"
-#include "abc_hair.h"
-#include "abc_mball.h"
-#include "abc_mesh.h"
-#include "abc_nurbs.h"
-#include "abc_points.h"
-#include "abc_transform.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 "abc_util.h"
extern "C" {
diff --git a/source/blender/alembic/intern/abc_archive.cc b/source/blender/alembic/intern/abc_reader_archive.cc
index 15e7efad1c3..6ad44553701 100644
--- a/source/blender/alembic/intern/abc_archive.cc
+++ b/source/blender/alembic/intern/abc_reader_archive.cc
@@ -21,15 +21,13 @@
* \ingroup balembic
*/
-#include "abc_archive.h"
+#include "abc_reader_archive.h"
+
extern "C" {
-#include "BKE_blender_version.h"
#include "BKE_main.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
-
-#include "DNA_scene_types.h"
}
#ifdef WIN32
@@ -42,7 +40,6 @@ using Alembic::Abc::ErrorHandler;
using Alembic::Abc::Exception;
using Alembic::Abc::IArchive;
using Alembic::Abc::kWrapExisting;
-using Alembic::Abc::OArchive;
static IArchive open_archive(const std::string &filename,
const std::vector<std::istream *> &input_streams,
@@ -141,77 +138,3 @@ Alembic::Abc::IObject ArchiveReader::getTop()
{
return m_archive.getTop();
}
-
-/* ************************************************************************** */
-
-/* This kinda duplicates CreateArchiveWithInfo, but Alembic does not seem to
- * have a version supporting streams. */
-static OArchive create_archive(std::ostream *ostream,
- const std::string &filename,
- const std::string &scene_name,
- double scene_fps,
- bool ogawa)
-{
- 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", versionstr);
- 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;
-
-#ifdef WITH_ALEMBIC_HDF5
- if (!ogawa) {
- return OArchive(Alembic::AbcCoreHDF5::WriteArchive(), filename, abc_metadata, policy);
- }
-#else
- static_cast<void>(filename);
- static_cast<void>(ogawa);
-#endif
-
- 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,
- bool do_ogawa)
-{
- /* Use stream to support unicode character paths on Windows. */
- if (do_ogawa) {
-#ifdef WIN32
- UTF16_ENCODE(filename);
- std::wstring wstr(filename_16);
- m_outfile.open(wstr.c_str(), std::ios::out | std::ios::binary);
- UTF16_UN_ENCODE(filename);
-#else
- m_outfile.open(filename, std::ios::out | std::ios::binary);
-#endif
- }
-
- m_archive = create_archive(&m_outfile, filename, abc_scene_name, FPS, do_ogawa);
-}
-
-OArchive &ArchiveWriter::archive()
-{
- return m_archive;
-}
diff --git a/source/blender/alembic/intern/abc_archive.h b/source/blender/alembic/intern/abc_reader_archive.h
index 32b1b72747f..bdb53bd0b8c 100644
--- a/source/blender/alembic/intern/abc_archive.h
+++ b/source/blender/alembic/intern/abc_reader_archive.h
@@ -21,8 +21,8 @@
* \ingroup balembic
*/
-#ifndef __ABC_ARCHIVE_H__
-#define __ABC_ARCHIVE_H__
+#ifndef __ABC_READER_ARCHIVE_H__
+#define __ABC_READER_ARCHIVE_H__
#include <Alembic/Abc/All.h>
@@ -64,17 +64,4 @@ class ArchiveReader {
Alembic::Abc::IObject getTop();
};
-class ArchiveWriter {
- std::ofstream m_outfile;
- Alembic::Abc::OArchive m_archive;
-
- public:
- ArchiveWriter(const char *filename,
- const std::string &abc_scene_name,
- const Scene *scene,
- bool do_ogawa);
-
- Alembic::Abc::OArchive &archive();
-};
-
-#endif /* __ABC_ARCHIVE_H__ */
+#endif /* __ABC_READER_ARCHIVE_H__ */
diff --git a/source/blender/alembic/intern/abc_camera.cc b/source/blender/alembic/intern/abc_reader_camera.cc
index dc7f00b63d9..ab506f32cbe 100644
--- a/source/blender/alembic/intern/abc_camera.cc
+++ b/source/blender/alembic/intern/abc_reader_camera.cc
@@ -18,9 +18,8 @@
* \ingroup balembic
*/
-#include "abc_camera.h"
-
-#include "abc_transform.h"
+#include "abc_reader_camera.h"
+#include "abc_reader_transform.h"
#include "abc_util.h"
extern "C" {
@@ -31,75 +30,15 @@ extern "C" {
#include "BKE_object.h"
#include "BLI_math.h"
-#include "BLI_string.h"
}
+using Alembic::AbcGeom::CameraSample;
using Alembic::AbcGeom::ICamera;
using Alembic::AbcGeom::ICompoundProperty;
using Alembic::AbcGeom::IFloatProperty;
using Alembic::AbcGeom::ISampleSelector;
-
-using Alembic::AbcGeom::OCamera;
-using Alembic::AbcGeom::OFloatProperty;
-
-using Alembic::AbcGeom::CameraSample;
using Alembic::AbcGeom::kWrapExisting;
-/* ************************************************************************** */
-
-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);
-}
-
-/* ************************************************************************** */
-
AbcCameraReader::AbcCameraReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
: AbcObjectReader(object, settings)
{
diff --git a/source/blender/alembic/intern/abc_reader_camera.h b/source/blender/alembic/intern/abc_reader_camera.h
new file mode 100644
index 00000000000..1d9763b0454
--- /dev/null
+++ b/source/blender/alembic/intern/abc_reader_camera.h
@@ -0,0 +1,40 @@
+/*
+ * 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_READER_CAMERA_H__
+#define __ABC_READER_CAMERA_H__
+
+#include "abc_reader_object.h"
+
+class AbcCameraReader : public AbcObjectReader {
+ Alembic::AbcGeom::ICameraSchema m_schema;
+
+ public:
+ AbcCameraReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
+
+ bool valid() const;
+ bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const;
+
+ void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
+};
+
+#endif /* __ABC_READER_CAMERA_H__ */
diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_reader_curves.cc
index 3b143356c04..1be164c7c94 100644
--- a/source/blender/alembic/intern/abc_curves.cc
+++ b/source/blender/alembic/intern/abc_reader_curves.cc
@@ -21,13 +21,12 @@
* \ingroup balembic
*/
-#include "abc_curves.h"
+#include "abc_reader_curves.h"
+#include "abc_reader_transform.h"
+#include "abc_util.h"
#include <cstdio>
-#include "abc_transform.h"
-#include "abc_util.h"
-
#include "MEM_guardedalloc.h"
extern "C" {
@@ -39,12 +38,9 @@ extern "C" {
#include "BKE_curve.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
-
-#include "ED_curve.h"
}
using Alembic::Abc::FloatArraySamplePtr;
-using Alembic::Abc::IInt32ArrayProperty;
using Alembic::Abc::Int32ArraySamplePtr;
using Alembic::Abc::P3fArraySamplePtr;
using Alembic::Abc::PropertyHeader;
@@ -59,165 +55,6 @@ using Alembic::AbcGeom::IInt16Property;
using Alembic::AbcGeom::ISampleSelector;
using Alembic::AbcGeom::kWrapExisting;
-using Alembic::AbcGeom::OCompoundProperty;
-using Alembic::AbcGeom::OCurves;
-using Alembic::AbcGeom::OCurvesSchema;
-using Alembic::AbcGeom::OInt16Property;
-using Alembic::AbcGeom::ON3fGeomParam;
-using Alembic::AbcGeom::OV2fGeomParam;
-
-#define ABC_CURVE_RESOLUTION_U_PROPNAME "blender:resolution"
-
-/* ************************************************************************** */
-
-AbcCurveWriter::AbcCurveWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings)
- : AbcObjectWriter(ob, time_sampling, settings, parent)
-{
- OCurves curves(parent->alembicXform(), m_name, m_time_sampling);
- m_schema = curves.getSchema();
-
- Curve *cu = static_cast<Curve *>(m_object->data);
- OCompoundProperty user_props = m_schema.getUserProperties();
- OInt16Property user_prop_resolu(user_props, ABC_CURVE_RESOLUTION_U_PROPNAME);
- user_prop_resolu.set(cu->resolu);
-}
-
-void AbcCurveWriter::do_write()
-{
- Curve *curve = static_cast<Curve *>(m_object->data);
-
- std::vector<Imath::V3f> verts;
- std::vector<int32_t> vert_counts;
- std::vector<float> widths;
- std::vector<float> weights;
- std::vector<float> knots;
- std::vector<uint8_t> orders;
- Imath::V3f temp_vert;
-
- Alembic::AbcGeom::BasisType curve_basis;
- Alembic::AbcGeom::CurveType curve_type;
- Alembic::AbcGeom::CurvePeriodicity periodicity;
-
- Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);
- for (; nurbs; nurbs = nurbs->next) {
- if (nurbs->bp) {
- curve_basis = Alembic::AbcGeom::kNoBasis;
- curve_type = Alembic::AbcGeom::kVariableOrder;
-
- const int totpoint = nurbs->pntsu * nurbs->pntsv;
-
- const BPoint *point = nurbs->bp;
-
- for (int i = 0; i < totpoint; i++, point++) {
- copy_yup_from_zup(temp_vert.getValue(), point->vec);
- verts.push_back(temp_vert);
- weights.push_back(point->vec[3]);
- widths.push_back(point->radius);
- }
- }
- else if (nurbs->bezt) {
- curve_basis = Alembic::AbcGeom::kBezierBasis;
- curve_type = Alembic::AbcGeom::kCubic;
-
- const int totpoint = nurbs->pntsu;
-
- const BezTriple *bezier = nurbs->bezt;
-
- /* TODO(kevin): store info about handles, Alembic doesn't have this. */
- for (int i = 0; i < totpoint; i++, bezier++) {
- copy_yup_from_zup(temp_vert.getValue(), bezier->vec[1]);
- verts.push_back(temp_vert);
- widths.push_back(bezier->radius);
- }
- }
-
- if ((nurbs->flagu & CU_NURB_ENDPOINT) != 0) {
- periodicity = Alembic::AbcGeom::kNonPeriodic;
- }
- else if ((nurbs->flagu & CU_NURB_CYCLIC) != 0) {
- periodicity = Alembic::AbcGeom::kPeriodic;
-
- /* Duplicate the start points to indicate that the curve is actually
- * cyclic since other software need those.
- */
-
- for (int i = 0; i < nurbs->orderu; i++) {
- verts.push_back(verts[i]);
- }
- }
-
- if (nurbs->knotsu != NULL) {
- const size_t num_knots = KNOTSU(nurbs);
-
- /* Add an extra knot at the beginning and end of the array since most apps
- * require/expect them. */
- knots.resize(num_knots + 2);
-
- for (int i = 0; i < num_knots; i++) {
- knots[i + 1] = nurbs->knotsu[i];
- }
-
- if ((nurbs->flagu & CU_NURB_CYCLIC) != 0) {
- knots[0] = nurbs->knotsu[0];
- knots[num_knots - 1] = nurbs->knotsu[num_knots - 1];
- }
- else {
- knots[0] = (2.0f * nurbs->knotsu[0] - nurbs->knotsu[1]);
- knots[num_knots - 1] = (2.0f * nurbs->knotsu[num_knots - 1] -
- nurbs->knotsu[num_knots - 2]);
- }
- }
-
- orders.push_back(nurbs->orderu);
- vert_counts.push_back(verts.size());
- }
-
- 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);
-}
-
-AbcCurveMeshWriter::AbcCurveMeshWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings)
- : AbcGenericMeshWriter(ob, parent, time_sampling, settings)
-{
-}
-
-Mesh *AbcCurveMeshWriter::getEvaluatedMesh(Scene * /*scene_eval*/,
- Object *ob_eval,
- bool &r_needsfree)
-{
- if (ob_eval->runtime.mesh_eval != NULL) {
- /* Mesh_eval only exists when generative modifiers are in use. */
- r_needsfree = false;
- return ob_eval->runtime.mesh_eval;
- }
-
- r_needsfree = true;
- return BKE_mesh_new_nomain_from_curve(ob_eval);
-}
-
-/* ************************************************************************** */
-
AbcCurveReader::AbcCurveReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
: AbcObjectReader(object, settings)
{
@@ -279,8 +116,6 @@ void AbcCurveReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSele
}
}
-/* ************************************************************************** */
-
void AbcCurveReader::read_curve_sample(Curve *cu,
const ICurvesSchema &schema,
const ISampleSelector &sample_sel)
diff --git a/source/blender/alembic/intern/abc_curves.h b/source/blender/alembic/intern/abc_reader_curves.h
index 6636558356f..1e4f28edc51 100644
--- a/source/blender/alembic/intern/abc_curves.h
+++ b/source/blender/alembic/intern/abc_reader_curves.h
@@ -21,42 +21,15 @@
* \ingroup balembic
*/
-#ifndef __ABC_CURVES_H__
-#define __ABC_CURVES_H__
+#ifndef __ABC_READER_CURVES_H__
+#define __ABC_READER_CURVES_H__
-#include "abc_object.h"
-#include "abc_mesh.h"
+#include "abc_reader_object.h"
+#include "abc_reader_mesh.h"
struct Curve;
-/* ************************************************************************** */
-
-class AbcCurveWriter : public AbcObjectWriter {
- Alembic::AbcGeom::OCurvesSchema m_schema;
- Alembic::AbcGeom::OCurvesSchema::Sample m_sample;
-
- public:
- AbcCurveWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings);
-
- protected:
- void do_write();
-};
-
-class AbcCurveMeshWriter : public AbcGenericMeshWriter {
- public:
- AbcCurveMeshWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings);
-
- protected:
- Mesh *getEvaluatedMesh(Scene *scene_eval, Object *ob_eval, bool &r_needsfree);
-};
-
-/* ************************************************************************** */
+#define ABC_CURVE_RESOLUTION_U_PROPNAME "blender:resolution"
class AbcCurveReader : public AbcObjectReader {
Alembic::AbcGeom::ICurvesSchema m_curves_schema;
@@ -80,6 +53,4 @@ class AbcCurveReader : public AbcObjectReader {
const Alembic::Abc::ISampleSelector &sample_selector);
};
-/* ************************************************************************** */
-
-#endif /* __ABC_CURVES_H__ */
+#endif /* __ABC_READER_CURVES_H__ */
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_reader_mesh.cc
index 991fa02e4be..a4e412695c3 100644
--- a/source/blender/alembic/intern/abc_mesh.cc
+++ b/source/blender/alembic/intern/abc_reader_mesh.cc
@@ -18,58 +18,35 @@
* \ingroup balembic
*/
-#include "abc_mesh.h"
+#include "abc_reader_mesh.h"
+#include "abc_reader_transform.h"
+#include "abc_util.h"
#include <algorithm>
-#include "abc_transform.h"
-#include "abc_util.h"
-
#include "MEM_guardedalloc.h"
extern "C" {
#include "DNA_material_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_object_types.h"
#include "BLI_math_geom.h"
-#include "BLI_string.h"
-#include "BKE_animsys.h"
-#include "BKE_key.h"
-#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
-#include "BKE_mesh_runtime.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
-
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "ED_mesh.h"
-
-#include "bmesh.h"
-#include "bmesh_tools.h"
-
-#include "DEG_depsgraph_query.h"
}
-using Alembic::Abc::C4fArraySample;
-using Alembic::Abc::FloatArraySample;
-using Alembic::Abc::ICompoundProperty;
-using Alembic::Abc::Int32ArraySample;
using Alembic::Abc::Int32ArraySamplePtr;
using Alembic::Abc::P3fArraySamplePtr;
-using Alembic::Abc::V2fArraySample;
-using Alembic::Abc::V3fArraySample;
using Alembic::AbcGeom::IFaceSet;
using Alembic::AbcGeom::IFaceSetSchema;
+using Alembic::AbcGeom::IN3fGeomParam;
using Alembic::AbcGeom::IObject;
using Alembic::AbcGeom::IPolyMesh;
using Alembic::AbcGeom::IPolyMeshSchema;
@@ -77,570 +54,14 @@ using Alembic::AbcGeom::ISampleSelector;
using Alembic::AbcGeom::ISubD;
using Alembic::AbcGeom::ISubDSchema;
using Alembic::AbcGeom::IV2fGeomParam;
-
-using Alembic::AbcGeom::OArrayProperty;
-using Alembic::AbcGeom::OBoolProperty;
-using Alembic::AbcGeom::OC3fArrayProperty;
-using Alembic::AbcGeom::OC3fGeomParam;
-using Alembic::AbcGeom::OC4fGeomParam;
-using Alembic::AbcGeom::OCompoundProperty;
-using Alembic::AbcGeom::OFaceSet;
-using Alembic::AbcGeom::OFaceSetSchema;
-using Alembic::AbcGeom::OFloatGeomParam;
-using Alembic::AbcGeom::OInt32GeomParam;
-using Alembic::AbcGeom::ON3fArrayProperty;
-using Alembic::AbcGeom::ON3fGeomParam;
-using Alembic::AbcGeom::OPolyMesh;
-using Alembic::AbcGeom::OPolyMeshSchema;
-using Alembic::AbcGeom::OSubD;
-using Alembic::AbcGeom::OSubDSchema;
-using Alembic::AbcGeom::OV2fGeomParam;
-using Alembic::AbcGeom::OV3fGeomParam;
-
-using Alembic::AbcGeom::IN3fGeomParam;
-using Alembic::AbcGeom::kFacevaryingScope;
-using Alembic::AbcGeom::kVaryingScope;
-using Alembic::AbcGeom::kVertexScope;
using Alembic::AbcGeom::kWrapExisting;
using Alembic::AbcGeom::N3fArraySample;
using Alembic::AbcGeom::N3fArraySamplePtr;
-using Alembic::AbcGeom::UInt32ArraySample;
-
-/* ************************************************************************** */
+using Alembic::AbcGeom::UInt32ArraySamplePtr;
+using Alembic::AbcGeom::V2fArraySamplePtr;
/* 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);
- }
-}
-
-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);
-}
-
-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)) {
- 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]);
- }
- }
-}
-
-/* *************** 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)
-{
- ModifierData *md = static_cast<ModifierData *>(ob->modifiers.last);
-
- for (; md; md = md->prev) {
- if (!modifier_isEnabled(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;
- }
- }
-
- return NULL;
-}
-
-static ModifierData *get_liquid_sim_modifier(Scene *scene, Object *ob)
-{
- ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim);
-
- if (md && (modifier_isEnabled(scene, md, eModifierMode_Render))) {
- FluidsimModifierData *fsmd = reinterpret_cast<FluidsimModifierData *>(md);
-
- if (fsmd->fss && fsmd->fss->type == OB_FLUIDSIM_DOMAIN) {
- return md;
- }
- }
-
- return NULL;
-}
-
-/* ************************************************************************** */
-
-AbcGenericMeshWriter::AbcGenericMeshWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings)
- : AbcObjectWriter(ob, time_sampling, settings, parent)
-{
- 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;
- }
-
- if (!m_settings.apply_subdiv) {
- m_subsurf_mod = get_subsurf_modifier(m_settings.scene, m_object);
- m_is_subd = (m_subsurf_mod != NULL);
- }
-
- m_is_liquid = (get_liquid_sim_modifier(m_settings.scene, m_object) != NULL);
-
- while (parent->alembicXform().getChildHeader(m_name)) {
- m_name.append("_");
- }
-
- 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);
- }
-}
-
-AbcGenericMeshWriter::~AbcGenericMeshWriter()
-{
- if (m_subsurf_mod) {
- m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary;
- }
-}
-
-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;
- }
-
- /* Test modifiers. */
- ModifierData *md = static_cast<ModifierData *>(m_object->modifiers.first);
- while (md) {
-
- if (md->type != eModifierType_Subsurf) {
- return true;
- }
-
- md = md->next;
- }
-
- return false;
-}
-
-void AbcGenericMeshWriter::setIsAnimated(bool is_animated)
-{
- m_is_animated = is_animated;
-}
-
-void AbcGenericMeshWriter::do_write()
-{
- /* We have already stored a sample for this object. */
- if (!m_first_frame && !m_is_animated) {
- return;
- }
-
- bool needsfree;
- struct Mesh *mesh = getFinalMesh(needsfree);
-
- try {
- if (m_settings.use_subdiv_schema && m_subdiv_schema.valid()) {
- writeSubD(mesh);
- }
- else {
- writeMesh(mesh);
- }
-
- if (needsfree) {
- freeEvaluatedMesh(mesh);
- }
- }
- catch (...) {
- if (needsfree) {
- freeEvaluatedMesh(mesh);
- }
- throw;
- }
-}
-
-void AbcGenericMeshWriter::freeEvaluatedMesh(struct Mesh *mesh)
-{
- BKE_id_free(NULL, mesh);
-}
-
-void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh)
-{
- std::vector<Imath::V3f> points, normals;
- std::vector<int32_t> poly_verts, loop_counts;
- std::vector<Imath::V3f> velocities;
- bool has_flat_shaded_poly = false;
-
- 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);
- }
-
- m_mesh_sample = OPolyMeshSchema::Sample(
- V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts));
-
- UVSample sample;
- if (m_first_frame && m_settings.export_uvs) {
- const char *name = get_uv_sample(sample, m_custom_data_config, &mesh->ldata);
-
- if (!sample.indices.empty() && !sample.uvs.empty()) {
- OV2fGeomParam::Sample uv_sample;
- uv_sample.setVals(V2fArraySample(sample.uvs));
- uv_sample.setIndices(UInt32ArraySample(sample.indices));
- uv_sample.setScope(kFacevaryingScope);
-
- m_mesh_schema.setUVSourceName(name);
- m_mesh_sample.setUVs(uv_sample);
- }
-
- write_custom_data(
- m_mesh_schema.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
- }
-
- if (m_settings.export_normals) {
- get_loop_normals(mesh, normals, has_flat_shaded_poly);
-
- ON3fGeomParam::Sample normals_sample;
- if (!normals.empty()) {
- normals_sample.setScope(kFacevaryingScope);
- normals_sample.setVals(V3fArraySample(normals));
- }
-
- m_mesh_sample.setNormals(normals_sample);
- }
-
- if (m_is_liquid) {
- getVelocities(mesh, velocities);
- m_mesh_sample.setVelocities(V3fArraySample(velocities));
- }
-
- m_mesh_sample.setSelfBounds(bounds());
-
- m_mesh_schema.set(m_mesh_sample);
-
- writeArbGeoParams(mesh);
-}
-
-void AbcGenericMeshWriter::writeSubD(struct Mesh *mesh)
-{
- std::vector<float> crease_sharpness;
- std::vector<Imath::V3f> points;
- std::vector<int32_t> poly_verts, loop_counts;
- std::vector<int32_t> crease_indices, crease_lengths;
- bool has_flat_poly = false;
-
- get_vertices(mesh, points);
- 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);
- }
-
- m_subdiv_sample = OSubDSchema::Sample(
- V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts));
-
- UVSample sample;
- if (m_first_frame && m_settings.export_uvs) {
- const char *name = get_uv_sample(sample, m_custom_data_config, &mesh->ldata);
-
- if (!sample.indices.empty() && !sample.uvs.empty()) {
- OV2fGeomParam::Sample uv_sample;
- uv_sample.setVals(V2fArraySample(sample.uvs));
- uv_sample.setIndices(UInt32ArraySample(sample.indices));
- uv_sample.setScope(kFacevaryingScope);
-
- m_subdiv_schema.setUVSourceName(name);
- m_subdiv_sample.setUVs(uv_sample);
- }
-
- write_custom_data(
- m_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));
- }
-
- m_subdiv_sample.setSelfBounds(bounds());
- m_subdiv_schema.set(m_subdiv_sample);
-
- writeArbGeoParams(mesh);
-}
-
-template<typename Schema> void AbcGenericMeshWriter::writeFaceSets(struct Mesh *me, Schema &schema)
-{
- std::map<std::string, std::vector<int32_t>> geo_groups;
- getGeoGroups(me, geo_groups);
-
- std::map<std::string, std::vector<int32_t>>::iterator it;
- for (it = geo_groups.begin(); it != geo_groups.end(); ++it) {
- OFaceSet face_set = schema.createFaceSet(it->first);
- OFaceSetSchema::Sample samp;
- samp.setFaces(Int32ArraySample(it->second));
- face_set.getSchema().set(samp);
- }
-}
-
-Mesh *AbcGenericMeshWriter::getFinalMesh(bool &r_needsfree)
-{
- /* 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;
- }
-
- 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. */
- 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);
- }
- }
-}
-
-void AbcGenericMeshWriter::getVelocities(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);
- FluidsimSettings *fss = fmd->fss;
-
- if (fss->meshVelocities) {
- float *mesh_vels = reinterpret_cast<float *>(fss->meshVelocities);
-
- for (int i = 0; i < totverts; i++) {
- copy_yup_from_zup(vels[i].getValue(), mesh_vels);
- mesh_vels += 3;
- }
- }
- else {
- std::fill(vels.begin(), vels.end(), Imath::V3f(0.0f));
- }
-}
-
-void AbcGenericMeshWriter::getGeoGroups(struct Mesh *mesh,
- std::map<std::string, std::vector<int32_t>> &geo_groups)
-{
- const int num_poly = mesh->totpoly;
- MPoly *polygons = mesh->mpoly;
-
- for (int i = 0; i < num_poly; i++) {
- MPoly &current_poly = polygons[i];
- short mnr = current_poly.mat_nr;
-
- Material *mat = BKE_object_material_get(m_object, mnr + 1);
-
- if (!mat) {
- continue;
- }
-
- std::string name = get_id_name(&mat->id);
-
- if (geo_groups.find(name) == geo_groups.end()) {
- std::vector<int32_t> faceArray;
- geo_groups[name] = faceArray;
- }
-
- geo_groups[name].push_back(i);
- }
-
- if (geo_groups.size() == 0) {
- Material *mat = BKE_object_material_get(m_object, 1);
-
- std::string name = (mat) ? get_id_name(&mat->id) : "default";
-
- std::vector<int32_t> faceArray;
-
- for (int i = 0, e = mesh->totface; i < e; i++) {
- faceArray.push_back(i);
- }
-
- geo_groups[name] = faceArray;
- }
-}
-
-AbcMeshWriter::AbcMeshWriter(Object *ob,
- AbcTransformWriter *parent,
- uint32_t time_sampling,
- ExportSettings &settings)
- : AbcGenericMeshWriter(ob, parent, time_sampling, settings)
-{
-}
-
-AbcMeshWriter::~AbcMeshWriter()
-{
-}
-
-Mesh *AbcMeshWriter::getEvaluatedMesh(Scene *scene_eval,
- Object *ob_eval,
- bool &UNUSED(r_needsfree))
-{
- return mesh_get_eval_final(m_settings.depsgraph, scene_eval, ob_eval, &CD_MASK_MESH);
-}
-
-/* ************************************************************************** */
-
/* Some helpers for mesh generation */
namespace utils {
@@ -698,11 +119,6 @@ static void assign_materials(Main *bmain,
} /* namespace utils */
-/* ************************************************************************** */
-
-using Alembic::AbcGeom::UInt32ArraySamplePtr;
-using Alembic::AbcGeom::V2fArraySamplePtr;
-
struct AbcMeshData {
Int32ArraySamplePtr face_indices;
Int32ArraySamplePtr face_counts;
diff --git a/source/blender/alembic/intern/abc_mesh.h b/source/blender/alembic/intern/abc_reader_mesh.h
index 38c589bbc32..bc95c7ec134 100644
--- a/source/blender/alembic/intern/abc_mesh.h
+++ b/source/blender/alembic/intern/abc_reader_mesh.h
@@ -18,79 +18,13 @@
* \ingroup balembic
*/
-#ifndef __ABC_MESH_H__
-#define __ABC_MESH_H__
+#ifndef __ABC_READER_MESH_H__
+#define __ABC_READER_MESH_H__
#include "abc_customdata.h"
-#include "abc_object.h"
+#include "abc_reader_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;
-};
-
-/* ************************************************************************** */
class AbcMeshReader : public AbcObjectReader {
Alembic::AbcGeom::IPolyMeshSchema m_schema;
@@ -124,8 +58,6 @@ class AbcMeshReader : public AbcObjectReader {
std::map<std::string, int> &r_mat_map);
};
-/* ************************************************************************** */
-
class AbcSubDReader : public AbcObjectReader {
Alembic::AbcGeom::ISubDSchema m_schema;
@@ -145,12 +77,10 @@ class AbcSubDReader : public AbcObjectReader {
const char **err_str);
};
-/* ************************************************************************** */
-
void read_mverts(MVert *mverts,
const Alembic::AbcGeom::P3fArraySamplePtr positions,
const Alembic::AbcGeom::N3fArraySamplePtr normals);
CDStreamConfig get_config(struct Mesh *mesh);
-#endif /* __ABC_MESH_H__ */
+#endif /* __ABC_READER_MESH_H__ */
diff --git a/source/blender/alembic/intern/abc_nurbs.cc b/source/blender/alembic/intern/abc_reader_nurbs.cc
index c11ca7d57b9..0ada10baba5 100644
--- a/source/blender/alembic/intern/abc_nurbs.cc
+++ b/source/blender/alembic/intern/abc_reader_nurbs.cc
@@ -18,9 +18,8 @@
* \ingroup balembic
*/
-#include "abc_nurbs.h"
-
-#include "abc_transform.h"
+#include "abc_reader_nurbs.h"
+#include "abc_reader_transform.h"
#include "abc_util.h"
#include "MEM_guardedalloc.h"
@@ -30,169 +29,21 @@ extern "C" {
#include "DNA_object_types.h"
#include "BLI_listbase.h"
-#include "BLI_math.h"
#include "BLI_string.h"
#include "BKE_curve.h"
#include "BKE_object.h"
}
-using Alembic::AbcGeom::bool_t;
-using Alembic::AbcGeom::FloatArraySample;
using Alembic::AbcGeom::FloatArraySamplePtr;
using Alembic::AbcGeom::kWrapExisting;
using Alembic::AbcGeom::MetaData;
using Alembic::AbcGeom::P3fArraySamplePtr;
-using Alembic::AbcGeom::IBoolProperty;
using Alembic::AbcGeom::ICompoundProperty;
using Alembic::AbcGeom::INuPatch;
using Alembic::AbcGeom::INuPatchSchema;
using Alembic::AbcGeom::IObject;
-using Alembic::AbcGeom::ISampleSelector;
-
-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)
-{
- 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);
-
- for (size_t i = 0; i < numNurbs; i++) {
- std::stringstream str;
- str << m_name << '_' << i;
-
- while (parent->alembicXform().getChildHeader(str.str())) {
- str << "_";
- }
-
- ONuPatch nurbs(parent->alembicXform(), str.str().c_str(), m_time_sampling);
- m_nurbs_schema.push_back(nurbs.getSchema());
- }
-}
-
-bool AbcNurbsWriter::isAnimated() const
-{
- /* check if object has shape keys */
- Curve *cu = static_cast<Curve *>(m_object->data);
- return (cu->key != NULL);
-}
-
-static void get_knots(std::vector<float> &knots, const int num_knots, float *nu_knots)
-{
- if (num_knots <= 1) {
- return;
- }
-
- /* Add an extra knot at the beginning and end of the array since most apps
- * require/expect them. */
- knots.reserve(num_knots + 2);
-
- knots.push_back(0.0f);
-
- for (int i = 0; i < num_knots; i++) {
- knots.push_back(nu_knots[i]);
- }
-
- knots[0] = 2.0f * knots[1] - knots[2];
- knots.push_back(2.0f * knots[num_knots] - knots[num_knots - 1]);
-}
-
-void AbcNurbsWriter::do_write()
-{
- /* 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);
- ListBase *nulb;
-
- if (m_object->runtime.curve_cache->deformed_nurbs.first != NULL) {
- nulb = &m_object->runtime.curve_cache->deformed_nurbs;
- }
- else {
- nulb = BKE_curve_nurbs_get(curve);
- }
-
- size_t count = 0;
- for (Nurb *nu = static_cast<Nurb *>(nulb->first); nu; nu = nu->next, count++) {
- std::vector<float> knotsU;
- get_knots(knotsU, KNOTSU(nu), nu->knotsu);
-
- std::vector<float> knotsV;
- get_knots(knotsV, KNOTSV(nu), nu->knotsv);
-
- const int size = nu->pntsu * nu->pntsv;
- std::vector<Imath::V3f> positions(size);
- std::vector<float> weights(size);
-
- const BPoint *bp = nu->bp;
-
- for (int i = 0; i < size; i++, bp++) {
- copy_yup_from_zup(positions[i].getValue(), bp->vec);
- weights[i] = bp->vec[3];
- }
-
- ONuPatchSchema::Sample sample;
- sample.setUOrder(nu->orderu + 1);
- sample.setVOrder(nu->orderv + 1);
- sample.setPositions(positions);
- sample.setPositionWeights(weights);
- sample.setUKnot(FloatArraySample(knotsU));
- sample.setVKnot(FloatArraySample(knotsV));
- sample.setNu(nu->pntsu);
- sample.setNv(nu->pntsv);
-
- /* 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();
-
- if ((nu->flagu & CU_NURB_ENDPOINT) != 0) {
- OBoolProperty prop(user_props, "endpoint_u");
- prop.set(true);
- }
-
- if ((nu->flagv & CU_NURB_ENDPOINT) != 0) {
- OBoolProperty prop(user_props, "endpoint_v");
- prop.set(true);
- }
-
- if ((nu->flagu & CU_NURB_CYCLIC) != 0) {
- OBoolProperty prop(user_props, "cyclic_u");
- prop.set(true);
- }
-
- if ((nu->flagv & CU_NURB_CYCLIC) != 0) {
- OBoolProperty prop(user_props, "cyclic_v");
- prop.set(true);
- }
-
- m_nurbs_schema[count].set(sample);
- }
-}
-
-/* ************************************************************************** */
AbcNurbsReader::AbcNurbsReader(const IObject &object, ImportSettings &settings)
: AbcObjectReader(object, settings)
diff --git a/source/blender/alembic/intern/abc_nurbs.h b/source/blender/alembic/intern/abc_reader_nurbs.h
index 3e12c9a3b62..f4284c136fb 100644
--- a/source/blender/alembic/intern/abc_nurbs.h
+++ b/source/blender/alembic/intern/abc_reader_nurbs.h
@@ -18,30 +18,10 @@
* \ingroup balembic
*/
-#ifndef __ABC_NURBS_H__
-#define __ABC_NURBS_H__
+#ifndef __ABC_READER_NURBS_H__
+#define __ABC_READER_NURBS_H__
-#include "abc_object.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);
-
- private:
- virtual void do_write();
-
- bool isAnimated() const;
-};
-
-/* ************************************************************************** */
+#include "abc_reader_object.h"
class AbcNurbsReader : public AbcObjectReader {
std::vector<std::pair<Alembic::AbcGeom::INuPatchSchema, Alembic::Abc::IObject>> m_schemas;
@@ -57,4 +37,4 @@ class AbcNurbsReader : public AbcObjectReader {
void getNurbsPatches(const Alembic::Abc::IObject &obj);
};
-#endif /* __ABC_NURBS_H__ */
+#endif /* __ABC_READER_NURBS_H__ */
diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_reader_object.cc
index 76aec9ad998..3e7f87d78cc 100644
--- a/source/blender/alembic/intern/abc_object.cc
+++ b/source/blender/alembic/intern/abc_reader_object.cc
@@ -18,25 +18,23 @@
* \ingroup balembic
*/
-#include "abc_object.h"
-
+#include "abc_reader_object.h"
#include "abc_util.h"
extern "C" {
#include "DNA_cachefile_types.h"
#include "DNA_constraint_types.h"
#include "DNA_modifier_types.h"
-#include "DNA_object_types.h"
#include "DNA_space_types.h" /* for FILE_MAX */
#include "BKE_constraint.h"
-#include "BKE_idprop.h"
#include "BKE_lib_id.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
+#include "BLI_utildefines.h"
#include "BLI_listbase.h"
-#include "BLI_math.h"
+#include "BLI_math_geom.h"
#include "BLI_string.h"
}
@@ -44,72 +42,6 @@ using Alembic::AbcGeom::IObject;
using Alembic::AbcGeom::IXform;
using Alembic::AbcGeom::IXformSchema;
-using Alembic::AbcGeom::OCompoundProperty;
-using Alembic::AbcGeom::ODoubleArrayProperty;
-using Alembic::AbcGeom::ODoubleProperty;
-using Alembic::AbcGeom::OFloatArrayProperty;
-using Alembic::AbcGeom::OFloatProperty;
-using Alembic::AbcGeom::OInt32ArrayProperty;
-using Alembic::AbcGeom::OInt32Property;
-using Alembic::AbcGeom::OStringArrayProperty;
-using Alembic::AbcGeom::OStringProperty;
-
-/* ************************************************************************** */
-
-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;
-}
-
-/* ************************************************************************** */
-
AbcObjectReader::AbcObjectReader(const IObject &object, ImportSettings &settings)
: m_name(""),
m_object_name(""),
diff --git a/source/blender/alembic/intern/abc_object.h b/source/blender/alembic/intern/abc_reader_object.h
index efe78b9017c..94923df2df9 100644
--- a/source/blender/alembic/intern/abc_object.h
+++ b/source/blender/alembic/intern/abc_reader_object.h
@@ -18,61 +18,22 @@
* \ingroup balembic
*/
-#ifndef __ABC_OBJECT_H__
-#define __ABC_OBJECT_H__
+#ifndef __ABC_READER_OBJECT_H__
+#define __ABC_READER_OBJECT_H__
#include <Alembic/Abc/All.h>
#include <Alembic/AbcGeom/All.h>
-#include "abc_exporter.h"
-
extern "C" {
#include "DNA_ID.h"
}
-class AbcTransformWriter;
-
+struct CacheFile;
struct Main;
+struct Mesh;
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;
-};
-
-/* ************************************************************************** */
-
-struct CacheFile;
+using Alembic::AbcCoreAbstract::chrono_t;
struct ImportSettings {
bool do_convert_mat;
@@ -116,12 +77,6 @@ template<typename Schema> static bool has_animations(Schema &schema, ImportSetti
return settings->is_sequence || !schema.isConstant();
}
-/* ************************************************************************** */
-
-struct Mesh;
-
-using Alembic::AbcCoreAbstract::chrono_t;
-
class AbcObjectReader {
protected:
std::string m_name;
@@ -213,4 +168,4 @@ class AbcObjectReader {
Imath::M44d get_matrix(const Alembic::AbcGeom::IXformSchema &schema, const float time);
-#endif /* __ABC_OBJECT_H__ */
+#endif /* __ABC_READER_OBJECT_H__ */
diff --git a/source/blender/alembic/intern/abc_points.cc b/source/blender/alembic/intern/abc_reader_points.cc
index d691087ca21..e4dc345f868 100644
--- a/source/blender/alembic/intern/abc_points.cc
+++ b/source/blender/alembic/intern/abc_reader_points.cc
@@ -21,29 +21,20 @@
* \ingroup balembic
*/
-#include "abc_points.h"
-
-#include "abc_mesh.h"
-#include "abc_transform.h"
+#include "abc_reader_points.h"
+#include "abc_reader_mesh.h"
+#include "abc_reader_transform.h"
#include "abc_util.h"
extern "C" {
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
-#include "BKE_cdderivedmesh.h"
-#include "BKE_lattice.h"
+#include "BKE_customdata.h"
#include "BKE_mesh.h"
#include "BKE_object.h"
-#include "BKE_particle.h"
-#include "BKE_scene.h"
-
-#include "BLI_math.h"
-
-#include "DEG_depsgraph_query.h"
}
-using Alembic::AbcGeom::kVertexScope;
using Alembic::AbcGeom::kWrapExisting;
using Alembic::AbcGeom::N3fArraySamplePtr;
using Alembic::AbcGeom::P3fArraySamplePtr;
@@ -54,91 +45,6 @@ using Alembic::AbcGeom::IPoints;
using Alembic::AbcGeom::IPointsSchema;
using Alembic::AbcGeom::ISampleSelector;
-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) {
- end_latt_deform(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);
-}
-
-/* ************************************************************************** */
-
AbcPointsReader::AbcPointsReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
: AbcObjectReader(object, settings)
{
diff --git a/source/blender/alembic/intern/abc_points.h b/source/blender/alembic/intern/abc_reader_points.h
index 5eb448f0f66..31ad6c4589b 100644
--- a/source/blender/alembic/intern/abc_points.h
+++ b/source/blender/alembic/intern/abc_reader_points.h
@@ -21,33 +21,12 @@
* \ingroup balembic
*/
-#ifndef __ABC_POINTS_H__
-#define __ABC_POINTS_H__
+#ifndef __ABC_READER_POINTS_H__
+#define __ABC_READER_POINTS_H__
-#include "abc_object.h"
+#include "abc_reader_object.h"
#include "abc_customdata.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();
-};
-
-/* ************************************************************************** */
-
class AbcPointsReader : public AbcObjectReader {
Alembic::AbcGeom::IPointsSchema m_schema;
Alembic::AbcGeom::IPointsSchema::Sample m_sample;
@@ -72,4 +51,4 @@ void read_points_sample(const Alembic::AbcGeom::IPointsSchema &schema,
const Alembic::AbcGeom::ISampleSelector &selector,
CDStreamConfig &config);
-#endif /* __ABC_POINTS_H__ */
+#endif /* __ABC_READER_POINTS_H__ */
diff --git a/source/blender/alembic/intern/abc_reader_transform.cc b/source/blender/alembic/intern/abc_reader_transform.cc
new file mode 100644
index 00000000000..ce569a9ccb5
--- /dev/null
+++ b/source/blender/alembic/intern/abc_reader_transform.cc
@@ -0,0 +1,76 @@
+/*
+ * 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_reader_transform.h"
+#include "abc_util.h"
+
+extern "C" {
+#include "DNA_object_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_object.h"
+}
+
+using Alembic::Abc::ISampleSelector;
+
+AbcEmptyReader::AbcEmptyReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
+ : AbcObjectReader(object, settings)
+{
+ /* Empties have no data. It makes the import of Alembic files easier to
+ * understand when we name the empty after its name in Alembic. */
+ m_object_name = object.getName();
+
+ Alembic::AbcGeom::IXform xform(object, Alembic::AbcGeom::kWrapExisting);
+ m_schema = xform.getSchema();
+
+ get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time);
+}
+
+bool AbcEmptyReader::valid() const
+{
+ return m_schema.valid();
+}
+
+bool AbcEmptyReader::accepts_object_type(
+ const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const
+{
+ if (!Alembic::AbcGeom::IXform::matches(alembic_header)) {
+ *err_str =
+ "Object type mismatch, Alembic object path pointed to XForm when importing, but not any "
+ "more.";
+ return false;
+ }
+
+ if (ob->type != OB_EMPTY) {
+ *err_str = "Object type mismatch, Alembic object path points to XForm.";
+ return false;
+ }
+
+ return true;
+}
+
+void AbcEmptyReader::readObjectData(Main *bmain, const ISampleSelector &UNUSED(sample_sel))
+{
+ m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_object_name.c_str());
+ m_object->data = NULL;
+}
diff --git a/source/blender/alembic/intern/abc_reader_transform.h b/source/blender/alembic/intern/abc_reader_transform.h
new file mode 100644
index 00000000000..6b4d23c1884
--- /dev/null
+++ b/source/blender/alembic/intern/abc_reader_transform.h
@@ -0,0 +1,42 @@
+/*
+ * 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_READER_TRANSFORM_H__
+#define __ABC_READER_TRANSFORM_H__
+
+#include "abc_reader_object.h"
+
+#include <Alembic/AbcGeom/All.h>
+
+class AbcEmptyReader : public AbcObjectReader {
+ Alembic::AbcGeom::IXformSchema m_schema;
+
+ public:
+ AbcEmptyReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
+
+ bool valid() const;
+ bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
+ const Object *const ob,
+ const char **err_str) const;
+
+ void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
+};
+
+#endif /* __ABC_READER_TRANSFORM_H__ */
diff --git a/source/blender/alembic/intern/abc_util.cc b/source/blender/alembic/intern/abc_util.cc
index 9a4d4e1a8cc..b26ef8b3b76 100644
--- a/source/blender/alembic/intern/abc_util.cc
+++ b/source/blender/alembic/intern/abc_util.cc
@@ -20,12 +20,12 @@
#include "abc_util.h"
-#include "abc_camera.h"
-#include "abc_curves.h"
-#include "abc_mesh.h"
-#include "abc_nurbs.h"
-#include "abc_points.h"
-#include "abc_transform.h"
+#include "abc_reader_camera.h"
+#include "abc_reader_curves.h"
+#include "abc_reader_mesh.h"
+#include "abc_reader_nurbs.h"
+#include "abc_reader_points.h"
+#include "abc_reader_transform.h"
#include <Alembic/AbcMaterial/IMaterial.h>
@@ -33,9 +33,8 @@
extern "C" {
#include "DNA_object_types.h"
-#include "DNA_layer_types.h"
-#include "BLI_math.h"
+#include "BLI_math_geom.h"
#include "PIL_time.h"
}
diff --git a/source/blender/alembic/intern/abc_writer_archive.cc b/source/blender/alembic/intern/abc_writer_archive.cc
new file mode 100644
index 00000000000..af18d480a18
--- /dev/null
+++ b/source/blender/alembic/intern/abc_writer_archive.cc
@@ -0,0 +1,114 @@
+/*
+ * 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"
+extern "C" {
+#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 &filename,
+ const std::string &scene_name,
+ double scene_fps,
+ bool ogawa)
+{
+ 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", versionstr);
+ 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;
+
+#ifdef WITH_ALEMBIC_HDF5
+ if (!ogawa) {
+ return OArchive(Alembic::AbcCoreHDF5::WriteArchive(), filename, abc_metadata, policy);
+ }
+#else
+ static_cast<void>(filename);
+ static_cast<void>(ogawa);
+#endif
+
+ 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,
+ bool do_ogawa)
+{
+ /* Use stream to support unicode character paths on Windows. */
+ if (do_ogawa) {
+#ifdef WIN32
+ UTF16_ENCODE(filename);
+ std::wstring wstr(filename_16);
+ m_outfile.open(wstr.c_str(), std::ios::out | std::ios::binary);
+ UTF16_UN_ENCODE(filename);
+#else
+ m_outfile.open(filename, std::ios::out | std::ios::binary);
+#endif
+ }
+
+ m_archive = create_archive(&m_outfile, filename, abc_scene_name, FPS, do_ogawa);
+}
+
+OArchive &ArchiveWriter::archive()
+{
+ return m_archive;
+}
diff --git a/source/blender/alembic/intern/abc_writer_archive.h b/source/blender/alembic/intern/abc_writer_archive.h
new file mode 100644
index 00000000000..e261e60990a
--- /dev/null
+++ b/source/blender/alembic/intern/abc_writer_archive.h
@@ -0,0 +1,58 @@
+/*
+ * 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_ARCHIVE_H__
+#define __ABC_WRITER_ARCHIVE_H__
+
+#include <Alembic/Abc/All.h>
+
+#ifdef WITH_ALEMBIC_HDF5
+# include <Alembic/AbcCoreHDF5/All.h>
+#endif
+
+#include <Alembic/AbcCoreOgawa/All.h>
+
+#include <fstream>
+
+struct Main;
+struct Scene;
+
+/* Wrappers around input and output archives. The goal is to be able to use
+ * streams so that unicode paths work on Windows (T49112), and to make sure that
+ * the stream objects remain valid as long as the archives are open.
+ */
+
+class ArchiveWriter {
+ std::ofstream m_outfile;
+ Alembic::Abc::OArchive m_archive;
+
+ public:
+ ArchiveWriter(const char *filename,
+ const std::string &abc_scene_name,
+ const Scene *scene,
+ bool do_ogawa);
+
+ Alembic::Abc::OArchive &archive();
+};
+
+#endif /* __ABC_WRITER_ARCHIVE_H__ */
diff --git a/source/blender/alembic/intern/abc_writer_camera.cc b/source/blender/alembic/intern/abc_writer_camera.cc
new file mode 100644
index 00000000000..e705e5ba911
--- /dev/null
+++ b/source/blender/alembic/intern/abc_writer_camera.cc
@@ -0,0 +1,81 @@
+/*
+ * 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"
+
+extern "C" {
+#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/alembic/intern/abc_camera.h b/source/blender/alembic/intern/abc_writer_camera.h
index 28169cb7d85..3b515911a48 100644
--- a/source/blender/alembic/intern/abc_camera.h
+++ b/source/blender/alembic/intern/abc_writer_camera.h
@@ -18,10 +18,10 @@
* \ingroup balembic
*/
-#ifndef __ABC_CAMERA_H__
-#define __ABC_CAMERA_H__
+#ifndef __ABC_WRITER_CAMERA_H__
+#define __ABC_WRITER_CAMERA_H__
-#include "abc_object.h"
+#include "abc_writer_object.h"
/* ************************************************************************** */
@@ -42,20 +42,4 @@ class AbcCameraWriter : public AbcObjectWriter {
virtual void do_write();
};
-/* ************************************************************************** */
-
-class AbcCameraReader : public AbcObjectReader {
- Alembic::AbcGeom::ICameraSchema m_schema;
-
- public:
- AbcCameraReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
-
- bool valid() const;
- bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
- const Object *const ob,
- const char **err_str) const;
-
- void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
-};
-
-#endif /* __ABC_CAMERA_H__ */
+#endif /* __ABC_WRITER_CAMERA_H__ */
diff --git a/source/blender/alembic/intern/abc_writer_curves.cc b/source/blender/alembic/intern/abc_writer_curves.cc
new file mode 100644
index 00000000000..bb9109dc025
--- /dev/null
+++ b/source/blender/alembic/intern/abc_writer_curves.cc
@@ -0,0 +1,187 @@
+/*
+ * 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_curves.h"
+#include "abc_reader_curves.h"
+#include "abc_writer_transform.h"
+
+extern "C" {
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_curve.h"
+#include "BKE_mesh.h"
+}
+
+using Alembic::AbcGeom::OCompoundProperty;
+using Alembic::AbcGeom::OCurves;
+using Alembic::AbcGeom::OCurvesSchema;
+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)
+{
+ OCurves curves(parent->alembicXform(), m_name, m_time_sampling);
+ m_schema = curves.getSchema();
+
+ Curve *cu = static_cast<Curve *>(m_object->data);
+ OCompoundProperty user_props = m_schema.getUserProperties();
+ OInt16Property user_prop_resolu(user_props, ABC_CURVE_RESOLUTION_U_PROPNAME);
+ user_prop_resolu.set(cu->resolu);
+}
+
+void AbcCurveWriter::do_write()
+{
+ Curve *curve = static_cast<Curve *>(m_object->data);
+
+ std::vector<Imath::V3f> verts;
+ std::vector<int32_t> vert_counts;
+ std::vector<float> widths;
+ std::vector<float> weights;
+ std::vector<float> knots;
+ std::vector<uint8_t> orders;
+ Imath::V3f temp_vert;
+
+ Alembic::AbcGeom::BasisType curve_basis;
+ Alembic::AbcGeom::CurveType curve_type;
+ Alembic::AbcGeom::CurvePeriodicity periodicity;
+
+ Nurb *nurbs = static_cast<Nurb *>(curve->nurb.first);
+ for (; nurbs; nurbs = nurbs->next) {
+ if (nurbs->bp) {
+ curve_basis = Alembic::AbcGeom::kNoBasis;
+ curve_type = Alembic::AbcGeom::kVariableOrder;
+
+ const int totpoint = nurbs->pntsu * nurbs->pntsv;
+
+ const BPoint *point = nurbs->bp;
+
+ for (int i = 0; i < totpoint; i++, point++) {
+ copy_yup_from_zup(temp_vert.getValue(), point->vec);
+ verts.push_back(temp_vert);
+ weights.push_back(point->vec[3]);
+ widths.push_back(point->radius);
+ }
+ }
+ else if (nurbs->bezt) {
+ curve_basis = Alembic::AbcGeom::kBezierBasis;
+ curve_type = Alembic::AbcGeom::kCubic;
+
+ const int totpoint = nurbs->pntsu;
+
+ const BezTriple *bezier = nurbs->bezt;
+
+ /* TODO(kevin): store info about handles, Alembic doesn't have this. */
+ for (int i = 0; i < totpoint; i++, bezier++) {
+ copy_yup_from_zup(temp_vert.getValue(), bezier->vec[1]);
+ verts.push_back(temp_vert);
+ widths.push_back(bezier->radius);
+ }
+ }
+
+ if ((nurbs->flagu & CU_NURB_ENDPOINT) != 0) {
+ periodicity = Alembic::AbcGeom::kNonPeriodic;
+ }
+ else if ((nurbs->flagu & CU_NURB_CYCLIC) != 0) {
+ periodicity = Alembic::AbcGeom::kPeriodic;
+
+ /* Duplicate the start points to indicate that the curve is actually
+ * cyclic since other software need those.
+ */
+
+ for (int i = 0; i < nurbs->orderu; i++) {
+ verts.push_back(verts[i]);
+ }
+ }
+
+ if (nurbs->knotsu != NULL) {
+ const size_t num_knots = KNOTSU(nurbs);
+
+ /* Add an extra knot at the beginning and end of the array since most apps
+ * require/expect them. */
+ knots.resize(num_knots + 2);
+
+ for (int i = 0; i < num_knots; i++) {
+ knots[i + 1] = nurbs->knotsu[i];
+ }
+
+ if ((nurbs->flagu & CU_NURB_CYCLIC) != 0) {
+ knots[0] = nurbs->knotsu[0];
+ knots[num_knots - 1] = nurbs->knotsu[num_knots - 1];
+ }
+ else {
+ knots[0] = (2.0f * nurbs->knotsu[0] - nurbs->knotsu[1]);
+ knots[num_knots - 1] = (2.0f * nurbs->knotsu[num_knots - 1] -
+ nurbs->knotsu[num_knots - 2]);
+ }
+ }
+
+ orders.push_back(nurbs->orderu);
+ vert_counts.push_back(verts.size());
+ }
+
+ 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);
+}
+
+AbcCurveMeshWriter::AbcCurveMeshWriter(Object *ob,
+ AbcTransformWriter *parent,
+ uint32_t time_sampling,
+ ExportSettings &settings)
+ : AbcGenericMeshWriter(ob, parent, time_sampling, settings)
+{
+}
+
+Mesh *AbcCurveMeshWriter::getEvaluatedMesh(Scene * /*scene_eval*/,
+ Object *ob_eval,
+ bool &r_needsfree)
+{
+ if (ob_eval->runtime.mesh_eval != NULL) {
+ /* Mesh_eval only exists when generative modifiers are in use. */
+ r_needsfree = false;
+ return ob_eval->runtime.mesh_eval;
+ }
+
+ r_needsfree = true;
+ return BKE_mesh_new_nomain_from_curve(ob_eval);
+}
diff --git a/source/blender/alembic/intern/abc_writer_curves.h b/source/blender/alembic/intern/abc_writer_curves.h
new file mode 100644
index 00000000000..d6d8c0a7f11
--- /dev/null
+++ b/source/blender/alembic/intern/abc_writer_curves.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) 2016 Kévin Dietrich.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup balembic
+ */
+
+#ifndef __ABC_WRITER_CURVES_H__
+#define __ABC_WRITER_CURVES_H__
+
+#include "abc_writer_object.h"
+#include "abc_writer_mesh.h"
+
+class AbcCurveWriter : public AbcObjectWriter {
+ Alembic::AbcGeom::OCurvesSchema m_schema;
+ Alembic::AbcGeom::OCurvesSchema::Sample m_sample;
+
+ public:
+ AbcCurveWriter(Object *ob,
+ AbcTransformWriter *parent,
+ uint32_t time_sampling,
+ ExportSettings &settings);
+
+ protected:
+ void do_write();
+};
+
+class AbcCurveMeshWriter : public AbcGenericMeshWriter {
+ public:
+ AbcCurveMeshWriter(Object *ob,
+ AbcTransformWriter *parent,
+ uint32_t time_sampling,
+ ExportSettings &settings);
+
+ protected:
+ Mesh *getEvaluatedMesh(Scene *scene_eval, Object *ob_eval, bool &r_needsfree);
+};
+
+#endif /* __ABC_WRITER_CURVES_H__ */
diff --git a/source/blender/alembic/intern/abc_hair.cc b/source/blender/alembic/intern/abc_writer_hair.cc
index 7eaecd271f4..bbba03ed7f4 100644
--- a/source/blender/alembic/intern/abc_hair.cc
+++ b/source/blender/alembic/intern/abc_writer_hair.cc
@@ -18,26 +18,22 @@
* \ingroup balembic
*/
-#include "abc_hair.h"
-
-#include <cstdio>
-
-#include "abc_transform.h"
+#include "abc_writer_hair.h"
+#include "abc_writer_transform.h"
#include "abc_util.h"
-#include "MEM_guardedalloc.h"
+#include <cstdio>
extern "C" {
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
+#include "DNA_object_types.h"
-#include "BLI_listbase.h"
#include "BLI_math_geom.h"
#include "BKE_mesh.h"
#include "BKE_mesh_runtime.h"
-#include "BKE_object.h"
#include "BKE_particle.h"
}
diff --git a/source/blender/alembic/intern/abc_hair.h b/source/blender/alembic/intern/abc_writer_hair.h
index 21f665a4795..67d1b7b3d23 100644
--- a/source/blender/alembic/intern/abc_hair.h
+++ b/source/blender/alembic/intern/abc_writer_hair.h
@@ -18,16 +18,14 @@
* \ingroup balembic
*/
-#ifndef __ABC_HAIR_H__
-#define __ABC_HAIR_H__
+#ifndef __ABC_WRITER_HAIR_H__
+#define __ABC_WRITER_HAIR_H__
-#include "abc_object.h"
+#include "abc_writer_object.h"
struct ParticleSettings;
struct ParticleSystem;
-/* ************************************************************************** */
-
class AbcHairWriter : public AbcObjectWriter {
ParticleSystem *m_psys;
@@ -61,4 +59,4 @@ class AbcHairWriter : public AbcObjectWriter {
std::vector<int32_t> &hvertices);
};
-#endif /* __ABC_HAIR_H__ */
+#endif /* __ABC_WRITER_HAIR_H__ */
diff --git a/source/blender/alembic/intern/abc_mball.cc b/source/blender/alembic/intern/abc_writer_mball.cc
index 6fc7d8c24c8..aa08146c6e2 100644
--- a/source/blender/alembic/intern/abc_mball.cc
+++ b/source/blender/alembic/intern/abc_writer_mball.cc
@@ -18,25 +18,20 @@
* \ingroup balembic
*/
-#include "abc_mball.h"
-#include "abc_mesh.h"
-#include "abc_transform.h"
-
-#include "MEM_guardedalloc.h"
+#include "abc_writer_mball.h"
+#include "abc_writer_mesh.h"
extern "C" {
#include "DNA_meta_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
-#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_lib_id.h"
#include "BKE_mball.h"
#include "BKE_mesh.h"
-#include "BKE_object.h"
-#include "DEG_depsgraph.h"
+#include "BLI_utildefines.h"
}
AbcMBallWriter::AbcMBallWriter(Main *bmain,
diff --git a/source/blender/alembic/intern/abc_mball.h b/source/blender/alembic/intern/abc_writer_mball.h
index 4be977fa8f5..c752472c86d 100644
--- a/source/blender/alembic/intern/abc_mball.h
+++ b/source/blender/alembic/intern/abc_writer_mball.h
@@ -18,11 +18,11 @@
* \ingroup balembic
*/
-#ifndef __ABC_MBALL_H__
-#define __ABC_MBALL_H__
+#ifndef __ABC_WRITER_MBALL_H__
+#define __ABC_WRITER_MBALL_H__
-#include "abc_object.h"
-#include "abc_mesh.h"
+#include "abc_writer_object.h"
+#include "abc_writer_mesh.h"
struct Main;
struct Object;
@@ -53,4 +53,4 @@ class AbcMBallWriter : public AbcGenericMeshWriter {
bool isAnimated() const override;
};
-#endif /* __ABC_MBALL_H__ */
+#endif /* __ABC_WRITER_MBALL_H__ */
diff --git a/source/blender/alembic/intern/abc_writer_mesh.cc b/source/blender/alembic/intern/abc_writer_mesh.cc
new file mode 100644
index 00000000000..b55d2473f99
--- /dev/null
+++ b/source/blender/alembic/intern/abc_writer_mesh.cc
@@ -0,0 +1,592 @@
+/*
+ * 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_mesh.h"
+#include "abc_writer_transform.h"
+#include "abc_util.h"
+
+extern "C" {
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_object_fluidsim_types.h"
+
+#include "BKE_animsys.h"
+#include "BKE_key.h"
+#include "BKE_lib_id.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_modifier.h"
+
+#include "bmesh.h"
+#include "bmesh_tools.h"
+
+#include "DEG_depsgraph_query.h"
+}
+
+using Alembic::Abc::FloatArraySample;
+using Alembic::Abc::Int32ArraySample;
+using Alembic::Abc::V2fArraySample;
+using Alembic::Abc::V3fArraySample;
+
+using Alembic::AbcGeom::kFacevaryingScope;
+using Alembic::AbcGeom::OBoolProperty;
+using Alembic::AbcGeom::OCompoundProperty;
+using Alembic::AbcGeom::OFaceSet;
+using Alembic::AbcGeom::OFaceSetSchema;
+using Alembic::AbcGeom::ON3fGeomParam;
+using Alembic::AbcGeom::OPolyMesh;
+using Alembic::AbcGeom::OPolyMeshSchema;
+using Alembic::AbcGeom::OSubD;
+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);
+
+ MVert *verts = mesh->mvert;
+
+ for (int i = 0, e = mesh->totvert; i < e; i++) {
+ copy_yup_from_zup(points[i].getValue(), verts[i].co);
+ }
+}
+
+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);
+}
+
+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)) {
+ 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]);
+ }
+ }
+}
+
+/* *************** 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)
+{
+ ModifierData *md = static_cast<ModifierData *>(ob->modifiers.last);
+
+ for (; md; md = md->prev) {
+ if (!modifier_isEnabled(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;
+ }
+ }
+
+ return NULL;
+}
+
+static ModifierData *get_liquid_sim_modifier(Scene *scene, Object *ob)
+{
+ ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim);
+
+ if (md && (modifier_isEnabled(scene, md, eModifierMode_Render))) {
+ FluidsimModifierData *fsmd = reinterpret_cast<FluidsimModifierData *>(md);
+
+ if (fsmd->fss && fsmd->fss->type == OB_FLUIDSIM_DOMAIN) {
+ return md;
+ }
+ }
+
+ return NULL;
+}
+
+/* ************************************************************************** */
+
+AbcGenericMeshWriter::AbcGenericMeshWriter(Object *ob,
+ AbcTransformWriter *parent,
+ uint32_t time_sampling,
+ ExportSettings &settings)
+ : AbcObjectWriter(ob, time_sampling, settings, parent)
+{
+ 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;
+ }
+
+ if (!m_settings.apply_subdiv) {
+ m_subsurf_mod = get_subsurf_modifier(m_settings.scene, m_object);
+ m_is_subd = (m_subsurf_mod != NULL);
+ }
+
+ m_is_liquid = (get_liquid_sim_modifier(m_settings.scene, m_object) != NULL);
+
+ while (parent->alembicXform().getChildHeader(m_name)) {
+ m_name.append("_");
+ }
+
+ 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);
+ }
+}
+
+AbcGenericMeshWriter::~AbcGenericMeshWriter()
+{
+ if (m_subsurf_mod) {
+ m_subsurf_mod->mode &= ~eModifierMode_DisableTemporary;
+ }
+}
+
+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;
+ }
+
+ /* Test modifiers. */
+ ModifierData *md = static_cast<ModifierData *>(m_object->modifiers.first);
+ while (md) {
+
+ if (md->type != eModifierType_Subsurf) {
+ return true;
+ }
+
+ md = md->next;
+ }
+
+ return false;
+}
+
+void AbcGenericMeshWriter::setIsAnimated(bool is_animated)
+{
+ m_is_animated = is_animated;
+}
+
+void AbcGenericMeshWriter::do_write()
+{
+ /* We have already stored a sample for this object. */
+ if (!m_first_frame && !m_is_animated) {
+ return;
+ }
+
+ bool needsfree;
+ struct Mesh *mesh = getFinalMesh(needsfree);
+
+ try {
+ if (m_settings.use_subdiv_schema && m_subdiv_schema.valid()) {
+ writeSubD(mesh);
+ }
+ else {
+ writeMesh(mesh);
+ }
+
+ if (needsfree) {
+ freeEvaluatedMesh(mesh);
+ }
+ }
+ catch (...) {
+ if (needsfree) {
+ freeEvaluatedMesh(mesh);
+ }
+ throw;
+ }
+}
+
+void AbcGenericMeshWriter::freeEvaluatedMesh(struct Mesh *mesh)
+{
+ BKE_id_free(NULL, mesh);
+}
+
+void AbcGenericMeshWriter::writeMesh(struct Mesh *mesh)
+{
+ std::vector<Imath::V3f> points, normals;
+ std::vector<int32_t> poly_verts, loop_counts;
+ std::vector<Imath::V3f> velocities;
+ bool has_flat_shaded_poly = false;
+
+ 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);
+ }
+
+ m_mesh_sample = OPolyMeshSchema::Sample(
+ V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts));
+
+ UVSample sample;
+ if (m_first_frame && m_settings.export_uvs) {
+ const char *name = get_uv_sample(sample, m_custom_data_config, &mesh->ldata);
+
+ if (!sample.indices.empty() && !sample.uvs.empty()) {
+ OV2fGeomParam::Sample uv_sample;
+ uv_sample.setVals(V2fArraySample(sample.uvs));
+ uv_sample.setIndices(UInt32ArraySample(sample.indices));
+ uv_sample.setScope(kFacevaryingScope);
+
+ m_mesh_schema.setUVSourceName(name);
+ m_mesh_sample.setUVs(uv_sample);
+ }
+
+ write_custom_data(
+ m_mesh_schema.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
+ }
+
+ if (m_settings.export_normals) {
+ get_loop_normals(mesh, normals, has_flat_shaded_poly);
+
+ ON3fGeomParam::Sample normals_sample;
+ if (!normals.empty()) {
+ normals_sample.setScope(kFacevaryingScope);
+ normals_sample.setVals(V3fArraySample(normals));
+ }
+
+ m_mesh_sample.setNormals(normals_sample);
+ }
+
+ if (m_is_liquid) {
+ getVelocities(mesh, velocities);
+ m_mesh_sample.setVelocities(V3fArraySample(velocities));
+ }
+
+ m_mesh_sample.setSelfBounds(bounds());
+
+ m_mesh_schema.set(m_mesh_sample);
+
+ writeArbGeoParams(mesh);
+}
+
+void AbcGenericMeshWriter::writeSubD(struct Mesh *mesh)
+{
+ std::vector<float> crease_sharpness;
+ std::vector<Imath::V3f> points;
+ std::vector<int32_t> poly_verts, loop_counts;
+ std::vector<int32_t> crease_indices, crease_lengths;
+ bool has_flat_poly = false;
+
+ get_vertices(mesh, points);
+ 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);
+ }
+
+ m_subdiv_sample = OSubDSchema::Sample(
+ V3fArraySample(points), Int32ArraySample(poly_verts), Int32ArraySample(loop_counts));
+
+ UVSample sample;
+ if (m_first_frame && m_settings.export_uvs) {
+ const char *name = get_uv_sample(sample, m_custom_data_config, &mesh->ldata);
+
+ if (!sample.indices.empty() && !sample.uvs.empty()) {
+ OV2fGeomParam::Sample uv_sample;
+ uv_sample.setVals(V2fArraySample(sample.uvs));
+ uv_sample.setIndices(UInt32ArraySample(sample.indices));
+ uv_sample.setScope(kFacevaryingScope);
+
+ m_subdiv_schema.setUVSourceName(name);
+ m_subdiv_sample.setUVs(uv_sample);
+ }
+
+ write_custom_data(
+ m_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));
+ }
+
+ m_subdiv_sample.setSelfBounds(bounds());
+ m_subdiv_schema.set(m_subdiv_sample);
+
+ writeArbGeoParams(mesh);
+}
+
+template<typename Schema> void AbcGenericMeshWriter::writeFaceSets(struct Mesh *me, Schema &schema)
+{
+ std::map<std::string, std::vector<int32_t>> geo_groups;
+ getGeoGroups(me, geo_groups);
+
+ std::map<std::string, std::vector<int32_t>>::iterator it;
+ for (it = geo_groups.begin(); it != geo_groups.end(); ++it) {
+ OFaceSet face_set = schema.createFaceSet(it->first);
+ OFaceSetSchema::Sample samp;
+ samp.setFaces(Int32ArraySample(it->second));
+ face_set.getSchema().set(samp);
+ }
+}
+
+Mesh *AbcGenericMeshWriter::getFinalMesh(bool &r_needsfree)
+{
+ /* 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;
+ }
+
+ 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. */
+ 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);
+ }
+ }
+}
+
+void AbcGenericMeshWriter::getVelocities(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);
+ FluidsimSettings *fss = fmd->fss;
+
+ if (fss->meshVelocities) {
+ float *mesh_vels = reinterpret_cast<float *>(fss->meshVelocities);
+
+ for (int i = 0; i < totverts; i++) {
+ copy_yup_from_zup(vels[i].getValue(), mesh_vels);
+ mesh_vels += 3;
+ }
+ }
+ else {
+ std::fill(vels.begin(), vels.end(), Imath::V3f(0.0f));
+ }
+}
+
+void AbcGenericMeshWriter::getGeoGroups(struct Mesh *mesh,
+ std::map<std::string, std::vector<int32_t>> &geo_groups)
+{
+ const int num_poly = mesh->totpoly;
+ MPoly *polygons = mesh->mpoly;
+
+ for (int i = 0; i < num_poly; i++) {
+ MPoly &current_poly = polygons[i];
+ short mnr = current_poly.mat_nr;
+
+ Material *mat = BKE_object_material_get(m_object, mnr + 1);
+
+ if (!mat) {
+ continue;
+ }
+
+ std::string name = get_id_name(&mat->id);
+
+ if (geo_groups.find(name) == geo_groups.end()) {
+ std::vector<int32_t> faceArray;
+ geo_groups[name] = faceArray;
+ }
+
+ geo_groups[name].push_back(i);
+ }
+
+ if (geo_groups.size() == 0) {
+ Material *mat = BKE_object_material_get(m_object, 1);
+
+ std::string name = (mat) ? get_id_name(&mat->id) : "default";
+
+ std::vector<int32_t> faceArray;
+
+ for (int i = 0, e = mesh->totface; i < e; i++) {
+ faceArray.push_back(i);
+ }
+
+ geo_groups[name] = faceArray;
+ }
+}
+
+AbcMeshWriter::AbcMeshWriter(Object *ob,
+ AbcTransformWriter *parent,
+ uint32_t time_sampling,
+ ExportSettings &settings)
+ : AbcGenericMeshWriter(ob, parent, time_sampling, settings)
+{
+}
+
+AbcMeshWriter::~AbcMeshWriter()
+{
+}
+
+Mesh *AbcMeshWriter::getEvaluatedMesh(Scene *scene_eval,
+ Object *ob_eval,
+ bool &UNUSED(r_needsfree))
+{
+ return mesh_get_eval_final(m_settings.depsgraph, scene_eval, ob_eval, &CD_MASK_MESH);
+}
diff --git a/source/blender/alembic/intern/abc_writer_mesh.h b/source/blender/alembic/intern/abc_writer_mesh.h
new file mode 100644
index 00000000000..9152a370e4f
--- /dev/null
+++ b/source/blender/alembic/intern/abc_writer_mesh.h
@@ -0,0 +1,91 @@
+/*
+ * 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/alembic/intern/abc_writer_nurbs.cc b/source/blender/alembic/intern/abc_writer_nurbs.cc
new file mode 100644
index 00000000000..9796eaf54c3
--- /dev/null
+++ b/source/blender/alembic/intern/abc_writer_nurbs.cc
@@ -0,0 +1,172 @@
+/*
+ * 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_nurbs.h"
+#include "abc_writer_transform.h"
+#include "abc_util.h"
+
+extern "C" {
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_listbase.h"
+
+#include "BKE_curve.h"
+}
+
+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)
+{
+ 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);
+
+ for (size_t i = 0; i < numNurbs; i++) {
+ std::stringstream str;
+ str << m_name << '_' << i;
+
+ while (parent->alembicXform().getChildHeader(str.str())) {
+ str << "_";
+ }
+
+ ONuPatch nurbs(parent->alembicXform(), str.str().c_str(), m_time_sampling);
+ m_nurbs_schema.push_back(nurbs.getSchema());
+ }
+}
+
+bool AbcNurbsWriter::isAnimated() const
+{
+ /* check if object has shape keys */
+ Curve *cu = static_cast<Curve *>(m_object->data);
+ return (cu->key != NULL);
+}
+
+static void get_knots(std::vector<float> &knots, const int num_knots, float *nu_knots)
+{
+ if (num_knots <= 1) {
+ return;
+ }
+
+ /* Add an extra knot at the beginning and end of the array since most apps
+ * require/expect them. */
+ knots.reserve(num_knots + 2);
+
+ knots.push_back(0.0f);
+
+ for (int i = 0; i < num_knots; i++) {
+ knots.push_back(nu_knots[i]);
+ }
+
+ knots[0] = 2.0f * knots[1] - knots[2];
+ knots.push_back(2.0f * knots[num_knots] - knots[num_knots - 1]);
+}
+
+void AbcNurbsWriter::do_write()
+{
+ /* 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);
+ ListBase *nulb;
+
+ if (m_object->runtime.curve_cache->deformed_nurbs.first != NULL) {
+ nulb = &m_object->runtime.curve_cache->deformed_nurbs;
+ }
+ else {
+ nulb = BKE_curve_nurbs_get(curve);
+ }
+
+ size_t count = 0;
+ for (Nurb *nu = static_cast<Nurb *>(nulb->first); nu; nu = nu->next, count++) {
+ std::vector<float> knotsU;
+ get_knots(knotsU, KNOTSU(nu), nu->knotsu);
+
+ std::vector<float> knotsV;
+ get_knots(knotsV, KNOTSV(nu), nu->knotsv);
+
+ const int size = nu->pntsu * nu->pntsv;
+ std::vector<Imath::V3f> positions(size);
+ std::vector<float> weights(size);
+
+ const BPoint *bp = nu->bp;
+
+ for (int i = 0; i < size; i++, bp++) {
+ copy_yup_from_zup(positions[i].getValue(), bp->vec);
+ weights[i] = bp->vec[3];
+ }
+
+ ONuPatchSchema::Sample sample;
+ sample.setUOrder(nu->orderu + 1);
+ sample.setVOrder(nu->orderv + 1);
+ sample.setPositions(positions);
+ sample.setPositionWeights(weights);
+ sample.setUKnot(FloatArraySample(knotsU));
+ sample.setVKnot(FloatArraySample(knotsV));
+ sample.setNu(nu->pntsu);
+ sample.setNv(nu->pntsv);
+
+ /* 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();
+
+ if ((nu->flagu & CU_NURB_ENDPOINT) != 0) {
+ OBoolProperty prop(user_props, "endpoint_u");
+ prop.set(true);
+ }
+
+ if ((nu->flagv & CU_NURB_ENDPOINT) != 0) {
+ OBoolProperty prop(user_props, "endpoint_v");
+ prop.set(true);
+ }
+
+ if ((nu->flagu & CU_NURB_CYCLIC) != 0) {
+ OBoolProperty prop(user_props, "cyclic_u");
+ prop.set(true);
+ }
+
+ if ((nu->flagv & CU_NURB_CYCLIC) != 0) {
+ OBoolProperty prop(user_props, "cyclic_v");
+ prop.set(true);
+ }
+
+ m_nurbs_schema[count].set(sample);
+ }
+}
diff --git a/source/blender/alembic/intern/abc_writer_nurbs.h b/source/blender/alembic/intern/abc_writer_nurbs.h
new file mode 100644
index 00000000000..c6a3c399b66
--- /dev/null
+++ b/source/blender/alembic/intern/abc_writer_nurbs.h
@@ -0,0 +1,42 @@
+/*
+ * 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_NURBS_H__
+#define __ABC_WRITER_NURBS_H__
+
+#include "abc_writer_object.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);
+
+ private:
+ virtual void do_write();
+
+ bool isAnimated() const;
+};
+
+#endif /* __ABC_WRITER_NURBS_H__ */
diff --git a/source/blender/alembic/intern/abc_writer_object.cc b/source/blender/alembic/intern/abc_writer_object.cc
new file mode 100644
index 00000000000..75dc93bd08e
--- /dev/null
+++ b/source/blender/alembic/intern/abc_writer_object.cc
@@ -0,0 +1,79 @@
+/*
+ * 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"
+
+extern "C" {
+#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/alembic/intern/abc_writer_object.h b/source/blender/alembic/intern/abc_writer_object.h
new file mode 100644
index 00000000000..c3511566372
--- /dev/null
+++ b/source/blender/alembic/intern/abc_writer_object.h
@@ -0,0 +1,71 @@
+/*
+ * 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"
+
+extern "C" {
+#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/alembic/intern/abc_writer_points.cc b/source/blender/alembic/intern/abc_writer_points.cc
new file mode 100644
index 00000000000..cc4abe8ec4b
--- /dev/null
+++ b/source/blender/alembic/intern/abc_writer_points.cc
@@ -0,0 +1,123 @@
+/*
+ * 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_writer_mesh.h"
+#include "abc_writer_transform.h"
+#include "abc_util.h"
+
+extern "C" {
+#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) {
+ end_latt_deform(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/alembic/intern/abc_writer_points.h b/source/blender/alembic/intern/abc_writer_points.h
new file mode 100644
index 00000000000..77dd10c4b26
--- /dev/null
+++ b/source/blender/alembic/intern/abc_writer_points.h
@@ -0,0 +1,49 @@
+/*
+ * 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_writer_object.h"
+#include "abc_customdata.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/alembic/intern/abc_transform.cc b/source/blender/alembic/intern/abc_writer_transform.cc
index 5135af131b1..d7bcc46d96f 100644
--- a/source/blender/alembic/intern/abc_transform.cc
+++ b/source/blender/alembic/intern/abc_writer_transform.cc
@@ -18,30 +18,22 @@
* \ingroup balembic
*/
-#include "abc_transform.h"
+#include "abc_writer_transform.h"
+#include "abc_util.h"
#include <OpenEXR/ImathBoxAlgo.h>
-#include "abc_util.h"
-
extern "C" {
#include "DNA_object_types.h"
-#include "BLI_listbase.h"
#include "BLI_math.h"
-#include "BKE_animsys.h"
-#include "BKE_object.h"
-
#include "DEG_depsgraph_query.h"
}
-using Alembic::Abc::ISampleSelector;
using Alembic::AbcGeom::OObject;
using Alembic::AbcGeom::OXform;
-/* ************************************************************************** */
-
AbcTransformWriter::AbcTransformWriter(Object *ob,
const OObject &abc_parent,
AbcTransformWriter *parent,
@@ -127,49 +119,3 @@ bool AbcTransformWriter::hasAnimation(Object * /*ob*/) const
{
return true;
}
-
-/* ************************************************************************** */
-
-AbcEmptyReader::AbcEmptyReader(const Alembic::Abc::IObject &object, ImportSettings &settings)
- : AbcObjectReader(object, settings)
-{
- /* Empties have no data. It makes the import of Alembic files easier to
- * understand when we name the empty after its name in Alembic. */
- m_object_name = object.getName();
-
- Alembic::AbcGeom::IXform xform(object, Alembic::AbcGeom::kWrapExisting);
- m_schema = xform.getSchema();
-
- get_min_max_time(m_iobject, m_schema, m_min_time, m_max_time);
-}
-
-bool AbcEmptyReader::valid() const
-{
- return m_schema.valid();
-}
-
-bool AbcEmptyReader::accepts_object_type(
- const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
- const Object *const ob,
- const char **err_str) const
-{
- if (!Alembic::AbcGeom::IXform::matches(alembic_header)) {
- *err_str =
- "Object type mismatch, Alembic object path pointed to XForm when importing, but not any "
- "more.";
- return false;
- }
-
- if (ob->type != OB_EMPTY) {
- *err_str = "Object type mismatch, Alembic object path points to XForm.";
- return false;
- }
-
- return true;
-}
-
-void AbcEmptyReader::readObjectData(Main *bmain, const ISampleSelector &UNUSED(sample_sel))
-{
- m_object = BKE_object_add_only_object(bmain, OB_EMPTY, m_object_name.c_str());
- m_object->data = NULL;
-}
diff --git a/source/blender/alembic/intern/abc_transform.h b/source/blender/alembic/intern/abc_writer_transform.h
index 7fa42cf0299..4397b220761 100644
--- a/source/blender/alembic/intern/abc_transform.h
+++ b/source/blender/alembic/intern/abc_writer_transform.h
@@ -18,15 +18,13 @@
* \ingroup balembic
*/
-#ifndef __ABC_TRANSFORM_H__
-#define __ABC_TRANSFORM_H__
+#ifndef __ABC_WRITER_TRANSFORM_H__
+#define __ABC_WRITER_TRANSFORM_H__
-#include "abc_object.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;
@@ -59,20 +57,4 @@ class AbcTransformWriter : public AbcObjectWriter {
bool hasAnimation(Object *ob) const;
};
-/* ************************************************************************** */
-
-class AbcEmptyReader : public AbcObjectReader {
- Alembic::AbcGeom::IXformSchema m_schema;
-
- public:
- AbcEmptyReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
-
- bool valid() const;
- bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
- const Object *const ob,
- const char **err_str) const;
-
- void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
-};
-
-#endif /* __ABC_TRANSFORM_H__ */
+#endif /* __ABC_WRITER_TRANSFORM_H__ */
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index 0cab0303fcc..6c7ab4d4b87 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -22,15 +22,21 @@
#include <Alembic/AbcMaterial/IMaterial.h>
-#include "abc_archive.h"
-#include "abc_camera.h"
-#include "abc_curves.h"
-#include "abc_hair.h"
-#include "abc_mesh.h"
-#include "abc_nurbs.h"
-#include "abc_points.h"
-#include "abc_transform.h"
+#include "abc_reader_archive.h"
+#include "abc_reader_camera.h"
+#include "abc_reader_curves.h"
+#include "abc_reader_mesh.h"
+#include "abc_reader_nurbs.h"
+#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"