diff options
Diffstat (limited to 'intern/cycles/render/alembic.cpp')
-rw-r--r-- | intern/cycles/render/alembic.cpp | 310 |
1 files changed, 188 insertions, 122 deletions
diff --git a/intern/cycles/render/alembic.cpp b/intern/cycles/render/alembic.cpp index 468ebf7140f..0841a3c09cd 100644 --- a/intern/cycles/render/alembic.cpp +++ b/intern/cycles/render/alembic.cpp @@ -402,16 +402,16 @@ static void add_uvs(AlembicProcedural *proc, } const ISampleSelector iss = ISampleSelector(time); - const IV2fGeomParam::Sample sample = uvs.getExpandedValue(iss); - const IV2fGeomParam::Sample uvsample = uvs.getIndexedValue(iss); if (!uvsample.valid()) { continue; } - const array<int3> *triangles = cached_data.triangles.data_for_time_no_check(time); - const array<int3> *triangles_loops = cached_data.triangles_loops.data_for_time_no_check(time); + const array<int3> *triangles = + cached_data.triangles.data_for_time_no_check(time).get_data_or_null(); + const array<int3> *triangles_loops = + cached_data.triangles_loops.data_for_time_no_check(time).get_data_or_null(); if (!triangles || !triangles_loops) { continue; @@ -458,7 +458,8 @@ static void add_normals(const Int32ArraySamplePtr face_indices, *normals.getTimeSampling()); attr.std = ATTR_STD_VERTEX_NORMAL; - const array<float3> *vertices = cached_data.vertices.data_for_time_no_check(time); + const array<float3> *vertices = + cached_data.vertices.data_for_time_no_check(time).get_data_or_null(); if (!vertices) { return; @@ -493,7 +494,8 @@ static void add_normals(const Int32ArraySamplePtr face_indices, *normals.getTimeSampling()); attr.std = ATTR_STD_VERTEX_NORMAL; - const array<float3> *vertices = cached_data.vertices.data_for_time_no_check(time); + const array<float3> *vertices = + cached_data.vertices.data_for_time_no_check(time).get_data_or_null(); if (!vertices) { return; @@ -717,11 +719,15 @@ void AlembicObject::read_face_sets(SchemaType &schema, void AlembicObject::load_all_data(AlembicProcedural *proc, IPolyMeshSchema &schema, - float scale, Progress &progress) { cached_data.clear(); + /* Only load data for the original Geometry. */ + if (instance_of) { + return; + } + const TimeSamplingPtr time_sampling = schema.getTimeSampling(); cached_data.set_time_sampling(*time_sampling); @@ -780,22 +786,18 @@ void AlembicObject::load_all_data(AlembicProcedural *proc, add_uvs(proc, uvs, cached_data, progress); } - if (progress.get_cancel()) { - return; - } - - setup_transform_cache(scale); - data_loaded = true; } -void AlembicObject::load_all_data(AlembicProcedural *proc, - ISubDSchema &schema, - float scale, - Progress &progress) +void AlembicObject::load_all_data(AlembicProcedural *proc, ISubDSchema &schema, Progress &progress) { cached_data.clear(); + /* Only load data for the original Geometry. */ + if (instance_of) { + return; + } + AttributeRequestSet requested_attributes = get_requested_attributes(); const TimeSamplingPtr time_sampling = schema.getTimeSampling(); @@ -920,19 +922,21 @@ void AlembicObject::load_all_data(AlembicProcedural *proc, return; } - setup_transform_cache(scale); - data_loaded = true; } void AlembicObject::load_all_data(AlembicProcedural *proc, const ICurvesSchema &schema, - float scale, Progress &progress, float default_radius) { cached_data.clear(); + /* Only load data for the original Geometry. */ + if (instance_of) { + return; + } + const TimeSamplingPtr time_sampling = schema.getTimeSampling(); cached_data.set_time_sampling(*time_sampling); @@ -1007,8 +1011,6 @@ void AlembicObject::load_all_data(AlembicProcedural *proc, // TODO(@kevindietrich): attributes, need example files - setup_transform_cache(scale); - data_loaded = true; } @@ -1017,6 +1019,10 @@ void AlembicObject::setup_transform_cache(float scale) cached_data.transforms.clear(); cached_data.transforms.invalidate_last_loaded_time(); + if (scale == 0.0f) { + scale = 1.0f; + } + if (xform_time_sampling) { cached_data.transforms.set_time_sampling(*xform_time_sampling); } @@ -1107,9 +1113,10 @@ void AlembicObject::read_attribute(const ICompoundProperty &arb_geom_params, attribute.element = ATTR_ELEMENT_CORNER; attribute.type_desc = TypeFloat2; - const array<int3> *triangles = cached_data.triangles.data_for_time_no_check(time); - const array<int3> *triangles_loops = cached_data.triangles_loops.data_for_time_no_check( - time); + const array<int3> *triangles = + cached_data.triangles.data_for_time_no_check(time).get_data_or_null(); + const array<int3> *triangles_loops = + cached_data.triangles_loops.data_for_time_no_check(time).get_data_or_null(); if (!triangles || !triangles_loops) { return; @@ -1162,7 +1169,8 @@ void AlembicObject::read_attribute(const ICompoundProperty &arb_geom_params, attribute.element = ATTR_ELEMENT_CORNER_BYTE; attribute.type_desc = TypeRGBA; - const array<int3> *triangles = cached_data.triangles.data_for_time_no_check(time); + const array<int3> *triangles = + cached_data.triangles.data_for_time_no_check(time).get_data_or_null(); if (!triangles) { return; @@ -1218,7 +1226,8 @@ void AlembicObject::read_attribute(const ICompoundProperty &arb_geom_params, attribute.element = ATTR_ELEMENT_CORNER_BYTE; attribute.type_desc = TypeRGBA; - const array<int3> *triangles = cached_data.triangles.data_for_time_no_check(time); + const array<int3> *triangles = + cached_data.triangles.data_for_time_no_check(time).get_data_or_null(); if (!triangles) { return; @@ -1257,7 +1266,7 @@ static void update_attributes(AttributeSet &attributes, CachedData &cached_data, set<Attribute *> cached_attributes; for (CachedData::CachedAttribute &attribute : cached_data.attributes) { - const array<char> *attr_data = attribute.data.data_for_time(frame_time); + const array<char> *attr_data = attribute.data.data_for_time(frame_time).get_data_or_null(); Attribute *attr = nullptr; if (attribute.std != ATTR_STD_NONE) { @@ -1282,6 +1291,7 @@ static void update_attributes(AttributeSet &attributes, CachedData &cached_data, } memcpy(attr->data(), attr_data->data(), attr_data->size()); + attr->modified = true; } /* remove any attributes not in cached_attributes */ @@ -1289,6 +1299,7 @@ static void update_attributes(AttributeSet &attributes, CachedData &cached_data, for (it = attributes.attributes.begin(); it != attributes.attributes.end();) { if (cached_attributes.find(&(*it)) == cached_attributes.end()) { attributes.attributes.erase(it++); + attributes.modified = true; continue; } @@ -1406,6 +1417,8 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress) const chrono_t frame_time = (chrono_t)((frame - frame_offset) / frame_rate); + build_caches(progress); + foreach (Node *node, objects) { AlembicObject *object = static_cast<AlembicObject *>(node); @@ -1414,19 +1427,19 @@ void AlembicProcedural::generate(Scene *scene, Progress &progress) } /* skip constant objects */ - if (object->has_data_loaded() && object->is_constant() && !object->is_modified() && - !object->need_shader_update && !scale_is_modified()) { + if (object->is_constant() && !object->is_modified() && !object->need_shader_update && + !scale_is_modified()) { continue; } if (object->schema_type == AlembicObject::POLY_MESH) { - read_mesh(object, frame_time, progress); + read_mesh(object, frame_time); } else if (object->schema_type == AlembicObject::CURVES) { - read_curves(object, frame_time, progress); + read_curves(object, frame_time); } else if (object->schema_type == AlembicObject::SUBD) { - read_subd(object, frame_time, progress); + read_subd(object, frame_time); } object->clear_modified(); @@ -1489,22 +1502,24 @@ void AlembicProcedural::load_objects(Progress &progress) Geometry *geometry = nullptr; - if (abc_object->schema_type == AlembicObject::CURVES) { - geometry = scene_->create_node<Hair>(); - } - else if (abc_object->schema_type == AlembicObject::POLY_MESH || - abc_object->schema_type == AlembicObject::SUBD) { - geometry = scene_->create_node<Mesh>(); - } - else { - continue; - } + if (!abc_object->instance_of) { + if (abc_object->schema_type == AlembicObject::CURVES) { + geometry = scene_->create_node<Hair>(); + } + else if (abc_object->schema_type == AlembicObject::POLY_MESH || + abc_object->schema_type == AlembicObject::SUBD) { + geometry = scene_->create_node<Mesh>(); + } + else { + continue; + } - geometry->set_owner(this); - geometry->name = abc_object->iobject.getName(); + geometry->set_owner(this); + geometry->name = abc_object->iobject.getName(); - array<Node *> used_shaders = abc_object->get_used_shaders(); - geometry->set_used_shaders(used_shaders); + array<Node *> used_shaders = abc_object->get_used_shaders(); + geometry->set_used_shaders(used_shaders); + } Object *object = scene_->create_node<Object>(); object->set_owner(this); @@ -1513,31 +1528,22 @@ void AlembicProcedural::load_objects(Progress &progress) abc_object->set_object(object); } -} -void AlembicProcedural::read_mesh(AlembicObject *abc_object, - Abc::chrono_t frame_time, - Progress &progress) -{ - IPolyMesh polymesh(abc_object->iobject, Alembic::Abc::kWrapExisting); - - Mesh *mesh = static_cast<Mesh *>(abc_object->get_object()->get_geometry()); - - CachedData &cached_data = abc_object->get_cached_data(); - IPolyMeshSchema schema = polymesh.getSchema(); - - if (!abc_object->has_data_loaded()) { - abc_object->load_all_data(this, schema, scale, progress); - } - else { - if (abc_object->need_shader_update) { - abc_object->update_shader_attributes(schema.getArbGeomParams(), progress); - } + /* Share geometries between instances. */ + foreach (Node *node, objects) { + AlembicObject *abc_object = static_cast<AlembicObject *>(node); - if (scale_is_modified()) { - abc_object->setup_transform_cache(scale); + if (abc_object->instance_of) { + abc_object->get_object()->set_geometry( + abc_object->instance_of->get_object()->get_geometry()); + abc_object->schema_type = abc_object->instance_of->schema_type; } } +} + +void AlembicProcedural::read_mesh(AlembicObject *abc_object, Abc::chrono_t frame_time) +{ + CachedData &cached_data = abc_object->get_cached_data(); /* update sockets */ @@ -1548,11 +1554,18 @@ void AlembicProcedural::read_mesh(AlembicObject *abc_object, object->tag_update(scene_); } + /* Only update sockets for the original Geometry. */ + if (abc_object->instance_of) { + return; + } + + Mesh *mesh = static_cast<Mesh *>(object->get_geometry()); + cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket()); cached_data.shader.copy_to_socket(frame_time, mesh, mesh->get_shader_socket()); - array<int3> *triangle_data = cached_data.triangles.data_for_time(frame_time); + array<int3> *triangle_data = cached_data.triangles.data_for_time(frame_time).get_data_or_null(); if (triangle_data) { array<int> triangles; array<bool> smooth; @@ -1590,41 +1603,31 @@ void AlembicProcedural::read_mesh(AlembicObject *abc_object, } } -void AlembicProcedural::read_subd(AlembicObject *abc_object, - Abc::chrono_t frame_time, - Progress &progress) +void AlembicProcedural::read_subd(AlembicObject *abc_object, Abc::chrono_t frame_time) { - ISubD subd_mesh(abc_object->iobject, Alembic::Abc::kWrapExisting); - ISubDSchema schema = subd_mesh.getSchema(); - - Mesh *mesh = static_cast<Mesh *>(abc_object->get_object()->get_geometry()); - - /* Alembic is OpenSubDiv compliant, there is no option to set another subdivision type. */ - mesh->set_subdivision_type(Mesh::SubdivisionType::SUBDIVISION_CATMULL_CLARK); + CachedData &cached_data = abc_object->get_cached_data(); - if (!abc_object->has_data_loaded()) { - abc_object->load_all_data(this, schema, scale, progress); + if (abc_object->subd_max_level_is_modified() || abc_object->subd_dicing_rate_is_modified()) { + /* need to reset the current data is something changed */ + cached_data.invalidate_last_loaded_time(); } - else { - if (abc_object->need_shader_update) { - abc_object->update_shader_attributes(schema.getArbGeomParams(), progress); - } - if (scale_is_modified()) { - abc_object->setup_transform_cache(scale); - } - } + /* Update sockets. */ - mesh->set_subd_max_level(abc_object->get_subd_max_level()); - mesh->set_subd_dicing_rate(abc_object->get_subd_dicing_rate()); + Object *object = abc_object->get_object(); + cached_data.transforms.copy_to_socket(frame_time, object, object->get_tfm_socket()); - CachedData &cached_data = abc_object->get_cached_data(); + if (object->is_modified()) { + object->tag_update(scene_); + } - if (abc_object->subd_max_level_is_modified() || abc_object->subd_dicing_rate_is_modified()) { - /* need to reset the current data is something changed */ - cached_data.invalidate_last_loaded_time(); + /* Only update sockets for the original Geometry. */ + if (abc_object->instance_of) { + return; } + Mesh *mesh = static_cast<Mesh *>(object->get_geometry()); + /* Cycles overwrites the original triangles when computing displacement, so we always have to * repass the data if something is animated (vertices most likely) to avoid buffer overflows. */ if (!cached_data.is_constant()) { @@ -1637,14 +1640,10 @@ void AlembicProcedural::read_subd(AlembicObject *abc_object, mesh->clear_non_sockets(); - /* Update sockets. */ - - Object *object = abc_object->get_object(); - cached_data.transforms.copy_to_socket(frame_time, object, object->get_tfm_socket()); - - if (object->is_modified()) { - object->tag_update(scene_); - } + /* Alembic is OpenSubDiv compliant, there is no option to set another subdivision type. */ + mesh->set_subdivision_type(Mesh::SubdivisionType::SUBDIVISION_CATMULL_CLARK); + mesh->set_subd_max_level(abc_object->get_subd_max_level()); + mesh->set_subd_dicing_rate(abc_object->get_subd_dicing_rate()); cached_data.vertices.copy_to_socket(frame_time, mesh, mesh->get_verts_socket()); @@ -1699,25 +1698,8 @@ void AlembicProcedural::read_subd(AlembicObject *abc_object, } } -void AlembicProcedural::read_curves(AlembicObject *abc_object, - Abc::chrono_t frame_time, - Progress &progress) +void AlembicProcedural::read_curves(AlembicObject *abc_object, Abc::chrono_t frame_time) { - ICurves curves(abc_object->iobject, Alembic::Abc::kWrapExisting); - Hair *hair = static_cast<Hair *>(abc_object->get_object()->get_geometry()); - - ICurvesSchema schema = curves.getSchema(); - - if (!abc_object->has_data_loaded() || default_radius_is_modified() || - abc_object->radius_scale_is_modified()) { - abc_object->load_all_data(this, schema, scale, progress, default_radius); - } - else { - if (scale_is_modified()) { - abc_object->setup_transform_cache(scale); - } - } - CachedData &cached_data = abc_object->get_cached_data(); /* update sockets */ @@ -1729,6 +1711,13 @@ void AlembicProcedural::read_curves(AlembicObject *abc_object, object->tag_update(scene_); } + /* Only update sockets for the original Geometry. */ + if (abc_object->instance_of) { + return; + } + + Hair *hair = static_cast<Hair *>(object->get_geometry()); + cached_data.curve_keys.copy_to_socket(frame_time, hair, hair->get_curve_keys_socket()); cached_data.curve_radius.copy_to_socket(frame_time, hair, hair->get_curve_radius_socket()); @@ -1867,9 +1856,38 @@ void AlembicProcedural::walk_hierarchy( else if (IFaceSet::matches(header)) { // ignore the face set, it will be read along with the data } + else if (IPoints::matches(header)) { + // unsupported for now + } + else if (INuPatch::matches(header)) { + // unsupported for now + } else { - // unsupported type for now (Points, NuPatch) next_object = parent.getChild(header.getName()); + + if (next_object.isInstanceRoot()) { + unordered_map<std::string, AlembicObject *>::const_iterator iter; + + /* Was this object asked to be rendered? */ + iter = object_map.find(next_object.getFullName()); + + if (iter != object_map.end()) { + AlembicObject *abc_object = iter->second; + + /* Only try to render an instance if the original object is also rendered. */ + iter = object_map.find(next_object.instanceSourcePath()); + + if (iter != object_map.end()) { + abc_object->iobject = next_object; + abc_object->instance_of = iter->second; + + if (matrix_samples_data.samples) { + abc_object->xform_samples = *matrix_samples_data.samples; + abc_object->xform_time_sampling = matrix_samples_data.time_sampling; + } + } + } + } } if (next_object.valid()) { @@ -1880,6 +1898,54 @@ void AlembicProcedural::walk_hierarchy( } } +void AlembicProcedural::build_caches(Progress &progress) +{ + for (Node *node : objects) { + AlembicObject *object = static_cast<AlembicObject *>(node); + + if (progress.get_cancel()) { + return; + } + + if (object->schema_type == AlembicObject::POLY_MESH) { + if (!object->has_data_loaded()) { + IPolyMesh polymesh(object->iobject, Alembic::Abc::kWrapExisting); + IPolyMeshSchema schema = polymesh.getSchema(); + object->load_all_data(this, schema, progress); + } + else if (object->need_shader_update) { + IPolyMesh polymesh(object->iobject, Alembic::Abc::kWrapExisting); + IPolyMeshSchema schema = polymesh.getSchema(); + object->update_shader_attributes(schema.getArbGeomParams(), progress); + } + } + else if (object->schema_type == AlembicObject::CURVES) { + if (!object->has_data_loaded() || default_radius_is_modified() || + object->radius_scale_is_modified()) { + ICurves curves(object->iobject, Alembic::Abc::kWrapExisting); + ICurvesSchema schema = curves.getSchema(); + object->load_all_data(this, schema, progress, default_radius); + } + } + else if (object->schema_type == AlembicObject::SUBD) { + if (!object->has_data_loaded()) { + ISubD subd_mesh(object->iobject, Alembic::Abc::kWrapExisting); + ISubDSchema schema = subd_mesh.getSchema(); + object->load_all_data(this, schema, progress); + } + else if (object->need_shader_update) { + ISubD subd_mesh(object->iobject, Alembic::Abc::kWrapExisting); + ISubDSchema schema = subd_mesh.getSchema(); + object->update_shader_attributes(schema.getArbGeomParams(), progress); + } + } + + if (scale_is_modified() || object->get_cached_data().transforms.size() == 0) { + object->setup_transform_cache(scale); + } + } +} + CCL_NAMESPACE_END #endif |