* Dyntopo now has its own brush spacing. This is a huge performance
boost for brushes with fine spacing, e.g. the clay brush.
This commit is contained in:
parent
0dc09668ce
commit
7bba304c57
|
@ -807,6 +807,8 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
|
|||
col.prop(sculpt, "use_smooth_shading")
|
||||
col.prop(sculpt, "use_flat_vcol_shading")
|
||||
|
||||
col.prop(sculpt, "dyntopo_spacing")
|
||||
|
||||
|
||||
class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel):
|
||||
bl_context = ".sculpt_mode" # dot on purpose (access from topbar)
|
||||
|
|
|
@ -2595,7 +2595,7 @@ void BKE_brush_get_dyntopo(Brush *brush, Sculpt *sd, DynTopoSettings *out)
|
|||
int inherit = out->inherit;
|
||||
|
||||
if (out->inherit & DYNTOPO_INHERIT_ALL) {
|
||||
inherit = 0x7FFF;
|
||||
inherit = 0x7FFFFFF;
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_INHERIT_MODE) {
|
||||
|
@ -2621,6 +2621,10 @@ void BKE_brush_get_dyntopo(Brush *brush, Sculpt *sd, DynTopoSettings *out)
|
|||
out->detail_percent = sd->detail_percent;
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_INHERIT_SPACING) {
|
||||
out->spacing = sd->dyntopo_spacing;
|
||||
}
|
||||
|
||||
if (inherit & DYNTOPO_INHERIT_CONSTANT_DETAIL) {
|
||||
out->constant_detail = sd->constant_detail;
|
||||
}
|
||||
|
|
|
@ -1913,6 +1913,11 @@ void BKE_sculpt_toolsettings_data_ensure(struct Scene *scene)
|
|||
if (!sd->detail_percent) {
|
||||
sd->detail_percent = 25;
|
||||
}
|
||||
|
||||
if (!sd->dyntopo_spacing) {
|
||||
sd->dyntopo_spacing = 25;
|
||||
}
|
||||
|
||||
if (sd->constant_detail == 0.0f) {
|
||||
sd->constant_detail = 3.0f;
|
||||
}
|
||||
|
|
|
@ -51,6 +51,10 @@ typedef struct CoNo {
|
|||
float no[3];
|
||||
} CoNo;
|
||||
|
||||
#include "ED_view3d.h"
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
/* paint_stroke.c */
|
||||
typedef bool (*StrokeGetLocation)(struct bContext *C, float location[3], const float mouse[2]);
|
||||
typedef bool (*StrokeTestStart)(struct bContext *C, struct wmOperator *op, const float mouse[2]);
|
||||
|
@ -60,6 +64,81 @@ typedef void (*StrokeUpdateStep)(struct bContext *C,
|
|||
typedef void (*StrokeRedraw)(const struct bContext *C, struct PaintStroke *stroke, bool final);
|
||||
typedef void (*StrokeDone)(const struct bContext *C, struct PaintStroke *stroke);
|
||||
|
||||
|
||||
typedef struct PaintSample {
|
||||
float mouse[2];
|
||||
float pressure;
|
||||
} PaintSample;
|
||||
|
||||
typedef struct PaintStroke {
|
||||
void *mode_data;
|
||||
void *stroke_cursor;
|
||||
struct wmTimer *timer;
|
||||
struct RNG *rng;
|
||||
|
||||
/* Cached values */
|
||||
struct ViewContext vc;
|
||||
struct Brush *brush;
|
||||
struct UnifiedPaintSettings *ups;
|
||||
|
||||
/* used for lines and curves */
|
||||
ListBase line;
|
||||
|
||||
/* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES prior inputs
|
||||
* to smooth the stroke */
|
||||
PaintSample samples[PAINT_MAX_INPUT_SAMPLES];
|
||||
int num_samples;
|
||||
int cur_sample;
|
||||
int tot_samples;
|
||||
|
||||
float last_mouse_position[2];
|
||||
float last_world_space_position[3];
|
||||
bool stroke_over_mesh;
|
||||
/* space distance covered so far */
|
||||
float stroke_distance;
|
||||
float stroke_distance_t; //divided by brush radius
|
||||
|
||||
/* Set whether any stroke step has yet occurred
|
||||
* e.g. in sculpt mode, stroke doesn't start until cursor
|
||||
* passes over the mesh */
|
||||
bool stroke_started;
|
||||
/* Set when enough motion was found for rake rotation */
|
||||
bool rake_started;
|
||||
/* event that started stroke, for modal() return */
|
||||
int event_type;
|
||||
/* check if stroke variables have been initialized */
|
||||
bool stroke_init;
|
||||
/* check if various brush mapping variables have been initialized */
|
||||
bool brush_init;
|
||||
float initial_mouse[2];
|
||||
/* cached_pressure stores initial pressure for size pressure influence mainly */
|
||||
float cached_size_pressure;
|
||||
/* last pressure will store last pressure value for use in interpolation for space strokes */
|
||||
float last_pressure;
|
||||
int stroke_mode;
|
||||
|
||||
float last_tablet_event_pressure;
|
||||
|
||||
float zoom_2d;
|
||||
int pen_flip;
|
||||
|
||||
/* Tilt, as read from the event. */
|
||||
float x_tilt;
|
||||
float y_tilt;
|
||||
|
||||
/* line constraint */
|
||||
bool constrain_line;
|
||||
float constrained_pos[2];
|
||||
|
||||
StrokeGetLocation get_location;
|
||||
StrokeTestStart test_start;
|
||||
StrokeUpdateStep update_step;
|
||||
StrokeRedraw redraw;
|
||||
StrokeDone done;
|
||||
|
||||
float spacing;
|
||||
} PaintStroke;
|
||||
|
||||
struct PaintStroke *paint_stroke_new(struct bContext *C,
|
||||
struct wmOperator *op,
|
||||
StrokeGetLocation get_location,
|
||||
|
|
|
@ -67,77 +67,6 @@
|
|||
# include "PIL_time_utildefines.h"
|
||||
#endif
|
||||
|
||||
typedef struct PaintSample {
|
||||
float mouse[2];
|
||||
float pressure;
|
||||
} PaintSample;
|
||||
|
||||
typedef struct PaintStroke {
|
||||
void *mode_data;
|
||||
void *stroke_cursor;
|
||||
wmTimer *timer;
|
||||
struct RNG *rng;
|
||||
|
||||
/* Cached values */
|
||||
ViewContext vc;
|
||||
Brush *brush;
|
||||
UnifiedPaintSettings *ups;
|
||||
|
||||
/* used for lines and curves */
|
||||
ListBase line;
|
||||
|
||||
/* Paint stroke can use up to PAINT_MAX_INPUT_SAMPLES prior inputs
|
||||
* to smooth the stroke */
|
||||
PaintSample samples[PAINT_MAX_INPUT_SAMPLES];
|
||||
int num_samples;
|
||||
int cur_sample;
|
||||
int tot_samples;
|
||||
|
||||
float last_mouse_position[2];
|
||||
float last_world_space_position[3];
|
||||
bool stroke_over_mesh;
|
||||
/* space distance covered so far */
|
||||
float stroke_distance;
|
||||
|
||||
/* Set whether any stroke step has yet occurred
|
||||
* e.g. in sculpt mode, stroke doesn't start until cursor
|
||||
* passes over the mesh */
|
||||
bool stroke_started;
|
||||
/* Set when enough motion was found for rake rotation */
|
||||
bool rake_started;
|
||||
/* event that started stroke, for modal() return */
|
||||
int event_type;
|
||||
/* check if stroke variables have been initialized */
|
||||
bool stroke_init;
|
||||
/* check if various brush mapping variables have been initialized */
|
||||
bool brush_init;
|
||||
float initial_mouse[2];
|
||||
/* cached_pressure stores initial pressure for size pressure influence mainly */
|
||||
float cached_size_pressure;
|
||||
/* last pressure will store last pressure value for use in interpolation for space strokes */
|
||||
float last_pressure;
|
||||
int stroke_mode;
|
||||
|
||||
float last_tablet_event_pressure;
|
||||
|
||||
float zoom_2d;
|
||||
int pen_flip;
|
||||
|
||||
/* Tilt, as read from the event. */
|
||||
float x_tilt;
|
||||
float y_tilt;
|
||||
|
||||
/* line constraint */
|
||||
bool constrain_line;
|
||||
float constrained_pos[2];
|
||||
|
||||
StrokeGetLocation get_location;
|
||||
StrokeTestStart test_start;
|
||||
StrokeUpdateStep update_step;
|
||||
StrokeRedraw redraw;
|
||||
StrokeDone done;
|
||||
} PaintStroke;
|
||||
|
||||
/*** Cursors ***/
|
||||
static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata)
|
||||
{
|
||||
|
@ -430,11 +359,13 @@ static bool paint_brush_update(bContext *C,
|
|||
ups->anchored_size /= 2.0f;
|
||||
ups->pixel_radius /= 2.0f;
|
||||
stroke->stroke_distance = ups->pixel_radius;
|
||||
stroke->stroke_distance_t = 1.0f;
|
||||
}
|
||||
else {
|
||||
copy_v2_v2(ups->anchored_initial_mouse, stroke->initial_mouse);
|
||||
copy_v2_v2(mouse, stroke->initial_mouse);
|
||||
stroke->stroke_distance = ups->pixel_radius;
|
||||
stroke->stroke_distance_t = 1.0f;
|
||||
}
|
||||
ups->pixel_radius /= stroke->zoom_2d;
|
||||
ups->draw_anchored = true;
|
||||
|
@ -868,6 +799,8 @@ static int paint_space_stroke(bContext *C,
|
|||
spacing / no_pressure_spacing);
|
||||
|
||||
stroke->stroke_distance += spacing / stroke->zoom_2d;
|
||||
stroke->stroke_distance_t += (spacing / stroke->zoom_2d) / stroke->ups->pixel_radius;
|
||||
|
||||
paint_brush_stroke_add_step(C, op, mouse, pressure);
|
||||
|
||||
length -= spacing;
|
||||
|
@ -1204,6 +1137,8 @@ static void paint_line_strokes_spacing(bContext *C,
|
|||
length += *length_residue;
|
||||
*length_residue = 0.0;
|
||||
|
||||
stroke->spacing = spacing;
|
||||
|
||||
if (length >= spacing) {
|
||||
mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing_final;
|
||||
mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing_final;
|
||||
|
@ -1211,6 +1146,8 @@ static void paint_line_strokes_spacing(bContext *C,
|
|||
ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush, 1.0);
|
||||
|
||||
stroke->stroke_distance += spacing / stroke->zoom_2d;
|
||||
stroke->stroke_distance_t += (spacing / stroke->zoom_2d) / stroke->ups->pixel_radius;
|
||||
|
||||
paint_brush_stroke_add_step(C, op, mouse, 1.0);
|
||||
|
||||
length -= spacing;
|
||||
|
@ -1426,6 +1363,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
/* one time stroke initialization */
|
||||
if (!stroke->stroke_started) {
|
||||
stroke->last_pressure = sample_average.pressure;
|
||||
|
||||
copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
|
||||
if (paint_stroke_use_scene_spacing(br, mode)) {
|
||||
stroke->stroke_over_mesh = SCULPT_stroke_get_location(
|
||||
|
@ -1512,6 +1450,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
|
|||
float dmouse[2];
|
||||
sub_v2_v2v2(dmouse, mouse, stroke->last_mouse_position);
|
||||
stroke->stroke_distance += len_v2(dmouse);
|
||||
stroke->stroke_distance_t += len_v2(dmouse) / stroke->ups->pixel_radius;
|
||||
|
||||
paint_brush_stroke_add_step(C, op, mouse, pressure);
|
||||
redraw = true;
|
||||
}
|
||||
|
|
|
@ -6204,6 +6204,16 @@ static void sculpt_topology_update(Sculpt *sd,
|
|||
{
|
||||
SculptSession *ss = ob->sculpt;
|
||||
|
||||
if (paint_space_stroke_enabled(brush, PAINT_MODE_SCULPT)) {
|
||||
float spacing = (float) brush->cached_dyntopo.spacing / 100.0f;
|
||||
|
||||
if (ss->cache->stroke_distance_t < ss->cache->last_dyntopo_t + spacing) {
|
||||
return;
|
||||
}
|
||||
|
||||
ss->cache->last_dyntopo_t = ss->cache->stroke_distance_t;
|
||||
}
|
||||
|
||||
int n, totnode;
|
||||
/* Build a list of all nodes that are potentially within the brush's area of influence. */
|
||||
const bool use_original = sculpt_tool_needs_original(brush->sculpt_tool) ? true :
|
||||
|
@ -8398,7 +8408,7 @@ static bool sculpt_stroke_test_start(bContext *C, struct wmOperator *op, const f
|
|||
}
|
||||
|
||||
static void sculpt_stroke_update_step(bContext *C,
|
||||
struct PaintStroke *UNUSED(stroke),
|
||||
struct PaintStroke *stroke,
|
||||
PointerRNA *itemptr)
|
||||
{
|
||||
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
|
||||
|
@ -8407,6 +8417,9 @@ static void sculpt_stroke_update_step(bContext *C,
|
|||
SculptSession *ss = ob->sculpt;
|
||||
const Brush *brush = BKE_paint_brush(&sd->paint);
|
||||
|
||||
ss->cache->stroke_distance = stroke->stroke_distance;
|
||||
ss->cache->stroke_distance_t = stroke->stroke_distance_t;
|
||||
|
||||
BKE_brush_get_dyntopo(brush, sd, &brush->cached_dyntopo);
|
||||
|
||||
SCULPT_stroke_modifiers_check(C, ob, brush);
|
||||
|
|
|
@ -1092,6 +1092,9 @@ typedef struct StrokeCache {
|
|||
rcti previous_r; /* previous redraw rectangle */
|
||||
rcti current_r; /* current redraw rectangle */
|
||||
|
||||
float stroke_distance; //copy of PaintStroke->stroke_distance
|
||||
float stroke_distance_t;
|
||||
float last_dyntopo_t;
|
||||
} StrokeCache;
|
||||
|
||||
/* Sculpt Filters */
|
||||
|
|
|
@ -111,7 +111,7 @@
|
|||
\
|
||||
.mtex = _DNA_DEFAULT_MTex, \
|
||||
.mask_mtex = _DNA_DEFAULT_MTex, \
|
||||
.dyntopo = {0.4f, 25.0f, 3.0f, DYNTOPO_COLLAPSE|DYNTOPO_SUBDIVIDE, DYNTOPO_DETAIL_RELATIVE, DYNTOPO_INHERIT_ALL}\
|
||||
.dyntopo = {0.4f, 25.0f, 3.0f, DYNTOPO_COLLAPSE|DYNTOPO_SUBDIVIDE, DYNTOPO_DETAIL_RELATIVE, DYNTOPO_INHERIT_ALL, 25}\
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -528,7 +528,6 @@ typedef enum eBrushUVSculptTool {
|
|||
SCULPT_TOOL_ELASTIC_DEFORM, \
|
||||
SCULPT_TOOL_ROTATE, \
|
||||
SCULPT_TOOL_THUMB, \
|
||||
SCULPT_TOOL_DRAW_SHARP, \
|
||||
SCULPT_TOOL_DISPLACEMENT_ERASER, \
|
||||
SCULPT_TOOL_SLIDE_RELAX, \
|
||||
SCULPT_TOOL_MASK) == 0)
|
||||
|
@ -633,7 +632,8 @@ enum {
|
|||
DYNTOPO_INHERIT_DETAIL_RANGE = 1<<11,
|
||||
DYNTOPO_INHERIT_DETAIL_PERCENT = 1<<12,
|
||||
DYNTOPO_INHERIT_MODE = 1<<13,
|
||||
DYNTOPO_INHERIT_CONSTANT_DETAIL = 1<<14
|
||||
DYNTOPO_INHERIT_CONSTANT_DETAIL = 1<<14,
|
||||
DYNTOPO_INHERIT_SPACING = 1<<15
|
||||
};
|
||||
|
||||
//dyntopo mode
|
||||
|
|
|
@ -155,7 +155,8 @@ typedef struct DynTopoSettings {
|
|||
float detail_percent;
|
||||
float constant_detail;
|
||||
short flag, mode;
|
||||
int inherit, _pad[1];
|
||||
int inherit;
|
||||
int spacing;
|
||||
} DynTopoSettings;
|
||||
|
||||
typedef struct Brush {
|
||||
|
|
|
@ -995,7 +995,7 @@ typedef struct Sculpt {
|
|||
/** Constant detail resolution (Blender unit / constant_detail). */
|
||||
float constant_detail;
|
||||
float detail_percent;
|
||||
int _pad[1];
|
||||
int dyntopo_spacing;
|
||||
|
||||
struct Object *gravity_object;
|
||||
} Sculpt;
|
||||
|
|
|
@ -1172,6 +1172,14 @@ static void rna_def_dyntopo_settings(BlenderRNA *brna) {
|
|||
"Dyntopo Settings",
|
||||
"");
|
||||
|
||||
prop = RNA_def_property(srna, "spacing", PROP_INT, PROP_PERCENTAGE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "spacing");
|
||||
RNA_def_property_range(prop, 1, 1000);
|
||||
RNA_def_property_ui_range(prop, 1, 500, 5, -1);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Spacing", "Spacing between DynTopo daubs as a percentage of brush diameter");
|
||||
RNA_def_property_update(prop, 0, "rna_Brush_update");
|
||||
|
||||
prop = RNA_def_property(srna, "subdivide", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", DYNTOPO_SUBDIVIDE);
|
||||
RNA_def_property_ui_icon(prop, ICON_NONE, 0);
|
||||
|
|
|
@ -803,6 +803,14 @@ static void rna_def_sculpt(BlenderRNA *brna)
|
|||
"Maximum edge length for dynamic topology sculpting (in brush percenage)");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "dyntopo_spacing", PROP_INT, PROP_PERCENTAGE);
|
||||
RNA_def_property_int_sdna(prop, NULL, "dyntopo_spacing");
|
||||
RNA_def_property_range(prop, 1, 1000);
|
||||
RNA_def_property_ui_range(prop, 1, 500, 5, -1);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "DynTopo Spacing", "Spacing between DynTopo daubs as a percentage of brush diameter");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "constant_detail_resolution", PROP_FLOAT, PROP_NONE);
|
||||
RNA_def_property_float_sdna(prop, NULL, "constant_detail");
|
||||
RNA_def_property_range(prop, 0.0001, FLT_MAX);
|
||||
|
|
Loading…
Reference in New Issue