Merging r48971 through r48980 from trunk into soc-2011-tomato
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 16 Jul 2012 17:58:23 +0000 (17:58 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 16 Jul 2012 17:58:23 +0000 (17:58 +0000)
source/blender/blenkernel/intern/mask.c
source/blender/blenkernel/intern/mask_rasterize.c
source/blender/blenkernel/intern/multires.c
source/blender/blenlib/BLI_math_geom.h
source/blender/blenlib/intern/math_geom.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/space_node/node_edit.c

index 7ec8f1571f2e2f2e8ddeec1fcb03f0607d07732a..86838c5565aad3c0fea3bdd08514bf76b203dc6f 100644 (file)
@@ -416,6 +416,140 @@ float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[
        return BKE_mask_spline_differentiate_with_resolution(spline, 0, 0, tot_diff_point);
 }
 
+/* ** feather points self-intersection collapse routine ** */
+
+typedef struct FeatherEdgesBucket {
+       int tot_segment;
+       int (*segments)[2];
+       int alloc_segment;
+} FeatherEdgesBucket;
+
+static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int end)
+{
+       const int alloc_delta = 20;
+
+       if (bucket->tot_segment >= bucket->alloc_segment) {
+               if (!bucket->segments) {
+                       bucket->segments = MEM_callocN(alloc_delta * sizeof(*bucket->segments), "feather bucket segments");
+               }
+               else {
+                       bucket->segments = MEM_reallocN(bucket->segments,
+                                       (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments));
+               }
+
+               bucket->alloc_segment += alloc_delta;
+       }
+
+       bucket->segments[bucket->tot_segment][0] = start;
+       bucket->segments[bucket->tot_segment][1] = end;
+
+       bucket->tot_segment++;
+}
+
+static void feather_bucket_check_intersect(float (*feather_points)[2], FeatherEdgesBucket *bucket, int cur_a, int cur_b)
+{
+       int i;
+
+       float *v1 = (float *) feather_points[cur_a];
+       float *v2 = (float *) feather_points[cur_b];
+
+       for (i = 0; i< bucket->tot_segment; i++) {
+               int check_a = bucket->segments[i][0];
+               int check_b = bucket->segments[i][1];
+
+               float *v3 = (float *) feather_points[check_a];
+               float *v4 = (float *) feather_points[check_b];
+
+               if (check_a >= cur_a - 1 || cur_b == check_a)
+                       continue;
+
+               if (isect_seg_seg_v2(v1, v2, v3, v4)) {
+                       int k;
+                       float p[2];
+
+                       isect_seg_seg_v2_point(v1, v2, v3, v4, p);
+
+                       for (k = check_b; k <= cur_a; k++) {
+                               copy_v2_v2(feather_points[k], p);
+                       }
+
+                       break;
+               }
+       }
+}
+
+static void spline_feather_collapse_inner_loops(float (*feather_points)[2], int tot_feather_point)
+{
+#define BUCKET_SIDE_INDEX(co, min, max) ((int) ((co - min) / (max - min + FLT_EPSILON) / bucket_size))
+
+#define BUCKET_INDEX_DELTA(co, dx, dy) \
+       BUCKET_SIDE_INDEX(co[1] + dy, min[1], max[1]) * buckets_per_side + \
+               BUCKET_SIDE_INDEX(co[0] + dx, min[0], max[0])
+
+#define BUCKET_INDEX(co) BUCKET_INDEX_DELTA(co, 0, 0)
+
+       const int buckets_per_side = 10;
+       const int tot_bucket = buckets_per_side * buckets_per_side;
+       const float bucket_size = 1.0f / buckets_per_side;
+
+       FeatherEdgesBucket *buckets;
+
+       int i;
+       float min[2], max[2];
+
+       /* find min/max corners of mask to build buckets in that space */
+       INIT_MINMAX2(min, max);
+
+       for (i = 0; i < tot_feather_point; i++) {
+               DO_MINMAX2(feather_points[i], min, max);
+       }
+
+       /* fill in buckets' edges */
+       buckets = MEM_callocN(sizeof(FeatherEdgesBucket) * tot_bucket, "feather buckets");
+
+       for (i = 0; i < tot_feather_point; i++) {
+               int start = i;
+               int end = (i + 1) % tot_feather_point;
+
+               int start_bucket_index = BUCKET_INDEX(feather_points[start]);
+               int end_bucket_index = BUCKET_INDEX(feather_points[end]);
+
+               feather_bucket_add_edge(&buckets[start_bucket_index], start, end);
+
+               if (start_bucket_index != end_bucket_index) {
+                       feather_bucket_add_edge(&buckets[end_bucket_index], start, end);
+               }
+       }
+
+       /* check all edges for intersection with edges from their buckets */
+       for (i = 0; i < tot_feather_point; i++) {
+               int cur_a = i;
+               int cur_b = (i + 1) % tot_feather_point;
+
+               int start_bucket_index = BUCKET_INDEX(feather_points[cur_a]);
+               int end_bucket_index = BUCKET_INDEX(feather_points[cur_b]);
+
+               FeatherEdgesBucket *start_bucket = &buckets[start_bucket_index];
+               FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index];
+
+               feather_bucket_check_intersect(feather_points, start_bucket, cur_a, cur_b);
+
+               if (start_bucket != end_bucket)
+                       feather_bucket_check_intersect(feather_points, end_bucket, cur_a, cur_b);
+       }
+
+       /* free buckets */
+       for (i = 0; i < tot_bucket; i++) {
+               if (buckets[i].segments)
+                       MEM_freeN(buckets[i].segments);
+       }
+
+       MEM_freeN(buckets);
+
+#undef BUCKET_INDEX
+#undef BUCKET_SIZE_INDEX
+}
+
 /**
  * values align with #BKE_mask_spline_differentiate_with_resolution_ex
  * when \a resol arguments match.
@@ -482,6 +616,8 @@ float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(MaskSpl
 
        *tot_feather_point = tot;
 
+       spline_feather_collapse_inner_loops(feather, tot);
+
        return feather;
 }
 
index 7b84abc3d36302c771e02ad356c92c5c814fbd44..2fe1ffaae9e0e91749a7aedbd40b815e01a76841 100644 (file)
@@ -499,10 +499,10 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas
                unsigned int sf_vert_tot = 0;
                unsigned int tot_feather_quads = 0;
 
-               if (masklay->restrictflag & MASK_RESTRICT_RENDER || masklay->alpha == 0.0f) {
-                       MaskRasterLayer *layer = &mr_handle->layers[masklay_index];
-                       layer_bucket_init_dummy(layer);
-                       layer->alpha = 0.0f; /* signal to skip this layer */
+               if (masklay->restrictflag & MASK_RESTRICT_RENDER) {
+                       /* skip the layer */
+                       mr_handle->layers_tot--;
+                       masklay_index--;
                        continue;
                }
 
@@ -1002,11 +1002,7 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x
                float value_layer;
 
                /* also used as signal for unused layer (when render is disabled) */
-               if (layer->alpha == 0.0f) {
-                       continue;
-               }
-
-               if (BLI_in_rctf_v(&layer->bounds, xy)) {
+               if (layer->alpha != 0.0f && BLI_in_rctf_v(&layer->bounds, xy)) {
                        value_layer = 1.0f - layer_bucket_depth_from_xy(layer, xy);
 
                        switch (layer->falloff) {
index db39bf74e488a2b30cadf62a7833f0aba410cfd3..a75d890dcb486f4f6be9d9c9e5dec9297648133c 100644 (file)
@@ -1067,9 +1067,12 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm
                        /* if needed, reallocate multires paint mask */
                        if (gpm && gpm->level < key.level) {
                                gpm->level = key.level;
-                               if (gpm->data)
-                                       MEM_freeN(gpm->data);
-                               gpm->data = MEM_callocN(sizeof(float) * key.grid_area, "gpm.data");
+                               #pragma omp critical
+                               {
+                                       if (gpm->data)
+                                               MEM_freeN(gpm->data);
+                                       gpm->data = MEM_callocN(sizeof(float) * key.grid_area, "gpm.data");
+                               }
                        }
 
                        for (y = 0; y < gridSize; y++) {
index 4c037b6e73c1a1662ca467ca7956959b3503e243..107b688b36a2c0c69baca2687c628770ef1789f0 100644 (file)
@@ -93,6 +93,7 @@ int isect_line_line_v2_int(const int a1[2], const int a2[2], const int b1[2], co
 int isect_line_sphere_v3(const float l1[3], const float l2[3], const float sp[3], const float r, float r_p1[3], float r_p2[3]);
 int isect_line_sphere_v2(const float l1[2], const float l2[2], const float sp[2], const float r, float r_p1[2], float r_p2[2]);
 int isect_seg_seg_v2_point(const float v1[2], const float v2[2], const float v3[2], const float v4[2], float vi[2]);
+int isect_seg_seg_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2]);
 
 /* Returns the number of point of interests
  * 0 - lines are colinear
index da4846e7af12bb1bdbcb6a4bdb6f89e03a3b0229..cc9cb7a876b20f65beecdf9abf904c13f8690fce 100644 (file)
@@ -426,6 +426,15 @@ int isect_seg_seg_v2_point(const float v1[2], const float v2[2], const float v3[
        return -1;
 }
 
+int isect_seg_seg_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
+{
+#define CCW(A, B, C) ((C[1] - A[1]) * (B[0] - A[0]) > (B[1]-A[1]) * (C[0]-A[0]))
+
+   return CCW(v1, v3, v4) != CCW(v2, v3, v4) && CCW(v1, v2, v3) != CCW(v1, v2, v4);
+
+#undef CCW
+}
+
 int isect_line_sphere_v3(const float l1[3], const float l2[3],
                          const float sp[3], const float r,
                          float r_p1[3], float r_p2[3])
index ad56410d538395b1a81e52b5332342dabf7b0e3f..a87fc76d9d8e57733ef11a4873bfb6d5c53f2165 100644 (file)
@@ -2248,7 +2248,7 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe
 
                uiBlockSetEmboss(block, UI_EMBOSSN);
                row = uiLayoutRow(split, TRUE);
-               uiItemR(row, itemptr, "alpha", 0, "", ICON_NONE); // enable when used
+               uiItemR(row, itemptr, "alpha", 0, "", ICON_NONE);
                uiItemR(row, itemptr, "hide", 0, "", 0);
                uiItemR(row, itemptr, "hide_select", 0, "", 0);
                uiItemR(row, itemptr, "hide_render", 0, "", 0);
index 5e5ffe2049cf00de06e9f063f97c5a70ce3dfb0b..8b7251c20184ebc880e6d2aa589f0e06c4a67e62 100644 (file)
@@ -3986,9 +3986,9 @@ static int node_hide_toggle_exec(bContext *C, wmOperator *UNUSED(op))
                return OPERATOR_CANCELLED;
        
        node_flag_toggle_exec(snode, NODE_HIDDEN);
-       
-       snode_notify(C, snode);
-       
+
+       WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
+
        return OPERATOR_FINISHED;
 }
 
@@ -4049,7 +4049,7 @@ static int node_options_toggle_exec(bContext *C, wmOperator *UNUSED(op))
 
        node_flag_toggle_exec(snode, NODE_OPTIONS);
 
-       snode_notify(C, snode);
+       WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
 
        return OPERATOR_FINISHED;
 }
@@ -4100,7 +4100,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
 
        ntreeUpdateTree(snode->edittree);
 
-       snode_notify(C, snode);
+       WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL);
 
        return OPERATOR_FINISHED;
 }