Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/alembic/intern/abc_object.cc56
-rw-r--r--source/blender/alembic/intern/abc_object.h6
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc2
-rw-r--r--tests/python/bl_alembic_import_test.py33
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.