Alembic import: fixed dupligroup export when the dupli-empty has a parent
This commit is contained in:
@@ -448,7 +448,12 @@ AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *pare
|
|||||||
* parent by name. We'll just call createTransformWriter(), which will
|
* parent by name. We'll just call createTransformWriter(), which will
|
||||||
* return the parent's AbcTransformWriter pointer. */
|
* return the parent's AbcTransformWriter pointer. */
|
||||||
if (parent->parent) {
|
if (parent->parent) {
|
||||||
parent_writer = createTransformWriter(parent, parent->parent, dupliObParent);
|
if (parent == dupliObParent) {
|
||||||
|
parent_writer = createTransformWriter(parent, parent->parent, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parent_writer = createTransformWriter(parent, parent->parent, dupliObParent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (parent == dupliObParent) {
|
else if (parent == dupliObParent) {
|
||||||
if (dupliObParent->parent == NULL) {
|
if (dupliObParent->parent == NULL) {
|
||||||
@@ -468,6 +473,12 @@ AbcTransformWriter * AbcExporter::createTransformWriter(Object *ob, Object *pare
|
|||||||
|
|
||||||
my_writer = new AbcTransformWriter(ob, alembic_parent, parent_writer,
|
my_writer = new AbcTransformWriter(ob, alembic_parent, parent_writer,
|
||||||
m_trans_sampling_index, m_settings);
|
m_trans_sampling_index, m_settings);
|
||||||
|
|
||||||
|
/* When flattening, the matrix of the dupliobject has to be added. */
|
||||||
|
if (m_settings.flatten_hierarchy && dupliObParent) {
|
||||||
|
my_writer->m_proxy_from = dupliObParent;
|
||||||
|
}
|
||||||
|
|
||||||
m_xforms[name] = my_writer;
|
m_xforms[name] = my_writer;
|
||||||
return my_writer;
|
return my_writer;
|
||||||
}
|
}
|
||||||
|
@@ -62,6 +62,7 @@ AbcTransformWriter::AbcTransformWriter(Object *ob,
|
|||||||
unsigned int time_sampling,
|
unsigned int time_sampling,
|
||||||
ExportSettings &settings)
|
ExportSettings &settings)
|
||||||
: AbcObjectWriter(NULL, ob, time_sampling, settings, parent)
|
: AbcObjectWriter(NULL, ob, time_sampling, settings, parent)
|
||||||
|
, m_proxy_from(NULL)
|
||||||
{
|
{
|
||||||
m_is_animated = hasAnimation(m_object);
|
m_is_animated = hasAnimation(m_object);
|
||||||
|
|
||||||
@@ -90,7 +91,8 @@ void AbcTransformWriter::do_write()
|
|||||||
|
|
||||||
float yup_mat[4][4];
|
float yup_mat[4][4];
|
||||||
create_transform_matrix(m_object, yup_mat,
|
create_transform_matrix(m_object, yup_mat,
|
||||||
m_inherits_xform ? ABC_MATRIX_LOCAL : ABC_MATRIX_WORLD);
|
m_inherits_xform ? ABC_MATRIX_LOCAL : ABC_MATRIX_WORLD,
|
||||||
|
m_proxy_from);
|
||||||
|
|
||||||
/* Only apply rotation to root camera, parenting will propagate it. */
|
/* Only apply rotation to root camera, parenting will propagate it. */
|
||||||
if (m_object->type == OB_CAMERA && (!m_inherits_xform || !has_parent_camera(m_object))) {
|
if (m_object->type == OB_CAMERA && (!m_inherits_xform || !has_parent_camera(m_object))) {
|
||||||
|
@@ -40,6 +40,9 @@ class AbcTransformWriter : public AbcObjectWriter {
|
|||||||
bool m_visible;
|
bool m_visible;
|
||||||
bool m_inherits_xform;
|
bool m_inherits_xform;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Object *m_proxy_from;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AbcTransformWriter(Object *ob,
|
AbcTransformWriter(Object *ob,
|
||||||
const Alembic::AbcGeom::OObject &abc_parent,
|
const Alembic::AbcGeom::OObject &abc_parent,
|
||||||
|
@@ -257,7 +257,8 @@ void convert_matrix(const Imath::M44d &xform, Object *ob, float r_mat[4][4])
|
|||||||
|
|
||||||
/* Recompute transform matrix of object in new coordinate system
|
/* Recompute transform matrix of object in new coordinate system
|
||||||
* (from Z-Up to Y-Up). */
|
* (from Z-Up to Y-Up). */
|
||||||
void create_transform_matrix(Object *obj, float r_yup_mat[4][4], AbcMatrixMode mode)
|
void create_transform_matrix(Object *obj, float r_yup_mat[4][4], AbcMatrixMode mode,
|
||||||
|
Object *proxy_from)
|
||||||
{
|
{
|
||||||
float zup_mat[4][4];
|
float zup_mat[4][4];
|
||||||
|
|
||||||
@@ -267,11 +268,16 @@ void create_transform_matrix(Object *obj, float r_yup_mat[4][4], AbcMatrixMode m
|
|||||||
* constraints and modifiers as well as the obj->parentinv matrix. */
|
* constraints and modifiers as well as the obj->parentinv matrix. */
|
||||||
invert_m4_m4(obj->parent->imat, obj->parent->obmat);
|
invert_m4_m4(obj->parent->imat, obj->parent->obmat);
|
||||||
mul_m4_m4m4(zup_mat, obj->parent->imat, obj->obmat);
|
mul_m4_m4m4(zup_mat, obj->parent->imat, obj->obmat);
|
||||||
copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
copy_m44_axis_swap(r_yup_mat, obj->obmat, ABC_YUP_FROM_ZUP);
|
copy_m4_m4(zup_mat, obj->obmat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (proxy_from) {
|
||||||
|
mul_m4_m4m4(zup_mat, proxy_from->obmat, zup_mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name)
|
bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name)
|
||||||
|
@@ -62,7 +62,8 @@ typedef enum {
|
|||||||
ABC_MATRIX_WORLD = 1,
|
ABC_MATRIX_WORLD = 1,
|
||||||
ABC_MATRIX_LOCAL = 2,
|
ABC_MATRIX_LOCAL = 2,
|
||||||
} AbcMatrixMode;
|
} AbcMatrixMode;
|
||||||
void create_transform_matrix(Object *obj, float r_transform_mat[4][4], AbcMatrixMode mode);
|
void create_transform_matrix(Object *obj, float r_transform_mat[4][4],
|
||||||
|
AbcMatrixMode mode, Object *proxy_from);
|
||||||
|
|
||||||
void split(const std::string &s, const char delim, std::vector<std::string> &tokens);
|
void split(const std::string &s, const char delim, std::vector<std::string> &tokens);
|
||||||
|
|
||||||
|
@@ -221,5 +221,46 @@ class HierarchicalAndFlatExportTest(AbstractAlembicTest):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DupliGroupExportTest(AbstractAlembicTest):
|
||||||
|
@with_tempdir
|
||||||
|
def test_hierarchical_export(self, tempdir: pathlib.Path):
|
||||||
|
abc = tempdir / 'dupligroup_hierarchical.abc'
|
||||||
|
script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \
|
||||||
|
"renderable_only=True, visible_layers_only=True, flatten=False)" % abc
|
||||||
|
self.run_blender('dupligroup-scene.blend', script)
|
||||||
|
|
||||||
|
# Now check the resulting Alembic file.
|
||||||
|
xform = self.abcprop(abc, '/Real_Cube/Linked_Suzanne/Cylinder/Suzanne/.xform')
|
||||||
|
self.assertEqual(1, xform['.inherits'])
|
||||||
|
self.assertAlmostEqualFloatArray(
|
||||||
|
xform['.vals'],
|
||||||
|
[1.0, 0.0, 0.0, 0.0,
|
||||||
|
0.0, 1.0, 0.0, 0.0,
|
||||||
|
0.0, 0.0, 1.0, 0.0,
|
||||||
|
0.0, 2.0, 0.0, 1.0]
|
||||||
|
)
|
||||||
|
|
||||||
|
@with_tempdir
|
||||||
|
def test_flat_export(self, tempdir: pathlib.Path):
|
||||||
|
abc = tempdir / 'dupligroup_hierarchical.abc'
|
||||||
|
script = "import bpy; bpy.ops.wm.alembic_export(filepath='%s', start=1, end=1, " \
|
||||||
|
"renderable_only=True, visible_layers_only=True, flatten=True)" % abc
|
||||||
|
self.run_blender('dupligroup-scene.blend', script)
|
||||||
|
|
||||||
|
# Now check the resulting Alembic file.
|
||||||
|
xform = self.abcprop(abc, '/Suzanne/.xform')
|
||||||
|
self.assertEqual(0, xform['.inherits'])
|
||||||
|
|
||||||
|
self.assertAlmostEqualFloatArray(
|
||||||
|
xform['.vals'],
|
||||||
|
[1.5, 0.0, 0.0, 0.0,
|
||||||
|
0.0, 1.5, 0.0, 0.0,
|
||||||
|
0.0, 0.0, 1.5, 0.0,
|
||||||
|
2.0, 3.0, 0.0, 1.0]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main(argv=sys.argv[0:1])
|
unittest.main(argv=sys.argv[0:1])
|
||||||
|
Reference in New Issue
Block a user