Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_dual_mesh.cc
| Show First 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | |||||
| * | * | ||||
| * Some special cases are needed for boundaries and non-manifold geometry. | * Some special cases are needed for boundaries and non-manifold geometry. | ||||
| */ | */ | ||||
| static void calc_dual_mesh(GeometrySet &geometry_set, | static void calc_dual_mesh(GeometrySet &geometry_set, | ||||
| const MeshComponent &in_component, | const MeshComponent &in_component, | ||||
| const bool keep_boundaries) | const bool keep_boundaries) | ||||
| { | { | ||||
| const Mesh &mesh_in = *in_component.get_for_read(); | const Mesh &mesh_in = *in_component.get_for_read(); | ||||
| const Span<MVert> src_verts = mesh_in.verts(); | const Span<float3> src_positions = mesh_in.positions(); | ||||
| const Span<MEdge> src_edges = mesh_in.edges(); | const Span<MEdge> src_edges = mesh_in.edges(); | ||||
| const Span<MPoly> src_polys = mesh_in.polys(); | const Span<MPoly> src_polys = mesh_in.polys(); | ||||
| const Span<MLoop> src_loops = mesh_in.loops(); | const Span<MLoop> src_loops = mesh_in.loops(); | ||||
| Map<AttributeIDRef, AttributeKind> attributes; | Map<AttributeIDRef, AttributeKind> attributes; | ||||
| geometry_set.gather_attributes_for_propagation( | geometry_set.gather_attributes_for_propagation( | ||||
| {GEO_COMPONENT_TYPE_MESH}, GEO_COMPONENT_TYPE_MESH, false, attributes); | {GEO_COMPONENT_TYPE_MESH}, GEO_COMPONENT_TYPE_MESH, false, attributes); | ||||
| ▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| vertex_corners[i] = std::move(sorted_corners); | vertex_corners[i] = std::move(sorted_corners); | ||||
| } | } | ||||
| }); | }); | ||||
| Vector<float3> vertex_positions(mesh_in.totpoly); | Vector<float3> vertex_positions(mesh_in.totpoly); | ||||
| for (const int i : IndexRange(mesh_in.totpoly)) { | for (const int i : IndexRange(mesh_in.totpoly)) { | ||||
| const MPoly &poly = src_polys[i]; | const MPoly &poly = src_polys[i]; | ||||
| BKE_mesh_calc_poly_center( | BKE_mesh_calc_poly_center(&poly, | ||||
| &poly, &src_loops[poly.loopstart], src_verts.data(), vertex_positions[i]); | &src_loops[poly.loopstart], | ||||
| reinterpret_cast<const float(*)[3]>(src_positions.data()), | |||||
| vertex_positions[i]); | |||||
| } | } | ||||
| Array<int> boundary_edge_midpoint_index; | Array<int> boundary_edge_midpoint_index; | ||||
| if (keep_boundaries) { | if (keep_boundaries) { | ||||
| /* Only initialize when we actually need it. */ | /* Only initialize when we actually need it. */ | ||||
| boundary_edge_midpoint_index.reinitialize(mesh_in.totedge); | boundary_edge_midpoint_index.reinitialize(mesh_in.totedge); | ||||
| /* We need to add vertices at the centers of boundary edges. */ | /* We need to add vertices at the centers of boundary edges. */ | ||||
| for (const int i : IndexRange(mesh_in.totedge)) { | for (const int i : IndexRange(mesh_in.totedge)) { | ||||
| if (edge_types[i] == EdgeType::Boundary) { | if (edge_types[i] == EdgeType::Boundary) { | ||||
| float3 mid; | |||||
| const MEdge &edge = src_edges[i]; | const MEdge &edge = src_edges[i]; | ||||
| mid_v3_v3v3(mid, src_verts[edge.v1].co, src_verts[edge.v2].co); | const float3 mid = math::midpoint(src_positions[edge.v1], src_positions[edge.v2]); | ||||
| boundary_edge_midpoint_index[i] = vertex_positions.size(); | boundary_edge_midpoint_index[i] = vertex_positions.size(); | ||||
| vertex_positions.append(mid); | vertex_positions.append(mid); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Vector<int> loop_lengths; | Vector<int> loop_lengths; | ||||
| Vector<int> loops; | Vector<int> loops; | ||||
| ▲ Show 20 Lines • Show All 134 Lines • ▼ Show 20 Lines | |||||
| else { | else { | ||||
| loop_edges.append(old_to_new_edges_map[edge1]); | loop_edges.append(old_to_new_edges_map[edge1]); | ||||
| } | } | ||||
| loop_indices.append(vertex_positions.size()); | loop_indices.append(vertex_positions.size()); | ||||
| /* This is sort of arbitrary, but interpolating would be a lot harder to do. */ | /* This is sort of arbitrary, but interpolating would be a lot harder to do. */ | ||||
| new_to_old_face_corners_map.append(sorted_corners.first()); | new_to_old_face_corners_map.append(sorted_corners.first()); | ||||
| boundary_vertex_to_relevant_face_map.append( | boundary_vertex_to_relevant_face_map.append( | ||||
| std::pair(loop_indices.last(), last_face_center)); | std::pair(loop_indices.last(), last_face_center)); | ||||
| vertex_positions.append(src_verts[i].co); | vertex_positions.append(src_positions[i]); | ||||
| const int boundary_vertex = loop_indices.last(); | const int boundary_vertex = loop_indices.last(); | ||||
| add_edge(src_edges, | add_edge(src_edges, | ||||
| edge1, | edge1, | ||||
| first_midpoint, | first_midpoint, | ||||
| boundary_vertex, | boundary_vertex, | ||||
| new_to_old_edges_map, | new_to_old_edges_map, | ||||
| new_edges, | new_edges, | ||||
| loop_edges); | loop_edges); | ||||
| Show All 37 Lines | |||||
| vertex_types, | vertex_types, | ||||
| keep_boundaries, | keep_boundaries, | ||||
| new_to_old_edges_map, | new_to_old_edges_map, | ||||
| new_to_old_face_corners_map, | new_to_old_face_corners_map, | ||||
| boundary_vertex_to_relevant_face_map, | boundary_vertex_to_relevant_face_map, | ||||
| mesh_in.attributes(), | mesh_in.attributes(), | ||||
| mesh_out->attributes_for_write()); | mesh_out->attributes_for_write()); | ||||
| MutableSpan<MVert> dst_verts = mesh_out->verts_for_write(); | mesh_out->positions_for_write().copy_from(vertex_positions); | ||||
| MutableSpan<MEdge> dst_edges = mesh_out->edges_for_write(); | MutableSpan<MEdge> dst_edges = mesh_out->edges_for_write(); | ||||
| MutableSpan<MPoly> dst_polys = mesh_out->polys_for_write(); | MutableSpan<MPoly> dst_polys = mesh_out->polys_for_write(); | ||||
| MutableSpan<MLoop> dst_loops = mesh_out->loops_for_write(); | MutableSpan<MLoop> dst_loops = mesh_out->loops_for_write(); | ||||
| int loop_start = 0; | int loop_start = 0; | ||||
| for (const int i : IndexRange(mesh_out->totpoly)) { | for (const int i : IndexRange(mesh_out->totpoly)) { | ||||
| dst_polys[i].loopstart = loop_start; | dst_polys[i].loopstart = loop_start; | ||||
| dst_polys[i].totloop = loop_lengths[i]; | dst_polys[i].totloop = loop_lengths[i]; | ||||
| loop_start += loop_lengths[i]; | loop_start += loop_lengths[i]; | ||||
| } | } | ||||
| for (const int i : IndexRange(mesh_out->totloop)) { | for (const int i : IndexRange(mesh_out->totloop)) { | ||||
| dst_loops[i].v = loops[i]; | dst_loops[i].v = loops[i]; | ||||
| dst_loops[i].e = loop_edges[i]; | dst_loops[i].e = loop_edges[i]; | ||||
| } | } | ||||
| for (const int i : IndexRange(mesh_out->totvert)) { | |||||
| copy_v3_v3(dst_verts[i].co, vertex_positions[i]); | |||||
| } | |||||
| dst_edges.copy_from(new_edges); | dst_edges.copy_from(new_edges); | ||||
| geometry_set.replace_mesh(mesh_out); | geometry_set.replace_mesh(mesh_out); | ||||
| } | } | ||||
| static void node_geo_exec(GeoNodeExecParams params) | static void node_geo_exec(GeoNodeExecParams params) | ||||
| { | { | ||||
| GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh"); | GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh"); | ||||
| const bool keep_boundaries = params.extract_input<bool>("Keep Boundaries"); | const bool keep_boundaries = params.extract_input<bool>("Keep Boundaries"); | ||||
| Show All 21 Lines | |||||