merge from 21113 to 21377
[blender.git] / source / blender / blenkernel / intern / cdderivedmesh.c
index 706eece108cd1261ee8944d79ea00f172f5743a1..16f6936935aa2ec994270fd8ea69347e7c7e3a8f 100644 (file)
@@ -60,6 +60,7 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "gpu_buffers.h"
 #include "GPU_draw.h"
 #include "GPU_extensions.h"
 #include "GPU_material.h"
@@ -266,58 +267,73 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, int (*setMaterial)(int, void *a
        glVertex3fv(mvert[index].co);   \
 }
 
-       glBegin(glmode = GL_QUADS);
-       for(a = 0; a < dm->numFaceData; a++, mface++) {
-               int new_glmode, new_matnr, new_shademodel;
+       if( GPU_buffer_legacy(dm) ) {
+               DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" );
+               glBegin(glmode = GL_QUADS);
+               for(a = 0; a < dm->numFaceData; a++, mface++) {
+                       int new_glmode, new_matnr, new_shademodel;
 
-               new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
-               new_matnr = mface->mat_nr + 1;
-               new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
-               
-               if(new_glmode != glmode || new_matnr != matnr
-                  || new_shademodel != shademodel) {
-                       glEnd();
+                       new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
+                       new_matnr = mface->mat_nr + 1;
+                       new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
+                       
+                       if(new_glmode != glmode || new_matnr != matnr
+                          || new_shademodel != shademodel) {
+                               glEnd();
 
-                       drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
+                               drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
 
-                       glShadeModel(shademodel = new_shademodel);
-                       glBegin(glmode = new_glmode);
-               } 
-               
-               if(drawCurrentMat) {
-                       if(shademodel == GL_FLAT) {
-                               if (nors) {
-                                       glNormal3fv(nors);
-                               }
-                               else {
-                                       /* TODO make this better (cache facenormals as layer?) */
-                                       float nor[3];
-                                       if(mface->v4) {
-                                               CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co,
-                                                                          mvert[mface->v3].co, mvert[mface->v4].co,
-                                                                          nor);
-                                       } else {
-                                               CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co,
-                                                                         mvert[mface->v3].co, nor);
+                               glShadeModel(shademodel = new_shademodel);
+                               glBegin(glmode = new_glmode);
+                       } 
+                       
+                       if(drawCurrentMat) {
+                               if(shademodel == GL_FLAT) {
+                                       if (nors) {
+                                               glNormal3fv(nors);
+                                       }
+                                       else {
+                                               /* TODO make this better (cache facenormals as layer?) */
+                                               float nor[3];
+                                               if(mface->v4) {
+                                                       CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co,
+                                                                                  mvert[mface->v3].co, mvert[mface->v4].co,
+                                                                                  nor);
+                                               } else {
+                                                       CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co,
+                                                                                 mvert[mface->v3].co, nor);
+                                               }
+                                               glNormal3fv(nor);
                                        }
-                                       glNormal3fv(nor);
+                               }
+
+                               PASSVERT(mface->v1);
+                               PASSVERT(mface->v2);
+                               PASSVERT(mface->v3);
+                               if(mface->v4) {
+                                       PASSVERT(mface->v4);
                                }
                        }
 
-                       PASSVERT(mface->v1);
-                       PASSVERT(mface->v2);
-                       PASSVERT(mface->v3);
-                       if(mface->v4) {
-                               PASSVERT(mface->v4);
+                       if(nors) nors += 3;
+               }
+               glEnd();
+       }
+       else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
+               GPU_vertex_setup( dm );
+               GPU_normal_setup( dm );
+               if( !GPU_buffer_legacy(dm) ) {
+                       glShadeModel(GL_SMOOTH);
+                       for( a = 0; a < dm->drawObject->nmaterials; a++ ) {
+                               setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL);
+                               glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start, dm->drawObject->materials[a].end-dm->drawObject->materials[a].start);
                        }
                }
-
-               if(nors) nors += 3;
+               GPU_buffer_unbind( );
        }
-       glEnd();
 
-       glShadeModel(GL_FLAT);
 #undef PASSVERT
+       glShadeModel(GL_FLAT);
 }
 
 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
@@ -341,43 +357,64 @@ static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned cha
        /* we need that as mesh option builtin, next to double sided lighting */
        if(col1 && col2)
                glEnable(GL_CULL_FACE);
-       
-       glShadeModel(GL_SMOOTH);
-       glBegin(glmode = GL_QUADS);
-       for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
-               int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
 
-               if(new_glmode != glmode) {
-                       glEnd();
-                       glBegin(glmode = new_glmode);
-               }
-                       
-               glColor3ub(cp1[0], cp1[1], cp1[2]);
-               glVertex3fv(mvert[mface->v1].co);
-               glColor3ub(cp1[4], cp1[5], cp1[6]);
-               glVertex3fv(mvert[mface->v2].co);
-               glColor3ub(cp1[8], cp1[9], cp1[10]);
-               glVertex3fv(mvert[mface->v3].co);
-               if(mface->v4) {
-                       glColor3ub(cp1[12], cp1[13], cp1[14]);
-                       glVertex3fv(mvert[mface->v4].co);
-               }
-                       
-               if(useTwoSided) {
-                       glColor3ub(cp2[8], cp2[9], cp2[10]);
-                       glVertex3fv(mvert[mface->v3].co );
-                       glColor3ub(cp2[4], cp2[5], cp2[6]);
-                       glVertex3fv(mvert[mface->v2].co );
-                       glColor3ub(cp2[0], cp2[1], cp2[2]);
-                       glVertex3fv(mvert[mface->v1].co );
+       if( GPU_buffer_legacy(dm) ) {
+               DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" );
+               glShadeModel(GL_SMOOTH);
+               glBegin(glmode = GL_QUADS);
+               for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
+                       int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
+
+                       if(new_glmode != glmode) {
+                               glEnd();
+                               glBegin(glmode = new_glmode);
+                       }
+                               
+                       glColor3ub(cp1[0], cp1[1], cp1[2]);
+                       glVertex3fv(mvert[mface->v1].co);
+                       glColor3ub(cp1[4], cp1[5], cp1[6]);
+                       glVertex3fv(mvert[mface->v2].co);
+                       glColor3ub(cp1[8], cp1[9], cp1[10]);
+                       glVertex3fv(mvert[mface->v3].co);
                        if(mface->v4) {
-                               glColor3ub(cp2[12], cp2[13], cp2[14]);
-                               glVertex3fv(mvert[mface->v4].co );
+                               glColor3ub(cp1[12], cp1[13], cp1[14]);
+                               glVertex3fv(mvert[mface->v4].co);
                        }
+                               
+                       if(useTwoSided) {
+                               glColor3ub(cp2[8], cp2[9], cp2[10]);
+                               glVertex3fv(mvert[mface->v3].co );
+                               glColor3ub(cp2[4], cp2[5], cp2[6]);
+                               glVertex3fv(mvert[mface->v2].co );
+                               glColor3ub(cp2[0], cp2[1], cp2[2]);
+                               glVertex3fv(mvert[mface->v1].co );
+                               if(mface->v4) {
+                                       glColor3ub(cp2[12], cp2[13], cp2[14]);
+                                       glVertex3fv(mvert[mface->v4].co );
+                               }
+                       }
+                       if(col2) cp2 += 16;
                }
-               if(col2) cp2 += 16;
+               glEnd();
+       }
+       else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
+               GPU_color4_upload(dm,cp1);
+               GPU_vertex_setup(dm);
+               GPU_color_setup(dm);
+               if( !GPU_buffer_legacy(dm) ) {
+                       glShadeModel(GL_SMOOTH);
+                       glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
+
+                       if( useTwoSided ) {
+                               GPU_color4_upload(dm,cp2);
+                               GPU_color_setup(dm);
+                               glCullFace(GL_FRONT);
+                               glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->nelements);
+                               glCullFace(GL_BACK);
+                       }
+               }
+               GPU_buffer_unbind();
        }
-       glEnd();
 
        glShadeModel(GL_FLAT);
        glDisable(GL_CULL_FACE);
@@ -395,80 +432,147 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm,
        float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
        MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
        int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
+       int startFace = 0, lastFlag = 0xdeadbeef;
 
-       for(i = 0; i < dm->numFaceData; i++, mf++) {
-               MVert *mvert;
-               int flag;
-               unsigned char *cp = NULL;
+       if( GPU_buffer_legacy(dm) ) {
+               DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
+               for(i = 0; i < dm->numFaceData; i++, mf++) {
+                       MVert *mvert;
+                       int flag;
+                       unsigned char *cp = NULL;
+
+                       if(drawParams) {
+                               flag = drawParams(tf? &tf[i]: NULL, mcol? &mcol[i*4]: NULL, mf->mat_nr);
+                       }
+                       else {
+                               if(index) {
+                                       orig = *index++;
+                                       if(orig == ORIGINDEX_NONE)              { if(nors) nors += 3; continue; }
+                                       if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
+                                       else    { if(nors) nors += 3; continue; }
+                               }
+                               else
+                                       if(drawParamsMapped) flag = drawParamsMapped(userData, i);
+                                       else    { if(nors) nors += 3; continue; }
+                       }
+                       
+                       if(flag != 0) {
+                               if (flag==1 && mcol)
+                                       cp= (unsigned char*) &mcol[i*4];
+
+                               if(!(mf->flag&ME_SMOOTH)) {
+                                       if (nors) {
+                                               glNormal3fv(nors);
+                                       }
+                                       else {
+                                               float nor[3];
+                                               if(mf->v4) {
+                                                       CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
+                                                                                  mv[mf->v3].co, mv[mf->v4].co,
+                                                                                  nor);
+                                               } else {
+                                                       CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
+                                                                                 mv[mf->v3].co, nor);
+                                               }
+                                               glNormal3fv(nor);
+                                       }
+                               }
+
+                               glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
+                               if(tf) glTexCoord2fv(tf[i].uv[0]);
+                               if(cp) glColor3ub(cp[3], cp[2], cp[1]);
+                               mvert = &mv[mf->v1];
+                               if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
+                               glVertex3fv(mvert->co);
+                                       
+                               if(tf) glTexCoord2fv(tf[i].uv[1]);
+                               if(cp) glColor3ub(cp[7], cp[6], cp[5]);
+                               mvert = &mv[mf->v2];
+                               if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
+                               glVertex3fv(mvert->co);
+
+                               if(tf) glTexCoord2fv(tf[i].uv[2]);
+                               if(cp) glColor3ub(cp[11], cp[10], cp[9]);
+                               mvert = &mv[mf->v3];
+                               if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
+                               glVertex3fv(mvert->co);
 
-               if(drawParams) {
-                       flag = drawParams(tf? &tf[i]: NULL, mcol? &mcol[i*4]: NULL, mf->mat_nr);
+                               if(mf->v4) {
+                                       if(tf) glTexCoord2fv(tf[i].uv[3]);
+                                       if(cp) glColor3ub(cp[15], cp[14], cp[13]);
+                                       mvert = &mv[mf->v4];
+                                       if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
+                                       glVertex3fv(mvert->co);
+                               }
+                               glEnd();
+                       }
+                       
+                       if(nors) nors += 3;
                }
-               else {
-                       if(index) {
-                               orig = *index++;
-                               if(orig == ORIGINDEX_NONE)              { if(nors) nors += 3; continue; }
-                               if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
-                               else    { if(nors) nors += 3; continue; }
+       } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
+               GPU_vertex_setup( dm );
+               GPU_normal_setup( dm );
+               GPU_uv_setup( dm );
+               if( mcol != 0 ) {
+                       if( dm->drawObject->colType != CD_MCOL ) {
+                               unsigned char *colors = MEM_mallocN(dm->getNumFaces(dm)*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
+                               for( i=0; i < dm->getNumFaces(dm); i++ ) {
+                                       colors[i*3] = mcol[i].r;
+                                       colors[i*3+1] = mcol[i].g;
+                                       colors[i*3+2] = mcol[i].b;
+                               }
+                               GPU_color3_upload(dm,colors);
+                               MEM_freeN(colors);
+                               dm->drawObject->colType = CD_MCOL;
                        }
-                       else
-                               if(drawParamsMapped) flag = drawParamsMapped(userData, i);
-                               else    { if(nors) nors += 3; continue; }
+                       GPU_color_setup( dm );
                }
-               
-               if(flag != 0) { /* if the flag is 0 it means the face is hidden or invisible */
-                       if (flag==1 && mcol)
-                               cp= (unsigned char*) &mcol[i*4];
-
-                       if(!(mf->flag&ME_SMOOTH)) {
-                               if (nors) {
-                                       glNormal3fv(nors);
+               if( !GPU_buffer_legacy(dm) ) {
+                       glShadeModel( GL_SMOOTH );
+                       for(i = 0; i < dm->drawObject->nelements/3; i++) {
+                               int actualFace = dm->drawObject->faceRemap[i];
+                               int flag;
+                               unsigned char *cp = NULL;
+
+                               if(drawParams) {
+                                       flag = drawParams(tf? &tf[actualFace]: NULL, mcol? &mcol[actualFace*4]: NULL, mf[actualFace].mat_nr);
                                }
                                else {
-                                       /* TODO make this better (cache facenormals as layer?) */
-                                       float nor[3];
-                                       if(mf->v4) {
-                                               CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
-                                                                          mv[mf->v3].co, mv[mf->v4].co,
-                                                                          nor);
-                                       } else {
-                                               CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
-                                                                         mv[mf->v3].co, nor);
+                                       if(index) {
+                                               orig = index[actualFace];
+                                               if(drawParamsMapped)
+                                                       flag = drawParamsMapped(userData, orig);
                                        }
-                                       glNormal3fv(nor);
+                                       else
+                                               if(drawParamsMapped)
+                                                       flag = drawParamsMapped(userData, actualFace);
+                               }
+                               if( flag != lastFlag ) {
+                                       if( startFace < i ) {
+                                               if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
+                                                       if (lastFlag==1 && mcol)
+                                                               GPU_color_switch(1);
+                                                       else
+                                                               GPU_color_switch(0);
+                                                       glDrawArrays(GL_TRIANGLES,startFace*3,(i-startFace)*3);
+                                               }
+                                       }
+                                       lastFlag = flag;
+                                       startFace = i;
                                }
                        }
-
-                       glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
-                       if(tf) glTexCoord2fv(tf[i].uv[0]);
-                       if(cp) glColor3ub(cp[3], cp[2], cp[1]);
-                       mvert = &mv[mf->v1];
-                       if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
-                       glVertex3fv(mvert->co);
-                               
-                       if(tf) glTexCoord2fv(tf[i].uv[1]);
-                       if(cp) glColor3ub(cp[7], cp[6], cp[5]);
-                       mvert = &mv[mf->v2];
-                       if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
-                       glVertex3fv(mvert->co);
-
-                       if(tf) glTexCoord2fv(tf[i].uv[2]);
-                       if(cp) glColor3ub(cp[11], cp[10], cp[9]);
-                       mvert = &mv[mf->v3];
-                       if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
-                       glVertex3fv(mvert->co);
-
-                       if(mf->v4) {
-                               if(tf) glTexCoord2fv(tf[i].uv[3]);
-                               if(cp) glColor3ub(cp[15], cp[14], cp[13]);
-                               mvert = &mv[mf->v4];
-                               if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
-                               glVertex3fv(mvert->co);
+                       if( startFace < dm->drawObject->nelements/3 ) {
+                               if( lastFlag != 0 ) { /* if the flag is 0 it means the face is hidden or invisible */
+                                       if (lastFlag==1 && mcol)
+                                               GPU_color_switch(1);
+                                       else
+                                               GPU_color_switch(0);
+                                       glDrawArrays(GL_TRIANGLES,startFace*3,dm->drawObject->nelements-startFace*3);
+                               }
                        }
-                       glEnd();
                }
-               
-               if(nors) nors += 3;
+               GPU_buffer_unbind();
+               glShadeModel( GL_FLAT );
        }
 }
 
@@ -490,75 +594,124 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, int (*setDrawOptions)(void *us
        if(!mc)
                mc = DM_get_face_data_layer(dm, CD_MCOL);
 
-       for(i = 0; i < dm->numFaceData; i++, mf++) {
-               int drawSmooth = (mf->flag & ME_SMOOTH);
+       if( GPU_buffer_legacy(dm) ) {
+               DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
+               for(i = 0; i < dm->numFaceData; i++, mf++) {
+                       int drawSmooth = (mf->flag & ME_SMOOTH);
 
-               if(index) {
-                       orig = *index++;
-                       if(setDrawOptions && orig == ORIGINDEX_NONE)
-                               { if(nors) nors += 3; continue; }
-               }
-               else
-                       orig = i;
+                       if(index) {
+                               orig = *index++;
+                               if(setDrawOptions && orig == ORIGINDEX_NONE)
+                                       { if(nors) nors += 3; continue; }
+                       }
+                       else
+                               orig = i;
 
-               if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) {
-                       unsigned char *cp = NULL;
+                       if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) {
+                               unsigned char *cp = NULL;
 
-                       if(useColors && mc)
-                               cp = (unsigned char *)&mc[i * 4];
+                               if(useColors && mc)
+                                       cp = (unsigned char *)&mc[i * 4];
 
-                       glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
-                       glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
+                               glShadeModel(drawSmooth?GL_SMOOTH:GL_FLAT);
+                               glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
 
-                       if (!drawSmooth) {
-                               if (nors) {
-                                       glNormal3fv(nors);
-                               }
-                               else {
-                                       /* TODO make this better (cache facenormals as layer?) */
-                                       float nor[3];
+                               if (!drawSmooth) {
+                                       if (nors) {
+                                               glNormal3fv(nors);
+                                       }
+                                       else {
+                                               float nor[3];
+                                               if(mf->v4) {
+                                                       CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
+                                                                                  mv[mf->v3].co, mv[mf->v4].co,
+                                                                                  nor);
+                                               } else {
+                                                       CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
+                                                                                 mv[mf->v3].co, nor);
+                                               }
+                                               glNormal3fv(nor);
+                                       }
+
+                                       if(cp) glColor3ub(cp[3], cp[2], cp[1]);
+                                       glVertex3fv(mv[mf->v1].co);
+                                       if(cp) glColor3ub(cp[7], cp[6], cp[5]);
+                                       glVertex3fv(mv[mf->v2].co);
+                                       if(cp) glColor3ub(cp[11], cp[10], cp[9]);
+                                       glVertex3fv(mv[mf->v3].co);
                                        if(mf->v4) {
-                                               CalcNormFloat4(mv[mf->v1].co, mv[mf->v2].co,
-                                                                          mv[mf->v3].co, mv[mf->v4].co,
-                                                                          nor);
-                                       } else {
-                                               CalcNormFloat(mv[mf->v1].co, mv[mf->v2].co,
-                                                                         mv[mf->v3].co, nor);
+                                               if(cp) glColor3ub(cp[15], cp[14], cp[13]);
+                                               glVertex3fv(mv[mf->v4].co);
+                                       }
+                               } else {
+                                       if(cp) glColor3ub(cp[3], cp[2], cp[1]);
+                                       glNormal3sv(mv[mf->v1].no);
+                                       glVertex3fv(mv[mf->v1].co);
+                                       if(cp) glColor3ub(cp[7], cp[6], cp[5]);
+                                       glNormal3sv(mv[mf->v2].no);
+                                       glVertex3fv(mv[mf->v2].co);
+                                       if(cp) glColor3ub(cp[11], cp[10], cp[9]);
+                                       glNormal3sv(mv[mf->v3].no);
+                                       glVertex3fv(mv[mf->v3].co);
+                                       if(mf->v4) {
+                                               if(cp) glColor3ub(cp[15], cp[14], cp[13]);
+                                               glNormal3sv(mv[mf->v4].no);
+                                               glVertex3fv(mv[mf->v4].co);
                                        }
-                                       glNormal3fv(nor);
                                }
 
-                               if(cp) glColor3ub(cp[3], cp[2], cp[1]);
-                               glVertex3fv(mv[mf->v1].co);
-                               if(cp) glColor3ub(cp[7], cp[6], cp[5]);
-                               glVertex3fv(mv[mf->v2].co);
-                               if(cp) glColor3ub(cp[11], cp[10], cp[9]);
-                               glVertex3fv(mv[mf->v3].co);
-                               if(mf->v4) {
-                                       if(cp) glColor3ub(cp[15], cp[14], cp[13]);
-                                       glVertex3fv(mv[mf->v4].co);
+                               glEnd();
+                       }
+                       
+                       if (nors) nors += 3;
+               }
+       }
+       else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
+               int state = 1;
+               int prevstate = 1;
+               int prevstart = 0;
+               GPU_vertex_setup(dm);
+               GPU_normal_setup(dm);
+               if( useColors && mc )
+                       GPU_color_setup(dm);
+               if( !GPU_buffer_legacy(dm) ) {
+                       glShadeModel(GL_SMOOTH);
+                       for( i = 0; i < dm->drawObject->nelements/3; i++ ) {
+                               int actualFace = dm->drawObject->faceRemap[i];
+                               int drawSmooth = (mf[actualFace].flag & ME_SMOOTH);
+                               int dontdraw = 0;
+                               if(index) {
+                                       orig = index[actualFace];
+                                       if(setDrawOptions && orig == ORIGINDEX_NONE)
+                                               dontdraw = 1;
                                }
-                       } else {
-                               if(cp) glColor3ub(cp[3], cp[2], cp[1]);
-                               glNormal3sv(mv[mf->v1].no);
-                               glVertex3fv(mv[mf->v1].co);
-                               if(cp) glColor3ub(cp[7], cp[6], cp[5]);
-                               glNormal3sv(mv[mf->v2].no);
-                               glVertex3fv(mv[mf->v2].co);
-                               if(cp) glColor3ub(cp[11], cp[10], cp[9]);
-                               glNormal3sv(mv[mf->v3].no);
-                               glVertex3fv(mv[mf->v3].co);
-                               if(mf->v4) {
-                                       if(cp) glColor3ub(cp[15], cp[14], cp[13]);
-                                       glNormal3sv(mv[mf->v4].no);
-                                       glVertex3fv(mv[mf->v4].co);
+                               else
+                                       orig = i;
+                               if( dontdraw ) {
+                                       state = 0;
+                               }
+                               else {
+                                       if(!setDrawOptions || setDrawOptions(userData, orig, &drawSmooth)) {
+                                               state = 1;
+                                       }
+                                       else {
+                                               state = 0;
+                                       }
+                               }
+                               if( prevstate != state && prevstate == 1 ) {
+                                       if( i-prevstart > 0 ) {
+                                               glDrawArrays(GL_TRIANGLES,prevstart*3,(i-prevstart)*3);
+                                       }
+                                       prevstart = i;
                                }
+                               prevstate = state;
                        }
-
-                       glEnd();
+                       if(state==1) {
+                               glDrawArrays(GL_TRIANGLES,prevstart*3,dm->drawObject->nelements-prevstart*3);
+                       }
+                       glShadeModel(GL_FLAT);
                }
-               
-               if (nors) nors += 3;
+               GPU_buffer_unbind();
        }
 }