diff options
-rw-r--r-- | source/blender/alembic/intern/abc_object.cc | 56 | ||||
-rw-r--r-- | source/blender/alembic/intern/abc_object.h | 6 | ||||
-rw-r--r-- | source/blender/alembic/intern/alembic_capi.cc | 2 | ||||
-rw-r--r-- | tests/python/bl_alembic_import_test.py | 33 |
4 files changed, 73 insertions, 24 deletions
diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc index 04f6da48711..6c4cb60d63c 100644 --- a/source/blender/alembic/intern/abc_object.cc +++ b/source/blender/alembic/intern/abc_object.cc @@ -140,6 +140,38 @@ AbcObjectReader::AbcObjectReader(const IObject &object, ImportSettings &settings else { m_object_name = m_data_name = parts[parts.size() - 1]; } + + determine_inherits_xform(); +} + +/* Determine whether we can inherit our parent's XForm */ +void AbcObjectReader::determine_inherits_xform() +{ + m_inherits_xform = false; + + IXform ixform = xform(); + if (!ixform) { + return; + } + + const IXformSchema & schema(ixform.getSchema()); + if (!schema.valid()) { + std::cerr << "Alembic object " << ixform.getFullName() + << " has an invalid schema." << std::endl; + return; + } + + m_inherits_xform = schema.getInheritsXforms(); + + IObject ixform_parent = ixform.getParent(); + if (!ixform_parent.getParent()) { + /* The archive top object certainly is not a transform itself, so handle + * it as "no parent". */ + m_inherits_xform = false; + } + else { + m_inherits_xform = ixform_parent && m_inherits_xform; + } } AbcObjectReader::~AbcObjectReader() @@ -286,32 +318,10 @@ void AbcObjectReader::read_matrix(float r_mat[4][4], const float time, return; } - bool has_alembic_parent; - IObject ixform_parent = ixform.getParent(); - if (!ixform_parent.getParent()) { - /* The archive top object certainly is not a transform itself, so handle - * it as "no parent". */ - has_alembic_parent = false; - } - else { - has_alembic_parent = ixform_parent && schema.getInheritsXforms(); - - if (has_alembic_parent && m_object->parent == NULL) { - /* TODO Sybren: This happened in some files. I think I solved it, - * but I'll leave this check in here anyway until we've tested it - * more thoroughly. Better than crashing on a null parent anyway. */ - std::cerr << "Alembic object " << m_iobject.getFullName() - << " with transform " << ixform.getFullName() - << " has an Alembic parent but no parent Blender object." - << std::endl; - has_alembic_parent = false; - } - } - const Imath::M44d matrix = get_matrix(schema, time); convert_matrix(matrix, m_object, r_mat); - if (has_alembic_parent) { + if (m_inherits_xform) { /* In this case, the matrix in Alembic is in local coordinates, so * convert to world matrix. To prevent us from reading and accumulating * all parent matrices in the Alembic file, we assume that the Blender diff --git a/source/blender/alembic/intern/abc_object.h b/source/blender/alembic/intern/abc_object.h index cba79ffede5..852ef451f23 100644 --- a/source/blender/alembic/intern/abc_object.h +++ b/source/blender/alembic/intern/abc_object.h @@ -143,6 +143,8 @@ protected: * modifiers and/or constraints. */ int m_refcount; + bool m_inherits_xform; + public: AbcObjectReader *parent_reader; @@ -167,6 +169,7 @@ public: const std::string & name() const { return m_name; } const std::string & object_name() const { return m_object_name; } const std::string & data_name() const { return m_data_name; } + bool inherits_xform() const { return m_inherits_xform; } virtual bool valid() const = 0; virtual bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header, @@ -194,6 +197,9 @@ public: void read_matrix(float r_mat[4][4], const float time, const float scale, bool &is_constant); + +protected: + void determine_inherits_xform(); }; Imath::M44d get_matrix(const Alembic::AbcGeom::IXformSchema &schema, const float time); diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc index 83d971d00d9..bee8e92e969 100644 --- a/source/blender/alembic/intern/alembic_capi.cc +++ b/source/blender/alembic/intern/alembic_capi.cc @@ -760,7 +760,7 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa const AbcObjectReader *parent_reader = reader->parent_reader; Object *ob = reader->object(); - if (parent_reader == NULL) { + if (parent_reader == NULL || !reader->inherits_xform()) { ob->parent = NULL; } else { diff --git a/tests/python/bl_alembic_import_test.py b/tests/python/bl_alembic_import_test.py index d8cd64a1d56..f45748f86e7 100644 --- a/tests/python/bl_alembic_import_test.py +++ b/tests/python/bl_alembic_import_test.py @@ -75,6 +75,39 @@ class SimpleImportTest(AbstractAlembicTest): self.assertEqual(objects['Cube_003'], objects['Cube_005'].parent) self.assertEqual(objects['Cube_003'], objects['Cube_006'].parent) + def test_inherit_or_not(self): + res = bpy.ops.wm.alembic_import( + filepath=str(self.testdir / "T52022-inheritance.abc"), + as_background_job=False) + self.assertEqual({'FINISHED'}, res) + + # The objects should be linked to scene_collection in Blender 2.8, + # and to scene in Blender 2.7x. + objects = bpy.context.scene.objects + + # ABC parent is top-level object, which translates to nothing in Blender + self.assertIsNone(objects['locator1'].parent) + + # ABC parent is locator1, but locator2 has "inherits Xforms" = false, which + # translates to "no parent" in Blender. + self.assertIsNone(objects['locator2'].parent) + + # Shouldn't have inherited the ABC parent's transform. + x, y, z = objects['locator2'].matrix_world.to_translation() + self.assertAlmostEqual(0, x) + self.assertAlmostEqual(0, y) + self.assertAlmostEqual(2, z) + + # ABC parent is inherited and translates to normal parent in Blender. + self.assertEqual(objects['locator2'], objects['locatorShape2'].parent) + + # Should have inherited its ABC parent's transform. + x, y, z = objects['locatorShape2'].matrix_world.to_translation() + self.assertAlmostEqual(0, x) + self.assertAlmostEqual(0, y) + self.assertAlmostEqual(2, z) + + def test_select_after_import(self): # Add a sphere, so that there is something in the scene, selected, and active, # before we do the Alembic import. |