From 5bdbc88ab81891eff0dafaabf7f58a9c865d6e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Tue, 18 Apr 2017 16:36:33 +0200 Subject: [PATCH] Alembic import/export: write curve resolution to user property Curve resolution isn't natively supported by Alembic, hence it is stored in a user property "blender:resolution". I've looked at a Maya curves example file, but that also didn't contain any information about curve resolution. Differential Revision: https://developer.blender.org/D2634 Reviewers: kevindietrich --- source/blender/alembic/intern/abc_curves.cc | 31 +++++++++++++++++---- source/blender/alembic/intern/abc_curves.h | 4 ++- tests/python/alembic_tests.py | 12 +++++++- 3 files changed, 40 insertions(+), 7 deletions(-) diff --git a/source/blender/alembic/intern/abc_curves.cc b/source/blender/alembic/intern/abc_curves.cc index e6a5b289c6b..c096ac036b4 100644 --- a/source/blender/alembic/intern/abc_curves.cc +++ b/source/blender/alembic/intern/abc_curves.cc @@ -49,19 +49,26 @@ using Alembic::Abc::Int32ArraySamplePtr; using Alembic::Abc::FloatArraySamplePtr; using Alembic::Abc::P3fArraySamplePtr; using Alembic::Abc::UcharArraySamplePtr; +using Alembic::Abc::PropertyHeader; +using Alembic::AbcGeom::ICompoundProperty; using Alembic::AbcGeom::ICurves; using Alembic::AbcGeom::ICurvesSchema; using Alembic::AbcGeom::IFloatGeomParam; +using Alembic::AbcGeom::IInt16Property; using Alembic::AbcGeom::ISampleSelector; using Alembic::AbcGeom::kWrapExisting; using Alembic::AbcGeom::CurvePeriodicity; +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(Scene *scene, @@ -73,6 +80,11 @@ AbcCurveWriter::AbcCurveWriter(Scene *scene, { OCurves curves(parent->alembicXform(), m_name, m_time_sampling); m_schema = curves.getSchema(); + + Curve *cu = static_cast(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() @@ -205,12 +217,22 @@ void AbcCurveReader::readObjectData(Main *bmain, float time) cu->flag |= CU_DEFORM_FILL | CU_3D; cu->actvert = CU_ACT_NONE; - cu->resolu = 1; + + const ISampleSelector sample_sel(time); + ICompoundProperty user_props = m_curves_schema.getUserProperties(); + const PropertyHeader *header = user_props.getPropertyHeader(ABC_CURVE_RESOLUTION_U_PROPNAME); + if (header != NULL && header->isScalar() && IInt16Property::matches(*header)) { + IInt16Property resolu(user_props, header->getName()); + cu->resolu = resolu.getValue(sample_sel); + } + else { + cu->resolu = 1; + } m_object = BKE_object_add_only_object(bmain, OB_CURVE, m_object_name.c_str()); m_object->data = cu; - read_curve_sample(cu, m_curves_schema, time); + read_curve_sample(cu, m_curves_schema, sample_sel); if (has_animations(m_curves_schema, m_settings)) { addCacheModifier(); @@ -219,9 +241,8 @@ void AbcCurveReader::readObjectData(Main *bmain, float time) /* ************************************************************************** */ -void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const float time) +void read_curve_sample(Curve *cu, const ICurvesSchema &schema, const ISampleSelector &sample_sel) { - const ISampleSelector sample_sel(time); ICurvesSchema::Sample smp = schema.getValue(sample_sel); const Int32ArraySamplePtr num_vertices = smp.getCurvesNumVertices(); const P3fArraySamplePtr positions = smp.getPositions(); @@ -383,7 +404,7 @@ DerivedMesh *AbcCurveReader::read_derivedmesh(DerivedMesh * /*dm*/, const float if (curve_count != num_vertices->size()) { BKE_nurbList_free(&curve->nurb); - read_curve_sample(curve, m_curves_schema, time); + read_curve_sample(curve, m_curves_schema, sample_sel); } else { Nurb *nurbs = static_cast(curve->nurb.first); diff --git a/source/blender/alembic/intern/abc_curves.h b/source/blender/alembic/intern/abc_curves.h index 2757d179a47..71b0d205820 100644 --- a/source/blender/alembic/intern/abc_curves.h +++ b/source/blender/alembic/intern/abc_curves.h @@ -61,6 +61,8 @@ public: /* ************************************************************************** */ -void read_curve_sample(Curve *cu, const Alembic::AbcGeom::ICurvesSchema &schema, const float time); +void read_curve_sample(Curve *cu, + const Alembic::AbcGeom::ICurvesSchema &schema, + const Alembic::Abc::ISampleSelector &sample_selector); #endif /* __ABC_CURVES_H__ */ diff --git a/tests/python/alembic_tests.py b/tests/python/alembic_tests.py index 845b9bd6288..155cbd545f0 100755 --- a/tests/python/alembic_tests.py +++ b/tests/python/alembic_tests.py @@ -128,6 +128,7 @@ class AbstractAlembicTest(unittest.TestCase): converters = { 'bool_t': int, 'uint8_t': int, + 'int16_t': int, 'int32_t': int, 'float64_t': float, 'float32_t': float, @@ -141,7 +142,13 @@ class AbstractAlembicTest(unittest.TestCase): info = lines.popleft() if not info: continue - proptype, valtype_and_arrsize, name_and_extent = info.split() + parts = info.split() + proptype = parts[0] + + if proptype == 'CompoundProperty': + # To read those, call self.abcprop() on it. + continue + valtype_and_arrsize, name_and_extent = parts[1:] # Parse name and extent m = self.abcls_array.match(name_and_extent) @@ -291,6 +298,9 @@ class CurveExportTest(AbstractAlembicTest): abcprop = self.abcprop(abc, '/NurbsCurve/NurbsCurveShape/.geom') self.assertEqual(abcprop['.orders'], [4]) + abcprop = self.abcprop(abc, '/NurbsCurve/NurbsCurveShape/.geom/.userProperties') + self.assertEqual(abcprop['blender:resolution'], 10) + if __name__ == '__main__': parser = argparse.ArgumentParser()