Merge remote-tracking branch 'origin/blender-v2.83-release'
This commit is contained in:
@@ -144,7 +144,7 @@ const char *get_uv_sample(UVSample &sample, const CDStreamConfig &config, Custom
|
|||||||
* - (optional due to its behavior) tag as UV using Alembic::AbcGeom::SetIsUV
|
* - (optional due to its behavior) tag as UV using Alembic::AbcGeom::SetIsUV
|
||||||
*/
|
*/
|
||||||
static void write_uv(const OCompoundProperty &prop,
|
static void write_uv(const OCompoundProperty &prop,
|
||||||
const CDStreamConfig &config,
|
CDStreamConfig &config,
|
||||||
void *data,
|
void *data,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
@@ -157,13 +157,18 @@ static void write_uv(const OCompoundProperty &prop,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OV2fGeomParam param(prop, name, true, kFacevaryingScope, 1);
|
std::string uv_map_name(name);
|
||||||
|
OV2fGeomParam param = config.abc_uv_maps[uv_map_name];
|
||||||
|
|
||||||
|
if (!param.valid()) {
|
||||||
|
param = OV2fGeomParam(prop, name, true, kFacevaryingScope, 1);
|
||||||
|
}
|
||||||
OV2fGeomParam::Sample sample(V2fArraySample(&uvs.front(), uvs.size()),
|
OV2fGeomParam::Sample sample(V2fArraySample(&uvs.front(), uvs.size()),
|
||||||
UInt32ArraySample(&indices.front(), indices.size()),
|
UInt32ArraySample(&indices.front(), indices.size()),
|
||||||
kFacevaryingScope);
|
kFacevaryingScope);
|
||||||
|
|
||||||
param.set(sample);
|
param.set(sample);
|
||||||
|
|
||||||
|
config.abc_uv_maps[uv_map_name] = param;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convention to write Vertex Colors:
|
/* Convention to write Vertex Colors:
|
||||||
@@ -217,7 +222,7 @@ static void write_mcol(const OCompoundProperty &prop,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void write_custom_data(const OCompoundProperty &prop,
|
void write_custom_data(const OCompoundProperty &prop,
|
||||||
const CDStreamConfig &config,
|
CDStreamConfig &config,
|
||||||
CustomData *data,
|
CustomData *data,
|
||||||
int data_type)
|
int data_type)
|
||||||
{
|
{
|
||||||
|
@@ -27,6 +27,8 @@
|
|||||||
#include <Alembic/Abc/All.h>
|
#include <Alembic/Abc/All.h>
|
||||||
#include <Alembic/AbcGeom/All.h>
|
#include <Alembic/AbcGeom/All.h>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
struct CustomData;
|
struct CustomData;
|
||||||
struct MLoop;
|
struct MLoop;
|
||||||
struct MLoopUV;
|
struct MLoopUV;
|
||||||
@@ -70,6 +72,12 @@ struct CDStreamConfig {
|
|||||||
|
|
||||||
const char **modifier_error_message;
|
const char **modifier_error_message;
|
||||||
|
|
||||||
|
/* Alembic needs Blender to keep references to C++ objects (the destructors
|
||||||
|
* finalise the writing to ABC). This map stores OV2fGeomParam objects for the
|
||||||
|
* 2nd and subsequent UV maps; the primary UV map is kept alive by the Alembic
|
||||||
|
* mesh sample itself. */
|
||||||
|
std::map<std::string, Alembic::AbcGeom::OV2fGeomParam> abc_uv_maps;
|
||||||
|
|
||||||
CDStreamConfig()
|
CDStreamConfig()
|
||||||
: mloop(NULL),
|
: mloop(NULL),
|
||||||
totloop(0),
|
totloop(0),
|
||||||
@@ -95,7 +103,7 @@ struct CDStreamConfig {
|
|||||||
const char *get_uv_sample(UVSample &sample, const CDStreamConfig &config, CustomData *data);
|
const char *get_uv_sample(UVSample &sample, const CDStreamConfig &config, CustomData *data);
|
||||||
|
|
||||||
void write_custom_data(const OCompoundProperty &prop,
|
void write_custom_data(const OCompoundProperty &prop,
|
||||||
const CDStreamConfig &config,
|
CDStreamConfig &config,
|
||||||
CustomData *data,
|
CustomData *data,
|
||||||
int data_type);
|
int data_type);
|
||||||
|
|
||||||
|
@@ -84,6 +84,7 @@ class AbstractAlembicTest(AbstractBlenderRunnerTest):
|
|||||||
'uint8_t': int,
|
'uint8_t': int,
|
||||||
'int16_t': int,
|
'int16_t': int,
|
||||||
'int32_t': int,
|
'int32_t': int,
|
||||||
|
'uint32_t': int,
|
||||||
'uint64_t': int,
|
'uint64_t': int,
|
||||||
'float64_t': float,
|
'float64_t': float,
|
||||||
'float32_t': float,
|
'float32_t': float,
|
||||||
@@ -325,6 +326,60 @@ class HairParticlesExportTest(AbstractAlembicTest):
|
|||||||
self.assertIn('.faceIndices', abcprop)
|
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):
|
class LongNamesExportTest(AbstractAlembicTest):
|
||||||
@with_tempdir
|
@with_tempdir
|
||||||
def test_export_long_names(self, tempdir: pathlib.Path):
|
def test_export_long_names(self, tempdir: pathlib.Path):
|
||||||
|
Reference in New Issue
Block a user