Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/geometry_set_instances.cc
| Show First 20 Lines • Show All 218 Lines • ▼ Show 20 Lines | for (const GeometryComponentType component_type : component_types) { | ||||
| r_attributes.add_or_modify(attribute_id, add_info, modify_info); | r_attributes.add_or_modify(attribute_id, add_info, modify_info); | ||||
| return true; | return true; | ||||
| }); | }); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGroup> set_groups, | static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGroup> set_groups) | ||||
| const bool convert_points_to_vertices) | |||||
| { | { | ||||
| int totverts = 0; | int totverts = 0; | ||||
| int totloops = 0; | int totloops = 0; | ||||
| int totedges = 0; | int totedges = 0; | ||||
| int totpolys = 0; | int totpolys = 0; | ||||
| int64_t cd_dirty_vert = 0; | int64_t cd_dirty_vert = 0; | ||||
| int64_t cd_dirty_poly = 0; | int64_t cd_dirty_poly = 0; | ||||
| int64_t cd_dirty_edge = 0; | int64_t cd_dirty_edge = 0; | ||||
| Show All 13 Lines | if (set.has_mesh()) { | ||||
| cd_dirty_poly |= mesh.runtime.cd_dirty_poly; | cd_dirty_poly |= mesh.runtime.cd_dirty_poly; | ||||
| cd_dirty_edge |= mesh.runtime.cd_dirty_edge; | cd_dirty_edge |= mesh.runtime.cd_dirty_edge; | ||||
| cd_dirty_loop |= mesh.runtime.cd_dirty_loop; | cd_dirty_loop |= mesh.runtime.cd_dirty_loop; | ||||
| for (const int slot_index : IndexRange(mesh.totcol)) { | for (const int slot_index : IndexRange(mesh.totcol)) { | ||||
| Material *material = mesh.mat[slot_index]; | Material *material = mesh.mat[slot_index]; | ||||
| materials.add(material); | materials.add(material); | ||||
| } | } | ||||
| } | } | ||||
| if (convert_points_to_vertices && set.has_pointcloud()) { | |||||
| const PointCloud &pointcloud = *set.get_pointcloud_for_read(); | |||||
| totverts += pointcloud.totpoint * tot_transforms; | |||||
| } | |||||
| } | } | ||||
| /* Don't create an empty mesh. */ | /* Don't create an empty mesh. */ | ||||
| if ((totverts + totloops + totedges + totpolys) == 0) { | if ((totverts + totloops + totedges + totpolys) == 0) { | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| Mesh *new_mesh = BKE_mesh_new_nomain(totverts, totedges, 0, totloops, totpolys); | Mesh *new_mesh = BKE_mesh_new_nomain(totverts, totedges, 0, totloops, totpolys); | ||||
| ▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | if (set.has_mesh()) { | ||||
| } | } | ||||
| vert_offset += mesh.totvert; | vert_offset += mesh.totvert; | ||||
| loop_offset += mesh.totloop; | loop_offset += mesh.totloop; | ||||
| edge_offset += mesh.totedge; | edge_offset += mesh.totedge; | ||||
| poly_offset += mesh.totpoly; | poly_offset += mesh.totpoly; | ||||
| } | } | ||||
| } | } | ||||
| const float3 point_normal{0.0f, 0.0f, 1.0f}; | |||||
| short point_normal_short[3]; | |||||
| normal_float_to_short_v3(point_normal_short, point_normal); | |||||
| if (convert_points_to_vertices && set.has_pointcloud()) { | |||||
| const PointCloud &pointcloud = *set.get_pointcloud_for_read(); | |||||
| for (const float4x4 &transform : set_group.transforms) { | |||||
| for (const int i : IndexRange(pointcloud.totpoint)) { | |||||
| MVert &new_vert = new_mesh->mvert[vert_offset + i]; | |||||
| const float3 old_position = pointcloud.co[i]; | |||||
| const float3 new_position = transform * old_position; | |||||
| copy_v3_v3(new_vert.co, new_position); | |||||
| memcpy(&new_vert.no, point_normal_short, sizeof(point_normal_short)); | |||||
| } | |||||
| vert_offset += pointcloud.totpoint; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| /* A possible optimization is to only tag the normals dirty when there are transforms that change | /* A possible optimization is to only tag the normals dirty when there are transforms that change | ||||
| * normals. */ | * normals. */ | ||||
| BKE_mesh_normals_tag_dirty(new_mesh); | BKE_mesh_normals_tag_dirty(new_mesh); | ||||
| return new_mesh; | return new_mesh; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | static CurveEval *join_curve_splines_and_builtin_attributes(Span<GeometryInstanceGroup> set_groups) | ||||
| for (SplinePtr &new_spline : new_splines) { | for (SplinePtr &new_spline : new_splines) { | ||||
| new_curve->add_spline(std::move(new_spline)); | new_curve->add_spline(std::move(new_spline)); | ||||
| } | } | ||||
| new_curve->attributes.reallocate(new_curve->splines().size()); | new_curve->attributes.reallocate(new_curve->splines().size()); | ||||
| return new_curve; | return new_curve; | ||||
| } | } | ||||
| static void join_instance_groups_mesh(Span<GeometryInstanceGroup> set_groups, | static void join_instance_groups_mesh(Span<GeometryInstanceGroup> set_groups, GeometrySet &result) | ||||
| bool convert_points_to_vertices, | |||||
| GeometrySet &result) | |||||
| { | { | ||||
| Mesh *new_mesh = join_mesh_topology_and_builtin_attributes(set_groups, | Mesh *new_mesh = join_mesh_topology_and_builtin_attributes(set_groups); | ||||
| convert_points_to_vertices); | |||||
| if (new_mesh == nullptr) { | if (new_mesh == nullptr) { | ||||
| return; | return; | ||||
| } | } | ||||
| MeshComponent &dst_component = result.get_component_for_write<MeshComponent>(); | MeshComponent &dst_component = result.get_component_for_write<MeshComponent>(); | ||||
| dst_component.replace(new_mesh); | dst_component.replace(new_mesh); | ||||
| Vector<GeometryComponentType> component_types; | |||||
| component_types.append(GEO_COMPONENT_TYPE_MESH); | |||||
| if (convert_points_to_vertices) { | |||||
| component_types.append(GEO_COMPONENT_TYPE_POINT_CLOUD); | |||||
| } | |||||
| /* Don't copy attributes that are stored directly in the mesh data structs. */ | /* Don't copy attributes that are stored directly in the mesh data structs. */ | ||||
| Map<AttributeIDRef, AttributeKind> attributes; | Map<AttributeIDRef, AttributeKind> attributes; | ||||
| geometry_set_gather_instances_attribute_info( | geometry_set_gather_instances_attribute_info( | ||||
| set_groups, | set_groups, | ||||
| component_types, | {GEO_COMPONENT_TYPE_MESH}, | ||||
| {"position", "material_index", "normal", "shade_smooth", "crease"}, | {"position", "material_index", "normal", "shade_smooth", "crease"}, | ||||
| attributes); | attributes); | ||||
| join_attributes( | join_attributes(set_groups, | ||||
| set_groups, component_types, attributes, static_cast<GeometryComponent &>(dst_component)); | {GEO_COMPONENT_TYPE_MESH}, | ||||
| attributes, | |||||
| static_cast<GeometryComponent &>(dst_component)); | |||||
| } | } | ||||
| static void join_instance_groups_pointcloud(Span<GeometryInstanceGroup> set_groups, | static void join_instance_groups_pointcloud(Span<GeometryInstanceGroup> set_groups, | ||||
| GeometrySet &result) | GeometrySet &result) | ||||
| { | { | ||||
| PointCloud *new_pointcloud = join_pointcloud_position_attribute(set_groups); | PointCloud *new_pointcloud = join_pointcloud_position_attribute(set_groups); | ||||
| if (new_pointcloud == nullptr) { | if (new_pointcloud == nullptr) { | ||||
| return; | return; | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | geometry_set_gather_instances_attribute_info( | ||||
| {"position", "radius", "tilt", "handle_left", "handle_right", "cyclic", "resolution"}, | {"position", "radius", "tilt", "handle_left", "handle_right", "cyclic", "resolution"}, | ||||
| attributes); | attributes); | ||||
| join_attributes(set_groups, | join_attributes(set_groups, | ||||
| {GEO_COMPONENT_TYPE_CURVE}, | {GEO_COMPONENT_TYPE_CURVE}, | ||||
| attributes, | attributes, | ||||
| static_cast<GeometryComponent &>(dst_component)); | static_cast<GeometryComponent &>(dst_component)); | ||||
| } | } | ||||
| GeometrySet geometry_set_realize_mesh_for_modifier(const GeometrySet &geometry_set) | |||||
| { | |||||
| if (!geometry_set.has_instances() && !geometry_set.has_pointcloud()) { | |||||
| return geometry_set; | |||||
| } | |||||
| GeometrySet new_geometry_set = geometry_set; | |||||
| Vector<GeometryInstanceGroup> set_groups; | |||||
| geometry_set_gather_instances(geometry_set, set_groups); | |||||
| join_instance_groups_mesh(set_groups, true, new_geometry_set); | |||||
| /* Remove all instances, even though some might contain other non-mesh data. We can't really | |||||
| * keep only non-mesh instances in general. */ | |||||
| new_geometry_set.remove<InstancesComponent>(); | |||||
| /* If there was a point cloud, it is now part of the mesh. */ | |||||
| new_geometry_set.remove<PointCloudComponent>(); | |||||
| return new_geometry_set; | |||||
| } | |||||
| GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set) | GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set) | ||||
| { | { | ||||
| if (!geometry_set.has_instances()) { | if (!geometry_set.has_instances()) { | ||||
| return geometry_set; | return geometry_set; | ||||
| } | } | ||||
| GeometrySet new_geometry_set; | GeometrySet new_geometry_set; | ||||
| Vector<GeometryInstanceGroup> set_groups; | Vector<GeometryInstanceGroup> set_groups; | ||||
| geometry_set_gather_instances(geometry_set, set_groups); | geometry_set_gather_instances(geometry_set, set_groups); | ||||
| join_instance_groups_mesh(set_groups, false, new_geometry_set); | join_instance_groups_mesh(set_groups, new_geometry_set); | ||||
| join_instance_groups_pointcloud(set_groups, new_geometry_set); | join_instance_groups_pointcloud(set_groups, new_geometry_set); | ||||
| join_instance_groups_volume(set_groups, new_geometry_set); | join_instance_groups_volume(set_groups, new_geometry_set); | ||||
| join_instance_groups_curve(set_groups, new_geometry_set); | join_instance_groups_curve(set_groups, new_geometry_set); | ||||
| return new_geometry_set; | return new_geometry_set; | ||||
| } | } | ||||
| } // namespace blender::bke | } // namespace blender::bke | ||||
| ▲ Show 20 Lines • Show All 88 Lines • Show Last 20 Lines | |||||