[Bf-blender-cvs] [bc19c3ba72f] temp-sybren-alembic: Alembic import: fixed crash on more complex model

Sybren A. Stüvel noreply at git.blender.org
Tue Apr 4 17:48:56 CEST 2017


Commit: bc19c3ba72f8def0dd5b04b510261a054ed1a70b
Author: Sybren A. Stüvel
Date:   Tue Apr 4 17:05:47 2017 +0200
Branches: temp-sybren-alembic
https://developer.blender.org/rBbc19c3ba72f8def0dd5b04b510261a054ed1a70b

Alembic import: fixed crash on more complex model

There was a problem with parent-child relations not getting set up
correctly when an Alembic object was both the transform for a mesh object
and the parent of other mesh objects.

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

M	source/blender/alembic/intern/abc_object.cc
M	source/blender/alembic/intern/alembic_capi.cc

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

diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc
index 6a9facd15af..d93326be918 100644
--- a/source/blender/alembic/intern/abc_object.cc
+++ b/source/blender/alembic/intern/abc_object.cc
@@ -286,6 +286,17 @@ void AbcObjectReader::read_matrix(float r_mat[4][4], const float time,
 	}
 	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);
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index 761ea598924..380227f2e74 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -407,8 +407,13 @@ static bool visit_object(const IObject &object,
 	// or a Blender object (empty) themselves.
 	size_t children_claiming_this_object = 0;
 	size_t num_children = object.getNumChildren();
+	IObject first_claiming_child;
 	for (size_t i = 0; i < num_children; ++i) {
-		bool child_claims_this_object = visit_object(object.getChild(i), readers, readers_map, settings);
+		const IObject ichild = object.getChild(i);
+		bool child_claims_this_object = visit_object(ichild , readers, readers_map, settings);
+		if (child_claims_this_object && !first_claiming_child) {
+			first_claiming_child = ichild;
+		}
 		children_claiming_this_object += child_claims_this_object ? 1 : 0;
 	}
 
@@ -535,7 +540,27 @@ static bool visit_object(const IObject &object,
 		 * memory, for example when dealing with instances. */
 		char * name_copy = static_cast<char *>(MEM_mallocN(
 		                                           full_name.length() + 1,
-		                                           "Alembic readers_map key"));
+		                                           "Alembic readers_map key 1"));
+		BLI_strncpy(name_copy, full_name.c_str(), full_name.length() + 1);
+		BLI_ghash_insert(readers_map, name_copy, reader);
+	}
+	else if (children_claiming_this_object > 0) {
+		/* In this case, add it to reader_map under the name of the claiming
+		 * child, but do not add to readers. The latter is used to instantiate
+		 * the new objects (which shouldn't be done for this one), whereas the
+		 * former is used for parent-child relationships (for which this
+		 * Alembic object should be represented by its claiming child). */
+
+		reader = reinterpret_cast<AbcObjectReader *>(
+		             BLI_ghash_lookup(readers_map,
+		                              first_claiming_child.getFullName().c_str())
+		             );
+
+		/* We have to take a copy of the name, because Alembic can reuse
+		 * memory, for example when dealing with instances. */
+		char * name_copy = static_cast<char *>(MEM_mallocN(
+		                                           full_name.length() + 1,
+		                                           "Alembic readers_map key 2"));
 		BLI_strncpy(name_copy, full_name.c_str(), full_name.length() + 1);
 		BLI_ghash_insert(readers_map, name_copy, reader);
 	}
@@ -698,6 +723,7 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
 		const AbcObjectReader *reader = *iter;
 		const AbcObjectReader *parent_reader = NULL;
 		const IObject &iobject = reader->iobject();
+		Object *ob = reader->object();
 
 		/* Find the parent reader by going up in the Alembic hierarchy until we find it.
 		 * Some Xform Alembic objects do not produce an AbcEmptyReader, since they
@@ -709,7 +735,10 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
 			parent_reader = reinterpret_cast<AbcObjectReader *>(
 			                    BLI_ghash_lookup(data->readers_map,
 			                                     parent_name));
-			if (parent_reader != NULL) {
+			/* NULL means: the reader with this name doesn't exist
+			 * equal to ob means: the Alembic object with this name represents
+			 * the same object, and the real parent is found higher up. */
+			if (parent_reader != NULL && parent_reader->object() != ob) {
 				break;  // found the parent reader.
 			}
 
@@ -720,7 +749,6 @@ static void import_startjob(void *user_data, short *stop, short *do_update, floa
 			Object *blender_parent = parent_reader->object();
 
 			if (blender_parent != NULL && reader->object() != blender_parent) {
-				Object *ob = reader->object();
 				ob->parent = blender_parent;
 			}
 		}




More information about the Bf-blender-cvs mailing list