12#include <Alembic/Abc/ICompoundProperty.h>
13#include <Alembic/Abc/ISampleSelector.h>
14#include <Alembic/Abc/OCompoundProperty.h>
15#include <Alembic/Abc/TypedArraySample.h>
16#include <Alembic/AbcCoreAbstract/PropertyHeader.h>
17#include <Alembic/AbcGeom/GeometryScope.h>
18#include <Alembic/AbcGeom/IGeomParam.h>
19#include <Alembic/AbcGeom/OGeomParam.h>
40using Alembic::AbcGeom::kFacevaryingScope;
41using Alembic::AbcGeom::kVaryingScope;
42using Alembic::AbcGeom::kVertexScope;
44using Alembic::Abc::C4fArraySample;
45using Alembic::Abc::UInt32ArraySample;
46using Alembic::Abc::V2fArraySample;
48using Alembic::AbcGeom::OC4fGeomParam;
49using Alembic::AbcGeom::OV2fGeomParam;
50using Alembic::AbcGeom::OV3fGeomParam;
58 std::vector<Imath::V2f> &uvs,
59 std::vector<uint32_t> &uvidx,
62 const float2 *mloopuv_array =
static_cast<const float2 *
>(cd_data);
77 for (
const int i : faces.index_range()) {
79 const float2 *loopuv = mloopuv_array + face.start() + face.size();
81 for (
int j = 0; j < face.size(); j++,
count++) {
85 uvs[
count][0] = (*loopuv)[0];
86 uvs[
count][1] = (*loopuv)[1];
92 std::vector<std::vector<uint32_t>> idx_map(config.
totvert);
95 for (
const int i : faces.index_range()) {
97 int *face_verts = corner_verts + face.
start() + face.size();
98 const float2 *loopuv = mloopuv_array + face.start() + face.size();
100 for (
int j = 0; j < face.size(); j++) {
104 Imath::V2f uv((*loopuv)[0], (*loopuv)[1]);
105 bool found_same =
false;
108 for (
uint32_t uv_idx : idx_map[*face_verts]) {
109 if (uvs[uv_idx] == uv) {
111 uvidx.push_back(uv_idx);
119 idx_map[*face_verts].push_back(uv_idx);
120 uvidx.push_back(uv_idx);
132 if (active_uvlayer < 0) {
154 std::vector<Imath::V2f> uvs;
156 get_uvs(config, uvs, indices, data);
158 if (indices.empty() || uvs.empty()) {
162 std::string uv_map_name(name);
163 OV2fGeomParam param = config.
abc_uv_maps[uv_map_name];
165 if (!param.valid()) {
166 param = OV2fGeomParam(prop, name,
true, kFacevaryingScope, 1);
168 OV2fGeomParam::Sample
sample(V2fArraySample(&uvs.front(), uvs.size()),
169 UInt32ArraySample(&indices.front(), indices.size()),
178 std::vector<Imath::C4f> &buffer,
179 std::vector<uint32_t> &uvidx,
182 const float cscale = 1.0f / 255.0f;
184 const MCol *cfaces =
static_cast<const MCol *
>(cd_data);
186 buffer.reserve(config.
totvert);
191 for (
const int i : faces.index_range()) {
193 const MCol *cface = &cfaces[face.start() + face.size()];
195 for (
int j = 0; j < face.size(); j++) {
198 col[0] = cface->
a * cscale;
199 col[1] = cface->
r * cscale;
200 col[2] = cface->
g * cscale;
201 col[3] = cface->
b * cscale;
203 buffer.push_back(
col);
204 uvidx.push_back(buffer.size() - 1);
219 std::vector<Imath::C4f> buffer;
221 get_cols(config, buffer, indices, data);
223 if (indices.empty() || buffer.empty()) {
227 std::string vcol_name(name);
230 if (!param.valid()) {
231 param = OC4fGeomParam(prop, name,
true, kFacevaryingScope, 1);
234 OC4fGeomParam::Sample
sample(C4fArraySample(&buffer.front(), buffer.size()),
235 UInt32ArraySample(&indices.front(), indices.size()),
248 if (customdata ==
nullptr) {
252 const float(*orcodata)[3] =
static_cast<const float(*)[3]
>(customdata);
255 std::vector<Imath::V3f> coords(config.
totvert);
257 for (
int vertex_idx = 0; vertex_idx < config.
totvert; vertex_idx++) {
259 coords[vertex_idx].setValue(orco_yup[0], orco_yup[1], orco_yup[2]);
265 mesh,
reinterpret_cast<float(*)[3]
>(coords.data()), mesh->verts_num,
true);
272 OV3fGeomParam::Sample
sample(coords, kVertexScope);
290 for (
int i = 0; i < tot_layers; i++) {
296 if (i == active_layer) {
300 write_uv(prop, config, cd_data, name);
310using Alembic::Abc::C3fArraySamplePtr;
311using Alembic::Abc::C4fArraySamplePtr;
312using Alembic::Abc::PropertyHeader;
313using Alembic::Abc::UInt32ArraySamplePtr;
315using Alembic::AbcGeom::IC3fGeomParam;
316using Alembic::AbcGeom::IC4fGeomParam;
317using Alembic::AbcGeom::IV2fGeomParam;
318using Alembic::AbcGeom::IV3fGeomParam;
323 const Alembic::AbcGeom::V2fArraySamplePtr &uvs,
324 const UInt32ArraySamplePtr &indices)
330 uint uv_index, loop_index, rev_loop_index;
335 for (
const int i : faces.index_range()) {
337 uint rev_loop_offset = face.
start() + face.size() - 1;
339 for (
int f = 0; f < face.size(); f++) {
340 rev_loop_index = rev_loop_offset - f;
341 loop_index = do_uvs_per_loop ? face.start() + f : corner_verts[rev_loop_index];
342 uv_index = (*indices)[loop_index];
343 const Imath::V2f &uv = (*uvs)[uv_index];
345 float2 &loopuv = mloopuvs[rev_loop_index];
353 const size_t array_size,
354 const std::string &iobject_full_name,
355 const PropertyHeader &prop_header,
356 bool &r_is_out_of_bounds,
357 bool &r_bounds_warning_given)
359 if (color_index < array_size) {
363 if (!r_bounds_warning_given) {
364 std::cerr <<
"Alembic: color index out of bounds "
365 "reading face colors for object "
366 << iobject_full_name <<
", property " << prop_header.getName() << std::endl;
367 r_bounds_warning_given =
true;
369 r_is_out_of_bounds =
true;
374 const ICompoundProperty &arbGeomParams,
375 const PropertyHeader &prop_header,
377 const Alembic::Abc::ISampleSelector &iss)
379 C3fArraySamplePtr c3f_ptr = C3fArraySamplePtr();
380 C4fArraySamplePtr c4f_ptr = C4fArraySamplePtr();
381 Alembic::Abc::UInt32ArraySamplePtr
indices;
386 if (IC3fGeomParam::matches(prop_header)) {
387 IC3fGeomParam color_param(arbGeomParams, prop_header.getName());
388 IC3fGeomParam::Sample
sample;
391 color_param.getIndexed(
sample, iss);
392 is_facevarying =
sample.getScope() == kFacevaryingScope &&
395 c3f_ptr =
sample.getVals();
396 indices =
sample.getIndices();
399 else if (IC4fGeomParam::matches(prop_header)) {
400 IC4fGeomParam color_param(arbGeomParams, prop_header.getName());
401 IC4fGeomParam::Sample
sample;
404 color_param.getIndexed(
sample, iss);
405 is_facevarying =
sample.getScope() == kFacevaryingScope &&
408 c4f_ptr =
sample.getVals();
409 indices =
sample.getIndices();
421 MCol *cfaces =
static_cast<MCol *
>(cd_data);
425 size_t face_index = 0;
427 bool bounds_warning_given =
false;
433 bool use_dual_indexing = is_facevarying && indices->size() > 0;
435 for (
const int i : faces.index_range()) {
437 MCol *cface = &cfaces[face.start() + face.size()];
438 const int *face_verts = &corner_verts[face.start() + face.size()];
440 for (
int j = 0; j < face.size(); j++, face_index++) {
444 color_index = is_facevarying ? face_index : *face_verts;
445 if (use_dual_indexing) {
446 color_index = (*indices)[color_index];
449 bool is_mcols_out_of_bounds =
false;
454 is_mcols_out_of_bounds,
455 bounds_warning_given);
456 if (is_mcols_out_of_bounds) {
459 const Imath::C3f &color = (*c3f_ptr)[color_index];
466 bool is_mcols_out_of_bounds =
false;
471 is_mcols_out_of_bounds,
472 bounds_warning_given);
473 if (is_mcols_out_of_bounds) {
476 const Imath::C4f &color = (*c4f_ptr)[color_index];
487 const PropertyHeader &prop_header,
489 const Alembic::Abc::ISampleSelector &iss)
491 IV2fGeomParam uv_param(prop, prop_header.getName());
493 if (!uv_param.isIndexed()) {
497 IV2fGeomParam::Sample
sample;
498 uv_param.getIndexed(
sample, iss);
500 UInt32ArraySamplePtr uvs_indices =
sample.getIndices();
511 read_uvs(config, cd_data, uv_scope,
sample.getVals(), uvs_indices);
516 const float velocity_scale)
518 const int num_velocity_vectors =
int(velocities->size());
530 for (
int i = 0; i < num_velocity_vectors; i++) {
531 const Imath::V3f &vel_in = (*velocities)[i];
539 const Alembic::Abc::ISampleSelector &iss)
547 if (!param.valid() || param.isIndexed()) {
551 if (param.getScope() != kVertexScope) {
556 IV3fGeomParam::Sample
sample = param.getExpandedValue(iss);
557 Alembic::AbcGeom::V3fArraySamplePtr abc_orco =
sample.getVals();
558 const size_t totvert = abc_orco.get()->size();
561 if (totvert != mesh->verts_num) {
575 float(*orcodata)[3] =
static_cast<float(*)[3]
>(cd_data);
576 for (
int vertex_idx = 0; vertex_idx < totvert; ++vertex_idx) {
577 const Imath::V3f &abc_coords = (*abc_orco)[vertex_idx];
587 const ICompoundProperty &prop,
589 const Alembic::Abc::ISampleSelector &iss)
597 const size_t num_props = prop.getNumProperties();
599 for (
size_t i = 0; i < num_props; i++) {
600 const Alembic::Abc::PropertyHeader &prop_header = prop.getPropertyHeader(i);
603 if (IV2fGeomParam::matches(prop_header) && Alembic::AbcGeom::isUV(prop_header)) {
613 if (IC3fGeomParam::matches(prop_header) || IC4fGeomParam::matches(prop_header)) {
622 const Alembic::AbcGeom::UInt32ArraySamplePtr &indices)
624 if (scope == kFacevaryingScope && indices->size() == config.
totloop) {
631 if (
ELEM(scope, kVaryingScope, kVertexScope) && indices->size() == config.
totvert) {
struct CustomDataLayer * BKE_attribute_new(AttributeOwner &owner, const char *name, eCustomDataType type, blender::bke::AttrDomain domain, struct ReportList *reports)
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer_n(const CustomData *data, eCustomDataType type, int n)
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
const char * CustomData_get_layer_name(const CustomData *data, eCustomDataType type, int n)
int CustomData_get_active_layer(const CustomData *data, eCustomDataType type)
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
int CustomData_number_of_layers(const CustomData *data, eCustomDataType type)
void BKE_mesh_orco_verts_transform(Mesh *mesh, blender::MutableSpan< blender::float3 > orco, bool invert)
MINLINE void mul_v3_fl(float r[3], float f)
static AttributeOwner from_id(ID *id)
constexpr int64_t start() const
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
#define unit_float_to_uchar_clamp(val)
AbcUvScope get_uv_scope(const Alembic::AbcGeom::GeometryScope scope, const CDStreamConfig &config, const Alembic::AbcGeom::UInt32ArraySamplePtr &indices)
BLI_INLINE void copy_yup_from_zup(float yup[3], const float zup[3])
const char * get_uv_sample(UVSample &sample, const CDStreamConfig &config, CustomData *data)
static void write_uv(const OCompoundProperty &prop, CDStreamConfig &config, const void *data, const char *name)
void read_velocity(const V3fArraySamplePtr &velocities, const CDStreamConfig &config, const float velocity_scale)
static void read_custom_data_mcols(const std::string &iobject_full_name, const ICompoundProperty &arbGeomParams, const PropertyHeader &prop_header, const CDStreamConfig &config, const Alembic::Abc::ISampleSelector &iss)
void write_custom_data(const OCompoundProperty &prop, CDStreamConfig &config, CustomData *data, int data_type)
static void write_mcol(const OCompoundProperty &prop, CDStreamConfig &config, const void *data, const char *name)
BLI_INLINE void copy_zup_from_yup(float zup[3], const float yup[3])
void read_custom_data(const std::string &iobject_full_name, const ICompoundProperty &prop, const CDStreamConfig &config, const Alembic::Abc::ISampleSelector &iss)
static void get_uvs(const CDStreamConfig &config, std::vector< Imath::V2f > &uvs, std::vector< uint32_t > &uvidx, const void *cd_data)
static const std::string propNameOriginalCoordinates("Pref")
static void read_custom_data_uvs(const ICompoundProperty &prop, const PropertyHeader &prop_header, const CDStreamConfig &config, const Alembic::Abc::ISampleSelector &iss)
void read_generated_coordinates(const ICompoundProperty &prop, const CDStreamConfig &config, const Alembic::Abc::ISampleSelector &iss)
static size_t mcols_out_of_bounds_check(const size_t color_index, const size_t array_size, const std::string &iobject_full_name, const PropertyHeader &prop_header, bool &r_is_out_of_bounds, bool &r_bounds_warning_given)
void write_generated_coordinates(const OCompoundProperty &prop, CDStreamConfig &config)
static void get_cols(const CDStreamConfig &config, std::vector< Imath::C4f > &buffer, std::vector< uint32_t > &uvidx, const void *cd_data)
static void read_uvs(const CDStreamConfig &config, void *data, const AbcUvScope uv_scope, const Alembic::AbcGeom::V2fArraySamplePtr &uvs, const UInt32ArraySamplePtr &indices)
std::map< std::string, Alembic::AbcGeom::OC4fGeomParam > abc_vertex_colors
void *(* add_customdata_cb)(Mesh *mesh, const char *name, int data_type)
Alembic::AbcGeom::OV3fGeomParam abc_orco
std::map< std::string, Alembic::AbcGeom::OV2fGeomParam > abc_uv_maps