diff options
Diffstat (limited to 'source/blender/blenkernel/BKE_curves.hh')
-rw-r--r-- | source/blender/blenkernel/BKE_curves.hh | 126 |
1 files changed, 121 insertions, 5 deletions
diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh index 2bebd3ff97d..568899721a9 100644 --- a/source/blender/blenkernel/BKE_curves.hh +++ b/source/blender/blenkernel/BKE_curves.hh @@ -11,6 +11,7 @@ #include <mutex> +#include "BLI_float3x3.hh" #include "BLI_float4x4.hh" #include "BLI_generic_virtual_array.hh" #include "BLI_index_mask.hh" @@ -20,7 +21,7 @@ #include "BLI_vector.hh" #include "BLI_virtual_array.hh" -#include "BKE_attribute_access.hh" +#include "BKE_attribute.hh" namespace blender::bke { @@ -385,8 +386,6 @@ class CurvesGeometry : public ::CurvesGeometry { void calculate_bezier_auto_handles(); - void update_customdata_pointers(); - void remove_points(IndexMask points_to_delete); void remove_curves(IndexMask curves_to_delete); @@ -401,6 +400,9 @@ class CurvesGeometry : public ::CurvesGeometry { */ void remove_attributes_based_on_types(); + AttributeAccessor attributes() const; + MutableAttributeAccessor attributes_for_write(); + /* -------------------------------------------------------------------- * Attributes. */ @@ -413,6 +415,38 @@ class CurvesGeometry : public ::CurvesGeometry { } }; +/** + * Used to propagate deformation data through modifier evaluation so that sculpt tools can work on + * evaluated data. + */ +class CurvesEditHints { + public: + /** + * Original data that the edit hints below are meant to be used for. + */ + const Curves &curves_id_orig; + /** + * Evaluated positions for the points in #curves_orig. If this is empty, the positions from the + * evaluated #Curves should be used if possible. + */ + std::optional<Array<float3>> positions; + /** + * Matrices which transform point movement vectors from original data to corresponding movements + * of evaluated data. + */ + std::optional<Array<float3x3>> deform_mats; + + CurvesEditHints(const Curves &curves_id_orig) : curves_id_orig(curves_id_orig) + { + } + + /** + * The edit hints have to correspond to the original curves, i.e. the number of deformed points + * is the same as the number of original points. + */ + bool is_valid() const; +}; + namespace curves { /* -------------------------------------------------------------------- */ @@ -423,7 +457,7 @@ namespace curves { * The number of segments between control points, accounting for the last segment of cyclic * curves. The logic is simple, but this function should be used to make intentions clearer. */ -inline int curve_segment_num(const int points_num, const bool cyclic) +inline int segments_num(const int points_num, const bool cyclic) { BLI_assert(points_num > 0); return (cyclic && points_num > 1) ? points_num : points_num - 1; @@ -483,6 +517,8 @@ namespace bezier { * Return true if the handles that make up a segment both have a vector type. Vector segments for * Bezier curves have special behavior because they aren't divided into many evaluated points. */ +bool segment_is_vector(const HandleType left, const HandleType right); +bool segment_is_vector(const int8_t left, const int8_t right); bool segment_is_vector(Span<int8_t> handle_types_left, Span<int8_t> handle_types_right, int segment_index); @@ -515,6 +551,43 @@ void calculate_evaluated_offsets(Span<int8_t> handle_types_left, int resolution, MutableSpan<int> evaluated_offsets); +/** See #insert. */ +struct Insertion { + float3 handle_prev; + float3 left_handle; + float3 position; + float3 right_handle; + float3 handle_next; +}; + +/** + * Compute the Bezier segment insertion for the given parameter on the segment, returning + * the position and handles of the new point and the updated existing handle positions. + * <pre> + * handle_prev handle_next + * x-----------------x + * / \ + * / x---O---x \ + * / result \ + * / \ + * O O + * point_prev point_next + * </pre> + */ +Insertion insert(const float3 &point_prev, + const float3 &handle_prev, + const float3 &handle_next, + const float3 &point_next, + float parameter); + +/** + * Calculate the automatically defined positions for a vector handle (#BEZIER_HANDLE_VECTOR). While + * this can be calculated automatically with #calculate_auto_handles, when more context is + * available, it can be preferable for performance reasons to calculate it for a single segment + * when necessary. + */ +float3 calculate_vector_handle(const float3 &point, const float3 &next_point); + /** * Recalculate all auto (#BEZIER_HANDLE_AUTO) and vector (#BEZIER_HANDLE_VECTOR) handles with * positions automatically derived from the neighboring control points, and update aligned @@ -599,6 +672,15 @@ int calculate_evaluated_num(int points_num, bool cyclic, int resolution); */ void interpolate_to_evaluated(GSpan src, bool cyclic, int resolution, GMutableSpan dst); +/** + * Evaluate the Catmull Rom curve. The size of each segment and its offset in the #dst span + * is encoded in #evaluated_offsets, with the same method as #CurvesGeometry::offsets(). + */ +void interpolate_to_evaluated(const GSpan src, + const bool cyclic, + const Span<int> evaluated_offsets, + GMutableSpan dst); + } // namespace catmull_rom /** \} */ @@ -684,6 +766,12 @@ Curves *curves_new_nomain(CurvesGeometry curves); */ Curves *curves_new_nomain_single(int points_num, CurveType type); +/** + * Copy data from #src to #dst, except the geometry data in #CurvesGeometry. Typically used to + * copy high-level parameters when a geometry-altering operation creates a new curves data-block. + */ +void curves_copy_parameters(const Curves &src, Curves &dst); + std::array<int, CURVE_TYPES_NUM> calculate_type_counts(const VArray<int8_t> &types); /* -------------------------------------------------------------------- */ @@ -782,7 +870,7 @@ inline IndexRange CurvesGeometry::lengths_range_for_curve(const int curve_index, BLI_assert(cyclic == this->cyclic()[curve_index]); const IndexRange points = this->evaluated_points_for_curve(curve_index); const int start = points.start() + curve_index; - return {start, curves::curve_segment_num(points.size(), cyclic)}; + return {start, curves::segments_num(points.size(), cyclic)}; } inline Span<float> CurvesGeometry::evaluated_lengths_for_curve(const int curve_index, @@ -819,8 +907,36 @@ inline bool point_is_sharp(const Span<int8_t> handle_types_left, ELEM(handle_types_right[index], BEZIER_HANDLE_VECTOR, BEZIER_HANDLE_FREE); } +inline bool segment_is_vector(const HandleType left, const HandleType right) +{ + return left == BEZIER_HANDLE_VECTOR && right == BEZIER_HANDLE_VECTOR; +} + +inline bool segment_is_vector(const int8_t left, const int8_t right) +{ + return segment_is_vector(HandleType(left), HandleType(right)); +} + +inline float3 calculate_vector_handle(const float3 &point, const float3 &next_point) +{ + return math::interpolate(point, next_point, 1.0f / 3.0f); +} + /** \} */ } // namespace curves::bezier +struct CurvesSurfaceTransforms { + float4x4 curves_to_world; + float4x4 curves_to_surface; + float4x4 world_to_curves; + float4x4 world_to_surface; + float4x4 surface_to_world; + float4x4 surface_to_curves; + float4x4 surface_to_curves_normal; + + CurvesSurfaceTransforms() = default; + CurvesSurfaceTransforms(const Object &curves_ob, const Object *surface_ob); +}; + } // namespace blender::bke |