24using namespace Alembic::AbcGeom;
30template<
typename SchemaType>
36 std::vector<std::string> face_set_names;
37 schema.getFaceSetNames(face_set_names);
39 if (face_set_names.empty()) {
43 for (
const std::string &face_set_name : face_set_names) {
46 for (
Node *node : used_shaders) {
47 if (node->name == face_set_name) {
54 if (shader_index >= used_shaders.size()) {
59 const Alembic::AbcGeom::IFaceSet face_set = schema.getFaceSet(face_set_name);
61 if (!face_set.valid()) {
65 result.push_back({face_set, shader_index});
71void CachedData::clear()
74 curve_first_key.clear();
80 subd_creases_edge.clear();
81 subd_creases_weight.clear();
82 subd_face_corners.clear();
83 subd_num_corners.clear();
84 subd_ptex_offset.clear();
86 subd_start_corner.clear();
93 points_shader.clear();
95 for (CachedAttribute &attr : attributes) {
102CachedData::CachedAttribute &CachedData::add_attribute(
const ustring &name,
103 const TimeSampling &time_sampling)
105 for (
auto &attr : attributes) {
106 if (attr.name == name) {
111 CachedAttribute &attr = attributes.emplace_back();
113 attr.data.set_time_sampling(time_sampling);
117bool CachedData::is_constant()
const
119# define CHECK_IF_CONSTANT(data) \
120 if (!data.is_constant()) { \
124 CHECK_IF_CONSTANT(curve_first_key)
125 CHECK_IF_CONSTANT(curve_keys)
126 CHECK_IF_CONSTANT(curve_radius)
127 CHECK_IF_CONSTANT(curve_shader)
128 CHECK_IF_CONSTANT(num_ngons)
129 CHECK_IF_CONSTANT(shader)
130 CHECK_IF_CONSTANT(subd_creases_edge)
131 CHECK_IF_CONSTANT(subd_creases_weight)
132 CHECK_IF_CONSTANT(subd_face_corners)
133 CHECK_IF_CONSTANT(subd_num_corners)
134 CHECK_IF_CONSTANT(subd_ptex_offset)
135 CHECK_IF_CONSTANT(subd_smooth)
136 CHECK_IF_CONSTANT(subd_start_corner)
137 CHECK_IF_CONSTANT(transforms)
138 CHECK_IF_CONSTANT(triangles)
139 CHECK_IF_CONSTANT(uv_loops)
140 CHECK_IF_CONSTANT(vertices)
141 CHECK_IF_CONSTANT(points)
142 CHECK_IF_CONSTANT(radiuses)
143 CHECK_IF_CONSTANT(points_shader)
145 for (
const CachedAttribute &attr : attributes) {
146 if (!attr.data.is_constant()) {
153# undef CHECK_IF_CONSTANT
156void CachedData::invalidate_last_loaded_time(
bool attributes_only)
158 if (attributes_only) {
159 for (CachedAttribute &attr : attributes) {
160 attr.data.invalidate_last_loaded_time();
166 curve_first_key.invalidate_last_loaded_time();
167 curve_keys.invalidate_last_loaded_time();
168 curve_radius.invalidate_last_loaded_time();
169 curve_shader.invalidate_last_loaded_time();
170 num_ngons.invalidate_last_loaded_time();
171 shader.invalidate_last_loaded_time();
172 subd_creases_edge.invalidate_last_loaded_time();
173 subd_creases_weight.invalidate_last_loaded_time();
174 subd_face_corners.invalidate_last_loaded_time();
175 subd_num_corners.invalidate_last_loaded_time();
176 subd_ptex_offset.invalidate_last_loaded_time();
177 subd_smooth.invalidate_last_loaded_time();
178 subd_start_corner.invalidate_last_loaded_time();
179 transforms.invalidate_last_loaded_time();
180 triangles.invalidate_last_loaded_time();
181 uv_loops.invalidate_last_loaded_time();
182 vertices.invalidate_last_loaded_time();
183 points.invalidate_last_loaded_time();
184 radiuses.invalidate_last_loaded_time();
185 points_shader.invalidate_last_loaded_time();
188void CachedData::set_time_sampling(TimeSampling time_sampling)
190 curve_first_key.set_time_sampling(time_sampling);
191 curve_keys.set_time_sampling(time_sampling);
192 curve_radius.set_time_sampling(time_sampling);
193 curve_shader.set_time_sampling(time_sampling);
194 num_ngons.set_time_sampling(time_sampling);
195 shader.set_time_sampling(time_sampling);
196 subd_creases_edge.set_time_sampling(time_sampling);
197 subd_creases_weight.set_time_sampling(time_sampling);
198 subd_face_corners.set_time_sampling(time_sampling);
199 subd_num_corners.set_time_sampling(time_sampling);
200 subd_ptex_offset.set_time_sampling(time_sampling);
201 subd_smooth.set_time_sampling(time_sampling);
202 subd_start_corner.set_time_sampling(time_sampling);
203 transforms.set_time_sampling(time_sampling);
204 triangles.set_time_sampling(time_sampling);
205 uv_loops.set_time_sampling(time_sampling);
206 vertices.set_time_sampling(time_sampling);
207 points.set_time_sampling(time_sampling);
208 radiuses.set_time_sampling(time_sampling);
209 points_shader.set_time_sampling(time_sampling);
211 for (CachedAttribute &attr : attributes) {
212 attr.data.set_time_sampling(time_sampling);
216size_t CachedData::memory_used()
const
220 mem_used += curve_first_key.memory_used();
221 mem_used += curve_keys.memory_used();
222 mem_used += curve_radius.memory_used();
223 mem_used += curve_shader.memory_used();
224 mem_used += num_ngons.memory_used();
225 mem_used += shader.memory_used();
226 mem_used += subd_creases_edge.memory_used();
227 mem_used += subd_creases_weight.memory_used();
228 mem_used += subd_face_corners.memory_used();
229 mem_used += subd_num_corners.memory_used();
230 mem_used += subd_ptex_offset.memory_used();
231 mem_used += subd_smooth.memory_used();
232 mem_used += subd_start_corner.memory_used();
233 mem_used += transforms.memory_used();
234 mem_used += triangles.memory_used();
235 mem_used += uv_loops.memory_used();
236 mem_used += vertices.memory_used();
237 mem_used += points.memory_used();
238 mem_used += radiuses.memory_used();
239 mem_used += points_shader.memory_used();
241 for (
const CachedAttribute &attr : attributes) {
242 mem_used += attr.data.memory_used();
248static M44d convert_yup_zup(
const M44d &mtx,
float scale_mult)
250 V3d
scale, shear, rotation, translation;
252 if (!extractSHRT(mtx,
258 IMATH_INTERNAL_NAMESPACE::Euler<double>::XZY))
263 M44d rot_mat, scale_mat, trans_mat;
264 rot_mat.setEulerAngles(V3d(rotation.x, -rotation.z, rotation.y));
266 trans_mat.setTranslation(V3d(translation.x, -translation.z, translation.y));
268 M44d temp_mat = scale_mat * rot_mat * trans_mat;
270 scale_mat.setScale(
static_cast<double>(scale_mult));
272 return temp_mat * scale_mat;
276 const M44d &mat, V3d &scale, V3d &shear, Quatd &rotation, V3d &translation)
278 M44d mat_remainder(mat);
281 Imath::extractAndRemoveScalingAndShear(mat_remainder, scale, shear);
284 translation.x = mat_remainder[3][0];
285 translation.y = mat_remainder[3][1];
286 translation.z = mat_remainder[3][2];
289 rotation = extractQuat(mat_remainder);
294 const Quatd &rotation,
295 const V3d &translation)
297 M44d scale_mat, shear_mat, rot_mat, trans_mat;
299 scale_mat.setScale(scale);
300 shear_mat.setShear(shear);
301 rot_mat = rotation.toMatrix44();
302 trans_mat.setTranslation(translation);
304 return scale_mat * shear_mat * rot_mat * trans_mat;
309static M44d get_matrix_for_time(
const MatrixSampleMap &samples, chrono_t time)
311 MatrixSampleMap::const_iterator iter = samples.find(time);
312 if (iter != samples.end()) {
321static M44d get_interpolated_matrix_for_time(
const MatrixSampleMap &samples, chrono_t time)
323 if (samples.empty()) {
328 MatrixSampleMap::const_iterator iter = samples.find(time);
329 if (iter != samples.end()) {
333 if (samples.size() == 1) {
334 return samples.begin()->second;
337 if (time <= samples.begin()->first) {
338 return samples.begin()->second;
341 if (time >= samples.rbegin()->first) {
342 return samples.rbegin()->second;
346 chrono_t prev_time = samples.begin()->first;
347 chrono_t next_time = samples.rbegin()->first;
349 for (MatrixSampleMap::const_iterator
I = samples.begin();
I != samples.end(); ++
I) {
350 chrono_t current_time = (*I).first;
352 if (current_time > prev_time && current_time <= time) {
353 prev_time = current_time;
356 if (current_time > next_time && current_time >= time) {
357 next_time = current_time;
361 const M44d prev_mat = get_matrix_for_time(samples, prev_time);
362 const M44d next_mat = get_matrix_for_time(samples, next_time);
364 V3d prev_scale, next_scale;
365 V3d prev_shear, next_shear;
366 V3d prev_translation, next_translation;
367 Quatd prev_rotation, next_rotation;
372 chrono_t t = (time - prev_time) / (next_time - prev_time);
375 if ((prev_rotation ^ next_rotation) < 0) {
376 next_rotation = -next_rotation;
380 Imath::lerp(prev_shear, next_shear, t),
381 Imath::slerp(prev_rotation, next_rotation, t),
382 Imath::lerp(prev_translation, next_translation, t));
385static void concatenate_xform_samples(
const MatrixSampleMap &parent_samples,
386 const MatrixSampleMap &local_samples,
387 MatrixSampleMap &output_samples)
389 set<chrono_t> union_of_samples;
391 for (
const std::pair<chrono_t, M44d> pair : parent_samples) {
392 union_of_samples.insert(pair.first);
395 for (
const std::pair<chrono_t, M44d> pair : local_samples) {
396 union_of_samples.insert(pair.first);
399 foreach (chrono_t time, union_of_samples) {
400 M44d parent_matrix = get_interpolated_matrix_for_time(parent_samples, time);
401 M44d local_matrix = get_interpolated_matrix_for_time(local_samples, time);
403 output_samples[time] = local_matrix * parent_matrix;
409 M44d m = convert_yup_zup(a, scale);
411 for (
int j = 0; j < 3; j++) {
412 for (
int i = 0; i < 4; i++) {
413 trans[j][i] =
static_cast<float>(m[i][j]);
428 SOCKET_INT(subd_max_level,
"Max Subdivision Level", 1);
429 SOCKET_FLOAT(subd_dicing_rate,
"Subdivision Dicing Rate", 1.0f);
436AlembicObject::AlembicObject() :
Node(get_node_type())
438 schema_type = INVALID;
441AlembicObject::~AlembicObject() {}
443void AlembicObject::set_object(
Object *object_)
448Object *AlembicObject::get_object()
453bool AlembicObject::has_data_loaded()
const
458void AlembicObject::load_data_in_cache(CachedData &cached_data,
459 AlembicProcedural *proc,
460 IPolyMeshSchema &schema,
470 PolyMeshSchemaData
data;
471 data.topology_variance = schema.getTopologyVariance();
472 data.time_sampling = schema.getTimeSampling();
473 data.positions = schema.getPositionsProperty();
474 data.face_counts = schema.getFaceCountsProperty();
475 data.face_indices = schema.getFaceIndicesProperty();
476 data.normals = schema.getNormalsParam();
477 data.num_samples = schema.getNumSamples();
478 data.shader_face_sets = parse_face_sets_for_shader_assignment(schema, get_used_shaders());
480 read_geometry_data(proc, cached_data,
data, progress);
489 proc, cached_data, schema, schema.getUVsParam(), get_requested_attributes(), progress);
495 cached_data.invalidate_last_loaded_time(
true);
499void AlembicObject::load_data_in_cache(CachedData &cached_data,
500 AlembicProcedural *proc,
511 if (this->get_ignore_subdivision()) {
512 PolyMeshSchemaData
data;
513 data.topology_variance = schema.getTopologyVariance();
514 data.time_sampling = schema.getTimeSampling();
515 data.positions = schema.getPositionsProperty();
516 data.face_counts = schema.getFaceCountsProperty();
517 data.face_indices = schema.getFaceIndicesProperty();
518 data.num_samples = schema.getNumSamples();
519 data.velocities = schema.getVelocitiesProperty();
520 data.shader_face_sets = parse_face_sets_for_shader_assignment(schema, get_used_shaders());
522 read_geometry_data(proc, cached_data,
data, progress);
531 proc, cached_data, schema, schema.getUVsParam(), get_requested_attributes(), progress);
533 cached_data.invalidate_last_loaded_time(
true);
539 data.time_sampling = schema.getTimeSampling();
540 data.num_samples = schema.getNumSamples();
541 data.topology_variance = schema.getTopologyVariance();
542 data.face_counts = schema.getFaceCountsProperty();
543 data.face_indices = schema.getFaceIndicesProperty();
544 data.positions = schema.getPositionsProperty();
545 data.face_varying_interpolate_boundary = schema.getFaceVaryingInterpolateBoundaryProperty();
546 data.face_varying_propagate_corners = schema.getFaceVaryingPropagateCornersProperty();
547 data.interpolate_boundary = schema.getInterpolateBoundaryProperty();
548 data.crease_indices = schema.getCreaseIndicesProperty();
549 data.crease_lengths = schema.getCreaseLengthsProperty();
550 data.crease_sharpnesses = schema.getCreaseSharpnessesProperty();
551 data.corner_indices = schema.getCornerIndicesProperty();
552 data.corner_sharpnesses = schema.getCornerSharpnessesProperty();
553 data.holes = schema.getHolesProperty();
554 data.subdivision_scheme = schema.getSubdivisionSchemeProperty();
555 data.velocities = schema.getVelocitiesProperty();
556 data.shader_face_sets = parse_face_sets_for_shader_assignment(schema, get_used_shaders());
558 read_geometry_data(proc, cached_data,
data, progress);
567 proc, cached_data, schema, schema.getUVsParam(), get_requested_attributes(), progress);
569 cached_data.invalidate_last_loaded_time(
true);
573void AlembicObject::load_data_in_cache(CachedData &cached_data,
574 AlembicProcedural *proc,
575 const ICurvesSchema &schema,
585 CurvesSchemaData
data;
586 data.positions = schema.getPositionsProperty();
587 data.position_weights = schema.getPositionWeightsProperty();
588 data.normals = schema.getNormalsParam();
589 data.knots = schema.getKnotsProperty();
590 data.orders = schema.getOrdersProperty();
591 data.widths = schema.getWidthsParam();
592 data.velocities = schema.getVelocitiesProperty();
593 data.time_sampling = schema.getTimeSampling();
594 data.topology_variance = schema.getTopologyVariance();
595 data.num_samples = schema.getNumSamples();
596 data.num_vertices = schema.getNumVerticesProperty();
597 data.default_radius = proc->get_default_radius();
598 data.radius_scale = get_radius_scale();
600 read_geometry_data(proc, cached_data,
data, progress);
609 proc, cached_data, schema, schema.getUVsParam(), get_requested_attributes(), progress);
611 cached_data.invalidate_last_loaded_time(
true);
615void AlembicObject::load_data_in_cache(CachedData &cached_data,
616 AlembicProcedural *proc,
617 const IPointsSchema &schema,
627 PointsSchemaData
data;
628 data.positions = schema.getPositionsProperty();
629 data.radiuses = schema.getWidthsParam();
630 data.velocities = schema.getVelocitiesProperty();
631 data.time_sampling = schema.getTimeSampling();
632 data.num_samples = schema.getNumSamples();
633 data.default_radius = proc->get_default_radius();
634 data.radius_scale = get_radius_scale();
636 read_geometry_data(proc, cached_data,
data, progress);
644 read_attributes(proc, cached_data, schema, {}, get_requested_attributes(), progress);
646 cached_data.invalidate_last_loaded_time(
true);
650void AlembicObject::setup_transform_cache(CachedData &cached_data,
float scale)
652 cached_data.transforms.clear();
653 cached_data.transforms.invalidate_last_loaded_time();
659 if (xform_time_sampling) {
660 cached_data.transforms.set_time_sampling(*xform_time_sampling);
663 if (xform_samples.size() == 0) {
665 cached_data.transforms.add_data(tfm, 0.0);
671 M44d first_matrix = xform_samples.begin()->first;
672 bool has_animation =
false;
673 for (
const std::pair<chrono_t, M44d> pair : xform_samples) {
674 if (pair.second != first_matrix) {
675 has_animation =
true;
680 if (!has_animation) {
682 cached_data.transforms.add_data(tfm, 0.0);
685 for (
const std::pair<chrono_t, M44d> pair : xform_samples) {
687 cached_data.transforms.add_data(tfm, pair.first);
697 Geometry *geometry =
object->get_geometry();
700 foreach (
Node *node, geometry->get_used_shaders()) {
704 if (attr.
name !=
"") {
705 requested_attributes.
add(attr.
name);
710 return requested_attributes;
715static void update_attributes(
AttributeSet &attributes, CachedData &cached_data,
double frame_time)
717 set<Attribute *> cached_attributes;
719 for (CachedData::CachedAttribute &
attribute : cached_data.attributes) {
720 const CacheLookupResult<array<char>>
result =
attribute.data.data_for_time(frame_time);
722 if (
result.has_no_data_for_time()) {
735 cached_attributes.insert(attr);
737 if (!
result.has_new_data()) {
741 const ccl::array<char> &attr_data =
result.get_data();
745 if (attr->
buffer.size() != attr_data.size()) {
746 attr->
buffer.resize(attr_data.size());
749 memcpy(attr->
data(), attr_data.data(), attr_data.size());
754 list<Attribute>::iterator it;
756 if (cached_attributes.find(&(*it)) == cached_attributes.end()) {
782 SOCKET_INT(prefetch_cache_size,
"Prefetch Cache Size", 4096);
787AlembicProcedural::AlembicProcedural() :
Procedural(get_node_type())
789 objects_loaded =
false;
793AlembicProcedural::~AlembicProcedural()
795 ccl::set<Geometry *> geometries_set;
796 ccl::set<Object *> objects_set;
797 ccl::set<AlembicObject *> abc_objects_set;
799 foreach (
Node *node, objects) {
800 AlembicObject *abc_object =
static_cast<AlembicObject *
>(node);
802 if (abc_object->get_object()) {
803 objects_set.insert(abc_object->get_object());
805 if (abc_object->get_object()->get_geometry()) {
806 geometries_set.insert(abc_object->get_object()->get_geometry());
810 delete_node(abc_object);
815 assert(geometries_set.empty());
816 assert(objects_set.empty());
820 scene_->delete_nodes(geometries_set,
this);
821 scene_->delete_nodes(objects_set,
this);
824void AlembicProcedural::generate(
Scene *scene,
Progress &progress)
826 assert(scene_ ==
nullptr || scene_ == scene);
829 if (frame < start_frame || frame > end_frame) {
834 bool need_shader_updates =
false;
835 bool need_data_updates =
false;
837 foreach (
Node *object_node, objects) {
838 AlembicObject *
object =
static_cast<AlembicObject *
>(object_node);
840 if (object->is_modified()) {
841 need_data_updates =
true;
845 if (object->used_shaders_is_modified() && object->get_object() &&
846 object->get_object()->get_geometry())
848 Geometry *geometry =
object->get_object()->get_geometry();
850 geometry->set_used_shaders(used_shaders);
851 need_shader_updates =
true;
855 foreach (
Node *shader_node, object->get_used_shaders()) {
859 object->need_shader_update =
true;
860 need_shader_updates =
true;
865 if (!is_modified() && !need_shader_updates && !need_data_updates) {
869 if (!archive.valid() || filepath_is_modified() || layers_is_modified()) {
870 Alembic::AbcCoreFactory::IFactory factory;
871 factory.setPolicy(Alembic::Abc::ErrorHandler::kQuietNoopPolicy);
873 std::vector<std::string> filenames;
874 filenames.push_back(filepath.c_str());
876 for (
const ustring &layer : layers) {
877 filenames.push_back(layer.c_str());
881 std::reverse(filenames.begin(), filenames.end());
883 archive = factory.getArchive(filenames);
885 if (!archive.valid()) {
894 if (!objects_loaded || objects_is_modified()) {
895 load_objects(progress);
896 objects_loaded =
true;
899 const chrono_t frame_time = (chrono_t)((frame - frame_offset) / frame_rate);
902 for (
Node *node : objects) {
903 AlembicObject *
object =
static_cast<AlembicObject *
>(node);
905 if (object->schema_type != AlembicObject::SUBD) {
909 if (object->ignore_subdivision_is_modified()) {
910 object->clear_cache();
914 if (use_prefetch_is_modified()) {
916 for (
Node *node : objects) {
917 AlembicObject *
object =
static_cast<AlembicObject *
>(node);
918 object->clear_cache();
923 if (prefetch_cache_size_is_modified()) {
926 size_t memory_used = 0ul;
927 for (
Node *node : objects) {
928 AlembicObject *
object =
static_cast<AlembicObject *
>(node);
929 memory_used +=
object->get_cached_data().memory_used();
932 if (memory_used > get_prefetch_cache_size_in_bytes()) {
933 progress.
set_error(
"Error: Alembic Procedural memory limit reached");
938 build_caches(progress);
940 foreach (
Node *node, objects) {
941 AlembicObject *
object =
static_cast<AlembicObject *
>(node);
948 if (object->is_constant() && !object->is_modified() && !object->need_shader_update &&
949 !scale_is_modified())
954 if (object->schema_type == AlembicObject::POLY_MESH) {
955 read_mesh(
object, frame_time);
957 else if (object->schema_type == AlembicObject::CURVES) {
958 read_curves(
object, frame_time);
960 else if (object->schema_type == AlembicObject::POINTS) {
961 read_points(
object, frame_time);
963 else if (object->schema_type == AlembicObject::SUBD) {
964 read_subd(
object, frame_time);
967 object->need_shader_update =
false;
968 object->clear_modified();
974void AlembicProcedural::add_object(AlembicObject *
object)
976 objects.push_back_slow(
object);
977 tag_objects_modified();
980void AlembicProcedural::tag_update(
Scene *scene)
985AlembicObject *AlembicProcedural::get_or_create_object(
const ustring &path)
987 foreach (
Node *node, objects) {
988 AlembicObject *
object =
static_cast<AlembicObject *
>(node);
990 if (object->get_path() == path) {
995 AlembicObject *
object = create_node<AlembicObject>();
996 object->set_path(path);
1003void AlembicProcedural::load_objects(
Progress &progress)
1005 unordered_map<string, AlembicObject *> object_map;
1007 foreach (
Node *node, objects) {
1008 AlembicObject *
object =
static_cast<AlembicObject *
>(node);
1011 if (object->get_object() ==
nullptr) {
1012 object_map.insert({
object->get_path().c_str(),
object});
1016 IObject root = archive.getTop();
1018 for (
size_t i = 0; i < root.getNumChildren(); ++i) {
1019 walk_hierarchy(root, root.getChildHeader(i), {}, object_map, progress);
1023 for (std::pair<string, AlembicObject *> pair : object_map) {
1024 AlembicObject *abc_object = pair.second;
1028 if (!abc_object->instance_of) {
1029 if (abc_object->schema_type == AlembicObject::CURVES) {
1030 geometry = scene_->create_node<
Hair>();
1032 else if (abc_object->schema_type == AlembicObject::POINTS) {
1033 geometry = scene_->create_node<
PointCloud>();
1035 else if (abc_object->schema_type == AlembicObject::POLY_MESH ||
1036 abc_object->schema_type == AlembicObject::SUBD)
1038 geometry = scene_->create_node<
Mesh>();
1045 geometry->
name = abc_object->iobject.getName();
1047 array<Node *> used_shaders = abc_object->get_used_shaders();
1048 geometry->set_used_shaders(used_shaders);
1053 object->set_geometry(geometry);
1054 object->name = abc_object->iobject.getName();
1056 abc_object->set_object(
object);
1060 foreach (
Node *node, objects) {
1061 AlembicObject *abc_object =
static_cast<AlembicObject *
>(node);
1063 if (abc_object->instance_of) {
1064 abc_object->get_object()->set_geometry(
1065 abc_object->instance_of->get_object()->get_geometry());
1066 abc_object->schema_type = abc_object->instance_of->schema_type;
1071void AlembicProcedural::read_mesh(AlembicObject *abc_object, Abc::chrono_t frame_time)
1073 CachedData &cached_data = abc_object->get_cached_data();
1077 Object *
object = abc_object->get_object();
1078 cached_data.transforms.copy_to_socket(frame_time,
object, object->get_tfm_socket());
1081 object->tag_update(scene_);
1085 if (abc_object->instance_of) {
1089 Mesh *mesh =
static_cast<Mesh *
>(
object->get_geometry());
1092 if (mesh->used_shaders_is_modified()) {
1093 mesh->tag_shader_modified();
1096 cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket());
1098 cached_data.shader.copy_to_socket(frame_time, mesh, mesh->get_shader_socket());
1100 array<int3> *triangle_data = cached_data.triangles.data_for_time(frame_time).get_data_or_null();
1101 if (triangle_data) {
1108 for (
size_t i = 0; i < triangle_data->
size(); ++i) {
1109 int3 tri = (*triangle_data)[i];
1113 smooth.push_back_reserved(1);
1116 mesh->set_triangles(triangles);
1117 mesh->set_smooth(
smooth);
1122 update_attributes(mesh->
attributes, cached_data, frame_time);
1125 bool need_rebuild = mesh->triangles_is_modified();
1130void AlembicProcedural::read_subd(AlembicObject *abc_object, Abc::chrono_t frame_time)
1132 if (abc_object->get_ignore_subdivision()) {
1133 read_mesh(abc_object, frame_time);
1137 CachedData &cached_data = abc_object->get_cached_data();
1141 Object *
object = abc_object->get_object();
1142 cached_data.transforms.copy_to_socket(frame_time,
object, object->get_tfm_socket());
1145 object->tag_update(scene_);
1149 if (abc_object->instance_of) {
1153 if (abc_object->subd_max_level_is_modified() || abc_object->subd_dicing_rate_is_modified()) {
1155 cached_data.invalidate_last_loaded_time();
1158 Mesh *mesh =
static_cast<Mesh *
>(
object->get_geometry());
1161 if (mesh->used_shaders_is_modified()) {
1162 mesh->tag_shader_modified();
1167 if (!cached_data.is_constant()) {
1168 cached_data.invalidate_last_loaded_time();
1172 mesh->set_triangles(triangles);
1179 mesh->set_subd_max_level(abc_object->get_subd_max_level());
1180 mesh->set_subd_dicing_rate(abc_object->get_subd_dicing_rate());
1182 cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket());
1185 cached_data.shader.copy_to_socket(frame_time, mesh, mesh->get_subd_shader_socket());
1187 cached_data.subd_start_corner.copy_to_socket(
1188 frame_time, mesh, mesh->get_subd_start_corner_socket());
1190 cached_data.subd_num_corners.copy_to_socket(
1191 frame_time, mesh, mesh->get_subd_num_corners_socket());
1193 cached_data.subd_smooth.copy_to_socket(frame_time, mesh, mesh->get_subd_smooth_socket());
1195 cached_data.subd_ptex_offset.copy_to_socket(
1196 frame_time, mesh, mesh->get_subd_ptex_offset_socket());
1198 cached_data.subd_face_corners.copy_to_socket(
1199 frame_time, mesh, mesh->get_subd_face_corners_socket());
1201 cached_data.num_ngons.copy_to_socket(frame_time, mesh, mesh->get_num_ngons_socket());
1203 cached_data.subd_creases_edge.copy_to_socket(
1204 frame_time, mesh, mesh->get_subd_creases_edge_socket());
1206 cached_data.subd_creases_weight.copy_to_socket(
1207 frame_time, mesh, mesh->get_subd_creases_weight_socket());
1209 cached_data.subd_vertex_crease_indices.copy_to_socket(
1210 frame_time, mesh, mesh->get_subd_vert_creases_socket());
1212 cached_data.subd_vertex_crease_weights.copy_to_socket(
1213 frame_time, mesh, mesh->get_subd_vert_creases_weight_socket());
1222 bool need_rebuild = (mesh->triangles_is_modified()) ||
1223 (mesh->subd_num_corners_is_modified()) ||
1224 (mesh->subd_shader_is_modified()) || (mesh->subd_smooth_is_modified()) ||
1225 (mesh->subd_ptex_offset_is_modified()) ||
1226 (mesh->subd_start_corner_is_modified()) ||
1227 (mesh->subd_face_corners_is_modified());
1233void AlembicProcedural::read_curves(AlembicObject *abc_object, Abc::chrono_t frame_time)
1235 CachedData &cached_data = abc_object->get_cached_data();
1239 Object *
object = abc_object->get_object();
1240 cached_data.transforms.copy_to_socket(frame_time,
object, object->get_tfm_socket());
1243 object->tag_update(scene_);
1247 if (abc_object->instance_of) {
1251 Hair *hair =
static_cast<Hair *
>(
object->get_geometry());
1254 if (hair->used_shaders_is_modified()) {
1255 hair->tag_curve_shader_modified();
1258 cached_data.curve_keys.copy_to_socket(frame_time, hair, hair->get_curve_keys_socket());
1260 cached_data.curve_radius.copy_to_socket(frame_time, hair, hair->get_curve_radius_socket());
1262 cached_data.curve_shader.copy_to_socket(frame_time, hair, hair->get_curve_shader_socket());
1264 cached_data.curve_first_key.copy_to_socket(frame_time, hair, hair->get_curve_first_key_socket());
1268 update_attributes(hair->
attributes, cached_data, frame_time);
1270 const bool rebuild = (hair->curve_keys_is_modified() || hair->curve_radius_is_modified());
1274void AlembicProcedural::read_points(AlembicObject *abc_object, Abc::chrono_t frame_time)
1276 CachedData &cached_data = abc_object->get_cached_data();
1280 Object *
object = abc_object->get_object();
1281 cached_data.transforms.copy_to_socket(frame_time,
object, object->get_tfm_socket());
1284 object->tag_update(scene_);
1288 if (abc_object->instance_of) {
1295 if (point_cloud->used_shaders_is_modified()) {
1296 point_cloud->tag_shader_modified();
1299 cached_data.points.copy_to_socket(frame_time, point_cloud, point_cloud->get_points_socket());
1300 cached_data.radiuses.copy_to_socket(frame_time, point_cloud, point_cloud->get_radius_socket());
1301 cached_data.points_shader.copy_to_socket(
1302 frame_time, point_cloud, point_cloud->get_shader_socket());
1306 update_attributes(point_cloud->
attributes, cached_data, frame_time);
1308 const bool rebuild = (point_cloud->points_is_modified() || point_cloud->radius_is_modified() ||
1309 point_cloud->shader_is_modified());
1313void AlembicProcedural::walk_hierarchy(
1315 const ObjectHeader &header,
1316 MatrixSamplesData matrix_samples_data,
1317 const unordered_map<std::string, AlembicObject *> &object_map,
1324 IObject next_object;
1326 MatrixSampleMap concatenated_xform_samples;
1328 if (IXform::matches(header)) {
1329 IXform xform(parent, header.getName());
1331 IXformSchema &xs = xform.getSchema();
1333 if (xs.getNumOps() > 0) {
1334 TimeSamplingPtr ts = xs.getTimeSampling();
1335 MatrixSampleMap local_xform_samples;
1337 MatrixSampleMap *temp_xform_samples =
nullptr;
1338 if (matrix_samples_data.samples ==
nullptr) {
1340 temp_xform_samples = &concatenated_xform_samples;
1344 temp_xform_samples = &local_xform_samples;
1347 for (
size_t i = 0; i < xs.getNumSamples(); ++i) {
1348 chrono_t sample_time = ts->getSampleTime(index_t(i));
1349 XformSample
sample = xs.getValue(ISampleSelector(sample_time));
1350 temp_xform_samples->insert({sample_time,
sample.getMatrix()});
1353 if (matrix_samples_data.samples !=
nullptr) {
1354 concatenate_xform_samples(
1355 *matrix_samples_data.samples, local_xform_samples, concatenated_xform_samples);
1358 matrix_samples_data.samples = &concatenated_xform_samples;
1359 matrix_samples_data.time_sampling = ts;
1362 next_object = xform;
1364 else if (ISubD::matches(header)) {
1365 ISubD subd(parent, header.getName());
1367 unordered_map<std::string, AlembicObject *>::const_iterator iter;
1368 iter = object_map.find(subd.getFullName());
1370 if (iter != object_map.end()) {
1371 AlembicObject *abc_object = iter->second;
1372 abc_object->iobject = subd;
1373 abc_object->schema_type = AlembicObject::SUBD;
1375 if (matrix_samples_data.samples) {
1376 abc_object->xform_samples = *matrix_samples_data.samples;
1377 abc_object->xform_time_sampling = matrix_samples_data.time_sampling;
1383 else if (IPolyMesh::matches(header)) {
1384 IPolyMesh mesh(parent, header.getName());
1386 unordered_map<std::string, AlembicObject *>::const_iterator iter;
1387 iter = object_map.find(mesh.getFullName());
1389 if (iter != object_map.end()) {
1390 AlembicObject *abc_object = iter->second;
1391 abc_object->iobject = mesh;
1392 abc_object->schema_type = AlembicObject::POLY_MESH;
1394 if (matrix_samples_data.samples) {
1395 abc_object->xform_samples = *matrix_samples_data.samples;
1396 abc_object->xform_time_sampling = matrix_samples_data.time_sampling;
1402 else if (ICurves::matches(header)) {
1403 ICurves curves(parent, header.getName());
1405 unordered_map<std::string, AlembicObject *>::const_iterator iter;
1406 iter = object_map.find(curves.getFullName());
1408 if (iter != object_map.end()) {
1409 AlembicObject *abc_object = iter->second;
1410 abc_object->iobject = curves;
1411 abc_object->schema_type = AlembicObject::CURVES;
1413 if (matrix_samples_data.samples) {
1414 abc_object->xform_samples = *matrix_samples_data.samples;
1415 abc_object->xform_time_sampling = matrix_samples_data.time_sampling;
1419 next_object = curves;
1421 else if (IFaceSet::matches(header)) {
1424 else if (IPoints::matches(header)) {
1425 IPoints points(parent, header.getName());
1427 unordered_map<std::string, AlembicObject *>::const_iterator iter;
1428 iter = object_map.find(points.getFullName());
1430 if (iter != object_map.end()) {
1431 AlembicObject *abc_object = iter->second;
1432 abc_object->iobject = points;
1433 abc_object->schema_type = AlembicObject::POINTS;
1435 if (matrix_samples_data.samples) {
1436 abc_object->xform_samples = *matrix_samples_data.samples;
1437 abc_object->xform_time_sampling = matrix_samples_data.time_sampling;
1441 next_object = points;
1443 else if (INuPatch::matches(header)) {
1447 next_object = parent.getChild(header.getName());
1449 if (next_object.isInstanceRoot()) {
1450 unordered_map<std::string, AlembicObject *>::const_iterator iter;
1453 iter = object_map.find(next_object.getFullName());
1455 if (iter != object_map.end()) {
1456 AlembicObject *abc_object = iter->second;
1459 iter = object_map.find(next_object.instanceSourcePath());
1461 if (iter != object_map.end()) {
1462 abc_object->iobject = next_object;
1463 abc_object->instance_of = iter->second;
1465 if (matrix_samples_data.samples) {
1466 abc_object->xform_samples = *matrix_samples_data.samples;
1467 abc_object->xform_time_sampling = matrix_samples_data.time_sampling;
1474 if (next_object.valid()) {
1475 for (
size_t i = 0; i < next_object.getNumChildren(); ++i) {
1477 next_object, next_object.getChildHeader(i), matrix_samples_data, object_map, progress);
1482void AlembicProcedural::build_caches(
Progress &progress)
1484 size_t memory_used = 0;
1486 for (
Node *node : objects) {
1487 AlembicObject *
object =
static_cast<AlembicObject *
>(node);
1493 if (object->schema_type == AlembicObject::POLY_MESH) {
1494 if (!object->has_data_loaded()) {
1495 IPolyMesh polymesh(object->iobject, Alembic::Abc::kWrapExisting);
1496 IPolyMeshSchema schema = polymesh.getSchema();
1497 object->load_data_in_cache(object->get_cached_data(),
this, schema, progress);
1499 else if (object->need_shader_update) {
1500 IPolyMesh polymesh(object->iobject, Alembic::Abc::kWrapExisting);
1501 IPolyMeshSchema schema = polymesh.getSchema();
1502 read_attributes(
this,
1503 object->get_cached_data(),
1505 schema.getUVsParam(),
1506 object->get_requested_attributes(),
1510 else if (object->schema_type == AlembicObject::CURVES) {
1511 if (!object->has_data_loaded() || default_radius_is_modified() ||
1512 object->radius_scale_is_modified())
1514 ICurves curves(object->iobject, Alembic::Abc::kWrapExisting);
1515 ICurvesSchema schema = curves.getSchema();
1516 object->load_data_in_cache(object->get_cached_data(),
this, schema, progress);
1519 else if (object->schema_type == AlembicObject::POINTS) {
1520 if (!object->has_data_loaded() || default_radius_is_modified() ||
1521 object->radius_scale_is_modified())
1523 IPoints points(object->iobject, Alembic::Abc::kWrapExisting);
1524 IPointsSchema schema = points.getSchema();
1525 object->load_data_in_cache(object->get_cached_data(),
this, schema, progress);
1528 else if (object->schema_type == AlembicObject::SUBD) {
1529 if (!object->has_data_loaded()) {
1530 ISubD subd_mesh(object->iobject, Alembic::Abc::kWrapExisting);
1531 ISubDSchema schema = subd_mesh.getSchema();
1532 object->load_data_in_cache(object->get_cached_data(),
this, schema, progress);
1534 else if (object->need_shader_update) {
1535 ISubD subd_mesh(object->iobject, Alembic::Abc::kWrapExisting);
1536 ISubDSchema schema = subd_mesh.getSchema();
1537 read_attributes(
this,
1538 object->get_cached_data(),
1540 schema.getUVsParam(),
1541 object->get_requested_attributes(),
1546 if (scale_is_modified() || object->get_cached_data().transforms.size() == 0) {
1547 object->setup_transform_cache(object->get_cached_data(), scale);
1550 memory_used +=
object->get_cached_data().memory_used();
1553 if (memory_used > get_prefetch_cache_size_in_bytes()) {
1554 progress.
set_error(
"Error: Alembic Procedural memory limit reached");
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
vector< AttributeRequest > requests
Attribute * add(ustring name, TypeDesc type, AttributeElement element)
list< Attribute > attributes
void remove(ustring name)
void tag_update(Scene *scene, bool rebuild)
void set_error(const string &error_message_)
bool need_update_geometry() const
AttributeRequestSet attributes
void push_back_reserved(const T &t)
void reserve(size_t newcapacity)
#define CCL_NAMESPACE_END
smooth(Type::VEC3, "P") .flat(Type out_color storage_buf(0, Qualifier::READ, "Surfel", "surfels_buf[]") .push_constant(Type smooth(Type::VEC4, "interp_color")
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
#define SOCKET_NODE_ARRAY(name, ui_name, node_type,...)
#define SOCKET_FLOAT(name, ui_name, default_value,...)
#define SOCKET_INT(name, ui_name, default_value,...)
#define NODE_DEFINE(structname)
#define SOCKET_BOOLEAN(name, ui_name, default_value,...)
#define SOCKET_STRING_ARRAY(name, ui_name, default_value,...)
#define SOCKET_STRING(name, ui_name, default_value,...)
string string_human_readable_size(size_t size)
AttributeSet subd_attributes
@ SUBDIVISION_CATMULL_CLARK
void set_num_subd_faces(size_t num_subd_faces_)
static NodeType * add(const char *name, CreateFunc create, Type type=NONE, const NodeType *base=NULL)
void set_owner(const NodeOwner *owner_)
ProceduralManager * procedural_manager