Blender V2.61 - r43446

cdderivedmesh.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software  Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2006 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): Ben Batt <benbatt@gmail.com>
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  *
00027  * Implementation of CDDerivedMesh.
00028  *
00029  * BKE_cdderivedmesh.h contains the function prototypes for this file.
00030  *
00031  */
00032 
00037 #include "GL/glew.h"
00038 
00039 #include "BLI_blenlib.h"
00040 #include "BLI_edgehash.h"
00041 #include "BLI_editVert.h"
00042 #include "BLI_math.h"
00043 #include "BLI_pbvh.h"
00044 #include "BLI_utildefines.h"
00045 
00046 #include "BKE_cdderivedmesh.h"
00047 #include "BKE_global.h"
00048 #include "BKE_mesh.h"
00049 #include "BKE_paint.h"
00050 
00051 
00052 #include "DNA_meshdata_types.h"
00053 #include "DNA_object_types.h"
00054 #include "DNA_curve_types.h" /* for Curve */
00055 
00056 #include "MEM_guardedalloc.h"
00057 
00058 #include "GPU_buffers.h"
00059 #include "GPU_draw.h"
00060 #include "GPU_extensions.h"
00061 #include "GPU_material.h"
00062 
00063 #include <string.h>
00064 #include <limits.h>
00065 #include <math.h>
00066 
00067 typedef struct {
00068     DerivedMesh dm;
00069 
00070     /* these point to data in the DerivedMesh custom data layers,
00071        they are only here for efficiency and convenience **/
00072     MVert *mvert;
00073     MEdge *medge;
00074     MFace *mface;
00075 
00076     /* Cached */
00077     struct PBVH *pbvh;
00078     int pbvh_draw;
00079 
00080     /* Mesh connectivity */
00081     struct ListBase *fmap;
00082     struct IndexNode *fmap_mem;
00083 } CDDerivedMesh;
00084 
00085 /**************** DerivedMesh interface functions ****************/
00086 static int cdDM_getNumVerts(DerivedMesh *dm)
00087 {
00088     return dm->numVertData;
00089 }
00090 
00091 static int cdDM_getNumEdges(DerivedMesh *dm)
00092 {
00093     return dm->numEdgeData;
00094 }
00095 
00096 static int cdDM_getNumFaces(DerivedMesh *dm)
00097 {
00098     return dm->numFaceData;
00099 }
00100 
00101 static void cdDM_getVert(DerivedMesh *dm, int index, MVert *vert_r)
00102 {
00103     CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
00104     *vert_r = cddm->mvert[index];
00105 }
00106 
00107 static void cdDM_getEdge(DerivedMesh *dm, int index, MEdge *edge_r)
00108 {
00109     CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
00110     *edge_r = cddm->medge[index];
00111 }
00112 
00113 static void cdDM_getFace(DerivedMesh *dm, int index, MFace *face_r)
00114 {
00115     CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
00116     *face_r = cddm->mface[index];
00117 }
00118 
00119 static void cdDM_copyVertArray(DerivedMesh *dm, MVert *vert_r)
00120 {
00121     CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
00122     memcpy(vert_r, cddm->mvert, sizeof(*vert_r) * dm->numVertData);
00123 }
00124 
00125 static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *edge_r)
00126 {
00127     CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
00128     memcpy(edge_r, cddm->medge, sizeof(*edge_r) * dm->numEdgeData);
00129 }
00130 
00131 static void cdDM_copyFaceArray(DerivedMesh *dm, MFace *face_r)
00132 {
00133     CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
00134     memcpy(face_r, cddm->mface, sizeof(*face_r) * dm->numFaceData);
00135 }
00136 
00137 static void cdDM_getMinMax(DerivedMesh *dm, float min_r[3], float max_r[3])
00138 {
00139     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00140     int i;
00141 
00142     if (dm->numVertData) {
00143         for (i=0; i<dm->numVertData; i++) {
00144             DO_MINMAX(cddm->mvert[i].co, min_r, max_r);
00145         }
00146     } else {
00147         min_r[0] = min_r[1] = min_r[2] = max_r[0] = max_r[1] = max_r[2] = 0.0;
00148     }
00149 }
00150 
00151 static void cdDM_getVertCo(DerivedMesh *dm, int index, float co_r[3])
00152 {
00153     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00154 
00155     copy_v3_v3(co_r, cddm->mvert[index].co);
00156 }
00157 
00158 static void cdDM_getVertCos(DerivedMesh *dm, float (*cos_r)[3])
00159 {
00160     MVert *mv = CDDM_get_verts(dm);
00161     int i;
00162 
00163     for(i = 0; i < dm->numVertData; i++, mv++)
00164         copy_v3_v3(cos_r[i], mv->co);
00165 }
00166 
00167 static void cdDM_getVertNo(DerivedMesh *dm, int index, float no_r[3])
00168 {
00169     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00170     normal_short_to_float_v3(no_r, cddm->mvert[index].no);
00171 }
00172 
00173 static ListBase *cdDM_getFaceMap(Object *ob, DerivedMesh *dm)
00174 {
00175     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00176 
00177     if(!cddm->fmap && ob->type == OB_MESH) {
00178         Mesh *me= ob->data;
00179 
00180         create_vert_face_map(&cddm->fmap, &cddm->fmap_mem, me->mface,
00181                      me->totvert, me->totface);
00182     }
00183 
00184     return cddm->fmap;
00185 }
00186 
00187 static int can_pbvh_draw(Object *ob, DerivedMesh *dm)
00188 {
00189     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00190     Mesh *me= ob->data;
00191     int deformed= 0;
00192 
00193     /* active modifiers means extra deformation, which can't be handled correct
00194        on bith of PBVH and sculpt "layer" levels, so use PBVH only for internal brush
00195        stuff and show final DerivedMesh so user would see actual object shape */
00196     deformed|= ob->sculpt->modifiers_active;
00197 
00198     /* as in case with modifiers, we can't synchronize deformation made against
00199        PBVH and non-locked keyblock, so also use PBVH only for brushes and
00200        final DM to give final result to user */
00201     deformed|= ob->sculpt->kb && (ob->shapeflag&OB_SHAPE_LOCK) == 0;
00202 
00203     if(deformed)
00204         return 0;
00205 
00206     return (cddm->mvert == me->mvert) || ob->sculpt->kb;
00207 }
00208 
00209 static struct PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
00210 {
00211     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00212 
00213     if(!ob) {
00214         cddm->pbvh= NULL;
00215         return NULL;
00216     }
00217 
00218     if(!ob->sculpt)
00219         return NULL;
00220     if(ob->sculpt->pbvh) {
00221         cddm->pbvh= ob->sculpt->pbvh;
00222         cddm->pbvh_draw = can_pbvh_draw(ob, dm);
00223     }
00224 
00225     /* always build pbvh from original mesh, and only use it for drawing if
00226        this derivedmesh is just original mesh. it's the multires subsurf dm
00227        that this is actually for, to support a pbvh on a modified mesh */
00228     if(!cddm->pbvh && ob->type == OB_MESH) {
00229         SculptSession *ss= ob->sculpt;
00230         Mesh *me= ob->data;
00231         cddm->pbvh = BLI_pbvh_new();
00232         cddm->pbvh_draw = can_pbvh_draw(ob, dm);
00233         BLI_pbvh_build_mesh(cddm->pbvh, me->mface, me->mvert,
00234                             me->totface, me->totvert);
00235 
00236         if(ss->modifiers_active && ob->derivedDeform) {
00237             DerivedMesh *deformdm= ob->derivedDeform;
00238             float (*vertCos)[3];
00239             int totvert;
00240 
00241             totvert= deformdm->getNumVerts(deformdm);
00242             vertCos= MEM_callocN(3*totvert*sizeof(float), "cdDM_getPBVH vertCos");
00243             deformdm->getVertCos(deformdm, vertCos);
00244             BLI_pbvh_apply_vertCos(cddm->pbvh, vertCos);
00245             MEM_freeN(vertCos);
00246         }
00247     }
00248 
00249     return cddm->pbvh;
00250 }
00251 
00252 /* update vertex normals so that drawing smooth faces works during sculpt
00253    TODO: proper fix is to support the pbvh in all drawing modes */
00254 static void cdDM_update_normals_from_pbvh(DerivedMesh *dm)
00255 {
00256     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00257     float (*face_nors)[3];
00258 
00259     if(!cddm->pbvh || !cddm->pbvh_draw || !dm->numFaceData)
00260         return;
00261 
00262     face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
00263 
00264     BLI_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors);
00265 }
00266 
00267 static void cdDM_drawVerts(DerivedMesh *dm)
00268 {
00269     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00270     MVert *mv = cddm->mvert;
00271     int i;
00272 
00273     if( GPU_buffer_legacy(dm) ) {
00274         glBegin(GL_POINTS);
00275         for(i = 0; i < dm->numVertData; i++, mv++)
00276             glVertex3fv(mv->co);
00277         glEnd();
00278     }
00279     else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
00280         GPU_vertex_setup(dm);
00281         if( !GPU_buffer_legacy(dm) ) {
00282             if(dm->drawObject->tot_triangle_point)
00283                 glDrawArrays(GL_POINTS,0, dm->drawObject->tot_triangle_point);
00284             else
00285                 glDrawArrays(GL_POINTS,0, dm->drawObject->tot_loose_point);
00286         }
00287         GPU_buffer_unbind();
00288     }
00289 }
00290 
00291 static void cdDM_drawUVEdges(DerivedMesh *dm)
00292 {
00293     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00294     MFace *mf = cddm->mface;
00295     MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
00296     int i;
00297 
00298     if(mf) {
00299         if( GPU_buffer_legacy(dm) ) {
00300             glBegin(GL_LINES);
00301             for(i = 0; i < dm->numFaceData; i++, mf++, tf++) {
00302                 if(!(mf->flag&ME_HIDE)) {
00303                     glVertex2fv(tf->uv[0]);
00304                     glVertex2fv(tf->uv[1]);
00305 
00306                     glVertex2fv(tf->uv[1]);
00307                     glVertex2fv(tf->uv[2]);
00308 
00309                     if(!mf->v4) {
00310                         glVertex2fv(tf->uv[2]);
00311                         glVertex2fv(tf->uv[0]);
00312                     } else {
00313                         glVertex2fv(tf->uv[2]);
00314                         glVertex2fv(tf->uv[3]);
00315 
00316                         glVertex2fv(tf->uv[3]);
00317                         glVertex2fv(tf->uv[0]);
00318                     }
00319                 }
00320             }
00321             glEnd();
00322         }
00323         else {
00324             int prevstart = 0;
00325             int prevdraw = 1;
00326             int draw = 1;
00327             int curpos = 0;
00328 
00329             GPU_uvedge_setup(dm);
00330             if( !GPU_buffer_legacy(dm) ) {
00331                 for(i = 0; i < dm->numFaceData; i++, mf++) {
00332                     if(!(mf->flag&ME_HIDE)) {
00333                         draw = 1;
00334                     } 
00335                     else {
00336                         draw = 0;
00337                     }
00338                     if( prevdraw != draw ) {
00339                         if( prevdraw > 0 && (curpos-prevstart) > 0) {
00340                             glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
00341                         }
00342                         prevstart = curpos;
00343                     }
00344                     if( mf->v4 ) {
00345                         curpos += 8;
00346                     }
00347                     else {
00348                         curpos += 6;
00349                     }
00350                     prevdraw = draw;
00351                 }
00352                 if( prevdraw > 0 && (curpos-prevstart) > 0 ) {
00353                     glDrawArrays(GL_LINES,prevstart,curpos-prevstart);
00354                 }
00355             }
00356             GPU_buffer_unbind();
00357         }
00358     }
00359 }
00360 
00361 static void cdDM_drawEdges(DerivedMesh *dm, int drawLooseEdges, int drawAllEdges)
00362 {
00363     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00364     MVert *mvert = cddm->mvert;
00365     MEdge *medge = cddm->medge;
00366     int i;
00367     
00368     if( GPU_buffer_legacy(dm) ) {
00369         DEBUG_VBO( "Using legacy code. cdDM_drawEdges\n" );
00370         glBegin(GL_LINES);
00371         for(i = 0; i < dm->numEdgeData; i++, medge++) {
00372             if((drawAllEdges || (medge->flag&ME_EDGEDRAW))
00373                && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
00374                 glVertex3fv(mvert[medge->v1].co);
00375                 glVertex3fv(mvert[medge->v2].co);
00376             }
00377         }
00378         glEnd();
00379     }
00380     else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
00381         int prevstart = 0;
00382         int prevdraw = 1;
00383         int draw = 1;
00384 
00385         GPU_edge_setup(dm);
00386         if( !GPU_buffer_legacy(dm) ) {
00387             for(i = 0; i < dm->numEdgeData; i++, medge++) {
00388                 if((drawAllEdges || (medge->flag&ME_EDGEDRAW))
00389                    && (drawLooseEdges || !(medge->flag&ME_LOOSEEDGE))) {
00390                     draw = 1;
00391                 } 
00392                 else {
00393                     draw = 0;
00394                 }
00395                 if( prevdraw != draw ) {
00396                     if( prevdraw > 0 && (i-prevstart) > 0 ) {
00397                         GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
00398                     }
00399                     prevstart = i;
00400                 }
00401                 prevdraw = draw;
00402             }
00403             if( prevdraw > 0 && (i-prevstart) > 0 ) {
00404                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
00405             }
00406         }
00407         GPU_buffer_unbind();
00408     }
00409 }
00410 
00411 static void cdDM_drawLooseEdges(DerivedMesh *dm)
00412 {
00413     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00414     MVert *mvert = cddm->mvert;
00415     MEdge *medge = cddm->medge;
00416     int i;
00417 
00418     if( GPU_buffer_legacy(dm) ) {
00419         DEBUG_VBO( "Using legacy code. cdDM_drawLooseEdges\n" );
00420         glBegin(GL_LINES);
00421         for(i = 0; i < dm->numEdgeData; i++, medge++) {
00422             if(medge->flag&ME_LOOSEEDGE) {
00423                 glVertex3fv(mvert[medge->v1].co);
00424                 glVertex3fv(mvert[medge->v2].co);
00425             }
00426         }
00427         glEnd();
00428     }
00429     else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
00430         int prevstart = 0;
00431         int prevdraw = 1;
00432         int draw = 1;
00433 
00434         GPU_edge_setup(dm);
00435         if( !GPU_buffer_legacy(dm) ) {
00436             for(i = 0; i < dm->numEdgeData; i++, medge++) {
00437                 if(medge->flag&ME_LOOSEEDGE) {
00438                     draw = 1;
00439                 } 
00440                 else {
00441                     draw = 0;
00442                 }
00443                 if( prevdraw != draw ) {
00444                     if( prevdraw > 0 && (i-prevstart) > 0) {
00445                         GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
00446                     }
00447                     prevstart = i;
00448                 }
00449                 prevdraw = draw;
00450             }
00451             if( prevdraw > 0 && (i-prevstart) > 0 ) {
00452                 GPU_buffer_draw_elements( dm->drawObject->edges, GL_LINES, prevstart*2, (i-prevstart)*2  );
00453             }
00454         }
00455         GPU_buffer_unbind();
00456     }
00457 }
00458 
00459 static void cdDM_drawFacesSolid(DerivedMesh *dm,
00460                 float (*partial_redraw_planes)[4],
00461                 int UNUSED(fast), int (*setMaterial)(int, void *attribs))
00462 {
00463     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00464     MVert *mvert = cddm->mvert;
00465     MFace *mface = cddm->mface;
00466     float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
00467     int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1;
00468 
00469 #define PASSVERT(index) {                       \
00470     if(shademodel == GL_SMOOTH) {               \
00471         short *no = mvert[index].no;            \
00472         glNormal3sv(no);                        \
00473     }                                           \
00474     glVertex3fv(mvert[index].co);   \
00475 }
00476 
00477     if(cddm->pbvh && cddm->pbvh_draw) {
00478         if(dm->numFaceData) {
00479             float (*face_nors)[3] = CustomData_get_layer(&dm->faceData, CD_NORMAL);
00480 
00481             /* should be per face */
00482             if(!setMaterial(mface->mat_nr+1, NULL))
00483                 return;
00484 
00485             glShadeModel((mface->flag & ME_SMOOTH)? GL_SMOOTH: GL_FLAT);
00486             BLI_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors, (mface->flag & ME_SMOOTH));
00487             glShadeModel(GL_FLAT);
00488         }
00489 
00490         return;
00491     }
00492 
00493     if( GPU_buffer_legacy(dm) ) {
00494         DEBUG_VBO( "Using legacy code. cdDM_drawFacesSolid\n" );
00495         glBegin(glmode = GL_QUADS);
00496         for(a = 0; a < dm->numFaceData; a++, mface++) {
00497             int new_glmode, new_matnr, new_shademodel;
00498 
00499             new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
00500             new_matnr = mface->mat_nr + 1;
00501             new_shademodel = (mface->flag & ME_SMOOTH)?GL_SMOOTH:GL_FLAT;
00502             
00503             if(new_glmode != glmode || new_matnr != matnr
00504                || new_shademodel != shademodel) {
00505                 glEnd();
00506 
00507                 drawCurrentMat = setMaterial(matnr = new_matnr, NULL);
00508 
00509                 glShadeModel(shademodel = new_shademodel);
00510                 glBegin(glmode = new_glmode);
00511             } 
00512             
00513             if(drawCurrentMat) {
00514                 if(shademodel == GL_FLAT) {
00515                     if (nors) {
00516                         glNormal3fv(nors);
00517                     }
00518                     else {
00519                         /* TODO make this better (cache facenormals as layer?) */
00520                         float nor[3];
00521                         if(mface->v4) {
00522                             normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
00523                         } else {
00524                             normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
00525                         }
00526                         glNormal3fv(nor);
00527                     }
00528                 }
00529 
00530                 PASSVERT(mface->v1);
00531                 PASSVERT(mface->v2);
00532                 PASSVERT(mface->v3);
00533                 if(mface->v4) {
00534                     PASSVERT(mface->v4);
00535                 }
00536             }
00537 
00538             if(nors) nors += 3;
00539         }
00540         glEnd();
00541     }
00542     else {  /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
00543         GPU_vertex_setup( dm );
00544         GPU_normal_setup( dm );
00545         if( !GPU_buffer_legacy(dm) ) {
00546             glShadeModel(GL_SMOOTH);
00547             for( a = 0; a < dm->drawObject->totmaterial; a++ ) {
00548                 if( setMaterial(dm->drawObject->materials[a].mat_nr+1, NULL) )
00549                     glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start,
00550                              dm->drawObject->materials[a].totpoint);
00551             }
00552         }
00553         GPU_buffer_unbind( );
00554     }
00555 
00556 #undef PASSVERT
00557     glShadeModel(GL_FLAT);
00558 }
00559 
00560 static void cdDM_drawFacesColored(DerivedMesh *dm, int useTwoSided, unsigned char *col1, unsigned char *col2)
00561 {
00562     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00563     int a, glmode;
00564     unsigned char *cp1, *cp2;
00565     MVert *mvert = cddm->mvert;
00566     MFace *mface = cddm->mface;
00567 
00568     cp1 = col1;
00569     if(col2) {
00570         cp2 = col2;
00571     } else {
00572         cp2 = NULL;
00573         useTwoSided = 0;
00574     }
00575 
00576     /* there's a conflict here... twosided colors versus culling...? */
00577     /* defined by history, only texture faces have culling option */
00578     /* we need that as mesh option builtin, next to double sided lighting */
00579     if(col2) {
00580         glEnable(GL_CULL_FACE);
00581     }
00582 
00583     cdDM_update_normals_from_pbvh(dm);
00584 
00585     if( GPU_buffer_legacy(dm) ) {
00586         DEBUG_VBO( "Using legacy code. cdDM_drawFacesColored\n" );
00587         glShadeModel(GL_SMOOTH);
00588         glBegin(glmode = GL_QUADS);
00589         for(a = 0; a < dm->numFaceData; a++, mface++, cp1 += 16) {
00590             int new_glmode = mface->v4?GL_QUADS:GL_TRIANGLES;
00591 
00592             if(new_glmode != glmode) {
00593                 glEnd();
00594                 glBegin(glmode = new_glmode);
00595             }
00596                 
00597             glColor3ubv(cp1+0);
00598             glVertex3fv(mvert[mface->v1].co);
00599             glColor3ubv(cp1+4);
00600             glVertex3fv(mvert[mface->v2].co);
00601             glColor3ubv(cp1+8);
00602             glVertex3fv(mvert[mface->v3].co);
00603             if(mface->v4) {
00604                 glColor3ubv(cp1+12);
00605                 glVertex3fv(mvert[mface->v4].co);
00606             }
00607                 
00608             if(useTwoSided) {
00609                 glColor3ubv(cp2+8);
00610                 glVertex3fv(mvert[mface->v3].co );
00611                 glColor3ubv(cp2+4);
00612                 glVertex3fv(mvert[mface->v2].co );
00613                 glColor3ubv(cp2+0);
00614                 glVertex3fv(mvert[mface->v1].co );
00615                 if(mface->v4) {
00616                     glColor3ubv(cp2+12);
00617                     glVertex3fv(mvert[mface->v4].co );
00618                 }
00619             }
00620             if(col2) cp2 += 16;
00621         }
00622         glEnd();
00623     }
00624     else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
00625         GPU_color4_upload(dm,cp1);
00626         GPU_vertex_setup(dm);
00627         GPU_color_setup(dm);
00628         if( !GPU_buffer_legacy(dm) ) {
00629             glShadeModel(GL_SMOOTH);
00630             glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->tot_triangle_point);
00631 
00632             if( useTwoSided ) {
00633                 GPU_color4_upload(dm,cp2);
00634                 GPU_color_setup(dm);
00635                 glCullFace(GL_FRONT);
00636                 glDrawArrays(GL_TRIANGLES, 0, dm->drawObject->tot_triangle_point);
00637                 glCullFace(GL_BACK);
00638             }
00639         }
00640         GPU_buffer_unbind();
00641     }
00642 
00643     glShadeModel(GL_FLAT);
00644     glDisable(GL_CULL_FACE);
00645 }
00646 
00647 static void cdDM_drawFacesTex_common(DerivedMesh *dm,
00648                int (*drawParams)(MTFace *tface, int has_mcol, int matnr),
00649                int (*drawParamsMapped)(void *userData, int index),
00650                int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
00651                void *userData) 
00652 {
00653     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00654     MVert *mv = cddm->mvert;
00655     MFace *mf = DM_get_face_data_layer(dm, CD_MFACE);
00656     MCol *realcol = dm->getFaceDataArray(dm, CD_TEXTURE_MCOL);
00657     float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
00658     MTFace *tf = DM_get_face_data_layer(dm, CD_MTFACE);
00659     int i, j, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
00660     int startFace = 0 /*, lastFlag = 0xdeadbeef */ /* UNUSED */;
00661     MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
00662     if(!mcol)
00663         mcol = dm->getFaceDataArray(dm, CD_MCOL);
00664 
00665     cdDM_update_normals_from_pbvh(dm);
00666 
00667     if( GPU_buffer_legacy(dm) ) {
00668         DEBUG_VBO( "Using legacy code. cdDM_drawFacesTex_common\n" );
00669         for(i = 0; i < dm->numFaceData; i++, mf++) {
00670             MVert *mvert;
00671             int flag;
00672             unsigned char *cp = NULL;
00673 
00674             if(drawParams) {
00675                 flag = drawParams(tf? &tf[i]: NULL, (mcol != NULL), mf->mat_nr);
00676             }
00677             else {
00678                 if(index) {
00679                     orig = *index++;
00680                     if(orig == ORIGINDEX_NONE)      { if(nors) nors += 3; continue; }
00681                     if(drawParamsMapped) flag = drawParamsMapped(userData, orig);
00682                     else    { if(nors) nors += 3; continue; }
00683                 }
00684                 else
00685                     if(drawParamsMapped) flag = drawParamsMapped(userData, i);
00686                     else    { if(nors) nors += 3; continue; }
00687             }
00688             
00689             if(flag != 0) {
00690                 if (flag==1 && mcol)
00691                     cp= (unsigned char*) &mcol[i*4];
00692 
00693                 if(!(mf->flag&ME_SMOOTH)) {
00694                     if (nors) {
00695                         glNormal3fv(nors);
00696                     }
00697                     else {
00698                         float nor[3];
00699                         if(mf->v4) {
00700                             normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
00701                         } else {
00702                             normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
00703                         }
00704                         glNormal3fv(nor);
00705                     }
00706                 }
00707 
00708                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
00709                 if(tf) glTexCoord2fv(tf[i].uv[0]);
00710                 if(cp) glColor3ub(cp[3], cp[2], cp[1]);
00711                 mvert = &mv[mf->v1];
00712                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
00713                 glVertex3fv(mvert->co);
00714                     
00715                 if(tf) glTexCoord2fv(tf[i].uv[1]);
00716                 if(cp) glColor3ub(cp[7], cp[6], cp[5]);
00717                 mvert = &mv[mf->v2];
00718                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
00719                 glVertex3fv(mvert->co);
00720 
00721                 if(tf) glTexCoord2fv(tf[i].uv[2]);
00722                 if(cp) glColor3ub(cp[11], cp[10], cp[9]);
00723                 mvert = &mv[mf->v3];
00724                 if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
00725                 glVertex3fv(mvert->co);
00726 
00727                 if(mf->v4) {
00728                     if(tf) glTexCoord2fv(tf[i].uv[3]);
00729                     if(cp) glColor3ub(cp[15], cp[14], cp[13]);
00730                     mvert = &mv[mf->v4];
00731                     if(mf->flag&ME_SMOOTH) glNormal3sv(mvert->no);
00732                     glVertex3fv(mvert->co);
00733                 }
00734                 glEnd();
00735             }
00736             
00737             if(nors) nors += 3;
00738         }
00739     } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
00740         MCol *col = realcol;
00741         if(!col)
00742             col = mcol;
00743 
00744         GPU_vertex_setup( dm );
00745         GPU_normal_setup( dm );
00746         GPU_uv_setup( dm );
00747         if( col != NULL ) {
00748             /*if( realcol && dm->drawObject->colType == CD_TEXTURE_MCOL )  {
00749                 col = 0;
00750             } else if( mcol && dm->drawObject->colType == CD_MCOL ) {
00751                 col = 0;
00752             }
00753             
00754             if( col != 0 ) {*/
00755                 unsigned char *colors = MEM_mallocN(dm->getNumFaces(dm)*4*3*sizeof(unsigned char), "cdDM_drawFacesTex_common");
00756                 for( i=0; i < dm->getNumFaces(dm); i++ ) {
00757                     for( j=0; j < 4; j++ ) {
00758                         /* bgr -> rgb is intentional (and stupid), but how its stored internally */
00759                         colors[i*12+j*3] = col[i*4+j].b;
00760                         colors[i*12+j*3+1] = col[i*4+j].g;
00761                         colors[i*12+j*3+2] = col[i*4+j].r;
00762                     }
00763                 }
00764                 GPU_color3_upload(dm,colors);
00765                 MEM_freeN(colors);
00766                 if(realcol)
00767                     dm->drawObject->colType = CD_TEXTURE_MCOL;
00768                 else if(mcol)
00769                     dm->drawObject->colType = CD_MCOL;
00770             //}
00771             GPU_color_setup( dm );
00772         }
00773 
00774         if( !GPU_buffer_legacy(dm) ) {
00775             int tottri = dm->drawObject->tot_triangle_point/3;
00776             int next_actualFace= dm->drawObject->triangle_to_mface[0];
00777 
00778             glShadeModel( GL_SMOOTH );
00779             /* lastFlag = 0; */ /* UNUSED */
00780             for(i = 0; i < tottri; i++) {
00781                 int actualFace = next_actualFace;
00782                 int flag = 1;
00783                 int flush = 0;
00784 
00785                 if(i != tottri-1)
00786                     next_actualFace= dm->drawObject->triangle_to_mface[i+1];
00787 
00788                 if(drawParams) {
00789                     flag = drawParams(tf? &tf[actualFace]: NULL, (mcol != NULL), mf[actualFace].mat_nr);
00790                 }
00791                 else {
00792                     if(index) {
00793                         orig = index[actualFace];
00794                         if(orig == ORIGINDEX_NONE) continue;
00795                         if(drawParamsMapped)
00796                             flag = drawParamsMapped(userData, orig);
00797                     }
00798                     else
00799                         if(drawParamsMapped)
00800                             flag = drawParamsMapped(userData, actualFace);
00801                 }
00802 
00803                 /* flush buffer if current triangle isn't drawable or it's last triangle */
00804                 flush= !flag || i == tottri - 1;
00805 
00806                 if(!flush && compareDrawOptions) {
00807                     /* also compare draw options and flush buffer if they're different
00808                        need for face selection highlight in edit mode */
00809                     flush|= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
00810                 }
00811 
00812                 if(flush) {
00813                     int first= startFace*3;
00814                     int count= (i-startFace+(flag ? 1 : 0))*3; /* Add one to the length if we're drawing at the end of the array */
00815 
00816                     if(count) {
00817                         if (col)
00818                             GPU_color_switch(1);
00819                         else
00820                             GPU_color_switch(0);
00821 
00822                         glDrawArrays(GL_TRIANGLES, first, count);
00823                     }
00824 
00825                     startFace = i + 1;
00826                 }
00827             }
00828         }
00829 
00830         GPU_buffer_unbind();
00831         glShadeModel( GL_FLAT );
00832     }
00833 }
00834 
00835 static void cdDM_drawFacesTex(DerivedMesh *dm,
00836                int (*setDrawOptions)(MTFace *tface, int has_mcol, int matnr),
00837                int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
00838                void *userData)
00839 {
00840     cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
00841 }
00842 
00843 static void cdDM_drawMappedFaces(DerivedMesh *dm,
00844             int (*setDrawOptions)(void *userData, int index, int *drawSmooth_r),
00845             int (*setMaterial)(int, void *attribs),
00846             int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
00847             void *userData, int useColors)
00848 {
00849     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
00850     MVert *mv = cddm->mvert;
00851     MFace *mf = cddm->mface;
00852     MCol *mc;
00853     float *nors= dm->getFaceDataArray(dm, CD_NORMAL);
00854     int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
00855 
00856     mc = DM_get_face_data_layer(dm, CD_ID_MCOL);
00857     if(!mc)
00858         mc = DM_get_face_data_layer(dm, CD_WEIGHT_MCOL);
00859     if(!mc)
00860         mc = DM_get_face_data_layer(dm, CD_MCOL);
00861 
00862     cdDM_update_normals_from_pbvh(dm);
00863 
00864     /* back-buffer always uses legacy since VBO's would need the
00865      * color array temporarily overwritten for drawing, then reset. */
00866     if( GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) {
00867         DEBUG_VBO( "Using legacy code. cdDM_drawMappedFaces\n" );
00868         for(i = 0; i < dm->numFaceData; i++, mf++) {
00869             int drawSmooth = (mf->flag & ME_SMOOTH);
00870             int draw= 1;
00871 
00872             orig= (index==NULL) ? i : *index++;
00873             
00874             if(orig == ORIGINDEX_NONE)
00875                 draw= setMaterial(mf->mat_nr + 1, NULL);
00876             else if (setDrawOptions != NULL)
00877                 draw= setDrawOptions(userData, orig, &drawSmooth);
00878 
00879             if(draw) {
00880                 unsigned char *cp = NULL;
00881 
00882                 if(useColors && mc)
00883                     cp = (unsigned char *)&mc[i * 4];
00884 
00885                 /* no need to set shading mode to flat because
00886                 *  normals are already used to change shading */
00887                 glShadeModel(GL_SMOOTH);
00888                 glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
00889 
00890                 if (!drawSmooth) {
00891                     if (nors) {
00892                         glNormal3fv(nors);
00893                     }
00894                     else {
00895                         float nor[3];
00896                         if(mf->v4) {
00897                             normal_quad_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
00898                         } else {
00899                             normal_tri_v3( nor,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
00900                         }
00901                         glNormal3fv(nor);
00902                     }
00903 
00904                     if(cp) glColor3ub(cp[3], cp[2], cp[1]);
00905                     glVertex3fv(mv[mf->v1].co);
00906                     if(cp) glColor3ub(cp[7], cp[6], cp[5]);
00907                     glVertex3fv(mv[mf->v2].co);
00908                     if(cp) glColor3ub(cp[11], cp[10], cp[9]);
00909                     glVertex3fv(mv[mf->v3].co);
00910                     if(mf->v4) {
00911                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
00912                         glVertex3fv(mv[mf->v4].co);
00913                     }
00914                 } else {
00915                     if(cp) glColor3ub(cp[3], cp[2], cp[1]);
00916                     glNormal3sv(mv[mf->v1].no);
00917                     glVertex3fv(mv[mf->v1].co);
00918                     if(cp) glColor3ub(cp[7], cp[6], cp[5]);
00919                     glNormal3sv(mv[mf->v2].no);
00920                     glVertex3fv(mv[mf->v2].co);
00921                     if(cp) glColor3ub(cp[11], cp[10], cp[9]);
00922                     glNormal3sv(mv[mf->v3].no);
00923                     glVertex3fv(mv[mf->v3].co);
00924                     if(mf->v4) {
00925                         if(cp) glColor3ub(cp[15], cp[14], cp[13]);
00926                         glNormal3sv(mv[mf->v4].no);
00927                         glVertex3fv(mv[mf->v4].co);
00928                     }
00929                 }
00930 
00931                 glEnd();
00932             }
00933             
00934             if (nors) nors += 3;
00935         }
00936     }
00937     else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */
00938         int prevstart = 0;
00939         GPU_vertex_setup(dm);
00940         GPU_normal_setup(dm);
00941         if( useColors && mc )
00942             GPU_color_setup(dm);
00943         if( !GPU_buffer_legacy(dm) ) {
00944             int tottri = dm->drawObject->tot_triangle_point/3;
00945             glShadeModel(GL_SMOOTH);
00946             
00947             if(tottri == 0) {
00948                 /* avoid buffer problems in following code */
00949             }
00950             if(setDrawOptions == NULL) {
00951                 /* just draw the entire face array */
00952                 glDrawArrays(GL_TRIANGLES, 0, (tottri) * 3);
00953             }
00954             else {
00955                 /* we need to check if the next material changes */
00956                 int next_actualFace= dm->drawObject->triangle_to_mface[0];
00957                 
00958                 for( i = 0; i < tottri; i++ ) {
00959                     //int actualFace = dm->drawObject->triangle_to_mface[i];
00960                     int actualFace = next_actualFace;
00961                     MFace *mface= mf + actualFace;
00962                     int drawSmooth= (mface->flag & ME_SMOOTH);
00963                     int draw = 1;
00964                     int flush = 0;
00965 
00966                     if(i != tottri-1)
00967                         next_actualFace= dm->drawObject->triangle_to_mface[i+1];
00968 
00969                     orig= (index==NULL) ? actualFace : index[actualFace];
00970 
00971                     if(orig == ORIGINDEX_NONE)
00972                         draw= setMaterial(mface->mat_nr + 1, NULL);
00973                     else if (setDrawOptions != NULL)
00974                         draw= setDrawOptions(userData, orig, &drawSmooth);
00975     
00976                     /* Goal is to draw as long of a contiguous triangle
00977                        array as possible, so draw when we hit either an
00978                        invisible triangle or at the end of the array */
00979 
00980                     /* flush buffer if current triangle isn't drawable or it's last triangle... */
00981                     flush= !draw || i == tottri - 1;
00982 
00983                     /* ... or when material setting is dissferent  */
00984                     flush|= mf[actualFace].mat_nr != mf[next_actualFace].mat_nr;
00985 
00986                     if(!flush && compareDrawOptions) {
00987                         flush|= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
00988                     }
00989 
00990                     if(flush) {
00991                         int first= prevstart*3;
00992                         int count= (i-prevstart+(draw ? 1 : 0))*3; /* Add one to the length if we're drawing at the end of the array */
00993 
00994                         if(count)
00995                             glDrawArrays(GL_TRIANGLES, first, count);
00996 
00997                         prevstart = i + 1;
00998                     }
00999                 }
01000             }
01001 
01002             glShadeModel(GL_FLAT);
01003         }
01004         GPU_buffer_unbind();
01005     }
01006 }
01007 
01008 static void cdDM_drawMappedFacesTex(DerivedMesh *dm,
01009                int (*setDrawOptions)(void *userData, int index),
01010                int (*compareDrawOptions)(void *userData, int cur_index, int next_index),
01011                void *userData)
01012 {
01013     cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
01014 }
01015 
01016 static void cddm_draw_attrib_vertex(DMVertexAttribs *attribs, MVert *mvert, int a, int index, int vert, int smoothnormal)
01017 {
01018     int b;
01019 
01020     /* orco texture coordinates */
01021     if(attribs->totorco) {
01022         if(attribs->orco.glTexco)
01023             glTexCoord3fv(attribs->orco.array[index]);
01024         else
01025             glVertexAttrib3fvARB(attribs->orco.glIndex, attribs->orco.array[index]);
01026     }
01027 
01028     /* uv texture coordinates */
01029     for(b = 0; b < attribs->tottface; b++) {
01030         MTFace *tf = &attribs->tface[b].array[a];
01031 
01032         if(attribs->tface[b].glTexco)
01033             glTexCoord2fv(tf->uv[vert]);
01034         else
01035             glVertexAttrib2fvARB(attribs->tface[b].glIndex, tf->uv[vert]);
01036     }
01037 
01038     /* vertex colors */
01039     for(b = 0; b < attribs->totmcol; b++) {
01040         MCol *cp = &attribs->mcol[b].array[a*4 + vert];
01041         GLubyte col[4];
01042         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
01043         glVertexAttrib4ubvARB(attribs->mcol[b].glIndex, col);
01044     }
01045 
01046     /* tangent for normal mapping */
01047     if(attribs->tottang) {
01048         float *tang = attribs->tang.array[a*4 + vert];
01049         glVertexAttrib4fvARB(attribs->tang.glIndex, tang);
01050     }
01051 
01052     /* vertex normal */
01053     if(smoothnormal)
01054         glNormal3sv(mvert[index].no);
01055     
01056     /* vertex coordinate */
01057     glVertex3fv(mvert[index].co);
01058 }
01059 
01060 static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm,
01061                int (*setMaterial)(int, void *attribs),
01062                int (*setDrawOptions)(void *userData, int index),
01063                void *userData)
01064 {
01065     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
01066     GPUVertexAttribs gattribs;
01067     DMVertexAttribs attribs;
01068     MVert *mvert = cddm->mvert;
01069     MFace *mface = cddm->mface;
01070     /* MTFace *tf = dm->getFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */
01071     float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
01072     int a, b, dodraw, matnr, new_matnr;
01073     int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
01074 
01075     cdDM_update_normals_from_pbvh(dm);
01076 
01077     matnr = -1;
01078     dodraw = 0;
01079 
01080     glShadeModel(GL_SMOOTH);
01081 
01082     if( GPU_buffer_legacy(dm) || setDrawOptions != NULL ) {
01083         DEBUG_VBO( "Using legacy code. cdDM_drawMappedFacesGLSL\n" );
01084         memset(&attribs, 0, sizeof(attribs));
01085 
01086         glBegin(GL_QUADS);
01087 
01088         for(a = 0; a < dm->numFaceData; a++, mface++) {
01089             const int smoothnormal = (mface->flag & ME_SMOOTH);
01090             new_matnr = mface->mat_nr + 1;
01091 
01092             if(new_matnr != matnr) {
01093                 glEnd();
01094 
01095                 dodraw = setMaterial(matnr = new_matnr, &gattribs);
01096                 if(dodraw)
01097                     DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
01098 
01099                 glBegin(GL_QUADS);
01100             }
01101 
01102             if(!dodraw) {
01103                 continue;
01104             }
01105             else if(setDrawOptions) {
01106                 orig = (index)? index[a]: a;
01107 
01108                 if(orig == ORIGINDEX_NONE) {
01109                     /* since the material is set by setMaterial(), faces with no
01110                      * origin can be assumed to be generated by a modifier */ 
01111                     
01112                     /* continue */
01113                 }
01114                 else if(!setDrawOptions(userData, orig))
01115                     continue;
01116             }
01117 
01118             if(!smoothnormal) {
01119                 if(nors) {
01120                     glNormal3fv(nors[a]);
01121                 }
01122                 else {
01123                     /* TODO ideally a normal layer should always be available */
01124                     float nor[3];
01125                     if(mface->v4) {
01126                         normal_quad_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co);
01127                     } else {
01128                         normal_tri_v3( nor,mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co);
01129                     }
01130                     glNormal3fv(nor);
01131                 }
01132             }
01133 
01134             cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, smoothnormal);
01135             cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v2, 1, smoothnormal);
01136             cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal);
01137 
01138             if(mface->v4)
01139                 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v4, 3, smoothnormal);
01140             else
01141                 cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, smoothnormal);
01142         }
01143         glEnd();
01144     }
01145     else {
01146         GPUBuffer *buffer = NULL;
01147         char *varray = NULL;
01148         int numdata = 0, elementsize = 0, offset;
01149         int start = 0, numfaces = 0 /* , prevdraw = 0 */ /* UNUSED */, curface = 0;
01150         int i;
01151 
01152         MFace *mf = mface;
01153         GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/
01154         memset(&attribs, 0, sizeof(attribs));
01155 
01156         GPU_vertex_setup(dm);
01157         GPU_normal_setup(dm);
01158 
01159         if( !GPU_buffer_legacy(dm) ) {
01160             for( i = 0; i < dm->drawObject->tot_triangle_point/3; i++ ) {
01161 
01162                 a = dm->drawObject->triangle_to_mface[i];
01163 
01164                 mface = mf + a;
01165                 new_matnr = mface->mat_nr + 1;
01166 
01167                 if(new_matnr != matnr ) {
01168                     numfaces = curface - start;
01169                     if( numfaces > 0 ) {
01170 
01171                         if( dodraw ) {
01172 
01173                             if( numdata != 0 ) {
01174 
01175                                 GPU_buffer_unlock(buffer);
01176 
01177                                 GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
01178                             }
01179 
01180                             glDrawArrays(GL_TRIANGLES,start*3,numfaces*3);
01181 
01182                             if( numdata != 0 ) {
01183 
01184                                 GPU_buffer_free(buffer);
01185 
01186                                 buffer = NULL;
01187                             }
01188 
01189                         }
01190                     }
01191                     numdata = 0;
01192                     start = curface;
01193                     /* prevdraw = dodraw; */ /* UNUSED */
01194                     dodraw = setMaterial(matnr = new_matnr, &gattribs);
01195                     if(dodraw) {
01196                         DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
01197 
01198                         if(attribs.totorco) {
01199                             datatypes[numdata].index = attribs.orco.glIndex;
01200                             datatypes[numdata].size = 3;
01201                             datatypes[numdata].type = GL_FLOAT;
01202                             numdata++;
01203                         }
01204                         for(b = 0; b < attribs.tottface; b++) {
01205                             datatypes[numdata].index = attribs.tface[b].glIndex;
01206                             datatypes[numdata].size = 2;
01207                             datatypes[numdata].type = GL_FLOAT;
01208                             numdata++;
01209                         }   
01210                         for(b = 0; b < attribs.totmcol; b++) {
01211                             datatypes[numdata].index = attribs.mcol[b].glIndex;
01212                             datatypes[numdata].size = 4;
01213                             datatypes[numdata].type = GL_UNSIGNED_BYTE;
01214                             numdata++;
01215                         }   
01216                         if(attribs.tottang) {
01217                             datatypes[numdata].index = attribs.tang.glIndex;
01218                             datatypes[numdata].size = 4;
01219                             datatypes[numdata].type = GL_FLOAT;
01220                             numdata++;
01221                         }
01222                         if( numdata != 0 ) {
01223                             elementsize = GPU_attrib_element_size( datatypes, numdata );
01224                             buffer = GPU_buffer_alloc( elementsize*dm->drawObject->tot_triangle_point);
01225                             if( buffer == NULL ) {
01226                                 GPU_buffer_unbind();
01227                                 dm->drawObject->legacy = 1;
01228                                 return;
01229                             }
01230                             varray = GPU_buffer_lock_stream(buffer);
01231                             if( varray == NULL ) {
01232                                 GPU_buffer_unbind();
01233                                 GPU_buffer_free(buffer);
01234                                 dm->drawObject->legacy = 1;
01235                                 return;
01236                             }
01237                         }
01238                         else {
01239                             /* if the buffer was set, dont use it again.
01240                              * prevdraw was assumed true but didnt run so set to false - [#21036] */
01241                             /* prevdraw= 0; */ /* UNUSED */
01242                             buffer= NULL;
01243                         }
01244                     }
01245                 }
01246 
01247                 if(dodraw && numdata != 0 ) {
01248                     offset = 0;
01249                     if(attribs.totorco) {
01250                         copy_v3_v3((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v1]);
01251                         copy_v3_v3((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v2]);
01252                         copy_v3_v3((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v3]);
01253                         offset += sizeof(float)*3;
01254                     }
01255                     for(b = 0; b < attribs.tottface; b++) {
01256                         MTFace *tf = &attribs.tface[b].array[a];
01257                         copy_v2_v2((float *)&varray[elementsize*curface*3+offset],tf->uv[0]);
01258                         copy_v2_v2((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[1]);
01259 
01260                         copy_v2_v2((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[2]);
01261                         offset += sizeof(float)*2;
01262                     }
01263                     for(b = 0; b < attribs.totmcol; b++) {
01264                         MCol *cp = &attribs.mcol[b].array[a*4 + 0];
01265                         GLubyte col[4];
01266                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
01267                         copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset], (char *)col);
01268                         cp = &attribs.mcol[b].array[a*4 + 1];
01269                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
01270                         copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset+elementsize], (char *)col);
01271                         cp = &attribs.mcol[b].array[a*4 + 2];
01272                         col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
01273                         copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset+elementsize*2], (char *)col);
01274                         offset += sizeof(unsigned char)*4;
01275                     }   
01276                     if(attribs.tottang) {
01277                         float *tang = attribs.tang.array[a*4 + 0];
01278                         copy_v4_v4((float *)&varray[elementsize*curface*3+offset], tang);
01279                         tang = attribs.tang.array[a*4 + 1];
01280                         copy_v4_v4((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
01281                         tang = attribs.tang.array[a*4 + 2];
01282                         copy_v4_v4((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
01283                         offset += sizeof(float)*4;
01284                     }
01285                     (void)offset;
01286                 }
01287                 curface++;
01288                 if(mface->v4) {
01289                     if(dodraw && numdata != 0 ) {
01290                         offset = 0;
01291                         if(attribs.totorco) {
01292                             copy_v3_v3((float *)&varray[elementsize*curface*3],(float *)attribs.orco.array[mface->v3]);
01293                             copy_v3_v3((float *)&varray[elementsize*curface*3+elementsize],(float *)attribs.orco.array[mface->v4]);
01294                             copy_v3_v3((float *)&varray[elementsize*curface*3+elementsize*2],(float *)attribs.orco.array[mface->v1]);
01295                             offset += sizeof(float)*3;
01296                         }
01297                         for(b = 0; b < attribs.tottface; b++) {
01298                             MTFace *tf = &attribs.tface[b].array[a];
01299                             copy_v2_v2((float *)&varray[elementsize*curface*3+offset],tf->uv[2]);
01300                             copy_v2_v2((float *)&varray[elementsize*curface*3+offset+elementsize],tf->uv[3]);
01301                             copy_v2_v2((float *)&varray[elementsize*curface*3+offset+elementsize*2],tf->uv[0]);
01302                             offset += sizeof(float)*2;
01303                         }
01304                         for(b = 0; b < attribs.totmcol; b++) {
01305                             MCol *cp = &attribs.mcol[b].array[a*4 + 2];
01306                             GLubyte col[4];
01307                             col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
01308                             copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset], (char *)col);
01309                             cp = &attribs.mcol[b].array[a*4 + 3];
01310                             col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
01311                             copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset+elementsize], (char *)col);
01312                             cp = &attribs.mcol[b].array[a*4 + 0];
01313                             col[0]= cp->b; col[1]= cp->g; col[2]= cp->r; col[3]= cp->a;
01314                             copy_v4_v4_char((char *)&varray[elementsize*curface*3+offset+elementsize*2], (char *)col);
01315                             offset += sizeof(unsigned char)*4;
01316                         }   
01317                         if(attribs.tottang) {
01318                             float *tang = attribs.tang.array[a*4 + 2];
01319                             copy_v4_v4((float *)&varray[elementsize*curface*3+offset], tang);
01320                             tang = attribs.tang.array[a*4 + 3];
01321                             copy_v4_v4((float *)&varray[elementsize*curface*3+offset+elementsize], tang);
01322                             tang = attribs.tang.array[a*4 + 0];
01323                             copy_v4_v4((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang);
01324                             offset += sizeof(float)*4;
01325                         }
01326                         (void)offset;
01327                     }
01328                     curface++;
01329                     i++;
01330                 }
01331             }
01332             numfaces = curface - start;
01333             if( numfaces > 0 ) {
01334                 if( dodraw ) {
01335                     if( numdata != 0 ) {
01336                         GPU_buffer_unlock(buffer);
01337                         GPU_interleaved_attrib_setup(buffer,datatypes,numdata);
01338                     }
01339                     glDrawArrays(GL_TRIANGLES,start*3,(curface-start)*3);
01340                 }
01341             }
01342             GPU_buffer_unbind();
01343         }
01344         GPU_buffer_free(buffer);
01345     }
01346 
01347     glShadeModel(GL_FLAT);
01348 }
01349 
01350 static void cdDM_drawFacesGLSL(DerivedMesh *dm,int (*setMaterial)(int, void *attribs))
01351 {
01352     dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL);
01353 }
01354 
01355 static void cdDM_drawMappedFacesMat(DerivedMesh *dm,
01356     void (*setMaterial)(void *userData, int, void *attribs),
01357     int (*setFace)(void *userData, int index), void *userData)
01358 {
01359     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
01360     GPUVertexAttribs gattribs;
01361     DMVertexAttribs attribs;
01362     MVert *mvert = cddm->mvert;
01363     MFace *mf = cddm->mface;
01364     float (*nors)[3] = dm->getFaceDataArray(dm, CD_NORMAL);
01365     int a, matnr, new_matnr;
01366     int orig, *index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
01367 
01368     cdDM_update_normals_from_pbvh(dm);
01369 
01370     matnr = -1;
01371 
01372     glShadeModel(GL_SMOOTH);
01373 
01374     memset(&attribs, 0, sizeof(attribs));
01375 
01376     glBegin(GL_QUADS);
01377 
01378     for(a = 0; a < dm->numFaceData; a++, mf++) {
01379         const int smoothnormal = (mf->flag & ME_SMOOTH);
01380 
01381         /* material */
01382         new_matnr = mf->mat_nr + 1;
01383 
01384         if(new_matnr != matnr) {
01385             glEnd();
01386 
01387             setMaterial(userData, matnr = new_matnr, &gattribs);
01388             DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs);
01389 
01390             glBegin(GL_QUADS);
01391         }
01392 
01393         /* skipping faces */
01394         if(setFace) {
01395             orig = (index)? index[a]: a;
01396 
01397             if(orig != ORIGINDEX_NONE && !setFace(userData, orig))
01398                 continue;
01399         }
01400 
01401         /* smooth normal */
01402         if(!smoothnormal) {
01403             if(nors) {
01404                 glNormal3fv(nors[a]);
01405             }
01406             else {
01407                 /* TODO ideally a normal layer should always be available */
01408                 float nor[3];
01409 
01410                 if(mf->v4)
01411                     normal_quad_v3( nor,mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co, mvert[mf->v4].co);
01412                 else
01413                     normal_tri_v3( nor,mvert[mf->v1].co, mvert[mf->v2].co, mvert[mf->v3].co);
01414 
01415                 glNormal3fv(nor);
01416             }
01417         }
01418 
01419         /* vertices */
01420         cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v1, 0, smoothnormal);
01421         cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v2, 1, smoothnormal);
01422         cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v3, 2, smoothnormal);
01423 
01424         if(mf->v4)
01425             cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v4, 3, smoothnormal);
01426         else
01427             cddm_draw_attrib_vertex(&attribs, mvert, a, mf->v3, 2, smoothnormal);
01428     }
01429     glEnd();
01430 
01431     glShadeModel(GL_FLAT);
01432 }
01433 
01434 static void cdDM_drawMappedEdges(DerivedMesh *dm, int (*setDrawOptions)(void *userData, int index), void *userData)
01435 {
01436     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
01437     MVert *vert = cddm->mvert;
01438     MEdge *edge = cddm->medge;
01439     int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
01440 
01441     glBegin(GL_LINES);
01442     for(i = 0; i < dm->numEdgeData; i++, edge++) {
01443         if(index) {
01444             orig = *index++;
01445             if(setDrawOptions && orig == ORIGINDEX_NONE) continue;
01446         }
01447         else
01448             orig = i;
01449 
01450         if(!setDrawOptions || setDrawOptions(userData, orig)) {
01451             glVertex3fv(vert[edge->v1].co);
01452             glVertex3fv(vert[edge->v2].co);
01453         }
01454     }
01455     glEnd();
01456 }
01457 
01458 static void cdDM_foreachMappedVert(
01459                            DerivedMesh *dm,
01460                            void (*func)(void *userData, int index, float *co,
01461                                         float *no_f, short *no_s),
01462                            void *userData)
01463 {
01464     MVert *mv = CDDM_get_verts(dm);
01465     int i, orig, *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
01466 
01467     for(i = 0; i < dm->numVertData; i++, mv++) {
01468         if(index) {
01469             orig = *index++;
01470             if(orig == ORIGINDEX_NONE) continue;
01471             func(userData, orig, mv->co, NULL, mv->no);
01472         }
01473         else
01474             func(userData, i, mv->co, NULL, mv->no);
01475     }
01476 }
01477 
01478 static void cdDM_foreachMappedEdge(
01479                            DerivedMesh *dm,
01480                            void (*func)(void *userData, int index,
01481                                         float *v0co, float *v1co),
01482                            void *userData)
01483 {
01484     CDDerivedMesh *cddm = (CDDerivedMesh*) dm;
01485     MVert *mv = cddm->mvert;
01486     MEdge *med = cddm->medge;
01487     int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
01488 
01489     for(i = 0; i < dm->numEdgeData; i++, med++) {
01490         if (index) {
01491             orig = *index++;
01492             if(orig == ORIGINDEX_NONE) continue;
01493             func(userData, orig, mv[med->v1].co, mv[med->v2].co);
01494         }
01495         else
01496             func(userData, i, mv[med->v1].co, mv[med->v2].co);
01497     }
01498 }
01499 
01500 static void cdDM_foreachMappedFaceCenter(
01501                            DerivedMesh *dm,
01502                            void (*func)(void *userData, int index,
01503                                         float *cent, float *no),
01504                            void *userData)
01505 {
01506     CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
01507     MVert *mv = cddm->mvert;
01508     MFace *mf = cddm->mface;
01509     int i, orig, *index = DM_get_face_data_layer(dm, CD_ORIGINDEX);
01510 
01511     for(i = 0; i < dm->numFaceData; i++, mf++) {
01512         float cent[3];
01513         float no[3];
01514 
01515         if (index) {
01516             orig = *index++;
01517             if(orig == ORIGINDEX_NONE) continue;
01518         }
01519         else
01520             orig = i;
01521 
01522         copy_v3_v3(cent, mv[mf->v1].co);
01523         add_v3_v3(cent, mv[mf->v2].co);
01524         add_v3_v3(cent, mv[mf->v3].co);
01525 
01526         if (mf->v4) {
01527             normal_quad_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co);
01528             add_v3_v3(cent, mv[mf->v4].co);
01529             mul_v3_fl(cent, 0.25f);
01530         } else {
01531             normal_tri_v3( no,mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co);
01532             mul_v3_fl(cent, 0.33333333333f);
01533         }
01534 
01535         func(userData, orig, cent, no);
01536     }
01537 }
01538 
01539 static void cdDM_free_internal(CDDerivedMesh *cddm)
01540 {
01541     if(cddm->fmap) MEM_freeN(cddm->fmap);
01542     if(cddm->fmap_mem) MEM_freeN(cddm->fmap_mem);
01543 }
01544 
01545 static void cdDM_release(DerivedMesh *dm)
01546 {
01547     CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
01548 
01549     if (DM_release(dm)) {
01550         cdDM_free_internal(cddm);
01551         MEM_freeN(cddm);
01552     }
01553 }
01554 
01555 /**************** CDDM interface functions ****************/
01556 static CDDerivedMesh *cdDM_create(const char *desc)
01557 {
01558     CDDerivedMesh *cddm;
01559     DerivedMesh *dm;
01560 
01561     cddm = MEM_callocN(sizeof(*cddm), desc);
01562     dm = &cddm->dm;
01563 
01564     dm->getMinMax = cdDM_getMinMax;
01565 
01566     dm->getNumVerts = cdDM_getNumVerts;
01567     dm->getNumFaces = cdDM_getNumFaces;
01568     dm->getNumEdges = cdDM_getNumEdges;
01569 
01570     dm->getVert = cdDM_getVert;
01571     dm->getEdge = cdDM_getEdge;
01572     dm->getFace = cdDM_getFace;
01573     dm->copyVertArray = cdDM_copyVertArray;
01574     dm->copyEdgeArray = cdDM_copyEdgeArray;
01575     dm->copyFaceArray = cdDM_copyFaceArray;
01576     dm->getVertData = DM_get_vert_data;
01577     dm->getEdgeData = DM_get_edge_data;
01578     dm->getFaceData = DM_get_face_data;
01579     dm->getVertDataArray = DM_get_vert_data_layer;
01580     dm->getEdgeDataArray = DM_get_edge_data_layer;
01581     dm->getFaceDataArray = DM_get_face_data_layer;
01582 
01583     dm->getVertCos = cdDM_getVertCos;
01584     dm->getVertCo = cdDM_getVertCo;
01585     dm->getVertNo = cdDM_getVertNo;
01586 
01587     dm->getPBVH = cdDM_getPBVH;
01588     dm->getFaceMap = cdDM_getFaceMap;
01589 
01590     dm->drawVerts = cdDM_drawVerts;
01591 
01592     dm->drawUVEdges = cdDM_drawUVEdges;
01593     dm->drawEdges = cdDM_drawEdges;
01594     dm->drawLooseEdges = cdDM_drawLooseEdges;
01595     dm->drawMappedEdges = cdDM_drawMappedEdges;
01596 
01597     dm->drawFacesSolid = cdDM_drawFacesSolid;
01598     dm->drawFacesColored = cdDM_drawFacesColored;
01599     dm->drawFacesTex = cdDM_drawFacesTex;
01600     dm->drawFacesGLSL = cdDM_drawFacesGLSL;
01601     dm->drawMappedFaces = cdDM_drawMappedFaces;
01602     dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
01603     dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
01604     dm->drawMappedFacesMat = cdDM_drawMappedFacesMat;
01605 
01606     dm->foreachMappedVert = cdDM_foreachMappedVert;
01607     dm->foreachMappedEdge = cdDM_foreachMappedEdge;
01608     dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
01609 
01610     dm->release = cdDM_release;
01611 
01612     return cddm;
01613 }
01614 
01615 DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces)
01616 {
01617     CDDerivedMesh *cddm = cdDM_create("CDDM_new dm");
01618     DerivedMesh *dm = &cddm->dm;
01619 
01620     DM_init(dm, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
01621 
01622     CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
01623     CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
01624     CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
01625 
01626     CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
01627     CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
01628     CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
01629 
01630     cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
01631     cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
01632     cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
01633 
01634     return dm;
01635 }
01636 
01637 DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob))
01638 {
01639     CDDerivedMesh *cddm = cdDM_create("CDDM_from_mesh dm");
01640     DerivedMesh *dm = &cddm->dm;
01641     CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS);
01642     int alloctype;
01643 
01644     /* this does a referenced copy, with an exception for fluidsim */
01645 
01646     DM_init(dm, DM_TYPE_CDDM, mesh->totvert, mesh->totedge, mesh->totface);
01647 
01648     dm->deformedOnly = 1;
01649 
01650     alloctype= CD_REFERENCE;
01651 
01652     CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype,
01653                      mesh->totvert);
01654     CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype,
01655                      mesh->totedge);
01656     CustomData_merge(&mesh->fdata, &dm->faceData, mask, alloctype,
01657                      mesh->totface);
01658 
01659     cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
01660     cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
01661     cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
01662 
01663     return dm;
01664 }
01665 
01666 DerivedMesh *CDDM_from_editmesh(EditMesh *em, Mesh *UNUSED(me))
01667 {
01668     DerivedMesh *dm = CDDM_new(BLI_countlist(&em->verts),
01669                                BLI_countlist(&em->edges),
01670                                BLI_countlist(&em->faces));
01671     CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
01672     EditVert *eve;
01673     EditEdge *eed;
01674     EditFace *efa;
01675     MVert *mvert = cddm->mvert;
01676     MEdge *medge = cddm->medge;
01677     MFace *mface = cddm->mface;
01678     int i, *index;
01679 
01680     dm->deformedOnly = 1;
01681 
01682     CustomData_merge(&em->vdata, &dm->vertData, CD_MASK_DERIVEDMESH,
01683                      CD_CALLOC, dm->numVertData);
01684     /* CustomData_merge(&em->edata, &dm->edgeData, CD_MASK_DERIVEDMESH,
01685                      CD_CALLOC, dm->numEdgeData); */
01686     CustomData_merge(&em->fdata, &dm->faceData, CD_MASK_DERIVEDMESH,
01687                      CD_CALLOC, dm->numFaceData);
01688 
01689     /* set eve->hash to vert index */
01690     for(i = 0, eve = em->verts.first; eve; eve = eve->next, ++i)
01691         eve->tmp.l = i;
01692 
01693     /* Need to be able to mark loose edges */
01694     for(eed = em->edges.first; eed; eed = eed->next) {
01695         eed->f2 = 0;
01696     }
01697     for(efa = em->faces.first; efa; efa = efa->next) {
01698         efa->e1->f2 = 1;
01699         efa->e2->f2 = 1;
01700         efa->e3->f2 = 1;
01701         if(efa->e4) efa->e4->f2 = 1;
01702     }
01703 
01704     index = dm->getVertDataArray(dm, CD_ORIGINDEX);
01705     for(i = 0, eve = em->verts.first; i < dm->numVertData;
01706         i++, eve = eve->next, index++) {
01707         MVert *mv = &mvert[i];
01708 
01709         copy_v3_v3(mv->co, eve->co);
01710 
01711         normal_float_to_short_v3(mv->no, eve->no);
01712         mv->bweight = (unsigned char) (eve->bweight * 255.0f);
01713 
01714         mv->flag = 0;
01715 
01716         *index = i;
01717 
01718         CustomData_from_em_block(&em->vdata, &dm->vertData, eve->data, i);
01719     }
01720 
01721     index = dm->getEdgeDataArray(dm, CD_ORIGINDEX);
01722     for(i = 0, eed = em->edges.first; i < dm->numEdgeData;
01723         i++, eed = eed->next, index++) {
01724         MEdge *med = &medge[i];
01725 
01726         med->v1 = eed->v1->tmp.l;
01727         med->v2 = eed->v2->tmp.l;
01728         med->crease = (unsigned char) (eed->crease * 255.0f);
01729         med->bweight = (unsigned char) (eed->bweight * 255.0f);
01730         med->flag = ME_EDGEDRAW|ME_EDGERENDER;
01731         
01732         if(eed->seam) med->flag |= ME_SEAM;
01733         if(eed->sharp) med->flag |= ME_SHARP;
01734         if(!eed->f2) med->flag |= ME_LOOSEEDGE;
01735 
01736         *index = i;
01737 
01738         /* CustomData_from_em_block(&em->edata, &dm->edgeData, eed->data, i); */
01739     }
01740 
01741     index = dm->getFaceDataArray(dm, CD_ORIGINDEX);
01742     for(i = 0, efa = em->faces.first; i < dm->numFaceData;
01743         i++, efa = efa->next, index++) {
01744         MFace *mf = &mface[i];
01745 
01746         mf->v1 = efa->v1->tmp.l;
01747         mf->v2 = efa->v2->tmp.l;
01748         mf->v3 = efa->v3->tmp.l;
01749         mf->v4 = efa->v4 ? efa->v4->tmp.l : 0;
01750         mf->mat_nr = efa->mat_nr;
01751         mf->flag = efa->flag;
01752 
01753         *index = i;
01754 
01755         CustomData_from_em_block(&em->fdata, &dm->faceData, efa->data, i);
01756         test_index_face(mf, &dm->faceData, i, efa->v4?4:3);
01757     }
01758 
01759     return dm;
01760 }
01761 
01762 DerivedMesh *CDDM_from_curve(Object *ob)
01763 {
01764     return CDDM_from_curve_customDB(ob, &ob->disp);
01765 }
01766 
01767 DerivedMesh *CDDM_from_curve_customDB(Object *ob, ListBase *dispbase)
01768 {
01769     DerivedMesh *dm;
01770     CDDerivedMesh *cddm;
01771     MVert *allvert;
01772     MEdge *alledge;
01773     MFace *allface;
01774     int totvert, totedge, totface;
01775 
01776     if (nurbs_to_mdata_customdb(ob, dispbase, &allvert, &totvert, &alledge,
01777         &totedge, &allface, &totface) != 0) {
01778         /* Error initializing mdata. This often happens when curve is empty */
01779         return CDDM_new(0, 0, 0);
01780     }
01781 
01782     dm = CDDM_new(totvert, totedge, totface);
01783     dm->deformedOnly = 1;
01784 
01785     cddm = (CDDerivedMesh*)dm;
01786 
01787     memcpy(cddm->mvert, allvert, totvert*sizeof(MVert));
01788     memcpy(cddm->medge, alledge, totedge*sizeof(MEdge));
01789     memcpy(cddm->mface, allface, totface*sizeof(MFace));
01790 
01791     MEM_freeN(allvert);
01792     MEM_freeN(alledge);
01793     MEM_freeN(allface);
01794 
01795     return dm;
01796 }
01797 
01798 DerivedMesh *CDDM_copy(DerivedMesh *source)
01799 {
01800     CDDerivedMesh *cddm = cdDM_create("CDDM_copy cddm");
01801     DerivedMesh *dm = &cddm->dm;
01802     int numVerts = source->numVertData;
01803     int numEdges = source->numEdgeData;
01804     int numFaces = source->numFaceData;
01805 
01806     /* ensure these are created if they are made on demand */
01807     source->getVertDataArray(source, CD_ORIGINDEX);
01808     source->getEdgeDataArray(source, CD_ORIGINDEX);
01809     source->getFaceDataArray(source, CD_ORIGINDEX);
01810 
01811     /* this initializes dm, and copies all non mvert/medge/mface layers */
01812     DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
01813     dm->deformedOnly = source->deformedOnly;
01814 
01815     CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
01816     CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
01817     CustomData_copy_data(&source->faceData, &dm->faceData, 0, 0, numFaces);
01818 
01819     /* now add mvert/medge/mface layers */
01820     cddm->mvert = source->dupVertArray(source);
01821     cddm->medge = source->dupEdgeArray(source);
01822     cddm->mface = source->dupFaceArray(source);
01823 
01824     CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, cddm->mvert, numVerts);
01825     CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, cddm->medge, numEdges);
01826     CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, cddm->mface, numFaces);
01827 
01828     return dm;
01829 }
01830 
01831 /* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
01832  * relationship betwen mesh data this needs to be set by the caller. */
01833 DerivedMesh *CDDM_from_template(DerivedMesh *source,
01834                                 int numVerts, int numEdges, int numFaces)
01835 {
01836     CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
01837     DerivedMesh *dm = &cddm->dm;
01838 
01839     /* ensure these are created if they are made on demand */
01840     source->getVertDataArray(source, CD_ORIGINDEX);
01841     source->getEdgeDataArray(source, CD_ORIGINDEX);
01842     source->getFaceDataArray(source, CD_ORIGINDEX);
01843 
01844     /* this does a copy of all non mvert/medge/mface layers */
01845     DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numFaces);
01846 
01847     /* now add mvert/medge/mface layers */
01848     CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
01849     CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
01850     CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numFaces);
01851 
01852     if(!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))
01853         CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
01854     if(!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX))
01855         CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
01856     if(!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX))
01857         CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numFaces);
01858 
01859     cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
01860     cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
01861     cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
01862 
01863     return dm;
01864 }
01865 
01866 void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
01867 {
01868     CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
01869     MVert *vert;
01870     int i;
01871 
01872     /* this will just return the pointer if it wasn't a referenced layer */
01873     vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
01874     cddm->mvert = vert;
01875 
01876     for(i = 0; i < dm->numVertData; ++i, ++vert)
01877         copy_v3_v3(vert->co, vertCoords[i]);
01878 }
01879 
01880 void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
01881 {
01882     CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
01883     MVert *vert;
01884     int i;
01885 
01886     /* this will just return the pointer if it wasn't a referenced layer */
01887     vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
01888     cddm->mvert = vert;
01889 
01890     for(i = 0; i < dm->numVertData; ++i, ++vert)
01891         copy_v3_v3_short(vert->no, vertNormals[i]);
01892 }
01893 
01894 void CDDM_calc_normals(DerivedMesh *dm)
01895 {
01896     CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
01897     float (*face_nors)[3];
01898 
01899     if(dm->numVertData == 0) return;
01900 
01901     /* we don't want to overwrite any referenced layers */
01902     cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
01903 
01904     /* make a face normal layer if not present */
01905     face_nors = CustomData_get_layer(&dm->faceData, CD_NORMAL);
01906     if(!face_nors)
01907         face_nors = CustomData_add_layer(&dm->faceData, CD_NORMAL, CD_CALLOC,
01908                                          NULL, dm->numFaceData);
01909 
01910     /* calculate face normals */
01911     mesh_calc_normals(cddm->mvert, dm->numVertData, CDDM_get_faces(dm), dm->numFaceData, face_nors);
01912 }
01913 
01914 void CDDM_calc_edges(DerivedMesh *dm)
01915 {
01916     CDDerivedMesh *cddm = (CDDerivedMesh*)dm;
01917     CustomData edgeData;
01918     EdgeHashIterator *ehi;
01919     MFace *mf = cddm->mface;
01920     MEdge *med;
01921     EdgeHash *eh = BLI_edgehash_new();
01922     int i, *index, numEdges, maxFaces = dm->numFaceData;
01923 
01924     for (i = 0; i < maxFaces; i++, mf++) {
01925         if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2))
01926             BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL);
01927         if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3))
01928             BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL);
01929         
01930         if (mf->v4) {
01931             if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4))
01932                 BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL);
01933             if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1))
01934                 BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL);
01935         } else {
01936             if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1))
01937                 BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL);
01938         }
01939     }
01940 
01941     numEdges = BLI_edgehash_size(eh);
01942 
01943     /* write new edges into a temporary CustomData */
01944     memset(&edgeData, 0, sizeof(edgeData));
01945     CustomData_add_layer(&edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
01946     CustomData_add_layer(&edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
01947 
01948     ehi = BLI_edgehashIterator_new(eh);
01949     med = CustomData_get_layer(&edgeData, CD_MEDGE);
01950     index = CustomData_get_layer(&edgeData, CD_ORIGINDEX);
01951     for(i = 0; !BLI_edgehashIterator_isDone(ehi);
01952         BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) {
01953         BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2);
01954 
01955         med->flag = ME_EDGEDRAW|ME_EDGERENDER;
01956         *index = ORIGINDEX_NONE;
01957     }
01958     BLI_edgehashIterator_free(ehi);
01959 
01960     /* free old CustomData and assign new one */
01961     CustomData_free(&dm->edgeData, dm->numEdgeData);
01962     dm->edgeData = edgeData;
01963     dm->numEdgeData = numEdges;
01964 
01965     cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
01966 
01967     BLI_edgehash_free(eh, NULL);
01968 }
01969 
01970 void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
01971 {
01972     if (numVerts < dm->numVertData)
01973         CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData-numVerts);
01974 
01975     dm->numVertData = numVerts;
01976 }
01977 
01978 void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
01979 {
01980     if (numEdges < dm->numEdgeData)
01981         CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData-numEdges);
01982 
01983     dm->numEdgeData = numEdges;
01984 }
01985 
01986 void CDDM_lower_num_faces(DerivedMesh *dm, int numFaces)
01987 {
01988     if (numFaces < dm->numFaceData)
01989         CustomData_free_elem(&dm->faceData, numFaces, dm->numFaceData-numFaces);
01990 
01991     dm->numFaceData = numFaces;
01992 }
01993 
01994 MVert *CDDM_get_vert(DerivedMesh *dm, int index)
01995 {
01996     return &((CDDerivedMesh*)dm)->mvert[index];
01997 }
01998 
01999 MEdge *CDDM_get_edge(DerivedMesh *dm, int index)
02000 {
02001     return &((CDDerivedMesh*)dm)->medge[index];
02002 }
02003 
02004 MFace *CDDM_get_face(DerivedMesh *dm, int index)
02005 {
02006     return &((CDDerivedMesh*)dm)->mface[index];
02007 }
02008 
02009 MVert *CDDM_get_verts(DerivedMesh *dm)
02010 {
02011     return ((CDDerivedMesh*)dm)->mvert;
02012 }
02013 
02014 MEdge *CDDM_get_edges(DerivedMesh *dm)
02015 {
02016     return ((CDDerivedMesh*)dm)->medge;
02017 }
02018 
02019 MFace *CDDM_get_faces(DerivedMesh *dm)
02020 {
02021     return ((CDDerivedMesh*)dm)->mface;
02022 }
02023