Merge branch 'arcpatch-D9622' into sculpt-dev

This commit is contained in:
2021-02-07 19:18:46 +01:00
16 changed files with 216 additions and 63 deletions

View File

@@ -1405,6 +1405,7 @@ class _defs_sculpt:
props = tool.operator_properties("sculpt.trim_lasso_gesture")
layout.prop(props, "trim_mode", expand=False)
layout.prop(props, "trim_orientation", expand=False)
layout.prop(props, "trim_location", expand=False)
layout.prop(props, "use_cursor_depth", expand=False)
return dict(
idname="builtin.lasso_trim",

View File

@@ -540,6 +540,7 @@ typedef struct SculptSession {
/* For Sculpt trimming gesture tools, initial raycast data from the position of the mouse when
* the gesture starts (intersection with the surface and if they ray hit the surface or not). */
float gesture_initial_back_location[3];
float gesture_initial_location[3];
float gesture_initial_normal[3];
bool gesture_initial_hit;

View File

@@ -159,7 +159,9 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
const float ray_start[3],
const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc,
int *hit_count,
float *depth,
float *back_depth,
int *active_vertex_index,
int *active_face_grid_index,
float *face_normal);

View File

@@ -2059,6 +2059,59 @@ bool ray_face_intersection_tri(const float ray_start[3],
return false;
}
bool ray_update_depth_and_hit_count(const float depth_test,
float *r_depth,
float *r_back_depth,
int *hit_count)
{
(*hit_count)++;
if (depth_test < *r_depth) {
*r_back_depth = *r_depth;
*r_depth = depth_test;
return true;
}
else if (depth_test > *r_depth && depth_test <= *r_back_depth) {
*r_back_depth = depth_test;
return false;
}
return false;
}
float ray_face_intersection_depth_quad(const float ray_start[3],
struct IsectRayPrecalc *isect_precalc,
const float t0[3],
const float t1[3],
const float t2[3],
const float t3[3],
float *r_depth,
float *r_back_depth,
int *hit_count)
{
float depth_test;
if (!(isect_ray_tri_watertight_v3(ray_start, isect_precalc, t0, t1, t2, &depth_test, NULL) ||
isect_ray_tri_watertight_v3(ray_start, isect_precalc, t0, t2, t3, &depth_test, NULL))) {
return false;
}
return ray_update_depth_and_hit_count(depth_test, r_depth, r_back_depth, hit_count);
}
bool ray_face_intersection_depth_tri(const float ray_start[3],
struct IsectRayPrecalc *isect_precalc,
const float t0[3],
const float t1[3],
const float t2[3],
float *r_depth,
float *r_back_depth,
int *hit_count)
{
float depth_test;
if (!isect_ray_tri_watertight_v3(ray_start, isect_precalc, t0, t1, t2, &depth_test, NULL)) {
return false;
}
return ray_update_depth_and_hit_count(depth_test, r_depth, r_back_depth, hit_count);
}
/* Take advantage of the fact we know this wont be an intersection.
* Just handle ray-tri edges. */
static float dist_squared_ray_to_tri_v3_fast(const float ray_origin[3],
@@ -2138,7 +2191,9 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
const float ray_start[3],
const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc,
int *hit_count,
float *depth,
float *depth_back,
int *r_active_vertex_index,
int *r_active_face_index,
float *r_face_normal)
@@ -2172,26 +2227,29 @@ static bool pbvh_faces_node_raycast(PBVH *pbvh,
co[2] = vert[mloop[lt->tri[2]].v].co;
}
if (ray_face_intersection_tri(ray_start, isect_precalc, co[0], co[1], co[2], depth)) {
hit = true;
if (!ray_face_intersection_depth_tri(
ray_start, isect_precalc, co[0], co[1], co[2], depth, depth_back, hit_count)) {
continue;
}
if (r_face_normal) {
normal_tri_v3(r_face_normal, co[0], co[1], co[2]);
}
hit = true;
if (r_active_vertex_index) {
float location[3] = {0.0f};
madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
for (int j = 0; j < 3; j++) {
/* Always assign nearest_vertex_co in the first iteration to avoid comparison against
* uninitialized values. This stores the closest vertex in the current intersecting
* triangle. */
if (j == 0 ||
len_squared_v3v3(location, co[j]) < len_squared_v3v3(location, nearest_vertex_co)) {
copy_v3_v3(nearest_vertex_co, co[j]);
*r_active_vertex_index = mloop[lt->tri[j]].v;
*r_active_face_index = lt->poly;
}
if (r_face_normal) {
normal_tri_v3(r_face_normal, co[0], co[1], co[2]);
}
if (r_active_vertex_index) {
float location[3] = {0.0f};
madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
for (int j = 0; j < 3; j++) {
/* Always assign nearest_vertex_co in the first iteration to avoid comparison against
* uninitialized values. This stores the closest vertex in the current intersecting
* triangle. */
if (j == 0 ||
len_squared_v3v3(location, co[j]) < len_squared_v3v3(location, nearest_vertex_co)) {
copy_v3_v3(nearest_vertex_co, co[j]);
*r_active_vertex_index = mloop[lt->tri[j]].v;
*r_active_face_index = lt->poly;
}
}
}
@@ -2206,7 +2264,9 @@ static bool pbvh_grids_node_raycast(PBVH *pbvh,
const float ray_start[3],
const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc,
int *hit_count,
float *depth,
float *back_depth,
int *r_active_vertex_index,
int *r_active_grid_index,
float *r_face_normal)
@@ -2251,37 +2311,45 @@ static bool pbvh_grids_node_raycast(PBVH *pbvh,
co[3] = CCG_grid_elem_co(gridkey, grid, x, y + 1);
}
if (ray_face_intersection_quad(
ray_start, isect_precalc, co[0], co[1], co[2], co[3], depth)) {
hit = true;
if (ray_face_intersection_depth_quad(ray_start,
isect_precalc,
co[0],
co[1],
co[2],
co[3],
depth,
back_depth,
hit_count)) {
continue;
}
hit = true;
if (r_face_normal) {
normal_quad_v3(r_face_normal, co[0], co[1], co[2], co[3]);
}
if (r_face_normal) {
normal_quad_v3(r_face_normal, co[0], co[1], co[2], co[3]);
}
if (r_active_vertex_index) {
float location[3] = {0.0};
madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
if (r_active_vertex_index) {
float location[3] = {0.0};
madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
const int x_it[4] = {0, 1, 1, 0};
const int y_it[4] = {0, 0, 1, 1};
const int x_it[4] = {0, 1, 1, 0};
const int y_it[4] = {0, 0, 1, 1};
for (int j = 0; j < 4; j++) {
/* Always assign nearest_vertex_co in the first iteration to avoid comparison against
* uninitialized values. This stores the closest vertex in the current intersecting
* quad. */
if (j == 0 || len_squared_v3v3(location, co[j]) <
len_squared_v3v3(location, nearest_vertex_co)) {
copy_v3_v3(nearest_vertex_co, co[j]);
for (int j = 0; j < 4; j++) {
/* Always assign nearest_vertex_co in the first iteration to avoid comparison against
* uninitialized values. This stores the closest vertex in the current intersecting
* quad. */
if (j == 0 || len_squared_v3v3(location, co[j]) <
len_squared_v3v3(location, nearest_vertex_co)) {
copy_v3_v3(nearest_vertex_co, co[j]);
*r_active_vertex_index = gridkey->grid_area * grid_index +
(y + y_it[j]) * gridkey->grid_size + (x + x_it[j]);
}
*r_active_vertex_index = gridkey->grid_area * grid_index +
(y + y_it[j]) * gridkey->grid_size + (x + x_it[j]);
}
}
if (r_active_grid_index) {
*r_active_grid_index = grid_index;
}
}
if (r_active_grid_index) {
*r_active_grid_index = grid_index;
}
}
}
@@ -2301,7 +2369,9 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
const float ray_start[3],
const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc,
int *hit_count,
float *depth,
float *back_depth,
int *active_vertex_index,
int *active_face_grid_index,
float *face_normal)
@@ -2320,7 +2390,9 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
ray_start,
ray_normal,
isect_precalc,
hit_count,
depth,
back_depth,
active_vertex_index,
active_face_grid_index,
face_normal);
@@ -2332,7 +2404,9 @@ bool BKE_pbvh_node_raycast(PBVH *pbvh,
ray_start,
ray_normal,
isect_precalc,
hit_count,
depth,
back_depth,
active_vertex_index,
active_face_grid_index,
face_normal);

View File

@@ -1367,7 +1367,7 @@ static void paint_cursor_sculpt_session_update_and_init(PaintCursorContext *pcon
pcontext->prev_active_vertex_index = ss->active_vertex_index;
if (!ups->stroke_active) {
pcontext->is_cursor_over_mesh = SCULPT_cursor_geometry_info_update(
C, &gi, mouse, pcontext->brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE);
C, &gi, mouse, (pcontext->brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE), false);
copy_v3_v3(pcontext->location, gi.location);
copy_v3_v3(pcontext->normal, gi.normal);
}

View File

@@ -950,6 +950,24 @@ static EnumPropertyItem prop_trim_orientation_types[] = {
{0, NULL, 0, NULL, NULL},
};
typedef enum eSculptTrimLocationType {
SCULPT_GESTURE_TRIM_LOCATION_DEPTH_SURFACE,
SCULPT_GESTURE_TRIM_LOCATION_DEPTH_VOLUME,
} eSculptTrimLocationType;
static EnumPropertyItem prop_trim_location_types[] = {
{SCULPT_GESTURE_TRIM_LOCATION_DEPTH_SURFACE,
"DEPTH_SURFACE",
0,
"Surface",
"Use the surface under the cursor to locate the trimming shape"},
{SCULPT_GESTURE_TRIM_LOCATION_DEPTH_VOLUME,
"DEPTH_VOLUME",
0,
"Volume",
"Use the volume of the mesh to locate the trimming shape in the center of the volume"},
{0, NULL, 0, NULL, NULL},
};
typedef struct SculptGestureTrimOperation {
SculptGestureOperation op;
@@ -963,6 +981,7 @@ typedef struct SculptGestureTrimOperation {
eSculptTrimOperationType mode;
eSculptTrimOrientationType orientation;
eSculptTrimLocationType location;
} SculptGestureTrimOperation;
static void sculpt_gesture_trim_normals_update(SculptGestureContext *sgcontext)
@@ -1054,8 +1073,19 @@ static void sculpt_gesture_trim_calculate_depth(bContext *C, SculptGestureContex
if (trim_operation->use_cursor_depth) {
float world_space_gesture_initial_location[3];
mul_v3_m4v3(
world_space_gesture_initial_location, vc->obact->obmat, ss->gesture_initial_location);
switch (trim_operation->location) {
case SCULPT_GESTURE_TRIM_LOCATION_DEPTH_SURFACE: {
mul_v3_m4v3(
world_space_gesture_initial_location, vc->obact->obmat, ss->gesture_initial_location);
} break;
case SCULPT_GESTURE_TRIM_LOCATION_DEPTH_VOLUME: {
float center_co[3];
mid_v3_v3v3(center_co, ss->gesture_initial_location, ss->gesture_initial_back_location);
mul_v3_m4v3(world_space_gesture_initial_location, vc->obact->obmat, center_co);
} break;
}
float mid_point_depth;
if (trim_operation->orientation == SCULPT_GESTURE_TRIM_ORIENTATION_VIEW) {
@@ -1363,6 +1393,7 @@ static void sculpt_gesture_init_trim_properties(SculptGestureContext *sgcontext,
trim_operation->mode = RNA_enum_get(op->ptr, "trim_mode");
trim_operation->use_cursor_depth = RNA_boolean_get(op->ptr, "use_cursor_depth");
trim_operation->orientation = RNA_enum_get(op->ptr, "trim_orientation");
trim_operation->location = RNA_enum_get(op->ptr, "trim_location");
/* If the cursor was not over the mesh, force the orientation to view. */
if (!sgcontext->ss->gesture_initial_hit) {
@@ -1390,6 +1421,13 @@ static void sculpt_trim_gesture_operator_properties(wmOperatorType *ot)
SCULPT_GESTURE_TRIM_ORIENTATION_VIEW,
"Shape Orientation",
NULL);
RNA_def_enum(ot->srna,
"trim_location",
prop_trim_location_types,
SCULPT_GESTURE_TRIM_LOCATION_DEPTH_SURFACE,
"Shape Location",
NULL);
}
/* Project Gesture Operation. */
@@ -1741,7 +1779,7 @@ static int sculpt_trim_gesture_box_invoke(bContext *C, wmOperator *op, const wmE
SculptCursorGeometryInfo sgi;
float mouse[2] = {event->mval[0], event->mval[1]};
SCULPT_vertex_random_access_ensure(ss);
ss->gesture_initial_hit = SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
ss->gesture_initial_hit = SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false, false);
if (ss->gesture_initial_hit) {
copy_v3_v3(ss->gesture_initial_location, sgi.location);
copy_v3_v3(ss->gesture_initial_normal, sgi.normal);
@@ -1782,9 +1820,10 @@ static int sculpt_trim_gesture_lasso_invoke(bContext *C, wmOperator *op, const w
SculptCursorGeometryInfo sgi;
float mouse[2] = {event->mval[0], event->mval[1]};
SCULPT_vertex_random_access_ensure(ss);
ss->gesture_initial_hit = SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
ss->gesture_initial_hit = SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false, true);
if (ss->gesture_initial_hit) {
copy_v3_v3(ss->gesture_initial_location, sgi.location);
copy_v3_v3(ss->gesture_initial_back_location, sgi.back_location);
copy_v3_v3(ss->gesture_initial_normal, sgi.normal);
}

View File

@@ -2887,9 +2887,18 @@ typedef struct {
const float *ray_start;
const float *ray_normal;
bool hit;
int hit_count;
bool back_hit;
float depth;
bool original;
/* Depth of the second raycast hit. */
float back_depth;
/* When the back depth is not needed, this can be set to false to avoid traversing unnecesary
* nodes. */
bool use_back_depth;
int active_vertex_index;
float *face_normal;
@@ -7791,8 +7800,8 @@ void SCULPT_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *b
static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
{
if (BKE_pbvh_node_get_tmin(node) < *tmin) {
SculptRaycastData *srd = data_v;
SculptRaycastData *srd = data_v;
if (srd->use_back_depth || BKE_pbvh_node_get_tmin(node) < *tmin) {
float(*origco)[3] = NULL;
bool use_origco = false;
@@ -7815,13 +7824,19 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
srd->ray_start,
srd->ray_normal,
&srd->isect_precalc,
&srd->hit_count,
&srd->depth,
&srd->back_depth,
&srd->active_vertex_index,
&srd->active_face_grid_index,
srd->face_normal)) {
srd->hit = true;
*tmin = srd->depth;
}
if (srd->hit_count >= 2) {
srd->back_hit = true;
}
}
}
@@ -7901,7 +7916,8 @@ float SCULPT_raycast_init(ViewContext *vc,
bool SCULPT_cursor_geometry_info_update(bContext *C,
SculptCursorGeometryInfo *out,
const float mouse[2],
bool use_sampled_normal)
bool use_sampled_normal,
bool use_back_depth)
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
Scene *scene = CTX_data_scene(C);
@@ -7931,14 +7947,19 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
/* PBVH raycast to get active vertex and face normal. */
depth = SCULPT_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original);
SCULPT_stroke_modifiers_check(C, ob, brush);
float back_depth = depth;
SculptRaycastData srd = {
.original = original,
.ss = ob->sculpt,
.hit = false,
.back_hit = false,
.ray_start = ray_start,
.ray_normal = ray_normal,
.depth = depth,
.back_depth = back_depth,
.hit_count = 0,
.use_back_depth = use_back_depth,
.face_normal = face_normal,
};
isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
@@ -7976,6 +7997,17 @@ bool SCULPT_cursor_geometry_info_update(bContext *C,
mul_v3_fl(out->location, srd.depth);
add_v3_v3(out->location, ray_start);
if (use_back_depth) {
copy_v3_v3(out->back_location, ray_normal);
if (srd.back_hit) {
mul_v3_fl(out->back_location, srd.back_depth);
}
else {
mul_v3_fl(out->back_location, srd.depth);
}
add_v3_v3(out->back_location, ray_start);
}
/* Option to return the face normal directly for performance o accuracy reasons. */
if (!use_sampled_normal) {
copy_v3_v3(out->normal, srd.face_normal);
@@ -9814,7 +9846,7 @@ static int sculpt_mask_by_color_invoke(bContext *C, wmOperator *op, const wmEven
float mouse[2];
mouse[0] = event->mval[0];
mouse[1] = event->mval[1];
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false, false);
SCULPT_undo_push_begin(ob, "Mask by color");

View File

@@ -1657,7 +1657,7 @@ static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent
SculptCursorGeometryInfo sgi;
mouse[0] = event->mval[0];
mouse[1] = event->mval[1];
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false, false);
SCULPT_vertex_random_access_ensure(ss);

View File

@@ -180,7 +180,7 @@ static void sample_detail_voxel(bContext *C, ViewContext *vc, int mx, int my)
/* Update the active vertex. */
const float mouse[2] = {mx, my};
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false, false);
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, false, false);
/* Average the edge length of the connected edges to the active vertex. */

View File

@@ -1137,7 +1137,7 @@ static int sculpt_expand_target_vertex_update_and_get(bContext *C,
{
SculptSession *ss = ob->sculpt;
SculptCursorGeometryInfo sgi;
if (SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false)) {
if (SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false, false)) {
return SCULPT_active_vertex_get(ss);
}
else {

View File

@@ -111,7 +111,7 @@ int ED_sculpt_face_sets_active_update_and_get(bContext *C, Object *ob, const flo
}
SculptCursorGeometryInfo gi;
if (!SCULPT_cursor_geometry_info_update(C, &gi, mval, false)) {
if (!SCULPT_cursor_geometry_info_update(C, &gi, mval, false, false)) {
return SCULPT_FACE_SET_NONE;
}
@@ -963,7 +963,7 @@ static int sculpt_face_sets_change_visibility_invoke(bContext *C,
mouse[0] = event->mval[0];
mouse[1] = event->mval[1];
SCULPT_vertex_random_access_ensure(ss);
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false, false);
return sculpt_face_sets_change_visibility_exec(C, op);
}
@@ -1668,10 +1668,12 @@ static int sculpt_face_set_edit_invoke(bContext *C, wmOperator *op, const wmEven
* tool without brush cursor. */
SculptCursorGeometryInfo sgi;
const float mouse[2] = {event->mval[0], event->mval[1]};
if (!SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false)) {
if (!SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false, false)) {
/* The cursor is not over the mesh. Cancel to avoid editing the last updated Face Set ID. */
return OPERATOR_CANCELLED;
}
const int active_face_set = SCULPT_active_face_set_get(ss);
switch (mode) {

View File

@@ -275,7 +275,7 @@ static int sculpt_color_filter_invoke(bContext *C, wmOperator *op, const wmEvent
SculptCursorGeometryInfo sgi;
mouse[0] = event->mval[0];
mouse[1] = event->mval[1];
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false, false);
}
/* Disable for multires and dyntopo for now */

View File

@@ -745,7 +745,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
SculptCursorGeometryInfo sgi;
mouse[0] = event->mval[0];
mouse[1] = event->mval[1];
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false, false);
}
SCULPT_vertex_random_access_ensure(ss);

View File

@@ -197,7 +197,7 @@ static void sculpt_gradient_context_init_common(bContext *C,
/* Depth */
SculptCursorGeometryInfo sgi;
float mouse[2] = {event->mval[0], event->mval[1]};
const bool hit = SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
const bool hit = SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false, false);
if (hit) {
copy_v3_v3(gcontext->depth_point, sgi.location);
}

View File

@@ -74,6 +74,7 @@ void SCULPT_tag_update_overlays(bContext *C);
typedef struct SculptCursorGeometryInfo {
float location[3];
float back_location[3];
float normal[3];
float active_vertex_co[3];
} SculptCursorGeometryInfo;
@@ -82,7 +83,8 @@ bool SCULPT_stroke_get_location(struct bContext *C, float out[3], const float mo
bool SCULPT_cursor_geometry_info_update(bContext *C,
SculptCursorGeometryInfo *out,
const float mouse[2],
bool use_sampled_normal);
bool use_sampled_normal,
bool use_back_depth);
void SCULPT_geometry_preview_lines_update(bContext *C, struct SculptSession *ss, float radius);
void SCULPT_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *brush);

View File

@@ -188,7 +188,7 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent *
float mouse[2];
mouse[0] = event->mval[0];
mouse[1] = event->mval[1];
if (SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false)) {
if (SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false, false)) {
/* The cursor is over the mesh, get the update iteration from the updated active vertex. */
mask_expand_update_it = ss->filter_cache->mask_update_it[(int)SCULPT_active_vertex_get(ss)];
}
@@ -368,7 +368,7 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent
op->customdata = MEM_mallocN(sizeof(float[2]), "initial mouse position");
copy_v2_v2(op->customdata, mouse);
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false, false);
BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true, false);