Refactor: Sculpt: Split sculpt_intern.hh into separate header files

This commit takes the namespaces used in `sculpt_intern.hh` and splits
them into their own header files to better logically separate data and
avoid pulling in so many transitive dependencies by needing to include
`sculpt_intern.hh`

Actual removal of `sculpt_intern.hh` from other files is pending
further cleanup of the methods contained within.

A quick summary of the other changes included in this commit:
* `enum` to `enum class` cleanup for enums to enable forward
  declarations
* `FilterCache` default destructor to allow forward declaration of
  other dependent `struct`s contained in `unique_ptr`s
* Cleanup of unused headers
* Move `SculptBoundary` into the `boundary` namespace
* Move misc brush method forward declarations into `types.hh`

For a given `.cc` file that corresponds to a specific `.hh` file, the
header has been placed at the very top to try and ensure that the
needed data is self contained.

Forward declaration is preferred in most of these files outside of the
templates, classes, and structs in BLI headers.

---

Manual testing done:
- Enter Sculpt mode and perform strokes
- Use automasking for some strokes
- Use mesh filter

Pull Request: https://projects.blender.org/blender/blender/pulls/126443
This commit is contained in:
Sean Kim
2024-08-19 19:01:27 +02:00
committed by Sean Kim
parent 5930e0404a
commit 852b3dbff3
53 changed files with 1742 additions and 1400 deletions

View File

@@ -5,22 +5,19 @@
#include "editors/sculpt_paint/brushes/types.hh"
#include "DNA_brush_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_key.hh"
#include "BKE_mesh.hh"
#include "BKE_paint.hh"
#include "BKE_pbvh.hh"
#include "BLI_array.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_vector.hh"
#include "BLI_task.hh"
#include "editors/sculpt_paint/mesh_brush_common.hh"
#include "editors/sculpt_paint/sculpt_intern.hh"
#include "editors/sculpt_paint/sculpt_smooth.hh"
namespace blender::ed::sculpt_paint {

View File

@@ -13,9 +13,9 @@
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_base.hh"
#include "BLI_task.h"
#include "BLI_task.hh"
#include "editors/sculpt_paint/sculpt_face_set.hh"
#include "editors/sculpt_paint/sculpt_intern.hh"
namespace blender::ed::sculpt_paint {

View File

@@ -9,7 +9,6 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_key.hh"
#include "BKE_mesh.hh"
#include "BKE_paint.hh"
#include "BKE_pbvh.hh"
@@ -17,11 +16,11 @@
#include "BLI_array.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_vector.hh"
#include "BLI_task.hh"
#include "editors/sculpt_paint/mesh_brush_common.hh"
#include "editors/sculpt_paint/sculpt_intern.hh"
#include "editors/sculpt_paint/sculpt_smooth.hh"
namespace blender::ed::sculpt_paint {

View File

@@ -10,13 +10,14 @@
#include "BKE_subdiv_ccg.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_base.hh"
#include "BLI_math_geom.h"
#include "BLI_math_vector.hh"
#include "BLI_task.hh"
#include "editors/sculpt_paint/mesh_brush_common.hh"
#include "editors/sculpt_paint/sculpt_boundary.hh"
#include "editors/sculpt_paint/sculpt_face_set.hh"
#include "editors/sculpt_paint/sculpt_intern.hh"
#include "editors/sculpt_paint/sculpt_smooth.hh"
namespace blender::ed::sculpt_paint {

View File

@@ -9,7 +9,6 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_colortools.hh"
#include "BKE_key.hh"
#include "BKE_mesh.hh"
#include "BKE_paint.hh"
@@ -18,14 +17,13 @@
#include "BLI_array.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_matrix.hh"
#include "BLI_math_vector.hh"
#include "BLI_task.h"
#include "BLI_task.hh"
#include "BLI_virtual_array.hh"
#include "editors/sculpt_paint/mesh_brush_common.hh"
#include "editors/sculpt_paint/sculpt_boundary.hh"
#include "editors/sculpt_paint/sculpt_intern.hh"
#include "editors/sculpt_paint/sculpt_smooth.hh"
namespace blender::ed::sculpt_paint {

View File

@@ -12,11 +12,12 @@
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_base.hh"
#include "BLI_task.h"
#include "editors/sculpt_paint/mesh_brush_common.hh"
#include "editors/sculpt_paint/paint_intern.hh"
#include "editors/sculpt_paint/sculpt_boundary.hh"
#include "editors/sculpt_paint/sculpt_intern.hh"
#include "editors/sculpt_paint/sculpt_smooth.hh"
namespace blender::ed::sculpt_paint {

View File

@@ -17,12 +17,12 @@
#include "BLI_array.hh"
#include "BLI_array_utils.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_vector.hh"
#include "BLI_task.hh"
#include "BLI_virtual_array.hh"
#include "editors/sculpt_paint/mesh_brush_common.hh"
#include "editors/sculpt_paint/sculpt_intern.hh"
#include "editors/sculpt_paint/sculpt_smooth.hh"
namespace blender::ed::sculpt_paint {

View File

@@ -163,4 +163,18 @@ void do_topology_relax_brush(const Depsgraph &depsgraph,
Object &object,
Span<bke::pbvh::Node *> nodes);
namespace boundary {
void do_boundary_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
}
namespace cloth {
void do_cloth_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &object,
Span<bke::pbvh::Node *> nodes);
}
} // namespace blender::ed::sculpt_paint

View File

@@ -14,8 +14,6 @@
#include "BLI_utildefines.h"
#include "DNA_brush_types.h"
#include "DNA_color_types.h"
#include "DNA_customdata_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_object_types.h"
@@ -47,8 +45,6 @@
#include "ED_image.hh"
#include "ED_view3d.hh"
#include "DEG_depsgraph.hh"
#include "GPU_immediate.hh"
#include "GPU_immediate_util.hh"
#include "GPU_matrix.hh"
@@ -58,9 +54,13 @@
#include "UI_resources.hh"
#include "paint_intern.hh"
#include "sculpt_boundary.hh"
#include "sculpt_cloth.hh"
#include "sculpt_expand.hh"
/* still needed for sculpt_stroke_get_location, should be
* removed eventually (TODO) */
#include "sculpt_intern.hh"
#include "sculpt_pose.hh"
/* TODOs:
*

View File

@@ -6,6 +6,7 @@
* \ingroup edsculpt
* Implements the bke::pbvh::Tree node hiding operator.
*/
#include "sculpt_hide.hh"
#include "MEM_guardedalloc.h"
@@ -13,13 +14,11 @@
#include "BLI_bit_span_ops.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_geom.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_attribute.hh"
#include "BKE_ccg.hh"
@@ -37,7 +36,6 @@
#include "WM_types.hh"
#include "ED_screen.hh"
#include "ED_view3d.hh"
#include "RNA_access.hh"
#include "RNA_define.hh"
@@ -46,7 +44,9 @@
#include "mesh_brush_common.hh"
#include "paint_intern.hh"
#include "sculpt_gesture.hh"
#include "sculpt_intern.hh"
#include "sculpt_islands.hh"
namespace blender::ed::sculpt_paint::hide {

View File

@@ -17,14 +17,12 @@
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_base.hh"
#include "BLI_span.hh"
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
#include "BKE_attribute.hh"
#include "BKE_brush.hh"
#include "BKE_ccg.hh"
#include "BKE_context.hh"
#include "BKE_layer.hh"
#include "BKE_mesh.hh"
#include "BKE_multires.hh"
#include "BKE_paint.hh"
@@ -38,13 +36,15 @@
#include "WM_api.hh"
#include "WM_types.hh"
#include "ED_sculpt.hh"
#include "ED_select_utils.hh"
#include "bmesh.hh"
#include "paint_intern.hh"
#include "sculpt_gesture.hh"
#include "sculpt_hide.hh"
#include "sculpt_intern.hh"
#include "sculpt_undo.hh"
namespace blender::ed::sculpt_paint::mask {

View File

@@ -42,6 +42,7 @@
#include "IMB_imbuf_types.hh"
#include "paint_intern.hh"
#include "sculpt_cloth.hh"
#include "sculpt_intern.hh"
// #define DEBUG_TIME

View File

@@ -32,7 +32,6 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "RNA_access.hh"
@@ -46,7 +45,6 @@
#include "BKE_editmesh.hh"
#include "BKE_lib_id.hh"
#include "BKE_mesh.hh"
#include "BKE_mesh_mapping.hh"
#include "BKE_object.hh"
#include "BKE_object_deform.h"
#include "BKE_object_types.hh"
@@ -77,6 +75,9 @@
#include "mesh_brush_common.hh"
#include "paint_intern.hh" /* own include */
#include "sculpt_automask.hh"
#include "sculpt_boundary.hh"
#include "sculpt_cloth.hh"
#include "sculpt_intern.hh"
using blender::IndexRange;

View File

@@ -51,10 +51,7 @@
#include "BKE_image.h"
#include "BKE_key.hh"
#include "BKE_layer.hh"
#include "BKE_lib_id.hh"
#include "BKE_main.hh"
#include "BKE_mesh.hh"
#include "BKE_mesh_mapping.hh"
#include "BKE_modifier.hh"
#include "BKE_multires.hh"
#include "BKE_node_runtime.hh"
@@ -63,7 +60,6 @@
#include "BKE_paint.hh"
#include "BKE_pbvh_api.hh"
#include "BKE_report.hh"
#include "BKE_scene.hh"
#include "BKE_subdiv_ccg.hh"
#include "BKE_subsurf.hh"
#include "BLI_math_vector.hh"
@@ -83,7 +79,16 @@
#include "ED_view3d.hh"
#include "paint_intern.hh"
#include "sculpt_automask.hh"
#include "sculpt_boundary.hh"
#include "sculpt_cloth.hh"
#include "sculpt_color.hh"
#include "sculpt_dyntopo.hh"
#include "sculpt_face_set.hh"
#include "sculpt_filter.hh"
#include "sculpt_intern.hh"
#include "sculpt_islands.hh"
#include "sculpt_pose.hh"
#include "RNA_access.hh"
#include "RNA_define.hh"

View File

@@ -0,0 +1,72 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include <memory>
#include "BLI_sys_types.h"
#include "DNA_brush_enums.h"
struct Brush;
struct CurveMapping;
struct Depsgraph;
struct Object;
struct Sculpt;
struct SculptSession;
namespace blender::ed::sculpt_paint::auto_mask {
struct Settings {
/* eAutomasking_flag. */
int flags;
int initial_face_set;
int initial_island_nr;
float cavity_factor;
int cavity_blur_steps;
CurveMapping *cavity_curve;
float start_normal_limit, start_normal_falloff;
float view_normal_limit, view_normal_falloff;
bool topology_use_brush_limit;
};
struct Cache {
Settings settings;
bool can_reuse_mask;
uchar current_stroke_id;
};
/* Returns the automasking cache depending on the active tool. Used for code that can run both for
* brushes and filter. */
const Cache *active_cache_get(const SculptSession &ss);
/**
* Creates and initializes an automasking cache.
*
* For automasking modes that cannot be calculated in real time,
* data is also stored at the vertex level prior to the stroke starting.
*/
std::unique_ptr<Cache> cache_init(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob);
std::unique_ptr<Cache> cache_init(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush *brush,
Object &ob);
bool mode_enabled(const Sculpt &sd, const Brush *br, eAutomasking_flag mode);
bool is_enabled(const Sculpt &sd, const SculptSession *ss, const Brush *br);
bool needs_normal(const SculptSession &ss, const Sculpt &sd, const Brush *brush);
int settings_hash(const Object &ob, const Cache &automasking);
bool tool_can_reuse_automask(int sculpt_tool);
} // namespace blender::ed::sculpt_paint::auto_mask

View File

@@ -6,6 +6,8 @@
* \ingroup edsculpt
*/
#include "sculpt_automask.hh"
#include "MEM_guardedalloc.h"
#include "BLI_array.hh"
@@ -27,7 +29,14 @@
#include "mesh_brush_common.hh"
#include "paint_intern.hh"
#include "sculpt_boundary.hh"
#include "sculpt_dyntopo.hh"
#include "sculpt_face_set.hh"
#include "sculpt_filter.hh"
#include "sculpt_flood_fill.hh"
#include "sculpt_intern.hh"
#include "sculpt_islands.hh"
#include "sculpt_undo.hh"
#include "bmesh.hh"

View File

@@ -5,8 +5,7 @@
/** \file
* \ingroup edsculpt
*/
#include "MEM_guardedalloc.h"
#include "sculpt_boundary.hh"
#include "BLI_array_utils.hh"
#include "BLI_enumerable_thread_specific.hh"
@@ -26,12 +25,13 @@
#include "mesh_brush_common.hh"
#include "paint_intern.hh"
#include "sculpt_cloth.hh"
#include "sculpt_flood_fill.hh"
#include "sculpt_intern.hh"
#include "GPU_immediate.hh"
#include "GPU_state.hh"
#include <cmath>
#include <cstdlib>
namespace blender::ed::sculpt_paint::boundary {

View File

@@ -0,0 +1,152 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include <memory>
#include "BLI_array.hh"
#include "BLI_bit_span.hh"
#include "BLI_map.hh"
#include "BLI_math_vector.hh"
#include "BLI_offset_indices.hh"
#include "BLI_span.hh"
#include "BLI_vector.hh"
struct Brush;
struct BMVert;
struct Depsgraph;
struct Object;
struct PBVHVertRef;
struct Sculpt;
struct SculptBoundaryPreview;
struct SculptSession;
struct SubdivCCG;
struct SubdivCCGCoord;
namespace blender::bke::pbvh {
class Node;
}
namespace blender::ed::sculpt_paint::boundary {
struct SculptBoundary {
/* Vertex indices of the active boundary. */
Vector<int> verts;
/* Distance from a vertex in the boundary to initial vertex indexed by vertex index, taking into
* account the length of all edges between them. Any vertex that is not in the boundary will have
* a distance of 0. */
Map<int, float> distance;
/* Data for drawing the preview. */
Vector<std::pair<float3, float3>> edges;
/* Initial vertex index in the boundary which is closest to the current sculpt active vertex. */
int initial_vert_i;
/* Vertex that at max_propagation_steps from the boundary and closest to the original active
* vertex that was used to initialize the boundary. This is used as a reference to check how much
* the deformation will go into the mesh and to calculate the strength of the brushes. */
float3 pivot_position;
/* Stores the initial positions of the pivot and boundary initial vertex as they may be deformed
* during the brush action. This allows to use them as a reference positions and vectors for some
* brush effects. */
float3 initial_vert_position;
/* Maximum number of topology steps that were calculated from the boundary. */
int max_propagation_steps;
/* Indexed by vertex index, contains the topology information needed for boundary deformations.
*/
struct {
/* Vertex index from where the topology propagation reached this vertex. */
Array<int> original_vertex_i;
/* How many steps were needed to reach this vertex from the boundary. */
Array<int> propagation_steps_num;
/* Strength that is used to deform this vertex. */
Array<float> strength_factor;
} edit_info;
/* Bend Deform type. */
struct {
Array<float3> pivot_rotation_axis;
Array<float3> pivot_positions;
} bend;
/* Slide Deform type. */
struct {
Array<float3> directions;
} slide;
/* Twist Deform type. */
struct {
float3 rotation_axis;
float3 pivot_position;
} twist;
};
/**
* Populates boundary information for a mesh.
*
* \see SculptVertexInfo
*/
void ensure_boundary_info(Object &object);
/**
* Determine if a vertex is a boundary vertex.
*
* Requires #ensure_boundary_info to have been called.
*/
bool vert_is_boundary(const SculptSession &ss, PBVHVertRef vertex);
bool vert_is_boundary(Span<bool> hide_poly,
GroupedSpan<int> vert_to_face_map,
BitSpan boundary,
int vert);
bool vert_is_boundary(const SubdivCCG &subdiv_ccg,
Span<int> corner_verts,
OffsetIndices<int> faces,
BitSpan boundary,
SubdivCCGCoord vert);
bool vert_is_boundary(BMVert *vert);
/**
* Main function to get #SculptBoundary data both for brush deformation and viewport preview.
* Can return NULL if there is no boundary from the given vertex using the given radius.
*/
std::unique_ptr<SculptBoundary> data_init(const Depsgraph &depsgraph,
Object &object,
const Brush *brush,
PBVHVertRef initial_vert,
float radius);
std::unique_ptr<SculptBoundary> data_init_mesh(const Depsgraph &depsgraph,
Object &object,
const Brush *brush,
int initial_vert,
float radius);
std::unique_ptr<SculptBoundary> data_init_grids(Object &object,
const Brush *brush,
SubdivCCGCoord initial_vert,
float radius);
std::unique_ptr<SculptBoundary> data_init_bmesh(Object &object,
const Brush *brush,
BMVert *initial_vert,
float radius);
std::unique_ptr<SculptBoundaryPreview> preview_data_init(const Depsgraph &depsgraph,
Object &object,
const Brush *brush,
float radius);
void edges_preview_draw(uint gpuattr,
SculptSession &ss,
const float outline_col[3],
float outline_alpha);
void pivot_line_preview_draw(uint gpuattr, SculptSession &ss);
} // namespace blender::ed::sculpt_paint::boundary

View File

@@ -5,6 +5,7 @@
/** \file
* \ingroup edsculpt
*/
#include "sculpt_cloth.hh"
#include "MEM_guardedalloc.h"
@@ -28,7 +29,6 @@
#include "BKE_bvhutils.hh"
#include "BKE_ccg.hh"
#include "BKE_collision.h"
#include "BKE_colortools.hh"
#include "BKE_context.hh"
#include "BKE_layer.hh"
#include "BKE_mesh.hh"
@@ -37,7 +37,6 @@
#include "BKE_pbvh_api.hh"
#include "BKE_subdiv_ccg.hh"
#include "DEG_depsgraph.hh"
#include "DEG_depsgraph_query.hh"
#include "WM_api.hh"
@@ -46,7 +45,10 @@
#include "ED_sculpt.hh"
#include "mesh_brush_common.hh"
#include "paint_intern.hh"
#include "sculpt_automask.hh"
#include "sculpt_face_set.hh"
#include "sculpt_filter.hh"
#include "sculpt_hide.hh"
#include "sculpt_intern.hh"
#include "RNA_access.hh"

View File

@@ -0,0 +1,156 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include "BLI_array.hh"
#include "BLI_map.hh"
#include "BLI_math_vector.hh"
#include "BLI_vector.hh"
#include "BKE_collision.h"
struct Brush;
struct Sculpt;
struct SculptSession;
namespace blender::bke::pbvh {
class Node;
}
namespace blender::ed::sculpt_paint::cloth {
/* Cloth Simulation. */
enum NodeSimState {
/* Constraints were not built for this node, so it can't be simulated. */
SCULPT_CLOTH_NODE_UNINITIALIZED,
/* There are constraints for the geometry in this node, but it should not be simulated. */
SCULPT_CLOTH_NODE_INACTIVE,
/* There are constraints for this node and they should be used by the solver. */
SCULPT_CLOTH_NODE_ACTIVE,
};
enum ConstraintType {
/* Constraint that creates the structure of the cloth. */
SCULPT_CLOTH_CONSTRAINT_STRUCTURAL = 0,
/* Constraint that references the position of a vertex and a position in deformation_pos which
* can be deformed by the tools. */
SCULPT_CLOTH_CONSTRAINT_DEFORMATION = 1,
/* Constraint that references the vertex position and a editable soft-body position for
* plasticity. */
SCULPT_CLOTH_CONSTRAINT_SOFTBODY = 2,
/* Constraint that references the vertex position and its initial position. */
SCULPT_CLOTH_CONSTRAINT_PIN = 3,
};
struct LengthConstraint {
/* Elements that are affected by the constraint. */
/* Element a should always be a mesh vertex with the index stored in elem_index_a as it is always
* deformed. Element b could be another vertex of the same mesh or any other position (arbitrary
* point, position for a previous state). In that case, elem_index_a and elem_index_b should be
* the same to avoid affecting two different vertices when solving the constraints.
* *elem_position points to the position which is owned by the element. */
int elem_index_a;
float *elem_position_a;
int elem_index_b;
float *elem_position_b;
float length;
float strength;
/* Index in #SimulationData.node_state of the node from where this constraint was created.
* This constraints will only be used by the solver if the state is active. */
int node;
ConstraintType type;
};
struct SimulationData {
Vector<LengthConstraint> length_constraints;
Array<float> length_constraint_tweak;
/* Position anchors for deformation brushes. These positions are modified by the brush and the
* final positions of the simulated vertices are updated with constraints that use these points
* as targets. */
Array<float3> deformation_pos;
Array<float> deformation_strength;
float mass;
float damping;
float softbody_strength;
Array<float3> acceleration;
Array<float3> pos;
Array<float3> init_pos;
Array<float3> init_no;
Array<float3> softbody_pos;
Array<float3> prev_pos;
Array<float3> last_iteration_pos;
Vector<ColliderCache> collider_list;
int totnode;
Map<const bke::pbvh::Node *, int> node_state_index;
Array<NodeSimState> node_state;
~SimulationData();
};
/* Public functions. */
std::unique_ptr<SimulationData> brush_simulation_create(const Depsgraph &depsgraph,
Object &ob,
float cloth_mass,
float cloth_damping,
float cloth_softbody_strength,
bool use_collisions,
bool needs_deform_coords);
void sim_activate_nodes(SimulationData &cloth_sim, Span<blender::bke::pbvh::Node *> nodes);
void brush_store_simulation_state(const Depsgraph &depsgraph,
const Object &object,
SimulationData &cloth_sim);
void do_simulation_step(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
SimulationData &cloth_sim,
Span<blender::bke::pbvh::Node *> nodes);
void ensure_nodes_constraints(const Sculpt &sd,
const Object &ob,
Span<bke::pbvh::Node *> nodes,
SimulationData &cloth_sim,
const float3 &initial_location,
float radius);
/**
* Cursor drawing function.
*/
void simulation_limits_draw(uint gpuattr,
const Brush &brush,
const float location[3],
const float normal[3],
float rds,
float line_width,
const float outline_col[3],
float alpha);
void plane_falloff_preview_draw(uint gpuattr,
SculptSession &ss,
const float outline_col[3],
float outline_alpha);
Vector<blender::bke::pbvh::Node *> brush_affected_nodes_gather(SculptSession &ss,
const Brush &brush);
bool is_cloth_deform_brush(const Brush &brush);
} // namespace blender::ed::sculpt_paint::cloth

View File

@@ -0,0 +1,74 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include "DNA_scene_types.h"
#include "BLI_generic_span.hh"
#include "BLI_math_vector.hh"
#include "BLI_offset_indices.hh"
#include "BLI_span.hh"
struct Depsgraph;
namespace blender::bke {
enum class AttrDomain : int8_t;
struct GAttributeReader;
struct GSpanAttributeWriter;
namespace pbvh {
class Node;
}
} // namespace blender::bke
namespace blender::ed::sculpt_paint::color {
/* Swaps colors at each element in indices with values in colors. */
void swap_gathered_colors(Span<int> indices,
GMutableSpan color_attribute,
MutableSpan<float4> r_colors);
/* Stores colors from the elements in indices into colors. */
void gather_colors(GSpan color_attribute, Span<int> indices, MutableSpan<float4> r_colors);
/* Like gather_colors but handles loop->vert conversion */
void gather_colors_vert(OffsetIndices<int> faces,
Span<int> corner_verts,
GroupedSpan<int> vert_to_face_map,
GSpan color_attribute,
bke::AttrDomain color_domain,
Span<int> verts,
MutableSpan<float4> r_colors);
void color_vert_set(OffsetIndices<int> faces,
Span<int> corner_verts,
GroupedSpan<int> vert_to_face_map,
bke::AttrDomain color_domain,
int vert,
const float4 &color,
GMutableSpan color_attribute);
float4 color_vert_get(OffsetIndices<int> faces,
Span<int> corner_verts,
GroupedSpan<int> vert_to_face_map,
GSpan color_attribute,
bke::AttrDomain color_domain,
int vert);
bke::GAttributeReader active_color_attribute(const Mesh &mesh);
bke::GSpanAttributeWriter active_color_attribute_for_write(Mesh &mesh);
void do_paint_brush(const Depsgraph &depsgraph,
PaintModeSettings &paint_mode_settings,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes,
Span<bke::pbvh::Node *> texnodes);
void do_smear_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
} // namespace blender::ed::sculpt_paint::color

View File

@@ -5,6 +5,7 @@
/** \file
* \ingroup edsculpt
*/
#include "sculpt_dyntopo.hh"
#include "MEM_guardedalloc.h"
@@ -26,8 +27,6 @@
#include "BKE_pbvh_api.hh"
#include "BKE_screen.hh"
#include "DEG_depsgraph.hh"
#include "GPU_immediate.hh"
#include "GPU_immediate_util.hh"
#include "GPU_matrix.hh"
@@ -39,6 +38,7 @@
#include "ED_screen.hh"
#include "ED_space_api.hh"
#include "ED_view3d.hh"
#include "sculpt_intern.hh"
#include "RNA_access.hh"

View File

@@ -6,10 +6,12 @@
* \ingroup edsculpt
*/
#include "sculpt_intern.hh"
#include "sculpt_dyntopo.hh"
#include "BKE_object_types.hh"
#include "DNA_object_types.h"
#include "testing/testing.h"
namespace blender::ed::sculpt_paint::dyntopo::detail_size::test {

View File

@@ -5,6 +5,7 @@
/** \file
* \ingroup edsculpt
*/
#include "sculpt_dyntopo.hh"
#include <cmath>
#include <cstdlib>
@@ -26,15 +27,15 @@
#include "BKE_pointcache.h"
#include "BKE_scene.hh"
#include "BLI_index_range.hh"
#include "DEG_depsgraph.hh"
#include "WM_api.hh"
#include "WM_types.hh"
#include "ED_undo.hh"
#include "sculpt_intern.hh"
#include "sculpt_undo.hh"
#include "UI_interface.hh"
#include "UI_resources.hh"

View File

@@ -0,0 +1,97 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include "BLI_utildefines.h"
struct bContext;
struct BMesh;
struct Brush;
struct Depsgraph;
struct Main;
struct Object;
struct Scene;
struct SculptSession;
namespace blender::ed::sculpt_paint::undo {
struct StepData;
}
namespace blender::ed::sculpt_paint::dyntopo {
enum WarnFlag {
VDATA = (1 << 0),
EDATA = (1 << 1),
LDATA = (1 << 2),
MODIFIER = (1 << 3),
};
ENUM_OPERATORS(WarnFlag, MODIFIER);
/** Enable dynamic topology; mesh will be triangulated */
void enable_ex(Main &bmain, Depsgraph &depsgraph, Object &ob);
void disable(bContext *C, undo::StepData *undo_step);
void disable_with_undo(Main &bmain, Depsgraph &depsgraph, Scene &scene, Object &ob);
/**
* Returns true if the stroke will use dynamic topology, false
* otherwise.
*
* Factors: some brushes like grab cannot do dynamic topology.
* Others, like smooth, are better without.
* Same goes for alt-key smoothing.
*/
bool stroke_is_dyntopo(const SculptSession &ss, const Brush &brush);
void triangulate(BMesh *bm);
WarnFlag check_attribute_warning(Scene &scene, Object &ob);
namespace detail_size {
/**
* Scaling factor to match the displayed size to the actual sculpted size
*/
constexpr float RELATIVE_SCALE_FACTOR = 0.4f;
/**
* Converts from Sculpt#constant_detail to the pbvh::Tree max edge length.
*/
float constant_to_detail_size(float constant_detail, const Object &ob);
/**
* Converts from Sculpt#detail_percent to the pbvh::Tree max edge length.
*/
float brush_to_detail_size(float brush_percent, float brush_radius);
/**
* Converts from Sculpt#detail_size to the pbvh::Tree max edge length.
*/
float relative_to_detail_size(float relative_detail,
float brush_radius,
float pixel_radius,
float pixel_size);
/**
* Converts from Sculpt#constant_detail to equivalent Sculpt#detail_percent value.
*
* Corresponds to a change from Constant & Manual Detailing to Brush Detailing.
*/
float constant_to_brush_detail(float constant_detail, float brush_radius, const Object &ob);
/**
* Converts from Sculpt#constant_detail to equivalent Sculpt#detail_size value.
*
* Corresponds to a change from Constant & Manual Detailing to Relative Detailing.
*/
float constant_to_relative_detail(float constant_detail,
float brush_radius,
float pixel_radius,
float pixel_size,
const Object &ob);
} // namespace detail_size
} // namespace blender::ed::sculpt_paint::dyntopo

View File

@@ -5,6 +5,7 @@
/** \file
* \ingroup edsculpt
*/
#include "sculpt_expand.hh"
#include <cmath>
#include <cstdlib>
@@ -41,8 +42,16 @@
#include "ED_screen.hh"
#include "ED_sculpt.hh"
#include "paint_intern.hh"
#include "sculpt_boundary.hh"
#include "sculpt_color.hh"
#include "sculpt_face_set.hh"
#include "sculpt_flood_fill.hh"
#include "sculpt_geodesic.hh"
#include "sculpt_intern.hh"
#include "sculpt_islands.hh"
#include "sculpt_smooth.hh"
#include "IMB_colormanagement.hh"
#include "IMB_imbuf.hh"
@@ -852,7 +861,7 @@ static Array<float> boundary_topology_falloff_create(const Depsgraph &depsgraph,
const PBVHVertRef symm_vertex = BKE_pbvh_index_to_vertex(*ss.pbvh, vert);
std::unique_ptr<SculptBoundary> boundary = boundary::data_init(
std::unique_ptr<boundary::SculptBoundary> boundary = boundary::data_init(
depsgraph, ob, nullptr, symm_vertex, FLT_MAX);
if (!boundary) {
continue;

View File

@@ -0,0 +1,178 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include "BLI_array.hh"
#include "BLI_math_vector.hh"
#include "BLI_set.hh"
#include "BKE_pbvh.hh"
struct Brush;
struct Scene;
namespace blender::bke::pbvh {
class Node;
}
namespace blender::ed::sculpt_paint::expand {
enum class FalloffType {
Geodesic,
Topology,
TopologyNormals,
Normals,
Sphere,
BoundaryTopology,
BoundaryFaceSet,
ActiveFaceSet,
};
enum class TargetType {
Mask,
FaceSets,
Colors,
};
enum class RecursionType {
Topology,
Geodesic,
};
#define EXPAND_SYMM_AREAS 8
struct Cache {
/* Target data elements that the expand operation will affect. */
TargetType target;
/* Falloff data. */
FalloffType falloff_type;
/* Indexed by vertex index, precalculated falloff value of that vertex (without any falloff
* editing modification applied). */
Array<float> vert_falloff;
/* Max falloff value in *vert_falloff. */
float max_vert_falloff;
/* Indexed by base mesh face index, precalculated falloff value of that face. These values are
* calculated from the per vertex falloff (*vert_falloff) when needed. */
Array<float> face_falloff;
float max_face_falloff;
/* Falloff value of the active element (vertex or base mesh face) that Expand will expand to. */
float active_falloff;
/* When set to true, expand skips all falloff computations and considers all elements as enabled.
*/
bool all_enabled;
/* Initial mouse and cursor data from where the current falloff started. This data can be changed
* during the execution of Expand by moving the origin. */
float2 initial_mouse_move;
float2 initial_mouse;
PBVHVertRef initial_active_vertex;
int initial_active_vertex_i;
int initial_active_face_set;
/* Maximum number of vertices allowed in the SculptSession for previewing the falloff using
* geodesic distances. */
int max_geodesic_move_preview;
/* Original falloff type before starting the move operation. */
FalloffType move_original_falloff_type;
/* Falloff type using when moving the origin for preview. */
FalloffType move_preview_falloff_type;
/* Face set ID that is going to be used when creating a new Face Set. */
int next_face_set;
/* Face Set ID of the Face set selected for editing. */
int update_face_set;
/* Mouse position since the last time the origin was moved. Used for reference when moving the
* initial position of Expand. */
float2 original_mouse_move;
/* Active island checks. */
/* Indexed by symmetry pass index, contains the connected island ID for that
* symmetry pass. Other connected island IDs not found in this
* array will be ignored by Expand. */
int active_connected_islands[EXPAND_SYMM_AREAS];
/* Snapping. */
/* Set containing all Face Sets IDs that Expand will use to snap the new data. */
std::unique_ptr<Set<int>> snap_enabled_face_sets;
/* Texture distortion data. */
const Brush *brush;
Scene *scene;
// struct MTex *mtex;
/* Controls how much texture distortion will be applied to the current falloff */
float texture_distortion_strength;
/* Cached pbvh::Tree nodes. This allows to skip gathering all nodes from the pbvh::Tree each time
* expand needs to update the state of the elements. */
Vector<bke::pbvh::Node *> nodes;
/* Expand state options. */
/* Number of loops (times that the falloff is going to be repeated). */
int loop_count;
/* Invert the falloff result. */
bool invert;
/* When set to true, preserves the previous state of the data and adds the new one on top. */
bool preserve;
/* When set to true, the mask or colors will be applied as a gradient. */
bool falloff_gradient;
/* When set to true, Expand will use the Brush falloff curve data to shape the gradient. */
bool brush_gradient;
/* When set to true, Expand will move the origin (initial active vertex and cursor position)
* instead of updating the active vertex and active falloff. */
bool move;
/* When set to true, Expand will snap the new data to the Face Sets IDs found in
* *original_face_sets. */
bool snap;
/* When set to true, Expand will use the current Face Set ID to modify an existing Face Set
* instead of creating a new one. */
bool modify_active_face_set;
/* When set to true, Expand will reposition the sculpt pivot to the boundary of the expand result
* after finishing the operation. */
bool reposition_pivot;
/* If nothing is masked set mask of every vertex to 0. */
bool auto_mask;
/* Color target data type related data. */
float fill_color[4];
short blend_mode;
/* Face Sets at the first step of the expand operation, before starting modifying the active
* vertex and active falloff. These are not the original Face Sets of the sculpt before starting
* the operator as they could have been modified by Expand when initializing the operator and
* before starting changing the active vertex. These Face Sets are used for restoring and
* checking the Face Sets state while the Expand operation modal runs. */
Array<int> initial_face_sets;
/* Original data of the sculpt as it was before running the Expand operator. */
Array<float> original_mask;
Array<int> original_face_sets;
Array<float4> original_colors;
bool check_islands;
int normal_falloff_blur_steps;
};
} // namespace blender::ed::sculpt_paint::expand

View File

@@ -5,6 +5,7 @@
/** \file
* \ingroup edsculpt
*/
#include "sculpt_face_set.hh"
#include <cmath>
#include <cstdlib>
@@ -27,14 +28,12 @@
#include "BLI_task.hh"
#include "BLI_vector.hh"
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "BKE_attribute.hh"
#include "BKE_ccg.hh"
#include "BKE_colortools.hh"
#include "BKE_context.hh"
#include "BKE_customdata.hh"
#include "BKE_layer.hh"
@@ -55,7 +54,10 @@
#include "mesh_brush_common.hh"
#include "paint_intern.hh"
#include "sculpt_boundary.hh"
#include "sculpt_gesture.hh"
#include "sculpt_intern.hh"
#include "sculpt_islands.hh"
#include "RNA_access.hh"
#include "RNA_define.hh"

View File

@@ -0,0 +1,83 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include "BLI_array.hh"
#include "BLI_offset_indices.hh"
#include "BLI_set.hh"
#include "BLI_span.hh"
#include "BKE_attribute.hh"
struct BMVert;
struct Mesh;
struct Object;
struct PBVHVertRef;
struct SculptSession;
struct SubdivCCG;
struct SubdivCCGCoord;
namespace blender::ed::sculpt_paint::face_set {
int active_face_set_get(const SculptSession &ss);
int vert_face_set_get(const SculptSession &ss, PBVHVertRef vertex);
int vert_face_set_get(GroupedSpan<int> vert_to_face_map, Span<int> face_sets, int vert);
bool vert_has_face_set(const SculptSession &ss, PBVHVertRef vertex, int face_set);
bool vert_has_face_set(GroupedSpan<int> vert_to_face_map,
const int *face_sets,
int vert,
int face_set);
bool vert_has_face_set(const SubdivCCG &subdiv_ccg, const int *face_sets, int grid, int face_set);
bool vert_has_face_set(int face_set_offset, const BMVert &vert, int face_set);
bool vert_has_unique_face_set(const SculptSession &ss, PBVHVertRef vertex);
bool vert_has_unique_face_set(GroupedSpan<int> vert_to_face_map, const int *face_sets, int vert);
bool vert_has_unique_face_set(GroupedSpan<int> vert_to_face_map,
Span<int> corner_verts,
OffsetIndices<int> faces,
const int *face_sets,
const SubdivCCG &subdiv_ccg,
SubdivCCGCoord coord);
bool vert_has_unique_face_set(const BMVert *vert);
/**
* Creates the sculpt face set attribute on the mesh if it doesn't exist.
*
* \see face_set::ensure_face_sets_mesh if further writing to the attribute is desired.
*/
bool create_face_sets_mesh(Object &object);
/**
* Ensures that the sculpt face set attribute exists on the mesh.
*
* \see face_set::create_face_sets_mesh to avoid having to remember to call .finish()
*/
bke::SpanAttributeWriter<int> ensure_face_sets_mesh(Object &object);
int ensure_face_sets_bmesh(Object &object);
Array<int> duplicate_face_sets(const Mesh &mesh);
Set<int> gather_hidden_face_sets(Span<bool> hide_poly, Span<int> face_sets);
void filter_verts_with_unique_face_sets_mesh(GroupedSpan<int> vert_to_face_map,
const int *face_sets,
bool unique,
Span<int> verts,
MutableSpan<float> factors);
void filter_verts_with_unique_face_sets_grids(GroupedSpan<int> vert_to_face_map,
Span<int> corner_verts,
OffsetIndices<int> faces,
const SubdivCCG &subdiv_ccg,
const int *face_sets,
bool unique,
Span<int> grids,
MutableSpan<float> factors);
void filter_verts_with_unique_face_sets_bmesh(bool unique,
const Set<BMVert *, 0> verts,
MutableSpan<float> factors);
} // namespace blender::ed::sculpt_paint::face_set

View File

@@ -0,0 +1,127 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include <array>
#include "BLI_array.hh"
#include "BLI_math_matrix.hh"
#include "BLI_math_vector.hh"
#include "BLI_vector.hh"
#include "ED_view3d.hh"
struct wmOperatorType;
namespace blender {
namespace bke::pbvh {
class Node;
}
namespace ed::sculpt_paint {
enum class TransformDisplacementMode;
namespace auto_mask {
struct Cache;
}
namespace cloth {
struct SimulationData;
}
namespace undo {
enum class Type : int8_t;
}
} // namespace ed::sculpt_paint
} // namespace blender
namespace blender::ed::sculpt_paint::filter {
enum class FilterOrientation {
Local = 0,
World = 1,
View = 2,
};
struct Cache {
std::array<bool, 3> enabled_axis;
int random_seed;
/* Used for alternating between filter operations in filters that need to apply different ones to
* achieve certain effects. */
int iteration_count;
/* Stores the displacement produced by the laplacian step of HC smooth. */
Array<float3> surface_smooth_laplacian_disp;
float surface_smooth_shape_preservation;
float surface_smooth_current_vertex;
/* Sharpen mesh filter. */
float sharpen_smooth_ratio;
float sharpen_intensify_detail_strength;
int sharpen_curvature_smooth_iterations;
Array<float> sharpen_factor;
Array<float3> detail_directions;
/* Filter orientation. */
FilterOrientation orientation;
float4x4 obmat;
float4x4 obmat_inv;
float4x4 viewmat;
float4x4 viewmat_inv;
/* Displacement eraser. */
Array<float3> limit_surface_co;
/* unmasked nodes */
Vector<bke::pbvh::Node *> nodes;
/* Cloth filter. */
std::unique_ptr<cloth::SimulationData> cloth_sim;
float3 cloth_sim_pinch_point;
/* mask expand iteration caches */
int mask_update_current_it;
int mask_update_last_it;
Array<int> mask_update_it;
Array<float> normal_factor;
Array<float> edge_factor;
Array<float> prev_mask;
float3 mask_expand_initial_co;
int new_face_set;
Array<int> prev_face_set;
int active_face_set;
TransformDisplacementMode transform_displacement_mode;
std::unique_ptr<auto_mask::Cache> automasking;
float3 initial_normal;
float3 view_normal;
/* Pre-smoothed colors used by sharpening. Colors are HSL. */
Array<float4> pre_smoothed_color;
ViewContext vc;
float start_filter_strength;
~Cache();
};
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 register_operator_props(wmOperatorType *ot);
/* Filter orientation utils. */
float3x3 to_orientation_space(const filter::Cache &filter_cache);
float3x3 to_object_space(const filter::Cache &filter_cache);
void zero_disabled_axis_components(const filter::Cache &filter_cache, MutableSpan<float3> vectors);
} // namespace blender::ed::sculpt_paint::filter

View File

@@ -16,8 +16,6 @@
#include "BLT_translation.hh"
#include "DNA_userdef_types.h"
#include "BKE_attribute.hh"
#include "BKE_context.hh"
#include "BKE_layer.hh"
@@ -33,7 +31,11 @@
#include "ED_paint.hh"
#include "mesh_brush_common.hh"
#include "sculpt_automask.hh"
#include "sculpt_color.hh"
#include "sculpt_filter.hh"
#include "sculpt_intern.hh"
#include "sculpt_smooth.hh"
#include "RNA_access.hh"
#include "RNA_define.hh"

View File

@@ -23,16 +23,15 @@
#include "mesh_brush_common.hh"
#include "paint_intern.hh"
#include "sculpt_hide.hh"
#include "sculpt_intern.hh"
#include "sculpt_smooth.hh"
#include "RNA_access.hh"
#include "RNA_define.hh"
#include "bmesh.hh"
#include <cmath>
#include <cstdlib>
namespace blender::ed::sculpt_paint::mask {
enum class FilterType {

View File

@@ -5,6 +5,7 @@
/** \file
* \ingroup edsculpt
*/
#include "sculpt_filter.hh" // TODO- Move this function's initialization to a separate file
#include <fmt/format.h>
@@ -42,7 +43,12 @@
#include "mesh_brush_common.hh"
#include "paint_intern.hh"
#include "sculpt_automask.hh"
#include "sculpt_boundary.hh"
#include "sculpt_cloth.hh"
#include "sculpt_face_set.hh"
#include "sculpt_intern.hh"
#include "sculpt_smooth.hh"
#include "RNA_access.hh"
#include "RNA_define.hh"
@@ -117,6 +123,8 @@ void zero_disabled_axis_components(const filter::Cache &filter_cache,
}
}
Cache::~Cache() {}
void cache_init(bContext *C,
Object &ob,
const Sculpt &sd,

View File

@@ -1,12 +1,14 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "sculpt_flood_fill.hh"
#include "BKE_mesh.hh"
#include "DNA_mesh_types.h"
#include "paint_intern.hh"
#include "sculpt_hide.hh"
#include "sculpt_intern.hh"
/* -------------------------------------------------------------------- */
@@ -15,9 +17,7 @@
* Iterate over connected vertices, starting from one or more initial vertices.
* \{ */
namespace blender::ed::sculpt_paint {
namespace flood_fill {
namespace blender::ed::sculpt_paint::flood_fill {
FillData init_fill(SculptSession &ss)
{
@@ -354,8 +354,6 @@ void FillDataBMesh::execute(Object & /*object*/,
}
}
} // namespace flood_fill
} // namespace blender::ed::sculpt_paint
} // namespace blender::ed::sculpt_paint::flood_fill
/** \} */

View File

@@ -0,0 +1,99 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include <queue>
#include "BLI_bit_vector.hh"
#include "BLI_function_ref.hh"
#include "BLI_offset_indices.hh"
#include "BKE_pbvh.hh"
#include "BKE_subdiv_ccg.hh"
struct Depsgraph;
struct Object;
struct SculptSession;
namespace blender::ed::sculpt_paint::flood_fill {
struct FillData {
std::queue<PBVHVertRef> queue;
BitVector<> visited_verts;
};
struct FillDataMesh {
FillDataMesh(int size) : visited_verts(size) {}
std::queue<int> queue;
BitVector<> visited_verts;
void add_initial(int vertex);
void add_and_skip_initial(int vertex, int index);
void add_initial_with_symmetry(const Depsgraph &depsgraph,
const Object &object,
const bke::pbvh::Tree &pbvh,
int vertex,
float radius);
void execute(Object &object,
GroupedSpan<int> vert_to_face_map,
FunctionRef<bool(int from_v, int to_v)> func);
};
struct FillDataGrids {
FillDataGrids(int size) : visited_verts(size) {}
std::queue<SubdivCCGCoord> queue;
BitVector<> visited_verts;
void add_initial(SubdivCCGCoord vertex);
void add_and_skip_initial(SubdivCCGCoord vertex, int index);
void add_initial_with_symmetry(const Object &object,
const bke::pbvh::Tree &pbvh,
const SubdivCCG &subdiv_ccg,
SubdivCCGCoord vertex,
float radius);
void execute(
Object &object,
const SubdivCCG &subdiv_ccg,
FunctionRef<bool(SubdivCCGCoord from_v, SubdivCCGCoord to_v, bool is_duplicate)> func);
};
struct FillDataBMesh {
FillDataBMesh(int size) : visited_verts(size) {}
std::queue<BMVert *> queue;
BitVector<> visited_verts;
void add_initial(BMVert *vertex);
void add_and_skip_initial(BMVert *vertex, int index);
void add_initial_with_symmetry(const Object &object,
const bke::pbvh::Tree &pbvh,
BMVert *vertex,
float radius);
void execute(Object &object, FunctionRef<bool(BMVert *from_v, BMVert *to_v)> func);
};
/**
* \deprecated See the individual FillData constructors instead of this method.
*/
FillData init_fill(SculptSession &ss);
void add_initial(FillData &flood, PBVHVertRef vertex);
void add_and_skip_initial(FillData &flood, PBVHVertRef vertex);
void add_initial_with_symmetry(const Depsgraph &depsgraph,
const Object &ob,
FillData &flood,
PBVHVertRef vertex,
float radius);
void execute(Object &object,
FillData &flood,
FunctionRef<bool(PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate)> func);
} // namespace blender::ed::sculpt_paint::flood_fill

View File

@@ -0,0 +1,36 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include "BLI_array.hh"
#include "BLI_set.hh"
struct Depsgraph;
struct Object;
struct PBVHVertRef;
namespace blender::ed::sculpt_paint::geodesic {
/**
* Returns an array indexed by vertex index containing the geodesic distance to the closest vertex
* in the initial vertex set. The caller is responsible for freeing the array.
* Geodesic distances will only work when used with blender::bke::pbvh::Type::Mesh, for other
* types of blender::bke::pbvh::Tree it will fallback to euclidean distances to one of the initial
* vertices in the set.
*/
Array<float> distances_create(const Depsgraph &depsgraph,
Object &ob,
const Set<int> &initial_verts,
float limit_radius);
Array<float> distances_create_from_vert_and_symm(const Depsgraph &depsgraph,
Object &ob,
PBVHVertRef vertex,
float limit_radius);
} // namespace blender::ed::sculpt_paint::geodesic

View File

@@ -6,11 +6,12 @@
* \ingroup edsculpt
* Common helper methods and structures for gesture operations.
*/
#include "sculpt_gesture.hh"
#include "MEM_guardedalloc.h"
#include "DNA_vec_types.h"
#include "BLI_bit_vector.hh"
#include "BLI_bitmap_draw_2d.h"
#include "BLI_lasso_2d.hh"
#include "BLI_math_geom.h"

View File

@@ -0,0 +1,151 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include "BLI_array.hh"
#include "BLI_bit_vector.hh"
#include "BLI_math_matrix.hh"
#include "BLI_vector.hh"
#include "DNA_scene_enums.h"
#include "DNA_vec_types.h"
#include "ED_view3d.hh"
struct SculptSession;
struct wmOperatorType;
namespace blender::bke::pbvh {
class Node;
}
namespace blender::ed::sculpt_paint::gesture {
enum ShapeType {
Box = 0,
/* In the context of a sculpt gesture, both lasso and polyline modal
* operators are handled as the same general shape. */
Lasso = 1,
Line = 2,
};
enum class SelectionType {
Inside = 0,
Outside = 1,
};
/* Common data structure for both lasso and polyline. */
struct LassoData {
float4x4 projviewobjmat;
rcti boundbox;
int width;
/* 2D bitmap to test if a vertex is affected by the surrounding shape. */
blender::BitVector<> mask_px;
};
struct LineData {
/* Plane aligned to the gesture line. */
float true_plane[4];
float plane[4];
/* Planes to limit the action to the length of the gesture segment at both sides of the affected
* area. */
float side_plane[2][4];
float true_side_plane[2][4];
bool use_side_planes;
bool flip;
};
struct Operation;
/* Common data used for executing a gesture operation. */
struct GestureData {
SculptSession *ss;
ViewContext vc;
/* Enabled and currently active symmetry. */
ePaintSymmetryFlags symm;
ePaintSymmetryFlags symmpass;
/* Operation parameters. */
ShapeType shape_type;
bool front_faces_only;
SelectionType selection_type;
Operation *operation;
/* Gesture data. */
/* Screen space points that represent the gesture shape. */
Array<float2> gesture_points;
/* View parameters. */
float3 true_view_normal;
float3 view_normal;
float3 true_view_origin;
float3 view_origin;
float true_clip_planes[4][4];
float clip_planes[4][4];
/* These store the view origin and normal in world space, which is used in some gestures to
* generate geometry aligned from the view directly in world space. */
/* World space view origin and normal are not affected by object symmetry when doing symmetry
* passes, so there is no separate variables with the `true_` prefix to store their original
* values without symmetry modifications. */
float3 world_space_view_origin;
float3 world_space_view_normal;
/* Lasso & Polyline Gesture. */
LassoData lasso;
/* Line Gesture. */
LineData line;
/* Task Callback Data. */
Vector<bke::pbvh::Node *> nodes;
~GestureData();
};
/* Common abstraction structure for gesture operations. */
struct Operation {
/* Initial setup (data updates, special undo push...). */
void (*begin)(bContext &, wmOperator &, GestureData &);
/* Apply the gesture action for each symmetry pass. */
void (*apply_for_symmetry_pass)(bContext &, GestureData &);
/* Remaining actions after finishing the symmetry passes iterations
* (updating data-layers, tagging bke::pbvh::Tree updates...). */
void (*end)(bContext &, GestureData &);
};
/* Determines whether or not a gesture action should be applied. */
bool is_affected(const GestureData &gesture_data, const float3 &position, const float3 &normal);
void filter_factors(const GestureData &gesture_data,
Span<float3> positions,
Span<float3> normals,
MutableSpan<float> factors);
/* Initialization functions. */
std::unique_ptr<GestureData> init_from_box(bContext *C, wmOperator *op);
std::unique_ptr<GestureData> init_from_lasso(bContext *C, wmOperator *op);
std::unique_ptr<GestureData> init_from_polyline(bContext *C, wmOperator *op);
std::unique_ptr<GestureData> init_from_line(bContext *C, wmOperator *op);
/* Common gesture operator properties. */
void operator_properties(wmOperatorType *ot, ShapeType shapeType);
/* Apply the gesture action to the selected nodes. */
void apply(bContext &C, GestureData &gesture_data, wmOperator &op);
} // namespace blender::ed::sculpt_paint::gesture

View File

@@ -0,0 +1,39 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include "BLI_offset_indices.hh"
#include "BLI_span.hh"
#include "BLI_vector.hh"
struct BMVert;
struct Object;
struct PBVHVertRef;
struct SubdivCCG;
struct SubdivCCGCoord;
namespace blender::bke::pbvh {
class Node;
}
namespace blender::ed::sculpt_paint::hide {
Span<int> node_visible_verts(const bke::pbvh::Node &node,
Span<bool> hide_vert,
Vector<int> &indices);
bool vert_visible_get(const Object &object, PBVHVertRef vertex);
/* Determines if all faces attached to a given vertex are visible. */
bool vert_all_faces_visible_get(Span<bool> hide_poly, GroupedSpan<int> vert_to_face_map, int vert);
bool vert_all_faces_visible_get(Span<bool> hide_poly,
const SubdivCCG &subdiv_ccg,
SubdivCCGCoord vert);
bool vert_all_faces_visible_get(BMVert *vert);
} // namespace blender::ed::sculpt_paint::hide

View File

@@ -12,13 +12,11 @@
#include <queue>
#include "BKE_attribute.hh"
#include "BKE_collision.h"
#include "BKE_paint.hh"
#include "BKE_pbvh_api.hh"
#include "BKE_subdiv_ccg.hh"
#include "BLI_array.hh"
#include "BLI_bit_vector.hh"
#include "BLI_generic_array.hh"
#include "BLI_math_matrix_types.hh"
#include "BLI_math_vector_types.hh"
@@ -29,12 +27,16 @@
#include "DNA_brush_enums.h"
#include "ED_view3d.hh"
#include "sculpt_undo.hh"
namespace blender::ed::sculpt_paint {
namespace auto_mask {
struct NodeData;
struct Cache;
}
namespace boundary {
struct SculptBoundary;
}
namespace cloth {
struct SimulationData;
}
@@ -118,56 +120,6 @@ struct SculptOrigVertData {
const float *col;
};
namespace blender::ed::sculpt_paint::undo {
enum class Type : int8_t {
None,
Position,
HideVert,
HideFace,
Mask,
DyntopoBegin,
DyntopoEnd,
DyntopoSymmetrize,
Geometry,
FaceSet,
Color,
};
struct Node {
Array<float3> position;
Array<float3> orig_position;
Array<float3> normal;
Array<float4> col;
Array<float> mask;
Array<float4> loop_col;
Array<float4> orig_loop_col;
/* Mesh. */
Array<int> vert_indices;
int unique_verts_num;
Array<int> corner_indices;
BitVector<> vert_hidden;
BitVector<> face_hidden;
/* Multires. */
/** Indices of grids in the pbvh::Tree node. */
Array<int> grids;
BitGroupVector<> grid_hidden;
/* Sculpt Face Sets */
Array<int> face_sets;
Vector<int> face_indices;
};
}
/* Factor of brush to have rake point following behind
* (could be configurable but this is reasonable default). */
#define SCULPT_RAKE_BRUSH_FACTOR 0.25f
@@ -178,92 +130,20 @@ struct SculptRakeData {
float angle;
};
/* Defines how transform tools are going to apply its displacement. */
enum SculptTransformDisplacementMode {
namespace blender::ed::sculpt_paint {
enum class TransformDisplacementMode {
/* Displaces the elements from their original coordinates. */
SCULPT_TRANSFORM_DISPLACEMENT_ORIGINAL = 0,
Original = 0,
/* Displaces the elements incrementally from their previous position. */
SCULPT_TRANSFORM_DISPLACEMENT_INCREMENTAL = 1,
Incremental = 1,
};
}
/* Defines how transform tools are going to apply its displacement. */
#define SCULPT_CLAY_STABILIZER_LEN 10
namespace blender::ed::sculpt_paint {
namespace filter {
enum class FilterOrientation {
Local = 0,
World = 1,
View = 2,
};
struct Cache {
std::array<bool, 3> enabled_axis;
int random_seed;
/* Used for alternating between filter operations in filters that need to apply different ones to
* achieve certain effects. */
int iteration_count;
/* Stores the displacement produced by the laplacian step of HC smooth. */
Array<float3> surface_smooth_laplacian_disp;
float surface_smooth_shape_preservation;
float surface_smooth_current_vertex;
/* Sharpen mesh filter. */
float sharpen_smooth_ratio;
float sharpen_intensify_detail_strength;
int sharpen_curvature_smooth_iterations;
Array<float> sharpen_factor;
Array<float3> detail_directions;
/* Filter orientation. */
FilterOrientation orientation;
float4x4 obmat;
float4x4 obmat_inv;
float4x4 viewmat;
float4x4 viewmat_inv;
/* Displacement eraser. */
Array<float3> limit_surface_co;
/* unmasked nodes */
Vector<bke::pbvh::Node *> nodes;
/* Cloth filter. */
std::unique_ptr<cloth::SimulationData> cloth_sim;
float3 cloth_sim_pinch_point;
/* mask expand iteration caches */
int mask_update_current_it;
int mask_update_last_it;
Array<int> mask_update_it;
Array<float> normal_factor;
Array<float> edge_factor;
Array<float> prev_mask;
float3 mask_expand_initial_co;
int new_face_set;
Array<int> prev_face_set;
int active_face_set;
SculptTransformDisplacementMode transform_displacement_mode;
std::unique_ptr<auto_mask::Cache> automasking;
float3 initial_normal;
float3 view_normal;
/* Pre-smoothed colors used by sharpening. Colors are HSL. */
Array<float4> pre_smoothed_color;
ViewContext vc;
float start_filter_strength;
};
}
/** Pose Brush IK Chain. */
struct SculptPoseIKChainSegment {
float3 orig;
@@ -288,65 +168,6 @@ struct SculptPoseIKChain {
float3 grab_delta_offset;
};
struct SculptBoundary {
/* Vertex indices of the active boundary. */
Vector<int> verts;
/* Distance from a vertex in the boundary to initial vertex indexed by vertex index, taking into
* account the length of all edges between them. Any vertex that is not in the boundary will have
* a distance of 0. */
Map<int, float> distance;
/* Data for drawing the preview. */
Vector<std::pair<float3, float3>> edges;
/* Initial vertex index in the boundary which is closest to the current sculpt active vertex. */
int initial_vert_i;
/* Vertex that at max_propagation_steps from the boundary and closest to the original active
* vertex that was used to initialize the boundary. This is used as a reference to check how much
* the deformation will go into the mesh and to calculate the strength of the brushes. */
float3 pivot_position;
/* Stores the initial positions of the pivot and boundary initial vertex as they may be deformed
* during the brush action. This allows to use them as a reference positions and vectors for some
* brush effects. */
float3 initial_vert_position;
/* Maximum number of topology steps that were calculated from the boundary. */
int max_propagation_steps;
/* Indexed by vertex index, contains the topology information needed for boundary deformations.
*/
struct {
/* Vertex index from where the topology propagation reached this vertex. */
Array<int> original_vertex_i;
/* How many steps were needed to reach this vertex from the boundary. */
Array<int> propagation_steps_num;
/* Strength that is used to deform this vertex. */
Array<float> strength_factor;
} edit_info;
/* Bend Deform type. */
struct {
Array<float3> pivot_rotation_axis;
Array<float3> pivot_positions;
} bend;
/* Slide Deform type. */
struct {
Array<float3> directions;
} slide;
/* Twist Deform type. */
struct {
float3 rotation_axis;
float3 pivot_position;
} twist;
};
/**
* This structure contains all the temporary data
* needed for individual brush strokes.
@@ -510,7 +331,7 @@ struct StrokeCache {
float3 true_initial_normal;
/* Boundary brush */
std::array<std::unique_ptr<SculptBoundary>, PAINT_SYMM_AREAS> boundaries;
std::array<std::unique_ptr<boundary::SculptBoundary>, PAINT_SYMM_AREAS> boundaries;
/* Surface Smooth Brush */
/* Stores the displacement produced by the laplacian step of HC smooth. */
@@ -556,172 +377,8 @@ struct StrokeCache {
~StrokeCache();
};
/* -------------------------------------------------------------------- */
/** \name Sculpt Expand
* \{ */
namespace expand {
enum class FalloffType {
Geodesic,
Topology,
TopologyNormals,
Normals,
Sphere,
BoundaryTopology,
BoundaryFaceSet,
ActiveFaceSet,
};
enum class TargetType {
Mask,
FaceSets,
Colors,
};
enum class RecursionType {
Topology,
Geodesic,
};
#define EXPAND_SYMM_AREAS 8
struct Cache {
/* Target data elements that the expand operation will affect. */
TargetType target;
/* Falloff data. */
FalloffType falloff_type;
/* Indexed by vertex index, precalculated falloff value of that vertex (without any falloff
* editing modification applied). */
Array<float> vert_falloff;
/* Max falloff value in *vert_falloff. */
float max_vert_falloff;
/* Indexed by base mesh face index, precalculated falloff value of that face. These values are
* calculated from the per vertex falloff (*vert_falloff) when needed. */
Array<float> face_falloff;
float max_face_falloff;
/* Falloff value of the active element (vertex or base mesh face) that Expand will expand to. */
float active_falloff;
/* When set to true, expand skips all falloff computations and considers all elements as enabled.
*/
bool all_enabled;
/* Initial mouse and cursor data from where the current falloff started. This data can be changed
* during the execution of Expand by moving the origin. */
float2 initial_mouse_move;
float2 initial_mouse;
PBVHVertRef initial_active_vertex;
int initial_active_vertex_i;
int initial_active_face_set;
/* Maximum number of vertices allowed in the SculptSession for previewing the falloff using
* geodesic distances. */
int max_geodesic_move_preview;
/* Original falloff type before starting the move operation. */
FalloffType move_original_falloff_type;
/* Falloff type using when moving the origin for preview. */
FalloffType move_preview_falloff_type;
/* Face set ID that is going to be used when creating a new Face Set. */
int next_face_set;
/* Face Set ID of the Face set selected for editing. */
int update_face_set;
/* Mouse position since the last time the origin was moved. Used for reference when moving the
* initial position of Expand. */
float2 original_mouse_move;
/* Active island checks. */
/* Indexed by symmetry pass index, contains the connected island ID for that
* symmetry pass. Other connected island IDs not found in this
* array will be ignored by Expand. */
int active_connected_islands[EXPAND_SYMM_AREAS];
/* Snapping. */
/* Set containing all Face Sets IDs that Expand will use to snap the new data. */
std::unique_ptr<Set<int>> snap_enabled_face_sets;
/* Texture distortion data. */
const Brush *brush;
Scene *scene;
// struct MTex *mtex;
/* Controls how much texture distortion will be applied to the current falloff */
float texture_distortion_strength;
/* Cached pbvh::Tree nodes. This allows to skip gathering all nodes from the pbvh::Tree each time
* expand needs to update the state of the elements. */
Vector<bke::pbvh::Node *> nodes;
/* Expand state options. */
/* Number of loops (times that the falloff is going to be repeated). */
int loop_count;
/* Invert the falloff result. */
bool invert;
/* When set to true, preserves the previous state of the data and adds the new one on top. */
bool preserve;
/* When set to true, the mask or colors will be applied as a gradient. */
bool falloff_gradient;
/* When set to true, Expand will use the Brush falloff curve data to shape the gradient. */
bool brush_gradient;
/* When set to true, Expand will move the origin (initial active vertex and cursor position)
* instead of updating the active vertex and active falloff. */
bool move;
/* When set to true, Expand will snap the new data to the Face Sets IDs found in
* *original_face_sets. */
bool snap;
/* When set to true, Expand will use the current Face Set ID to modify an existing Face Set
* instead of creating a new one. */
bool modify_active_face_set;
/* When set to true, Expand will reposition the sculpt pivot to the boundary of the expand result
* after finishing the operation. */
bool reposition_pivot;
/* If nothing is masked set mask of every vertex to 0. */
bool auto_mask;
/* Color target data type related data. */
float fill_color[4];
short blend_mode;
/* Face Sets at the first step of the expand operation, before starting modifying the active
* vertex and active falloff. These are not the original Face Sets of the sculpt before starting
* the operator as they could have been modified by Expand when initializing the operator and
* before starting changing the active vertex. These Face Sets are used for restoring and
* checking the Face Sets state while the Expand operation modal runs. */
Array<int> initial_face_sets;
/* Original data of the sculpt as it was before running the Expand operator. */
Array<float> original_mask;
Array<int> original_face_sets;
Array<float4> original_colors;
bool check_islands;
int normal_falloff_blur_steps;
};
}
}
/** \} */
/** \} */
/* -------------------------------------------------------------------- */
@@ -944,126 +601,6 @@ void SCULPT_fake_neighbors_enable(Object &ob);
void SCULPT_fake_neighbors_disable(Object &ob);
void SCULPT_fake_neighbors_free(Object &ob);
namespace blender::ed::sculpt_paint {
namespace boundary {
/**
* Populates boundary information for a mesh.
*
* \see SculptVertexInfo
*/
void ensure_boundary_info(Object &object);
/**
* Determine if a vertex is a boundary vertex.
*
* Requires #ensure_boundary_info to have been called.
*/
bool vert_is_boundary(const SculptSession &ss, PBVHVertRef vertex);
bool vert_is_boundary(Span<bool> hide_poly,
GroupedSpan<int> vert_to_face_map,
BitSpan boundary,
int vert);
bool vert_is_boundary(const SubdivCCG &subdiv_ccg,
Span<int> corner_verts,
OffsetIndices<int> faces,
BitSpan boundary,
SubdivCCGCoord vert);
bool vert_is_boundary(BMVert *vert);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Sculpt Visibility API
* \{ */
namespace hide {
Span<int> node_visible_verts(const bke::pbvh::Node &node,
Span<bool> hide_vert,
Vector<int> &indices);
bool vert_visible_get(const Object &object, PBVHVertRef vertex);
/* Determines if all faces attached to a given vertex are visible. */
bool vert_all_faces_visible_get(Span<bool> hide_poly, GroupedSpan<int> vert_to_face_map, int vert);
bool vert_all_faces_visible_get(Span<bool> hide_poly,
const SubdivCCG &subdiv_ccg,
SubdivCCGCoord vert);
bool vert_all_faces_visible_get(BMVert *vert);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Face Sets API
* \{ */
namespace face_set {
int active_face_set_get(const SculptSession &ss);
int vert_face_set_get(const SculptSession &ss, PBVHVertRef vertex);
int vert_face_set_get(GroupedSpan<int> vert_to_face_map, Span<int> face_sets, int vert);
bool vert_has_face_set(const SculptSession &ss, PBVHVertRef vertex, int face_set);
bool vert_has_face_set(GroupedSpan<int> vert_to_face_map,
const int *face_sets,
int vert,
int face_set);
bool vert_has_face_set(const SubdivCCG &subdiv_ccg, const int *face_sets, int grid, int face_set);
bool vert_has_face_set(int face_set_offset, const BMVert &vert, int face_set);
bool vert_has_unique_face_set(const SculptSession &ss, PBVHVertRef vertex);
bool vert_has_unique_face_set(GroupedSpan<int> vert_to_face_map, const int *face_sets, int vert);
bool vert_has_unique_face_set(GroupedSpan<int> vert_to_face_map,
Span<int> corner_verts,
OffsetIndices<int> faces,
const int *face_sets,
const SubdivCCG &subdiv_ccg,
SubdivCCGCoord coord);
bool vert_has_unique_face_set(const BMVert *vert);
/**
* Creates the sculpt face set attribute on the mesh if it doesn't exist.
*
* \see face_set::ensure_face_sets_mesh if further writing to the attribute is desired.
*/
bool create_face_sets_mesh(Object &object);
/**
* Ensures that the sculpt face set attribute exists on the mesh.
*
* \see face_set::create_face_sets_mesh to avoid having to remember to call .finish()
*/
bke::SpanAttributeWriter<int> ensure_face_sets_mesh(Object &object);
int ensure_face_sets_bmesh(Object &object);
Array<int> duplicate_face_sets(const Mesh &mesh);
Set<int> gather_hidden_face_sets(Span<bool> hide_poly, Span<int> face_sets);
void filter_verts_with_unique_face_sets_mesh(GroupedSpan<int> vert_to_face_map,
const int *face_sets,
bool unique,
Span<int> verts,
MutableSpan<float> factors);
void filter_verts_with_unique_face_sets_grids(GroupedSpan<int> vert_to_face_map,
Span<int> corner_verts,
OffsetIndices<int> faces,
const SubdivCCG &subdiv_ccg,
const int *face_sets,
bool unique,
Span<int> grids,
MutableSpan<float> factors);
void filter_verts_with_unique_face_sets_bmesh(bool unique,
const Set<BMVert *, 0> verts,
MutableSpan<float> factors);
}
}
/** \} */
/* -------------------------------------------------------------------- */
@@ -1194,425 +731,6 @@ void SCULPT_tilt_effective_normal_get(const SculptSession &ss, const Brush &brus
/** \} */
/* -------------------------------------------------------------------- */
/** \name Flood Fill
* \{ */
namespace blender::ed::sculpt_paint::flood_fill {
struct FillData {
std::queue<PBVHVertRef> queue;
BitVector<> visited_verts;
};
struct FillDataMesh {
FillDataMesh(int size) : visited_verts(size) {}
std::queue<int> queue;
BitVector<> visited_verts;
void add_initial(int vertex);
void add_and_skip_initial(int vertex, int index);
void add_initial_with_symmetry(const Depsgraph &depsgraph,
const Object &object,
const bke::pbvh::Tree &pbvh,
int vertex,
float radius);
void execute(Object &object,
GroupedSpan<int> vert_to_face_map,
FunctionRef<bool(int from_v, int to_v)> func);
};
struct FillDataGrids {
FillDataGrids(int size) : visited_verts(size) {}
std::queue<SubdivCCGCoord> queue;
BitVector<> visited_verts;
void add_initial(SubdivCCGCoord vertex);
void add_and_skip_initial(SubdivCCGCoord vertex, int index);
void add_initial_with_symmetry(const Object &object,
const bke::pbvh::Tree &pbvh,
const SubdivCCG &subdiv_ccg,
SubdivCCGCoord vertex,
float radius);
void execute(
Object &object,
const SubdivCCG &subdiv_ccg,
FunctionRef<bool(SubdivCCGCoord from_v, SubdivCCGCoord to_v, bool is_duplicate)> func);
};
struct FillDataBMesh {
FillDataBMesh(int size) : visited_verts(size) {}
std::queue<BMVert *> queue;
BitVector<> visited_verts;
void add_initial(BMVert *vertex);
void add_and_skip_initial(BMVert *vertex, int index);
void add_initial_with_symmetry(const Object &object,
const bke::pbvh::Tree &pbvh,
BMVert *vertex,
float radius);
void execute(Object &object, FunctionRef<bool(BMVert *from_v, BMVert *to_v)> func);
};
/**
* \deprecated See the individual FillData constructors instead of this method.
*/
FillData init_fill(SculptSession &ss);
void add_initial(FillData &flood, PBVHVertRef vertex);
void add_and_skip_initial(FillData &flood, PBVHVertRef vertex);
void add_initial_with_symmetry(const Depsgraph &depsgraph,
const Object &ob,
FillData &flood,
PBVHVertRef vertex,
float radius);
void execute(Object &object,
FillData &flood,
FunctionRef<bool(PBVHVertRef from_v, PBVHVertRef to_v, bool is_duplicate)> func);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Dynamic topology
* \{ */
namespace blender::ed::sculpt_paint::dyntopo {
enum WarnFlag {
VDATA = (1 << 0),
EDATA = (1 << 1),
LDATA = (1 << 2),
MODIFIER = (1 << 3),
};
ENUM_OPERATORS(WarnFlag, MODIFIER);
/** Enable dynamic topology; mesh will be triangulated */
void enable_ex(Main &bmain, Depsgraph &depsgraph, Object &ob);
void disable(bContext *C, undo::StepData *undo_step);
void disable_with_undo(Main &bmain, Depsgraph &depsgraph, Scene &scene, Object &ob);
/**
* Returns true if the stroke will use dynamic topology, false
* otherwise.
*
* Factors: some brushes like grab cannot do dynamic topology.
* Others, like smooth, are better without.
* Same goes for alt-key smoothing.
*/
bool stroke_is_dyntopo(const SculptSession &ss, const Brush &brush);
void triangulate(BMesh *bm);
WarnFlag check_attribute_warning(Scene &scene, Object &ob);
namespace detail_size {
/**
* Scaling factor to match the displayed size to the actual sculpted size
*/
constexpr float RELATIVE_SCALE_FACTOR = 0.4f;
/**
* Converts from Sculpt#constant_detail to the pbvh::Tree max edge length.
*/
float constant_to_detail_size(float constant_detail, const Object &ob);
/**
* Converts from Sculpt#detail_percent to the pbvh::Tree max edge length.
*/
float brush_to_detail_size(float brush_percent, float brush_radius);
/**
* Converts from Sculpt#detail_size to the pbvh::Tree max edge length.
*/
float relative_to_detail_size(float relative_detail,
float brush_radius,
float pixel_radius,
float pixel_size);
/**
* Converts from Sculpt#constant_detail to equivalent Sculpt#detail_percent value.
*
* Corresponds to a change from Constant & Manual Detailing to Brush Detailing.
*/
float constant_to_brush_detail(float constant_detail, float brush_radius, const Object &ob);
/**
* Converts from Sculpt#constant_detail to equivalent Sculpt#detail_size value.
*
* Corresponds to a change from Constant & Manual Detailing to Relative Detailing.
*/
float constant_to_relative_detail(float constant_detail,
float brush_radius,
float pixel_radius,
float pixel_size,
const Object &ob);
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Auto-masking.
* \{ */
namespace blender::ed::sculpt_paint::auto_mask {
struct Settings {
/* eAutomasking_flag. */
int flags;
int initial_face_set;
int initial_island_nr;
float cavity_factor;
int cavity_blur_steps;
CurveMapping *cavity_curve;
float start_normal_limit, start_normal_falloff;
float view_normal_limit, view_normal_falloff;
bool topology_use_brush_limit;
};
struct Cache {
Settings settings;
bool can_reuse_mask;
uchar current_stroke_id;
};
/* Returns the automasking cache depending on the active tool. Used for code that can run both for
* brushes and filter. */
const Cache *active_cache_get(const SculptSession &ss);
/**
* Creates and initializes an automasking cache.
*
* For automasking modes that cannot be calculated in real time,
* data is also stored at the vertex level prior to the stroke starting.
*/
std::unique_ptr<Cache> cache_init(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob);
std::unique_ptr<Cache> cache_init(const Depsgraph &depsgraph,
const Sculpt &sd,
const Brush *brush,
Object &ob);
bool mode_enabled(const Sculpt &sd, const Brush *br, eAutomasking_flag mode);
bool is_enabled(const Sculpt &sd, const SculptSession *ss, const Brush *br);
bool needs_normal(const SculptSession &ss, const Sculpt &sd, const Brush *brush);
int settings_hash(const Object &ob, const Cache &automasking);
bool tool_can_reuse_automask(int sculpt_tool);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Geodesic distances.
* \{ */
namespace blender::ed::sculpt_paint::geodesic {
/**
* Returns an array indexed by vertex index containing the geodesic distance to the closest vertex
* in the initial vertex set. The caller is responsible for freeing the array.
* Geodesic distances will only work when used with blender::bke::pbvh::Type::Mesh, for other
* types of blender::bke::pbvh::Tree it will fallback to euclidean distances to one of the initial
* vertices in the set.
*/
Array<float> distances_create(const Depsgraph &depsgraph,
Object &ob,
const Set<int> &initial_verts,
float limit_radius);
Array<float> distances_create_from_vert_and_symm(const Depsgraph &depsgraph,
Object &ob,
PBVHVertRef vertex,
float limit_radius);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Filter API
* \{ */
namespace blender::ed::sculpt_paint::filter {
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 register_operator_props(wmOperatorType *ot);
/* Filter orientation utils. */
float3x3 to_orientation_space(const filter::Cache &filter_cache);
float3x3 to_object_space(const filter::Cache &filter_cache);
void zero_disabled_axis_components(const filter::Cache &filter_cache, MutableSpan<float3> vectors);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Cloth Simulation.
* \{ */
namespace blender::ed::sculpt_paint::cloth {
/* Cloth Simulation. */
enum NodeSimState {
/* Constraints were not built for this node, so it can't be simulated. */
SCULPT_CLOTH_NODE_UNINITIALIZED,
/* There are constraints for the geometry in this node, but it should not be simulated. */
SCULPT_CLOTH_NODE_INACTIVE,
/* There are constraints for this node and they should be used by the solver. */
SCULPT_CLOTH_NODE_ACTIVE,
};
enum ConstraintType {
/* Constraint that creates the structure of the cloth. */
SCULPT_CLOTH_CONSTRAINT_STRUCTURAL = 0,
/* Constraint that references the position of a vertex and a position in deformation_pos which
* can be deformed by the tools. */
SCULPT_CLOTH_CONSTRAINT_DEFORMATION = 1,
/* Constraint that references the vertex position and a editable soft-body position for
* plasticity. */
SCULPT_CLOTH_CONSTRAINT_SOFTBODY = 2,
/* Constraint that references the vertex position and its initial position. */
SCULPT_CLOTH_CONSTRAINT_PIN = 3,
};
struct LengthConstraint {
/* Elements that are affected by the constraint. */
/* Element a should always be a mesh vertex with the index stored in elem_index_a as it is always
* deformed. Element b could be another vertex of the same mesh or any other position (arbitrary
* point, position for a previous state). In that case, elem_index_a and elem_index_b should be
* the same to avoid affecting two different vertices when solving the constraints.
* *elem_position points to the position which is owned by the element. */
int elem_index_a;
float *elem_position_a;
int elem_index_b;
float *elem_position_b;
float length;
float strength;
/* Index in #SimulationData.node_state of the node from where this constraint was created.
* This constraints will only be used by the solver if the state is active. */
int node;
ConstraintType type;
};
struct SimulationData {
Vector<LengthConstraint> length_constraints;
Array<float> length_constraint_tweak;
/* Position anchors for deformation brushes. These positions are modified by the brush and the
* final positions of the simulated vertices are updated with constraints that use these points
* as targets. */
Array<float3> deformation_pos;
Array<float> deformation_strength;
float mass;
float damping;
float softbody_strength;
Array<float3> acceleration;
Array<float3> pos;
Array<float3> init_pos;
Array<float3> init_no;
Array<float3> softbody_pos;
Array<float3> prev_pos;
Array<float3> last_iteration_pos;
Vector<ColliderCache> collider_list;
int totnode;
Map<const bke::pbvh::Node *, int> node_state_index;
Array<NodeSimState> node_state;
~SimulationData();
};
/* Main cloth brush function */
void do_cloth_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<blender::bke::pbvh::Node *> nodes);
/* Public functions. */
std::unique_ptr<SimulationData> brush_simulation_create(const Depsgraph &depsgraph,
Object &ob,
float cloth_mass,
float cloth_damping,
float cloth_softbody_strength,
bool use_collisions,
bool needs_deform_coords);
void sim_activate_nodes(SimulationData &cloth_sim, Span<blender::bke::pbvh::Node *> nodes);
void brush_store_simulation_state(const Depsgraph &depsgraph,
const Object &object,
SimulationData &cloth_sim);
void do_simulation_step(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
SimulationData &cloth_sim,
Span<blender::bke::pbvh::Node *> nodes);
void ensure_nodes_constraints(const Sculpt &sd,
const Object &ob,
Span<bke::pbvh::Node *> nodes,
SimulationData &cloth_sim,
const float3 &initial_location,
float radius);
/**
* Cursor drawing function.
*/
void simulation_limits_draw(uint gpuattr,
const Brush &brush,
const float location[3],
const float normal[3],
float rds,
float line_width,
const float outline_col[3],
float alpha);
void plane_falloff_preview_draw(uint gpuattr,
SculptSession &ss,
const float outline_col[3],
float outline_alpha);
Vector<blender::bke::pbvh::Node *> brush_affected_nodes_gather(SculptSession &ss,
const Brush &brush);
bool is_cloth_deform_brush(const Brush &brush);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Smoothing API
* \{ */
namespace blender::ed::sculpt_paint {
void calc_smooth_translations(const Depsgraph &depsgraph,
@@ -1622,106 +740,6 @@ void calc_smooth_translations(const Depsgraph &depsgraph,
}
namespace blender::ed::sculpt_paint::smooth {
/**
* For bmesh: Average surrounding verts based on an orthogonality measure.
* Naturally converges to a quad-like structure.
*/
void bmesh_four_neighbor_average(float avg[3], const float3 &direction, const BMVert *v);
void neighbor_color_average(OffsetIndices<int> faces,
Span<int> corner_verts,
GroupedSpan<int> vert_to_face_map,
GSpan color_attribute,
bke::AttrDomain color_domain,
Span<Vector<int>> vert_neighbors,
MutableSpan<float4> smooth_colors);
void neighbor_position_average_grids(const SubdivCCG &subdiv_ccg,
Span<int> grids,
MutableSpan<float3> new_positions);
void neighbor_position_average_interior_grids(OffsetIndices<int> faces,
Span<int> corner_verts,
BitSpan boundary_verts,
const SubdivCCG &subdiv_ccg,
Span<int> grids,
MutableSpan<float3> new_positions);
void neighbor_position_average_bmesh(const Set<BMVert *, 0> &verts,
MutableSpan<float3> new_positions);
void neighbor_position_average_interior_bmesh(const Set<BMVert *, 0> &verts,
MutableSpan<float3> new_positions);
template<typename T>
void neighbor_data_average_mesh(Span<T> src, Span<Vector<int>> vert_neighbors, MutableSpan<T> dst);
template<typename T>
void neighbor_data_average_mesh_check_loose(Span<T> src,
Span<int> verts,
Span<Vector<int>> vert_neighbors,
MutableSpan<T> dst);
template<typename T>
void average_data_grids(const SubdivCCG &subdiv_ccg,
Span<T> src,
Span<int> grids,
MutableSpan<T> dst);
template<typename T>
void average_data_bmesh(Span<T> src, const Set<BMVert *, 0> &verts, MutableSpan<T> dst);
/* Average the data in the argument span across vertex neighbors. */
void blur_geometry_data_array(const Object &object, int iterations, MutableSpan<float> data);
/* Surface Smooth Brush. */
void surface_smooth_laplacian_step(Span<float3> positions,
Span<float3> orig_positions,
Span<float3> average_positions,
float alpha,
MutableSpan<float3> laplacian_disp,
MutableSpan<float3> translations);
void surface_smooth_displace_step(Span<float3> laplacian_disp,
Span<float3> average_laplacian_disp,
float beta,
MutableSpan<float3> translations);
void calc_relaxed_translations_faces(Span<float3> vert_positions,
Span<float3> vert_normals,
OffsetIndices<int> faces,
Span<int> corner_verts,
GroupedSpan<int> vert_to_face_map,
BitSpan boundary_verts,
const int *face_sets,
Span<bool> hide_poly,
bool filter_boundary_face_sets,
Span<int> verts,
Span<float> factors,
Vector<Vector<int>> &neighbors,
MutableSpan<float3> translations);
void calc_relaxed_translations_grids(const SubdivCCG &subdiv_ccg,
OffsetIndices<int> faces,
Span<int> corner_verts,
const int *face_sets,
GroupedSpan<int> vert_to_face_map,
BitSpan boundary_verts,
Span<int> grids,
bool filter_boundary_face_sets,
Span<float> factors,
Span<float3> positions,
Vector<Vector<SubdivCCGCoord>> &neighbors,
MutableSpan<float3> translations);
void calc_relaxed_translations_bmesh(const Set<BMVert *, 0> &verts,
Span<float3> positions,
bool filter_boundary_face_sets,
Span<float> factors,
Vector<Vector<BMVert *>> &neighbors,
MutableSpan<float3> translations);
}
/** \} */
/**
* Flip all the edit-data across the axis/axes specified by \a symm.
* Used to calculate multiple modifications to the mesh when symmetry is enabled.
@@ -1731,57 +749,6 @@ void SCULPT_cache_calc_brushdata_symm(blender::ed::sculpt_paint::StrokeCache &ca
char axis,
float angle);
/* -------------------------------------------------------------------- */
/** \name Sculpt Undo
* \{ */
namespace blender::ed::sculpt_paint::undo {
/**
* Store undo data of the given type for a pbvh::Tree node. This function can be called by multiple
* threads concurrently, as long as they don't pass the same pbvh::Tree node.
*
* This is only possible when building an undo step, in between #push_begin and #push_end.
*/
void push_node(const Depsgraph &depsgraph,
const Object &object,
const bke::pbvh::Node *node,
undo::Type type);
void push_nodes(const Depsgraph &depsgraph,
Object &object,
Span<const bke::pbvh::Node *> nodes,
undo::Type type);
/**
* Retrieve the undo data of a given type for the active undo step. For example, this is used to
* access "original" data from before the current stroke.
*
* This is only possible when building an undo step, in between #push_begin and #push_end.
*/
const undo::Node *get_node(const bke::pbvh::Node *node, undo::Type type);
/**
* Pushes an undo step using the operator name. This is necessary for
* redo panels to work; operators that do not support that may use
* #push_begin_ex instead if so desired.
*/
void push_begin(Object &ob, const wmOperator *op);
/**
* NOTE: #push_begin is preferred since `name`
* must match operator name for redo panels to work.
*/
void push_begin_ex(Object &ob, const char *name);
void push_end(Object &ob);
void push_end_ex(Object &ob, bool use_nested_undo);
void restore_from_bmesh_enter_geometry(const StepData &step_data, Mesh &mesh);
BMLogEntry *get_bmesh_log_entry();
void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object);
}
namespace blender::ed::sculpt_paint {
struct OrigPositionData {
@@ -1830,136 +797,6 @@ void modal_keymap(wmKeyConfig *keyconf);
/** \} */
/* -------------------------------------------------------------------- */
/** \name Gesture Operators
* \{ */
namespace blender::ed::sculpt_paint::gesture {
enum ShapeType {
Box = 0,
/* In the context of a sculpt gesture, both lasso and polyline modal
* operators are handled as the same general shape. */
Lasso = 1,
Line = 2,
};
enum class SelectionType {
Inside = 0,
Outside = 1,
};
/* Common data structure for both lasso and polyline. */
struct LassoData {
float4x4 projviewobjmat;
rcti boundbox;
int width;
/* 2D bitmap to test if a vertex is affected by the surrounding shape. */
blender::BitVector<> mask_px;
};
struct LineData {
/* Plane aligned to the gesture line. */
float true_plane[4];
float plane[4];
/* Planes to limit the action to the length of the gesture segment at both sides of the affected
* area. */
float side_plane[2][4];
float true_side_plane[2][4];
bool use_side_planes;
bool flip;
};
struct Operation;
/* Common data used for executing a gesture operation. */
struct GestureData {
SculptSession *ss;
ViewContext vc;
/* Enabled and currently active symmetry. */
ePaintSymmetryFlags symm;
ePaintSymmetryFlags symmpass;
/* Operation parameters. */
ShapeType shape_type;
bool front_faces_only;
SelectionType selection_type;
Operation *operation;
/* Gesture data. */
/* Screen space points that represent the gesture shape. */
Array<float2> gesture_points;
/* View parameters. */
float3 true_view_normal;
float3 view_normal;
float3 true_view_origin;
float3 view_origin;
float true_clip_planes[4][4];
float clip_planes[4][4];
/* These store the view origin and normal in world space, which is used in some gestures to
* generate geometry aligned from the view directly in world space. */
/* World space view origin and normal are not affected by object symmetry when doing symmetry
* passes, so there is no separate variables with the `true_` prefix to store their original
* values without symmetry modifications. */
float3 world_space_view_origin;
float3 world_space_view_normal;
/* Lasso & Polyline Gesture. */
LassoData lasso;
/* Line Gesture. */
LineData line;
/* Task Callback Data. */
Vector<bke::pbvh::Node *> nodes;
~GestureData();
};
/* Common abstraction structure for gesture operations. */
struct Operation {
/* Initial setup (data updates, special undo push...). */
void (*begin)(bContext &, wmOperator &, GestureData &);
/* Apply the gesture action for each symmetry pass. */
void (*apply_for_symmetry_pass)(bContext &, GestureData &);
/* Remaining actions after finishing the symmetry passes iterations
* (updating data-layers, tagging bke::pbvh::Tree updates...). */
void (*end)(bContext &, GestureData &);
};
/* Determines whether or not a gesture action should be applied. */
bool is_affected(const GestureData &gesture_data, const float3 &position, const float3 &normal);
void filter_factors(const GestureData &gesture_data,
Span<float3> positions,
Span<float3> normals,
MutableSpan<float> factors);
/* Initialization functions. */
std::unique_ptr<GestureData> init_from_box(bContext *C, wmOperator *op);
std::unique_ptr<GestureData> init_from_lasso(bContext *C, wmOperator *op);
std::unique_ptr<GestureData> init_from_polyline(bContext *C, wmOperator *op);
std::unique_ptr<GestureData> init_from_line(bContext *C, wmOperator *op);
/* Common gesture operator properties. */
void operator_properties(wmOperatorType *ot, ShapeType shapeType);
/* Apply the gesture action to the selected nodes. */
void apply(bContext &C, GestureData &gesture_data, wmOperator &op);
}
namespace blender::ed::sculpt_paint::project {
void SCULPT_OT_project_line_gesture(wmOperatorType *ot);
}
@@ -2063,86 +900,6 @@ void SCULPT_OT_dynamic_topology_toggle(wmOperatorType *ot);
/** \name Brushes
* \{ */
namespace blender::ed::sculpt_paint::pose {
/**
* Main Brush Function.
*/
void do_pose_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
/**
* Calculate the pose origin and (Optionally the pose factor)
* that is used when using the pose brush.
*
* \param r_pose_origin: Must be a valid pointer.
* \param r_pose_factor: Optional, when set to NULL it won't be calculated.
*/
void calc_pose_data(const Depsgraph &depsgraph,
Object &ob,
SculptSession &ss,
const float3 &initial_location,
float radius,
float pose_offset,
float3 &r_pose_origin,
MutableSpan<float> r_pose_factor);
void pose_brush_init(const Depsgraph &depsgraph,
Object &ob,
SculptSession &ss,
const Brush &brush);
std::unique_ptr<SculptPoseIKChainPreview> preview_ik_chain_init(const Depsgraph &depsgraph,
Object &ob,
SculptSession &ss,
const Brush &brush,
const float3 &initial_location,
float radius);
}
namespace blender::ed::sculpt_paint::boundary {
/**
* Main function to get #SculptBoundary data both for brush deformation and viewport preview.
* Can return NULL if there is no boundary from the given vertex using the given radius.
*/
std::unique_ptr<SculptBoundary> data_init(const Depsgraph &depsgraph,
Object &object,
const Brush *brush,
PBVHVertRef initial_vert,
float radius);
std::unique_ptr<SculptBoundary> data_init_mesh(const Depsgraph &depsgraph,
Object &object,
const Brush *brush,
int initial_vert,
float radius);
std::unique_ptr<SculptBoundary> data_init_grids(Object &object,
const Brush *brush,
SubdivCCGCoord initial_vert,
float radius);
std::unique_ptr<SculptBoundary> data_init_bmesh(Object &object,
const Brush *brush,
BMVert *initial_vert,
float radius);
std::unique_ptr<SculptBoundaryPreview> preview_data_init(const Depsgraph &depsgraph,
Object &object,
const Brush *brush,
float radius);
/* Main Brush Function. */
void do_boundary_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
void edges_preview_draw(uint gpuattr,
SculptSession &ss,
const float outline_col[3],
float outline_alpha);
void pivot_line_preview_draw(uint gpuattr, SculptSession &ss);
}
namespace blender::ed::sculpt_paint {
void multiplane_scrape_preview_draw(uint gpuattr,
@@ -2151,54 +908,6 @@ void multiplane_scrape_preview_draw(uint gpuattr,
const float outline_col[3],
float outline_alpha);
namespace color {
/* Swaps colors at each element in indices with values in colors. */
void swap_gathered_colors(Span<int> indices,
GMutableSpan color_attribute,
MutableSpan<float4> r_colors);
/* Stores colors from the elements in indices into colors. */
void gather_colors(GSpan color_attribute, Span<int> indices, MutableSpan<float4> r_colors);
/* Like gather_colors but handles loop->vert conversion */
void gather_colors_vert(OffsetIndices<int> faces,
Span<int> corner_verts,
GroupedSpan<int> vert_to_face_map,
GSpan color_attribute,
bke::AttrDomain color_domain,
Span<int> verts,
MutableSpan<float4> r_colors);
void color_vert_set(OffsetIndices<int> faces,
Span<int> corner_verts,
GroupedSpan<int> vert_to_face_map,
bke::AttrDomain color_domain,
int vert,
const float4 &color,
GMutableSpan color_attribute);
float4 color_vert_get(OffsetIndices<int> faces,
Span<int> corner_verts,
GroupedSpan<int> vert_to_face_map,
GSpan color_attribute,
bke::AttrDomain color_domain,
int vert);
bke::GAttributeReader active_color_attribute(const Mesh &mesh);
bke::GSpanAttributeWriter active_color_attribute_for_write(Mesh &mesh);
void do_paint_brush(const Depsgraph &depsgraph,
PaintModeSettings &paint_mode_settings,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes,
Span<bke::pbvh::Node *> texnodes);
void do_smear_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
}
}
/**
* \brief Get the image canvas for painting on the given object.
@@ -2249,28 +958,6 @@ namespace blender::ed::sculpt_paint {
void ensure_valid_pivot(const Object &ob, Scene &scene);
}
/* -------------------------------------------------------------------- */
/** \name Topology island API
* \{
* Each mesh island shell gets its own integer
* key; these are temporary and internally limited to 8 bits.
*/
namespace blender::ed::sculpt_paint::islands {
/* Ensure vertex island keys exist and are valid. */
void ensure_cache(Object &object);
/** Mark vertex island keys as invalid. Call when adding or hiding geometry. */
void invalidate(SculptSession &ss);
/** Get vertex island key. */
int vert_id_get(const SculptSession &ss, int vert);
}
/** \} */
namespace blender::ed::sculpt_paint {
float sculpt_calc_radius(const ViewContext &vc,
const Brush &brush,

View File

@@ -0,0 +1,25 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
struct Object;
struct SculptSession;
namespace blender::ed::sculpt_paint::islands {
/* Ensure vertex island keys exist and are valid. */
void ensure_cache(Object &object);
/** Mark vertex island keys as invalid. Call when adding or hiding geometry. */
void invalidate(SculptSession &ss);
/** Get vertex island key. */
int vert_id_get(const SculptSession &ss, int vert);
} // namespace blender::ed::sculpt_paint::islands

View File

@@ -31,13 +31,13 @@
#include "RNA_define.hh"
#include "paint_intern.hh"
#include "sculpt_face_set.hh"
#include "sculpt_hide.hh"
#include "sculpt_intern.hh"
#include "sculpt_islands.hh"
#include "bmesh.hh"
#include <cmath>
#include <cstdlib>
namespace blender::ed::sculpt_paint::mask {
enum class InitMode {

View File

@@ -20,7 +20,6 @@
#include "BLT_translation.hh"
#include "DNA_brush_types.h"
#include "DNA_customdata_types.h"
#include "DNA_listBase.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
@@ -58,7 +57,14 @@
#include "mesh_brush_common.hh"
#include "paint_intern.hh"
#include "sculpt_automask.hh"
#include "sculpt_color.hh"
#include "sculpt_dyntopo.hh"
#include "sculpt_face_set.hh"
#include "sculpt_flood_fill.hh"
#include "sculpt_intern.hh"
#include "sculpt_islands.hh"
#include "sculpt_undo.hh"
#include "RNA_access.hh"
#include "RNA_define.hh"

View File

@@ -31,6 +31,7 @@
#include "mesh_brush_common.hh"
#include "sculpt_intern.hh"
#include "sculpt_smooth.hh"
#include "IMB_imbuf.hh"

View File

@@ -28,7 +28,12 @@
#include "mesh_brush_common.hh"
#include "paint_intern.hh"
#include "sculpt_cloth.hh"
#include "sculpt_face_set.hh"
#include "sculpt_flood_fill.hh"
#include "sculpt_hide.hh"
#include "sculpt_intern.hh"
#include "sculpt_smooth.hh"
#include "bmesh.hh"

View File

@@ -0,0 +1,59 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include "BLI_math_vector.hh"
#include "BLI_span.hh"
struct Brush;
struct Depsgraph;
struct Object;
struct Sculpt;
struct SculptPoseIKChainPreview;
struct SculptSession;
namespace blender::bke::pbvh {
class Node;
}
namespace blender::ed::sculpt_paint::pose {
/**
* Main Brush Function.
*/
void do_pose_brush(const Depsgraph &depsgraph,
const Sculpt &sd,
Object &ob,
Span<bke::pbvh::Node *> nodes);
/**
* Calculate the pose origin and (Optionally the pose factor)
* that is used when using the pose brush.
*
* \param r_pose_origin: Must be a valid pointer.
* \param r_pose_factor: Optional, when set to NULL it won't be calculated.
*/
void calc_pose_data(const Depsgraph &depsgraph,
Object &ob,
SculptSession &ss,
const float3 &initial_location,
float radius,
float pose_offset,
float3 &r_pose_origin,
MutableSpan<float> r_pose_factor);
void pose_brush_init(const Depsgraph &depsgraph,
Object &ob,
SculptSession &ss,
const Brush &brush);
std::unique_ptr<SculptPoseIKChainPreview> preview_ik_chain_init(const Depsgraph &depsgraph,
Object &ob,
SculptSession &ss,
const Brush &brush,
const float3 &initial_location,
float radius);
} // namespace blender::ed::sculpt_paint::pose

View File

@@ -8,9 +8,6 @@
#include "BLI_array_utils.hh"
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_math_geom.h"
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BKE_context.hh"
#include "BKE_layer.hh"
@@ -21,6 +18,7 @@
#include "WM_types.hh"
#include "mesh_brush_common.hh"
#include "sculpt_gesture.hh"
#include "sculpt_intern.hh"
namespace blender::ed::sculpt_paint::project {

View File

@@ -5,6 +5,7 @@
/** \file
* \ingroup edsculpt
*/
#include "sculpt_smooth.hh"
#include "MEM_guardedalloc.h"
@@ -15,19 +16,19 @@
#include "BLI_math_vector.hh"
#include "BLI_task.h"
#include "DNA_brush_types.h"
#include "BKE_mesh.hh"
#include "BKE_paint.hh"
#include "BKE_pbvh_api.hh"
#include "BKE_subdiv_ccg.hh"
#include "mesh_brush_common.hh"
#include "sculpt_color.hh"
#include "sculpt_face_set.hh"
#include "sculpt_hide.hh"
#include "sculpt_intern.hh"
#include "bmesh.hh"
#include <cmath>
#include <cstdlib>
namespace blender::ed::sculpt_paint::smooth {

View File

@@ -0,0 +1,122 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include "BLI_generic_span.hh"
#include "BLI_math_vector.hh"
#include "BLI_offset_indices.hh"
#include "BLI_set.hh"
#include "BKE_subdiv_ccg.hh"
struct BMVert;
struct Object;
struct SubdivCCG;
struct SubdivCCGCoord;
namespace blender::bke {
enum class AttrDomain : int8_t;
}
namespace blender::ed::sculpt_paint::smooth {
/**
* For bmesh: Average surrounding verts based on an orthogonality measure.
* Naturally converges to a quad-like structure.
*/
void bmesh_four_neighbor_average(float avg[3], const float3 &direction, const BMVert *v);
void neighbor_color_average(OffsetIndices<int> faces,
Span<int> corner_verts,
GroupedSpan<int> vert_to_face_map,
GSpan color_attribute,
bke::AttrDomain color_domain,
Span<Vector<int>> vert_neighbors,
MutableSpan<float4> smooth_colors);
void neighbor_position_average_grids(const SubdivCCG &subdiv_ccg,
Span<int> grids,
MutableSpan<float3> new_positions);
void neighbor_position_average_interior_grids(OffsetIndices<int> faces,
Span<int> corner_verts,
BitSpan boundary_verts,
const SubdivCCG &subdiv_ccg,
Span<int> grids,
MutableSpan<float3> new_positions);
void neighbor_position_average_bmesh(const Set<BMVert *, 0> &verts,
MutableSpan<float3> new_positions);
void neighbor_position_average_interior_bmesh(const Set<BMVert *, 0> &verts,
MutableSpan<float3> new_positions);
template<typename T>
void neighbor_data_average_mesh(Span<T> src, Span<Vector<int>> vert_neighbors, MutableSpan<T> dst);
template<typename T>
void neighbor_data_average_mesh_check_loose(Span<T> src,
Span<int> verts,
Span<Vector<int>> vert_neighbors,
MutableSpan<T> dst);
template<typename T>
void average_data_grids(const SubdivCCG &subdiv_ccg,
Span<T> src,
Span<int> grids,
MutableSpan<T> dst);
template<typename T>
void average_data_bmesh(Span<T> src, const Set<BMVert *, 0> &verts, MutableSpan<T> dst);
/* Average the data in the argument span across vertex neighbors. */
void blur_geometry_data_array(const Object &object, int iterations, MutableSpan<float> data);
/* Surface Smooth Brush. */
void surface_smooth_laplacian_step(Span<float3> positions,
Span<float3> orig_positions,
Span<float3> average_positions,
float alpha,
MutableSpan<float3> laplacian_disp,
MutableSpan<float3> translations);
void surface_smooth_displace_step(Span<float3> laplacian_disp,
Span<float3> average_laplacian_disp,
float beta,
MutableSpan<float3> translations);
void calc_relaxed_translations_faces(Span<float3> vert_positions,
Span<float3> vert_normals,
OffsetIndices<int> faces,
Span<int> corner_verts,
GroupedSpan<int> vert_to_face_map,
BitSpan boundary_verts,
const int *face_sets,
Span<bool> hide_poly,
bool filter_boundary_face_sets,
Span<int> verts,
Span<float> factors,
Vector<Vector<int>> &neighbors,
MutableSpan<float3> translations);
void calc_relaxed_translations_grids(const SubdivCCG &subdiv_ccg,
OffsetIndices<int> faces,
Span<int> corner_verts,
const int *face_sets,
GroupedSpan<int> vert_to_face_map,
BitSpan boundary_verts,
Span<int> grids,
bool filter_boundary_face_sets,
Span<float> factors,
Span<float3> positions,
Vector<Vector<SubdivCCGCoord>> &neighbors,
MutableSpan<float3> translations);
void calc_relaxed_translations_bmesh(const Set<BMVert *, 0> &verts,
Span<float3> positions,
bool filter_boundary_face_sets,
Span<float> factors,
Vector<Vector<BMVert *>> &neighbors,
MutableSpan<float3> translations);
} // namespace blender::ed::sculpt_paint::smooth

View File

@@ -35,6 +35,7 @@
#include "mesh_brush_common.hh"
#include "paint_intern.hh"
#include "sculpt_filter.hh"
#include "sculpt_intern.hh"
#include "RNA_access.hh"
@@ -71,17 +72,16 @@ void init_transform(bContext *C, Object &ob, const float mval_fl[2], const char
filter::cache_init(C, ob, sd, undo::Type::Position, mval_fl, 5.0, 1.0f);
if (sd.transform_mode == SCULPT_TRANSFORM_MODE_RADIUS_ELASTIC) {
ss.filter_cache->transform_displacement_mode = SCULPT_TRANSFORM_DISPLACEMENT_INCREMENTAL;
ss.filter_cache->transform_displacement_mode = TransformDisplacementMode::Incremental;
}
else {
ss.filter_cache->transform_displacement_mode = SCULPT_TRANSFORM_DISPLACEMENT_ORIGINAL;
ss.filter_cache->transform_displacement_mode = TransformDisplacementMode::Original;
}
}
static std::array<float4x4, 8> transform_matrices_init(
const SculptSession &ss,
const ePaintSymmetryFlags symm,
const SculptTransformDisplacementMode t_mode)
static std::array<float4x4, 8> transform_matrices_init(const SculptSession &ss,
const ePaintSymmetryFlags symm,
const TransformDisplacementMode t_mode)
{
std::array<float4x4, 8> mats;
@@ -92,12 +92,12 @@ static std::array<float4x4, 8> transform_matrices_init(
float start_pivot_pos[3], start_pivot_rot[4], start_pivot_scale[3];
switch (t_mode) {
case SCULPT_TRANSFORM_DISPLACEMENT_ORIGINAL:
case TransformDisplacementMode::Original:
copy_v3_v3(start_pivot_pos, ss.init_pivot_pos);
copy_v4_v4(start_pivot_rot, ss.init_pivot_rot);
copy_v3_v3(start_pivot_scale, ss.init_pivot_scale);
break;
case SCULPT_TRANSFORM_DISPLACEMENT_INCREMENTAL:
case TransformDisplacementMode::Incremental:
copy_v3_v3(start_pivot_pos, ss.prev_pivot_pos);
copy_v4_v4(start_pivot_rot, ss.prev_pivot_rot);
copy_v3_v3(start_pivot_scale, ss.prev_pivot_scale);
@@ -452,7 +452,7 @@ static void transform_radius_elastic(const Depsgraph &depsgraph,
{
SculptSession &ss = *ob.sculpt;
BLI_assert(ss.filter_cache->transform_displacement_mode ==
SCULPT_TRANSFORM_DISPLACEMENT_INCREMENTAL);
TransformDisplacementMode::Incremental);
const ePaintSymmetryFlags symm = SCULPT_mesh_symmetry_xyz_get(ob);

View File

@@ -38,7 +38,10 @@
#include "tools/bmesh_intersect.hh"
#include "paint_intern.hh"
#include "sculpt_face_set.hh"
#include "sculpt_gesture.hh"
#include "sculpt_intern.hh"
#include "sculpt_islands.hh"
namespace blender::ed::sculpt_paint::trim {

View File

@@ -29,6 +29,7 @@
* a tentative undo step with is appended later when the operator ends.
* Operators must have the OPTYPE_UNDO flag set for this to work properly.
*/
#include "sculpt_undo.hh"
#include <cstddef>
@@ -76,6 +77,9 @@
#include "bmesh.hh"
#include "paint_intern.hh"
#include "sculpt_color.hh"
#include "sculpt_dyntopo.hh"
#include "sculpt_face_set.hh"
#include "sculpt_intern.hh"
namespace blender::ed::sculpt_paint::undo {

View File

@@ -0,0 +1,117 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup edsculpt
*/
#pragma once
#include "BLI_array.hh"
#include "BLI_bit_group_vector.hh"
#include "BLI_bit_vector.hh"
#include "BLI_math_vector.hh"
#include "BLI_vector.hh"
struct BMLogEntry;
struct Depsgraph;
struct Mesh;
struct Object;
struct StepData;
struct wmOperator;
namespace blender::bke::pbvh {
class Node;
}
namespace blender::ed::sculpt_paint::undo {
enum class Type : int8_t {
None,
Position,
HideVert,
HideFace,
Mask,
DyntopoBegin,
DyntopoEnd,
DyntopoSymmetrize,
Geometry,
FaceSet,
Color,
};
struct Node {
Array<float3> position;
Array<float3> orig_position;
Array<float3> normal;
Array<float4> col;
Array<float> mask;
Array<float4> loop_col;
Array<float4> orig_loop_col;
/* Mesh. */
Array<int> vert_indices;
int unique_verts_num;
Array<int> corner_indices;
BitVector<> vert_hidden;
BitVector<> face_hidden;
/* Multires. */
/** Indices of grids in the pbvh::Tree node. */
Array<int> grids;
BitGroupVector<> grid_hidden;
/* Sculpt Face Sets */
Array<int> face_sets;
Vector<int> face_indices;
};
/**
* Store undo data of the given type for a pbvh::Tree node. This function can be called by multiple
* threads concurrently, as long as they don't pass the same pbvh::Tree node.
*
* This is only possible when building an undo step, in between #push_begin and #push_end.
*/
void push_node(const Depsgraph &depsgraph,
const Object &object,
const bke::pbvh::Node *node,
undo::Type type);
void push_nodes(const Depsgraph &depsgraph,
Object &object,
Span<const bke::pbvh::Node *> nodes,
undo::Type type);
/**
* Retrieve the undo data of a given type for the active undo step. For example, this is used to
* access "original" data from before the current stroke.
*
* This is only possible when building an undo step, in between #push_begin and #push_end.
*/
const undo::Node *get_node(const bke::pbvh::Node *node, undo::Type type);
/**
* Pushes an undo step using the operator name. This is necessary for
* redo panels to work; operators that do not support that may use
* #push_begin_ex instead if so desired.
*/
void push_begin(Object &ob, const wmOperator *op);
/**
* NOTE: #push_begin is preferred since `name`
* must match operator name for redo panels to work.
*/
void push_begin_ex(Object &ob, const char *name);
void push_end(Object &ob);
void push_end_ex(Object &ob, bool use_nested_undo);
void restore_from_bmesh_enter_geometry(const StepData &step_data, Mesh &mesh);
BMLogEntry *get_bmesh_log_entry();
void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object);
} // namespace blender::ed::sculpt_paint::undo