Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/curve_to_mesh_convert.cc
| Show First 20 Lines • Show All 223 Lines • ▼ Show 20 Lines | |||||
| struct CurvesInfo { | struct CurvesInfo { | ||||
| const CurvesGeometry &main; | const CurvesGeometry &main; | ||||
| const CurvesGeometry &profile; | const CurvesGeometry &profile; | ||||
| /* Make sure these are spans because they are potentially accessed many times. */ | /* Make sure these are spans because they are potentially accessed many times. */ | ||||
| VArray_Span<bool> main_cyclic; | VArray_Span<bool> main_cyclic; | ||||
| VArray_Span<bool> profile_cyclic; | VArray_Span<bool> profile_cyclic; | ||||
| /* TODO: Remove once these are cached on #CurvesGeometry. */ | |||||
| std::array<int, CURVE_TYPES_NUM> main_type_counts; | |||||
| std::array<int, CURVE_TYPES_NUM> profile_type_counts; | |||||
| }; | }; | ||||
| static CurvesInfo get_curves_info(const CurvesGeometry &main, const CurvesGeometry &profile) | static CurvesInfo get_curves_info(const CurvesGeometry &main, const CurvesGeometry &profile) | ||||
| { | { | ||||
| return {main, | return {main, profile, main.cyclic(), profile.cyclic()}; | ||||
| profile, | |||||
| main.cyclic(), | |||||
| profile.cyclic(), | |||||
| main.count_curve_types(), | |||||
| profile.count_curve_types()}; | |||||
| } | } | ||||
| struct ResultOffsets { | struct ResultOffsets { | ||||
| /** The total number of curve combinations. */ | /** The total number of curve combinations. */ | ||||
| int total; | int total; | ||||
| /** Offsets into the result mesh for each combination. */ | /** Offsets into the result mesh for each combination. */ | ||||
| Array<int> vert; | Array<int> vert; | ||||
| ▲ Show 20 Lines • Show All 433 Lines • ▼ Show 20 Lines | Mesh *curve_to_mesh_sweep(const CurvesGeometry &main, | ||||
| CurveComponent profile_component; | CurveComponent profile_component; | ||||
| profile_component.replace(&profile_id, GeometryOwnershipType::Editable); | profile_component.replace(&profile_id, GeometryOwnershipType::Editable); | ||||
| Span<float> radii = {}; | Span<float> radii = {}; | ||||
| if (main_component.attribute_exists("radius")) { | if (main_component.attribute_exists("radius")) { | ||||
| radii = evaluated_attribute_if_necessary( | radii = evaluated_attribute_if_necessary( | ||||
| main_component.attribute_get_for_read<float>("radius", ATTR_DOMAIN_POINT, 1.0f), | main_component.attribute_get_for_read<float>("radius", ATTR_DOMAIN_POINT, 1.0f), | ||||
| main, | main, | ||||
| curves_info.main_type_counts, | main.curve_type_counts(), | ||||
| eval_buffer) | eval_buffer) | ||||
| .typed<float>(); | .typed<float>(); | ||||
| } | } | ||||
| foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) { | foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) { | ||||
| fill_mesh_positions(info.main_points.size(), | fill_mesh_positions(info.main_points.size(), | ||||
| info.profile_points.size(), | info.profile_points.size(), | ||||
| main_positions.slice(info.main_points), | main_positions.slice(info.main_points), | ||||
| profile_positions.slice(info.profile_points), | profile_positions.slice(info.profile_points), | ||||
| tangents.slice(info.main_points), | tangents.slice(info.main_points), | ||||
| normals.slice(info.main_points), | normals.slice(info.main_points), | ||||
| radii.is_empty() ? radii : radii.slice(info.main_points), | radii.is_empty() ? radii : radii.slice(info.main_points), | ||||
| verts.slice(info.vert_range)); | verts.slice(info.vert_range)); | ||||
| }); | }); | ||||
| if (curves_info.profile_type_counts[CURVE_TYPE_BEZIER] > 0) { | if (profile.curve_type_counts()[CURVE_TYPE_BEZIER] > 0) { | ||||
| const VArray<int8_t> curve_types = profile.curve_types(); | const VArray<int8_t> curve_types = profile.curve_types(); | ||||
| const VArray_Span<int8_t> handle_types_left{profile.handle_types_left()}; | const VArray_Span<int8_t> handle_types_left{profile.handle_types_left()}; | ||||
| const VArray_Span<int8_t> handle_types_right{profile.handle_types_right()}; | const VArray_Span<int8_t> handle_types_right{profile.handle_types_right()}; | ||||
| foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) { | foreach_curve_combination(curves_info, offsets, [&](const CombinationInfo &info) { | ||||
| if (curve_types[info.i_profile] == CURVE_TYPE_BEZIER) { | if (curve_types[info.i_profile] == CURVE_TYPE_BEZIER) { | ||||
| const IndexRange points = profile.points_for_curve(info.i_profile); | const IndexRange points = profile.points_for_curve(info.i_profile); | ||||
| mark_bezier_vector_edges_sharp(points.size(), | mark_bezier_vector_edges_sharp(points.size(), | ||||
| Show All 28 Lines | if (!dst) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| if (src_domain == ATTR_DOMAIN_POINT) { | if (src_domain == ATTR_DOMAIN_POINT) { | ||||
| copy_main_point_domain_attribute_to_mesh( | copy_main_point_domain_attribute_to_mesh( | ||||
| curves_info, | curves_info, | ||||
| offsets, | offsets, | ||||
| dst_domain, | dst_domain, | ||||
| evaluated_attribute_if_necessary(src, main, curves_info.main_type_counts, eval_buffer), | evaluated_attribute_if_necessary(src, main, main.curve_type_counts(), eval_buffer), | ||||
| dst.as_span()); | dst.as_span()); | ||||
| } | } | ||||
| else if (src_domain == ATTR_DOMAIN_CURVE) { | else if (src_domain == ATTR_DOMAIN_CURVE) { | ||||
| copy_curve_domain_attribute_to_mesh( | copy_curve_domain_attribute_to_mesh( | ||||
| offsets, offsets.main_indices, dst_domain, src, dst.as_span()); | offsets, offsets.main_indices, dst_domain, src, dst.as_span()); | ||||
| } | } | ||||
| dst.save(); | dst.save(); | ||||
| Show All 18 Lines | if (!dst) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| if (src_domain == ATTR_DOMAIN_POINT) { | if (src_domain == ATTR_DOMAIN_POINT) { | ||||
| copy_profile_point_domain_attribute_to_mesh( | copy_profile_point_domain_attribute_to_mesh( | ||||
| curves_info, | curves_info, | ||||
| offsets, | offsets, | ||||
| dst_domain, | dst_domain, | ||||
| evaluated_attribute_if_necessary( | evaluated_attribute_if_necessary(src, profile, profile.curve_type_counts(), eval_buffer), | ||||
| src, profile, curves_info.profile_type_counts, eval_buffer), | |||||
| dst.as_span()); | dst.as_span()); | ||||
| } | } | ||||
| else if (src_domain == ATTR_DOMAIN_CURVE) { | else if (src_domain == ATTR_DOMAIN_CURVE) { | ||||
| copy_curve_domain_attribute_to_mesh( | copy_curve_domain_attribute_to_mesh( | ||||
| offsets, offsets.profile_indices, dst_domain, src, dst.as_span()); | offsets, offsets.profile_indices, dst_domain, src, dst.as_span()); | ||||
| } | } | ||||
| dst.save(); | dst.save(); | ||||
| return true; | return true; | ||||
| }); | }); | ||||
| return mesh; | return mesh; | ||||
| } | } | ||||
| static CurvesGeometry get_curve_single_vert() | static CurvesGeometry get_curve_single_vert() | ||||
| { | { | ||||
| CurvesGeometry curves(1, 1); | CurvesGeometry curves(1, 1); | ||||
| curves.offsets_for_write().last() = 1; | curves.offsets_for_write().last() = 1; | ||||
| curves.positions_for_write().fill(float3(0)); | curves.positions_for_write().fill(float3(0)); | ||||
| curves.fill_curve_types(CURVE_TYPE_POLY); | |||||
| return curves; | return curves; | ||||
| } | } | ||||
| Mesh *curve_to_wire_mesh(const CurvesGeometry &curve) | Mesh *curve_to_wire_mesh(const CurvesGeometry &curve) | ||||
| { | { | ||||
| static const CurvesGeometry vert_curve = get_curve_single_vert(); | static const CurvesGeometry vert_curve = get_curve_single_vert(); | ||||
| return curve_to_mesh_sweep(curve, vert_curve, false); | return curve_to_mesh_sweep(curve, vert_curve, false); | ||||
| } | } | ||||
| } // namespace blender::bke | } // namespace blender::bke | ||||