Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKévin Dietrich <kevin.dietrich@mailoo.org>2022-03-13 21:50:35 +0300
committerKévin Dietrich <kevin.dietrich@mailoo.org>2022-03-13 21:50:35 +0300
commitc0ef2a5cf56590c7b01502d8d6c5a18067afc028 (patch)
treef04018116f9c412cea30bb6cc14c6a0357568e33
parent5a0efc9c8b5ad991109c97d52d476d8c071a78ac (diff)
Start replacing write_custom_data with the attribute exporter.temp-abc-features
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_mesh.cc32
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_mesh.h4
-rw-r--r--source/blender/io/alembic/intern/abc_customdata.cc383
-rw-r--r--source/blender/io/alembic/intern/abc_customdata.h85
4 files changed, 318 insertions, 186 deletions
diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.cc b/source/blender/io/alembic/exporter/abc_writer_mesh.cc
index 11693eeb4de..44924f9cee0 100644
--- a/source/blender/io/alembic/exporter/abc_writer_mesh.cc
+++ b/source/blender/io/alembic/exporter/abc_writer_mesh.cc
@@ -76,6 +76,12 @@ static void get_loop_normals(struct Mesh *mesh,
ABCGenericMeshWriter::ABCGenericMeshWriter(const ABCWriterConstructorArgs &args)
: ABCAbstractWriter(args), is_subd_(false)
{
+ attribute_exporter_ = nullptr;
+}
+
+ABCGenericMeshWriter::~ABCGenericMeshWriter()
+{
+ delete_attribute_exporter(attribute_exporter_);
}
void ABCGenericMeshWriter::create_alembic_objects(const HierarchyContext *context)
@@ -254,10 +260,6 @@ void ABCGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh)
mesh_sample.setNormals(normals_sample);
}
- if (args_.export_params->orcos) {
- write_generated_coordinates(abc_poly_mesh_schema_.getArbGeomParams(), m_custom_data_config);
- }
-
if (get_velocities(mesh, velocities)) {
mesh_sample.setVelocities(V3fArraySample(velocities));
}
@@ -266,7 +268,6 @@ void ABCGenericMeshWriter::write_mesh(HierarchyContext &context, Mesh *mesh)
mesh_sample.setSelfBounds(bounding_box_);
abc_poly_mesh_schema_.set(mesh_sample);
-
write_arb_geo_params(mesh);
}
@@ -308,10 +309,6 @@ void ABCGenericMeshWriter::write_subd(HierarchyContext &context, struct Mesh *me
abc_subdiv_schema_.getArbGeomParams(), m_custom_data_config, &mesh->ldata, CD_MLOOPUV);
}
- if (args_.export_params->orcos) {
- write_generated_coordinates(abc_subdiv_schema_.getArbGeomParams(), m_custom_data_config);
- }
-
if (!edge_crease_indices.empty()) {
subdiv_sample.setCreaseIndices(Int32ArraySample(edge_crease_indices));
subdiv_sample.setCreaseLengths(Int32ArraySample(edge_crease_lengths));
@@ -347,8 +344,15 @@ void ABCGenericMeshWriter::write_face_sets(Object *object, struct Mesh *mesh, Sc
void ABCGenericMeshWriter::write_arb_geo_params(struct Mesh *me)
{
+ int64_t cd_mask = CD_MASK_ALL;
if (!args_.export_params->vcolors) {
- return;
+ cd_mask &= ~CD_MASK_MCOL;
+ }
+ if (!args_.export_params->uvs) {
+ cd_mask &= ~CD_MASK_MLOOPUV;
+ }
+ if (!args_.export_params->orcos) {
+ cd_mask &= ~CD_MASK_ORCO;
}
OCompoundProperty arb_geom_params;
@@ -358,7 +362,13 @@ void ABCGenericMeshWriter::write_arb_geo_params(struct Mesh *me)
else {
arb_geom_params = abc_poly_mesh_.getSchema().getArbGeomParams();
}
- write_custom_data(arb_geom_params, m_custom_data_config, &me->ldata, CD_MLOOPCOL);
+
+ if (!attribute_exporter_) {
+ attribute_exporter_ = make_attribute_exporter(&me->id, cd_mask, arb_geom_params);
+ }
+
+ set_timesample_index(attribute_exporter_, m_custom_data_config.timesample_index);
+ attribute_exporter_->export_attributes();
}
bool ABCGenericMeshWriter::get_velocities(struct Mesh *mesh, std::vector<Imath::V3f> &vels)
diff --git a/source/blender/io/alembic/exporter/abc_writer_mesh.h b/source/blender/io/alembic/exporter/abc_writer_mesh.h
index a5d1a0e6613..7d9eb75d107 100644
--- a/source/blender/io/alembic/exporter/abc_writer_mesh.h
+++ b/source/blender/io/alembic/exporter/abc_writer_mesh.h
@@ -34,9 +34,13 @@ class ABCGenericMeshWriter : public ABCAbstractWriter {
CDStreamConfig m_custom_data_config;
+ GenericAttributeExporter *attribute_exporter_;
+
public:
explicit ABCGenericMeshWriter(const ABCWriterConstructorArgs &args);
+ ~ABCGenericMeshWriter();
+
virtual void create_alembic_objects(const HierarchyContext *context) override;
virtual Alembic::Abc::OObject get_alembic_object() const override;
Alembic::Abc::OCompoundProperty abc_prop_for_custom_props() override;
diff --git a/source/blender/io/alembic/intern/abc_customdata.cc b/source/blender/io/alembic/intern/abc_customdata.cc
index 0ecff22c02b..5301fb2be48 100644
--- a/source/blender/io/alembic/intern/abc_customdata.cc
+++ b/source/blender/io/alembic/intern/abc_customdata.cc
@@ -249,38 +249,6 @@ static void write_mcol(const OCompoundProperty &prop,
config.abc_vertex_colors[vcol_name] = param;
}
-void write_generated_coordinates(const OCompoundProperty &prop, CDStreamConfig &config)
-{
- Mesh *mesh = config.mesh;
- const void *customdata = CustomData_get_layer(&mesh->vdata, CD_ORCO);
- if (customdata == nullptr) {
- /* Data not available, so don't even bother creating an Alembic property for it. */
- return;
- }
- const float(*orcodata)[3] = static_cast<const float(*)[3]>(customdata);
-
- /* Convert 3D vertices from float[3] z=up to V3f y=up. */
- std::vector<Imath::V3f> coords(config.totvert);
- float orco_yup[3];
- for (int vertex_idx = 0; vertex_idx < config.totvert; vertex_idx++) {
- copy_yup_from_zup(orco_yup, orcodata[vertex_idx]);
- coords[vertex_idx].setValue(orco_yup[0], orco_yup[1], orco_yup[2]);
- }
-
- /* ORCOs are always stored in the normalized 0..1 range in Blender, but Alembic stores them
- * unnormalized, so we need to unnormalize (invert transform) them. */
- BKE_mesh_orco_verts_transform(
- mesh, reinterpret_cast<float(*)[3]>(&coords[0]), mesh->totvert, true);
-
- if (!config.abc_orco.valid()) {
- /* Create the Alembic property and keep a reference so future frames can reuse it. */
- config.abc_orco = OV3fGeomParam(prop, propNameOriginalCoordinates, false, kVertexScope, 1);
- }
-
- OV3fGeomParam::Sample sample(coords, kVertexScope);
- config.abc_orco.set(sample);
-}
-
void write_custom_data(const OCompoundProperty &prop,
CDStreamConfig &config,
CustomData *data,
@@ -407,116 +375,95 @@ template<> struct type_trait_converter<ColorGeometry4f> {
}
};
-class GenericAttributeExporter {
- public:
- void export_attributes(ID *id)
- {
- DomainInfo domain_info[ATTR_DOMAIN_NUM];
- BKE_id_attribute_get_domains(id, domain_info);
-
- export_attribute_for_domain(domain_info[ATTR_DOMAIN_POINT], ATTR_DOMAIN_POINT);
- export_attribute_for_domain(domain_info[ATTR_DOMAIN_FACE], ATTR_DOMAIN_FACE);
- export_attribute_for_domain(domain_info[ATTR_DOMAIN_CORNER], ATTR_DOMAIN_CORNER);
- export_attribute_for_domain(domain_info[ATTR_DOMAIN_CURVE], ATTR_DOMAIN_CURVE);
- }
-
- protected:
- virtual void export_attribute(blender::Span<bool> span,
- const char *name,
- AttributeDomain domain) = 0;
-
- virtual void export_attribute(blender::Span<char> span,
- const char *name,
- AttributeDomain domain) = 0;
-
- virtual void export_attribute(blender::Span<int> span,
- const char *name,
- AttributeDomain domain) = 0;
-
- virtual void export_attribute(blender::Span<float> span,
- const char *name,
- AttributeDomain domain) = 0;
+void GenericAttributeExporter::export_attributes()
+{
+ DomainInfo domain_info[ATTR_DOMAIN_NUM];
+ BKE_id_attribute_get_domains(m_id, domain_info);
- virtual void export_attribute(blender::Span<float2> span,
- const char *name,
- AttributeDomain domain) = 0;
+ export_attribute_for_domain(domain_info[ATTR_DOMAIN_POINT], ATTR_DOMAIN_POINT);
+ export_attribute_for_domain(domain_info[ATTR_DOMAIN_FACE], ATTR_DOMAIN_FACE);
+ export_attribute_for_domain(domain_info[ATTR_DOMAIN_CORNER], ATTR_DOMAIN_CORNER);
+ export_attribute_for_domain(domain_info[ATTR_DOMAIN_CURVE], ATTR_DOMAIN_CURVE);
+}
- virtual void export_attribute(blender::Span<float3> span,
- const char *name,
- AttributeDomain domain) = 0;
+void GenericAttributeExporter::export_generated_coordinates(CustomDataLayer *layer,
+ DomainInfo info,
+ AttributeDomain domain)
+{
+ BLI_assert_msg(GS(m_id->name) == ID_ME, "ORCO layer found on an ID that is not a Mesh!");
- virtual void export_attribute(blender::Span<ColorGeometry4f> span,
- const char *name,
- AttributeDomain domain) = 0;
+ Mesh *mesh = reinterpret_cast<Mesh *>(m_id);
+ /* Duplicate data for transformation. */
+ float3 *export_data = static_cast<float3 *>(MEM_dupallocN(layer->data));
- virtual void export_attribute(blender::Span<MLoopUV> span,
- const char *name,
- AttributeDomain domain) = 0;
+ /* ORCOs are always stored in the normalized 0..1 range in Blender, but Alembic stores them
+ * unnormalized, so we need to unnormalize (invert transform) them. */
+ BKE_mesh_orco_verts_transform(
+ mesh, reinterpret_cast<float(*)[3]>(&export_data[0].x), mesh->totvert, true);
- virtual void export_attribute(blender::Span<MCol> span,
- const char *name,
- AttributeDomain domain) = 0;
+ int64_t size = static_cast<int64_t>(info.length);
+ blender::Span<float3> data_span(export_data, size);
+ this->export_attribute(data_span, propNameOriginalCoordinates.c_str(), domain);
+ MEM_freeN(export_data);
+}
- template<typename BlenderDataType>
- void export_customdata_layer(CustomDataLayer *layer, DomainInfo info, AttributeDomain domain)
- {
- BlenderDataType *data = static_cast<BlenderDataType *>(layer->data);
- int64_t size = static_cast<int64_t>(info.length);
- blender::Span<BlenderDataType> data_span(data, size);
- this->export_attribute(data_span, layer->name, domain);
+void GenericAttributeExporter::export_attribute_for_domain(DomainInfo info, AttributeDomain domain)
+{
+ if (info.length == 0 || info.customdata == nullptr || info.customdata->layers == nullptr ||
+ info.customdata->totlayer == 0) {
+ return;
}
- void export_attribute_for_domain(DomainInfo info, AttributeDomain domain)
- {
- if (info.length == 0 || info.customdata == nullptr || info.customdata->layers == nullptr ||
- info.customdata->totlayer == 0) {
- return;
- }
+ CustomData *customdata = info.customdata;
+ for (int i = 0; i < customdata->totlayer; i++) {
+ CustomDataLayer *layer = &customdata->layers[i];
- CustomData *customdata = info.customdata;
- for (int i = 0; i < customdata->totlayer; i++) {
- CustomDataLayer *layer = &customdata->layers[i];
-
- if (layer->type == CD_PROP_BOOL) {
- export_customdata_layer<bool>(layer, info, domain);
- }
- else if (layer->type == CD_PROP_INT8) {
- export_customdata_layer<char>(layer, info, domain);
- }
- else if (layer->type == CD_PROP_INT32) {
- export_customdata_layer<int>(layer, info, domain);
- }
- else if (layer->type == CD_PROP_COLOR) {
- export_customdata_layer<ColorGeometry4f>(layer, info, domain);
- }
- else if (layer->type == CD_PROP_FLOAT) {
- export_customdata_layer<float>(layer, info, domain);
- }
- else if (layer->type == CD_PROP_FLOAT2) {
- export_customdata_layer<float2>(layer, info, domain);
- }
- else if (layer->type == CD_PROP_FLOAT3) {
- // todo: velocities
- export_customdata_layer<float3>(layer, info, domain);
- }
- else if (layer->type == CD_MLOOPUV) {
- BLI_assert_msg(domain == ATTR_DOMAIN_CORNER, "MLoopUVs found on non-corner domain!");
+ if (layer->type == CD_PROP_BOOL) {
+ export_customdata_layer<bool>(layer, info, domain);
+ }
+ else if (layer->type == CD_PROP_INT8) {
+ export_customdata_layer<char>(layer, info, domain);
+ }
+ else if (layer->type == CD_PROP_INT32) {
+ export_customdata_layer<int>(layer, info, domain);
+ }
+ else if (layer->type == CD_PROP_COLOR) {
+ export_customdata_layer<ColorGeometry4f>(layer, info, domain);
+ }
+ else if (layer->type == CD_PROP_FLOAT) {
+ export_customdata_layer<float>(layer, info, domain);
+ }
+ else if (layer->type == CD_PROP_FLOAT2) {
+ export_customdata_layer<float2>(layer, info, domain);
+ }
+ else if (layer->type == CD_PROP_FLOAT3) {
+ export_customdata_layer<float3>(layer, info, domain);
+ }
+ else if (layer->type == CD_MLOOPUV) {
+ BLI_assert_msg(domain == ATTR_DOMAIN_CORNER, "MLoopUVs found on non-corner domain!");
+ if (cd_mask & CD_MASK_MLOOPUV) {
export_customdata_layer<MLoopUV>(layer, info, domain);
}
- else if (layer->type == CD_MCOL) {
- BLI_assert_msg(domain == ATTR_DOMAIN_CORNER, "MCol found on non-corner domain!");
+ }
+ else if (layer->type == CD_MCOL) {
+ BLI_assert_msg(domain == ATTR_DOMAIN_CORNER, "MCol found on non-corner domain!");
+ if (cd_mask & CD_MASK_MCOL) {
export_customdata_layer<MCol>(layer, info, domain);
}
- else if (layer->type == CD_ORCO) {
- // todo CD_ORCO
+ }
+ else if (layer->type == CD_ORCO) {
+ if (cd_mask & CD_MASK_ORCO) {
+ export_generated_coordinates(layer, info, domain);
}
}
}
-};
+}
class AlembicAttributeExporter final : public GenericAttributeExporter {
const OCompoundProperty &prop;
+ int timesample_index_ = 0;
+
std::map<std::string, OBoolGeomParam> bool_params;
std::map<std::string, OCharGeomParam> int8_params;
std::map<std::string, OInt32GeomParam> int32_params;
@@ -528,8 +475,11 @@ class AlembicAttributeExporter final : public GenericAttributeExporter {
std::map<std::string, OC4fGeomParam> mcol_params;
public:
- AlembicAttributeExporter(const OCompoundProperty &prop_) : prop(prop_)
+ AlembicAttributeExporter(ID *id, int64_t cd_mask_, const OCompoundProperty &prop_);
+
+ void set_timesample_index(int timesample_index)
{
+ timesample_index_ = timesample_index;
}
private:
@@ -555,7 +505,7 @@ class AlembicAttributeExporter final : public GenericAttributeExporter {
template<typename BlenderDataType>
void create_attribute_for_data(blender::Span<BlenderDataType> span,
- const char *name,
+ const std::string &name,
AttributeDomain domain)
{
const Alembic::AbcGeom::GeometryScope scope = get_scope_for_attibute_domain(domain);
@@ -579,79 +529,161 @@ class AlembicAttributeExporter final : public GenericAttributeExporter {
ParamType param;
init_param(param, name, scope);
- // todo: param.setTimeSampling(config.timesample_index);
+ param.setTimeSampling(timesample_index_);
SampleType sample(values, scope);
param.set(sample);
}
+ void create_velocity_attribute(blender::Span<float3> span, AttributeDomain domain);
+
void export_attribute(blender::Span<bool> span,
- const char *name,
- AttributeDomain domain) override
- {
- create_attribute_for_data(span, name, domain);
- }
+ const std::string &name,
+ AttributeDomain domain) override;
void export_attribute(blender::Span<char> span,
- const char *name,
- AttributeDomain domain) override
- {
- create_attribute_for_data(span, name, domain);
- }
+ const std::string &name,
+ AttributeDomain domain) override;
- void export_attribute(blender::Span<int> span, const char *name, AttributeDomain domain) override
- {
- create_attribute_for_data(span, name, domain);
- }
+ void export_attribute(blender::Span<int> span,
+ const std::string &name,
+ AttributeDomain domain) override;
void export_attribute(blender::Span<float> span,
- const char *name,
- AttributeDomain domain) override
- {
- create_attribute_for_data(span, name, domain);
- }
+ const std::string &name,
+ AttributeDomain domain) override;
void export_attribute(blender::Span<float2> span,
- const char *name,
- AttributeDomain domain) override
- {
- create_attribute_for_data(span, name, domain);
- }
+ const std::string &name,
+ AttributeDomain domain) override;
void export_attribute(blender::Span<float3> span,
- const char *name,
- AttributeDomain domain) override
- {
- create_attribute_for_data(span, name, domain);
- }
+ const std::string &name,
+ AttributeDomain domain) override;
void export_attribute(blender::Span<ColorGeometry4f> span,
- const char *name,
- AttributeDomain domain) override
- {
- create_attribute_for_data(span, name, domain);
- }
+ const std::string &name,
+ AttributeDomain domain) override;
void export_attribute(blender::Span<MLoopUV> span,
- const char *name,
- AttributeDomain domain) override
- {
- // todo
- // if active layer, set_uvs
- }
+ const std::string &name,
+ AttributeDomain domain) override;
void export_attribute(blender::Span<MCol> span,
- const char *name,
- AttributeDomain domain) override
- {
- // todo
- }
+ const std::string &name,
+ AttributeDomain domain) override;
};
-static void write_arbitrary_attributes(ID *id, const OCompoundProperty &arb_geom_params)
+AlembicAttributeExporter::AlembicAttributeExporter(ID *id,
+ int64_t cd_mask_,
+ const OCompoundProperty &prop_)
+ : GenericAttributeExporter(id, cd_mask_), prop(prop_)
{
- AlembicAttributeExporter exporter{arb_geom_params};
- exporter.export_attributes(id);
+}
+
+void AlembicAttributeExporter::create_velocity_attribute(blender::Span<float3> span,
+ AttributeDomain domain)
+{
+ const Alembic::AbcGeom::GeometryScope scope = get_scope_for_attibute_domain(domain);
+ BLI_assert_msg(scope == kVertexScope, "The scope of the velocities should have been validated!");
+
+ using TypeConverter = type_trait_converter<float3>;
+ std::vector<V3f> values(static_cast<size_t>(span.size()));
+ V3f *values_ptr = values.data();
+ for (float3 value : span) {
+ *values_ptr++ = TypeConverter::convert(value);
+ }
+
+ /* Use default Alembic name. */
+ static std::string name = ".velocities";
+ OV3fGeomParam param = float3_params[name];
+ if (!param.valid()) {
+ param = OV3fGeomParam(prop, name, false, scope, 1);
+ float3_params[name] = param;
+ }
+ param.setTimeSampling(timesample_index_);
+
+ OV3fGeomParam::Sample sample(values, scope);
+ param.set(sample);
+}
+
+void AlembicAttributeExporter::export_attribute(blender::Span<bool> span,
+ const std::string &name,
+ AttributeDomain domain)
+{
+ create_attribute_for_data(span, name, domain);
+}
+
+void AlembicAttributeExporter::export_attribute(blender::Span<char> span,
+ const std::string &name,
+ AttributeDomain domain)
+{
+ create_attribute_for_data(span, name, domain);
+}
+
+void AlembicAttributeExporter::export_attribute(blender::Span<int> span,
+ const std::string &name,
+ AttributeDomain domain)
+{
+ create_attribute_for_data(span, name, domain);
+}
+
+void AlembicAttributeExporter::export_attribute(blender::Span<float> span,
+ const std::string &name,
+ AttributeDomain domain)
+{
+ create_attribute_for_data(span, name, domain);
+}
+
+void AlembicAttributeExporter::export_attribute(blender::Span<float2> span,
+ const std::string &name,
+ AttributeDomain domain)
+{
+ create_attribute_for_data(span, name, domain);
+}
+
+void AlembicAttributeExporter::export_attribute(blender::Span<float3> span,
+ const std::string &name,
+ AttributeDomain domain)
+{
+ if (name == "velocity" && domain == ATTR_DOMAIN_POINT) {
+ create_velocity_attribute(span, domain);
+ }
+ else {
+ create_attribute_for_data(span, name, domain);
+ }
+}
+
+void AlembicAttributeExporter::export_attribute(blender::Span<ColorGeometry4f> span,
+ const std::string &name,
+ AttributeDomain domain)
+{
+ create_attribute_for_data(span, name, domain);
+}
+
+void AlembicAttributeExporter::export_attribute(blender::Span<MLoopUV> /*span*/,
+ const std::string & /*name*/,
+ AttributeDomain /*domain*/)
+{
+ // todo
+ // if active layer, set_uvs
+}
+
+void AlembicAttributeExporter::export_attribute(blender::Span<MCol> /*span*/,
+ const std::string & /*name*/,
+ AttributeDomain /*domain*/)
+{
+ // todo
+}
+
+GenericAttributeExporter *make_attribute_exporter(ID *id, int64_t cd_mask, OCompoundProperty &prop)
+{
+ return new AlembicAttributeExporter(id, cd_mask, prop);
+}
+
+void set_timesample_index(GenericAttributeExporter *exporter, int timesample_index)
+{
+ static_cast<AlembicAttributeExporter *>(exporter)->set_timesample_index(timesample_index);
}
/* ************************************************************************** */
@@ -1984,4 +2016,9 @@ bool AttributeSelector::select_attribute(const std::string &attr_name) const
return true;
}
+void delete_attribute_exporter(GenericAttributeExporter *exporter)
+{
+ delete static_cast<AlembicAttributeExporter *>(exporter);
+}
+
} // namespace blender::io::alembic
diff --git a/source/blender/io/alembic/intern/abc_customdata.h b/source/blender/io/alembic/intern/abc_customdata.h
index 3b162364de8..b5dbb023100 100644
--- a/source/blender/io/alembic/intern/abc_customdata.h
+++ b/source/blender/io/alembic/intern/abc_customdata.h
@@ -13,7 +13,10 @@
#include "BKE_attribute.h"
+#include "BLI_color.hh"
#include "BLI_listbase_wrapper.hh"
+#include "BLI_math_vec_types.hh"
+#include "BLI_span.hh"
struct CacheAttributeMapping;
struct CustomData;
@@ -23,6 +26,7 @@ struct MLoopUV;
struct MPoly;
struct MVert;
struct Mesh;
+struct MCol;
using Alembic::Abc::ICompoundProperty;
using Alembic::Abc::OCompoundProperty;
@@ -111,13 +115,90 @@ struct CDStreamConfig {
* For now the active layer is used, maybe needs a better way to choose this. */
const char *get_uv_sample(UVSample &sample, const CDStreamConfig &config, CustomData *data);
-void write_generated_coordinates(const OCompoundProperty &prop, CDStreamConfig &config);
-
void write_custom_data(const OCompoundProperty &prop,
CDStreamConfig &config,
CustomData *data,
int data_type);
+/* Need special handling for:
+ * - creases (vertex/edge)
+ * - velocity
+ * - generated coordinate
+ * - UVs
+ * - vertex colors
+ */
+class GenericAttributeExporter {
+ ID *m_id;
+ int64_t cd_mask = CD_MASK_ALL;
+
+ public:
+ GenericAttributeExporter(ID *id, int64_t cd_mask_) : m_id(id), cd_mask(cd_mask_)
+ {
+ }
+
+ void export_attributes();
+
+ protected:
+ virtual void export_attribute(blender::Span<bool> span,
+ const std::string &name,
+ AttributeDomain domain) = 0;
+
+ virtual void export_attribute(blender::Span<char> span,
+ const std::string &name,
+ AttributeDomain domain) = 0;
+
+ virtual void export_attribute(blender::Span<int> span,
+ const std::string &name,
+ AttributeDomain domain) = 0;
+
+ virtual void export_attribute(blender::Span<float> span,
+ const std::string &name,
+ AttributeDomain domain) = 0;
+
+ virtual void export_attribute(blender::Span<float2> span,
+ const std::string &name,
+ AttributeDomain domain) = 0;
+
+ virtual void export_attribute(blender::Span<float3> span,
+ const std::string &name,
+ AttributeDomain domain) = 0;
+
+ virtual void export_attribute(blender::Span<ColorGeometry4f> span,
+ const std::string &name,
+ AttributeDomain domain) = 0;
+
+ virtual void export_attribute(blender::Span<MLoopUV> span,
+ const std::string &name,
+ AttributeDomain domain) = 0;
+
+ virtual void export_attribute(blender::Span<MCol> span,
+ const std::string &name,
+ AttributeDomain domain) = 0;
+
+ template<typename BlenderDataType>
+ void export_customdata_layer(CustomDataLayer *layer, DomainInfo info, AttributeDomain domain)
+ {
+ BlenderDataType *data = static_cast<BlenderDataType *>(layer->data);
+ int64_t size = static_cast<int64_t>(info.length);
+ blender::Span<BlenderDataType> data_span(data, size);
+ this->export_attribute(data_span, layer->name, domain);
+ }
+
+ void export_generated_coordinates(CustomDataLayer *layer,
+ DomainInfo info,
+ AttributeDomain domain);
+
+ void export_attribute_for_domain(DomainInfo info, AttributeDomain domain);
+};
+
+GenericAttributeExporter *make_attribute_exporter(ID *id,
+ int64_t cd_mask,
+ OCompoundProperty &prop);
+
+void set_timesample_index(GenericAttributeExporter *exporter, int timesample_index);
+
+void delete_attribute_exporter(GenericAttributeExporter *exporter);
+
class AttributeSelector {
/* Name of the velocity attribute, it is ignored since we deal with separately. */
std::string velocity_attribute = "";