Cleanup: Various non-functional changes for sculpt raycast methods
* Removes `SculptSession` from being passed to the raycast callbacks,
it was only used to determine the existence of the `StrokeCache` and
has been replaced with a boolean.
* Use C++ math library where possible.
* Use const where possible.
* Moves most related `SCULPT_` prefixed methods into the corresponding
namespace.
* Renames `SCULPT_stroke_get_location` to `stroke_get_location_bvh`
to avoid potential collisions in the `sculpt_paint` namespace with
other editors & be more clear about the usage.
Pull Request: https://projects.blender.org/blender/blender/pulls/138796
This commit is contained in:
@@ -1412,14 +1412,14 @@ static void paint_cursor_sculpt_session_update_and_init(PaintCursorContext &pcon
|
||||
Scene &scene = *pcontext.scene;
|
||||
UnifiedPaintSettings &ups = *pcontext.ups;
|
||||
ViewContext &vc = pcontext.vc;
|
||||
SculptCursorGeometryInfo gi;
|
||||
CursorGeometryInfo gi;
|
||||
|
||||
const float2 mval_fl = {
|
||||
float(pcontext.mval.x - pcontext.region->winrct.xmin),
|
||||
float(pcontext.mval.y - pcontext.region->winrct.ymin),
|
||||
};
|
||||
|
||||
/* Ensure that the PBVH is generated before we call #SCULPT_cursor_geometry_info_update because
|
||||
/* Ensure that the PBVH is generated before we call #cursor_geometry_info_update because
|
||||
* the PBVH is needed to do a ray-cast to find the active vertex. */
|
||||
bke::object::pbvh_ensure(*pcontext.depsgraph, *pcontext.vc.obact);
|
||||
|
||||
@@ -1427,7 +1427,7 @@ static void paint_cursor_sculpt_session_update_and_init(PaintCursorContext &pcon
|
||||
* work correctly */
|
||||
pcontext.prev_active_vert_index = ss.active_vert_index();
|
||||
if (!ups.stroke_active) {
|
||||
pcontext.is_cursor_over_mesh = SCULPT_cursor_geometry_info_update(
|
||||
pcontext.is_cursor_over_mesh = cursor_geometry_info_update(
|
||||
C, &gi, mval_fl, (pcontext.brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE));
|
||||
pcontext.location = gi.location;
|
||||
pcontext.normal = gi.normal;
|
||||
|
||||
@@ -592,7 +592,7 @@ static void paint_brush_stroke_add_step(
|
||||
if (paint_stroke_use_scene_spacing(brush, mode)) {
|
||||
float3 world_space_position;
|
||||
|
||||
if (SCULPT_stroke_get_location(
|
||||
if (stroke_get_location_bvh(
|
||||
C, world_space_position, stroke->last_mouse_position, stroke->original))
|
||||
{
|
||||
stroke->last_world_space_position = math::transform_point(
|
||||
@@ -835,7 +835,7 @@ static int paint_space_stroke(bContext *C,
|
||||
const bool use_scene_spacing = paint_stroke_use_scene_spacing(brush, mode);
|
||||
if (use_scene_spacing) {
|
||||
float3 world_space_position;
|
||||
const bool hit = SCULPT_stroke_get_location(
|
||||
const bool hit = stroke_get_location_bvh(
|
||||
C, world_space_position, final_mouse, stroke->original);
|
||||
world_space_position = math::transform_point(stroke->vc.obact->object_to_world(),
|
||||
world_space_position);
|
||||
@@ -1255,11 +1255,11 @@ static void paint_line_strokes_spacing(bContext *C,
|
||||
stroke->last_mouse_position = old_pos;
|
||||
|
||||
if (use_scene_spacing) {
|
||||
const bool hit_old = SCULPT_stroke_get_location(
|
||||
const bool hit_old = stroke_get_location_bvh(
|
||||
C, world_space_position_old, old_pos, stroke->original);
|
||||
|
||||
float3 world_space_position_new;
|
||||
const bool hit_new = SCULPT_stroke_get_location(
|
||||
const bool hit_new = stroke_get_location_bvh(
|
||||
C, world_space_position_new, new_pos, stroke->original);
|
||||
|
||||
world_space_position_old = math::transform_point(stroke->vc.obact->object_to_world(),
|
||||
@@ -1404,7 +1404,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
|
||||
copy_v2_v2(stroke->last_mouse_position, data + 2 * j);
|
||||
|
||||
if (paint_stroke_use_scene_spacing(br, BKE_paintmode_get_active_from_context(C))) {
|
||||
stroke->stroke_over_mesh = SCULPT_stroke_get_location(
|
||||
stroke->stroke_over_mesh = stroke_get_location_bvh(
|
||||
C, stroke->last_world_space_position, data + 2 * j, stroke->original);
|
||||
mul_m4_v3(stroke->vc.obact->object_to_world().ptr(), stroke->last_world_space_position);
|
||||
}
|
||||
@@ -1532,7 +1532,7 @@ wmOperatorStatus paint_stroke_modal(bContext *C,
|
||||
stroke->last_pressure = sample_average.pressure;
|
||||
stroke->last_mouse_position = sample_average.mouse;
|
||||
if (paint_stroke_use_scene_spacing(*br, mode)) {
|
||||
stroke->stroke_over_mesh = SCULPT_stroke_get_location(
|
||||
stroke->stroke_over_mesh = stroke_get_location_bvh(
|
||||
C, stroke->last_world_space_position, sample_average.mouse, stroke->original);
|
||||
stroke->last_world_space_position = math::transform_point(
|
||||
stroke->vc.obact->object_to_world(), stroke->last_world_space_position);
|
||||
|
||||
@@ -2029,7 +2029,7 @@ static wmOperatorStatus vpaint_invoke(bContext *C, wmOperator *op, const wmEvent
|
||||
{
|
||||
op->customdata = paint_stroke_new(C,
|
||||
op,
|
||||
SCULPT_stroke_get_location,
|
||||
stroke_get_location_bvh,
|
||||
vpaint_stroke_test_start,
|
||||
vpaint_stroke_update_step,
|
||||
nullptr,
|
||||
@@ -2055,7 +2055,7 @@ static wmOperatorStatus vpaint_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
op->customdata = paint_stroke_new(C,
|
||||
op,
|
||||
SCULPT_stroke_get_location,
|
||||
stroke_get_location_bvh,
|
||||
vpaint_stroke_test_start,
|
||||
vpaint_stroke_update_step,
|
||||
nullptr,
|
||||
|
||||
@@ -1905,7 +1905,7 @@ static wmOperatorStatus wpaint_invoke(bContext *C, wmOperator *op, const wmEvent
|
||||
{
|
||||
op->customdata = paint_stroke_new(C,
|
||||
op,
|
||||
SCULPT_stroke_get_location,
|
||||
stroke_get_location_bvh,
|
||||
wpaint_stroke_test_start,
|
||||
wpaint_stroke_update_step,
|
||||
nullptr,
|
||||
@@ -1930,7 +1930,7 @@ static wmOperatorStatus wpaint_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
op->customdata = paint_stroke_new(C,
|
||||
op,
|
||||
SCULPT_stroke_get_location,
|
||||
stroke_get_location_bvh,
|
||||
wpaint_stroke_test_start,
|
||||
wpaint_stroke_update_step,
|
||||
nullptr,
|
||||
|
||||
@@ -2764,20 +2764,21 @@ static void sculpt_pbvh_update_pixels(const Depsgraph &depsgraph,
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Generic Brush Plane & Symmetry Utilities
|
||||
* \{ */
|
||||
namespace blender::ed::sculpt_paint {
|
||||
|
||||
struct SculptRaycastData {
|
||||
struct RaycastData {
|
||||
Object *object;
|
||||
SculptSession *ss;
|
||||
const float *ray_start;
|
||||
const float *ray_normal;
|
||||
float3 ray_start;
|
||||
float3 ray_normal;
|
||||
bool hit;
|
||||
float depth;
|
||||
bool original;
|
||||
Span<blender::float3> vert_positions;
|
||||
blender::OffsetIndices<int> faces;
|
||||
bool is_mid_stroke;
|
||||
bool use_original;
|
||||
Span<float3> vert_positions;
|
||||
OffsetIndices<int> faces;
|
||||
Span<int> corner_verts;
|
||||
Span<blender::int3> corner_tris;
|
||||
blender::VArraySpan<bool> hide_poly;
|
||||
Span<int3> corner_tris;
|
||||
VArraySpan<bool> hide_poly;
|
||||
|
||||
const SubdivCCG *subdiv_ccg;
|
||||
|
||||
@@ -2789,22 +2790,24 @@ struct SculptRaycastData {
|
||||
IsectRayPrecalc isect_precalc;
|
||||
};
|
||||
|
||||
struct SculptFindNearestToRayData {
|
||||
struct FindNearestToRayData {
|
||||
Object *object;
|
||||
SculptSession *ss;
|
||||
const float *ray_start, *ray_normal;
|
||||
float3 ray_start;
|
||||
float3 ray_normal;
|
||||
bool hit;
|
||||
float depth;
|
||||
float dist_sq_to_ray;
|
||||
bool original;
|
||||
bool is_mid_stroke;
|
||||
bool use_original;
|
||||
Span<float3> vert_positions;
|
||||
blender::OffsetIndices<int> faces;
|
||||
OffsetIndices<int> faces;
|
||||
Span<int> corner_verts;
|
||||
Span<blender::int3> corner_tris;
|
||||
blender::VArraySpan<bool> hide_poly;
|
||||
Span<int3> corner_tris;
|
||||
VArraySpan<bool> hide_poly;
|
||||
|
||||
const SubdivCCG *subdiv_ccg;
|
||||
};
|
||||
} // namespace blender::ed::sculpt_paint
|
||||
|
||||
ePaintSymmetryAreas SCULPT_get_vertex_symm_area(const float co[3])
|
||||
{
|
||||
@@ -4031,7 +4034,7 @@ static void sculpt_update_cache_invariants(
|
||||
/* Cache projection matrix. */
|
||||
cache->projection_mat = ED_view3d_ob_project_mat_get(cache->vc->rv3d, &ob);
|
||||
|
||||
const float3 z_axis = {0.0f, 0.0f, 1.0f};
|
||||
const float3 z_axis(0.0f, 0.0f, 1.0f);
|
||||
ob.runtime->world_to_object = math::invert(ob.object_to_world());
|
||||
cache->view_normal = math::normalize(math::transform_direction(
|
||||
ob.world_to_object() * float4x4(cache->vc->rv3d->viewinv), z_axis));
|
||||
@@ -4486,23 +4489,22 @@ void SCULPT_stroke_modifiers_check(const bContext *C, Object &ob, const Brush &b
|
||||
}
|
||||
}
|
||||
|
||||
static void sculpt_raycast_cb(blender::bke::pbvh::Node &node, SculptRaycastData &srd, float *tmin)
|
||||
namespace blender::ed::sculpt_paint {
|
||||
static void sculpt_raycast_cb(bke::pbvh::Node &node, RaycastData &rd, float *tmin)
|
||||
{
|
||||
using namespace blender;
|
||||
using namespace blender::ed::sculpt_paint;
|
||||
if (BKE_pbvh_node_get_tmin(&node) >= *tmin) {
|
||||
return;
|
||||
}
|
||||
|
||||
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(*srd.object);
|
||||
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(*rd.object);
|
||||
bool use_origco = false;
|
||||
Span<float3> origco;
|
||||
if (srd.original && srd.ss->cache) {
|
||||
if (rd.use_original && rd.is_mid_stroke) {
|
||||
switch (pbvh.type()) {
|
||||
case bke::pbvh::Type::Mesh:
|
||||
if (const std::optional<OrigPositionData> orig_data =
|
||||
orig_position_data_lookup_mesh_all_verts(
|
||||
*srd.object, static_cast<const bke::pbvh::MeshNode &>(node)))
|
||||
*rd.object, static_cast<const bke::pbvh::MeshNode &>(node)))
|
||||
{
|
||||
use_origco = true;
|
||||
origco = orig_data->positions;
|
||||
@@ -4510,7 +4512,7 @@ static void sculpt_raycast_cb(blender::bke::pbvh::Node &node, SculptRaycastData
|
||||
break;
|
||||
case bke::pbvh::Type::Grids:
|
||||
if (const std::optional<OrigPositionData> orig_data = orig_position_data_lookup_grids(
|
||||
*srd.object, static_cast<const bke::pbvh::GridsNode &>(node)))
|
||||
*rd.object, static_cast<const bke::pbvh::GridsNode &>(node)))
|
||||
{
|
||||
use_origco = true;
|
||||
origco = orig_data->positions;
|
||||
@@ -4532,82 +4534,80 @@ static void sculpt_raycast_cb(blender::bke::pbvh::Node &node, SculptRaycastData
|
||||
int mesh_active_vert;
|
||||
hit = bke::pbvh::node_raycast_mesh(static_cast<bke::pbvh::MeshNode &>(node),
|
||||
origco,
|
||||
srd.vert_positions,
|
||||
srd.faces,
|
||||
srd.corner_verts,
|
||||
srd.corner_tris,
|
||||
srd.hide_poly,
|
||||
srd.ray_start,
|
||||
srd.ray_normal,
|
||||
&srd.isect_precalc,
|
||||
&srd.depth,
|
||||
rd.vert_positions,
|
||||
rd.faces,
|
||||
rd.corner_verts,
|
||||
rd.corner_tris,
|
||||
rd.hide_poly,
|
||||
rd.ray_start,
|
||||
rd.ray_normal,
|
||||
&rd.isect_precalc,
|
||||
&rd.depth,
|
||||
mesh_active_vert,
|
||||
srd.active_face_grid_index,
|
||||
srd.face_normal);
|
||||
rd.active_face_grid_index,
|
||||
rd.face_normal);
|
||||
if (hit) {
|
||||
srd.active_vertex = mesh_active_vert;
|
||||
rd.active_vertex = mesh_active_vert;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case bke::pbvh::Type::Grids: {
|
||||
SubdivCCGCoord grids_active_vert;
|
||||
hit = bke::pbvh::node_raycast_grids(*srd.subdiv_ccg,
|
||||
hit = bke::pbvh::node_raycast_grids(*rd.subdiv_ccg,
|
||||
static_cast<bke::pbvh::GridsNode &>(node),
|
||||
origco,
|
||||
srd.ray_start,
|
||||
srd.ray_normal,
|
||||
&srd.isect_precalc,
|
||||
&srd.depth,
|
||||
rd.ray_start,
|
||||
rd.ray_normal,
|
||||
&rd.isect_precalc,
|
||||
&rd.depth,
|
||||
grids_active_vert,
|
||||
srd.active_face_grid_index,
|
||||
srd.face_normal);
|
||||
rd.active_face_grid_index,
|
||||
rd.face_normal);
|
||||
if (hit) {
|
||||
srd.active_vertex = grids_active_vert.to_index(
|
||||
BKE_subdiv_ccg_key_top_level(*srd.subdiv_ccg));
|
||||
rd.active_vertex = grids_active_vert.to_index(
|
||||
BKE_subdiv_ccg_key_top_level(*rd.subdiv_ccg));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case bke::pbvh::Type::BMesh: {
|
||||
BMVert *bmesh_active_vert;
|
||||
hit = bke::pbvh::node_raycast_bmesh(static_cast<bke::pbvh::BMeshNode &>(node),
|
||||
srd.ray_start,
|
||||
srd.ray_normal,
|
||||
&srd.isect_precalc,
|
||||
&srd.depth,
|
||||
rd.ray_start,
|
||||
rd.ray_normal,
|
||||
&rd.isect_precalc,
|
||||
&rd.depth,
|
||||
use_origco,
|
||||
&bmesh_active_vert,
|
||||
srd.face_normal);
|
||||
rd.face_normal);
|
||||
if (hit) {
|
||||
srd.active_vertex = bmesh_active_vert;
|
||||
rd.active_vertex = bmesh_active_vert;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hit) {
|
||||
srd.hit = true;
|
||||
*tmin = srd.depth;
|
||||
rd.hit = true;
|
||||
*tmin = rd.depth;
|
||||
}
|
||||
}
|
||||
|
||||
static void sculpt_find_nearest_to_ray_cb(blender::bke::pbvh::Node &node,
|
||||
SculptFindNearestToRayData &srd,
|
||||
static void sculpt_find_nearest_to_ray_cb(bke::pbvh::Node &node,
|
||||
FindNearestToRayData &fntrd,
|
||||
float *tmin)
|
||||
{
|
||||
using namespace blender;
|
||||
using namespace blender::ed::sculpt_paint;
|
||||
if (BKE_pbvh_node_get_tmin(&node) >= *tmin) {
|
||||
return;
|
||||
}
|
||||
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(*srd.object);
|
||||
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(*fntrd.object);
|
||||
bool use_origco = false;
|
||||
Span<float3> origco;
|
||||
if (srd.original && srd.ss->cache) {
|
||||
if (fntrd.use_original && fntrd.is_mid_stroke) {
|
||||
switch (pbvh.type()) {
|
||||
case bke::pbvh::Type::Mesh:
|
||||
if (const std::optional<OrigPositionData> orig_data =
|
||||
orig_position_data_lookup_mesh_all_verts(
|
||||
*srd.object, static_cast<const bke::pbvh::MeshNode &>(node)))
|
||||
*fntrd.object, static_cast<const bke::pbvh::MeshNode &>(node)))
|
||||
{
|
||||
use_origco = true;
|
||||
origco = orig_data->positions;
|
||||
@@ -4615,7 +4615,7 @@ static void sculpt_find_nearest_to_ray_cb(blender::bke::pbvh::Node &node,
|
||||
break;
|
||||
case bke::pbvh::Type::Grids:
|
||||
if (const std::optional<OrigPositionData> orig_data = orig_position_data_lookup_grids(
|
||||
*srd.object, static_cast<const bke::pbvh::GridsNode &>(node)))
|
||||
*fntrd.object, static_cast<const bke::pbvh::GridsNode &>(node)))
|
||||
{
|
||||
use_origco = true;
|
||||
origco = orig_data->positions;
|
||||
@@ -4632,78 +4632,71 @@ static void sculpt_find_nearest_to_ray_cb(blender::bke::pbvh::Node &node,
|
||||
node,
|
||||
origco,
|
||||
use_origco,
|
||||
srd.vert_positions,
|
||||
srd.faces,
|
||||
srd.corner_verts,
|
||||
srd.corner_tris,
|
||||
srd.hide_poly,
|
||||
srd.subdiv_ccg,
|
||||
srd.ray_start,
|
||||
srd.ray_normal,
|
||||
&srd.depth,
|
||||
&srd.dist_sq_to_ray))
|
||||
fntrd.vert_positions,
|
||||
fntrd.faces,
|
||||
fntrd.corner_verts,
|
||||
fntrd.corner_tris,
|
||||
fntrd.hide_poly,
|
||||
fntrd.subdiv_ccg,
|
||||
fntrd.ray_start,
|
||||
fntrd.ray_normal,
|
||||
&fntrd.depth,
|
||||
&fntrd.dist_sq_to_ray))
|
||||
{
|
||||
srd.hit = true;
|
||||
*tmin = srd.dist_sq_to_ray;
|
||||
fntrd.hit = true;
|
||||
*tmin = fntrd.dist_sq_to_ray;
|
||||
}
|
||||
}
|
||||
|
||||
float SCULPT_raycast_init(ViewContext *vc,
|
||||
const float mval[2],
|
||||
float ray_start[3],
|
||||
float ray_end[3],
|
||||
float ray_normal[3],
|
||||
bool original)
|
||||
float raycast_init(ViewContext *vc,
|
||||
const float2 &mval,
|
||||
float3 &r_ray_start,
|
||||
float3 &r_ray_end,
|
||||
float3 &r_ray_normal,
|
||||
bool original)
|
||||
{
|
||||
using namespace blender;
|
||||
float obimat[4][4];
|
||||
float dist;
|
||||
Object &ob = *vc->obact;
|
||||
RegionView3D *rv3d = vc->rv3d;
|
||||
View3D *v3d = vc->v3d;
|
||||
|
||||
/* TODO: what if the segment is totally clipped? (return == 0). */
|
||||
ED_view3d_win_to_segment_clipped(
|
||||
vc->depsgraph, vc->region, vc->v3d, mval, ray_start, ray_end, true);
|
||||
vc->depsgraph, vc->region, vc->v3d, mval, r_ray_start, r_ray_end, true);
|
||||
|
||||
invert_m4_m4(obimat, ob.object_to_world().ptr());
|
||||
mul_m4_v3(obimat, ray_start);
|
||||
mul_m4_v3(obimat, ray_end);
|
||||
const float4x4 &world_to_object = ob.world_to_object();
|
||||
r_ray_start = math::transform_point(world_to_object, r_ray_start);
|
||||
r_ray_end = math::transform_point(world_to_object, r_ray_end);
|
||||
|
||||
sub_v3_v3v3(ray_normal, ray_end, ray_start);
|
||||
dist = normalize_v3(ray_normal);
|
||||
float dist;
|
||||
r_ray_normal = math::normalize_and_get_length(r_ray_end - r_ray_start, dist);
|
||||
|
||||
/* If the ray is clipped, don't adjust its start/end. */
|
||||
if ((rv3d->is_persp == false) && !RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
|
||||
/* Get the view origin without the addition
|
||||
* of -ray_normal * clip_start that
|
||||
* ED_view3d_win_to_segment_clipped gave us.
|
||||
* This is necessary to avoid floating point overflow.
|
||||
*/
|
||||
ED_view3d_win_to_origin(vc->region, mval, ray_start);
|
||||
mul_m4_v3(obimat, ray_start);
|
||||
|
||||
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
|
||||
bke::pbvh::clip_ray_ortho(pbvh, original, ray_start, ray_end, ray_normal);
|
||||
|
||||
dist = len_v3v3(ray_start, ray_end);
|
||||
if (rv3d->is_persp || RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
|
||||
return dist;
|
||||
}
|
||||
|
||||
return dist;
|
||||
/* Get the view origin without the addition
|
||||
* of -ray_normal * clip_start that
|
||||
* ED_view3d_win_to_segment_clipped gave us.
|
||||
* This is necessary to avoid floating point overflow.
|
||||
*/
|
||||
float3 view_origin;
|
||||
ED_view3d_win_to_origin(vc->region, mval, view_origin);
|
||||
r_ray_start = math::transform_point(world_to_object, view_origin);
|
||||
|
||||
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
|
||||
bke::pbvh::clip_ray_ortho(pbvh, original, r_ray_start, r_ray_end, r_ray_normal);
|
||||
|
||||
return math::distance(r_ray_start, r_ray_end);
|
||||
}
|
||||
|
||||
bool SCULPT_cursor_geometry_info_update(bContext *C,
|
||||
SculptCursorGeometryInfo *out,
|
||||
const float mval[2],
|
||||
bool use_sampled_normal)
|
||||
bool cursor_geometry_info_update(bContext *C,
|
||||
CursorGeometryInfo *out,
|
||||
const float2 &mval,
|
||||
const bool use_sampled_normal)
|
||||
{
|
||||
using namespace blender;
|
||||
using namespace blender::ed::sculpt_paint;
|
||||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const Brush &brush = *BKE_paint_brush_for_read(BKE_paint_get_active_from_context(C));
|
||||
float ray_start[3], ray_end[3], ray_normal[3], depth, mat[3][3];
|
||||
float viewDir[3] = {0.0f, 0.0f, 1.0f};
|
||||
bool original = false;
|
||||
|
||||
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
|
||||
@@ -4717,21 +4710,24 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
|
||||
bke::pbvh::Tree *pbvh = bke::object::pbvh_get(ob);
|
||||
|
||||
if (!pbvh || !vc.rv3d || !BKE_base_is_visible(v3d, base)) {
|
||||
zero_v3(out->location);
|
||||
zero_v3(out->normal);
|
||||
zero_v3(out->active_vertex_co);
|
||||
out->location = float3(0.0f);
|
||||
out->normal = float3(0.0f);
|
||||
out->active_vertex_co = float3(0.0f);
|
||||
ss.clear_active_vert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* bke::pbvh::Tree raycast to get active vertex and face normal. */
|
||||
depth = SCULPT_raycast_init(&vc, mval, ray_start, ray_end, ray_normal, original);
|
||||
float3 ray_start;
|
||||
float3 ray_end;
|
||||
float3 ray_normal;
|
||||
float depth = raycast_init(&vc, mval, ray_start, ray_end, ray_normal, original);
|
||||
SCULPT_stroke_modifiers_check(C, ob, brush);
|
||||
|
||||
SculptRaycastData srd{};
|
||||
srd.original = original;
|
||||
RaycastData srd{};
|
||||
srd.use_original = original;
|
||||
srd.object = &ob;
|
||||
srd.ss = ob.sculpt;
|
||||
srd.is_mid_stroke = ob.sculpt->cache != nullptr;
|
||||
srd.hit = false;
|
||||
if (pbvh->type() == bke::pbvh::Type::Mesh) {
|
||||
const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
|
||||
@@ -4756,13 +4752,13 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
|
||||
[&](bke::pbvh::Node &node, float *tmin) { sculpt_raycast_cb(node, srd, tmin); },
|
||||
ray_start,
|
||||
ray_normal,
|
||||
srd.original);
|
||||
srd.use_original);
|
||||
|
||||
/* Cursor is not over the mesh, return default values. */
|
||||
if (!srd.hit) {
|
||||
zero_v3(out->location);
|
||||
zero_v3(out->normal);
|
||||
zero_v3(out->active_vertex_co);
|
||||
out->location = float3(0.0f);
|
||||
out->normal = float3(0.0f);
|
||||
out->active_vertex_co = float3(0.0f);
|
||||
ss.clear_active_vert(true);
|
||||
return false;
|
||||
}
|
||||
@@ -4786,13 +4782,11 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
|
||||
break;
|
||||
}
|
||||
|
||||
copy_v3_v3(out->location, ray_normal);
|
||||
mul_v3_fl(out->location, srd.depth);
|
||||
add_v3_v3(out->location, ray_start);
|
||||
out->location = ray_start + ray_normal * srd.depth;
|
||||
|
||||
/* Option to return the face normal directly for performance o accuracy reasons. */
|
||||
if (!use_sampled_normal) {
|
||||
copy_v3_v3(out->normal, srd.face_normal);
|
||||
out->normal = srd.face_normal;
|
||||
return srd.hit;
|
||||
}
|
||||
|
||||
@@ -4800,14 +4794,12 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
|
||||
float radius;
|
||||
|
||||
/* Update cursor data in SculptSession. */
|
||||
invert_m4_m4(ob.runtime->world_to_object.ptr(), ob.object_to_world().ptr());
|
||||
copy_m3_m4(mat, vc.rv3d->viewinv);
|
||||
mul_m3_v3(mat, viewDir);
|
||||
copy_m3_m4(mat, ob.world_to_object().ptr());
|
||||
mul_m3_v3(mat, viewDir);
|
||||
normalize_v3_v3(ss.cursor_view_normal, viewDir);
|
||||
copy_v3_v3(ss.cursor_normal, srd.face_normal);
|
||||
copy_v3_v3(ss.cursor_location, out->location);
|
||||
const float3 z_axis = {0.0f, 0.0f, 1.0f};
|
||||
ob.runtime->world_to_object = math::invert(ob.object_to_world());
|
||||
ss.cursor_view_normal = math::normalize(
|
||||
math::transform_direction(ob.world_to_object() * float4x4(vc.rv3d->viewinv), z_axis));
|
||||
ss.cursor_normal = srd.face_normal;
|
||||
ss.cursor_location = out->location;
|
||||
ss.rv3d = vc.rv3d;
|
||||
ss.v3d = vc.v3d;
|
||||
|
||||
@@ -4824,7 +4816,7 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
|
||||
|
||||
/* In case there are no nodes under the cursor, return the face normal. */
|
||||
if (node_mask.is_empty()) {
|
||||
copy_v3_v3(out->normal, srd.face_normal);
|
||||
out->normal = srd.face_normal;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -4834,38 +4826,28 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
|
||||
if (const std::optional<float3> sampled_normal = calc_area_normal(
|
||||
*depsgraph, brush, ob, node_mask))
|
||||
{
|
||||
copy_v3_v3(out->normal, *sampled_normal);
|
||||
out->normal = *sampled_normal;
|
||||
ss.cursor_sampled_normal = *sampled_normal;
|
||||
}
|
||||
else {
|
||||
/* Use face normal when there are no vertices to sample inside the cursor radius. */
|
||||
copy_v3_v3(out->normal, srd.face_normal);
|
||||
out->normal = srd.face_normal;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SCULPT_stroke_get_location(bContext *C,
|
||||
float out[3],
|
||||
const float mval[2],
|
||||
bool force_original)
|
||||
/**
|
||||
* \param check_closest if true and the ray test fails a point closest to the ray will be found.
|
||||
* \param limit_closest_radius if true then the closest point will be tested against the active
|
||||
* brush radius. */
|
||||
static bool stroke_get_location_bvh_ex(bContext *C,
|
||||
float3 &out,
|
||||
const float2 &mval,
|
||||
const bool force_original,
|
||||
const bool check_closest,
|
||||
const bool limit_closest_radius)
|
||||
{
|
||||
const Brush *brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
|
||||
bool check_closest = brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE;
|
||||
|
||||
return SCULPT_stroke_get_location_ex(C, out, mval, force_original, check_closest, true);
|
||||
}
|
||||
|
||||
bool SCULPT_stroke_get_location_ex(bContext *C,
|
||||
float out[3],
|
||||
const float mval[2],
|
||||
bool force_original,
|
||||
bool check_closest,
|
||||
bool limit_closest_radius)
|
||||
{
|
||||
using namespace blender;
|
||||
using namespace blender::ed::sculpt_paint;
|
||||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
float ray_start[3], ray_end[3], ray_normal[3], depth;
|
||||
|
||||
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
|
||||
|
||||
@@ -4873,56 +4855,53 @@ bool SCULPT_stroke_get_location_ex(bContext *C,
|
||||
|
||||
SculptSession &ss = *ob.sculpt;
|
||||
StrokeCache *cache = ss.cache;
|
||||
bool original = force_original || ((cache) ? !cache->accum : false);
|
||||
const bool original = force_original || ((cache) ? !cache->accum : false);
|
||||
|
||||
const Brush &brush = *BKE_paint_brush(BKE_paint_get_active_from_context(C));
|
||||
|
||||
SCULPT_stroke_modifiers_check(C, ob, brush);
|
||||
|
||||
depth = SCULPT_raycast_init(&vc, mval, ray_start, ray_end, ray_normal, original);
|
||||
float3 ray_start;
|
||||
float3 ray_end;
|
||||
float3 ray_normal;
|
||||
const float depth = raycast_init(&vc, mval, ray_start, ray_end, ray_normal, original);
|
||||
|
||||
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
|
||||
if (pbvh.type() == bke::pbvh::Type::BMesh) {
|
||||
BM_mesh_elem_table_ensure(ss.bm, BM_VERT);
|
||||
BM_mesh_elem_index_ensure(ss.bm, BM_VERT);
|
||||
}
|
||||
|
||||
bool hit = false;
|
||||
{
|
||||
SculptRaycastData srd;
|
||||
srd.object = &ob;
|
||||
srd.ss = ob.sculpt;
|
||||
srd.ray_start = ray_start;
|
||||
srd.ray_normal = ray_normal;
|
||||
srd.hit = false;
|
||||
RaycastData rd;
|
||||
rd.object = &ob;
|
||||
rd.is_mid_stroke = ob.sculpt->cache != nullptr;
|
||||
rd.ray_start = ray_start;
|
||||
rd.ray_normal = ray_normal;
|
||||
rd.hit = false;
|
||||
if (pbvh.type() == bke::pbvh::Type::Mesh) {
|
||||
const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
|
||||
srd.vert_positions = bke::pbvh::vert_positions_eval(*depsgraph, ob);
|
||||
srd.faces = mesh.faces();
|
||||
srd.corner_verts = mesh.corner_verts();
|
||||
srd.corner_tris = mesh.corner_tris();
|
||||
rd.vert_positions = bke::pbvh::vert_positions_eval(*depsgraph, ob);
|
||||
rd.faces = mesh.faces();
|
||||
rd.corner_verts = mesh.corner_verts();
|
||||
rd.corner_tris = mesh.corner_tris();
|
||||
const bke::AttributeAccessor attributes = mesh.attributes();
|
||||
srd.hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
|
||||
rd.hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
|
||||
}
|
||||
else if (pbvh.type() == bke::pbvh::Type::Grids) {
|
||||
srd.subdiv_ccg = ss.subdiv_ccg;
|
||||
rd.subdiv_ccg = ss.subdiv_ccg;
|
||||
}
|
||||
SCULPT_vertex_random_access_ensure(ob);
|
||||
srd.depth = depth;
|
||||
srd.original = original;
|
||||
isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
|
||||
rd.depth = depth;
|
||||
rd.use_original = original;
|
||||
isect_ray_tri_watertight_v3_precalc(&rd.isect_precalc, ray_normal);
|
||||
|
||||
bke::pbvh::raycast(
|
||||
pbvh,
|
||||
[&](bke::pbvh::Node &node, float *tmin) { sculpt_raycast_cb(node, srd, tmin); },
|
||||
[&](bke::pbvh::Node &node, float *tmin) { sculpt_raycast_cb(node, rd, tmin); },
|
||||
ray_start,
|
||||
ray_normal,
|
||||
srd.original);
|
||||
if (srd.hit) {
|
||||
rd.use_original);
|
||||
if (rd.hit) {
|
||||
hit = true;
|
||||
copy_v3_v3(out, ray_normal);
|
||||
mul_v3_fl(out, srd.depth);
|
||||
add_v3_v3(out, ray_start);
|
||||
out = ray_start + ray_normal * rd.depth;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4930,39 +4909,39 @@ bool SCULPT_stroke_get_location_ex(bContext *C,
|
||||
return hit;
|
||||
}
|
||||
|
||||
SculptFindNearestToRayData srd{};
|
||||
srd.original = original;
|
||||
srd.object = &ob;
|
||||
srd.ss = ob.sculpt;
|
||||
srd.hit = false;
|
||||
FindNearestToRayData fntrd{};
|
||||
fntrd.use_original = original;
|
||||
fntrd.object = &ob;
|
||||
fntrd.is_mid_stroke = ss.cache != nullptr;
|
||||
fntrd.hit = false;
|
||||
if (pbvh.type() == bke::pbvh::Type::Mesh) {
|
||||
const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
|
||||
srd.vert_positions = bke::pbvh::vert_positions_eval(*depsgraph, ob);
|
||||
srd.faces = mesh.faces();
|
||||
srd.corner_verts = mesh.corner_verts();
|
||||
srd.corner_tris = mesh.corner_tris();
|
||||
fntrd.vert_positions = bke::pbvh::vert_positions_eval(*depsgraph, ob);
|
||||
fntrd.faces = mesh.faces();
|
||||
fntrd.corner_verts = mesh.corner_verts();
|
||||
fntrd.corner_tris = mesh.corner_tris();
|
||||
const bke::AttributeAccessor attributes = mesh.attributes();
|
||||
srd.hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
|
||||
fntrd.hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
|
||||
}
|
||||
else if (pbvh.type() == bke::pbvh::Type::Grids) {
|
||||
srd.subdiv_ccg = ss.subdiv_ccg;
|
||||
fntrd.subdiv_ccg = ss.subdiv_ccg;
|
||||
}
|
||||
srd.ray_start = ray_start;
|
||||
srd.ray_normal = ray_normal;
|
||||
srd.depth = std::numeric_limits<float>::max();
|
||||
srd.dist_sq_to_ray = std::numeric_limits<float>::max();
|
||||
fntrd.ray_start = ray_start;
|
||||
fntrd.ray_normal = ray_normal;
|
||||
fntrd.depth = std::numeric_limits<float>::max();
|
||||
fntrd.dist_sq_to_ray = std::numeric_limits<float>::max();
|
||||
|
||||
bke::pbvh::find_nearest_to_ray(
|
||||
pbvh,
|
||||
[&](bke::pbvh::Node &node, float *tmin) { sculpt_find_nearest_to_ray_cb(node, srd, tmin); },
|
||||
[&](bke::pbvh::Node &node, float *tmin) {
|
||||
sculpt_find_nearest_to_ray_cb(node, fntrd, tmin);
|
||||
},
|
||||
ray_start,
|
||||
ray_normal,
|
||||
srd.original);
|
||||
if (srd.hit && srd.dist_sq_to_ray) {
|
||||
fntrd.use_original);
|
||||
if (fntrd.hit && fntrd.dist_sq_to_ray) {
|
||||
hit = true;
|
||||
copy_v3_v3(out, ray_normal);
|
||||
mul_v3_fl(out, srd.depth);
|
||||
add_v3_v3(out, ray_start);
|
||||
out = ray_start + ray_normal * fntrd.depth;
|
||||
}
|
||||
|
||||
float closest_radius_sq = std::numeric_limits<float>::max();
|
||||
@@ -4971,9 +4950,27 @@ bool SCULPT_stroke_get_location_ex(bContext *C,
|
||||
closest_radius_sq *= closest_radius_sq;
|
||||
}
|
||||
|
||||
return hit && srd.dist_sq_to_ray < closest_radius_sq;
|
||||
return hit && fntrd.dist_sq_to_ray < closest_radius_sq;
|
||||
}
|
||||
|
||||
bool stroke_get_location_bvh(bContext *C,
|
||||
float out[3],
|
||||
const float mval[2],
|
||||
const bool force_original)
|
||||
{
|
||||
const Brush *brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
|
||||
const bool check_closest = brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE;
|
||||
|
||||
float3 location;
|
||||
const bool result = stroke_get_location_bvh_ex(
|
||||
C, location, mval, force_original, check_closest, true);
|
||||
if (result) {
|
||||
copy_v3_v3(out, location);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} // namespace blender::ed::sculpt_paint
|
||||
|
||||
static void brush_init_tex(const Sculpt &sd, SculptSession &ss)
|
||||
{
|
||||
const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
|
||||
@@ -5445,13 +5442,14 @@ void store_mesh_from_eval(const wmOperator &op,
|
||||
* or over the background (0). */
|
||||
static bool over_mesh(bContext *C, wmOperator * /*op*/, const float mval[2])
|
||||
{
|
||||
float co_dummy[3];
|
||||
float3 co_dummy;
|
||||
Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
|
||||
Brush *brush = BKE_paint_brush(&sd->paint);
|
||||
|
||||
bool check_closest = brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE;
|
||||
const bool check_closest = brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE;
|
||||
|
||||
return SCULPT_stroke_get_location_ex(C, co_dummy, mval, false, check_closest, true);
|
||||
return blender::ed::sculpt_paint::stroke_get_location_bvh_ex(
|
||||
C, co_dummy, mval, false, check_closest, true);
|
||||
}
|
||||
|
||||
static void stroke_undo_begin(const bContext *C, wmOperator *op)
|
||||
@@ -5535,8 +5533,8 @@ static bool stroke_test_start(bContext *C, wmOperator *op, const float mval[2])
|
||||
|
||||
sculpt_update_cache_invariants(C, sd, ss, *op, mval);
|
||||
|
||||
SculptCursorGeometryInfo sgi;
|
||||
SCULPT_cursor_geometry_info_update(C, &sgi, mval, false);
|
||||
CursorGeometryInfo cgi;
|
||||
cursor_geometry_info_update(C, &cgi, mval, false);
|
||||
|
||||
stroke_undo_begin(C, op);
|
||||
|
||||
@@ -5706,7 +5704,7 @@ static wmOperatorStatus sculpt_brush_stroke_invoke(bContext *C,
|
||||
|
||||
stroke = paint_stroke_new(C,
|
||||
op,
|
||||
SCULPT_stroke_get_location,
|
||||
stroke_get_location_bvh,
|
||||
stroke_test_start,
|
||||
stroke_update_step,
|
||||
nullptr,
|
||||
@@ -5744,7 +5742,7 @@ static wmOperatorStatus sculpt_brush_stroke_exec(bContext *C, wmOperator *op)
|
||||
|
||||
op->customdata = paint_stroke_new(C,
|
||||
op,
|
||||
SCULPT_stroke_get_location,
|
||||
stroke_get_location_bvh,
|
||||
stroke_test_start,
|
||||
stroke_update_step,
|
||||
nullptr,
|
||||
@@ -6147,33 +6145,33 @@ void SCULPT_fake_neighbors_free(Object &ob)
|
||||
pose_fake_neighbors_free(ss);
|
||||
}
|
||||
|
||||
bool SCULPT_vertex_is_occluded(const Depsgraph &depsgraph,
|
||||
const Object &object,
|
||||
const float3 &position,
|
||||
bool original)
|
||||
namespace blender::ed::sculpt_paint {
|
||||
bool vertex_is_occluded(const Depsgraph &depsgraph,
|
||||
const Object &object,
|
||||
const float3 &position,
|
||||
bool original)
|
||||
{
|
||||
using namespace blender;
|
||||
SculptSession &ss = *object.sculpt;
|
||||
float ray_start[3], ray_end[3], ray_normal[3];
|
||||
|
||||
ViewContext *vc = ss.cache ? ss.cache->vc : &ss.filter_cache->vc;
|
||||
|
||||
const blender::float2 mouse = ED_view3d_project_float_v2_m4(
|
||||
const float2 mouse = ED_view3d_project_float_v2_m4(
|
||||
vc->region, position, ss.cache ? ss.cache->projection_mat : ss.filter_cache->viewmat);
|
||||
|
||||
int depth = SCULPT_raycast_init(vc, mouse, ray_end, ray_start, ray_normal, original);
|
||||
float3 ray_start;
|
||||
float3 ray_end;
|
||||
float3 ray_normal;
|
||||
float depth = raycast_init(vc, mouse, ray_end, ray_start, ray_normal, original);
|
||||
|
||||
negate_v3(ray_normal);
|
||||
|
||||
copy_v3_v3(ray_start, position);
|
||||
madd_v3_v3fl(ray_start, ray_normal, 0.002);
|
||||
ray_normal = ray_normal * -1.0f;
|
||||
ray_start = position + ray_normal * 0.002f;
|
||||
|
||||
bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(const_cast<Object &>(object));
|
||||
|
||||
SculptRaycastData srd = {nullptr};
|
||||
srd.original = original;
|
||||
RaycastData srd = {nullptr};
|
||||
srd.use_original = original;
|
||||
srd.object = &const_cast<Object &>(object);
|
||||
srd.ss = &ss;
|
||||
srd.is_mid_stroke = ss.cache != nullptr;
|
||||
srd.hit = false;
|
||||
srd.ray_start = ray_start;
|
||||
srd.ray_normal = ray_normal;
|
||||
@@ -6196,10 +6194,11 @@ bool SCULPT_vertex_is_occluded(const Depsgraph &depsgraph,
|
||||
[&](bke::pbvh::Node &node, float *tmin) { sculpt_raycast_cb(node, srd, tmin); },
|
||||
ray_start,
|
||||
ray_normal,
|
||||
srd.original);
|
||||
srd.use_original);
|
||||
|
||||
return srd.hit;
|
||||
}
|
||||
} // namespace blender::ed::sculpt_paint
|
||||
|
||||
namespace blender::ed::sculpt_paint::islands {
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ static bool calc_view_occlusion_factor(const Depsgraph &depsgraph,
|
||||
const float3 &vert_position)
|
||||
{
|
||||
if (automasking.occlusion[vert] == Cache::OcclusionValue::Unknown) {
|
||||
const bool occluded = SCULPT_vertex_is_occluded(depsgraph, object, vert_position, true);
|
||||
const bool occluded = vertex_is_occluded(depsgraph, object, vert_position, true);
|
||||
automasking.occlusion[vert] = occluded ? Cache::OcclusionValue::Occluded :
|
||||
Cache::OcclusionValue::Visible;
|
||||
}
|
||||
|
||||
@@ -2415,8 +2415,8 @@ static wmOperatorStatus sculpt_cloth_filter_invoke(bContext *C,
|
||||
|
||||
/* Update the active vertex */
|
||||
float2 mval_fl{float(event->mval[0]), float(event->mval[1])};
|
||||
SculptCursorGeometryInfo sgi;
|
||||
SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false);
|
||||
CursorGeometryInfo cgi;
|
||||
cursor_geometry_info_update(C, &cgi, mval_fl, false);
|
||||
|
||||
/* Needs mask data to be available as it is used when solving the constraints. */
|
||||
BKE_sculpt_update_object_for_edit(depsgraph, &ob, false);
|
||||
|
||||
@@ -214,11 +214,11 @@ static bool sample_detail_voxel(bContext *C, ViewContext *vc, const int mval[2])
|
||||
const bke::AttributeAccessor attributes = mesh.attributes();
|
||||
const VArraySpan hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
|
||||
|
||||
SculptCursorGeometryInfo sgi;
|
||||
CursorGeometryInfo cgi;
|
||||
|
||||
/* Update the active vertex. */
|
||||
const float mval_fl[2] = {float(mval[0]), float(mval[1])};
|
||||
if (!SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false)) {
|
||||
if (!cursor_geometry_info_update(C, &cgi, mval_fl, false)) {
|
||||
return false;
|
||||
}
|
||||
BKE_sculpt_update_object_for_edit(depsgraph, &ob, false);
|
||||
@@ -259,9 +259,11 @@ static void sample_detail_dyntopo(bContext *C, ViewContext *vc, const int mval[2
|
||||
|
||||
SCULPT_stroke_modifiers_check(C, ob, brush);
|
||||
|
||||
const float mval_fl[2] = {float(mval[0]), float(mval[1])};
|
||||
float ray_start[3], ray_end[3], ray_normal[3];
|
||||
float depth = SCULPT_raycast_init(vc, mval_fl, ray_start, ray_end, ray_normal, false);
|
||||
const float2 mval_fl = {float(mval[0]), float(mval[1])};
|
||||
float3 ray_start;
|
||||
float3 ray_end;
|
||||
float3 ray_normal;
|
||||
float depth = raycast_init(vc, mval_fl, ray_start, ray_end, ray_normal, false);
|
||||
|
||||
SculptDetailRaycastData srd;
|
||||
srd.hit = false;
|
||||
|
||||
@@ -2025,8 +2025,8 @@ static void update_for_vert(bContext *C, Object &ob, const std::optional<int> ve
|
||||
static std::optional<int> target_vert_update_and_get(bContext *C, Object &ob, const float mval[2])
|
||||
{
|
||||
SculptSession &ss = *ob.sculpt;
|
||||
SculptCursorGeometryInfo sgi;
|
||||
if (SCULPT_cursor_geometry_info_update(C, &sgi, mval, false)) {
|
||||
CursorGeometryInfo cgi;
|
||||
if (cursor_geometry_info_update(C, &cgi, mval, false)) {
|
||||
return ss.active_vert_index();
|
||||
}
|
||||
return std::nullopt;
|
||||
|
||||
@@ -142,8 +142,8 @@ int active_update_and_get(bContext *C, Object &ob, const float mval[2])
|
||||
return SCULPT_FACE_SET_NONE;
|
||||
}
|
||||
|
||||
SculptCursorGeometryInfo gi;
|
||||
if (!SCULPT_cursor_geometry_info_update(C, &gi, mval, false)) {
|
||||
CursorGeometryInfo gi;
|
||||
if (!cursor_geometry_info_update(C, &gi, mval, false)) {
|
||||
return SCULPT_FACE_SET_NONE;
|
||||
}
|
||||
|
||||
@@ -1101,10 +1101,10 @@ static wmOperatorStatus change_visibility_invoke(bContext *C, wmOperator *op, co
|
||||
|
||||
/* Update the active vertex and Face Set using the cursor position to avoid relying on the paint
|
||||
* cursor updates. */
|
||||
SculptCursorGeometryInfo sgi;
|
||||
CursorGeometryInfo cgi;
|
||||
const float mval_fl[2] = {float(event->mval[0]), float(event->mval[1])};
|
||||
SCULPT_vertex_random_access_ensure(ob);
|
||||
SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false);
|
||||
cursor_geometry_info_update(C, &cgi, mval_fl, false);
|
||||
|
||||
return change_visibility_exec(C, op);
|
||||
}
|
||||
@@ -1566,9 +1566,9 @@ static wmOperatorStatus edit_op_invoke(bContext *C, wmOperator *op, const wmEven
|
||||
|
||||
/* Update the current active Face Set and Vertex as the operator can be used directly from the
|
||||
* tool without brush cursor. */
|
||||
SculptCursorGeometryInfo sgi;
|
||||
CursorGeometryInfo cgi;
|
||||
const float mval_fl[2] = {float(event->mval[0]), float(event->mval[1])};
|
||||
if (!SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false)) {
|
||||
if (!cursor_geometry_info_update(C, &cgi, mval_fl, false)) {
|
||||
/* The cursor is not over the mesh. Cancel to avoid editing the last updated Face Set ID. */
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
@@ -478,8 +478,8 @@ static int sculpt_color_filter_init(bContext *C, wmOperator *op)
|
||||
if (v3d) {
|
||||
/* Update the active face set manually as the paint cursor is not enabled when using the Mesh
|
||||
* Filter Tool. */
|
||||
SculptCursorGeometryInfo sgi;
|
||||
SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false);
|
||||
CursorGeometryInfo cgi;
|
||||
cursor_geometry_info_update(C, &cgi, mval_fl, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ void cache_init(bContext *C,
|
||||
|
||||
float3 co;
|
||||
|
||||
if (vc.rv3d && SCULPT_stroke_get_location(C, co, mval_fl, false)) {
|
||||
if (vc.rv3d && stroke_get_location_bvh(C, co, mval_fl, false)) {
|
||||
/* Get radius from brush. */
|
||||
const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
|
||||
|
||||
@@ -2424,8 +2424,8 @@ static wmOperatorStatus sculpt_mesh_filter_start(bContext *C, wmOperator *op)
|
||||
if (use_automasking) {
|
||||
/* Update the active face set manually as the paint cursor is not enabled when using the
|
||||
* Mesh Filter Tool. */
|
||||
SculptCursorGeometryInfo sgi;
|
||||
SCULPT_cursor_geometry_info_update(C, &sgi, mval_fl, false);
|
||||
CursorGeometryInfo cgi;
|
||||
cursor_geometry_info_update(C, &cgi, mval_fl, false);
|
||||
}
|
||||
|
||||
SCULPT_vertex_random_access_ensure(ob);
|
||||
|
||||
@@ -125,12 +125,6 @@ enum class UpdateType {
|
||||
|
||||
} // namespace blender::ed::sculpt_paint
|
||||
|
||||
struct SculptCursorGeometryInfo {
|
||||
blender::float3 location;
|
||||
blender::float3 normal;
|
||||
blender::float3 active_vertex_co;
|
||||
};
|
||||
|
||||
/* Factor of brush to have rake point following behind
|
||||
* (could be configurable but this is reasonable default). */
|
||||
#define SCULPT_RAKE_BRUSH_FACTOR 0.25f
|
||||
@@ -473,51 +467,48 @@ void SCULPT_tag_update_overlays(bContext *C);
|
||||
/** \name Stroke Functions
|
||||
* \{ */
|
||||
|
||||
namespace blender::ed::sculpt_paint {
|
||||
/**
|
||||
* Do a ray-cast in the tree to find the 3d brush location
|
||||
* (This allows us to ignore the GL depth buffer)
|
||||
* Returns 0 if the ray doesn't hit the mesh, non-zero otherwise.
|
||||
*
|
||||
* If check_closest is true and the ray test fails a point closest
|
||||
* to the ray will be found. If limit_closest_radius is true then
|
||||
* the closest point will be tested against the active brush radius.
|
||||
* TODO: This should be updated to return std::optional<float3>
|
||||
*/
|
||||
bool SCULPT_stroke_get_location_ex(bContext *C,
|
||||
float out[3],
|
||||
const float mval[2],
|
||||
bool force_original,
|
||||
bool check_closest,
|
||||
bool limit_closest_radius);
|
||||
bool stroke_get_location_bvh(bContext *C, float out[3], const float mval[2], bool force_original);
|
||||
|
||||
struct CursorGeometryInfo {
|
||||
float3 location;
|
||||
float3 normal;
|
||||
float3 active_vertex_co;
|
||||
};
|
||||
|
||||
bool SCULPT_stroke_get_location(bContext *C,
|
||||
float out[3],
|
||||
const float mval[2],
|
||||
bool force_original);
|
||||
/**
|
||||
* Gets the normal, location and active vertex location of the geometry under the cursor. This also
|
||||
* updates the active vertex and cursor related data of the SculptSession using the mouse position
|
||||
*
|
||||
* TODO: This should be updated to return `std::optional<CursorGeometryInfo>`
|
||||
*/
|
||||
bool SCULPT_cursor_geometry_info_update(bContext *C,
|
||||
SculptCursorGeometryInfo *out,
|
||||
const float mval[2],
|
||||
bool use_sampled_normal);
|
||||
|
||||
namespace blender::ed::sculpt_paint {
|
||||
bool cursor_geometry_info_update(bContext *C,
|
||||
CursorGeometryInfo *out,
|
||||
const float2 &mval,
|
||||
bool use_sampled_normal);
|
||||
|
||||
void geometry_preview_lines_update(Depsgraph &depsgraph,
|
||||
Object &object,
|
||||
SculptSession &ss,
|
||||
float radius);
|
||||
|
||||
}
|
||||
} // namespace blender::ed::sculpt_paint
|
||||
|
||||
void SCULPT_stroke_modifiers_check(const bContext *C, Object &ob, const Brush &brush);
|
||||
float SCULPT_raycast_init(ViewContext *vc,
|
||||
const float mval[2],
|
||||
float ray_start[3],
|
||||
float ray_end[3],
|
||||
float ray_normal[3],
|
||||
bool original);
|
||||
namespace blender::ed::sculpt_paint {
|
||||
float raycast_init(ViewContext *vc,
|
||||
const float2 &mval,
|
||||
float3 &ray_start,
|
||||
float3 &ray_end,
|
||||
float3 &ray_normal,
|
||||
bool original);
|
||||
}
|
||||
|
||||
/* Symmetry */
|
||||
ePaintSymmetryFlags SCULPT_mesh_symmetry_xyz_get(const Object &object);
|
||||
@@ -561,12 +552,11 @@ void SCULPT_vertex_random_access_ensure(Object &object);
|
||||
|
||||
int SCULPT_vertex_count_get(const Object &object);
|
||||
|
||||
bool SCULPT_vertex_is_occluded(const Depsgraph &depsgraph,
|
||||
const Object &object,
|
||||
const blender::float3 &position,
|
||||
bool original);
|
||||
|
||||
namespace blender::ed::sculpt_paint {
|
||||
bool vertex_is_occluded(const Depsgraph &depsgraph,
|
||||
const Object &object,
|
||||
const float3 &position,
|
||||
bool original);
|
||||
|
||||
/**
|
||||
* Coordinates used for manipulating the base mesh when Grab Active Vertex is enabled.
|
||||
|
||||
@@ -840,8 +840,8 @@ static wmOperatorStatus mask_by_color(bContext *C, wmOperator *op, const float2
|
||||
|
||||
/* Tools that are not brushes do not have the brush gizmo to update the vertex as the mouse move,
|
||||
* so it needs to be updated here. */
|
||||
SculptCursorGeometryInfo sgi;
|
||||
SCULPT_cursor_geometry_info_update(C, &sgi, region_location, false);
|
||||
CursorGeometryInfo cgi;
|
||||
cursor_geometry_info_update(C, &cgi, region_location, false);
|
||||
|
||||
if (std::holds_alternative<std::monostate>(ss.active_vert())) {
|
||||
return OPERATOR_CANCELLED;
|
||||
|
||||
@@ -943,7 +943,7 @@ static wmOperatorStatus set_pivot_position_exec(bContext *C, wmOperator *op)
|
||||
RNA_float_get(op->ptr, "mouse_x"),
|
||||
RNA_float_get(op->ptr, "mouse_y"),
|
||||
};
|
||||
if (SCULPT_stroke_get_location(C, stroke_location, mval, false)) {
|
||||
if (stroke_get_location_bvh(C, stroke_location, mval, false)) {
|
||||
copy_v3_v3(ss.pivot_pos, stroke_location);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -764,14 +764,14 @@ static void initialize_cursor_info(bContext &C,
|
||||
int mval[2];
|
||||
RNA_int_get_array(op.ptr, "location", mval);
|
||||
|
||||
SculptCursorGeometryInfo sgi;
|
||||
CursorGeometryInfo cgi;
|
||||
const float mval_fl[2] = {float(mval[0]), float(mval[1])};
|
||||
|
||||
TrimOperation *trim_operation = (TrimOperation *)gesture_data.operation;
|
||||
trim_operation->initial_hit = SCULPT_cursor_geometry_info_update(&C, &sgi, mval_fl, false);
|
||||
trim_operation->initial_hit = cursor_geometry_info_update(&C, &cgi, mval_fl, false);
|
||||
if (trim_operation->initial_hit) {
|
||||
copy_v3_v3(trim_operation->initial_location, sgi.location);
|
||||
copy_v3_v3(trim_operation->initial_normal, sgi.normal);
|
||||
copy_v3_v3(trim_operation->initial_location, cgi.location);
|
||||
copy_v3_v3(trim_operation->initial_normal, cgi.normal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user