Curves: initial surface collision for curves sculpt mode #104469
|
@ -22,6 +22,8 @@
|
|||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "GEO_curve_constraint_solver.hh"
|
||||
|
||||
/**
|
||||
* The code below uses a prefix naming convention to indicate the coordinate space:
|
||||
* cu: Local space of the curves object that is being edited.
|
||||
|
@ -424,4 +426,40 @@ void report_invalid_uv_map(ReportList *reports)
|
|||
BKE_report(reports, RPT_WARNING, TIP_("Invalid UV map: UV islands must not overlap"));
|
||||
}
|
||||
|
||||
void CurvesConstraintSolver::initialize(const bke::CurvesGeometry &curves,
|
||||
const IndexMask curve_selection,
|
||||
const bool use_surface_collision)
|
||||
{
|
||||
use_surface_collision_ = use_surface_collision;
|
||||
segment_lengths_.reinitialize(curves.points_num());
|
||||
geometry::curve_constraint_solver::compute_segment_lengths(
|
||||
curves.points_by_curve(), curves.positions(), curve_selection, segment_lengths_);
|
||||
if (use_surface_collision_) {
|
||||
start_positions_ = curves.positions();
|
||||
}
|
||||
}
|
||||
|
||||
void CurvesConstraintSolver::solve_step(bke::CurvesGeometry &curves,
|
||||
const IndexMask curve_selection,
|
||||
const Mesh *surface,
|
||||
const CurvesSurfaceTransforms &transforms)
|
||||
{
|
||||
if (use_surface_collision_ && surface != nullptr) {
|
||||
geometry::curve_constraint_solver::solve_length_and_collision_constraints(
|
||||
curves.points_by_curve(),
|
||||
curve_selection,
|
||||
segment_lengths_,
|
||||
start_positions_,
|
||||
*surface,
|
||||
transforms,
|
||||
curves.positions_for_write());
|
||||
start_positions_ = curves.positions();
|
||||
}
|
||||
else {
|
||||
geometry::curve_constraint_solver::solve_length_constraints(
|
||||
curves.points_by_curve(), curve_selection, segment_lengths_, curves.positions_for_write());
|
||||
}
|
||||
curves.tag_positions_changed();
|
||||
}
|
||||
|
||||
} // namespace blender::ed::sculpt_paint
|
||||
|
|
|
@ -38,8 +38,6 @@
|
|||
#include "ED_screen.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "GEO_curve_constraint_solver.hh"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
@ -57,52 +55,6 @@ namespace blender::ed::sculpt_paint {
|
|||
using blender::bke::CurvesGeometry;
|
||||
using threading::EnumerableThreadSpecific;
|
||||
|
||||
struct ConstraintSolver {
|
||||
private:
|
||||
bool use_surface_collision_;
|
||||
Array<float3> start_positions_;
|
||||
Array<float> segment_lengths_;
|
||||
|
||||
public:
|
||||
void initialize(const bke::CurvesGeometry &curves,
|
||||
const IndexMask curve_selection,
|
||||
const bool use_surface_collision)
|
||||
{
|
||||
use_surface_collision_ = use_surface_collision;
|
||||
segment_lengths_.reinitialize(curves.points_num());
|
||||
geometry::curve_constraint_solver::compute_segment_lengths(
|
||||
curves.points_by_curve(), curves.positions(), curve_selection, segment_lengths_);
|
||||
if (use_surface_collision_) {
|
||||
start_positions_ = curves.positions();
|
||||
}
|
||||
}
|
||||
|
||||
void solve(bke::CurvesGeometry &curves,
|
||||
const IndexMask curve_selection,
|
||||
const Mesh &surface,
|
||||
const CurvesSurfaceTransforms &transforms)
|
||||
{
|
||||
if (use_surface_collision_) {
|
||||
geometry::curve_constraint_solver::solve_length_and_collision_constraints(
|
||||
curves.points_by_curve(),
|
||||
curve_selection,
|
||||
segment_lengths_,
|
||||
start_positions_,
|
||||
surface,
|
||||
transforms,
|
||||
curves.positions_for_write());
|
||||
start_positions_ = curves.positions();
|
||||
}
|
||||
else {
|
||||
geometry::curve_constraint_solver::solve_length_constraints(curves.points_by_curve(),
|
||||
curve_selection,
|
||||
segment_lengths_,
|
||||
curves.positions_for_write());
|
||||
}
|
||||
curves.tag_positions_changed();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Moves individual points under the brush and does a length preservation step afterwards.
|
||||
*/
|
||||
|
@ -114,8 +66,8 @@ class CombOperation : public CurvesSculptStrokeOperation {
|
|||
/** Only used when a 3D brush is used. */
|
||||
CurvesBrush3D brush_3d_;
|
||||
|
||||
/** Solver for length and contact constraints. */
|
||||
ConstraintSolver constraint_solver_;
|
||||
/** Solver for length and collision constraints. */
|
||||
CurvesConstraintSolver constraint_solver_;
|
||||
|
||||
friend struct CombOperationExecutor;
|
||||
|
||||
|
@ -230,8 +182,8 @@ struct CombOperationExecutor {
|
|||
totcurves += curves.size();
|
||||
};
|
||||
|
||||
self_->constraint_solver_.solve(
|
||||
*curves_orig_, IndexMask(all_changed_curves), *surface, transforms_);
|
||||
self_->constraint_solver_.solve_step(
|
||||
*curves_orig_, IndexMask(all_changed_curves), surface, transforms_);
|
||||
|
||||
curves_orig_->tag_positions_changed();
|
||||
DEG_id_tag_update(&curves_id_orig_->id, ID_RECALC_GEOMETRY);
|
||||
|
|
|
@ -144,4 +144,25 @@ void report_missing_uv_map_on_original_surface(ReportList *reports);
|
|||
void report_missing_uv_map_on_evaluated_surface(ReportList *reports);
|
||||
void report_invalid_uv_map(ReportList *reports);
|
||||
|
||||
/**
|
||||
* Utility class to make it easy for brushes to implement length preservation and surface
|
||||
* collision.
|
||||
*/
|
||||
struct CurvesConstraintSolver {
|
||||
private:
|
||||
bool use_surface_collision_;
|
||||
Array<float3> start_positions_;
|
||||
Array<float> segment_lengths_;
|
||||
|
||||
public:
|
||||
void initialize(const bke::CurvesGeometry &curves,
|
||||
const IndexMask curve_selection,
|
||||
const bool use_surface_collision);
|
||||
|
||||
void solve_step(bke::CurvesGeometry &curves,
|
||||
const IndexMask curve_selection,
|
||||
const Mesh *surface,
|
||||
const CurvesSurfaceTransforms &transforms);
|
||||
};
|
||||
|
||||
} // namespace blender::ed::sculpt_paint
|
||||
|
|
|
@ -40,14 +40,12 @@
|
|||
|
||||
namespace blender::ed::sculpt_paint {
|
||||
|
||||
using geometry::ConstraintSolver;
|
||||
|
||||
class PinchOperation : public CurvesSculptStrokeOperation {
|
||||
private:
|
||||
bool invert_pinch_;
|
||||
|
||||
/** Solver for length and contact constraints. */
|
||||
ConstraintSolver constraint_solver_;
|
||||
/** Solver for length and collision constraints. */
|
||||
CurvesConstraintSolver constraint_solver_;
|
||||
|
||||
/** Only used when a 3D brush is used. */
|
||||
CurvesBrush3D brush_3d_;
|
||||
|
@ -131,9 +129,8 @@ struct PinchOperationExecutor {
|
|||
brush_radius_base_re_);
|
||||
}
|
||||
|
||||
ConstraintSolver::Params params;
|
||||
params.use_collision_constraints = curves_id_->flag & CV_SCULPT_COLLISION_ENABLED;
|
||||
self_->constraint_solver_.initialize(params, *curves_, curve_selection_);
|
||||
self_->constraint_solver_.initialize(
|
||||
*curves_, curve_selection_, curves_id_->flag & CV_SCULPT_COLLISION_ENABLED);
|
||||
}
|
||||
|
||||
start_positions_ = curves_->positions();
|
||||
|
@ -162,8 +159,8 @@ struct PinchOperationExecutor {
|
|||
const Mesh *surface = curves_id_->surface && curves_id_->surface->type == OB_MESH ?
|
||||
static_cast<Mesh *>(curves_id_->surface->data) :
|
||||
nullptr;
|
||||
self_->constraint_solver_.step_curves(
|
||||
*curves_, surface, transforms_, start_positions_, IndexMask(changed_curves_indices));
|
||||
self_->constraint_solver_.solve_step(
|
||||
*curves_, IndexMask(changed_curves_indices), surface, transforms_);
|
||||
|
||||
curves_->tag_positions_changed();
|
||||
DEG_id_tag_update(&curves_id_->id, ID_RECALC_GEOMETRY);
|
||||
|
|
|
@ -22,21 +22,18 @@
|
|||
#include "BLI_length_parameterize.hh"
|
||||
|
||||
#include "GEO_add_curves_on_mesh.hh"
|
||||
#include "GEO_constraint_solver.hh"
|
||||
|
||||
#include "curves_sculpt_intern.hh"
|
||||
|
||||
namespace blender::ed::sculpt_paint {
|
||||
|
||||
using geometry::ConstraintSolver;
|
||||
|
||||
class PuffOperation : public CurvesSculptStrokeOperation {
|
||||
private:
|
||||
/** Only used when a 3D brush is used. */
|
||||
CurvesBrush3D brush_3d_;
|
||||
|
||||
/** Solver for length and contact constraints. */
|
||||
ConstraintSolver constraint_solver_;
|
||||
/** Solver for length and collision constraints. */
|
||||
CurvesConstraintSolver constraint_solver_;
|
||||
|
||||
friend struct PuffOperationExecutor;
|
||||
|
||||
|
@ -142,9 +139,8 @@ struct PuffOperationExecutor {
|
|||
brush_radius_base_re_);
|
||||
}
|
||||
|
||||
ConstraintSolver::Params params;
|
||||
params.use_collision_constraints = curves_id_->flag & CV_SCULPT_COLLISION_ENABLED;
|
||||
self_->constraint_solver_.initialize(params, *curves_, curve_selection_);
|
||||
self_->constraint_solver_.initialize(
|
||||
*curves_, curve_selection_, curves_id_->flag & CV_SCULPT_COLLISION_ENABLED);
|
||||
}
|
||||
|
||||
start_positions_ = curves_->positions();
|
||||
|
@ -173,8 +169,8 @@ struct PuffOperationExecutor {
|
|||
}
|
||||
}
|
||||
|
||||
self_->constraint_solver_.step_curves(
|
||||
*curves_, surface_, transforms_, start_positions_, IndexMask(changed_curves_indices));
|
||||
self_->constraint_solver_.solve_step(
|
||||
*curves_, IndexMask(changed_curves_indices), surface_, transforms_);
|
||||
|
||||
curves_->tag_positions_changed();
|
||||
DEG_id_tag_update(&curves_id_->id, ID_RECALC_GEOMETRY);
|
||||
|
|
Loading…
Reference in New Issue