Merge branch 'blender-v2.83-release'
This commit is contained in:
commit
00674c12cc
|
@ -230,8 +230,7 @@ static bool paint_tool_require_location(Brush *brush, ePaintMode mode)
|
|||
SCULPT_TOOL_THUMB)) {
|
||||
return false;
|
||||
}
|
||||
else if (brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
|
||||
brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) {
|
||||
else if (SCULPT_is_cloth_deform_brush(brush)) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -156,9 +156,16 @@ const float *SCULPT_vertex_co_get(SculptSession *ss, int index)
|
|||
void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3])
|
||||
{
|
||||
switch (BKE_pbvh_type(ss->pbvh)) {
|
||||
case PBVH_FACES:
|
||||
normal_short_to_float_v3(no, ss->mvert[index].no);
|
||||
return;
|
||||
case PBVH_FACES: {
|
||||
if (ss->shapekey_active || ss->deform_modifiers_active) {
|
||||
const MVert *mverts = BKE_pbvh_get_verts(ss->pbvh);
|
||||
normal_short_to_float_v3(no, mverts[index].no);
|
||||
}
|
||||
else {
|
||||
normal_short_to_float_v3(no, ss->mvert[index].no);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PBVH_BMESH:
|
||||
copy_v3_v3(no, BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->no);
|
||||
break;
|
||||
|
@ -2084,9 +2091,13 @@ static float brush_strength(const Sculpt *sd,
|
|||
case SCULPT_TOOL_LAYER:
|
||||
return alpha * flip * pressure * overlap * feather;
|
||||
case SCULPT_TOOL_CLOTH:
|
||||
/* Expand is more sensible to strength as it keeps expanding the cloth when sculpting over
|
||||
* the same vertices. */
|
||||
if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_EXPAND) {
|
||||
if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB) {
|
||||
/* Grab deform uses the same falloff as a regular grab brush. */
|
||||
return root_alpha * feather;
|
||||
}
|
||||
else if (brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_EXPAND) {
|
||||
/* Expand is more sensible to strength as it keeps expanding the cloth when sculpting over
|
||||
* the same vertices. */
|
||||
return 0.1f * alpha * flip * pressure * overlap * feather;
|
||||
}
|
||||
else {
|
||||
|
@ -6208,6 +6219,34 @@ static float sculpt_brush_dynamic_size_get(Brush *brush, StrokeCache *cache, flo
|
|||
}
|
||||
}
|
||||
|
||||
/* In these brushes the grab delta is calculated always from the initial stroke location, which is
|
||||
* generally used to create grab deformations. */
|
||||
static bool sculpt_needs_delta_from_anchored_origin(Brush *brush)
|
||||
{
|
||||
return ELEM(brush->sculpt_tool,
|
||||
SCULPT_TOOL_GRAB,
|
||||
SCULPT_TOOL_POSE,
|
||||
SCULPT_TOOL_THUMB,
|
||||
SCULPT_TOOL_ELASTIC_DEFORM) ||
|
||||
SCULPT_is_cloth_deform_brush(brush);
|
||||
}
|
||||
|
||||
/* In these brushes the grab delta is calculated from the previous stroke location, which is used
|
||||
* to calculate to orientate the brush tip and deformation towards the stroke direction. */
|
||||
static bool sculpt_needs_delta_for_tip_orientation(Brush *brush)
|
||||
{
|
||||
if (brush->sculpt_tool == SCULPT_TOOL_CLOTH) {
|
||||
return !SCULPT_is_cloth_deform_brush(brush);
|
||||
}
|
||||
return ELEM(brush->sculpt_tool,
|
||||
SCULPT_TOOL_CLAY_STRIPS,
|
||||
SCULPT_TOOL_PINCH,
|
||||
SCULPT_TOOL_MULTIPLANE_SCRAPE,
|
||||
SCULPT_TOOL_CLAY_THUMB,
|
||||
SCULPT_TOOL_NUDGE,
|
||||
SCULPT_TOOL_SNAKE_HOOK);
|
||||
}
|
||||
|
||||
static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Brush *brush)
|
||||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
@ -6251,38 +6290,27 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
|
|||
|
||||
/* Compute delta to move verts by. */
|
||||
if (!cache->first_time) {
|
||||
switch (tool) {
|
||||
case SCULPT_TOOL_GRAB:
|
||||
case SCULPT_TOOL_POSE:
|
||||
case SCULPT_TOOL_THUMB:
|
||||
case SCULPT_TOOL_ELASTIC_DEFORM:
|
||||
sub_v3_v3v3(delta, grab_location, cache->old_grab_location);
|
||||
invert_m4_m4(imat, ob->obmat);
|
||||
mul_mat3_m4_v3(imat, delta);
|
||||
add_v3_v3(cache->grab_delta, delta);
|
||||
break;
|
||||
case SCULPT_TOOL_CLAY_STRIPS:
|
||||
case SCULPT_TOOL_PINCH:
|
||||
case SCULPT_TOOL_CLOTH:
|
||||
case SCULPT_TOOL_MULTIPLANE_SCRAPE:
|
||||
case SCULPT_TOOL_CLAY_THUMB:
|
||||
case SCULPT_TOOL_NUDGE:
|
||||
case SCULPT_TOOL_SNAKE_HOOK:
|
||||
if (brush->flag & BRUSH_ANCHORED) {
|
||||
float orig[3];
|
||||
mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location);
|
||||
sub_v3_v3v3(cache->grab_delta, grab_location, orig);
|
||||
}
|
||||
else {
|
||||
sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location);
|
||||
}
|
||||
invert_m4_m4(imat, ob->obmat);
|
||||
mul_mat3_m4_v3(imat, cache->grab_delta);
|
||||
break;
|
||||
default:
|
||||
/* Use for 'Brush.topology_rake_factor'. */
|
||||
if (sculpt_needs_delta_from_anchored_origin(brush)) {
|
||||
sub_v3_v3v3(delta, grab_location, cache->old_grab_location);
|
||||
invert_m4_m4(imat, ob->obmat);
|
||||
mul_mat3_m4_v3(imat, delta);
|
||||
add_v3_v3(cache->grab_delta, delta);
|
||||
}
|
||||
else if (sculpt_needs_delta_for_tip_orientation(brush)) {
|
||||
if (brush->flag & BRUSH_ANCHORED) {
|
||||
float orig[3];
|
||||
mul_v3_m4v3(orig, ob->obmat, cache->orig_grab_location);
|
||||
sub_v3_v3v3(cache->grab_delta, grab_location, orig);
|
||||
}
|
||||
else {
|
||||
sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location);
|
||||
break;
|
||||
}
|
||||
invert_m4_m4(imat, ob->obmat);
|
||||
mul_mat3_m4_v3(imat, cache->grab_delta);
|
||||
}
|
||||
else {
|
||||
/* Use for 'Brush.topology_rake_factor'. */
|
||||
sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -6303,18 +6331,14 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
|
|||
copy_v3_v3(cache->anchored_location, cache->true_location);
|
||||
}
|
||||
}
|
||||
else if (tool == SCULPT_TOOL_ELASTIC_DEFORM) {
|
||||
else if (tool == SCULPT_TOOL_ELASTIC_DEFORM || SCULPT_is_cloth_deform_brush(brush)) {
|
||||
copy_v3_v3(cache->anchored_location, cache->true_location);
|
||||
}
|
||||
else if (tool == SCULPT_TOOL_THUMB) {
|
||||
copy_v3_v3(cache->anchored_location, cache->orig_grab_location);
|
||||
}
|
||||
|
||||
if (ELEM(tool,
|
||||
SCULPT_TOOL_GRAB,
|
||||
SCULPT_TOOL_THUMB,
|
||||
SCULPT_TOOL_ELASTIC_DEFORM,
|
||||
SCULPT_TOOL_POSE)) {
|
||||
if (sculpt_needs_delta_from_anchored_origin(brush)) {
|
||||
/* Location stays the same for finding vertices in brush radius. */
|
||||
copy_v3_v3(cache->true_location, cache->orig_grab_location);
|
||||
|
||||
|
@ -6385,9 +6409,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
|
|||
|
||||
if (cache->first_time ||
|
||||
!((brush->flag & BRUSH_ANCHORED) || (brush->sculpt_tool == SCULPT_TOOL_SNAKE_HOOK) ||
|
||||
(brush->sculpt_tool == SCULPT_TOOL_ROTATE) ||
|
||||
(brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
|
||||
brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB))) {
|
||||
(brush->sculpt_tool == SCULPT_TOOL_ROTATE) || SCULPT_is_cloth_deform_brush(brush))) {
|
||||
RNA_float_get_array(ptr, "location", cache->true_location);
|
||||
}
|
||||
|
||||
|
|
|
@ -212,8 +212,9 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
|
|||
const float *grab_delta = data->grab_delta;
|
||||
float(*imat)[4] = data->mat;
|
||||
|
||||
const bool use_falloff_plane = brush->cloth_force_falloff_type ==
|
||||
BRUSH_CLOTH_FORCE_FALLOFF_PLANE;
|
||||
const bool use_falloff_plane = !SCULPT_is_cloth_deform_brush(brush) &&
|
||||
brush->cloth_force_falloff_type ==
|
||||
BRUSH_CLOTH_FORCE_FALLOFF_PLANE;
|
||||
|
||||
PBVHVertexIter vd;
|
||||
const float bstrength = ss->cache->bstrength;
|
||||
|
@ -246,14 +247,29 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
|
|||
gravity, ss->cache->gravity_direction, -ss->cache->radius * data->sd->gravity_factor);
|
||||
}
|
||||
|
||||
/* Original data for deform brushes. */
|
||||
SculptOrigVertData orig_data;
|
||||
if (SCULPT_is_cloth_deform_brush(brush)) {
|
||||
SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
|
||||
}
|
||||
|
||||
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
|
||||
{
|
||||
float force[3];
|
||||
const float sim_factor = cloth_brush_simulation_falloff_get(
|
||||
brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[vd.index]);
|
||||
|
||||
float current_vertex_location[3];
|
||||
if (SCULPT_is_cloth_deform_brush(brush)) {
|
||||
SCULPT_orig_vert_data_update(&orig_data, &vd);
|
||||
copy_v3_v3(current_vertex_location, orig_data.co);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(current_vertex_location, vd.co);
|
||||
}
|
||||
|
||||
/* When using the plane falloff mode the falloff is not constrained by the brush radius. */
|
||||
if (sculpt_brush_test_sq_fn(&test, vd.co) || use_falloff_plane) {
|
||||
if (sculpt_brush_test_sq_fn(&test, current_vertex_location) || use_falloff_plane) {
|
||||
|
||||
float dist = sqrtf(test.dist);
|
||||
|
||||
|
@ -264,7 +280,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
|
|||
const float fade = sim_factor * bstrength *
|
||||
SCULPT_brush_strength_factor(ss,
|
||||
brush,
|
||||
vd.co,
|
||||
current_vertex_location,
|
||||
dist,
|
||||
vd.no,
|
||||
vd.fno,
|
||||
|
@ -293,7 +309,10 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
|
|||
mul_v3_v3fl(force, offset, -fade);
|
||||
break;
|
||||
case BRUSH_CLOTH_DEFORM_GRAB:
|
||||
mul_v3_v3fl(force, grab_delta, fade);
|
||||
/* Grab writes the positions in the simulation directly without applying forces. */
|
||||
madd_v3_v3v3fl(
|
||||
cloth_sim->pos[vd.index], orig_data.co, ss->cache->grab_delta_symmetry, fade);
|
||||
zero_v3(force);
|
||||
break;
|
||||
case BRUSH_CLOTH_DEFORM_PINCH_POINT:
|
||||
if (use_falloff_plane) {
|
||||
|
|
|
@ -120,7 +120,7 @@ void SCULPT_vertex_neighbors_get(struct SculptSession *ss,
|
|||
SCULPT_vertex_neighbors_get(ss, v_index, false, &neighbor_iterator); \
|
||||
for (neighbor_iterator.i = 0; neighbor_iterator.i < neighbor_iterator.size; \
|
||||
neighbor_iterator.i++) { \
|
||||
neighbor_iterator.index = ni.neighbors[ni.i];
|
||||
neighbor_iterator.index = neighbor_iterator.neighbors[neighbor_iterator.i];
|
||||
|
||||
/* Iterate over neighboring and duplicate vertices (for PBVH_GRIDS). Duplicates come
|
||||
* first since they are nearest for floodfill. */
|
||||
|
@ -128,8 +128,8 @@ void SCULPT_vertex_neighbors_get(struct SculptSession *ss,
|
|||
SCULPT_vertex_neighbors_get(ss, v_index, true, &neighbor_iterator); \
|
||||
for (neighbor_iterator.i = neighbor_iterator.size - 1; neighbor_iterator.i >= 0; \
|
||||
neighbor_iterator.i--) { \
|
||||
neighbor_iterator.index = ni.neighbors[ni.i]; \
|
||||
neighbor_iterator.is_duplicate = (ni.i >= \
|
||||
neighbor_iterator.index = neighbor_iterator.neighbors[neighbor_iterator.i]; \
|
||||
neighbor_iterator.is_duplicate = (neighbor_iterator.i >= \
|
||||
neighbor_iterator.size - neighbor_iterator.num_duplicates);
|
||||
|
||||
#define SCULPT_VERTEX_NEIGHBORS_ITER_END(neighbor_iterator) \
|
||||
|
@ -333,6 +333,13 @@ void SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr,
|
|||
struct SculptSession *ss,
|
||||
const float outline_col[3],
|
||||
float outline_alpha);
|
||||
|
||||
BLI_INLINE bool SCULPT_is_cloth_deform_brush(const Brush *brush)
|
||||
{
|
||||
return brush->sculpt_tool == SCULPT_TOOL_CLOTH &&
|
||||
brush->cloth_deform_type == BRUSH_CLOTH_DEFORM_GRAB;
|
||||
}
|
||||
|
||||
/* Pose Brush. */
|
||||
void SCULPT_do_pose_brush(struct Sculpt *sd,
|
||||
struct Object *ob,
|
||||
|
|
|
@ -393,6 +393,10 @@ typedef struct PoseFloodFillData {
|
|||
|
||||
bool is_first_iteration;
|
||||
|
||||
/* In topology mode this stores the furthest point from the stroke origin for cases when a pose
|
||||
* origin based on the brush radius can't be set. */
|
||||
float fallback_floodfill_origin[3];
|
||||
|
||||
/* Fallback origin. If we can't find any face set to continue, use the position of all vertices
|
||||
* that have the current face set. */
|
||||
float fallback_origin[3];
|
||||
|
@ -403,12 +407,17 @@ static bool pose_topology_floodfill_cb(
|
|||
SculptSession *ss, int UNUSED(from_v), int to_v, bool is_duplicate, void *userdata)
|
||||
{
|
||||
PoseFloodFillData *data = userdata;
|
||||
const float *co = SCULPT_vertex_co_get(ss, to_v);
|
||||
|
||||
if (data->pose_factor) {
|
||||
data->pose_factor[to_v] = 1.0f;
|
||||
}
|
||||
|
||||
const float *co = SCULPT_vertex_co_get(ss, to_v);
|
||||
if (len_squared_v3v3(data->pose_initial_co, data->fallback_floodfill_origin) <
|
||||
len_squared_v3v3(data->pose_initial_co, co)) {
|
||||
copy_v3_v3(data->fallback_floodfill_origin, co);
|
||||
}
|
||||
|
||||
if (sculpt_pose_brush_is_vertex_inside_brush_radius(
|
||||
co, data->pose_initial_co, data->radius, data->symm)) {
|
||||
return true;
|
||||
|
@ -547,12 +556,16 @@ void SCULPT_pose_calc_pose_data(Sculpt *sd,
|
|||
};
|
||||
zero_v3(fdata.pose_origin);
|
||||
copy_v3_v3(fdata.pose_initial_co, initial_location);
|
||||
copy_v3_v3(fdata.fallback_floodfill_origin, initial_location);
|
||||
SCULPT_floodfill_execute(ss, &flood, pose_topology_floodfill_cb, &fdata);
|
||||
SCULPT_floodfill_free(&flood);
|
||||
|
||||
if (fdata.tot_co > 0) {
|
||||
mul_v3_fl(fdata.pose_origin, 1.0f / (float)fdata.tot_co);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(fdata.pose_origin, fdata.fallback_floodfill_origin);
|
||||
}
|
||||
|
||||
/* Offset the pose origin. */
|
||||
float pose_d[3];
|
||||
|
|
Loading…
Reference in New Issue