Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/sculpt_paint/curves_sculpt_brush.cc')
-rw-r--r--source/blender/editors/sculpt_paint/curves_sculpt_brush.cc103
1 files changed, 103 insertions, 0 deletions
diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc
index 92ce6ba3153..10564942ab9 100644
--- a/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc
+++ b/source/blender/editors/sculpt_paint/curves_sculpt_brush.cc
@@ -4,6 +4,7 @@
#include "curves_sculpt_intern.hh"
+#include "BKE_attribute_math.hh"
#include "BKE_bvhutils.h"
#include "BKE_context.h"
#include "BKE_curves.hh"
@@ -12,7 +13,11 @@
#include "UI_interface.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
#include "BLI_enumerable_thread_specific.hh"
+#include "BLI_length_parameterize.hh"
#include "BLI_task.hh"
/**
@@ -249,6 +254,55 @@ std::optional<CurvesBrush3D> sample_curves_3d_brush(const Depsgraph &depsgraph,
return brush_3d;
}
+std::optional<CurvesBrush3D> sample_curves_surface_3d_brush(
+ const Depsgraph &depsgraph,
+ const ARegion &region,
+ const View3D &v3d,
+ const CurvesSurfaceTransforms &transforms,
+ const BVHTreeFromMesh &surface_bvh,
+ const float2 &brush_pos_re,
+ const float brush_radius_re)
+{
+ float3 brush_ray_start_wo, brush_ray_end_wo;
+ ED_view3d_win_to_segment_clipped(
+ &depsgraph, &region, &v3d, brush_pos_re, brush_ray_start_wo, brush_ray_end_wo, true);
+ const float3 brush_ray_start_su = transforms.world_to_surface * brush_ray_start_wo;
+ const float3 brush_ray_end_su = transforms.world_to_surface * brush_ray_end_wo;
+
+ const float3 brush_ray_direction_su = math::normalize(brush_ray_end_su - brush_ray_start_su);
+
+ BVHTreeRayHit ray_hit;
+ ray_hit.dist = FLT_MAX;
+ ray_hit.index = -1;
+ BLI_bvhtree_ray_cast(surface_bvh.tree,
+ brush_ray_start_su,
+ brush_ray_direction_su,
+ 0.0f,
+ &ray_hit,
+ surface_bvh.raycast_callback,
+ const_cast<void *>(static_cast<const void *>(&surface_bvh)));
+ if (ray_hit.index == -1) {
+ return std::nullopt;
+ }
+
+ float3 brush_radius_ray_start_wo, brush_radius_ray_end_wo;
+ ED_view3d_win_to_segment_clipped(&depsgraph,
+ &region,
+ &v3d,
+ brush_pos_re + float2(brush_radius_re, 0),
+ brush_radius_ray_start_wo,
+ brush_radius_ray_end_wo,
+ true);
+ const float3 brush_radius_ray_start_cu = transforms.world_to_curves * brush_radius_ray_start_wo;
+ const float3 brush_radius_ray_end_cu = transforms.world_to_curves * brush_radius_ray_end_wo;
+
+ const float3 brush_pos_su = ray_hit.co;
+ const float3 brush_pos_cu = transforms.surface_to_curves * brush_pos_su;
+ const float brush_radius_cu = dist_to_line_v3(
+ brush_pos_cu, brush_radius_ray_start_cu, brush_radius_ray_end_cu);
+ return CurvesBrush3D{brush_pos_cu, brush_radius_cu};
+}
+
Vector<float4x4> get_symmetry_brush_transforms(const eCurvesSymmetryType symmetry)
{
Vector<float4x4> matrices;
@@ -277,4 +331,53 @@ Vector<float4x4> get_symmetry_brush_transforms(const eCurvesSymmetryType symmetr
return matrices;
}
+float transform_brush_radius(const float4x4 &transform,
+ const float3 &brush_position,
+ const float old_radius)
+{
+ const float3 offset_position = brush_position + float3(old_radius, 0.0f, 0.0f);
+ const float3 new_position = transform * brush_position;
+ const float3 new_offset_position = transform * offset_position;
+ return math::distance(new_position, new_offset_position);
+}
+
+void move_last_point_and_resample(MutableSpan<float3> positions, const float3 &new_last_position)
+{
+ /* Find the accumulated length of each point in the original curve,
+ * treating it as a poly curve for performance reasons and simplicity. */
+ Array<float> orig_lengths(length_parameterize::segments_num(positions.size(), false));
+ length_parameterize::accumulate_lengths<float3>(positions, false, orig_lengths);
+ const float orig_total_length = orig_lengths.last();
+
+ /* Find the factor by which the new curve is shorter or longer than the original. */
+ const float new_last_segment_length = math::distance(positions.last(1), new_last_position);
+ const float new_total_length = orig_lengths.last(1) + new_last_segment_length;
+ const float length_factor = safe_divide(new_total_length, orig_total_length);
+
+ /* Calculate the lengths to sample the original curve with by scaling the original lengths. */
+ Array<float> new_lengths(positions.size() - 1);
+ new_lengths.first() = 0.0f;
+ for (const int i : new_lengths.index_range().drop_front(1)) {
+ new_lengths[i] = orig_lengths[i - 1] * length_factor;
+ }
+
+ Array<int> indices(positions.size() - 1);
+ Array<float> factors(positions.size() - 1);
+ length_parameterize::sample_at_lengths(orig_lengths, new_lengths, indices, factors);
+
+ Array<float3> new_positions(positions.size() - 1);
+ length_parameterize::linear_interpolation<float3>(positions, indices, factors, new_positions);
+ positions.drop_back(1).copy_from(new_positions);
+ positions.last() = new_last_position;
+}
+
+CurvesSculptCommonContext::CurvesSculptCommonContext(const bContext &C)
+{
+ this->depsgraph = CTX_data_depsgraph_pointer(&C);
+ this->scene = CTX_data_scene(&C);
+ this->region = CTX_wm_region(&C);
+ this->v3d = CTX_wm_view3d(&C);
+ this->rv3d = CTX_wm_region_view3d(&C);
+}
+
} // namespace blender::ed::sculpt_paint