Fix #28347: VBO's highlights wrong faces when Mirror modifier is in use
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 29 Aug 2011 16:07:44 +0000 (16:07 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 29 Aug 2011 16:07:44 +0000 (16:07 +0000)
Added callback to drawMappedFaces which checks if two faces have got equal draw options.

After discussion with Brecht we found it's nicest solution for now:
- Disabling VBOs in edit mode for this case wouldn't be nicer for this case -
  some additional flag stored in DM should be added in this case.
- Adding new callback in DM isn't nicer that this solution.
- Handling face selection in drawobject would lead to duplicated code
  which is also not nice.

Hopefully, this callback could handle all cases in the future.

Also, Brecht mentioned current VBO implementation isn't perfect, so maybe
when we'll redesign this area dealing with edit mode wouldn't be so tricky.

source/blender/blenkernel/BKE_DerivedMesh.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/cdderivedmesh.c
source/blender/blenkernel/intern/subsurf_ccg.c
source/blender/editors/space_view3d/drawmesh.c
source/blender/editors/space_view3d/drawobject.c

index 46b533f33fdc4826fe82da8242e2a85e82bb063a..6e17b056685e9d5cc789040f90f0204862b4a64b 100644 (file)
@@ -283,7 +283,8 @@ struct DerivedMesh {
                                                        int (*setDrawOptions)(void *userData, int index,
                                                                                                  int *drawSmooth_r),
                                                        void *userData, int useColors,
-                                                       int (*setMaterial)(int, void *attribs));
+                                                       int (*setMaterial)(int, void *attribs),
+                                                       int (*compareDrawOptions)(void *userData, int cur_index, int next_index));
 
        /* Draw mapped faces using MTFace 
         *  o Drawing options too complicated to enumerate, look at code.
index c84bcaabbd3257035811d3293aab3bc31d91b78e..ff7f2586767b30c017350412f3aec58b6f223c7f 100644 (file)
@@ -637,7 +637,8 @@ static void emDM_foreachMappedFaceCenter(DerivedMesh *dm, void (*func)(void *use
 }
 
 /* note, material function is ignored for now. */
-static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int UNUSED(useColors), int (*setMaterial)(int, void *attribs))
+static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int UNUSED(useColors), int (*setMaterial)(int, void *attribs),
+                       int (*compareDrawOptions)(void *userData, int cur_index, int next_index))
 {
        EditMeshDerivedMesh *emdm= (EditMeshDerivedMesh*) dm;
        EditFace *efa;
@@ -645,6 +646,9 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
        
        (void)setMaterial; /* unused */
 
+       /* currently unused -- each original face is handled separately */
+       (void)compareDrawOptions;
+
        if (emdm->vertexCos) {
                EditVert *eve;
 
index 12fb11c68b3050901a459f210ecde9182ce8f0dd..5eb97630e83d16fd03ddde1018b2cd846e4b27bd 100644 (file)
@@ -843,7 +843,8 @@ static void cdDM_drawFacesTex(DerivedMesh *dm, int (*setDrawOptions)(MTFace *tfa
        cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, NULL);
 }
 
-static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs))
+static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs),
+                       int (*compareDrawOptions)(void *userData, int cur_index, int next_index))
 {
        CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
        MVert *mv = cddm->mvert;
@@ -958,6 +959,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
                                        MFace *mface= mf + actualFace;
                                        int drawSmooth= (mface->flag & ME_SMOOTH);
                                        int draw = 1;
+                                       int flush = 0;
 
                                        if(i != tottri-1)
                                                next_actualFace= dm->drawObject->triangle_to_mface[i+1];
@@ -972,11 +974,28 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
                                        /* Goal is to draw as long of a contiguous triangle
                                           array as possible, so draw when we hit either an
                                           invisible triangle or at the end of the array */
-                                       if(!draw || i == tottri - 1 || mf[actualFace].mat_nr != mf[next_actualFace].mat_nr) {
-                                               if(prevstart != i)
-                                                       /* Add one to the length (via `draw')
-                                                          if we're drawing at the end of the array */
-                                                       glDrawArrays(GL_TRIANGLES,prevstart*3, (i-prevstart+draw)*3);
+
+                                       /* flush buffer if current triangle isn't drawable or it's last triangle... */
+                                       flush= !draw || i == tottri - 1;
+
+                                       /* ... or when material setting is dissferent  */
+                                       flush|= mf[actualFace].mat_nr != mf[next_actualFace].mat_nr;
+
+                                       if(!flush && compareDrawOptions) {
+                                               int next_orig= (index==NULL) ? next_actualFace : index[next_actualFace];
+
+                                               /* also compare draw options and flush buffer if they're different
+                                                  need for face selection highlight in edit mode */
+                                               flush|= compareDrawOptions(userData, orig, next_orig) == 0;
+                                       }
+
+                                       if(flush) {
+                                               int first= prevstart*3;
+                                               int count= (i-prevstart+(draw ? 1 : 0))*3; /* Add one to the length if we're drawing at the end of the array */
+
+                                               if(count)
+                                                       glDrawArrays(GL_TRIANGLES, first, count);
+
                                                prevstart = i + 1;
                                        }
                                }
index 67d7e7bffd6b479c77864b27d2594d2975f51a5c..186a5ea1852926ed30427b60e44b88806a04f7d1 100644 (file)
@@ -1779,7 +1779,8 @@ static void ccgDM_drawUVEdges(DerivedMesh *dm)
        }
 }
 
-static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs)) {
+static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r), void *userData, int useColors, int (*setMaterial)(int, void *attribs),
+                       int (*compareDrawOptions)(void *userData, int cur_index, int next_index)) {
        CCGDerivedMesh *ccgdm = (CCGDerivedMesh*) dm;
        CCGSubSurf *ss = ccgdm->ss;
        MCol *mcol= NULL;
@@ -1787,6 +1788,9 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *u
        char *faceFlags = ccgdm->faceFlags;
        int gridFaces = gridSize - 1, totface;
 
+       /* currently unused -- each original face is handled separately */
+       (void)compareDrawOptions;
+
        if(useColors) {
                mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
                if(!mcol)
index 71c8548324484ed04a502379ec119c6a0e86902c..6e02ecbd5a866fed660736117a8949ce4e32fc75 100644 (file)
@@ -607,7 +607,7 @@ void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *o
        }
        else if(faceselect) {
                if(ob->mode & OB_MODE_WEIGHT_PAINT)
-                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1, GPU_enable_material);
+                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1, GPU_enable_material, NULL);
                else
                        dm->drawMappedFacesTex(dm, me->mface ? draw_tface_mapped__set_draw : NULL, me);
        }
index 638d197ccf7ddca9cc2abe5ef4f960218eea0329..8ca352ffe42ca1f9553cf064d07c4cb6f2cdf869 100644 (file)
@@ -2030,6 +2030,28 @@ static int draw_dm_faces_sel__setDrawOptions(void *userData, int index, int *UNU
        return 0;
 }
 
+static int draw_dm_faces_sel__compareDrawOptions(void *userData, int index, int next_index)
+{
+       struct { unsigned char *cols[3]; EditFace *efa_act; } * data = userData;
+       EditFace *efa = EM_get_face_for_index(index);
+       EditFace *next_efa = EM_get_face_for_index(next_index);
+       unsigned char *col, *next_col;
+
+       if(efa == next_efa)
+               return 1;
+
+       if(efa == data->efa_act || next_efa == data->efa_act)
+               return 0;
+
+       col = data->cols[(efa->f&SELECT)?1:0];
+       next_col = data->cols[(next_efa->f&SELECT)?1:0];
+
+       if(col[3]==0 || next_col[3]==0)
+               return 0;
+
+       return col == next_col;
+}
+
 /* also draws the active face */
 static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned char *selCol, unsigned char *actCol, EditFace *efa_act) 
 {
@@ -2039,7 +2061,7 @@ static void draw_dm_faces_sel(DerivedMesh *dm, unsigned char *baseCol, unsigned
        data.cols[2] = actCol;
        data.efa_act = efa_act;
 
-       dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material);
+       dm->drawMappedFaces(dm, draw_dm_faces_sel__setDrawOptions, &data, 0, GPU_enable_material, draw_dm_faces_sel__compareDrawOptions);
 }
 
 static int draw_dm_creases__setDrawOptions(void *UNUSED(userData), int index)
@@ -2449,7 +2471,7 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
                        glEnable(GL_LIGHTING);
                        glFrontFace((ob->transflag&OB_NEG_SCALE)?GL_CW:GL_CCW);
 
-                       finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material);
+                       finalDM->drawMappedFaces(finalDM, draw_em_fancy__setFaceOpts, NULL, 0, GPU_enable_material, NULL);
 
                        glFrontFace(GL_CCW);
                        glDisable(GL_LIGHTING);
@@ -2678,7 +2700,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
                        /* weight paint in solid mode, special case. focus on making the weights clear
                         * rather than the shading, this is also forced in wire view */
                        GPU_enable_material(0, NULL);
-                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
+                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
                
                        bglPolygonOffset(rv3d->dist, 1.0);
                        glDepthMask(0); // disable write in zbuffer, selected edge wires show better
@@ -2758,7 +2780,7 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
                                glEnable(GL_LIGHTING);
                                glEnable(GL_COLOR_MATERIAL);
 
-                               dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material);
+                               dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me->mface, 1, GPU_enable_material, NULL);
                                glDisable(GL_COLOR_MATERIAL);
                                glDisable(GL_LIGHTING);
 
@@ -2766,10 +2788,10 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D
                        }
                        else if(ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_TEXTURE_PAINT)) {
                                if(me->mcol)
-                                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material);
+                                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 1, GPU_enable_material, NULL);
                                else {
                                        glColor3f(1.0f, 1.0f, 1.0f);
-                                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material);
+                                       dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, NULL, 0, GPU_enable_material, NULL);
                                }
                        }
                }
@@ -6459,7 +6481,7 @@ static void bbs_mesh_solid_EM(Scene *scene, View3D *v3d, Object *ob, DerivedMesh
        cpack(0);
 
        if (facecol) {
-               dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*)(intptr_t) 1, 0, GPU_enable_material);
+               dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*)(intptr_t) 1, 0, GPU_enable_material, NULL);
 
                if(check_ob_drawface_dot(scene, v3d, ob->dt)) {
                        glPointSize(UI_GetThemeValuef(TH_FACEDOT_SIZE));
@@ -6470,7 +6492,7 @@ static void bbs_mesh_solid_EM(Scene *scene, View3D *v3d, Object *ob, DerivedMesh
                }
 
        } else {
-               dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*) 0, 0, GPU_enable_material);
+               dm->drawMappedFaces(dm, bbs_mesh_solid__setSolidDrawOptions, (void*) 0, 0, GPU_enable_material, NULL);
        }
 }
 
@@ -6499,8 +6521,8 @@ static void bbs_mesh_solid(Scene *scene, Object *ob)
        
        glColor3ub(0, 0, 0);
                
-       if((me->editflag & ME_EDIT_PAINT_MASK)) dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, me, 0, GPU_enable_material);
-       else                                                                    dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, me, 0, GPU_enable_material);
+       if((me->editflag & ME_EDIT_PAINT_MASK)) dm->drawMappedFaces(dm, bbs_mesh_solid_hide__setDrawOpts, me, 0, GPU_enable_material, NULL);
+       else                                                                    dm->drawMappedFaces(dm, bbs_mesh_solid__setDrawOpts, me, 0, GPU_enable_material, NULL);
 
        dm->release(dm);
 }
@@ -6607,7 +6629,7 @@ static void draw_object_mesh_instance(Scene *scene, View3D *v3d, RegionView3D *r
                        GPU_end_object_materials();
                }
                else if(edm)
-                       edm->drawMappedFaces(edm, NULL, NULL, 0, GPU_enable_material);
+                       edm->drawMappedFaces(edm, NULL, NULL, 0, GPU_enable_material, NULL);
                
                glDisable(GL_LIGHTING);
        }