diff --git a/source/blender/blenkernel/intern/curves_attributes.cc b/source/blender/blenkernel/intern/curves_attributes.cc index 66c8aff14c4..0af8e45fb74 100644 --- a/source/blender/blenkernel/intern/curves_attributes.cc +++ b/source/blender/blenkernel/intern/curves_attributes.cc @@ -189,9 +189,6 @@ static const auto &builtin_attributes() AttrBuiltinInfo radius(AttrDomain::Point, AttrType::Float); map.add_new("radius", std::move(radius)); - AttrBuiltinInfo id(AttrDomain::Point, AttrType::Int32); - map.add_new("id", std::move(id)); - AttrBuiltinInfo tilt(AttrDomain::Point, AttrType::Float); map.add_new("tilt", std::move(tilt)); diff --git a/source/blender/blenkernel/intern/instances_attributes.cc b/source/blender/blenkernel/intern/instances_attributes.cc index 4e9294d4092..817ff89dfbb 100644 --- a/source/blender/blenkernel/intern/instances_attributes.cc +++ b/source/blender/blenkernel/intern/instances_attributes.cc @@ -28,15 +28,6 @@ static const auto &builtin_attributes() static auto attributes = []() { Map map; - /** - * IDs of the instances. They are used for consistency over multiple frames for things like - * motion blur. Proper stable ID data that actually helps when rendering can only be generated - * in some situations, so this vector is allowed to be empty, in which case the index of each - * instance will be used for the final ID. - */ - AttrBuiltinInfo id(bke::AttrDomain::Instance, bke::AttrType::Int32); - map.add_new("id", std::move(id)); - AttrBuiltinInfo instance_transform(bke::AttrDomain::Instance, bke::AttrType::Float4x4); instance_transform.deletable = false; map.add_new("instance_transform", std::move(instance_transform)); diff --git a/source/blender/blenkernel/intern/mesh_attributes.cc b/source/blender/blenkernel/intern/mesh_attributes.cc index 6c7ec49768e..bf1a51fed1e 100644 --- a/source/blender/blenkernel/intern/mesh_attributes.cc +++ b/source/blender/blenkernel/intern/mesh_attributes.cc @@ -878,13 +878,6 @@ static GeometryAttributeProviders create_attribute_providers_for_mesh() point_access, tag_component_positions_changed); - static BuiltinCustomDataLayerProvider id("id", - AttrDomain::Point, - CD_PROP_INT32, - BuiltinAttributeProvider::Deletable, - point_access, - nullptr); - static const auto material_index_clamp = mf::build::SI1_SO( "Material Index Validate", [](int value) { @@ -957,7 +950,6 @@ static GeometryAttributeProviders create_attribute_providers_for_mesh() &edge_verts, &corner_vert, &corner_edge, - &id, &material_index, &sharp_face, &sharp_edge}, diff --git a/source/blender/geometry/intern/mix_geometries.cc b/source/blender/geometry/intern/mix_geometries.cc index ecd5a046f78..095c0773d07 100644 --- a/source/blender/geometry/intern/mix_geometries.cc +++ b/source/blender/geometry/intern/mix_geometries.cc @@ -125,19 +125,26 @@ static Map create_value_to_first_index_map(const Span values) } static Array create_id_index_map(const bke::AttributeAccessor attributes_a, - const bke::AttributeAccessor b_attributes) + const bke::AttributeAccessor b_attributes, + const bke::AttrDomain id_domain) { - const bke::AttributeReader ids_a = attributes_a.lookup("id"); - const bke::AttributeReader ids_b = b_attributes.lookup("id"); + const bke::GAttributeReader ids_a = attributes_a.lookup("id"); + const bke::GAttributeReader ids_b = b_attributes.lookup("id"); if (!ids_a || !ids_b) { return {}; } + if (!ids_a.varray.type().is() || !ids_b.varray.type().is()) { + return {}; + } + if (ids_a.domain != id_domain || ids_b.domain != id_domain) { + return {}; + } if (sharing_info_equal(ids_a.sharing_info, ids_b.sharing_info)) { return {}; } - const VArraySpan ids_span_a(*ids_a); - const VArraySpan ids_span_b(*ids_b); + const VArraySpan ids_span_a(ids_a.varray.typed()); + const VArraySpan ids_span_b(ids_b.varray.typed()); const Map id_map_b = create_value_to_first_index_map(ids_span_b); Array index_map(ids_span_a.size()); @@ -153,7 +160,8 @@ bke::GeometrySet mix_geometries(bke::GeometrySet a, const bke::GeometrySet &b, c { if (Mesh *mesh_a = a.get_mesh_for_write()) { if (const Mesh *mesh_b = b.get_mesh()) { - Array vert_map = create_id_index_map(mesh_a->attributes(), mesh_b->attributes()); + Array vert_map = create_id_index_map( + mesh_a->attributes(), mesh_b->attributes(), bke::AttrDomain::Point); mix_attributes(mesh_a->attributes_for_write(), mesh_b->attributes(), vert_map, @@ -164,8 +172,8 @@ bke::GeometrySet mix_geometries(bke::GeometrySet a, const bke::GeometrySet &b, c } if (PointCloud *points_a = a.get_pointcloud_for_write()) { if (const PointCloud *points_b = b.get_pointcloud()) { - const Array index_map = create_id_index_map(points_a->attributes(), - points_b->attributes()); + const Array index_map = create_id_index_map( + points_a->attributes(), points_b->attributes(), bke::AttrDomain::Point); mix_attributes(points_a->attributes_for_write(), points_b->attributes(), index_map, @@ -177,7 +185,7 @@ bke::GeometrySet mix_geometries(bke::GeometrySet a, const bke::GeometrySet &b, c if (const Curves *curves_b = b.get_curves()) { bke::MutableAttributeAccessor a = curves_a->geometry.wrap().attributes_for_write(); const bke::AttributeAccessor b = curves_b->geometry.wrap().attributes(); - const Array index_map = create_id_index_map(a, b); + const Array index_map = create_id_index_map(a, b, bke::AttrDomain::Point); mix_attributes( a, b, @@ -189,8 +197,8 @@ bke::GeometrySet mix_geometries(bke::GeometrySet a, const bke::GeometrySet &b, c } if (bke::Instances *instances_a = a.get_instances_for_write()) { if (const bke::Instances *instances_b = b.get_instances()) { - const Array index_map = create_id_index_map(instances_a->attributes(), - instances_b->attributes()); + const Array index_map = create_id_index_map( + instances_a->attributes(), instances_b->attributes(), bke::AttrDomain::Instance); mix_attributes(instances_a->attributes_for_write(), instances_b->attributes(), index_map, diff --git a/source/blender/geometry/intern/point_merge_by_distance.cc b/source/blender/geometry/intern/point_merge_by_distance.cc index 52da7ee7122..89c82e15b04 100644 --- a/source/blender/geometry/intern/point_merge_by_distance.cc +++ b/source/blender/geometry/intern/point_merge_by_distance.cc @@ -106,8 +106,11 @@ PointCloud *point_merge_by_distance(const PointCloud &src_points, Set attribute_ids = src_attributes.all_ids(); /* Transfer the ID attribute if it exists, using the ID of the first merged point. */ - if (attribute_ids.contains("id")) { - VArraySpan src = *src_attributes.lookup_or_default("id", bke::AttrDomain::Point, 0); + bke::GAttributeReader src_id_attribute = src_attributes.lookup("id"); + if (src_id_attribute && src_id_attribute.domain == bke::AttrDomain::Point && + src_id_attribute.varray.type().is()) + { + VArraySpan src = src_id_attribute.varray.typed(); bke::SpanAttributeWriter dst = dst_attributes.lookup_or_add_for_write_only_span( "id", bke::AttrDomain::Point); diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 760cc954e47..9f78aa1fff5 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -610,9 +610,11 @@ static void gather_realize_tasks_for_instances(GatherTasksInfo &gather_info, Span stored_instance_ids; if (gather_info.create_id_attribute_on_any_component) { - bke::AttributeReader ids = instances.attributes().lookup("id"); - if (ids) { - stored_instance_ids = ids.varray.get_internal_span(); + bke::GAttributeReader ids = instances.attributes().lookup("id"); + if (ids && ids.domain == bke::AttrDomain::Instance && ids.varray.type().is() && + ids.varray.is_span()) + { + stored_instance_ids = ids.varray.get_internal_span().typed(); } } @@ -1184,7 +1186,9 @@ static AllPointCloudsInfo preprocess_pointclouds(const bke::GeometrySet &geometr } if (info.create_id_attribute) { bke::GAttributeReader ids_attribute = attributes.lookup("id"); - if (ids_attribute) { + if (ids_attribute && ids_attribute.domain == bke::AttrDomain::Point && + ids_attribute.varray.type().is() && ids_attribute.varray.is_span()) + { pointcloud_info.stored_ids = ids_attribute.varray.get_internal_span().typed(); } } @@ -1464,7 +1468,9 @@ static AllMeshesInfo preprocess_meshes(const bke::GeometrySet &geometry_set, } if (info.create_id_attribute) { bke::GAttributeReader ids_attribute = attributes.lookup("id"); - if (ids_attribute) { + if (ids_attribute && ids_attribute.domain == bke::AttrDomain::Point && + ids_attribute.varray.type().is() && ids_attribute.varray.is_span()) + { mesh_info.stored_vertex_ids = ids_attribute.varray.get_internal_span().typed(); } } @@ -1915,7 +1921,9 @@ static AllCurvesInfo preprocess_curves(const bke::GeometrySet &geometry_set, } if (info.create_id_attribute) { bke::GAttributeReader id_attribute = attributes.lookup("id"); - if (id_attribute) { + if (id_attribute && id_attribute.domain == bke::AttrDomain::Point && + id_attribute.varray.type().is() && id_attribute.varray.is_span()) + { curve_info.stored_ids = id_attribute.varray.get_internal_span().typed(); } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc index c79204dba55..af2bd6dc569 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_duplicate_elements.cc @@ -138,6 +138,12 @@ static void copy_stable_id_point(const OffsetIndices offsets, if (!src_attribute) { return; } + if (!ELEM(src_attribute.domain, AttrDomain::Point, AttrDomain::Instance)) { + return; + } + if (!src_attribute.varray.type().is()) { + return; + } SpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span( "id", AttrDomain::Point); if (!dst_attribute) { @@ -217,6 +223,13 @@ static void copy_stable_id_curves(const bke::CurvesGeometry &src_curves, if (!src_attribute) { return; } + if (src_attribute.domain != AttrDomain::Point) { + return; + } + if (!src_attribute.varray.type().is()) { + return; + } + SpanAttributeWriter dst_attribute = dst_curves.attributes_for_write().lookup_or_add_for_write_only_span("id", AttrDomain::Point); @@ -426,6 +439,12 @@ static void copy_stable_id_faces(const Mesh &mesh, if (!src_attribute) { return; } + if (src_attribute.domain != AttrDomain::Point) { + return; + } + if (!src_attribute.varray.type().is()) { + return; + } SpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span( "id", AttrDomain::Point); if (!dst_attribute) { @@ -617,6 +636,12 @@ static void copy_stable_id_edges(const Mesh &mesh, if (!src_attribute) { return; } + if (src_attribute.domain != AttrDomain::Point) { + return; + } + if (!src_attribute.varray.type().is()) { + return; + } SpanAttributeWriter dst_attribute = dst_attributes.lookup_or_add_for_write_only_span( "id", AttrDomain::Point); if (!dst_attribute) { diff --git a/source/blender/nodes/geometry/nodes/node_geo_set_id.cc b/source/blender/nodes/geometry/nodes/node_geo_set_id.cc index af53bc6e643..85008fdfcef 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_set_id.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_set_id.cc @@ -36,22 +36,26 @@ static void set_id_in_component(GeometryComponent &component, /* Since adding the ID attribute can change the result of the field evaluation (the random value * node uses the index if the ID is unavailable), make sure that it isn't added before evaluating * the field. However, as an optimization, use a faster code path when it already exists. */ - if (attributes.contains("id")) { - AttributeWriter id_attribute = attributes.lookup_or_add_for_write("id", domain); - evaluator.add_with_destination(id_field, id_attribute.varray); - evaluator.evaluate(); - id_attribute.finish(); - } - else { - evaluator.add(id_field); - evaluator.evaluate(); - const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); - const VArray result_ids = evaluator.get_evaluated(0); - SpanAttributeWriter id_attribute = attributes.lookup_or_add_for_write_span("id", - domain); - result_ids.materialize(selection, id_attribute.span); - id_attribute.finish(); + if (const std::optional meta_data = attributes.lookup_meta_data("id")) { + if (meta_data->domain == domain && meta_data->data_type == bke::AttrType::Int32) { + AttributeWriter id_attribute = attributes.lookup_or_add_for_write("id", domain); + evaluator.add_with_destination(id_field, id_attribute.varray); + evaluator.evaluate(); + id_attribute.finish(); + return; + } + /* There is an ID attribute, but it has the wrong type, so remove it so that it can be + * recreated below. */ + attributes.remove("id"); } + evaluator.add(id_field); + evaluator.evaluate(); + const IndexMask selection = evaluator.get_evaluated_selection_as_mask(); + const VArray result_ids = evaluator.get_evaluated(0); + SpanAttributeWriter id_attribute = attributes.lookup_or_add_for_write_span("id", + domain); + result_ids.materialize(selection, id_attribute.span); + id_attribute.finish(); } static void node_geo_exec(GeoNodeExecParams params)