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.
This commit is contained in:
Sybren A. Stüvel 2020-02-17 11:47:13 +01:00
parent c498abb103
commit 2d1b05a15f
41 changed files with 2016 additions and 1616 deletions

View File

@ -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

View File

@ -32,6 +32,8 @@ extern "C" {
#include "DNA_meshdata_types.h"
#include "BLI_math_base.h"
#include "BLI_utildefines.h"
#include "BKE_customdata.h"
}

View File

@ -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" {

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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)
{

View File

@ -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__ */

View File

@ -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)

View File

@ -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__ */

View File

@ -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;

View File

@ -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__ */

View File

@ -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)

View File

@ -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__ */

View File

@ -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(""),

View File

@ -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__ */

View File

@ -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)
{

View File

@ -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__ */

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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"
}

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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);
}

View File

@ -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__ */

View File

@ -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);
}

View File

@ -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__ */

View File

@ -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"
}

View File

@ -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__ */

View File

@ -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,

View File

@ -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__ */

View File

@ -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);
}

View File

@ -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__ */

View File

@ -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);
}
}

View File

@ -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__ */

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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);
}

View File

@ -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__ */

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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"