Sculpt-dev: Clean up brush test code
* The standard sculpt brush spot test API now supports square brushes. * Supports tip scale x from paint brush. * TODO: rewrite clay strips and paint brushes to use standard api. * Roll texture mapping semi-works.
This commit is contained in:
parent
d6d1ddbf0b
commit
7217d1f355
|
@ -923,6 +923,9 @@ typedef struct SculptSession {
|
|||
* Last used painting canvas key.
|
||||
*/
|
||||
char *last_paint_canvas_key;
|
||||
|
||||
/* Used to derive initial tip rotation. */
|
||||
float last_grab_delta[3];
|
||||
} SculptSession;
|
||||
|
||||
void BKE_sculptsession_free(struct Object *ob);
|
||||
|
|
|
@ -2308,11 +2308,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];
|
||||
/* leave the coordinates relative to the screen */
|
||||
|
||||
invradius = 1.0f / ups->pixel_radius;
|
||||
/* use unadjusted size for tiled mode */
|
||||
invradius = 1.0f / BKE_brush_size_get(scene, br, false);
|
||||
|
||||
x = point_2d[0];
|
||||
y = point_2d[1];
|
||||
}
|
||||
|
||||
x *= invradius;
|
||||
|
|
|
@ -324,6 +324,8 @@ static bool check_builtin_init()
|
|||
// SETCAT(direction, "Basic");
|
||||
SETCAT(accumulate, "Basic");
|
||||
SETCAT(use_frontface, "Basic");
|
||||
SETCAT(tip_roundness, "Basic");
|
||||
SETCAT(tip_scale_x, "Basic");
|
||||
|
||||
SETCAT(smear_deform_type, "Smear");
|
||||
SETCAT(smear_deform_blend, "Smear");
|
||||
|
@ -435,6 +437,16 @@ static bool check_builtin_init()
|
|||
# undef ADDCH
|
||||
#endif
|
||||
|
||||
/* TODO: Destroy these macros.*/
|
||||
|
||||
#define ADDCH_EX(idname, category, visflag) \
|
||||
do { \
|
||||
BKE_brush_channelset_ensure_builtin(chset, BRUSH_BUILTIN_##idname); \
|
||||
BrushChannel *ch = BKE_brush_channelset_lookup(chset, BRUSH_BUILTIN_##idname); \
|
||||
SETCAT(idname, category); \
|
||||
ch->flag |= visflag; \
|
||||
} while (0);
|
||||
|
||||
/* TODO: replace these two macros with equivalent BRUSHSET_XXX ones */
|
||||
#define ADDCH(name) \
|
||||
(BKE_brush_channelset_ensure_builtin(chset, BRUSH_BUILTIN_##name), \
|
||||
|
@ -1266,6 +1278,19 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
|
|||
|
||||
ADDCH(deform_target);
|
||||
|
||||
/* Patch olds files. */
|
||||
if (!BRUSHSET_LOOKUP(chset, tip_scale_x)) {
|
||||
ADDCH_EX(tip_scale_x,
|
||||
"Basic",
|
||||
BRUSH_CHANNEL_SHOW_IN_WORKSPACE | BRUSH_CHANNEL_SHOW_IN_CONTEXT_MENU);
|
||||
ADDCH_EX(tip_roundness,
|
||||
"Basic",
|
||||
BRUSH_CHANNEL_SHOW_IN_WORKSPACE | BRUSH_CHANNEL_SHOW_IN_CONTEXT_MENU);
|
||||
|
||||
if (tool == SCULPT_TOOL_CLAY_STRIPS) {
|
||||
BRUSHSET_SET_FLOAT(chset, tip_roundness, 0.18f);
|
||||
}
|
||||
}
|
||||
/* stuff for deform_target cloth mode*/
|
||||
ADDCH(cloth_use_collision);
|
||||
ADDCH(cloth_solve_bending);
|
||||
|
@ -1306,8 +1331,6 @@ void BKE_brush_builtin_patch(Brush *brush, int tool)
|
|||
ADDCH(wet_paint_radius_factor);
|
||||
ADDCH(wet_persistence);
|
||||
ADDCH(density);
|
||||
ADDCH(tip_scale_x);
|
||||
ADDCH(tip_roundness);
|
||||
ADDCH(flow);
|
||||
ADDCH(rate);
|
||||
ADDCH(blend);
|
||||
|
@ -1489,6 +1512,11 @@ void BKE_brush_channelset_ui_init(Brush *brush, int tool)
|
|||
SHOWWRK(hardness);
|
||||
SHOWWRK(dyntopo_disabled);
|
||||
|
||||
SHOWWRK(tip_roundness);
|
||||
SHOWCTX(tip_roundness);
|
||||
SHOWWRK(tip_scale_x);
|
||||
SHOWCTX(tip_scale_x);
|
||||
|
||||
switch (tool) {
|
||||
case SCULPT_TOOL_DRAW_SHARP:
|
||||
SHOWWRK(sharp_mode);
|
||||
|
@ -1555,7 +1583,6 @@ void BKE_brush_channelset_ui_init(Brush *brush, int tool)
|
|||
SHOWWRK(area_radius_factor);
|
||||
SHOW_WRK_CTX(plane_offset);
|
||||
SHOW_WRK_CTX(plane_trim);
|
||||
SHOWWRK(tip_roundness);
|
||||
SHOW_WRK_CTX(use_plane_trim);
|
||||
|
||||
SHOWWRK(use_smoothed_rake);
|
||||
|
@ -1568,7 +1595,6 @@ void BKE_brush_channelset_ui_init(Brush *brush, int tool)
|
|||
SHOWWRK(area_radius_factor);
|
||||
SHOWWRK(plane_offset);
|
||||
SHOWWRK(plane_trim);
|
||||
SHOWWRK(tip_roundness);
|
||||
SHOWWRK(use_plane_trim);
|
||||
|
||||
SHOWCTX(autosmooth);
|
||||
|
@ -1661,10 +1687,8 @@ void BKE_brush_channelset_ui_init(Brush *brush, int tool)
|
|||
SHOWWRK(wet_paint_radius_factor);
|
||||
SHOWWRK(wet_persistence);
|
||||
SHOWWRK(density);
|
||||
SHOWWRK(tip_scale_x);
|
||||
SHOWWRK(hardness);
|
||||
SHOWWRK(wet_mix);
|
||||
SHOWWRK(tip_roundness);
|
||||
SHOWWRK(flow);
|
||||
SHOWWRK(rate);
|
||||
SHOWALL(blend);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "BKE_attribute.h"
|
||||
#include "BKE_ccg.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_mesh.h" /* for BKE_mesh_calc_normals */
|
||||
#include "BKE_mesh_mapping.h"
|
||||
#include "BKE_object.h"
|
||||
|
@ -1543,7 +1544,8 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
|
|||
pbvh->face_sets_color_seed,
|
||||
pbvh->face_sets_color_default,
|
||||
update_flags,
|
||||
pbvh->vert_normals);
|
||||
pbvh->vert_normals,
|
||||
pbvh->mdyntopo_verts);
|
||||
} break;
|
||||
case PBVH_BMESH:
|
||||
if (BKE_pbvh_bmesh_check_tris(pbvh, node)) {
|
||||
|
@ -1644,7 +1646,8 @@ void pbvh_update_free_all_draw_buffers(PBVH *pbvh, PBVHNode *node)
|
|||
}
|
||||
}
|
||||
|
||||
static void pbvh_update_draw_buffers(PBVH *pbvh, Mesh *me, PBVHNode **nodes, int totnode, int update_flag)
|
||||
static void pbvh_update_draw_buffers(
|
||||
PBVH *pbvh, Mesh *me, PBVHNode **nodes, int totnode, int update_flag)
|
||||
{
|
||||
|
||||
CustomData *vdata;
|
||||
|
@ -2098,7 +2101,8 @@ void BKE_pbvh_node_mark_original_update(PBVHNode *node)
|
|||
void BKE_pbvh_node_mark_update(PBVHNode *node)
|
||||
{
|
||||
node->flag |= PBVH_UpdateNormals | PBVH_UpdateBB | PBVH_UpdateOriginalBB |
|
||||
PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw | PBVH_UpdateCurvatureDir | PBVH_RebuildPixels;
|
||||
PBVH_UpdateDrawBuffers | PBVH_UpdateRedraw | PBVH_UpdateCurvatureDir |
|
||||
PBVH_RebuildPixels | PBVH_UpdateTriAreas;
|
||||
}
|
||||
|
||||
void BKE_pbvh_node_mark_update_mask(PBVHNode *node)
|
||||
|
@ -2503,15 +2507,15 @@ bool ray_update_depth_and_hit_count(const float depth_test,
|
|||
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)
|
||||
bool 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) ||
|
||||
|
@ -4907,10 +4911,21 @@ void BKE_pbvh_clear_cache(PBVH *preserve)
|
|||
pbvh_clear_cached_pbvhs(NULL);
|
||||
}
|
||||
|
||||
#define PBVH_CACHE_KEY_SIZE 1024
|
||||
|
||||
static void pbvh_make_cached_key(Object *ob, char out[PBVH_CACHE_KEY_SIZE])
|
||||
{
|
||||
sprintf(out, "%s:%p", ob->id.name, G.main);
|
||||
}
|
||||
|
||||
void BKE_pbvh_invalidate_cache(Object *ob)
|
||||
{
|
||||
Object *ob_orig = DEG_get_original_object(ob);
|
||||
PBVH *pbvh = BLI_ghash_lookup(cached_pbvhs, ob_orig->id.name);
|
||||
|
||||
char key[PBVH_CACHE_KEY_SIZE];
|
||||
pbvh_make_cached_key(ob_orig, key);
|
||||
|
||||
PBVH *pbvh = BLI_ghash_lookup(cached_pbvhs, key);
|
||||
|
||||
if (pbvh) {
|
||||
BKE_pbvh_cache_remove(pbvh);
|
||||
|
@ -4921,7 +4936,10 @@ PBVH *BKE_pbvh_get_or_free_cached(Object *ob, Mesh *me, PBVHType pbvh_type)
|
|||
{
|
||||
Object *ob_orig = DEG_get_original_object(ob);
|
||||
|
||||
PBVH *pbvh = BLI_ghash_lookup(cached_pbvhs, ob_orig->id.name);
|
||||
char key[PBVH_CACHE_KEY_SIZE];
|
||||
pbvh_make_cached_key(ob_orig, key);
|
||||
|
||||
PBVH *pbvh = BLI_ghash_lookup(cached_pbvhs, key);
|
||||
|
||||
if (!pbvh) {
|
||||
return NULL;
|
||||
|
@ -4966,7 +4984,10 @@ void BKE_pbvh_set_cached(Object *ob, PBVH *pbvh)
|
|||
|
||||
Object *ob_orig = DEG_get_original_object(ob);
|
||||
|
||||
PBVH *exist = BLI_ghash_lookup(cached_pbvhs, ob_orig->id.name);
|
||||
char key[PBVH_CACHE_KEY_SIZE];
|
||||
pbvh_make_cached_key(ob_orig, key);
|
||||
|
||||
PBVH *exist = BLI_ghash_lookup(cached_pbvhs, key);
|
||||
|
||||
if (pbvh->invalid) {
|
||||
printf("pbvh invalid!");
|
||||
|
@ -4978,7 +4999,11 @@ void BKE_pbvh_set_cached(Object *ob, PBVH *pbvh)
|
|||
|
||||
if (!exist || exist != pbvh) {
|
||||
pbvh_clear_cached_pbvhs(pbvh);
|
||||
BLI_ghash_insert(cached_pbvhs, BLI_strdup(ob_orig->id.name), pbvh);
|
||||
|
||||
char key[PBVH_CACHE_KEY_SIZE];
|
||||
pbvh_make_cached_key(ob_orig, key);
|
||||
|
||||
BLI_ghash_insert(cached_pbvhs, BLI_strdup(key), pbvh);
|
||||
}
|
||||
|
||||
BKE_pbvh_cache(BKE_object_get_original_mesh(ob_orig), pbvh);
|
||||
|
|
|
@ -141,6 +141,7 @@ typedef struct PaintStroke {
|
|||
StrokeDone done;
|
||||
|
||||
float spacing;
|
||||
void *debug_draw_handle;
|
||||
} PaintStroke;
|
||||
|
||||
struct PaintStroke *paint_stroke_new(struct bContext *C,
|
||||
|
@ -619,6 +620,8 @@ void paint_delete_blur_kernel(BlurKernel *);
|
|||
#define PAINT_CURVE_NUM_SEGMENTS 40
|
||||
|
||||
bool paint_stroke_has_cubic(const PaintStroke *stroke);
|
||||
float bezier3_arclength_v2(const float control[4][2]);
|
||||
float bezier3_arclength_v3(const float control[4][3]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "GPU_state.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
#include "ED_space_api.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "IMB_imbuf_types.h"
|
||||
|
@ -51,6 +52,89 @@
|
|||
# include "PIL_time_utildefines.h"
|
||||
#endif
|
||||
|
||||
static void paint_stroke_add_sample(
|
||||
const Paint *paint, PaintStroke *stroke, float x, float y, float pressure);
|
||||
|
||||
#define DRAW_DEBUG_VIS
|
||||
|
||||
#ifdef DRAW_DEBUG_VIS
|
||||
static void paint_brush_cubic_vis(const bContext *C, ARegion *region, void *userdata)
|
||||
{
|
||||
PaintStroke *stroke = userdata;
|
||||
|
||||
if (!stroke->num_samples) {
|
||||
return;
|
||||
}
|
||||
|
||||
GPU_line_smooth(true);
|
||||
GPU_blend(GPU_BLEND_ALPHA);
|
||||
|
||||
uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
|
||||
immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
|
||||
immUniformColor4ub(0, 0, 0, 155);
|
||||
|
||||
GPU_point_size(12);
|
||||
|
||||
immBegin(GPU_PRIM_LINES, 6);
|
||||
immVertex2f(pos, stroke->mouse_cubic[0][0], stroke->mouse_cubic[0][1]);
|
||||
immVertex2f(pos, stroke->mouse_cubic[1][0], stroke->mouse_cubic[1][1]);
|
||||
|
||||
immVertex2f(pos, stroke->mouse_cubic[1][0], stroke->mouse_cubic[1][1]);
|
||||
immVertex2f(pos, stroke->mouse_cubic[2][0], stroke->mouse_cubic[2][1]);
|
||||
|
||||
immVertex2f(pos, stroke->mouse_cubic[2][0], stroke->mouse_cubic[2][1]);
|
||||
immVertex2f(pos, stroke->mouse_cubic[3][0], stroke->mouse_cubic[3][1]);
|
||||
|
||||
immEnd();
|
||||
|
||||
immBegin(GPU_PRIM_POINTS, 2);
|
||||
immVertex2f(pos, stroke->mouse_cubic[0][0], stroke->mouse_cubic[0][1]);
|
||||
// immVertex2f(pos, stroke->mouse_cubic[1][0], stroke->mouse_cubic[1][1]);
|
||||
// immVertex2f(pos, stroke->mouse_cubic[2][0], stroke->mouse_cubic[2][1]);
|
||||
immVertex2f(pos, stroke->mouse_cubic[3][0], stroke->mouse_cubic[3][1]);
|
||||
immEnd();
|
||||
|
||||
immUniformColor4ub(255, 0, 0, 155);
|
||||
|
||||
GPU_point_size(8);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (i) {
|
||||
if (stroke->num_samples < 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
immBegin(GPU_PRIM_LINES, (stroke->num_samples - 1) * 2);
|
||||
}
|
||||
else {
|
||||
immBegin(GPU_PRIM_POINTS, stroke->num_samples);
|
||||
}
|
||||
|
||||
for (int j = 0; j < stroke->num_samples; j++) {
|
||||
int j2 = (j + stroke->cur_sample) % stroke->num_samples;
|
||||
immVertex2f(pos, stroke->samples[j2].mouse[0], stroke->samples[j2].mouse[1]);
|
||||
|
||||
if (i && j < stroke->num_samples - 1) {
|
||||
int j3 = (j + stroke->cur_sample + 1) % stroke->num_samples;
|
||||
immVertex2f(pos, stroke->samples[j3].mouse[0], stroke->samples[j3].mouse[1]);
|
||||
}
|
||||
}
|
||||
|
||||
immEnd();
|
||||
}
|
||||
|
||||
immUniformColor4ub(0, 0, 255, 155);
|
||||
immBegin(GPU_PRIM_POINTS, 1);
|
||||
immVertex2fv(pos, stroke->samples[stroke->cur_sample].mouse);
|
||||
immEnd();
|
||||
|
||||
immUnbindProgram();
|
||||
|
||||
GPU_blend(GPU_BLEND_NONE);
|
||||
GPU_line_smooth(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*** Cursors ***/
|
||||
static void paint_draw_smooth_cursor(bContext *C, int x, int y, void *customdata)
|
||||
{
|
||||
|
@ -205,6 +289,58 @@ static bool paint_tool_require_inbetween_mouse_events(Brush *brush, ePaintMode m
|
|||
return true;
|
||||
}
|
||||
|
||||
static void paint_brush_make_cubic(PaintStroke *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 - 2 + stroke->num_samples) % stroke->num_samples;
|
||||
|
||||
int ib = (stroke->cur_sample - 4 + stroke->num_samples) % stroke->num_samples;
|
||||
int ic = (stroke->cur_sample - 1 + 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[2];
|
||||
#if 1
|
||||
sub_v2_v2v2(tmp, d, a);
|
||||
sub_v2_v2v2(b, a, b);
|
||||
interp_v2_v2v2(b, b, tmp, 0.5f);
|
||||
mul_v2_fl(b, 1.0f / 3.0f);
|
||||
#else
|
||||
zero_v2(b);
|
||||
#endif
|
||||
|
||||
add_v2_v2(b, a);
|
||||
|
||||
#if 1
|
||||
sub_v2_v2v2(tmp, a, d);
|
||||
sub_v2_v2v2(c, d, c);
|
||||
interp_v2_v2v2(c, c, tmp, 0.5f);
|
||||
mul_v2_fl(c, 1.0f / 3.0f);
|
||||
#else
|
||||
zero_v2(c);
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
#if 0
|
||||
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]);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool paint_stroke_apply_subspacing(struct PaintStroke *stroke,
|
||||
const float spacing,
|
||||
const enum ePaintMode mode,
|
||||
|
@ -461,8 +597,8 @@ 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 */
|
||||
ATTR_NO_OPT static void paint_brush_stroke_add_step(
|
||||
bContext *C, wmOperator *op, PaintStroke *stroke, const float mouse_in[2], float pressure)
|
||||
static void paint_brush_stroke_add_step(
|
||||
bContext *C, wmOperator *op, PaintStroke *stroke, const float mouse[2], float pressure)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Paint *paint = BKE_paint_get_active_from_context(C);
|
||||
|
@ -473,6 +609,37 @@ ATTR_NO_OPT static void paint_brush_stroke_add_step(
|
|||
PointerRNA itemptr;
|
||||
float location[3];
|
||||
|
||||
const float *mouse_in;
|
||||
|
||||
if (stroke->has_cubic_stroke) {
|
||||
paint_stroke_add_sample(paint, stroke, mouse[0], mouse[1], pressure);
|
||||
paint_brush_make_cubic(stroke);
|
||||
}
|
||||
|
||||
float mousetemp[2];
|
||||
|
||||
if (stroke->has_cubic_stroke) {
|
||||
printf("\n");
|
||||
|
||||
for (int i = 0; i < stroke->num_samples; i++) {
|
||||
PaintSample *sample = stroke->samples + ((stroke->cur_sample + i) % stroke->num_samples);
|
||||
printf("%.2f %.2f\n", sample->mouse[0], sample->mouse[1]);
|
||||
}
|
||||
|
||||
mouse_in = mousetemp;
|
||||
|
||||
PaintSample *sample1 = stroke->samples +
|
||||
((stroke->cur_sample - 3 + stroke->num_samples) % stroke->num_samples);
|
||||
PaintSample *sample2 = stroke->samples +
|
||||
((stroke->cur_sample - 2 + stroke->num_samples) % stroke->num_samples);
|
||||
interp_v2_v2v2(mousetemp, sample1->mouse, sample2->mouse, 0.5f);
|
||||
|
||||
// copy_v2_v2(mousetemp, sample1->mouse);
|
||||
}
|
||||
else {
|
||||
mouse_in = mouse;
|
||||
}
|
||||
|
||||
stroke->stroke_sample_index++;
|
||||
|
||||
/* the following code is adapted from texture paint. It may not be needed but leaving here
|
||||
|
@ -504,7 +671,8 @@ ATTR_NO_OPT 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);
|
||||
copy_v2_v2(stroke->last_mouse_position, mouse);
|
||||
|
||||
stroke->last_pressure2 = stroke->last_pressure;
|
||||
stroke->last_pressure = pressure;
|
||||
|
||||
|
@ -537,6 +705,7 @@ ATTR_NO_OPT static void paint_brush_stroke_add_step(
|
|||
}
|
||||
|
||||
bool is_location_is_set;
|
||||
|
||||
ups->last_hit = paint_brush_update(
|
||||
C, brush, mode, stroke, mouse_in, mouse_out, pressure, location, &is_location_is_set);
|
||||
if (is_location_is_set) {
|
||||
|
@ -838,11 +1007,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. */
|
||||
ATTR_NO_OPT static int paint_space_stroke(bContext *C,
|
||||
wmOperator *op,
|
||||
PaintStroke *stroke,
|
||||
const float final_mouse[2],
|
||||
float final_pressure)
|
||||
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);
|
||||
|
@ -910,18 +1079,24 @@ ATTR_NO_OPT static int paint_space_stroke(bContext *C,
|
|||
|
||||
ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush,
|
||||
spacing / no_pressure_spacing);
|
||||
float real_spacing = spacing;
|
||||
if (stroke->has_cubic_stroke) {
|
||||
// paint_brush_make_cubic(stroke);
|
||||
// real_spacing = bezier3_arclength_v2(stroke->mouse_cubic);
|
||||
}
|
||||
|
||||
if (use_scene_spacing) {
|
||||
float size = paint_space_get_final_size(C, scene, stroke, pressure, dpressure, length);
|
||||
|
||||
stroke->stroke_distance += stroke->ups->pixel_radius * spacing / size;
|
||||
stroke->stroke_distance_t += spacing / size;
|
||||
stroke->stroke_distance += stroke->ups->pixel_radius * real_spacing / size;
|
||||
stroke->stroke_distance_t += real_spacing / size;
|
||||
}
|
||||
else {
|
||||
stroke->stroke_distance += spacing / stroke->zoom_2d;
|
||||
stroke->stroke_distance_t += (spacing / stroke->zoom_2d) / stroke->ups->pixel_radius;
|
||||
stroke->stroke_distance += real_spacing / stroke->zoom_2d;
|
||||
stroke->stroke_distance_t += (real_spacing / stroke->zoom_2d) / stroke->ups->pixel_radius;
|
||||
}
|
||||
|
||||
stroke->stroke_distance += spacing / stroke->zoom_2d;
|
||||
stroke->stroke_distance += real_spacing / stroke->zoom_2d;
|
||||
paint_brush_stroke_add_step(C, op, stroke, mouse, pressure);
|
||||
|
||||
length -= spacing;
|
||||
|
@ -940,14 +1115,14 @@ ATTR_NO_OPT static int paint_space_stroke(bContext *C,
|
|||
|
||||
/**** Public API ****/
|
||||
|
||||
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)
|
||||
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");
|
||||
|
@ -957,9 +1132,15 @@ ATTR_NO_OPT PaintStroke *paint_stroke_new(bContext *C,
|
|||
Brush *br = stroke->brush = BKE_paint_brush(p);
|
||||
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||
float zoomx, zoomy;
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
|
||||
ED_view3d_viewcontext_init(C, &stroke->vc, depsgraph);
|
||||
|
||||
#ifdef DRAW_DEBUG_VIS
|
||||
stroke->debug_draw_handle = ED_region_draw_cb_activate(
|
||||
region->type, paint_brush_cubic_vis, stroke, REGION_DRAW_POST_PIXEL);
|
||||
#endif
|
||||
|
||||
stroke->get_location = get_location;
|
||||
stroke->test_start = test_start;
|
||||
stroke->update_step = update_step;
|
||||
|
@ -1034,6 +1215,14 @@ void paint_stroke_free(bContext *C, wmOperator *UNUSED(op), PaintStroke *stroke)
|
|||
|
||||
BLI_freelistN(&stroke->line);
|
||||
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
|
||||
#ifdef DRAW_DEBUG_VIS
|
||||
ED_region_draw_cb_exit(region->type, stroke->debug_draw_handle);
|
||||
#endif
|
||||
|
||||
ED_region_tag_redraw(region);
|
||||
|
||||
MEM_SAFE_FREE(stroke);
|
||||
}
|
||||
|
||||
|
@ -1206,15 +1395,22 @@ bool paint_stroke_has_cubic(const PaintStroke *stroke)
|
|||
return stroke->has_cubic_stroke;
|
||||
}
|
||||
|
||||
static int paint_stroke_max_samples(const Paint *paint, PaintStroke *stroke)
|
||||
{
|
||||
int max_samples = CLAMPIS(paint->num_input_samples, 1, PAINT_MAX_INPUT_SAMPLES);
|
||||
|
||||
if (stroke->has_cubic_stroke) {
|
||||
max_samples = max_ii(max_samples, 6);
|
||||
}
|
||||
|
||||
return max_samples;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
int max_samples = paint_stroke_max_samples(paint, stroke);
|
||||
|
||||
sample->mouse[0] = x;
|
||||
sample->mouse[1] = y;
|
||||
|
@ -1434,10 +1630,6 @@ 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));
|
||||
}
|
||||
|
@ -1490,10 +1682,7 @@ static void paint_stroke_line_constrain(PaintStroke *stroke, float mouse[2])
|
|||
}
|
||||
}
|
||||
|
||||
ATTR_NO_OPT int paint_stroke_modal(bContext *C,
|
||||
wmOperator *op,
|
||||
const wmEvent *event,
|
||||
PaintStroke **stroke_p)
|
||||
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);
|
||||
|
@ -1524,52 +1713,25 @@ ATTR_NO_OPT int paint_stroke_modal(bContext *C,
|
|||
stroke->last_tablet_event_pressure = pressure;
|
||||
}
|
||||
|
||||
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) {
|
||||
paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure);
|
||||
paint_stroke_sample_average(stroke, &sample_average);
|
||||
}
|
||||
else {
|
||||
sample_average.mouse[0] = (float)event->mval[0];
|
||||
sample_average.mouse[1] = (float)event->mval[1];
|
||||
sample_average.pressure = pressure;
|
||||
}
|
||||
|
||||
if (stroke->has_cubic_stroke) {
|
||||
float a[2], b[2], c[2], d[2];
|
||||
if (stroke->stroke_sample_index == 0) {
|
||||
stroke->last_mouse_position[0] = event->mval[0];
|
||||
stroke->last_mouse_position[1] = event->mval[1];
|
||||
|
||||
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;
|
||||
int max_samples = paint_stroke_max_samples(p, stroke);
|
||||
|
||||
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]);
|
||||
for (int i = stroke->num_samples; i < max_samples; i++) {
|
||||
paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1], pressure);
|
||||
}
|
||||
}
|
||||
|
||||
/* Tilt. */
|
||||
|
@ -1734,7 +1896,7 @@ ATTR_NO_OPT int paint_stroke_modal(bContext *C,
|
|||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
ATTR_NO_OPT int paint_stroke_exec(bContext *C, wmOperator *op, PaintStroke *stroke)
|
||||
int paint_stroke_exec(bContext *C, wmOperator *op, PaintStroke *stroke)
|
||||
{
|
||||
/* only when executed for the first time */
|
||||
if (stroke->stroke_started == 0) {
|
||||
|
|
|
@ -1979,8 +1979,8 @@ static void do_wpaint_brush_blur_task_cb_ex(void *__restrict userdata,
|
|||
const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, (eBrushFalloffShape)data->brush->falloff_shape);
|
||||
const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
|
||||
ss, data->brush->falloff_shape);
|
||||
|
||||
|
@ -2080,8 +2080,8 @@ static void do_wpaint_brush_smear_task_cb_ex(void *__restrict userdata,
|
|||
if (cache->is_last_valid && (normalize_v3(brush_dir) != 0.0f)) {
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, (eBrushFalloffShape)data->brush->falloff_shape);
|
||||
const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
|
||||
ss, data->brush->falloff_shape);
|
||||
|
||||
|
@ -2191,8 +2191,8 @@ static void do_wpaint_brush_draw_task_cb_ex(void *__restrict userdata,
|
|||
const bool use_vert_sel = (data->me->editflag & ME_EDIT_PAINT_VERT_SEL) != 0;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, (eBrushFalloffShape)data->brush->falloff_shape);
|
||||
const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
|
||||
ss, data->brush->falloff_shape);
|
||||
|
||||
|
@ -2258,8 +2258,8 @@ static void do_wpaint_brush_calc_average_weight_cb_ex(
|
|||
accum->value = 0.0;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, (eBrushFalloffShape)data->brush->falloff_shape);
|
||||
const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
|
||||
ss, data->brush->falloff_shape);
|
||||
|
||||
|
@ -3054,8 +3054,8 @@ static void do_vpaint_brush_blur_loops(bContext *C,
|
|||
const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
ss, &test, brush->falloff_shape);
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, (eBrushFalloffShape)brush->falloff_shape);
|
||||
const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
|
||||
ss, brush->falloff_shape);
|
||||
|
||||
|
@ -3201,8 +3201,8 @@ static void do_vpaint_brush_blur_verts(bContext *C,
|
|||
const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
ss, &test, brush->falloff_shape);
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, (eBrushFalloffShape)brush->falloff_shape);
|
||||
const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
|
||||
ss, brush->falloff_shape);
|
||||
|
||||
|
@ -3357,8 +3357,8 @@ static void do_vpaint_brush_smear(bContext *C,
|
|||
if (cache->is_last_valid && (normalize_v3(brush_dir) != 0.0f)) {
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
ss, &test, brush->falloff_shape);
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, (eBrushFalloffShape)brush->falloff_shape);
|
||||
const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
|
||||
ss, brush->falloff_shape);
|
||||
|
||||
|
@ -3523,8 +3523,8 @@ static void calculate_average_color(VPaintData<Color, Traits, domain> *vpd,
|
|||
memset(accum2->value, 0, sizeof(accum2->value));
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
ss, &test, brush->falloff_shape);
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, (eBrushFalloffShape)brush->falloff_shape);
|
||||
|
||||
/* For each vertex */
|
||||
PBVHVertexIter vd;
|
||||
|
@ -3641,8 +3641,8 @@ static void vpaint_do_draw(bContext *C,
|
|||
const bool use_face_sel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
ss, &test, brush->falloff_shape);
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, (eBrushFalloffShape)brush->falloff_shape);
|
||||
const float *sculpt_normal_frontface = SCULPT_brush_frontface_normal_from_falloff_shape(
|
||||
ss, brush->falloff_shape);
|
||||
|
||||
|
|
|
@ -2984,11 +2984,13 @@ void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *region, Object *ob
|
|||
|
||||
/************************ Brush Testing *******************/
|
||||
|
||||
void SCULPT_brush_test_init(SculptSession *ss, SculptBrushTest *test)
|
||||
static void sculpt_brush_test_init(const SculptSession *ss, SculptBrushTest *test)
|
||||
{
|
||||
RegionView3D *rv3d = ss->cache ? ss->cache->vc->rv3d : ss->rv3d;
|
||||
View3D *v3d = ss->cache ? ss->cache->vc->v3d : ss->v3d;
|
||||
|
||||
test->tip_roundness = test->tip_scale_x = 1.0f;
|
||||
|
||||
test->radius_squared = ss->cache ? ss->cache->radius_squared :
|
||||
ss->cursor_radius * ss->cursor_radius;
|
||||
test->radius = sqrtf(test->radius_squared);
|
||||
|
@ -3051,6 +3053,28 @@ bool SCULPT_brush_test_sphere(SculptBrushTest *test, const float co[3])
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SCULPT_brush_test_cube_sq(SculptBrushTest *test, const float co[3])
|
||||
{
|
||||
if (SCULPT_brush_test_cube(test, co, test->cube_matrix, test->tip_roundness, true)) {
|
||||
test->dist *= test->dist * test->radius_squared;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SCULPT_brush_test_thru_cube_sq(SculptBrushTest *test, const float co[3])
|
||||
{
|
||||
if (SCULPT_brush_test_cube(test, co, test->cube_matrix, test->tip_roundness, false)) {
|
||||
test->dist *= test->dist * test->radius_squared;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SCULPT_brush_test_sphere_sq(SculptBrushTest *test, const float co[3])
|
||||
{
|
||||
float distsq = len_squared_v3v3(co, test->location);
|
||||
|
@ -3094,7 +3118,8 @@ bool SCULPT_brush_test_circle_sq(SculptBrushTest *test, const float co[3])
|
|||
bool SCULPT_brush_test_cube(SculptBrushTest *test,
|
||||
const float co[3],
|
||||
const float local[4][4],
|
||||
const float roundness)
|
||||
const float roundness,
|
||||
bool test_z)
|
||||
{
|
||||
float side = M_SQRT1_2;
|
||||
float local_co[3];
|
||||
|
@ -3116,7 +3141,7 @@ bool SCULPT_brush_test_cube(SculptBrushTest *test,
|
|||
const float constant_side = hardness * side;
|
||||
const float falloff_side = roundness * side;
|
||||
|
||||
if (!(local_co[0] <= side && local_co[1] <= side && local_co[2] <= side)) {
|
||||
if (!(local_co[0] <= side && local_co[1] <= side && (!test_z || local_co[2] <= side))) {
|
||||
/* Outside the square. */
|
||||
return false;
|
||||
}
|
||||
|
@ -3138,20 +3163,140 @@ bool SCULPT_brush_test_cube(SculptBrushTest *test,
|
|||
return true;
|
||||
}
|
||||
|
||||
SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(SculptSession *ss,
|
||||
SculptBrushTest *test,
|
||||
char falloff_shape)
|
||||
SculptBrushTestFn SCULPT_brush_test_init(const SculptSession *ss,
|
||||
SculptBrushTest *test,
|
||||
eBrushFalloffShape falloff_mode)
|
||||
{
|
||||
SCULPT_brush_test_init(ss, test);
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn;
|
||||
if (falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
|
||||
sculpt_brush_test_sq_fn = SCULPT_brush_test_sphere_sq;
|
||||
float tip_roundness = 1.0f;
|
||||
float tip_scale_x = 1.0f;
|
||||
|
||||
if (ss->cache && ss->cache->channels_final) {
|
||||
tip_roundness = SCULPT_get_float(ss, tip_roundness, NULL, NULL);
|
||||
tip_scale_x = SCULPT_get_float(ss, tip_scale_x, NULL, NULL);
|
||||
}
|
||||
|
||||
return SCULPT_brush_test_init_ex(ss, test, falloff_mode, tip_roundness, tip_scale_x);
|
||||
}
|
||||
|
||||
SculptBrushTestFn SCULPT_brush_test_init_ex(const SculptSession *ss,
|
||||
SculptBrushTest *test,
|
||||
eBrushFalloffShape falloff_mode,
|
||||
float tip_roundness,
|
||||
float tip_scale_x)
|
||||
{
|
||||
sculpt_brush_test_init(ss, test);
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = NULL;
|
||||
|
||||
test->tip_roundness = tip_roundness;
|
||||
test->tip_scale_x = tip_scale_x;
|
||||
|
||||
if (tip_roundness != 1.0f || tip_scale_x != 1.0f) {
|
||||
float mat[4][4], tmat[4][4], scale[4][4];
|
||||
|
||||
float grab_delta[3];
|
||||
copy_v3_v3(grab_delta, ss->cache->grab_delta_symmetry);
|
||||
|
||||
if (dot_v3v3(grab_delta, grab_delta) < 0.0001f) {
|
||||
/* First time, use cached grab delta. */
|
||||
|
||||
copy_v3_v3(grab_delta, ss->last_grab_delta);
|
||||
flip_v3_v3(grab_delta, grab_delta, ss->cache->mirror_symmetry_pass);
|
||||
|
||||
mul_m4_v3(ss->cache->symm_rot_mat, grab_delta);
|
||||
}
|
||||
|
||||
if (dot_v3v3(grab_delta, grab_delta) < 0.0001f) {
|
||||
/* Grab_delta still zero? Use cross of view and normal vectors. */
|
||||
cross_v3_v3v3(grab_delta, ss->cache->view_normal, ss->cache->sculpt_normal);
|
||||
}
|
||||
|
||||
if (dot_v3v3(grab_delta, grab_delta) < 0.0001f) {
|
||||
/* Still zero? */
|
||||
int axis;
|
||||
|
||||
float ax = fabsf(ss->cache->view_normal[0]);
|
||||
float ay = fabsf(ss->cache->view_normal[1]);
|
||||
float az = fabsf(ss->cache->view_normal[2]);
|
||||
|
||||
if (ax > ay && ax > az) {
|
||||
axis = 1;
|
||||
}
|
||||
else if (ay > ax && ay > az) {
|
||||
axis = 2;
|
||||
}
|
||||
else {
|
||||
axis = 0;
|
||||
}
|
||||
|
||||
grab_delta[axis] = 1.0f;
|
||||
}
|
||||
|
||||
cross_v3_v3v3(mat[0], ss->cache->cached_area_normal, grab_delta);
|
||||
mat[0][3] = 0;
|
||||
cross_v3_v3v3(mat[1], ss->cache->cached_area_normal, mat[0]);
|
||||
mat[1][3] = 0;
|
||||
copy_v3_v3(mat[2], ss->cache->cached_area_normal);
|
||||
mat[2][3] = 0;
|
||||
copy_v3_v3(mat[3], ss->cache->location);
|
||||
mat[3][3] = 1;
|
||||
normalize_m4(mat);
|
||||
|
||||
if (determinant_m4(mat) < 0.000001f) {
|
||||
fprintf(stderr, "%s: Matrix error 1\n", __func__);
|
||||
unit_m4(mat);
|
||||
}
|
||||
|
||||
scale_m4_fl(scale, ss->cache->radius);
|
||||
mul_m4_m4m4(tmat, mat, scale);
|
||||
mul_v3_fl(tmat[1], tip_scale_x);
|
||||
|
||||
if (determinant_m4(tmat) < 0.000001f) {
|
||||
fprintf(stderr, "%s: Matrix error 2\n", __func__);
|
||||
unit_m4(tmat);
|
||||
}
|
||||
|
||||
invert_m4_m4(mat, tmat);
|
||||
|
||||
copy_m4_m4(test->cube_matrix, mat);
|
||||
|
||||
switch (falloff_mode) {
|
||||
case PAINT_FALLOFF_SHAPE_SPHERE:
|
||||
sculpt_brush_test_sq_fn = SCULPT_brush_test_cube_sq;
|
||||
|
||||
case PAINT_FALLOFF_SHAPE_TUBE:
|
||||
if (ss->cache) {
|
||||
plane_from_point_normal_v3(test->plane_view, test->location, ss->cache->view_normal);
|
||||
}
|
||||
else {
|
||||
zero_v3(test->plane_view);
|
||||
test->plane_view[2] = 1.0f;
|
||||
}
|
||||
|
||||
sculpt_brush_test_sq_fn = SCULPT_brush_test_thru_cube_sq;
|
||||
case PAINT_FALLOFF_NOOP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* PAINT_FALLOFF_SHAPE_TUBE */
|
||||
plane_from_point_normal_v3(test->plane_view, test->location, ss->cache->view_normal);
|
||||
sculpt_brush_test_sq_fn = SCULPT_brush_test_circle_sq;
|
||||
switch (falloff_mode) {
|
||||
case PAINT_FALLOFF_SHAPE_SPHERE:
|
||||
sculpt_brush_test_sq_fn = SCULPT_brush_test_sphere_sq;
|
||||
|
||||
case PAINT_FALLOFF_SHAPE_TUBE:
|
||||
if (ss->cache) {
|
||||
plane_from_point_normal_v3(test->plane_view, test->location, ss->cache->view_normal);
|
||||
}
|
||||
else {
|
||||
zero_v3(test->plane_view);
|
||||
test->plane_view[2] = 1.0f;
|
||||
}
|
||||
|
||||
sculpt_brush_test_sq_fn = SCULPT_brush_test_circle_sq;
|
||||
case PAINT_FALLOFF_NOOP:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return sculpt_brush_test_sq_fn;
|
||||
}
|
||||
|
||||
|
@ -3319,8 +3464,8 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
|
|||
}
|
||||
|
||||
SculptBrushTest normal_test;
|
||||
SculptBrushTestFn sculpt_brush_normal_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
ss, &normal_test, data->brush->falloff_shape);
|
||||
SculptBrushTestFn sculpt_brush_normal_test_sq_fn = SCULPT_brush_test_init_ex(
|
||||
ss, &normal_test, data->brush->falloff_shape, 1.0f, 1.0f);
|
||||
|
||||
/* Update the test radius to sample the normal using the normal radius of the brush. */
|
||||
if (data->brush->ob_mode == OB_MODE_SCULPT) {
|
||||
|
@ -3331,8 +3476,8 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
|
|||
}
|
||||
|
||||
SculptBrushTest area_test;
|
||||
SculptBrushTestFn sculpt_brush_area_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
ss, &area_test, data->brush->falloff_shape);
|
||||
SculptBrushTestFn sculpt_brush_area_test_sq_fn = SCULPT_brush_test_init_ex(
|
||||
ss, &area_test, data->brush->falloff_shape, 1.0f, 1.0f);
|
||||
|
||||
if (data->brush->ob_mode == OB_MODE_SCULPT) {
|
||||
float test_radius = sqrtf(area_test.radius_squared);
|
||||
|
@ -3704,34 +3849,58 @@ off fort;
|
|||
|
||||
*/
|
||||
|
||||
ATTR_NO_OPT float dcubic(float k1, float k2, float k3, float k4, float t)
|
||||
float bezier3_derivative(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])
|
||||
void bezier3_derivative_v3(float r_out[3], float control[4][3], float t)
|
||||
{
|
||||
r_out[0] = bezier3_derivative(control[0][0], control[1][0], control[2][0], control[3][0], t);
|
||||
r_out[1] = bezier3_derivative(control[0][1], control[1][1], control[2][1], control[3][1], t);
|
||||
r_out[2] = bezier3_derivative(control[0][2], control[1][2], control[2][2], control[3][2], t);
|
||||
}
|
||||
|
||||
float bezier3_arclength_v3(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);
|
||||
float dx = bezier3_derivative(control[0][0], control[1][0], control[2][0], control[3][0], t);
|
||||
float dy = bezier3_derivative(control[0][1], control[1][1], control[2][1], control[3][1], t);
|
||||
float dz = bezier3_derivative(control[0][2], control[1][2], control[2][2], control[3][2], t);
|
||||
|
||||
arc += sqrtf(dx * dx + dy * dy + dz * dz);
|
||||
arc += sqrtf(dx * dx + dy * dy + dz * dz) * dt;
|
||||
}
|
||||
|
||||
return arc;
|
||||
}
|
||||
|
||||
float bezier3_arclength_v2(const float control[4][2])
|
||||
{
|
||||
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 = bezier3_derivative(control[0][0], control[1][0], control[2][0], control[3][0], t);
|
||||
float dy = bezier3_derivative(control[0][1], control[1][1], control[2][1], control[3][1], t);
|
||||
|
||||
arc += sqrtf(dx * dx + dy * dy) * dt;
|
||||
}
|
||||
|
||||
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])
|
||||
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);
|
||||
|
@ -3745,12 +3914,12 @@ ATTR_NO_OPT static void evaluate_cubic_bezier(const float control[4][3],
|
|||
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);
|
||||
r_tangent[0] = bezier3_derivative(control[0][0], control[1][0], control[2][0], control[3][0], t);
|
||||
r_tangent[1] = bezier3_derivative(control[0][1], control[1][1], control[2][1], control[3][1], t);
|
||||
r_tangent[2] = bezier3_derivative(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])
|
||||
static float cubic_uv_test(const float co[3], const float p[3], const float tan[3])
|
||||
{
|
||||
float tmp[3];
|
||||
|
||||
|
@ -3758,12 +3927,10 @@ ATTR_NO_OPT static float cubic_uv_test(const float co[3], const float p[3], cons
|
|||
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])
|
||||
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;
|
||||
const int binary_steps = 10;
|
||||
float dt = 1.0f / (float)steps, t = dt;
|
||||
|
||||
float lastp[3];
|
||||
|
@ -4018,15 +4185,15 @@ static float brush_strength(const Sculpt *sd,
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
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;
|
||||
|
@ -4087,23 +4254,63 @@ ATTR_NO_OPT float SCULPT_brush_strength_factor(SculptSession *ss,
|
|||
|
||||
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) {
|
||||
float eps = 0.001;
|
||||
if (point_3d[0] < eps || point_3d[0] >= 1.0f - eps) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
point_3d[1] /= ss->cache->radius;
|
||||
if (point_3d[1] >= ss->cache->radius) {
|
||||
// return 0.0f;
|
||||
}
|
||||
|
||||
//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 pos[3], tan[3];
|
||||
evaluate_cubic_bezier(ss->cache->world_cubic, point_3d[0], pos, tan);
|
||||
|
||||
float vec[3], vec2[3];
|
||||
|
||||
normalize_v3(tan);
|
||||
sub_v3_v3v3(vec, SCULPT_vertex_co_get(ss, vertex_index), pos);
|
||||
normalize_v3(vec);
|
||||
|
||||
cross_v3_v3v3(vec2, vec, tan);
|
||||
|
||||
if (dot_v3v3(vec2, ss->cache->view_normal) < 0.0) {
|
||||
point_3d[1] = (ss->cache->radius + point_3d[1]) * 0.5f;
|
||||
}
|
||||
else {
|
||||
point_3d[1] = (ss->cache->radius - point_3d[1]) * 0.5f;
|
||||
}
|
||||
|
||||
float t1 = ss->cache->last_stroke_distance_t;
|
||||
float t2 = point_3d[0] * ss->cache->world_cubic_arclength / ss->cache->radius;
|
||||
|
||||
point_3d[0] = t1 + t2;
|
||||
point_3d[0] *= ss->cache->radius;
|
||||
|
||||
#if 0
|
||||
float color[4] = {point_3d[0], point_3d[0], point_3d[0], 1.0f};
|
||||
mul_v3_fl(color, 0.25f / ss->cache->radius);
|
||||
color[0] -= floorf(color[0]);
|
||||
color[1] -= floorf(color[1]);
|
||||
color[2] -= floorf(color[2]);
|
||||
|
||||
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);
|
||||
// avg = 0.0f;
|
||||
#endif
|
||||
//#else
|
||||
// point_3d[0] /= ss->cache->radius;
|
||||
// point_3d[0] -= floorf(point_3d[0]);
|
||||
|
||||
float pixel_radius = br->size;
|
||||
mul_v3_fl(point_3d, pixel_radius / ss->cache->radius);
|
||||
|
||||
avg = BKE_brush_sample_tex_3d(scene, br, point_3d, rgba, thread_id, ss->tex_pool);
|
||||
//#endif
|
||||
}
|
||||
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);
|
||||
avg = BKE_brush_sample_tex_3d(scene, br, point_3d, rgba, thread_id, ss->tex_pool);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4714,7 +4921,7 @@ static void do_gravity_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -5128,6 +5335,10 @@ static void get_nodes_undo(Sculpt *sd,
|
|||
float radius_scale = 1.0f;
|
||||
const bool use_original = sculpt_tool_needs_original(cmd->tool) ? true : ss->cache->original;
|
||||
|
||||
if (BRUSHSET_GET_FLOAT(cmd->params_mapped, tip_roundness, &ss->cache->input_mapping) != 1.0f) {
|
||||
radius_scale *= sqrtf(2.0f);
|
||||
}
|
||||
|
||||
if (SCULPT_tool_needs_all_pbvh_nodes(brush)) {
|
||||
/* These brushes need to update all nodes as they are not constrained by the brush radius
|
||||
*/
|
||||
|
@ -5280,6 +5491,12 @@ static void sculpt_apply_alt_smmoth_settings(SculptSession *ss, Sculpt *sd, Brus
|
|||
BRUSHSET_LOOKUP(ss->cache->channels_final, projection), ch, parentch, false, true);
|
||||
}
|
||||
|
||||
bool SCULPT_needs_area_normal(SculptSession *ss, Sculpt *sd, Brush *brush)
|
||||
{
|
||||
return SCULPT_get_float(ss, tip_roundness, sd, brush) != 1.0f ||
|
||||
SCULPT_get_float(ss, tip_scale_x, sd, brush) != 1.0f;
|
||||
}
|
||||
|
||||
static void SCULPT_run_command(Sculpt *sd,
|
||||
Object *ob,
|
||||
Brush *brush,
|
||||
|
@ -5313,7 +5530,7 @@ static void SCULPT_run_command(Sculpt *sd,
|
|||
Brush _brush2, *brush2 = &_brush2;
|
||||
|
||||
/*
|
||||
* Check that original data is for anchored and drag dot modes
|
||||
* Check that original data exists for anchored and drag dot modes
|
||||
*/
|
||||
if (brush->flag & (BRUSH_ANCHORED | BRUSH_DRAG_DOT)) {
|
||||
for (int i = 0; i < totnode; i++) {
|
||||
|
@ -5378,6 +5595,14 @@ static void SCULPT_run_command(Sculpt *sd,
|
|||
|
||||
/*Search PBVH*/
|
||||
|
||||
if (SCULPT_needs_area_normal(ss, sd, brush2)) {
|
||||
SCULPT_calc_area_normal(sd, ob, nodes, totnode, ss->cache->cached_area_normal);
|
||||
|
||||
if (dot_v3v3(ss->cache->cached_area_normal, ss->cache->cached_area_normal) == 0.0f) {
|
||||
ss->cache->cached_area_normal[2] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (sculpt_brush_needs_normal(ss, brush2)) {
|
||||
update_sculpt_normal(sd, ob, nodes, totnode);
|
||||
}
|
||||
|
@ -6853,6 +7078,9 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
|
|||
SCULPT_TOOL_ARRAY,
|
||||
SCULPT_TOOL_THUMB);
|
||||
|
||||
bad = bad && SCULPT_get_float(ss, tip_roundness, NULL, brush) == 1.0f;
|
||||
bad = bad && SCULPT_get_float(ss, tip_scale_x, NULL, brush) == 1.0f;
|
||||
|
||||
bad = bad && !sculpt_brush_use_topology_rake(ss, brush);
|
||||
bad = bad && !SCULPT_get_bool(ss, use_autofset, NULL, brush);
|
||||
|
||||
|
@ -6981,6 +7209,10 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru
|
|||
}
|
||||
}
|
||||
|
||||
if (dot_v3v3(cache->grab_delta, cache->grab_delta) > 0.0f) {
|
||||
copy_v3_v3(ss->last_grab_delta, cache->grab_delta);
|
||||
}
|
||||
|
||||
// XXX implement me
|
||||
|
||||
if (SCULPT_get_int(ss, use_smoothed_rake, NULL, brush)) {
|
||||
|
@ -7125,10 +7357,7 @@ static float sculpt_update_speed_average(SculptSession *ss, float speed)
|
|||
return speed / (float)tot;
|
||||
}
|
||||
/* Initialize the stroke cache variants from operator properties. */
|
||||
ATTR_NO_OPT static void sculpt_update_cache_variants(bContext *C,
|
||||
Sculpt *sd,
|
||||
Object *ob,
|
||||
PointerRNA *ptr)
|
||||
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;
|
||||
|
@ -7143,6 +7372,43 @@ ATTR_NO_OPT static void sculpt_update_cache_variants(bContext *C,
|
|||
RNA_float_get_array(ptr, "location", cache->true_location);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure last_grab_delta, which controls tip rotation on
|
||||
* first brush dab, is not zero.
|
||||
*/
|
||||
if (dot_v3v3(ss->last_grab_delta, ss->last_grab_delta) == 0.0f) {
|
||||
int axis;
|
||||
|
||||
float mat[4][4];
|
||||
|
||||
ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, mat);
|
||||
invert_m4(mat);
|
||||
|
||||
float dx = mat[0][0];
|
||||
float dy = mat[1][1];
|
||||
float dz = mat[2][2];
|
||||
|
||||
float ax = fabsf(dx);
|
||||
float ay = fabsf(dy);
|
||||
float az = fabsf(dz);
|
||||
float sign;
|
||||
|
||||
if (ax > ay && ax > az) {
|
||||
axis = 1;
|
||||
sign = dx < 0.0f ? -1.0f : 1.0f;
|
||||
}
|
||||
else if (ay > ax && ay > az) {
|
||||
axis = 2;
|
||||
sign = dy < 0.0f ? -1.0f : 1.0f;
|
||||
}
|
||||
else {
|
||||
axis = 0;
|
||||
sign = dz < 0.0f ? -1.0f : 1.0f;
|
||||
}
|
||||
|
||||
ss->last_grab_delta[axis] = sign;
|
||||
}
|
||||
|
||||
float last_mouse[2];
|
||||
copy_v2_v2(last_mouse, cache->mouse);
|
||||
|
||||
|
@ -7275,13 +7541,18 @@ ATTR_NO_OPT static void sculpt_update_cache_variants(bContext *C,
|
|||
10.0f; /*scale to a more user-friendly value*/
|
||||
|
||||
if (cache->has_cubic) {
|
||||
RNA_float_get_array(ptr, "mouse_cubic", (float *)cache->mouse_cubic);
|
||||
float mouse_cubic[4][2];
|
||||
|
||||
printf("\n");
|
||||
RNA_float_get_array(ptr, "mouse_cubic", (float *)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])) {
|
||||
copy_v2_v2(cache->mouse_cubic[i], mouse_cubic[i]);
|
||||
cache->mouse_cubic[i][2] = 0.0f;
|
||||
|
||||
if (!SCULPT_stroke_get_location(C, cache->world_cubic[i], mouse_cubic[i])) {
|
||||
float loc[3];
|
||||
|
||||
mul_v3_m4v3(loc, ob->obmat, cache->true_location);
|
||||
|
@ -7289,11 +7560,11 @@ ATTR_NO_OPT static void sculpt_update_cache_variants(bContext *C,
|
|||
ED_view3d_win_to_3d(CTX_wm_view3d(C),
|
||||
CTX_wm_region(C),
|
||||
cache->true_location,
|
||||
cache->mouse_cubic[i],
|
||||
mouse_cubic[i],
|
||||
cache->world_cubic[i]);
|
||||
}
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
printf("%.2f, %.2f %.2f\n",
|
||||
cache->world_cubic[i][0],
|
||||
cache->world_cubic[i][1],
|
||||
|
@ -7301,7 +7572,8 @@ ATTR_NO_OPT static void sculpt_update_cache_variants(bContext *C,
|
|||
#endif
|
||||
}
|
||||
|
||||
cache->world_cubic_arclength = cubic_arclen(cache->world_cubic);
|
||||
cache->world_cubic_arclength = bezier3_arclength_v3(cache->world_cubic);
|
||||
cache->mouse_cubic_arclength = bezier3_arclength_v3(cache->mouse_cubic);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8090,17 +8362,17 @@ static void sculpt_cache_dyntopo_settings(BrushChannelSet *chset,
|
|||
r_settings->flag = BRUSHSET_GET_INT(chset, dyntopo_mode, NULL);
|
||||
r_settings->mode = BRUSHSET_GET_INT(chset, dyntopo_detail_mode, NULL);
|
||||
r_settings->radius_scale = BRUSHSET_GET_FLOAT(chset, dyntopo_radius_scale, input_data);
|
||||
r_settings->spacing = BRUSHSET_GET_FLOAT(chset, dyntopo_spacing, input_data);
|
||||
r_settings->spacing = (int)BRUSHSET_GET_FLOAT(chset, dyntopo_spacing, input_data);
|
||||
r_settings->detail_size = BRUSHSET_GET_FLOAT(chset, dyntopo_detail_size, input_data);
|
||||
r_settings->detail_range = BRUSHSET_GET_FLOAT(chset, dyntopo_detail_range, input_data);
|
||||
r_settings->detail_percent = BRUSHSET_GET_FLOAT(chset, dyntopo_detail_percent, input_data);
|
||||
r_settings->constant_detail = BRUSHSET_GET_FLOAT(chset, dyntopo_constant_detail, input_data);
|
||||
};
|
||||
|
||||
ATTR_NO_OPT static void sculpt_stroke_update_step(bContext *C,
|
||||
wmOperator *UNUSED(op),
|
||||
struct PaintStroke *stroke,
|
||||
PointerRNA *itemptr)
|
||||
static void sculpt_stroke_update_step(bContext *C,
|
||||
wmOperator *UNUSED(op),
|
||||
struct PaintStroke *stroke,
|
||||
PointerRNA *itemptr)
|
||||
|
||||
{
|
||||
|
||||
|
@ -8182,8 +8454,10 @@ ATTR_NO_OPT static void sculpt_stroke_update_step(bContext *C,
|
|||
}
|
||||
|
||||
ss->cache->stroke_distance = stroke->stroke_distance;
|
||||
ss->cache->last_stroke_distance_t = ss->cache->stroke_distance_t;
|
||||
ss->cache->stroke_distance_t = stroke->stroke_distance_t;
|
||||
ss->cache->stroke = stroke;
|
||||
ss->cache->stroke_spacing_t = SCULPT_get_float(ss, spacing, sd, brush) / 100.0f;
|
||||
|
||||
if (SCULPT_stroke_is_first_brush_step(ss->cache)) {
|
||||
ss->cache->last_dyntopo_t = 0.0f;
|
||||
|
|
|
@ -229,7 +229,7 @@ typedef float (*SculptBrushTestFn)(SculptBrushTest *test, float *co);
|
|||
typedef bool (*BKE_pbvh_SearchCallback)(PBVHNode *node, void *data);
|
||||
void BKE_pbvh_search_gather(
|
||||
PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot);
|
||||
SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(struct SculptSession *ss,
|
||||
SculptBrushTestFn SCULPT_brush_test_init(struct SculptSession *ss,
|
||||
SculptBrushTest *test,
|
||||
char falloff_shape);
|
||||
bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v);
|
||||
|
@ -747,7 +747,7 @@ class BMeshPBVH {
|
|||
|
||||
if (!args->test) {
|
||||
args->test = &default_test;
|
||||
args->test_func = SCULPT_brush_test_init_with_falloff_shape(
|
||||
args->test_func = SCULPT_brush_test_init(
|
||||
_ss, &default_test, /*args->brush->falloff_shape*/ 0);
|
||||
}
|
||||
|
||||
|
@ -859,7 +859,7 @@ class SculptImpl {
|
|||
BKE_curvemapping_init(brush->curve);
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, ss->cache->brush->falloff_shape);
|
||||
|
||||
/*
|
||||
|
|
|
@ -322,7 +322,7 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -404,7 +404,7 @@ static void do_twist_brush_task_cb_ex(void *__restrict userdata,
|
|||
const float bstrength = flip ? -ss->cache->bstrength : ss->cache->bstrength;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -484,7 +484,7 @@ static void do_twist_brush_post_smooth_task_cb_ex(void *__restrict userdata,
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -681,7 +681,7 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -780,7 +780,7 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
plane_from_point_normal_v3(test.plane_tool, area_co, area_no);
|
||||
|
@ -883,7 +883,7 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -1056,7 +1056,7 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -1154,7 +1154,7 @@ static void calc_clay_surface_task_cb(void *__restrict userdata,
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, brush->falloff_shape);
|
||||
|
||||
/* Apply the brush normal radius to the test before sampling. */
|
||||
|
@ -1211,7 +1211,7 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -1336,12 +1336,16 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata,
|
|||
|
||||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SCULPT_brush_test_init(ss, &test);
|
||||
SCULPT_brush_test_init(ss, &test, PAINT_FALLOFF_NOOP);
|
||||
plane_from_point_normal_v3(test.plane_tool, area_co, area_no_sp);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
if (!SCULPT_brush_test_cube(&test, vd.co, mat, brush->tip_roundness)) {
|
||||
if (!SCULPT_brush_test_cube(&test,
|
||||
vd.co,
|
||||
mat,
|
||||
brush->tip_roundness,
|
||||
brush->falloff_shape != PAINT_FALLOFF_SHAPE_TUBE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1503,7 +1507,7 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -1644,7 +1648,7 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -1714,7 +1718,7 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -1828,7 +1832,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata,
|
|||
SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -2108,7 +2112,7 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -2176,7 +2180,7 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -2254,7 +2258,7 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -2369,7 +2373,7 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -2486,7 +2490,7 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -2737,7 +2741,7 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -2793,7 +2797,7 @@ static void do_draw_sharp_brush_task_cb_ex_plane(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -3030,7 +3034,7 @@ static void do_scene_project_brush_task_cb_ex(void *__restrict userdata,
|
|||
SculptThreadedTaskData *data = userdata;
|
||||
SculptSession *ss = data->ob->sculpt;
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
|
||||
const float bstrength = clamp_f(ss->cache->bstrength, 0.0f, 1.0f);
|
||||
|
@ -3147,7 +3151,7 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -3318,7 +3322,7 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata,
|
|||
BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n]);
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -3416,7 +3420,7 @@ static void do_fairing_brush_tag_store_task_cb_ex(void *__restrict userdata,
|
|||
SculptThreadedTaskData *data = userdata;
|
||||
SculptSession *ss = data->ob->sculpt;
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
PBVHVertexIter vd;
|
||||
|
||||
|
@ -3722,7 +3726,7 @@ static void do_displacement_eraser_brush_task_cb_ex(void *__restrict userdata,
|
|||
float(*proxy)[3] = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -3785,7 +3789,7 @@ static void do_displacement_smear_brush_task_cb_ex(void *__restrict userdata,
|
|||
const float bstrength = clamp_f(ss->cache->bstrength, 0.0f, 1.0f);
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -3952,7 +3956,7 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata,
|
|||
const float bstrength = sqrtf(clamp_f(data->strength, 0.0f, 1.0f));
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -4098,7 +4102,7 @@ void SCULPT_bmesh_topology_rake(Sculpt *sd,
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, brush->falloff_shape);
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
|
||||
|
@ -4180,7 +4184,7 @@ static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata,
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
|
|
@ -1265,7 +1265,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
|
|||
const float bstrength = ss->cache->bstrength;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
|
|
@ -1609,7 +1609,7 @@ static void sculpt_uv_brush_cb(void *__restrict userdata,
|
|||
// const float *offset = data->offset;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
|
||||
PBVHNode *node = data->nodes[n];
|
||||
|
@ -1767,7 +1767,7 @@ void SCULPT_uv_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
|
|||
uvsolver_solve_begin(solver);
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, brush->falloff_shape);
|
||||
|
||||
BLI_mempool_iter iter;
|
||||
|
|
|
@ -367,7 +367,7 @@ void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata,
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
@ -637,7 +637,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata,
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
|
||||
const bool relax_face_sets = !(ss->cache->iteration_count % 3 == 0);
|
||||
|
|
|
@ -444,6 +444,11 @@ typedef struct SculptBrushTest {
|
|||
int radial_symmetry_pass;
|
||||
float symm_rot_mat_inv[4][4];
|
||||
|
||||
float tip_roundness;
|
||||
float tip_scale_x;
|
||||
|
||||
float cube_matrix[4][4];
|
||||
|
||||
/* For circle (not sphere) projection. */
|
||||
float plane_view[4];
|
||||
|
||||
|
@ -604,6 +609,8 @@ typedef struct StrokeCache {
|
|||
float sculpt_normal[3];
|
||||
float sculpt_normal_symm[3];
|
||||
|
||||
float cached_area_normal[3];
|
||||
|
||||
/* Used for area texture mode, local_mat gets calculated by
|
||||
* calc_brush_local_mat() and used in tex_strength(). */
|
||||
float brush_local_mat[4][4];
|
||||
|
@ -692,6 +699,8 @@ typedef struct StrokeCache {
|
|||
|
||||
float stroke_distance; // copy of PaintStroke->stroke_distance
|
||||
float stroke_distance_t; // copy of PaintStroke->stroke_distance_t
|
||||
float stroke_spacing_t;
|
||||
float last_stroke_distance_t;
|
||||
|
||||
float last_dyntopo_t;
|
||||
float last_smooth_t[SCULPT_MAX_SYMMETRY_PASSES];
|
||||
|
@ -715,9 +724,10 @@ typedef struct StrokeCache {
|
|||
int tool_override;
|
||||
BrushChannelSet *tool_override_channels;
|
||||
|
||||
float mouse_cubic[4][2];
|
||||
float mouse_cubic[4][3];
|
||||
float world_cubic[4][3];
|
||||
float world_cubic_arclength;
|
||||
float mouse_cubic_arclength;
|
||||
bool has_cubic;
|
||||
} StrokeCache;
|
||||
|
||||
|
@ -1483,9 +1493,20 @@ void SCULPT_flip_quat_by_symm_area(float quat[4],
|
|||
const float pivot[3]);
|
||||
|
||||
/**
|
||||
* Initialize a point-in-brush test
|
||||
* Initialize a point-in-brush test with a given falloff shape.
|
||||
*
|
||||
* \param falloff_shape: #PAINT_FALLOFF_SHAPE_SPHERE, #PAINT_FALLOFF_SHAPE_TUBE or
|
||||
* #PAINT_FALLOFF_SHAPE_NOOP \return The brush falloff function, or nullptr if falloff_shape was
|
||||
* #PAINT_FALLOFF_SHAPE_NOOP
|
||||
*/
|
||||
void SCULPT_brush_test_init(struct SculptSession *ss, SculptBrushTest *test);
|
||||
SculptBrushTestFn SCULPT_brush_test_init(const SculptSession *ss,
|
||||
SculptBrushTest *test,
|
||||
eBrushFalloffShape falloff_mode);
|
||||
SculptBrushTestFn SCULPT_brush_test_init_ex(const SculptSession *ss,
|
||||
SculptBrushTest *test,
|
||||
eBrushFalloffShape falloff_mode,
|
||||
float tip_roundness,
|
||||
float tip_scale_x);
|
||||
|
||||
bool SCULPT_brush_test_sphere(SculptBrushTest *test, const float co[3]);
|
||||
bool SCULPT_brush_test_sphere_sq(SculptBrushTest *test, const float co[3]);
|
||||
|
@ -1493,7 +1514,8 @@ bool SCULPT_brush_test_sphere_fast(const SculptBrushTest *test, const float co[3
|
|||
bool SCULPT_brush_test_cube(SculptBrushTest *test,
|
||||
const float co[3],
|
||||
const float local[4][4],
|
||||
float roundness);
|
||||
float roundness,
|
||||
bool test_z);
|
||||
bool SCULPT_brush_test_circle_sq(SculptBrushTest *test, const float co[3]);
|
||||
/**
|
||||
* Test AABB against sphere.
|
||||
|
@ -1504,15 +1526,6 @@ bool SCULPT_search_sphere_cb(PBVHNode *node, void *data_v);
|
|||
*/
|
||||
bool SCULPT_search_circle_cb(PBVHNode *node, void *data_v);
|
||||
|
||||
/**
|
||||
* Initialize a point-in-brush test with a given falloff shape.
|
||||
*
|
||||
* \param falloff_shape: #PAINT_FALLOFF_SHAPE_SPHERE or #PAINT_FALLOFF_SHAPE_TUBE.
|
||||
* \return The brush falloff function.
|
||||
*/
|
||||
SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(SculptSession *ss,
|
||||
SculptBrushTest *test,
|
||||
char falloff_shape);
|
||||
const float *SCULPT_brush_frontface_normal_from_falloff_shape(SculptSession *ss,
|
||||
char falloff_shape);
|
||||
|
||||
|
@ -2602,6 +2615,7 @@ void SCULPT_dyntopo_automasking_end(void *mask_data);
|
|||
#define BOUNDARY_SMOOTH_EXP 2.0
|
||||
|
||||
#define SCULPT_TOOL_NEEDS_COLOR(tool) ELEM(tool, SCULPT_TOOL_PAINT, SCULPT_TOOL_SMEAR)
|
||||
bool SCULPT_needs_area_normal(SculptSession *ss, Sculpt *sd, Brush *brush);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata,
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -140,7 +140,7 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata,
|
|||
proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ static void do_color_smooth_task_cb_exec(void *__restrict userdata,
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -118,7 +118,7 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -143,6 +143,9 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
|
|||
float alpha = BKE_brush_channelset_get_final_float(
|
||||
BKE_paint_brush(&data->sd->paint)->channels, data->sd->channels, "strength", NULL);
|
||||
|
||||
bool do_test = brush->mtex.brush_map_mode != MTEX_MAP_MODE_ROLL &&
|
||||
brush->mtex.brush_map_mode != MTEX_MAP_MODE_ROLL;
|
||||
|
||||
BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
|
||||
// SCULPT_orig_vert_data_update(&orig_data, vd.vertex);
|
||||
SCULPT_vertex_check_origdata(ss, vd.vertex);
|
||||
|
@ -163,7 +166,8 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
|
|||
bool affect_vertex = false;
|
||||
float distance_to_stroke_location = 0.0f;
|
||||
if (brush->tip_roundness < 1.0f) {
|
||||
affect_vertex = SCULPT_brush_test_cube(&test, vd.co, data->mat, brush->tip_roundness);
|
||||
affect_vertex = SCULPT_brush_test_cube(
|
||||
&test, vd.co, data->mat, brush->tip_roundness, brush->falloff_shape != PAINT_FALLOFF_SHAPE_TUBE);
|
||||
distance_to_stroke_location = ss->cache->radius * test.dist;
|
||||
}
|
||||
else {
|
||||
|
@ -171,7 +175,7 @@ static void do_paint_brush_task_cb_ex(void *__restrict userdata,
|
|||
distance_to_stroke_location = sqrtf(test.dist);
|
||||
}
|
||||
|
||||
if (!affect_vertex) {
|
||||
if (do_test && !affect_vertex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -251,7 +255,7 @@ static void do_sample_wet_paint_task_cb(void *__restrict userdata,
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
|
||||
test.radius *= data->brush->wet_paint_radius_factor;
|
||||
|
@ -467,7 +471,7 @@ static void do_smear_brush_task_cb_exec(void *__restrict userdata,
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
|
|
@ -221,7 +221,7 @@ template<typename ImageBuffer> class PaintingKernel {
|
|||
}
|
||||
void init_brush_test()
|
||||
{
|
||||
brush_test_fn = SCULPT_brush_test_init_with_falloff_shape(ss, &test, brush->falloff_shape);
|
||||
brush_test_fn = SCULPT_brush_test_init(ss, &test, (eBrushFalloffShape)brush->falloff_shape);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -269,7 +269,7 @@ static std::vector<bool> init_triangle_brush_test(SculptSession *ss,
|
|||
{
|
||||
std::vector<bool> brush_test(triangles.size());
|
||||
SculptBrushTest test;
|
||||
SCULPT_brush_test_init(ss, &test);
|
||||
SCULPT_brush_test_init(ss, &test, PAINT_FALLOFF_NOOP);
|
||||
float3 brush_min_bounds(test.location[0] - test.radius,
|
||||
test.location[1] - test.radius,
|
||||
test.location[2] - test.radius);
|
||||
|
|
|
@ -1481,7 +1481,7 @@ static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata,
|
|||
CLAMP(bstrength, -1.0f, 1.0f);
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
@ -1523,7 +1523,7 @@ static void do_enhance_details_brush_dir_task_cb_ex(void *__restrict userdata,
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
|
||||
SculptCustomLayer *strokeid_scl = data->scl2;
|
||||
|
@ -1577,7 +1577,7 @@ static void do_enhance_details_brush_dir2_task_cb_ex(void *__restrict userdata,
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
|
||||
// SculptCustomLayer *strokeid_scl = data->scl2;
|
||||
|
@ -1832,7 +1832,7 @@ static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
|
|||
CLAMP(bstrength, 0.0f, 1.0f);
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
@ -2254,7 +2254,7 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex(
|
|||
SculptOrigVertData orig_data;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -2333,7 +2333,7 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex(
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -2404,7 +2404,7 @@ static void SCULPT_do_directional_smooth_task_cb_ex(void *__restrict userdata,
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -2505,7 +2505,7 @@ static void SCULPT_do_uniform_weigths_smooth_task_cb_ex(void *__restrict userdat
|
|||
PBVHVertexIter vd;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
@ -2619,7 +2619,7 @@ static void do_smooth_vcol_boundary_brush_task_cb_ex(void *__restrict userdata,
|
|||
CLAMP(bstrength, 0.0f, 1.0f);
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, data->brush->falloff_shape);
|
||||
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
|
|
@ -219,7 +219,7 @@ static void do_shape_symmetrize_brush_task_cb(void *__restrict userdata,
|
|||
const Brush *brush = data->brush;
|
||||
|
||||
SculptBrushTest test;
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
|
||||
SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init(
|
||||
ss, &test, brush->falloff_shape);
|
||||
const int thread_id = BLI_task_parallel_thread_id(tls);
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ struct TableGSet;
|
|||
struct MLoop;
|
||||
struct MLoopCol;
|
||||
struct MLoopTri;
|
||||
struct MSculptVert;
|
||||
struct MPoly;
|
||||
struct MPropCol;
|
||||
struct MVert;
|
||||
|
@ -119,7 +120,8 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
|||
const int face_sets_color_seed,
|
||||
const int face_sets_color_default,
|
||||
const int update_flags,
|
||||
const float (*vert_normals)[3]);
|
||||
const float (*vert_normals)[3],
|
||||
struct MSculptVert *sverts);
|
||||
|
||||
bool GPU_pbvh_update_attribute_names(
|
||||
const CustomData *vdata,
|
||||
|
|
|
@ -128,6 +128,7 @@ typedef struct PBVHGPUFormat {
|
|||
} PBVHGPUFormat;
|
||||
|
||||
static PBVHGPUFormat g_vbo_id = {{0}};
|
||||
bool pbvh_show_orig_co = false;
|
||||
|
||||
static int gpu_pbvh_make_attr_offs(AttributeDomainMask domain_mask,
|
||||
CustomDataMask type_mask,
|
||||
|
@ -253,7 +254,8 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
|||
const int face_sets_color_seed,
|
||||
const int face_sets_color_default,
|
||||
const int update_flags,
|
||||
const float (*vert_normals)[3])
|
||||
const float (*vert_normals)[3],
|
||||
MSculptVert *sverts)
|
||||
{
|
||||
GPUAttrRef vcol_refs[MAX_GPU_ATTR];
|
||||
GPUAttrRef cd_uvs[MAX_GPU_ATTR];
|
||||
|
@ -297,184 +299,188 @@ void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers,
|
|||
bool empty_mask = true;
|
||||
bool default_face_set = true;
|
||||
|
||||
{
|
||||
const int totelem = buffers->tot_tri * 3;
|
||||
const int totelem = buffers->tot_tri * 3;
|
||||
|
||||
/* Build VBO */
|
||||
if (gpu_pbvh_vert_buf_data_set(buffers, totelem)) {
|
||||
GPUVertBufRaw pos_step = {0};
|
||||
GPUVertBufRaw nor_step = {0};
|
||||
GPUVertBufRaw msk_step = {0};
|
||||
GPUVertBufRaw fset_step = {0};
|
||||
GPUVertBufRaw col_step = {0};
|
||||
GPUVertBufRaw uv_step = {0};
|
||||
/* Build VBO */
|
||||
if (gpu_pbvh_vert_buf_data_set(buffers, totelem)) {
|
||||
GPUVertBufRaw pos_step = {0};
|
||||
GPUVertBufRaw nor_step = {0};
|
||||
GPUVertBufRaw msk_step = {0};
|
||||
GPUVertBufRaw fset_step = {0};
|
||||
GPUVertBufRaw col_step = {0};
|
||||
GPUVertBufRaw uv_step = {0};
|
||||
|
||||
GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, g_vbo_id.pos, &pos_step);
|
||||
GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, g_vbo_id.nor, &nor_step);
|
||||
GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, g_vbo_id.msk, &msk_step);
|
||||
GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, g_vbo_id.fset, &fset_step);
|
||||
GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, g_vbo_id.pos, &pos_step);
|
||||
GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, g_vbo_id.nor, &nor_step);
|
||||
GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, g_vbo_id.msk, &msk_step);
|
||||
GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, g_vbo_id.fset, &fset_step);
|
||||
|
||||
/* calculate normal for each polygon only once */
|
||||
uint mpoly_prev = UINT_MAX;
|
||||
short no[3] = {0, 0, 0};
|
||||
/* calculate normal for each polygon only once */
|
||||
uint mpoly_prev = UINT_MAX;
|
||||
short no[3] = {0, 0, 0};
|
||||
|
||||
if (cd_uv_count > 0) {
|
||||
for (int uv_i = 0; uv_i < cd_uv_count; uv_i++) {
|
||||
GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, g_vbo_id.uv[uv_i], &uv_step);
|
||||
if (cd_uv_count > 0) {
|
||||
for (int uv_i = 0; uv_i < cd_uv_count; uv_i++) {
|
||||
GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, g_vbo_id.uv[uv_i], &uv_step);
|
||||
|
||||
GPUAttrRef *ref = cd_uvs + uv_i;
|
||||
CustomDataLayer *layer = ldata->layers + ref->layer_idx;
|
||||
MLoopUV *muv = layer->data;
|
||||
GPUAttrRef *ref = cd_uvs + uv_i;
|
||||
CustomDataLayer *layer = ldata->layers + ref->layer_idx;
|
||||
MLoopUV *muv = layer->data;
|
||||
|
||||
for (uint i = 0; i < buffers->face_indices_len; i++) {
|
||||
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
|
||||
for (uint i = 0; i < buffers->face_indices_len; i++) {
|
||||
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
|
||||
|
||||
if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (uint j = 0; j < 3; j++) {
|
||||
MLoopUV *muv2 = muv + lt->tri[j];
|
||||
|
||||
memcpy(GPU_vertbuf_raw_step(&uv_step), muv2->uv, sizeof(muv2->uv));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (show_vcol) {
|
||||
for (int col_i = 0; col_i < totcol; col_i++) {
|
||||
GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, g_vbo_id.col[col_i], &col_step);
|
||||
|
||||
MPropCol *pcol = NULL;
|
||||
MLoopCol *mcol = NULL;
|
||||
|
||||
GPUAttrRef *ref = vcol_refs + col_i;
|
||||
const CustomData *cdata = ref->domain == ATTR_DOMAIN_POINT ? vdata : ldata;
|
||||
CustomDataLayer *layer = cdata->layers + ref->layer_idx;
|
||||
|
||||
bool color_loops = ref->domain == ATTR_DOMAIN_CORNER;
|
||||
|
||||
if (layer->type == CD_PROP_COLOR) {
|
||||
pcol = (MPropCol *)layer->data;
|
||||
}
|
||||
else {
|
||||
mcol = (MLoopCol *)layer->data;
|
||||
if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < buffers->face_indices_len; i++) {
|
||||
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
|
||||
const uint vtri[3] = {
|
||||
buffers->mloop[lt->tri[0]].v,
|
||||
buffers->mloop[lt->tri[1]].v,
|
||||
buffers->mloop[lt->tri[2]].v,
|
||||
};
|
||||
for (uint j = 0; j < 3; j++) {
|
||||
MLoopUV *muv2 = muv + lt->tri[j];
|
||||
|
||||
if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (uint j = 0; j < 3; j++) {
|
||||
/* Vertex Colors. */
|
||||
if (show_vcol) {
|
||||
ushort scol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX};
|
||||
if (pcol) {
|
||||
if (color_loops) {
|
||||
scol[0] = unit_float_to_ushort_clamp(pcol[lt->tri[j]].color[0]);
|
||||
scol[1] = unit_float_to_ushort_clamp(pcol[lt->tri[j]].color[1]);
|
||||
scol[2] = unit_float_to_ushort_clamp(pcol[lt->tri[j]].color[2]);
|
||||
scol[3] = unit_float_to_ushort_clamp(pcol[lt->tri[j]].color[3]);
|
||||
}
|
||||
else {
|
||||
scol[0] = unit_float_to_ushort_clamp(pcol[vtri[j]].color[0]);
|
||||
scol[1] = unit_float_to_ushort_clamp(pcol[vtri[j]].color[1]);
|
||||
scol[2] = unit_float_to_ushort_clamp(pcol[vtri[j]].color[2]);
|
||||
scol[3] = unit_float_to_ushort_clamp(pcol[vtri[j]].color[3]);
|
||||
}
|
||||
|
||||
memcpy(GPU_vertbuf_raw_step(&col_step), scol, sizeof(scol));
|
||||
}
|
||||
else if (mcol) {
|
||||
const uint loop_index = lt->tri[j];
|
||||
const MLoopCol *mcol2 = mcol + (color_loops ? loop_index : vtri[j]);
|
||||
|
||||
scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->r]);
|
||||
scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->g]);
|
||||
scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->b]);
|
||||
scol[3] = unit_float_to_ushort_clamp(mcol2->a * (1.0f / 255.0f));
|
||||
memcpy(GPU_vertbuf_raw_step(&col_step), scol, sizeof(scol));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint i = 0; i < buffers->face_indices_len; i++) {
|
||||
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
|
||||
const uint vtri[3] = {
|
||||
buffers->mloop[lt->tri[0]].v,
|
||||
buffers->mloop[lt->tri[1]].v,
|
||||
buffers->mloop[lt->tri[2]].v,
|
||||
};
|
||||
|
||||
if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Face normal and mask */
|
||||
if (lt->poly != mpoly_prev && !buffers->smooth) {
|
||||
const MPoly *mp = &buffers->mpoly[lt->poly];
|
||||
float fno[3];
|
||||
BKE_mesh_calc_poly_normal(mp, &buffers->mloop[mp->loopstart], mvert, fno);
|
||||
normal_float_to_short_v3(no, fno);
|
||||
mpoly_prev = lt->poly;
|
||||
}
|
||||
|
||||
uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
|
||||
if (show_face_sets) {
|
||||
const int fset = abs(sculpt_face_sets[lt->poly]);
|
||||
/* Skip for the default color Face Set to render it white. */
|
||||
if (fset != face_sets_color_default) {
|
||||
BKE_paint_face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color);
|
||||
default_face_set = false;
|
||||
}
|
||||
}
|
||||
|
||||
float fmask = 0.0f;
|
||||
uchar cmask = 0;
|
||||
if (show_mask && !buffers->smooth) {
|
||||
fmask = (vmask[vtri[0]] + vmask[vtri[1]] + vmask[vtri[2]]) / 3.0f;
|
||||
cmask = (uchar)(fmask * 255);
|
||||
}
|
||||
|
||||
for (uint j = 0; j < 3; j++) {
|
||||
const MVert *v = &mvert[vtri[j]];
|
||||
copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), v->co);
|
||||
|
||||
if (buffers->smooth) {
|
||||
normal_float_to_short_v3(no, vert_normals[vtri[j]]);
|
||||
}
|
||||
copy_v3_v3_short(GPU_vertbuf_raw_step(&nor_step), no);
|
||||
|
||||
if (show_mask && buffers->smooth) {
|
||||
cmask = (uchar)(vmask[vtri[j]] * 255);
|
||||
}
|
||||
|
||||
*(uchar *)GPU_vertbuf_raw_step(&msk_step) = cmask;
|
||||
empty_mask = empty_mask && (cmask == 0);
|
||||
|
||||
if (!g_vbo_id.fast_mode) {
|
||||
/* Face Sets. */
|
||||
memcpy(GPU_vertbuf_raw_step(&fset_step), face_set_color, sizeof(uchar[3]));
|
||||
memcpy(GPU_vertbuf_raw_step(&uv_step), muv2->uv, sizeof(muv2->uv));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
|
||||
if (show_vcol) {
|
||||
for (int col_i = 0; col_i < totcol; col_i++) {
|
||||
GPU_vertbuf_attr_get_raw_data(buffers->vert_buf, g_vbo_id.col[col_i], &col_step);
|
||||
|
||||
MPropCol *pcol = NULL;
|
||||
MLoopCol *mcol = NULL;
|
||||
|
||||
GPUAttrRef *ref = vcol_refs + col_i;
|
||||
const CustomData *cdata = ref->domain == ATTR_DOMAIN_POINT ? vdata : ldata;
|
||||
CustomDataLayer *layer = cdata->layers + ref->layer_idx;
|
||||
|
||||
bool color_loops = ref->domain == ATTR_DOMAIN_CORNER;
|
||||
|
||||
if (layer->type == CD_PROP_COLOR) {
|
||||
pcol = (MPropCol *)layer->data;
|
||||
}
|
||||
else {
|
||||
mcol = (MLoopCol *)layer->data;
|
||||
}
|
||||
|
||||
for (uint i = 0; i < buffers->face_indices_len; i++) {
|
||||
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
|
||||
const uint vtri[3] = {
|
||||
buffers->mloop[lt->tri[0]].v,
|
||||
buffers->mloop[lt->tri[1]].v,
|
||||
buffers->mloop[lt->tri[2]].v,
|
||||
};
|
||||
|
||||
if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (uint j = 0; j < 3; j++) {
|
||||
/* Vertex Colors. */
|
||||
if (show_vcol) {
|
||||
ushort scol[4] = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX};
|
||||
if (pcol) {
|
||||
if (color_loops) {
|
||||
scol[0] = unit_float_to_ushort_clamp(pcol[lt->tri[j]].color[0]);
|
||||
scol[1] = unit_float_to_ushort_clamp(pcol[lt->tri[j]].color[1]);
|
||||
scol[2] = unit_float_to_ushort_clamp(pcol[lt->tri[j]].color[2]);
|
||||
scol[3] = unit_float_to_ushort_clamp(pcol[lt->tri[j]].color[3]);
|
||||
}
|
||||
else {
|
||||
scol[0] = unit_float_to_ushort_clamp(pcol[vtri[j]].color[0]);
|
||||
scol[1] = unit_float_to_ushort_clamp(pcol[vtri[j]].color[1]);
|
||||
scol[2] = unit_float_to_ushort_clamp(pcol[vtri[j]].color[2]);
|
||||
scol[3] = unit_float_to_ushort_clamp(pcol[vtri[j]].color[3]);
|
||||
}
|
||||
|
||||
memcpy(GPU_vertbuf_raw_step(&col_step), scol, sizeof(scol));
|
||||
}
|
||||
else if (mcol) {
|
||||
const uint loop_index = lt->tri[j];
|
||||
const MLoopCol *mcol2 = mcol + (color_loops ? loop_index : vtri[j]);
|
||||
|
||||
scol[0] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->r]);
|
||||
scol[1] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->g]);
|
||||
scol[2] = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol2->b]);
|
||||
scol[3] = unit_float_to_ushort_clamp(mcol2->a * (1.0f / 255.0f));
|
||||
memcpy(GPU_vertbuf_raw_step(&col_step), scol, sizeof(scol));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint i = 0; i < buffers->face_indices_len; i++) {
|
||||
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
|
||||
const uint vtri[3] = {
|
||||
buffers->mloop[lt->tri[0]].v,
|
||||
buffers->mloop[lt->tri[1]].v,
|
||||
buffers->mloop[lt->tri[2]].v,
|
||||
};
|
||||
|
||||
if (!gpu_pbvh_is_looptri_visible(lt, mvert, buffers->mloop, sculpt_face_sets)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Face normal and mask */
|
||||
if (lt->poly != mpoly_prev && !buffers->smooth) {
|
||||
const MPoly *mp = &buffers->mpoly[lt->poly];
|
||||
float fno[3];
|
||||
BKE_mesh_calc_poly_normal(mp, &buffers->mloop[mp->loopstart], mvert, fno);
|
||||
normal_float_to_short_v3(no, fno);
|
||||
mpoly_prev = lt->poly;
|
||||
}
|
||||
|
||||
uchar face_set_color[4] = {UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX};
|
||||
if (show_face_sets) {
|
||||
const int fset = abs(sculpt_face_sets[lt->poly]);
|
||||
/* Skip for the default color Face Set to render it white. */
|
||||
if (fset != face_sets_color_default) {
|
||||
BKE_paint_face_set_overlay_color_get(fset, face_sets_color_seed, face_set_color);
|
||||
default_face_set = false;
|
||||
}
|
||||
}
|
||||
|
||||
float fmask = 0.0f;
|
||||
uchar cmask = 0;
|
||||
if (show_mask && !buffers->smooth) {
|
||||
fmask = (vmask[vtri[0]] + vmask[vtri[1]] + vmask[vtri[2]]) / 3.0f;
|
||||
cmask = (uchar)(fmask * 255);
|
||||
}
|
||||
|
||||
for (uint j = 0; j < 3; j++) {
|
||||
const MVert *v = &mvert[vtri[j]];
|
||||
|
||||
if (pbvh_show_orig_co) {
|
||||
copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), sverts[vtri[j]].origco);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(GPU_vertbuf_raw_step(&pos_step), v->co);
|
||||
}
|
||||
|
||||
if (buffers->smooth) {
|
||||
normal_float_to_short_v3(no, vert_normals[vtri[j]]);
|
||||
}
|
||||
copy_v3_v3_short(GPU_vertbuf_raw_step(&nor_step), no);
|
||||
|
||||
if (show_mask && buffers->smooth) {
|
||||
cmask = (uchar)(vmask[vtri[j]] * 255);
|
||||
}
|
||||
|
||||
*(uchar *)GPU_vertbuf_raw_step(&msk_step) = cmask;
|
||||
empty_mask = empty_mask && (cmask == 0);
|
||||
|
||||
if (!g_vbo_id.fast_mode) {
|
||||
/* Face Sets. */
|
||||
memcpy(GPU_vertbuf_raw_step(&fset_step), face_set_color, sizeof(uchar[3]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS);
|
||||
|
||||
/* Get material index from the first face of this buffer. */
|
||||
const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
|
||||
const MPoly *mp = &buffers->mpoly[lt->poly];
|
||||
|
@ -948,7 +954,6 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hid
|
|||
* \{ */
|
||||
|
||||
static int debug_pass = 0;
|
||||
bool pbvh_show_orig_co = false;
|
||||
|
||||
static void gpu_bmesh_get_vcol(BMVert *v, BMLoop *l, const GPUAttrRef *ref, float color[4])
|
||||
{
|
||||
|
|
|
@ -337,7 +337,7 @@ typedef enum eAutomasking_flag {
|
|||
BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS = (1 << 3),
|
||||
BRUSH_AUTOMASKING_CONCAVITY = (1 << 4),
|
||||
BRUSH_AUTOMASKING_INVERT_CONCAVITY = (1 << 5),
|
||||
BRUSH_AUTOMASKING_BRUSH_NORMAL = (1<<6),
|
||||
BRUSH_AUTOMASKING_BRUSH_NORMAL = (1 << 6),
|
||||
BRUSH_AUTOMASKING_VIEW_NORMAL = (1 << 7),
|
||||
} eAutomasking_flag;
|
||||
|
||||
|
@ -660,6 +660,7 @@ typedef enum eBlurKernelType {
|
|||
typedef enum eBrushFalloffShape {
|
||||
PAINT_FALLOFF_SHAPE_SPHERE = 0,
|
||||
PAINT_FALLOFF_SHAPE_TUBE = 1,
|
||||
PAINT_FALLOFF_NOOP = 2,
|
||||
} eBrushFalloffShape;
|
||||
|
||||
// dyntopo flags
|
||||
|
|
|
@ -73,7 +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", ""},
|
||||
{MTEX_MAP_MODE_ROLL, "ROLL", 0, "Roll", ""},
|
||||
{0, NULL, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue