16using namespace Alembic::AbcGeom;
20static float3 make_float3_from_yup(
const V3f &
v)
26static set<chrono_t> get_relevant_sample_times(AlembicProcedural *proc,
27 const TimeSampling &time_sampling,
28 const size_t num_samples)
32 if (num_samples < 2) {
40 if (proc->get_use_prefetch()) {
42 start_frame =
static_cast<double>(proc->get_start_frame());
43 end_frame =
static_cast<double>(proc->get_end_frame());
47 start_frame =
static_cast<double>(proc->get_frame());
48 end_frame = start_frame;
51 const double frame_rate =
static_cast<double>(proc->get_frame_rate());
52 const double frame_offset = proc->get_frame_offset();
53 const double start_time = (start_frame - frame_offset) / frame_rate;
54 const double end_time = (end_frame - frame_offset + 1) / frame_rate;
56 const size_t start_index = time_sampling.getFloorIndex(start_time, num_samples).first;
57 const size_t end_index = time_sampling.getCeilIndex(end_time, num_samples).first;
59 for (
size_t i = start_index;
i < end_index; ++
i) {
60 result.insert(time_sampling.getSampleTime(
i));
69template<
typename Params,
typename DataReadingFunc>
70static void read_data_loop(AlembicProcedural *proc,
71 CachedData &cached_data,
73 DataReadingFunc &&func,
76 const std::set<chrono_t> times = get_relevant_sample_times(
79 cached_data.set_time_sampling(*
params.time_sampling);
81 for (
const chrono_t time : times) {
86 func(cached_data,
params, time);
94static void compute_vertex_normals(CachedData &cache,
const double current_time)
96 if (cache.vertices.size() == 0) {
100 CachedData::CachedAttribute &attr_normal = cache.add_attribute(
101 ustring(
"N"), cache.vertices.get_time_sampling());
104 attr_normal.type_desc = TypeNormal;
107 cache.vertices.data_for_time_no_check(current_time).get_data_or_null();
109 cache.triangles.data_for_time_no_check(current_time).get_data_or_null();
111 if (!vertices || !triangles) {
112 attr_normal.data.add_no_data(current_time);
117 float3 *attr_ptr =
reinterpret_cast<float3 *
>(attr_data.data());
120 for (
size_t t = 0; t < triangles->
size(); ++t) {
121 const int3 tri_int3 = triangles->
data()[t];
123 tri.
v[0] = tri_int3[0];
124 tri.
v[1] = tri_int3[1];
125 tri.
v[2] = tri_int3[2];
129 for (
int v = 0;
v < 3; ++
v) {
130 attr_ptr[tri_int3[
v]] += tri_N;
134 for (
size_t v = 0;
v < vertices->
size(); ++
v) {
138 attr_normal.data.add_data(attr_data, current_time);
141static void add_normals(
const Int32ArraySamplePtr face_indices,
144 CachedData &cached_data)
147 case kFacevaryingScope: {
148 const ISampleSelector iss = ISampleSelector(time);
149 const IN3fGeomParam::Sample
sample =
normals.getExpandedValue(iss);
155 CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(
normals.getName()),
160 cached_data.vertices.data_for_time_no_check(time).get_data_or_null();
171 const int *face_indices_array = face_indices->get();
172 const N3fArraySamplePtr values =
sample.getVals();
174 for (
size_t i = 0;
i < face_indices->size(); ++
i) {
175 const int point_index = face_indices_array[
i];
176 data_float3[point_index] = make_float3_from_yup(values->get()[
i]);
179 attr.data.add_data(
data, time);
184 const ISampleSelector iss = ISampleSelector(time);
185 const IN3fGeomParam::Sample
sample =
normals.getExpandedValue(iss);
191 CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(
normals.getName()),
196 cached_data.vertices.data_for_time_no_check(time).get_data_or_null();
207 const Imath::V3f *values =
sample.getVals()->get();
209 for (
size_t i = 0;
i < vertices->
size(); ++
i) {
210 data_float3[
i] = make_float3_from_yup(values[
i]);
213 attr.data.add_data(
data, time);
223static void add_positions(
const P3fArraySamplePtr positions,
225 CachedData &cached_data)
232 vertices.
reserve(positions->size());
234 for (
size_t i = 0;
i < positions->size();
i++) {
235 const V3f f = positions->get()[
i];
239 cached_data.vertices.add_data(vertices, time);
242static void add_triangles(
const Int32ArraySamplePtr face_counts,
243 const Int32ArraySamplePtr face_indices,
245 CachedData &cached_data,
248 if (!face_counts || !face_indices) {
252 const size_t num_faces = face_counts->size();
253 const int *face_counts_array = face_counts->get();
254 const int *face_indices_array = face_indices->get();
256 size_t num_triangles = 0;
257 for (
size_t i = 0;
i < face_counts->size();
i++) {
258 num_triangles += face_counts_array[
i] - 2;
265 triangles.
reserve(num_triangles);
266 uv_loops.
reserve(num_triangles * 3);
267 int index_offset = 0;
269 for (
size_t i = 0;
i < num_faces;
i++) {
270 int current_shader = 0;
272 if (!polygon_to_shader.
empty()) {
273 current_shader = polygon_to_shader[
i];
276 for (
int j = 0; j < face_counts_array[
i] - 2; j++) {
277 const int v0 = face_indices_array[index_offset];
278 const int v1 = face_indices_array[index_offset + j + 1];
279 const int v2 = face_indices_array[index_offset + j + 2];
290 index_offset += face_counts_array[
i];
293 cached_data.triangles.add_data(triangles, time);
294 cached_data.uv_loops.add_data(uv_loops, time);
295 cached_data.shader.add_data(shader, time);
298static array<int> compute_polygon_to_shader_map(
299 const Int32ArraySamplePtr &face_counts,
301 ISampleSelector sample_sel)
303 if (face_set_shader_index.empty()) {
311 if (face_counts->size() == 0) {
315 const array<int> polygon_to_shader(face_counts->size());
317 for (
const FaceSetShaderIndexPair &pair : face_set_shader_index) {
318 const IFaceSet &face_set = pair.face_set;
319 const IFaceSetSchema face_schem = face_set.getSchema();
320 const IFaceSetSchema::Sample face_sample = face_schem.getValue(sample_sel);
321 const Int32ArraySamplePtr group_faces = face_sample.getFaces();
322 const size_t num_group_faces = group_faces->size();
324 for (
size_t l = 0;
l < num_group_faces;
l++) {
325 const size_t pos = (*group_faces)[
l];
327 if (
pos >= polygon_to_shader.
size()) {
331 polygon_to_shader[
pos] = pair.shader_index;
335 return polygon_to_shader;
338static void read_poly_mesh_geometry(CachedData &cached_data,
339 const PolyMeshSchemaData &
data,
342 const ISampleSelector iss = ISampleSelector(time);
344 add_positions(
data.positions.getValue(iss), time, cached_data);
346 const Int32ArraySamplePtr face_counts =
data.face_counts.getValue(iss);
347 const Int32ArraySamplePtr face_indices =
data.face_indices.getValue(iss);
350 if (
data.topology_variance != kHomogeneousTopology || cached_data.triangles.size() == 0) {
351 bool do_triangles =
true;
354 if (cached_data.triangles.size() > 0) {
355 const ArraySample::Key key = face_indices->getKey();
357 if (key == cached_data.triangles.key1) {
358 do_triangles =
false;
361 cached_data.triangles.key1 = key;
365 const array<int> polygon_to_shader = compute_polygon_to_shader_map(
366 face_counts,
data.shader_face_sets, iss);
367 add_triangles(face_counts, face_indices, time, cached_data, polygon_to_shader);
370 cached_data.triangles.reuse_data_for_last_time(time);
371 cached_data.uv_loops.reuse_data_for_last_time(time);
372 cached_data.shader.reuse_data_for_last_time(time);
376 if (
data.topology_variance != kHomogeneousTopology && cached_data.triangles.size() == 1) {
377 cached_data.triangles.key1 = face_indices->getKey();
381 if (
data.normals.valid()) {
382 add_normals(face_indices,
data.normals, time, cached_data);
385 compute_vertex_normals(cached_data, time);
389void read_geometry_data(AlembicProcedural *proc,
390 CachedData &cached_data,
391 const PolyMeshSchemaData &
data,
394 read_data_loop(proc, cached_data,
data, read_poly_mesh_geometry,
progress);
399static void add_subd_polygons(CachedData &cached_data,
const SubDSchemaData &
data, chrono_t time)
401 const ISampleSelector iss = ISampleSelector(time);
403 const Int32ArraySamplePtr face_counts =
data.face_counts.getValue(iss);
404 const Int32ArraySamplePtr face_indices =
data.face_indices.getValue(iss);
414 const size_t num_faces = face_counts->
size();
415 const int *face_counts_array = face_counts->get();
416 const int *face_indices_array = face_indices->get();
419 for (
size_t i = 0;
i < face_counts->size();
i++) {
420 num_corners += face_counts_array[
i];
423 subd_start_corner.
reserve(num_faces);
424 subd_num_corners.
reserve(num_faces);
425 subd_smooth.
reserve(num_faces);
426 subd_ptex_offset.
reserve(num_faces);
428 subd_face_corners.
reserve(num_corners);
431 int start_corner = 0;
432 int current_shader = 0;
435 const array<int> polygon_to_shader = compute_polygon_to_shader_map(
436 face_counts,
data.shader_face_sets, iss);
438 for (
size_t i = 0;
i < face_counts->size();
i++) {
439 num_corners = face_counts_array[
i];
441 if (!polygon_to_shader.
empty()) {
442 current_shader = polygon_to_shader[
i];
448 for (
int j = 0; j < num_corners; ++j) {
457 ptex_offset += (num_corners == 4 ? 1 : num_corners);
459 start_corner += num_corners;
462 cached_data.shader.add_data(shader, time);
463 cached_data.subd_start_corner.add_data(subd_start_corner, time);
464 cached_data.subd_num_corners.add_data(subd_num_corners, time);
465 cached_data.subd_smooth.add_data(subd_smooth, time);
466 cached_data.subd_ptex_offset.add_data(subd_ptex_offset, time);
467 cached_data.subd_face_corners.add_data(subd_face_corners, time);
468 cached_data.uv_loops.add_data(uv_loops, time);
471static void add_subd_edge_creases(CachedData &cached_data,
472 const SubDSchemaData &
data,
475 if (!(
data.crease_indices.valid() &&
data.crease_lengths.valid() &&
476 data.crease_sharpnesses.valid()))
481 const ISampleSelector iss = ISampleSelector(time);
483 const Int32ArraySamplePtr creases_length =
data.crease_lengths.getValue(iss);
484 const Int32ArraySamplePtr creases_indices =
data.crease_indices.getValue(iss);
485 const FloatArraySamplePtr creases_sharpnesses =
data.crease_sharpnesses.getValue(iss);
487 if (creases_length && creases_indices && creases_sharpnesses) {
491 creases_edge.
reserve(creases_sharpnesses->size() * 2);
492 creases_weight.
reserve(creases_sharpnesses->size());
494 int length_offset = 0;
495 int weight_offset = 0;
496 for (
size_t c = 0; c < creases_length->size(); ++c) {
497 const int crease_length = creases_length->get()[c];
499 for (
size_t j = 0; j < crease_length - 1; ++j) {
505 length_offset += crease_length;
508 cached_data.subd_creases_edge.add_data(creases_edge, time);
509 cached_data.subd_creases_weight.add_data(creases_weight, time);
513static void add_subd_vertex_creases(CachedData &cached_data,
514 const SubDSchemaData &
data,
517 if (!(
data.corner_indices.valid() &&
data.crease_sharpnesses.valid())) {
521 const ISampleSelector iss = ISampleSelector(time);
522 const Int32ArraySamplePtr creases_indices =
data.crease_indices.getValue(iss);
523 const FloatArraySamplePtr creases_sharpnesses =
data.crease_sharpnesses.getValue(iss);
525 if (!(creases_indices && creases_sharpnesses) ||
526 creases_indices->size() != creases_sharpnesses->size())
532 sharpnesses.
reserve(creases_indices->size());
534 indices.reserve(creases_indices->size());
536 for (
size_t i = 0;
i < creases_indices->size();
i++) {
537 indices.push_back_reserved((*creases_indices)[
i]);
541 cached_data.subd_vertex_crease_indices.add_data(
indices, time);
542 cached_data.subd_vertex_crease_weights.add_data(sharpnesses, time);
545static void read_subd_geometry(CachedData &cached_data,
const SubDSchemaData &
data, chrono_t time)
547 const ISampleSelector iss = ISampleSelector(time);
549 add_positions(
data.positions.getValue(iss), time, cached_data);
551 if (
data.topology_variance != kHomogeneousTopology || cached_data.shader.size() == 0) {
552 add_subd_polygons(cached_data,
data, time);
553 add_subd_edge_creases(cached_data,
data, time);
554 add_subd_vertex_creases(cached_data,
data, time);
558void read_geometry_data(AlembicProcedural *proc,
559 CachedData &cached_data,
560 const SubDSchemaData &
data,
563 read_data_loop(proc, cached_data,
data, read_subd_geometry,
progress);
568static void read_curves_data(CachedData &cached_data,
const CurvesSchemaData &
data, chrono_t time)
570 const ISampleSelector iss = ISampleSelector(time);
572 const Int32ArraySamplePtr curves_num_vertices =
data.num_vertices.getValue(iss);
573 const P3fArraySamplePtr position =
data.positions.getValue(iss);
575 FloatArraySamplePtr radiuses;
577 if (
data.widths.valid()) {
578 const IFloatGeomParam::Sample wsample =
data.widths.getExpandedValue(iss);
579 radiuses = wsample.getVals();
582 const bool do_radius = (radiuses !=
nullptr) && (radiuses->size() > 1);
583 float radius = (radiuses && radiuses->size() == 1) ? (*radiuses)[0] :
data.default_radius;
590 const bool is_homogeneous =
data.topology_variance == kHomogeneousTopology;
592 curve_keys.
reserve(position->size());
593 curve_radius.
reserve(position->size());
594 curve_first_key.
reserve(curves_num_vertices->size());
595 curve_shader.
reserve(curves_num_vertices->size());
598 for (
size_t i = 0;
i < curves_num_vertices->size();
i++) {
599 const int num_vertices = curves_num_vertices->get()[
i];
601 for (
int j = 0; j < num_vertices; j++) {
602 const V3f &f = position->get()[offset + j];
607 radius = (*radiuses)[offset + j];
613 if (!is_homogeneous || cached_data.curve_first_key.size() == 0) {
618 offset += num_vertices;
621 cached_data.curve_keys.add_data(curve_keys, time);
622 cached_data.curve_radius.add_data(curve_radius, time);
624 if (!is_homogeneous || cached_data.curve_first_key.size() == 0) {
625 cached_data.curve_first_key.add_data(curve_first_key, time);
626 cached_data.curve_shader.add_data(curve_shader, time);
630void read_geometry_data(AlembicProcedural *proc,
631 CachedData &cached_data,
632 const CurvesSchemaData &
data,
635 read_data_loop(proc, cached_data,
data, read_curves_data,
progress);
640static void read_points_data(CachedData &cached_data,
const PointsSchemaData &
data, chrono_t time)
642 const ISampleSelector iss = ISampleSelector(time);
644 const P3fArraySamplePtr position =
data.positions.getValue(iss);
645 FloatArraySamplePtr radiuses;
650 a_positions.
reserve(position->size());
651 a_radius.
reserve(position->size());
652 a_shader.
reserve(position->size());
654 if (
data.radiuses.valid()) {
655 const IFloatGeomParam::Sample wsample =
data.radiuses.getExpandedValue(iss);
656 radiuses = wsample.getVals();
659 const bool do_radius = (radiuses !=
nullptr) && (radiuses->size() > 1);
660 float radius = (radiuses && radiuses->size() == 1) ? (*radiuses)[0] :
data.default_radius;
662 const int offset = 0;
663 for (
size_t i = 0;
i < position->size();
i++) {
664 const V3f &f = position->get()[offset +
i];
668 radius = (*radiuses)[offset +
i];
675 cached_data.points.add_data(a_positions, time);
676 cached_data.radiuses.add_data(a_radius, time);
677 cached_data.points_shader.add_data(a_shader, time);
680void read_geometry_data(AlembicProcedural *proc,
681 CachedData &cached_data,
682 const PointsSchemaData &
data,
685 read_data_loop(proc, cached_data,
data, read_points_data,
progress);
692template<
typename T>
struct value_type_converter {
693 using cycles_type = float;
695 static constexpr TypeDesc type_desc = TypeDesc::FLOAT;
696 static constexpr const char *type_name =
"float (default)";
700 return static_cast<float>(value);
704template<>
struct value_type_converter<Imath::V2f> {
705 using cycles_type =
float2;
706 static constexpr TypeDesc type_desc = TypeFloat2;
707 static constexpr const char *type_name =
"float2";
715template<>
struct value_type_converter<Imath::V3f> {
716 using cycles_type =
float3;
717 static constexpr TypeDesc type_desc = TypeVector;
718 static constexpr const char *type_name =
"float3";
722 return make_float3_from_yup(value);
726template<>
struct value_type_converter<Imath::C3f> {
727 using cycles_type =
uchar4;
729 static constexpr const char *type_name =
"rgb";
737template<>
struct value_type_converter<Imath::C4f> {
738 using cycles_type =
uchar4;
740 static constexpr const char *type_name =
"rgba";
749template<
typename TRAIT>
750static void process_attribute(CachedData &cache,
751 CachedData::CachedAttribute &attribute,
753 const typename ITypedGeomParam<TRAIT>::Sample &
sample,
756 using abc_type =
typename TRAIT::value_type;
757 using cycles_type =
typename value_type_converter<abc_type>::cycles_type;
759 const TypedArraySample<TRAIT> &values = *
sample.getVals();
765 cache.vertices.data_for_time_no_check(time).get_data_or_null();
768 attribute.data.add_no_data(time);
772 if (vertices->
size() != values.size()) {
773 attribute.data.add_no_data(time);
779 cycles_type *pod_typed_data =
reinterpret_cast<cycles_type *
>(
data.data());
781 for (
size_t i = 0;
i < values.size(); ++
i) {
782 *pod_typed_data++ = value_type_converter<abc_type>::convert_value(values[
i]);
785 attribute.data.add_data(
data, time);
788 case kVaryingScope: {
790 cache.triangles.data_for_time_no_check(time).get_data_or_null();
793 attribute.data.add_no_data(time);
799 cycles_type *pod_typed_data =
reinterpret_cast<cycles_type *
>(
data.data());
801 for (
const int3 &tri : *triangles) {
802 *pod_typed_data++ = value_type_converter<abc_type>::convert_value(values[tri.x]);
803 *pod_typed_data++ = value_type_converter<abc_type>::convert_value(values[tri.y]);
804 *pod_typed_data++ = value_type_converter<abc_type>::convert_value(values[tri.z]);
807 attribute.data.add_data(
data, time);
818static void process_uvs(CachedData &cache,
819 CachedData::CachedAttribute &attribute,
821 const IV2fGeomParam::Sample &
sample,
824 if (scope != kFacevaryingScope && scope != kVaryingScope && scope != kVertexScope) {
828 const array<int> *uv_loops = cache.uv_loops.data_for_time_no_check(time).get_data_or_null();
831 if (!uv_loops && scope == kFacevaryingScope) {
835 const array<int3> *triangles = cache.triangles.data_for_time_no_check(time).get_data_or_null();
837 cache.subd_face_corners.data_for_time_no_check(time).get_data_or_null();
853 const V2f *values =
sample.getVals()->get();
855 if (scope == kFacevaryingScope) {
856 for (
const int uv_loop_index : *uv_loops) {
858 *data_float2++ =
make_float2(values[index][0], values[index][1]);
861 else if (scope == kVaryingScope || scope == kVertexScope) {
863 for (
size_t i = 0;
i < triangles->
size();
i++) {
864 const int3 t = (*triangles)[
i];
865 *data_float2++ =
make_float2(values[t.
x][0], values[t.
x][1]);
866 *data_float2++ =
make_float2(values[t.
y][0], values[t.
y][1]);
867 *data_float2++ =
make_float2(values[t.
z][0], values[t.
z][1]);
871 for (
size_t i = 0;
i <
corners->size();
i++) {
872 const int c = (*corners)[
i];
873 *data_float2++ =
make_float2(values[c][0], values[c][1]);
878 attribute.data.add_data(
data, time);
883template<
typename TRAIT>
884using process_callback_type = void (*)(CachedData &,
885 CachedData::CachedAttribute &,
887 const typename ITypedGeomParam<TRAIT>::Sample &,
893template<
typename TRAIT>
894static void read_attribute_loop(AlembicProcedural *proc,
896 const ITypedGeomParam<TRAIT> ¶m,
897 process_callback_type<TRAIT> callback,
901 const std::set<chrono_t> times = get_relevant_sample_times(
902 proc, *param.getTimeSampling(), param.getNumSamples());
908 std::string name = param.getName();
911 const std::string uv_source_name = Alembic::Abc::GetSourceName(param.getMetaData());
916 if (!uv_source_name.empty()) {
917 name = uv_source_name;
921 CachedData::CachedAttribute &attribute = cache.add_attribute(ustring(name),
922 *param.getTimeSampling());
924 using abc_type =
typename TRAIT::value_type;
926 attribute.data.set_time_sampling(*param.getTimeSampling());
928 attribute.type_desc = value_type_converter<abc_type>::type_desc;
930 if (attribute.type_desc ==
TypeRGBA) {
934 if (param.getScope() == kVaryingScope || param.getScope() == kFacevaryingScope) {
942 for (
const chrono_t time : times) {
947 const ISampleSelector iss = ISampleSelector(time);
948 typename ITypedGeomParam<TRAIT>::Sample
sample;
949 param.getIndexed(
sample, iss);
956 attribute.data.add_no_data(time);
961 if (attribute.data.size() != 0) {
962 if (param.isConstant()) {
966 const ArraySample::Key indices_key =
sample.getIndices()->getKey();
967 const ArraySample::Key values_key =
sample.getVals()->getKey();
969 const bool is_same_as_last_time = (indices_key == attribute.data.key1 &&
970 values_key == attribute.data.key2);
972 attribute.data.key1 = indices_key;
973 attribute.data.key2 = values_key;
975 if (is_same_as_last_time) {
976 attribute.data.reuse_data_for_last_time(time);
981 callback(cache, attribute, param.getScope(),
sample, time);
989struct PropHeaderAndParent {
990 const PropertyHeader *prop;
991 ICompoundProperty parent;
998static void parse_requested_attributes_recursive(
const AttributeRequestSet &requested_attributes,
999 const ICompoundProperty &arb_geom_params,
1002 if (!arb_geom_params.valid()) {
1007 const PropertyHeader *property_header = arb_geom_params.getPropertyHeader(req.
name.c_str());
1009 if (!property_header) {
1013 requested_properties.push_back({property_header, arb_geom_params});
1017 for (
size_t i = 0;
i < arb_geom_params.getNumProperties(); ++
i) {
1018 const PropertyHeader &property_header = arb_geom_params.getPropertyHeader(
i);
1020 if (property_header.isCompound()) {
1021 const ICompoundProperty compound_property = ICompoundProperty(arb_geom_params,
1022 property_header.getName());
1023 parse_requested_attributes_recursive(
1024 requested_attributes, compound_property, requested_properties);
1033 const AttributeRequestSet &requested_attributes,
const ICompoundProperty &arb_geom_params)
1036 parse_requested_attributes_recursive(
1037 requested_attributes, arb_geom_params, requested_properties);
1038 return requested_properties;
1045void read_attributes(AlembicProcedural *proc,
1047 const ICompoundProperty &arb_geom_params,
1048 const IV2fGeomParam &default_uvs_param,
1052 if (default_uvs_param.valid()) {
1058 requested_attributes, arb_geom_params);
1060 for (
const PropHeaderAndParent &prop_and_parent : requested_properties) {
1065 const PropertyHeader *prop = prop_and_parent.prop;
1066 const ICompoundProperty &parent = prop_and_parent.parent;
1068 if (IBoolGeomParam::matches(*prop)) {
1069 const IBoolGeomParam ¶m = IBoolGeomParam(parent, prop->getName());
1070 read_attribute_loop(proc, cache, param, process_attribute<BooleanTPTraits>,
progress);
1072 else if (IInt32GeomParam::matches(*prop)) {
1073 const IInt32GeomParam ¶m = IInt32GeomParam(parent, prop->getName());
1074 read_attribute_loop(proc, cache, param, process_attribute<Int32TPTraits>,
progress);
1076 else if (IFloatGeomParam::matches(*prop)) {
1077 const IFloatGeomParam ¶m = IFloatGeomParam(parent, prop->getName());
1078 read_attribute_loop(proc, cache, param, process_attribute<Float32TPTraits>,
progress);
1080 else if (IV2fGeomParam::matches(*prop)) {
1081 const IV2fGeomParam ¶m = IV2fGeomParam(parent, prop->getName());
1082 if (Alembic::AbcGeom::isUV(*prop)) {
1083 read_attribute_loop(proc, cache, param, process_uvs,
progress);
1086 read_attribute_loop(proc, cache, param, process_attribute<V2fTPTraits>,
progress);
1089 else if (IV3fGeomParam::matches(*prop)) {
1090 const IV3fGeomParam ¶m = IV3fGeomParam(parent, prop->getName());
1091 read_attribute_loop(proc, cache, param, process_attribute<V3fTPTraits>,
progress);
1093 else if (IN3fGeomParam::matches(*prop)) {
1094 const IN3fGeomParam ¶m = IN3fGeomParam(parent, prop->getName());
1095 read_attribute_loop(proc, cache, param, process_attribute<N3fTPTraits>,
progress);
1097 else if (IC3fGeomParam::matches(*prop)) {
1098 const IC3fGeomParam ¶m = IC3fGeomParam(parent, prop->getName());
1099 read_attribute_loop(proc, cache, param, process_attribute<C3fTPTraits>,
progress);
1101 else if (IC4fGeomParam::matches(*prop)) {
1102 const IC4fGeomParam ¶m = IC4fGeomParam(parent, prop->getName());
1103 read_attribute_loop(proc, cache, param, process_attribute<C4fTPTraits>,
progress);
1107 cache.invalidate_last_loaded_time(
true);
BMesh const char void * data
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
vector< AttributeRequest > requests
void push_back_reserved(const T &t)
void reserve(const size_t newcapacity)
void push_back_slow(const T &t)
ccl_device uchar4 color_float_to_byte(const float3 c)
ccl_device uchar4 color_float4_to_uchar4(const float4 c)
#define CCL_NAMESPACE_END
static float normals[][3]
VecBase< float, 2 > float2
VecBase< uchar, 4 > uchar4
VecBase< float, D > normalize(VecOp< float, D >) RET
VecBase< float, 3 > float3
@ ATTR_ELEMENT_CORNER_BYTE
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
std::array< VecBase< T, 3 >, 8 > corners(const Bounds< VecBase< T, 3 > > &bounds)
To convert_value(const From value)
static constexpr TypeDesc TypeRGBA(TypeDesc::FLOAT, TypeDesc::VEC4, TypeDesc::COLOR)
float3 compute_normal(const float3 *verts) const