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