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:
parent
c498abb103
commit
2d1b05a15f
|
@ -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
|
||||
|
|
|
@ -32,6 +32,8 @@ extern "C" {
|
|||
#include "DNA_meshdata_types.h"
|
||||
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_customdata.h"
|
||||
}
|
||||
|
||||
|
|
|
@ -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" {
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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)
|
||||
{
|
|
@ -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__ */
|
|
@ -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)
|
|
@ -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__ */
|
|
@ -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 ¤t_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;
|
|
@ -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__ */
|
|
@ -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)
|
|
@ -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__ */
|
|
@ -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(""),
|
|
@ -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__ */
|
|
@ -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)
|
||||
{
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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);
|
||||
}
|
|
@ -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__ */
|
|
@ -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);
|
||||
}
|
|
@ -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__ */
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -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__ */
|
|
@ -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,
|
|
@ -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__ */
|
|
@ -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 ¤t_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);
|
||||
}
|
|
@ -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__ */
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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);
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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"
|
||||
|
||||
|
|
Loading…
Reference in New Issue