90 std::array<float4x4, 8> mats;
92 float3 final_pivot_pos, d_t, d_s;
94 float t_mat[4][4], r_mat[4][4], s_mat[4][4], pivot_mat[4][4], pivot_imat[4][4],
97 float start_pivot_pos[3], start_pivot_rot[4], start_pivot_scale[3];
140 translate_m4(pivot_mat, final_pivot_pos[0], final_pivot_pos[1], final_pivot_pos[2]);
163 const std::array<float4x4, 8> &transform_mats,
166 for (
const int i : positions.index_range()) {
169 translations[i] = transformed - positions[i];
180 for (
const int i : positions.index_range()) {
182 translations[i].x = 0.0f;
185 translations[i].y = 0.0f;
188 translations[i].z = 0.0f;
194 const std::array<float4x4, 8> &transform_mats,
223 const std::array<float4x4, 8> &transform_mats,
255 const std::array<float4x4, 8> &transform_mats,
301 switch (pbvh.
type()) {
343 for (
const int i : positions.index_range()) {
345 r_translations[i] = transformed - positions[i];
350 const float3 &elastic_transform_pivot,
354 for (
const int i : positions.index_range()) {
356 translations[i], &
params, positions[i], elastic_transform_pivot, translations[i]);
362 const float4x4 &elastic_transform_mat,
363 const float3 &elastic_transform_pivot,
394 const float4x4 &elastic_transform_mat,
395 const float3 &elastic_transform_pivot,
425 const float4x4 &elastic_transform_mat,
426 const float3 &elastic_transform_pivot,
455 const float transform_radius)
473 const float force = 1.0f;
474 const float shear_modulus = 1.0f;
475 const float poisson_ratio = 0.4f;
487 float4x4 elastic_transform_mat = transform_mats[symm_area];
488 switch (pbvh.
type()) {
498 elastic_transform_mat,
499 elastic_transform_pivot,
516 sd,
params, elastic_transform_mat, elastic_transform_pivot, nodes[i], ob, tls);
526 sd,
params, elastic_transform_mat, elastic_transform_pivot, nodes[i], ob, tls);
554 float transform_radius;
600 "Sets the pivot to the origin of the sculpt"},
605 "Sets the pivot position to the average position of the unmasked vertices"},
610 "Sets the pivot position to the center of the border of the mask"},
615 "Sets the pivot position to the active vertex position"},
620 "Sets the pivot position to the surface under the cursor"},
621 {0,
nullptr, 0,
nullptr,
nullptr},
650 for (
const int i : positions.index_range()) {
651 total.position +=
double3(positions[i] * factors[i]);
652 total.weight_total += factors[i];
676 switch (pbvh.
type()) {
679 const Mesh &mesh = *
static_cast<const Mesh *
>(
object.data);
687 LocalData &tls = all_tls.local();
688 threading::isolate_task([&]() {
689 node_mask.slice(range).foreach_index([&](const int i) {
690 const Span<int> verts = nodes[i].verts();
692 tls.positions.resize(verts.size());
693 const MutableSpan<float3> positions = tls.positions;
694 array_utils::gather(vert_positions, verts, positions);
696 tls.factors.resize(verts.size());
697 const MutableSpan<float> factors = tls.factors;
698 fill_factor_from_hide_and_mask(
699 attribute_data.hide_vert, attribute_data.mask, verts, factors);
700 filter_verts_outside_symmetry_area(positions, pivot, symm, factors);
702 accumulate_weighted_average_position(positions, factors, sum);
718 LocalData &tls = all_tls.local();
719 node_mask.slice(range).foreach_index([&](const int i) {
720 const Span<int> grids = nodes[i].grids();
721 const MutableSpan positions = gather_grids_positions(
722 subdiv_ccg, grids, tls.positions);
724 tls.factors.resize(positions.size());
725 const MutableSpan<float> factors = tls.factors;
726 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
727 filter_verts_outside_symmetry_area(positions, pivot, symm, factors);
729 accumulate_weighted_average_position(positions, factors, sum);
739 node_mask.index_range(),
741 AveragePositionAccumulation{},
742 [&](
const IndexRange range, AveragePositionAccumulation
sum) {
743 LocalData &tls = all_tls.local();
744 node_mask.slice(range).foreach_index([&](const int i) {
745 const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(
746 &const_cast<bke::pbvh::BMeshNode &>(nodes[i]));
747 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
749 tls.factors.resize(verts.size());
750 const MutableSpan<float> factors = tls.factors;
751 fill_factor_from_hide_and_mask(*ss.bm, verts, factors);
752 filter_verts_outside_symmetry_area(positions, pivot, symm, factors);
754 accumulate_weighted_average_position(positions, factors, sum);
769 constexpr float threshold = 0.2f;
771 for (
const int i : masks.index_range()) {
772 if (std::abs(masks[i] - 0.5f) > threshold) {
787 const IndexMask node_mask = bke::pbvh::search_nodes(
799 switch (pbvh.
type()) {
800 case bke::pbvh::Type::Mesh: {
802 const Mesh &mesh = *
static_cast<const Mesh *
>(
object.data);
805 const VArraySpan mask_attr = *attributes.lookup_or_default<
float>(
806 ".sculpt_mask", bke::AttrDomain::Point, 0.0f);
807 const VArraySpan hide_vert = *attributes.lookup<
bool>(
".hide_vert", bke::AttrDomain::Point);
813 LocalData &tls = all_tls.local();
814 node_mask.slice(range).foreach_index([&](const int i) {
815 const Span<int> verts = nodes[i].verts();
816 MutableSpan positions = gather_data_mesh(vert_positions, verts, tls.positions);
817 MutableSpan masks = gather_data_mesh(mask_attr, verts, tls.masks);
819 tls.factors.resize(verts.size());
820 const MutableSpan<float> factors = tls.factors;
821 fill_factor_from_hide(hide_vert, verts, factors);
823 mask_border_weight_calc(masks, factors);
824 filter_verts_outside_symmetry_area(positions, pivot, symm, factors);
826 accumulate_weighted_average_position(positions, factors, sum);
833 case bke::pbvh::Type::Grids: {
841 LocalData &tls = all_tls.local();
842 node_mask.slice(range).foreach_index([&](const int i) {
843 const Span<int> grids = nodes[i].grids();
844 const MutableSpan positions = gather_grids_positions(
845 subdiv_ccg, grids, tls.positions);
847 tls.masks.resize(positions.size());
848 const MutableSpan<float> masks = tls.masks;
849 mask::gather_mask_grids(subdiv_ccg, grids, masks);
851 tls.factors.resize(positions.size());
852 const MutableSpan<float> factors = tls.factors;
853 fill_factor_from_hide(subdiv_ccg, grids, factors);
854 mask_border_weight_calc(masks, factors);
855 filter_verts_outside_symmetry_area(positions, pivot, symm, factors);
857 accumulate_weighted_average_position(positions, factors, sum);
864 case bke::pbvh::Type::BMesh: {
866 const AveragePositionAccumulation total = threading::parallel_reduce(
867 node_mask.index_range(),
869 AveragePositionAccumulation{},
870 [&](
const IndexRange range, AveragePositionAccumulation
sum) {
871 LocalData &tls = all_tls.local();
872 node_mask.slice(range).foreach_index([&](const int i) {
873 const Set<BMVert *, 0> &verts = BKE_pbvh_bmesh_node_unique_verts(
874 &const_cast<bke::pbvh::BMeshNode &>(nodes[i]));
875 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
877 tls.masks.resize(verts.size());
878 const MutableSpan<float> masks = tls.masks;
879 mask::gather_mask_bmesh(*ss.bm, verts, masks);
881 tls.factors.resize(verts.size());
882 const MutableSpan<float> factors = tls.factors;
883 fill_factor_from_hide(verts, factors);
884 mask_border_weight_calc(masks, factors);
885 filter_verts_outside_symmetry_area(positions, pivot, symm, factors);
887 accumulate_weighted_average_position(positions, factors, sum);
891 combine_average_position_accumulation);
918 if (mode == PivotPositionMode::Origin) {
922 else if (mode == PivotPositionMode::ActiveVert) {
926 else if (mode == PivotPositionMode::CursorSurface) {
927 float stroke_location[3];
928 const float mval[2] = {
936 else if (mode == PivotPositionMode::Unmasked) {
968 return mode == PivotPositionMode::CursorSurface;
975 ot->
name =
"Set Pivot Position";
976 ot->
idname =
"SCULPT_OT_set_pivot_position";
977 ot->
description =
"Sets the sculpt transform pivot position";
989 int(PivotPositionMode::Unmasked),
999 "Position of the mouse used for \"Surface\" mode",
1008 "Position of the mouse used for \"Surface\" mode",
float BKE_brush_unprojected_radius_get(const Scene *scene, const Brush *brush)
int BKE_brush_size_get(const Scene *scene, const Brush *brush)
bool BKE_brush_use_locked_size(const Scene *scene, const Brush *brush)
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Base * CTX_data_active_base(const bContext *C)
ToolSettings * CTX_data_tool_settings(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
void BKE_kelvinlet_grab_triscale(float radius_elem_disp[3], const KelvinletParams *params, const float elem_orig_co[3], const float brush_location[3], const float brush_delta[3])
void BKE_kelvinlet_init_params(KelvinletParams *params, float radius, float force, float shear_modulus, float poisson_ratio)
bool BKE_base_is_visible(const View3D *v3d, const Base *base)
std::variant< std::monostate, int, SubdivCCGCoord, BMVert * > ActiveVert
const Brush * BKE_paint_brush_for_read(const Paint *paint)
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
A BVH for high poly meshes.
const blender::Set< BMVert *, 0 > & BKE_pbvh_bmesh_node_unique_verts(blender::bke::pbvh::BMeshNode *node)
CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
#define BLI_assert_unreachable()
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void unit_m4(float m[4][4])
void translate_m4(float mat[4][4], float Tx, float Ty, float Tz)
void size_to_mat4(float R[4][4], const float size[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void sub_qt_qtqt(float q[4], const float a[4], const float b[4])
float normalize_qt(float q[4])
void quat_to_mat4(float m[4][4], const float q[4])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE void add_v3_fl(float r[3], float f)
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
@ SCULPT_TRANSFORM_MODE_RADIUS_ELASTIC
@ SCULPT_TRANSFORM_MODE_ALL_VERTICES
void ED_region_tag_redraw(ARegion *region)
ViewContext ED_view3d_viewcontext_init(bContext *C, Depsgraph *depsgraph)
Read Guarded memory(de)allocation.
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
static T sum(const btAlignedObjectArray< T > &items)
constexpr int64_t size() const
void resize(const int64_t new_size)
void tag_positions_changed(const IndexMask &node_mask)
Span< NodeT > nodes() const
IndexRange index_range() const
void foreach_index(Fn &&fn) const
local_group_size(16, 16) .push_constant(Type b
const Depsgraph * depsgraph
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
pbvh::Tree * pbvh_get(Object &object)
IndexMask search_nodes(const Tree &pbvh, IndexMaskMemory &memory, FunctionRef< bool(const Node &)> filter_fn)
void update_node_bounds_bmesh(BMeshNode &node)
void update_node_bounds_mesh(Span< float3 > positions, MeshNode &node)
void update_node_bounds_grids(int grid_area, Span< float3 > positions, GridsNode &node)
Span< float3 > vert_positions_eval(const Depsgraph &depsgraph, const Object &object_orig)
void flush_bounds_to_parents(Tree &pbvh)
static BLI_NOINLINE void fill_factor_from_hide_and_mask(const Mesh &mesh, const Span< int > face_indices, const MutableSpan< float > r_factors)
void cache_init(bContext *C, Object &ob, const Sculpt &sd, undo::Type undo_type, const float mval_fl[2], float area_normal_radius, float start_strength)
void push_end(Object &ob)
void push_begin_ex(const Scene &, Object &ob, const char *name)
void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object)
static void elastic_transform_node_bmesh(const Sculpt &sd, const KelvinletParams ¶ms, const float4x4 &elastic_transform_mat, const float3 &elastic_transform_pivot, bke::pbvh::BMeshNode &node, Object &object, TransformLocalData &tls)
static BLI_NOINLINE void mask_border_weight_calc(const Span< float > masks, const MutableSpan< float > factors)
MutableSpan< float3 > gather_grids_positions(const SubdivCCG &subdiv_ccg, const Span< int > grids, Vector< float3 > &positions)
void gather_bmesh_positions(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions)
static std::array< float4x4, 8 > transform_matrices_init(const SculptSession &ss, const ePaintSymmetryFlags symm, const TransformDisplacementMode t_mode)
static bool set_pivot_position_poll_property(const bContext *, wmOperator *op, const PropertyRNA *prop)
void update_modal_transform(bContext *C, Object &ob)
static void transform_node_mesh(const Sculpt &sd, const std::array< float4x4, 8 > &transform_mats, const MeshAttributeData &attribute_data, const bke::pbvh::MeshNode &node, Object &object, TransformLocalData &tls, const PositionDeformData &position_data)
bool node_fully_masked_or_hidden(const bke::pbvh::Node &node)
static int set_pivot_position_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void transform_node_grids(const Sculpt &sd, const std::array< float4x4, 8 > &transform_mats, const bke::pbvh::GridsNode &node, Object &object, TransformLocalData &tls)
void flush_update_done(const bContext *C, Object &ob, UpdateType update_type)
float3 symmetry_flip(const float3 &src, const ePaintSymmetryFlags symm)
void orig_position_data_gather_bmesh(const BMLog &bm_log, const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions, MutableSpan< float3 > normals)
static BLI_NOINLINE void calc_symm_area_transform_translations(const Span< float3 > positions, const std::array< float4x4, 8 > &transform_mats, const MutableSpan< float3 > translations)
void scale_translations(MutableSpan< float3 > translations, Span< float > factors)
void end_transform(bContext *C, Object &ob)
void flush_update_step(bContext *C, UpdateType update_type)
static void elastic_transform_node_mesh(const Sculpt &sd, const KelvinletParams ¶ms, const float4x4 &elastic_transform_mat, const float3 &elastic_transform_pivot, const MeshAttributeData &attribute_data, const bke::pbvh::MeshNode &node, Object &object, TransformLocalData &tls, const PositionDeformData &position_data)
void init_transform(bContext *C, Object &ob, const float mval_fl[2], const char *undo_name)
void scale_factors(MutableSpan< float > factors, float strength)
static BLI_NOINLINE void filter_translations_with_symmetry(const Span< float3 > positions, const ePaintSymmetryFlags symm, const MutableSpan< float3 > translations)
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
static BLI_NOINLINE void accumulate_weighted_average_position(const Span< float3 > positions, const Span< float > factors, AveragePositionAccumulation &total)
static void elastic_transform_node_grids(const Sculpt &sd, const KelvinletParams ¶ms, const float4x4 &elastic_transform_mat, const float3 &elastic_transform_pivot, const bke::pbvh::GridsNode &node, Object &object, TransformLocalData &tls)
static void transform_node_bmesh(const Sculpt &sd, const std::array< float4x4, 8 > &transform_mats, bke::pbvh::BMeshNode &node, Object &object, TransformLocalData &tls)
static constexpr float transform_mirror_max_distance_eps
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
OrigPositionData orig_position_data_get_mesh(const Object &object, const bke::pbvh::MeshNode &node)
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
OrigPositionData orig_position_data_get_grids(const Object &object, const bke::pbvh::GridsNode &node)
static void sculpt_transform_all_vertices(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob)
static int set_pivot_position_exec(bContext *C, wmOperator *op)
static float3 average_unmasked_position(const Depsgraph &depsgraph, const Object &object, const float3 &pivot, const ePaintSymmetryFlags symm)
static BLI_NOINLINE void apply_kelvinet_to_translations(const KelvinletParams ¶ms, const float3 &elastic_transform_pivot, const Span< float3 > positions, const MutableSpan< float3 > translations)
static void transform_radius_elastic(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, const float transform_radius)
static BLI_NOINLINE void calc_transform_translations(const float4x4 &elastic_transform_mat, const Span< float3 > positions, const MutableSpan< float3 > r_translations)
static AveragePositionAccumulation combine_average_position_accumulation(const AveragePositionAccumulation &a, const AveragePositionAccumulation &b)
static float3 average_mask_border_position(const Depsgraph &depsgraph, const Object &object, const float3 &pivot, const ePaintSymmetryFlags symm)
static bool set_pivot_depends_on_cursor(bContext &, wmOperatorType &, PointerRNA *ptr)
static EnumPropertyItem prop_sculpt_pivot_position_types[]
TransformDisplacementMode
void SCULPT_OT_set_pivot_position(wmOperatorType *ot)
T safe_divide(const T &a, const T &b)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
VecBase< double, 3 > double3
VecBase< float, 3 > float3
float paint_calc_object_space_radius(const ViewContext &vc, const blender::float3 ¢er, float pixel_radius)
float RNA_float_get(PointerRNA *ptr, const char *name)
void RNA_float_set(PointerRNA *ptr, const char *name, float value)
int RNA_enum_get(PointerRNA *ptr, const char *name)
const char * RNA_property_identifier(const PropertyRNA *prop)
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, const float default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
ePaintSymmetryFlags SCULPT_mesh_symmetry_xyz_get(const Object &object)
bool SCULPT_stroke_get_location(bContext *C, float out[3], const float mval[2], bool force_original)
bool SCULPT_is_symmetry_iteration_valid(char i, char symm)
void SCULPT_vertex_random_access_ensure(Object &object)
float3 SCULPT_flip_v3_by_symm_area(const float3 &vector, const ePaintSymmetryFlags symm, const ePaintSymmetryAreas symmarea, const float3 &pivot)
bool SCULPT_mode_poll(bContext *C)
ePaintSymmetryAreas SCULPT_get_vertex_symm_area(const float co[3])
void SCULPT_flip_quat_by_symm_area(float quat[4], const ePaintSymmetryFlags symm, const ePaintSymmetryAreas symmarea, const float pivot[3])
struct SculptSession * sculpt
blender::float4 prev_pivot_rot
blender::ed::sculpt_paint::filter::Cache * filter_cache
blender::float3 prev_pivot_pos
blender::float4 pivot_rot
blender::float3 active_vert_position(const Depsgraph &depsgraph, const Object &object) const
blender::float3 pivot_pos
blender::float3 pivot_scale
blender::float3 init_pivot_pos
blender::float4 init_pivot_rot
blender::float3 prev_pivot_scale
blender::float3 init_pivot_scale
blender::Array< blender::float3 > positions
float average_stroke_accum[3]
int average_stroke_counter
Vector< float3 > positions
VArraySpan< bool > hide_vert
TransformDisplacementMode transform_displacement_mode
bool(* poll_property)(const bContext *C, wmOperator *op, const PropertyRNA *prop) ATTR_WARN_UNUSED_RESULT
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
bool(* depends_on_cursor)(bContext &C, wmOperatorType &ot, PointerRNA *ptr)
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
void WM_event_add_notifier(const bContext *C, uint type, void *reference)