[Bf-blender-cvs] [32edfd53d97] master: Fix T52022 Alembic Inherits transform not taken into account

Sybren A. Stüvel noreply at git.blender.org
Tue Jul 11 16:18:04 CEST 2017


Commit: 32edfd53d978b34c9eb528e705f29e3feb673d37
Author: Sybren A. Stüvel
Date:   Tue Jul 11 16:16:56 2017 +0200
Branches: master
https://developer.blender.org/rB32edfd53d978b34c9eb528e705f29e3feb673d37

Fix T52022 Alembic Inherits transform not taken into account

Alembic's "inherits transform" flag wasn't taken into account when
constructing the parent object relations.

===================================================================

M	source/blender/alembic/intern/abc_object.cc
M	source/blender/alembic/intern/abc_object.h
M	source/blender/alembic/intern/alembic_capi.cc
M	tests/python/bl_alembic_import_test.py

===================================================================

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.




More information about the Bf-blender-cvs mailing list