Support more mapping modes for alpha masks. Tiled, stencil and random

This commit is contained in:
Antony Riakiotakis 2013-04-22 10:46:01 +00:00
parent 53479be581
commit c0eadedb70
4 changed files with 111 additions and 35 deletions

@ -67,7 +67,7 @@ int BKE_brush_clone_image_delete(struct Brush *brush);
/* jitter */ /* jitter */
void BKE_brush_jitter_pos(const struct Scene *scene, struct Brush *brush, void BKE_brush_jitter_pos(const struct Scene *scene, struct Brush *brush,
const float pos[2], float jitterpos[2]); const float pos[2], float jitterpos[2]);
void BKE_brush_randomize_texture_coordinates(struct UnifiedPaintSettings *ups); void BKE_brush_randomize_texture_coordinates(struct UnifiedPaintSettings *ups, bool mask);
/* brush curve */ /* brush curve */
void BKE_brush_curve_preset(struct Brush *b, int preset); void BKE_brush_curve_preset(struct Brush *b, int preset);

@ -560,11 +560,11 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
x /= (br->stencil_dimension[0]); x /= (br->stencil_dimension[0]);
y /= (br->stencil_dimension[1]); y /= (br->stencil_dimension[1]);
x *= br->mtex.size[0]; x *= mtex->size[0];
y *= br->mtex.size[1]; y *= mtex->size[1];
co[0] = x + br->mtex.ofs[0]; co[0] = x + mtex->ofs[0];
co[1] = y + br->mtex.ofs[1]; co[1] = y + mtex->ofs[1];
co[2] = 0.0f; co[2] = 0.0f;
hasrgb = externtex(mtex, co, &intensity, hasrgb = externtex(mtex, co, &intensity,
@ -620,11 +620,11 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
y = flen * sinf(angle); y = flen * sinf(angle);
} }
x *= br->mtex.size[0]; x *= mtex->size[0];
y *= br->mtex.size[1]; y *= mtex->size[1];
co[0] = x + br->mtex.ofs[0]; co[0] = x + mtex->ofs[0];
co[1] = y + br->mtex.ofs[1]; co[1] = y + mtex->ofs[1];
co[2] = 0.0f; co[2] = 0.0f;
hasrgb = externtex(mtex, co, &intensity, hasrgb = externtex(mtex, co, &intensity,
@ -650,26 +650,83 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
{ {
UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings;
MTex *mtex = &br->mask_mtex; MTex *mtex = &br->mask_mtex;
float rgba[4], intensity;
if (mtex && mtex->tex) { if (!mtex->tex) {
return 1.0f;
}
if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) {
float rotation = -mtex->rot; float rotation = -mtex->rot;
float point_2d[2] = {point[0], point[1]}; float point_2d[2] = {point[0], point[1]};
float x = 0.0f, y = 0.0f; /* Quite warnings */ float x = 0.0f, y = 0.0f; /* Quite warnings */
float radius = 1.0f; /* Quite warnings */
float co[3]; float co[3];
float rgba[4], intensity = 1.0;
point_2d[0] -= ups->tex_mouse[0]; x = point_2d[0] - br->stencil_pos[0];
point_2d[1] -= ups->tex_mouse[1]; y = point_2d[1] - br->stencil_pos[1];
/* use pressure adjusted size for fixed mode */ if (rotation > 0.001f || rotation < -0.001f) {
radius = ups->pixel_radius; const float angle = atan2f(y, x) + rotation;
const float flen = sqrtf(x * x + y * y);
x = point_2d[0]; x = flen * cosf(angle);
y = point_2d[1]; y = flen * sinf(angle);
}
x /= radius; if (fabsf(x) > br->stencil_dimension[0] || fabsf(y) > br->stencil_dimension[1]) {
y /= radius; zero_v4(rgba);
return 0.0f;
}
x /= (br->stencil_dimension[0]);
y /= (br->stencil_dimension[1]);
x *= mtex->size[0];
y *= mtex->size[1];
co[0] = x + mtex->ofs[0];
co[1] = y + mtex->ofs[1];
co[2] = 0.0f;
externtex(mtex, co, &intensity,
rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
}
else {
float rotation = -mtex->rot;
float point_2d[2] = {point[0], point[1]};
float x = 0.0f, y = 0.0f; /* Quite warnings */
float invradius = 1.0f; /* Quite warnings */
float co[3];
if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) {
/* keep coordinates relative to mouse */
rotation += ups->brush_rotation;
x = point_2d[0] - ups->mask_tex_mouse[0];
y = point_2d[1] - ups->mask_tex_mouse[1];
/* use pressure adjusted size for fixed mode */
invradius = 1.0f / ups->pixel_radius;
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) {
/* leave the coordinates relative to the screen */
/* use unadjusted size for tiled mode */
invradius = 1.0f / BKE_brush_size_get(scene, br);
x = point_2d[0];
y = point_2d[1];
}
else if (mtex->brush_map_mode == MTEX_MAP_MODE_RANDOM) {
rotation += ups->brush_rotation;
/* these contain a random coordinate */
x = point_2d[0] - ups->mask_tex_mouse[0];
y = point_2d[1] - ups->mask_tex_mouse[1];
invradius = 1.0f / ups->pixel_radius;
}
x *= invradius;
y *= invradius;
/* it is probably worth optimizing for those cases where /* it is probably worth optimizing for those cases where
* the texture is not rotated by skipping the calls to * the texture is not rotated by skipping the calls to
@ -682,21 +739,18 @@ float BKE_brush_sample_masktex(const Scene *scene, Brush *br,
y = flen * sinf(angle); y = flen * sinf(angle);
} }
x *= br->mask_mtex.size[0]; x *= mtex->size[0];
y *= br->mask_mtex.size[1]; y *= mtex->size[1];
co[0] = x + br->mask_mtex.ofs[0]; co[0] = x + mtex->ofs[0];
co[1] = y + br->mask_mtex.ofs[1]; co[1] = y + mtex->ofs[1];
co[2] = 0.0f; co[2] = 0.0f;
externtex(mtex, co, &intensity, externtex(mtex, co, &intensity,
rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool); rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
}
return intensity; return intensity;
}
else {
return 1.0f;
}
} }
/* Brush Sampling for 2D brushes. when we unify the brush systems this will be necessarily a separate function */ /* Brush Sampling for 2D brushes. when we unify the brush systems this will be necessarily a separate function */
@ -1044,12 +1098,18 @@ void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2],
} }
} }
void BKE_brush_randomize_texture_coordinates(UnifiedPaintSettings *ups) void BKE_brush_randomize_texture_coordinates(UnifiedPaintSettings *ups, bool mask)
{ {
/* we multiply with brush radius as an optimization for the brush /* we multiply with brush radius as an optimization for the brush
* texture sampling functions */ * texture sampling functions */
ups->tex_mouse[0] = BLI_rng_get_float(brush_rng) * ups->pixel_radius; if (mask) {
ups->tex_mouse[1] = BLI_rng_get_float(brush_rng) * ups->pixel_radius; ups->mask_tex_mouse[0] = BLI_rng_get_float(brush_rng) * ups->pixel_radius;
ups->mask_tex_mouse[1] = BLI_rng_get_float(brush_rng) * ups->pixel_radius;
}
else {
ups->tex_mouse[0] = BLI_rng_get_float(brush_rng) * ups->pixel_radius;
ups->tex_mouse[1] = BLI_rng_get_float(brush_rng) * ups->pixel_radius;
}
} }
/* Uses the brush curve control to find a strength value between 0 and 1 */ /* Uses the brush curve control to find a strength value between 0 and 1 */

@ -160,6 +160,7 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
if (paint_supports_dynamic_size(brush, mode) || !stroke->brush_init) { if (paint_supports_dynamic_size(brush, mode) || !stroke->brush_init) {
copy_v2_v2(stroke->initial_mouse, mouse); copy_v2_v2(stroke->initial_mouse, mouse);
copy_v2_v2(ups->tex_mouse, mouse); copy_v2_v2(ups->tex_mouse, mouse);
copy_v2_v2(ups->mask_tex_mouse, mouse);
stroke->cached_pressure = pressure; stroke->cached_pressure = pressure;
} }
@ -186,11 +187,22 @@ static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode,
} }
if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM) if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
BKE_brush_randomize_texture_coordinates(ups); BKE_brush_randomize_texture_coordinates(ups, false);
else else {
copy_v2_v2(ups->tex_mouse, mouse); copy_v2_v2(ups->tex_mouse, mouse);
}
} }
/* take care of mask texture, if any */
if (brush->mask_mtex.tex) {
if (brush->mask_mtex.brush_map_mode == MTEX_MAP_MODE_RANDOM)
BKE_brush_randomize_texture_coordinates(ups, true);
else {
copy_v2_v2(ups->mask_tex_mouse, mouse);
}
}
if (brush->flag & BRUSH_ANCHORED) { if (brush->flag & BRUSH_ANCHORED) {
bool hit = false; bool hit = false;
float halfway[2]; float halfway[2];

@ -914,6 +914,10 @@ typedef struct UnifiedPaintSettings {
/* position of mouse, used to sample the texture */ /* position of mouse, used to sample the texture */
float tex_mouse[2]; float tex_mouse[2];
/* position of mouse, used to sample the mask texture */
float mask_tex_mouse[2];
/* radius of brush, premultiplied with pressure. /* radius of brush, premultiplied with pressure.
* In case of anchored brushes contains that radius */ * In case of anchored brushes contains that radius */
float pixel_radius; float pixel_radius;