Sculpt-dev: Roll brush tests.
Wrote test code for a "roll" texture mapping mode. This is purely a development test, there is no user-visible functionality here.
This commit is contained in:
parent
7e969000a2
commit
d6d1ddbf0b
|
@ -2307,6 +2307,13 @@ float BKE_brush_sample_tex_3d(const Scene *scene,
|
|||
|
||||
invradius = 1.0f / ups->pixel_radius;
|
||||
}
|
||||
else if (mtex->brush_map_mode == MTEX_MAP_MODE_ROLL) {
|
||||
// XXX implement me
|
||||
x = point_2d[0] - ups->tex_mouse[0];
|
||||
y = point_2d[1] - ups->tex_mouse[1];
|
||||
|
||||
invradius = 1.0f / ups->pixel_radius;
|
||||
}
|
||||
|
||||
x *= invradius;
|
||||
y *= invradius;
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
#include "BKE_paint.h"
|
||||
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_compiler_compat.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_rect.h"
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
|
@ -87,8 +87,16 @@ typedef struct PaintStroke {
|
|||
|
||||
float last_mouse_position[2];
|
||||
float last_world_space_position[3];
|
||||
|
||||
float mouse_cubic[4][2];
|
||||
float world_cubic[4][3];
|
||||
|
||||
bool has_cubic_stroke;
|
||||
|
||||
bool stroke_over_mesh;
|
||||
|
||||
/* space distance covered so far */
|
||||
int stroke_sample_index;
|
||||
float stroke_distance;
|
||||
float stroke_distance_t; // divided by brush radius
|
||||
|
||||
|
@ -109,6 +117,8 @@ typedef struct PaintStroke {
|
|||
float cached_size_pressure;
|
||||
/* last pressure will store last pressure value for use in interpolation for space strokes */
|
||||
float last_pressure;
|
||||
float last_pressure2;
|
||||
|
||||
int stroke_mode;
|
||||
|
||||
float last_tablet_event_pressure;
|
||||
|
@ -608,6 +618,8 @@ void paint_delete_blur_kernel(BlurKernel *);
|
|||
/* paint curve defines */
|
||||
#define PAINT_CURVE_NUM_SEGMENTS 40
|
||||
|
||||
bool paint_stroke_has_cubic(const PaintStroke *stroke);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -166,8 +166,9 @@ static bool paint_stroke_use_scene_spacing(ToolSettings *ts, Brush *brush, ePain
|
|||
{
|
||||
switch (mode) {
|
||||
case PAINT_MODE_SCULPT:
|
||||
return BRUSHSET_GET_FINAL_BOOL(brush->channels, ts->sculpt->channels, use_scene_spacing, NULL);
|
||||
//return brush->flag & BRUSH_SCENE_SPACING;
|
||||
return BRUSHSET_GET_FINAL_BOOL(
|
||||
brush->channels, ts->sculpt->channels, use_scene_spacing, NULL);
|
||||
// return brush->flag & BRUSH_SCENE_SPACING;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -460,7 +461,7 @@ static bool paint_stroke_use_jitter(ePaintMode mode, Brush *brush, bool invert)
|
|||
}
|
||||
|
||||
/* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */
|
||||
static void paint_brush_stroke_add_step(
|
||||
ATTR_NO_OPT static void paint_brush_stroke_add_step(
|
||||
bContext *C, wmOperator *op, PaintStroke *stroke, const float mouse_in[2], float pressure)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
@ -472,6 +473,8 @@ static void paint_brush_stroke_add_step(
|
|||
PointerRNA itemptr;
|
||||
float location[3];
|
||||
|
||||
stroke->stroke_sample_index++;
|
||||
|
||||
/* the following code is adapted from texture paint. It may not be needed but leaving here
|
||||
* just in case for reference (code in texpaint removed as part of refactoring).
|
||||
* It's strange that only texpaint had these guards. */
|
||||
|
@ -502,6 +505,7 @@ static void paint_brush_stroke_add_step(
|
|||
/* copy last position -before- jittering, or space fill code
|
||||
* will create too many dabs */
|
||||
copy_v2_v2(stroke->last_mouse_position, mouse_in);
|
||||
stroke->last_pressure2 = stroke->last_pressure;
|
||||
stroke->last_pressure = pressure;
|
||||
|
||||
if (paint_stroke_use_scene_spacing(scene->toolsettings, brush, mode)) {
|
||||
|
@ -566,6 +570,10 @@ static void paint_brush_stroke_add_step(
|
|||
RNA_float_set(&itemptr, "x_tilt", stroke->x_tilt);
|
||||
RNA_float_set(&itemptr, "y_tilt", stroke->y_tilt);
|
||||
|
||||
if (stroke->has_cubic_stroke) {
|
||||
RNA_float_set_array(&itemptr, "mouse_cubic", (float *)stroke->mouse_cubic);
|
||||
}
|
||||
|
||||
stroke->update_step(C, op, stroke, &itemptr);
|
||||
|
||||
/* don't record this for now, it takes up a lot of memory when doing long
|
||||
|
@ -656,7 +664,7 @@ static float paint_space_stroke_spacing(bContext *C,
|
|||
}
|
||||
|
||||
/* apply spacing pressure */
|
||||
//mapping.pressure = 1.5f - spacing_pressure;
|
||||
// mapping.pressure = 1.5f - spacing_pressure;
|
||||
mapping.pressure = spacing_pressure;
|
||||
|
||||
if (ss->cache && ss->cache->channels_final) {
|
||||
|
@ -830,11 +838,11 @@ static float paint_space_stroke_spacing_variable(bContext *C,
|
|||
|
||||
/* For brushes with stroke spacing enabled, moves mouse in steps
|
||||
* towards the final mouse location. */
|
||||
static int paint_space_stroke(bContext *C,
|
||||
wmOperator *op,
|
||||
PaintStroke *stroke,
|
||||
const float final_mouse[2],
|
||||
float final_pressure)
|
||||
ATTR_NO_OPT static int paint_space_stroke(bContext *C,
|
||||
wmOperator *op,
|
||||
PaintStroke *stroke,
|
||||
const float final_mouse[2],
|
||||
float final_pressure)
|
||||
{
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
|
@ -855,6 +863,11 @@ static int paint_space_stroke(bContext *C,
|
|||
sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
|
||||
float length = normalize_v2(dmouse);
|
||||
|
||||
/* normalize_v2 is giving inf on negative zero*/
|
||||
if (isinf(length)) {
|
||||
length = 0.0f;
|
||||
}
|
||||
|
||||
if (use_scene_spacing) {
|
||||
float world_space_position[3];
|
||||
bool hit = SCULPT_stroke_get_location(C, world_space_position, final_mouse);
|
||||
|
@ -927,14 +940,14 @@ static int paint_space_stroke(bContext *C,
|
|||
|
||||
/**** Public API ****/
|
||||
|
||||
PaintStroke *paint_stroke_new(bContext *C,
|
||||
wmOperator *op,
|
||||
StrokeGetLocation get_location,
|
||||
StrokeTestStart test_start,
|
||||
StrokeUpdateStep update_step,
|
||||
StrokeRedraw redraw,
|
||||
StrokeDone done,
|
||||
int event_type)
|
||||
ATTR_NO_OPT PaintStroke *paint_stroke_new(bContext *C,
|
||||
wmOperator *op,
|
||||
StrokeGetLocation get_location,
|
||||
StrokeTestStart test_start,
|
||||
StrokeUpdateStep update_step,
|
||||
StrokeRedraw redraw,
|
||||
StrokeDone done,
|
||||
int event_type)
|
||||
{
|
||||
struct Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
PaintStroke *stroke = MEM_callocN(sizeof(PaintStroke), "PaintStroke");
|
||||
|
@ -959,6 +972,10 @@ PaintStroke *paint_stroke_new(bContext *C,
|
|||
get_imapaint_zoom(C, &zoomx, &zoomy);
|
||||
stroke->zoom_2d = max_ff(zoomx, zoomy);
|
||||
|
||||
stroke->has_cubic_stroke = ELEM(
|
||||
MTEX_MAP_MODE_ROLL, br->mtex.brush_map_mode, br->mask_mtex.brush_map_mode);
|
||||
stroke->stroke_sample_index = 0;
|
||||
|
||||
if (stroke->stroke_mode == BRUSH_STROKE_INVERT) {
|
||||
if (br->flag & BRUSH_CURVE) {
|
||||
RNA_enum_set(op->ptr, "mode", BRUSH_STROKE_NORMAL);
|
||||
|
@ -1184,12 +1201,21 @@ struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf)
|
|||
return keymap;
|
||||
}
|
||||
|
||||
bool paint_stroke_has_cubic(const PaintStroke *stroke)
|
||||
{
|
||||
return stroke->has_cubic_stroke;
|
||||
}
|
||||
|
||||
static void paint_stroke_add_sample(
|
||||
const Paint *paint, PaintStroke *stroke, float x, float y, float pressure)
|
||||
{
|
||||
PaintSample *sample = &stroke->samples[stroke->cur_sample];
|
||||
int max_samples = CLAMPIS(paint->num_input_samples, 1, PAINT_MAX_INPUT_SAMPLES);
|
||||
|
||||
if (stroke->has_cubic_stroke) {
|
||||
max_samples = max_ii(max_samples, 5);
|
||||
}
|
||||
|
||||
sample->mouse[0] = x;
|
||||
sample->mouse[1] = y;
|
||||
sample->pressure = pressure;
|
||||
|
@ -1238,7 +1264,8 @@ static void paint_line_strokes_spacing(bContext *C,
|
|||
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
|
||||
const bool use_scene_spacing = paint_stroke_use_scene_spacing(CTX_data_scene(C)->toolsettings, brush, mode);
|
||||
const bool use_scene_spacing = paint_stroke_use_scene_spacing(
|
||||
CTX_data_scene(C)->toolsettings, brush, mode);
|
||||
|
||||
float mouse[2], dmouse[2];
|
||||
float length;
|
||||
|
@ -1395,7 +1422,8 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
|
|||
stroke->last_pressure = 1.0;
|
||||
copy_v2_v2(stroke->last_mouse_position, data + 2 * j);
|
||||
|
||||
if (paint_stroke_use_scene_spacing(scene->toolsettings, br, BKE_paintmode_get_active_from_context(C))) {
|
||||
if (paint_stroke_use_scene_spacing(
|
||||
scene->toolsettings, br, BKE_paintmode_get_active_from_context(C))) {
|
||||
stroke->stroke_over_mesh = SCULPT_stroke_get_location(
|
||||
C, stroke->last_world_space_position, data + 2 * j);
|
||||
mul_m4_v3(stroke->vc.obact->obmat, stroke->last_world_space_position);
|
||||
|
@ -1405,6 +1433,11 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
|
|||
|
||||
if (stroke->stroke_started) {
|
||||
paint_brush_stroke_add_step(C, op, stroke, data + 2 * j, 1.0);
|
||||
|
||||
if (stroke->has_cubic_stroke) {
|
||||
paint_brush_stroke_add_step(C, op, stroke, data + 2 * j, 1.0);
|
||||
}
|
||||
|
||||
paint_line_strokes_spacing(
|
||||
C, op, stroke, spacing, &length_residue, data + 2 * j, data + 2 * (j + 1));
|
||||
}
|
||||
|
@ -1457,7 +1490,10 @@ static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2])
|
|||
}
|
||||
}
|
||||
|
||||
int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintStroke **stroke_p)
|
||||
ATTR_NO_OPT int paint_stroke_modal(bContext *C,
|
||||
wmOperator *op,
|
||||
const wmEvent *event,
|
||||
PaintStroke **stroke_p)
|
||||
{
|
||||
Paint *p = BKE_paint_get_active_from_context(C);
|
||||
ePaintMode mode = BKE_paintmode_get_active_from_context(C);
|
||||
|
@ -1491,12 +1527,59 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS
|
|||
paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure);
|
||||
paint_stroke_sample_average(stroke, &sample_average);
|
||||
|
||||
if (stroke->stroke_sample_index == 0) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure);
|
||||
}
|
||||
}
|
||||
|
||||
if (stroke->has_cubic_stroke) {
|
||||
float a[2], b[2], c[2], d[2];
|
||||
|
||||
int ia = (stroke->cur_sample - 3 + stroke->num_samples) % stroke->num_samples;
|
||||
int id = (stroke->cur_sample - 1 + stroke->num_samples) % stroke->num_samples;
|
||||
int ib = (stroke->cur_sample - 2 + stroke->num_samples) % stroke->num_samples;
|
||||
int ic = (stroke->cur_sample - 0 + stroke->num_samples) % stroke->num_samples;
|
||||
|
||||
copy_v2_v2(a, stroke->samples[ia].mouse);
|
||||
copy_v2_v2(b, stroke->samples[ib].mouse);
|
||||
copy_v2_v2(c, stroke->samples[ic].mouse);
|
||||
copy_v2_v2(d, stroke->samples[id].mouse);
|
||||
|
||||
float tmp[3];
|
||||
|
||||
sub_v2_v2v2(tmp, d, a);
|
||||
sub_v2_v2(b, a);
|
||||
negate_v2(b);
|
||||
interp_v2_v2v2(b, b, tmp, 0.5f);
|
||||
add_v2_v2(b, a);
|
||||
|
||||
sub_v2_v2v2(tmp, d, a);
|
||||
sub_v2_v2(c, d);
|
||||
interp_v2_v2v2(c, c, tmp, 0.5f);
|
||||
negate_v2(c);
|
||||
add_v2_v2(c, d);
|
||||
|
||||
copy_v2_v2(stroke->mouse_cubic[0], a);
|
||||
copy_v2_v2(stroke->mouse_cubic[1], b);
|
||||
copy_v2_v2(stroke->mouse_cubic[2], c);
|
||||
copy_v2_v2(stroke->mouse_cubic[3], d);
|
||||
|
||||
printf("\n");
|
||||
printf("a: %.2f: %.2f\n", a[0], a[1]);
|
||||
printf("b: %.2f: %.2f\n", b[0], b[1]);
|
||||
printf("c: %.2f: %.2f\n", c[0], c[1]);
|
||||
printf("d: %.2f: %.2f\n", d[0], d[1]);
|
||||
}
|
||||
|
||||
/* Tilt. */
|
||||
if (WM_event_is_tablet(event)) {
|
||||
stroke->x_tilt = event->tablet.x_tilt;
|
||||
stroke->y_tilt = event->tablet.y_tilt;
|
||||
}
|
||||
|
||||
stroke->stroke_sample_index++;
|
||||
|
||||
#ifdef WITH_INPUT_NDOF
|
||||
/* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously!
|
||||
* this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it
|
||||
|
@ -1651,7 +1734,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintS
|
|||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
int paint_stroke_exec(bContext *C, wmOperator *op, PaintStroke *stroke)
|
||||
ATTR_NO_OPT int paint_stroke_exec(bContext *C, wmOperator *op, PaintStroke *stroke)
|
||||
{
|
||||
/* only when executed for the first time */
|
||||
if (stroke->stroke_started == 0) {
|
||||
|
|
|
@ -3663,6 +3663,174 @@ void SCULPT_calc_area_normal_and_center(
|
|||
|
||||
/** \} */
|
||||
|
||||
/*
|
||||
|
||||
off period;
|
||||
|
||||
procedure bez(a, b);
|
||||
a + (b - a) * t;
|
||||
|
||||
lin := bez(k1, k2);
|
||||
quad := bez(lin, sub(k2=k3, k1=k2, lin));
|
||||
|
||||
cubic := bez(quad, sub(k3=k4, k2=k3, k1=k2, quad));
|
||||
dcubic := df(cubic, t);
|
||||
icubic := int(cubic, t);
|
||||
|
||||
dx := sub(k1=x1, k2=x2, k3=x3, k4=x4, dcubic);
|
||||
dy := sub(k1=y1, k2=y2, k3=y3, k4=y4, dcubic);
|
||||
dz := sub(k1=z1, k2=z2, k3=z3, k4=z4, dcubic);
|
||||
darc := sqrt(dx**2 + dy**2 + dz**2);
|
||||
|
||||
arcstep := darc*dt + 0.5*df(darc, t)*dt*dt;
|
||||
|
||||
gentran
|
||||
begin
|
||||
declare <<
|
||||
x1,x2,x3,x4 : float;
|
||||
y1,y2,y3,y4 : float;
|
||||
z1,z2,z3,z4 : float;
|
||||
dt,t : float;
|
||||
>>;
|
||||
return eval(dcubic)
|
||||
end;
|
||||
|
||||
on fort;
|
||||
cubic;
|
||||
dcubic;
|
||||
icubic;
|
||||
arcstep;
|
||||
off fort;
|
||||
|
||||
*/
|
||||
|
||||
ATTR_NO_OPT float dcubic(float k1, float k2, float k3, float k4, float t)
|
||||
{
|
||||
return -3.0f * ((t - 1.0f) * (t - 1.0f) * k1 - k4 * t * t + (3.0f * t - 2.0f) * k3 * t -
|
||||
(3.0f * t - 1.0f) * (t - 1.0f) * k2);
|
||||
}
|
||||
|
||||
ATTR_NO_OPT float cubic_arclen(const float control[4][3])
|
||||
{
|
||||
const int steps = 2048;
|
||||
float t = 0.0f, dt = 1.0f / (float)steps;
|
||||
float arc = 0.0f;
|
||||
|
||||
for (int i = 0; i < steps; i++, t += dt) {
|
||||
float dx = dcubic(control[0][0], control[1][0], control[2][0], control[3][0], t);
|
||||
float dy = dcubic(control[0][1], control[1][1], control[2][1], control[3][1], t);
|
||||
float dz = dcubic(control[0][2], control[1][2], control[2][2], control[3][2], t);
|
||||
|
||||
arc += sqrtf(dx * dx + dy * dy + dz * dz);
|
||||
}
|
||||
|
||||
return arc;
|
||||
}
|
||||
/* Evaluate bezier position and tangent at a specific parameter value
|
||||
* using the De Casteljau algorithm. */
|
||||
ATTR_NO_OPT static void evaluate_cubic_bezier(const float control[4][3],
|
||||
float t,
|
||||
float r_pos[3],
|
||||
float r_tangent[3])
|
||||
{
|
||||
float layer1[3][3];
|
||||
interp_v3_v3v3(layer1[0], control[0], control[1], t);
|
||||
interp_v3_v3v3(layer1[1], control[1], control[2], t);
|
||||
interp_v3_v3v3(layer1[2], control[2], control[3], t);
|
||||
|
||||
float layer2[2][3];
|
||||
interp_v3_v3v3(layer2[0], layer1[0], layer1[1], t);
|
||||
interp_v3_v3v3(layer2[1], layer1[1], layer1[2], t);
|
||||
|
||||
sub_v3_v3v3(r_tangent, layer2[1], layer2[0]);
|
||||
madd_v3_v3v3fl(r_pos, layer2[0], r_tangent, t);
|
||||
|
||||
r_tangent[0] = dcubic(control[0][0], control[1][0], control[2][0], control[3][0], t);
|
||||
r_tangent[1] = dcubic(control[0][1], control[1][1], control[2][1], control[3][1], t);
|
||||
r_tangent[2] = dcubic(control[0][2], control[1][2], control[2][2], control[3][2], t);
|
||||
}
|
||||
|
||||
ATTR_NO_OPT static float cubic_uv_test(const float co[3], const float p[3], const float tan[3])
|
||||
{
|
||||
float tmp[3];
|
||||
|
||||
sub_v3_v3v3(tmp, co, p);
|
||||
return dot_v3v3(tmp, tan);
|
||||
}
|
||||
|
||||
ATTR_NO_OPT static void calc_cubic_uv_v3(const float cubic[4][3],
|
||||
const float co[3],
|
||||
float r_out[2])
|
||||
{
|
||||
const int steps = 5;
|
||||
const int binary_steps = 5;
|
||||
float dt = 1.0f / (float)steps, t = dt;
|
||||
|
||||
float lastp[3];
|
||||
float p[3];
|
||||
float tan[3];
|
||||
float lasttan[3];
|
||||
|
||||
evaluate_cubic_bezier(cubic, 0.0f, p, tan);
|
||||
|
||||
float mindis = len_v3v3(co, cubic[0]);
|
||||
float dis = len_v3v3(co, cubic[3]);
|
||||
|
||||
if (dis < mindis) {
|
||||
mindis = dis;
|
||||
r_out[0] = 1.0f;
|
||||
r_out[1] = mindis;
|
||||
}
|
||||
else {
|
||||
r_out[0] = 0.0f;
|
||||
r_out[1] = mindis;
|
||||
}
|
||||
|
||||
for (int i = 0; i < steps; i++, t += dt) {
|
||||
copy_v3_v3(lastp, p);
|
||||
copy_v3_v3(lasttan, tan);
|
||||
|
||||
evaluate_cubic_bezier(cubic, t, p, tan);
|
||||
|
||||
float f1 = cubic_uv_test(co, lastp, lasttan);
|
||||
float f2 = cubic_uv_test(co, p, tan);
|
||||
|
||||
if ((f1 < 0.0f) == (f2 < 0.0f)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float midp[3], midtan[3];
|
||||
|
||||
float start = t - dt;
|
||||
float end = t;
|
||||
float mid;
|
||||
|
||||
for (int j = 0; j < binary_steps; j++) {
|
||||
mid = (start + end) * 0.5f;
|
||||
|
||||
evaluate_cubic_bezier(cubic, mid, midp, midtan);
|
||||
float fmid = cubic_uv_test(co, midp, midtan);
|
||||
|
||||
if ((fmid < 0.0f) == (f1 < 0.0f)) {
|
||||
start = mid;
|
||||
f1 = fmid;
|
||||
}
|
||||
else {
|
||||
end = mid;
|
||||
f2 = fmid;
|
||||
}
|
||||
}
|
||||
|
||||
dis = len_v3v3(midp, co);
|
||||
if (dis < mindis) {
|
||||
mindis = dis;
|
||||
|
||||
r_out[0] = mid;
|
||||
r_out[1] = dis;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Generic Brush Utilities
|
||||
* \{ */
|
||||
|
@ -3850,15 +4018,15 @@ static float brush_strength(const Sculpt *sd,
|
|||
}
|
||||
}
|
||||
|
||||
float SCULPT_brush_strength_factor(SculptSession *ss,
|
||||
const Brush *br,
|
||||
const float brush_point[3],
|
||||
const float len,
|
||||
const float vno[3],
|
||||
const float fno[3],
|
||||
const float mask,
|
||||
const SculptVertRef vertex_index,
|
||||
const int thread_id)
|
||||
ATTR_NO_OPT float SCULPT_brush_strength_factor(SculptSession *ss,
|
||||
const Brush *br,
|
||||
const float brush_point[3],
|
||||
const float len,
|
||||
const float vno[3],
|
||||
const float fno[3],
|
||||
const float mask,
|
||||
const SculptVertRef vertex_index,
|
||||
const int thread_id)
|
||||
{
|
||||
StrokeCache *cache = ss->cache;
|
||||
const Scene *scene = cache->vc->scene;
|
||||
|
@ -3913,6 +4081,26 @@ float SCULPT_brush_strength_factor(SculptSession *ss,
|
|||
|
||||
avg += br->texture_sample_bias;
|
||||
}
|
||||
else if (mtex->brush_map_mode == MTEX_MAP_MODE_ROLL) {
|
||||
float point_3d[3];
|
||||
point_3d[2] = 0.0f;
|
||||
|
||||
calc_cubic_uv_v3(ss->cache->world_cubic, SCULPT_vertex_co_get(ss, vertex_index), point_3d);
|
||||
|
||||
if (point_3d[0] == 0.0f || point_3d[0] == 1.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
point_3d[1] /= ss->cache->radius;
|
||||
|
||||
//point_3d[0] = ss->cache->input_mapping.stroke_t + point_3d[0] * ss->cache->world_cubic_arclength;
|
||||
point_3d[0] -= floorf(point_3d[0]);
|
||||
|
||||
float color[4] = {point_3d[0], point_3d[1], 0.0f, 1.0f};
|
||||
SCULPT_vertex_color_set(ss, vertex_index, color);
|
||||
|
||||
avg = BKE_brush_sample_tex_3d(scene, br, point_3d, rgba, 0, ss->tex_pool);
|
||||
}
|
||||
else {
|
||||
const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f};
|
||||
avg = BKE_brush_sample_tex_3d(scene, br, point_3d, rgba, 0, ss->tex_pool);
|
||||
|
@ -6937,7 +7125,10 @@ static float sculpt_update_speed_average(SculptSession *ss, float speed)
|
|||
return speed / (float)tot;
|
||||
}
|
||||
/* Initialize the stroke cache variants from operator properties. */
|
||||
static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, PointerRNA *ptr)
|
||||
ATTR_NO_OPT static void sculpt_update_cache_variants(bContext *C,
|
||||
Sculpt *sd,
|
||||
Object *ob,
|
||||
PointerRNA *ptr)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
|
||||
|
@ -7082,6 +7273,36 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, Po
|
|||
|
||||
cache->input_mapping.stroke_t = cache->stroke_distance_t /
|
||||
10.0f; /*scale to a more user-friendly value*/
|
||||
|
||||
if (cache->has_cubic) {
|
||||
RNA_float_get_array(ptr, "mouse_cubic", (float *)cache->mouse_cubic);
|
||||
|
||||
printf("\n");
|
||||
|
||||
/* Project mouse cubic into 3d space. */
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!SCULPT_stroke_get_location(C, cache->world_cubic[i], cache->mouse_cubic[i])) {
|
||||
float loc[3];
|
||||
|
||||
mul_v3_m4v3(loc, ob->obmat, cache->true_location);
|
||||
|
||||
ED_view3d_win_to_3d(CTX_wm_view3d(C),
|
||||
CTX_wm_region(C),
|
||||
cache->true_location,
|
||||
cache->mouse_cubic[i],
|
||||
cache->world_cubic[i]);
|
||||
}
|
||||
|
||||
#if 1
|
||||
printf("%.2f, %.2f %.2f\n",
|
||||
cache->world_cubic[i][0],
|
||||
cache->world_cubic[i][1],
|
||||
cache->world_cubic[i][2]);
|
||||
#endif
|
||||
}
|
||||
|
||||
cache->world_cubic_arclength = cubic_arclen(cache->world_cubic);
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns true if any of the smoothing modes are active (currently
|
||||
|
@ -7876,10 +8097,10 @@ static void sculpt_cache_dyntopo_settings(BrushChannelSet *chset,
|
|||
r_settings->constant_detail = BRUSHSET_GET_FLOAT(chset, dyntopo_constant_detail, input_data);
|
||||
};
|
||||
|
||||
static void sculpt_stroke_update_step(bContext *C,
|
||||
wmOperator *UNUSED(op),
|
||||
struct PaintStroke *stroke,
|
||||
PointerRNA *itemptr)
|
||||
ATTR_NO_OPT static void sculpt_stroke_update_step(bContext *C,
|
||||
wmOperator *UNUSED(op),
|
||||
struct PaintStroke *stroke,
|
||||
PointerRNA *itemptr)
|
||||
|
||||
{
|
||||
|
||||
|
@ -7892,6 +8113,8 @@ static void sculpt_stroke_update_step(bContext *C,
|
|||
SculptSession *ss = ob->sculpt;
|
||||
Brush *brush = BKE_paint_brush(&sd->paint);
|
||||
|
||||
ss->cache->has_cubic = paint_stroke_has_cubic(stroke);
|
||||
|
||||
if (ss->cache->channels_final) {
|
||||
BKE_brush_channelset_free(ss->cache->channels_final);
|
||||
}
|
||||
|
|
|
@ -714,6 +714,11 @@ typedef struct StrokeCache {
|
|||
// if nonzero, override brush sculpt tool
|
||||
int tool_override;
|
||||
BrushChannelSet *tool_override_channels;
|
||||
|
||||
float mouse_cubic[4][2];
|
||||
float world_cubic[4][3];
|
||||
float world_cubic_arclength;
|
||||
bool has_cubic;
|
||||
} StrokeCache;
|
||||
|
||||
/* Sculpt Filters */
|
||||
|
|
|
@ -438,6 +438,7 @@ typedef struct ColorMapping {
|
|||
#define MTEX_MAP_MODE_AREA 3
|
||||
#define MTEX_MAP_MODE_RANDOM 4
|
||||
#define MTEX_MAP_MODE_STENCIL 5
|
||||
#define MTEX_MAP_MODE_ROLL 6
|
||||
|
||||
/* brush_angle_mode */
|
||||
#define MTEX_ANGLE_RANDOM 1
|
||||
|
|
|
@ -73,6 +73,7 @@ static const EnumPropertyItem rna_enum_brush_texture_slot_map_all_mode_items[] =
|
|||
{MTEX_MAP_MODE_3D, "3D", 0, "3D", ""},
|
||||
{MTEX_MAP_MODE_RANDOM, "RANDOM", 0, "Random", ""},
|
||||
{MTEX_MAP_MODE_STENCIL, "STENCIL", 0, "Stencil", ""},
|
||||
//{MTEX_MAP_MODE_ROLL, "ROLL", 0, "Roll", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
|
@ -4097,6 +4098,16 @@ static void rna_def_operator_stroke_element(BlenderRNA *brna)
|
|||
|
||||
/* XXX: i don't think blender currently supports the ability to properly do a remappable modifier
|
||||
* in the middle of a stroke */
|
||||
|
||||
prop = RNA_def_property(srna, "mouse_cubic", PROP_FLOAT, PROP_COORDS);
|
||||
RNA_def_property_flag(prop, PROP_IDPROPERTY);
|
||||
RNA_def_property_array(prop, 8);
|
||||
RNA_def_property_ui_text(prop, "Mouse", "");
|
||||
|
||||
prop = RNA_def_property(srna, "world_cubic", PROP_FLOAT, PROP_COORDS);
|
||||
RNA_def_property_flag(prop, PROP_IDPROPERTY);
|
||||
RNA_def_property_array(prop, 12);
|
||||
RNA_def_property_ui_text(prop, "Mouse", "");
|
||||
}
|
||||
|
||||
void RNA_def_brush(BlenderRNA *brna)
|
||||
|
|
Loading…
Reference in New Issue