Merging r58475 through r58700 from trunk into soc-2013-depsgraph_mt
[blender.git] / source / blender / editors / sculpt_paint / paint_image_proj.c
index 553a5cbe9aca8693e08b83205d95fbe991cf40b3..db55dc271f1f8d6a64d8e3a6c81b84b4d92dbfce 100644 (file)
@@ -245,7 +245,8 @@ typedef struct ProjPaintState {
        float normal_angle_inner;
        float normal_angle_range;       /* difference between normal_angle and normal_angle_inner, for easy access */
 
-       short is_ortho;
+       bool do_face_sel;               /* quick access to (me->editflag & ME_EDIT_PAINT_FACE_SEL) */
+       bool is_ortho;
        bool do_masking;              /* use masking during painting. Some operations such as airbrush may disable */
        bool is_texbrush;              /* only to avoid running  */
        bool is_maskbrush;            /* mask brush is applied before masking */
@@ -2809,22 +2810,32 @@ static void project_paint_begin(ProjPaintState *ps)
        Image *tpage_last = NULL, *tpage;
 
        /* Face vars */
+       MPoly *mpoly_orig;
        MFace *mf;
        MTFace *tf;
 
        int a, i; /* generic looping vars */
        int image_index = -1, face_index;
+
+       /* double lookup */
+       const int *index_mf_to_mpoly = NULL;
+       const int *index_mp_to_orig  = NULL;
+
        MVert *mv;
 
        MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */
 
        const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush);
 
+       bool reset_threads = false;
+
        /* ---- end defines ---- */
 
        if (ps->source == PROJ_SRC_VIEW)
                ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat);  /* faster clipping lookups */
 
+       ps->do_face_sel = ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) != 0);
+
        /* paint onto the derived mesh */
 
        /* Workaround for subsurf selection, try the display mesh first */
@@ -2833,12 +2844,17 @@ static void project_paint_begin(ProjPaintState *ps)
                ps->dm = mesh_create_derived_render(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE);
                ps->dm_release = TRUE;
        }
-       else if (ps->ob->derivedFinal && CustomData_has_layer(&ps->ob->derivedFinal->faceData, CD_MTFACE)) {
+       else if (ps->ob->derivedFinal &&
+                CustomData_has_layer(&ps->ob->derivedFinal->faceData, CD_MTFACE) &&
+                (ps->do_face_sel == false || CustomData_has_layer(&ps->ob->derivedFinal->polyData, CD_ORIGINDEX)))
+       {
                ps->dm = ps->ob->derivedFinal;
                ps->dm_release = FALSE;
        }
        else {
-               ps->dm = mesh_get_derived_final(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE);
+               ps->dm = mesh_get_derived_final(
+                            ps->scene, ps->ob,
+                            ps->scene->customdata_mask | CD_MASK_MTFACE | (ps->do_face_sel ? CD_ORIGINDEX : 0));
                ps->dm_release = TRUE;
        }
 
@@ -2858,6 +2874,20 @@ static void project_paint_begin(ProjPaintState *ps)
        ps->dm_totvert = ps->dm->getNumVerts(ps->dm);
        ps->dm_totface = ps->dm->getNumTessFaces(ps->dm);
 
+       if (ps->do_face_sel) {
+               index_mf_to_mpoly = ps->dm->getTessFaceDataArray(ps->dm, CD_ORIGINDEX);
+               index_mp_to_orig  = ps->dm->getPolyDataArray(ps->dm, CD_ORIGINDEX);
+               if (index_mf_to_mpoly == NULL) {
+                       index_mp_to_orig = NULL;
+               }
+               else {
+                       mpoly_orig = ((Mesh *)ps->ob->data)->mpoly;
+               }
+       }
+       else {
+               mpoly_orig = NULL;
+       }
+
        /* use clone mtface? */
 
 
@@ -3064,6 +3094,10 @@ static void project_paint_begin(ProjPaintState *ps)
 
        /* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */
 
+       if (ps->buckets_x > PROJ_BUCKET_RECT_MAX || ps->buckets_y > PROJ_BUCKET_RECT_MAX) {
+               reset_threads = true;
+       }
+
        /* really high values could cause problems since it has to allocate a few
         * (ps->buckets_x*ps->buckets_y) sized arrays  */
        CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX);
@@ -3089,6 +3123,11 @@ static void project_paint_begin(ProjPaintState *ps)
 
        ps->thread_tot = BKE_scene_num_threads(ps->scene);
 
+       /* workaround for #35057, disable threading if diameter is less than is possible for
+        * optimum bucket number generation */
+       if (reset_threads)
+               ps->thread_tot = 1;
+
        for (a = 0; a < ps->thread_tot; a++) {
                ps->arena_mt[a] = BLI_memarena_new(1 << 16, "project paint arena");
        }
@@ -3118,8 +3157,8 @@ static void project_paint_begin(ProjPaintState *ps)
                }
        }
 
-
        for (face_index = 0, tf = ps->dm_mtface, mf = ps->dm_mface; face_index < ps->dm_totface; mf++, tf++, face_index++) {
+               bool is_face_sel;
 
 #ifndef PROJ_DEBUG_NOSEAMBLEED
                /* add face user if we have bleed enabled, set the UV seam flags later */
@@ -3134,10 +3173,23 @@ static void project_paint_begin(ProjPaintState *ps)
                }
 #endif
 
-               tpage = project_paint_face_image(ps, ps->dm_mtface, face_index);
-
-               if (tpage && ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) == 0 || mf->flag & ME_FACE_SEL)) {
+               if (ps->do_face_sel) {
+                       int orig_index;
+                       if (index_mp_to_orig && ((orig_index = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig,
+                                                                                       face_index))) != ORIGINDEX_NONE)
+                       {
+                               MPoly *mp = &mpoly_orig[orig_index];
+                               is_face_sel = ((mp->flag & ME_FACE_SEL) != 0);
+                       }
+                       else {
+                               is_face_sel = ((mf->flag & ME_FACE_SEL) != 0);
+                       }
+               }
+               else {
+                       is_face_sel = true;
+               }
 
+               if (is_face_sel && (tpage = project_paint_face_image(ps, ps->dm_mtface, face_index))) {
                        float *v1coSS, *v2coSS, *v3coSS, *v4coSS = NULL;
 
                        v1coSS = ps->screenCoords[mf->v1];