diff options
author | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-03-13 21:50:35 +0300 |
---|---|---|
committer | Kévin Dietrich <kevin.dietrich@mailoo.org> | 2022-03-13 21:50:35 +0300 |
commit | c0ef2a5cf56590c7b01502d8d6c5a18067afc028 (patch) | |
tree | f04018116f9c412cea30bb6cc14c6a0357568e33 | |
parent | 5a0efc9c8b5ad991109c97d52d476d8c071a78ac (diff) |
Start replacing write_custom_data with the attribute exporter.temp-abc-features
-rw-r--r-- | source/blender/io/alembic/exporter/abc_writer_mesh.cc | 32 | ||||
-rw-r--r-- | source/blender/io/alembic/exporter/abc_writer_mesh.h | 4 | ||||
-rw-r--r-- | source/blender/io/alembic/intern/abc_customdata.cc | 383 | ||||
-rw-r--r-- | source/blender/io/alembic/intern/abc_customdata.h | 85 |
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 ∝ + 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 = ""; |