Fix T77021: Alembic export of animated mesh with multiple UV maps fails

This was caused by a side-effect of our exporting code's memory
management (Alembic considers data "written" and "final" when its C++
objects go out of scope) in combination with my change in
rB65574463fa2d. I removed an "only export UVs on the first frame" clause
because it was unclear why this restriction was there. As it turns out,
it breaks the export of the 2nd and subsequent UV maps on an animated
mesh. Effectively, on every frame the Alembic library thought we want to
create a new UV map, instead of continuing to write a new frame of data
to the existing one.

This is resolved by keeping a reference to the C++ objects for the UV
maps in memory while the exporter is running.
This commit is contained in:
Sybren A. Stüvel
2020-05-26 16:38:47 +02:00
parent f3cf29ac96
commit a1c9d42584
3 changed files with 73 additions and 5 deletions

View File

@@ -84,6 +84,7 @@ class AbstractAlembicTest(AbstractBlenderRunnerTest):
'uint8_t': int,
'int16_t': int,
'int32_t': int,
'uint32_t': int,
'uint64_t': int,
'float64_t': float,
'float32_t': float,
@@ -325,6 +326,60 @@ class HairParticlesExportTest(AbstractAlembicTest):
self.assertIn('.faceIndices', abcprop)
class UVMapExportTest(AbstractAlembicTest):
@with_tempdir
def test_uvmap_export(self, tempdir: pathlib.Path):
"""Minimal test for exporting multiple UV maps on an animated mesh.
This covers the issue reported in T77021.
"""
basename = 'T77021-multiple-uvmaps-animated-mesh'
abc = tempdir / f'{basename}.abc'
script = f"import bpy; bpy.ops.wm.alembic_export(filepath='{abc.as_posix()}', start=1, end=1, " \
f"renderable_only=True, visible_objects_only=True, flatten=False)"
self.run_blender(f'{basename}.blend', script)
self.maxDiff = 1000
# The main UV map should be written to .geom
abcprop = self.abcprop(abc, '/Cube/CubeShape/.geom/uv')
self.assertEqual(abcprop['.vals'], [
[0.625, 0.75],
[0.875, 0.75],
[0.875, 0.5],
[0.625, 0.5],
[0.375, 1.0],
[0.625, 1.0],
[0.375, 0.75],
[0.375, 0.25],
[0.625, 0.25],
[0.625, 0.0],
[0.375, 0.0],
[0.125, 0.75],
[0.375, 0.5],
[0.125, 0.5],
])
# The second UV map should be written to .arbGeomParams
abcprop = self.abcprop(abc, '/Cube/CubeShape/.geom/.arbGeomParams/Secondary')
self.assertEqual(abcprop['.vals'], [
[0.75, 0.375],
[0.75, 0.125],
[0.5, 0.125],
[0.5, 0.375],
[1.0, 0.625],
[1.0, 0.375],
[0.75, 0.625],
[0.25, 0.625],
[0.25, 0.375],
[0.0, 0.375],
[0.0, 0.625],
[0.75, 0.875],
[0.5, 0.625],
[0.5, 0.875],
])
class LongNamesExportTest(AbstractAlembicTest):
@with_tempdir
def test_export_long_names(self, tempdir: pathlib.Path):