Alembic export: fixed curve type and order.

The order number written to Alembic is the same as we use in memory, so
the +1 wasn't needed, at least according to the reference Maya exporter
maya/AbcExport/MayaNurbsCurveWriter.cpp, function
MayaNurbsCurveWriter::write(), in the Alembic source code.

Furthermore, when writing an array of nurb orders, the curve type should
be set to kVariableOrder, otherwise the importer will ignore it.
This commit is contained in:
Sybren A. Stüvel 2017-04-18 12:17:07 +02:00
parent 8825a8e951
commit d24578b676
2 changed files with 46 additions and 10 deletions

View File

@ -95,7 +95,7 @@ void AbcCurveWriter::do_write()
for (; nurbs; nurbs = nurbs->next) {
if (nurbs->bp) {
curve_basis = Alembic::AbcGeom::kNoBasis;
curve_type = Alembic::AbcGeom::kLinear;
curve_type = Alembic::AbcGeom::kVariableOrder;
const int totpoint = nurbs->pntsu * nurbs->pntsv;
@ -160,7 +160,7 @@ void AbcCurveWriter::do_write()
}
}
orders.push_back(nurbs->orderu + 1);
orders.push_back(nurbs->orderu);
vert_counts.push_back(verts.size());
}

View File

@ -116,6 +116,7 @@ class AbstractAlembicTest(unittest.TestCase):
The Python bindings for Alembic are old, and only compatible with Python 2.x,
so that's why we can't use them here, and have to rely on other tooling.
"""
import collections
abcls = self.alembic_root / 'bin' / 'abcls'
@ -133,14 +134,19 @@ class AbstractAlembicTest(unittest.TestCase):
converters = {
'bool_t': int,
'uint8_t': int,
'int32_t': int,
'float64_t': float,
'float32_t': float,
}
result = {}
# Ideally we'd get abcls to output JSON, see https://github.com/alembic/alembic/issues/121
lines = output.split('\n')
for info, value in zip(lines[0::2], lines[1::2]):
lines = collections.deque(output.split('\n'))
while lines:
info = lines.popleft()
if not info:
continue
proptype, valtype_and_arrsize, name_and_extent = info.split()
# Parse name and extent
@ -152,22 +158,41 @@ class AbstractAlembicTest(unittest.TestCase):
if extent != '1':
self.fail('Unsupported extent %s for property %s/%s' % (extent, proppath, name))
# Parse type and convert values
# Parse type
m = self.abcls_array.match(valtype_and_arrsize)
if not m:
self.fail('Unparsable value type from abcls: %s' % valtype_and_arrsize)
valtype, arraysize = m.group('name'), m.group('arraysize')
valtype, scalarsize = m.group('name'), m.group('arraysize')
# Convert values
try:
conv = converters[valtype]
except KeyError:
self.fail('Unsupported type %s for property %s/%s' % (valtype, proppath, name))
if arraysize is None:
result[name] = conv(value)
def convert_single_line(linevalue):
try:
if scalarsize is None:
return conv(linevalue)
else:
return [conv(v.strip()) for v in linevalue.split(',')]
except ValueError as ex:
return str(ex)
if proptype == 'ScalarProperty':
value = lines.popleft()
result[name] = convert_single_line(value)
elif proptype == 'ArrayProperty':
arrayvalue = []
# Arrays consist of a variable number of items, and end in a blank line.
while True:
linevalue = lines.popleft()
if not linevalue:
break
arrayvalue.append(convert_single_line(linevalue))
result[name] = arrayvalue
else:
values = [conv(v.strip()) for v in value.split(',')]
result[name] = values
self.fail('Unsupported type %s for property %s/%s' % (proptype, proppath, name))
return result
@ -260,6 +285,17 @@ class DupliGroupExportTest(AbstractAlembicTest):
)
class CurveExportTest(AbstractAlembicTest):
@with_tempdir
def test_export_single_curve(self, tempdir: pathlib.Path):
abc = tempdir / 'single-curve.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('single-curve.blend', script)
# Now check the resulting Alembic file.
abcprop = self.abcprop(abc, '/NurbsCurve/NurbsCurveShape/.geom')
self.assertEqual(abcprop['.orders'], [4])
if __name__ == '__main__':