Support more mapping modes for alpha masks. Tiled, stencil and random
authorAntony Riakiotakis <kalast@gmail.com>
Mon, 22 Apr 2013 10:46:01 +0000 (10:46 +0000)
committerAntony Riakiotakis <kalast@gmail.com>
Mon, 22 Apr 2013 10:46:01 +0000 (10:46 +0000)
source/blender/blenkernel/BKE_brush.h
source/blender/blenkernel/intern/brush.c
source/blender/editors/sculpt_paint/paint_stroke.c
source/blender/makesdna/DNA_scene_types.h

index 503c7a7f435a64fbab58e13b32eae2ce41603ab9..452030d05e6d21319a38877796d1d3ef792147c2 100644 (file)
@@ -67,7 +67,7 @@ int BKE_brush_clone_image_delete(struct Brush *brush);
 /* jitter */
 void BKE_brush_jitter_pos(const struct Scene *scene, struct Brush *brush,
                           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 */
 void BKE_brush_curve_preset(struct Brush *b, int preset);
index dd299be97643a1831996f5c836fea5bd668873d9..064e902f83134e75f423dd0bb7383eddeb26590c 100644 (file)
@@ -560,11 +560,11 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
                x /= (br->stencil_dimension[0]);
                y /= (br->stencil_dimension[1]);
 
-               x *= br->mtex.size[0];
-               y *= br->mtex.size[1];
+               x *= mtex->size[0];
+               y *= mtex->size[1];
 
-               co[0] = x + br->mtex.ofs[0];
-               co[1] = y + br->mtex.ofs[1];
+               co[0] = x + mtex->ofs[0];
+               co[1] = y + mtex->ofs[1];
                co[2] = 0.0f;
 
                hasrgb = externtex(mtex, co, &intensity,
@@ -620,11 +620,11 @@ float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br,
                        y = flen * sinf(angle);
                }
 
-               x *= br->mtex.size[0];
-               y *= br->mtex.size[1];
+               x *= mtex->size[0];
+               y *= mtex->size[1];
 
-               co[0] = x + br->mtex.ofs[0];
-               co[1] = y + br->mtex.ofs[1];
+               co[0] = x + mtex->ofs[0];
+               co[1] = y + mtex->ofs[1];
                co[2] = 0.0f;
 
                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;
        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 point_2d[2] = {point[0], point[1]};
                float x = 0.0f, y = 0.0f; /* Quite warnings */
-               float radius = 1.0f; /* Quite warnings */
                float co[3];
-               float rgba[4], intensity = 1.0;
 
-               point_2d[0] -= ups->tex_mouse[0];
-               point_2d[1] -= ups->tex_mouse[1];
+               x = point_2d[0] - br->stencil_pos[0];
+               y = point_2d[1] - br->stencil_pos[1];
 
-               /* use pressure adjusted size for fixed mode */
-               radius = ups->pixel_radius;
+               if (rotation > 0.001f || rotation < -0.001f) {
+                       const float angle    = atan2f(y, x) + rotation;
+                       const float flen     = sqrtf(x * x + y * y);
 
-               x = point_2d[0];
-               y = point_2d[1];
+                       x = flen * cosf(angle);
+                       y = flen * sinf(angle);
+               }
 
-               x /= radius;
-               y /= radius;
+               if (fabsf(x) > br->stencil_dimension[0] || fabsf(y) > br->stencil_dimension[1]) {
+                       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
                 * 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);
                }
 
-               x *= br->mask_mtex.size[0];
-               y *= br->mask_mtex.size[1];
+               x *= mtex->size[0];
+               y *= mtex->size[1];
 
-               co[0] = x + br->mask_mtex.ofs[0];
-               co[1] = y + br->mask_mtex.ofs[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);
-
-               return intensity;
-       }
-       else {
-               return 1.0f;
+                         rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool);
        }
+
+       return intensity;
 }
 
 /* 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
         * texture sampling functions */
-       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;
+       if (mask) {
+               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 */
index bbddd2e4a69cd7a351412ceee71480148ee6804e..d754567bd992a1cf516ec194fdde295c60c3fccc 100644 (file)
@@ -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) {
                copy_v2_v2(stroke->initial_mouse, mouse);
                copy_v2_v2(ups->tex_mouse, mouse);
+               copy_v2_v2(ups->mask_tex_mouse, mouse);
                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)
-                       BKE_brush_randomize_texture_coordinates(ups);
-               else
+                       BKE_brush_randomize_texture_coordinates(ups, false);
+               else {
                        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) {
                bool hit = false;
                float halfway[2];
index e5127e51d1377a7c3e9e1b88cdfe6e703d046f80..eb8c8138e850ea65ffa439905a14d268223bd921 100644 (file)
@@ -914,6 +914,10 @@ typedef struct UnifiedPaintSettings {
 
        /* position of mouse, used to sample the texture */
        float tex_mouse[2];
+
+       /* position of mouse, used to sample the mask texture */
+       float mask_tex_mouse[2];
+
        /* radius of brush, premultiplied with pressure.
         * In case of anchored brushes contains that radius */
        float pixel_radius;