14using namespace Alembic::AbcGeom;
18static float3 make_float3_from_yup(
const V3f &
v)
24static set<chrono_t> get_relevant_sample_times(AlembicProcedural *proc,
25 const TimeSampling &time_sampling,
30 if (num_samples < 2) {
38 if (proc->get_use_prefetch()) {
40 start_frame =
static_cast<double>(proc->get_start_frame());
41 end_frame =
static_cast<double>(proc->get_end_frame());
45 start_frame =
static_cast<double>(proc->get_frame());
46 end_frame = start_frame;
49 const double frame_rate =
static_cast<double>(proc->get_frame_rate());
50 const double start_time = start_frame / frame_rate;
51 const double end_time = (end_frame + 1) / frame_rate;
53 const size_t start_index = time_sampling.getFloorIndex(start_time, num_samples).first;
54 const size_t end_index = time_sampling.getCeilIndex(end_time, num_samples).first;
56 for (
size_t i = start_index; i < end_index; ++i) {
57 result.insert(time_sampling.getSampleTime(i));
66template<
typename Params,
typename DataReadingFunc>
67static void read_data_loop(AlembicProcedural *proc,
68 CachedData &cached_data,
70 DataReadingFunc &&func,
73 const std::set<chrono_t> times = get_relevant_sample_times(
76 cached_data.set_time_sampling(*
params.time_sampling);
78 for (chrono_t time : times) {
83 func(cached_data,
params, time);
91static void compute_vertex_normals(CachedData &cache,
double current_time)
93 if (cache.vertices.size() == 0) {
97 CachedData::CachedAttribute &attr_normal = cache.add_attribute(
98 ustring(
"N"), cache.vertices.get_time_sampling());
101 attr_normal.type_desc = TypeNormal;
104 cache.vertices.data_for_time_no_check(current_time).get_data_or_null();
106 cache.triangles.data_for_time_no_check(current_time).get_data_or_null();
108 if (!vertices || !triangles) {
109 attr_normal.data.add_no_data(current_time);
114 float3 *attr_ptr =
reinterpret_cast<float3 *
>(attr_data.data());
115 memset(attr_ptr, 0, vertices->
size() *
sizeof(
float3));
117 for (
size_t t = 0; t < triangles->
size(); ++t) {
118 const int3 tri_int3 = triangles->
data()[t];
120 tri.
v[0] = tri_int3[0];
121 tri.
v[1] = tri_int3[1];
122 tri.
v[2] = tri_int3[2];
126 for (
int v = 0;
v < 3; ++
v) {
127 attr_ptr[tri_int3[
v]] += tri_N;
131 for (
size_t v = 0;
v < vertices->
size(); ++
v) {
135 attr_normal.data.add_data(attr_data, current_time);
138static void add_normals(
const Int32ArraySamplePtr face_indices,
141 CachedData &cached_data)
144 case kFacevaryingScope: {
145 const ISampleSelector iss = ISampleSelector(time);
146 const IN3fGeomParam::Sample
sample =
normals.getExpandedValue(iss);
152 CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(
normals.getName()),
157 cached_data.vertices.data_for_time_no_check(time).get_data_or_null();
168 const int *face_indices_array = face_indices->get();
169 const N3fArraySamplePtr values =
sample.getVals();
171 for (
size_t i = 0; i < face_indices->size(); ++i) {
172 int point_index = face_indices_array[i];
173 data_float3[point_index] = make_float3_from_yup(values->get()[i]);
176 attr.data.add_data(
data, time);
181 const ISampleSelector iss = ISampleSelector(time);
182 const IN3fGeomParam::Sample
sample =
normals.getExpandedValue(iss);
188 CachedData::CachedAttribute &attr = cached_data.add_attribute(ustring(
normals.getName()),
193 cached_data.vertices.data_for_time_no_check(time).get_data_or_null();
204 const Imath::V3f *values =
sample.getVals()->get();
206 for (
size_t i = 0; i < vertices->
size(); ++i) {
207 data_float3[i] = make_float3_from_yup(values[i]);
210 attr.data.add_data(
data, time);
220static void add_positions(
const P3fArraySamplePtr positions,
double time, CachedData &cached_data)
227 vertices.
reserve(positions->size());
229 for (
size_t i = 0; i < positions->size(); i++) {
230 V3f f = positions->get()[i];
234 cached_data.vertices.add_data(vertices, time);
237static void add_triangles(
const Int32ArraySamplePtr face_counts,
238 const Int32ArraySamplePtr face_indices,
240 CachedData &cached_data,
243 if (!face_counts || !face_indices) {
247 const size_t num_faces = face_counts->size();
248 const int *face_counts_array = face_counts->get();
249 const int *face_indices_array = face_indices->get();
251 size_t num_triangles = 0;
252 for (
size_t i = 0; i < face_counts->size(); i++) {
253 num_triangles += face_counts_array[i] - 2;
260 triangles.
reserve(num_triangles);
261 uv_loops.
reserve(num_triangles * 3);
262 int index_offset = 0;
264 for (
size_t i = 0; i < num_faces; i++) {
265 int current_shader = 0;
267 if (!polygon_to_shader.
empty()) {
268 current_shader = polygon_to_shader[i];
271 for (
int j = 0; j < face_counts_array[i] - 2; j++) {
272 int v0 = face_indices_array[index_offset];
273 int v1 = face_indices_array[index_offset + j + 1];
274 int v2 = face_indices_array[index_offset + j + 2];
285 index_offset += face_counts_array[i];
288 cached_data.triangles.add_data(triangles, time);
289 cached_data.uv_loops.add_data(uv_loops, time);
290 cached_data.shader.add_data(shader, time);
293static array<int> compute_polygon_to_shader_map(
294 const Int32ArraySamplePtr &face_counts,
296 ISampleSelector sample_sel)
298 if (face_set_shader_index.empty()) {
306 if (face_counts->size() == 0) {
310 array<int> polygon_to_shader(face_counts->size());
312 for (
const FaceSetShaderIndexPair &pair : face_set_shader_index) {
313 const IFaceSet &face_set = pair.face_set;
314 const IFaceSetSchema face_schem = face_set.getSchema();
315 const IFaceSetSchema::Sample face_sample = face_schem.getValue(sample_sel);
316 const Int32ArraySamplePtr group_faces = face_sample.getFaces();
317 const size_t num_group_faces = group_faces->size();
319 for (
size_t l = 0;
l < num_group_faces;
l++) {
320 size_t pos = (*group_faces)[
l];
322 if (
pos >= polygon_to_shader.
size()) {
326 polygon_to_shader[
pos] = pair.shader_index;
330 return polygon_to_shader;
333static void read_poly_mesh_geometry(CachedData &cached_data,
334 const PolyMeshSchemaData &
data,
337 const ISampleSelector iss = ISampleSelector(time);
339 add_positions(
data.positions.getValue(iss), time, cached_data);
341 const Int32ArraySamplePtr face_counts =
data.face_counts.getValue(iss);
342 const Int32ArraySamplePtr face_indices =
data.face_indices.getValue(iss);
345 if (
data.topology_variance != kHomogeneousTopology || cached_data.triangles.size() == 0) {
346 bool do_triangles =
true;
349 if (cached_data.triangles.size() > 0) {
350 const ArraySample::Key key = face_indices->getKey();
352 if (key == cached_data.triangles.key1) {
353 do_triangles =
false;
356 cached_data.triangles.key1 = key;
360 const array<int> polygon_to_shader = compute_polygon_to_shader_map(
361 face_counts,
data.shader_face_sets, iss);
362 add_triangles(face_counts, face_indices, time, cached_data, polygon_to_shader);
365 cached_data.triangles.reuse_data_for_last_time(time);
366 cached_data.uv_loops.reuse_data_for_last_time(time);
367 cached_data.shader.reuse_data_for_last_time(time);
371 if (
data.topology_variance != kHomogeneousTopology && cached_data.triangles.size() == 1) {
372 cached_data.triangles.key1 = face_indices->getKey();
376 if (
data.normals.valid()) {
377 add_normals(face_indices,
data.normals, time, cached_data);
380 compute_vertex_normals(cached_data, time);
384void read_geometry_data(AlembicProcedural *proc,
385 CachedData &cached_data,
386 const PolyMeshSchemaData &
data,
389 read_data_loop(proc, cached_data,
data, read_poly_mesh_geometry, progress);
394static void add_subd_polygons(CachedData &cached_data,
const SubDSchemaData &
data, chrono_t time)
396 const ISampleSelector iss = ISampleSelector(time);
398 const Int32ArraySamplePtr face_counts =
data.face_counts.getValue(iss);
399 const Int32ArraySamplePtr face_indices =
data.face_indices.getValue(iss);
409 const size_t num_faces = face_counts->
size();
410 const int *face_counts_array = face_counts->get();
411 const int *face_indices_array = face_indices->get();
415 for (
size_t i = 0; i < face_counts->size(); i++) {
416 num_ngons += (face_counts_array[i] == 4 ? 0 : 1);
417 num_corners += face_counts_array[i];
420 subd_start_corner.
reserve(num_faces);
421 subd_num_corners.
reserve(num_faces);
422 subd_smooth.
reserve(num_faces);
423 subd_ptex_offset.
reserve(num_faces);
425 subd_face_corners.
reserve(num_corners);
428 int start_corner = 0;
429 int current_shader = 0;
432 const array<int> polygon_to_shader = compute_polygon_to_shader_map(
433 face_counts,
data.shader_face_sets, iss);
435 for (
size_t i = 0; i < face_counts->size(); i++) {
436 num_corners = face_counts_array[i];
438 if (!polygon_to_shader.
empty()) {
439 current_shader = polygon_to_shader[i];
445 for (
int j = 0; j < num_corners; ++j) {
454 ptex_offset += (num_corners == 4 ? 1 : num_corners);
456 start_corner += num_corners;
459 cached_data.shader.add_data(shader, time);
460 cached_data.subd_start_corner.add_data(subd_start_corner, time);
461 cached_data.subd_num_corners.add_data(subd_num_corners, time);
462 cached_data.subd_smooth.add_data(subd_smooth, time);
463 cached_data.subd_ptex_offset.add_data(subd_ptex_offset, time);
464 cached_data.subd_face_corners.add_data(subd_face_corners, time);
465 cached_data.num_ngons.add_data(num_ngons, time);
466 cached_data.uv_loops.add_data(uv_loops, time);
469static void add_subd_edge_creases(CachedData &cached_data,
470 const SubDSchemaData &
data,
473 if (!(
data.crease_indices.valid() &&
data.crease_lengths.valid() &&
474 data.crease_sharpnesses.valid()))
479 const ISampleSelector iss = ISampleSelector(time);
481 const Int32ArraySamplePtr creases_length =
data.crease_lengths.getValue(iss);
482 const Int32ArraySamplePtr creases_indices =
data.crease_indices.getValue(iss);
483 const FloatArraySamplePtr creases_sharpnesses =
data.crease_sharpnesses.getValue(iss);
485 if (creases_length && creases_indices && creases_sharpnesses) {
489 creases_edge.
reserve(creases_sharpnesses->size() * 2);
490 creases_weight.
reserve(creases_sharpnesses->size());
492 int length_offset = 0;
493 int weight_offset = 0;
494 for (
size_t c = 0; c < creases_length->size(); ++c) {
495 const int crease_length = creases_length->get()[c];
497 for (
size_t j = 0; j < crease_length - 1; ++j) {
503 length_offset += crease_length;
506 cached_data.subd_creases_edge.add_data(creases_edge, time);
507 cached_data.subd_creases_weight.add_data(creases_weight, time);
511static void add_subd_vertex_creases(CachedData &cached_data,
512 const SubDSchemaData &
data,
515 if (!(
data.corner_indices.valid() &&
data.crease_sharpnesses.valid())) {
519 const ISampleSelector iss = ISampleSelector(time);
520 const Int32ArraySamplePtr creases_indices =
data.crease_indices.getValue(iss);
521 const FloatArraySamplePtr creases_sharpnesses =
data.crease_sharpnesses.getValue(iss);
523 if (!(creases_indices && creases_sharpnesses) ||
524 creases_indices->size() != creases_sharpnesses->size())
530 sharpnesses.
reserve(creases_indices->size());
532 indices.reserve(creases_indices->size());
534 for (
size_t i = 0; i < creases_indices->size(); i++) {
535 indices.push_back_reserved((*creases_indices)[i]);
539 cached_data.subd_vertex_crease_indices.add_data(
indices, time);
540 cached_data.subd_vertex_crease_weights.add_data(sharpnesses, time);
543static void read_subd_geometry(CachedData &cached_data,
const SubDSchemaData &
data, chrono_t time)
545 const ISampleSelector iss = ISampleSelector(time);
547 add_positions(
data.positions.getValue(iss), time, cached_data);
549 if (
data.topology_variance != kHomogeneousTopology || cached_data.shader.size() == 0) {
550 add_subd_polygons(cached_data,
data, time);
551 add_subd_edge_creases(cached_data,
data, time);
552 add_subd_vertex_creases(cached_data,
data, time);
556void read_geometry_data(AlembicProcedural *proc,
557 CachedData &cached_data,
558 const SubDSchemaData &
data,
561 read_data_loop(proc, cached_data,
data, read_subd_geometry, progress);
566static void read_curves_data(CachedData &cached_data,
const CurvesSchemaData &
data, chrono_t time)
568 const ISampleSelector iss = ISampleSelector(time);
570 const Int32ArraySamplePtr curves_num_vertices =
data.num_vertices.getValue(iss);
571 const P3fArraySamplePtr
position =
data.positions.getValue(iss);
573 FloatArraySamplePtr radiuses;
575 if (
data.widths.valid()) {
576 IFloatGeomParam::Sample wsample =
data.widths.getExpandedValue(iss);
577 radiuses = wsample.getVals();
580 const bool do_radius = (radiuses !=
nullptr) && (radiuses->size() > 1);
581 float radius = (radiuses && radiuses->size() == 1) ? (*radiuses)[0] :
data.default_radius;
588 const bool is_homogeneous =
data.topology_variance == kHomogeneousTopology;
592 curve_first_key.
reserve(curves_num_vertices->size());
593 curve_shader.
reserve(curves_num_vertices->size());
596 for (
size_t i = 0; i < curves_num_vertices->size(); i++) {
597 const int num_vertices = curves_num_vertices->get()[i];
599 for (
int j = 0; j < num_vertices; j++) {
600 const V3f &f =
position->get()[offset + j];
605 radius = (*radiuses)[offset + j];
611 if (!is_homogeneous || cached_data.curve_first_key.size() == 0) {
616 offset += num_vertices;
619 cached_data.curve_keys.add_data(curve_keys, time);
620 cached_data.curve_radius.add_data(curve_radius, time);
622 if (!is_homogeneous || cached_data.curve_first_key.size() == 0) {
623 cached_data.curve_first_key.add_data(curve_first_key, time);
624 cached_data.curve_shader.add_data(curve_shader, time);
628void read_geometry_data(AlembicProcedural *proc,
629 CachedData &cached_data,
630 const CurvesSchemaData &
data,
633 read_data_loop(proc, cached_data,
data, read_curves_data, progress);
638static void read_points_data(CachedData &cached_data,
const PointsSchemaData &
data, chrono_t time)
640 const ISampleSelector iss = ISampleSelector(time);
642 const P3fArraySamplePtr
position =
data.positions.getValue(iss);
643 FloatArraySamplePtr radiuses;
652 if (
data.radiuses.valid()) {
653 IFloatGeomParam::Sample wsample =
data.radiuses.getExpandedValue(iss);
654 radiuses = wsample.getVals();
657 const bool do_radius = (radiuses !=
nullptr) && (radiuses->size() > 1);
658 float radius = (radiuses && radiuses->size() == 1) ? (*radiuses)[0] :
data.default_radius;
661 for (
size_t i = 0; i <
position->size(); i++) {
662 const V3f &f =
position->get()[offset + i];
666 radius = (*radiuses)[offset + i];
673 cached_data.points.add_data(a_positions, time);
674 cached_data.radiuses.add_data(a_radius, time);
675 cached_data.points_shader.add_data(a_shader, time);
678void read_geometry_data(AlembicProcedural *proc,
679 CachedData &cached_data,
680 const PointsSchemaData &
data,
683 read_data_loop(proc, cached_data,
data, read_points_data, progress);
690template<
typename T>
struct value_type_converter {
691 using cycles_type =
float;
693 static constexpr TypeDesc type_desc = TypeDesc::FLOAT;
694 static constexpr const char *type_name =
"float (default)";
698 return static_cast<float>(value);
702template<>
struct value_type_converter<Imath::V2f> {
703 using cycles_type =
float2;
705 static constexpr const char *type_name =
"float2";
713template<>
struct value_type_converter<Imath::V3f> {
714 using cycles_type =
float3;
715 static constexpr TypeDesc type_desc = TypeVector;
716 static constexpr const char *type_name =
"float3";
720 return make_float3_from_yup(value);
724template<>
struct value_type_converter<Imath::C3f> {
725 using cycles_type =
uchar4;
727 static constexpr const char *type_name =
"rgb";
735template<>
struct value_type_converter<Imath::C4f> {
736 using cycles_type =
uchar4;
738 static constexpr const char *type_name =
"rgba";
747template<
typename TRAIT>
748static void process_attribute(CachedData &cache,
751 const typename ITypedGeomParam<TRAIT>::Sample &
sample,
754 using abc_type =
typename TRAIT::value_type;
755 using cycles_type =
typename value_type_converter<abc_type>::cycles_type;
757 const TypedArraySample<TRAIT> &values = *
sample.getVals();
763 cache.vertices.data_for_time_no_check(time).get_data_or_null();
770 if (vertices->
size() != values.size()) {
777 cycles_type *pod_typed_data =
reinterpret_cast<cycles_type *
>(
data.data());
779 for (
size_t i = 0; i < values.size(); ++i) {
780 *pod_typed_data++ = value_type_converter<abc_type>::convert_value(values[i]);
786 case kVaryingScope: {
788 cache.triangles.data_for_time_no_check(time).get_data_or_null();
797 cycles_type *pod_typed_data =
reinterpret_cast<cycles_type *
>(
data.data());
799 for (
const int3 &tri : *triangles) {
800 *pod_typed_data++ = value_type_converter<abc_type>::convert_value(values[tri.x]);
801 *pod_typed_data++ = value_type_converter<abc_type>::convert_value(values[tri.y]);
802 *pod_typed_data++ = value_type_converter<abc_type>::convert_value(values[tri.z]);
816static void process_uvs(CachedData &cache,
819 const IV2fGeomParam::Sample &
sample,
822 if (scope != kFacevaryingScope && scope != kVaryingScope && scope != kVertexScope) {
826 const array<int> *uv_loops = cache.uv_loops.data_for_time_no_check(time).get_data_or_null();
829 if (!uv_loops && scope == kFacevaryingScope) {
833 const array<int3> *triangles = cache.triangles.data_for_time_no_check(time).get_data_or_null();
835 cache.subd_face_corners.data_for_time_no_check(time).get_data_or_null();
851 const V2f *values =
sample.getVals()->get();
853 if (scope == kFacevaryingScope) {
854 for (
const int uv_loop_index : *uv_loops) {
856 *data_float2++ =
make_float2(values[index][0], values[index][1]);
859 else if (scope == kVaryingScope || scope == kVertexScope) {
861 for (
size_t i = 0; i < triangles->
size(); i++) {
862 const int3 t = (*triangles)[i];
863 *data_float2++ =
make_float2(values[t.
x][0], values[t.
x][1]);
864 *data_float2++ =
make_float2(values[t.
y][0], values[t.
y][1]);
865 *data_float2++ =
make_float2(values[t.
z][0], values[t.
z][1]);
869 for (
size_t i = 0; i < corners->
size(); i++) {
870 const int c = (*corners)[i];
871 *data_float2++ =
make_float2(values[c][0], values[c][1]);
881template<
typename TRAIT>
882using process_callback_type = void (*)(CachedData &,
883 CachedData::CachedAttribute &,
885 const typename ITypedGeomParam<TRAIT>::Sample &,
891template<
typename TRAIT>
892static void read_attribute_loop(AlembicProcedural *proc,
894 const ITypedGeomParam<TRAIT> ¶m,
895 process_callback_type<TRAIT> callback,
899 const std::set<chrono_t> times = get_relevant_sample_times(
900 proc, *param.getTimeSampling(), param.getNumSamples());
906 std::string name = param.getName();
909 std::string uv_source_name = Alembic::Abc::GetSourceName(param.getMetaData());
914 if (!uv_source_name.empty()) {
915 name = uv_source_name;
919 CachedData::CachedAttribute &
attribute = cache.add_attribute(ustring(name),
920 *param.getTimeSampling());
922 using abc_type =
typename TRAIT::value_type;
924 attribute.data.set_time_sampling(*param.getTimeSampling());
926 attribute.type_desc = value_type_converter<abc_type>::type_desc;
932 if (param.getScope() == kVaryingScope || param.getScope() == kFacevaryingScope) {
940 for (
const chrono_t time : times) {
945 ISampleSelector iss = ISampleSelector(time);
946 typename ITypedGeomParam<TRAIT>::Sample
sample;
947 param.getIndexed(
sample, iss);
960 if (param.isConstant()) {
964 const ArraySample::Key indices_key =
sample.getIndices()->getKey();
965 const ArraySample::Key values_key =
sample.getVals()->getKey();
967 const bool is_same_as_last_time = (indices_key ==
attribute.data.key1 &&
973 if (is_same_as_last_time) {
974 attribute.data.reuse_data_for_last_time(time);
987struct PropHeaderAndParent {
988 const PropertyHeader *prop;
989 ICompoundProperty parent;
996static void parse_requested_attributes_recursive(
const AttributeRequestSet &requested_attributes,
997 const ICompoundProperty &arb_geom_params,
1000 if (!arb_geom_params.valid()) {
1005 const PropertyHeader *property_header = arb_geom_params.getPropertyHeader(req.
name.c_str());
1007 if (!property_header) {
1011 requested_properties.push_back({property_header, arb_geom_params});
1015 for (
size_t i = 0; i < arb_geom_params.getNumProperties(); ++i) {
1016 const PropertyHeader &property_header = arb_geom_params.getPropertyHeader(i);
1018 if (property_header.isCompound()) {
1019 ICompoundProperty compound_property = ICompoundProperty(arb_geom_params,
1020 property_header.getName());
1021 parse_requested_attributes_recursive(
1022 requested_attributes, compound_property, requested_properties);
1031 const AttributeRequestSet &requested_attributes,
const ICompoundProperty &arb_geom_params)
1034 parse_requested_attributes_recursive(
1035 requested_attributes, arb_geom_params, requested_properties);
1036 return requested_properties;
1043void read_attributes(AlembicProcedural *proc,
1045 const ICompoundProperty &arb_geom_params,
1046 const IV2fGeomParam &default_uvs_param,
1050 if (default_uvs_param.valid()) {
1052 read_attribute_loop(proc, cache, default_uvs_param, process_uvs, progress,
ATTR_STD_UV);
1056 requested_attributes, arb_geom_params);
1058 for (
const PropHeaderAndParent &prop_and_parent : requested_properties) {
1063 const PropertyHeader *prop = prop_and_parent.prop;
1064 const ICompoundProperty &parent = prop_and_parent.parent;
1066 if (IBoolGeomParam::matches(*prop)) {
1067 const IBoolGeomParam ¶m = IBoolGeomParam(parent, prop->getName());
1068 read_attribute_loop(proc, cache, param, process_attribute<BooleanTPTraits>, progress);
1070 else if (IInt32GeomParam::matches(*prop)) {
1071 const IInt32GeomParam ¶m = IInt32GeomParam(parent, prop->getName());
1072 read_attribute_loop(proc, cache, param, process_attribute<Int32TPTraits>, progress);
1074 else if (IFloatGeomParam::matches(*prop)) {
1075 const IFloatGeomParam ¶m = IFloatGeomParam(parent, prop->getName());
1076 read_attribute_loop(proc, cache, param, process_attribute<Float32TPTraits>, progress);
1078 else if (IV2fGeomParam::matches(*prop)) {
1079 const IV2fGeomParam ¶m = IV2fGeomParam(parent, prop->getName());
1080 if (Alembic::AbcGeom::isUV(*prop)) {
1081 read_attribute_loop(proc, cache, param, process_uvs, progress);
1084 read_attribute_loop(proc, cache, param, process_attribute<V2fTPTraits>, progress);
1087 else if (IV3fGeomParam::matches(*prop)) {
1088 const IV3fGeomParam ¶m = IV3fGeomParam(parent, prop->getName());
1089 read_attribute_loop(proc, cache, param, process_attribute<V3fTPTraits>, progress);
1091 else if (IN3fGeomParam::matches(*prop)) {
1092 const IN3fGeomParam ¶m = IN3fGeomParam(parent, prop->getName());
1093 read_attribute_loop(proc, cache, param, process_attribute<N3fTPTraits>, progress);
1095 else if (IC3fGeomParam::matches(*prop)) {
1096 const IC3fGeomParam ¶m = IC3fGeomParam(parent, prop->getName());
1097 read_attribute_loop(proc, cache, param, process_attribute<C3fTPTraits>, progress);
1099 else if (IC4fGeomParam::matches(*prop)) {
1100 const IC4fGeomParam ¶m = IC4fGeomParam(parent, prop->getName());
1101 read_attribute_loop(proc, cache, param, process_attribute<C4fTPTraits>, progress);
1105 cache.invalidate_last_loaded_time(
true);
typedef double(DMatrix)[4][4]
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
VecBase< float, 3 > float3
vector< AttributeRequest > requests
void push_back_reserved(const T &t)
void reserve(size_t newcapacity)
void push_back_slow(const T &t)
VecBase< float, 2 > float2
#define CCL_NAMESPACE_END
draw_view in_light_buf[] float
static float normals[][3]
@ ATTR_ELEMENT_CORNER_BYTE
To convert_value(const From value)
static constexpr TypeDesc TypeRGBA(TypeDesc::FLOAT, TypeDesc::VEC4, TypeDesc::COLOR)
CCL_NAMESPACE_BEGIN static OIIO_NAMESPACE_USING constexpr TypeDesc TypeFloat2(TypeDesc::FLOAT, TypeDesc::VEC2)
blender::VecBase< uint8_t, 4 > uchar4
float3 compute_normal(const float3 *verts) const
ccl_device uchar4 color_float4_to_uchar4(float4 c)
ccl_device uchar4 color_float_to_byte(float3 c)