Fix a few compile warnings and rename gpu_buffers.h to GPU_buffers.h
[blender.git] / source / blender / editors / space_view3d / drawmesh.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation, full update, glsl support
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <string.h>
29 #include <math.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "BLI_blenlib.h"
34 #include "BLI_math.h"
35 #include "BLI_edgehash.h"
36 #include "BLI_editVert.h"
37
38
39 #include "DNA_material_types.h"
40 #include "DNA_meshdata_types.h"
41 #include "DNA_property_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_screen_types.h"
44 #include "DNA_view3d_types.h"
45
46 #include "BKE_bmfont.h"
47 #include "BKE_displist.h"
48 #include "BKE_DerivedMesh.h"
49 #include "BKE_effect.h"
50 #include "BKE_global.h"
51 #include "BKE_image.h"
52 #include "BKE_main.h"
53 #include "BKE_material.h"
54 #include "BKE_mesh.h"
55 #include "BKE_object.h"
56 #include "BKE_paint.h"
57 #include "BKE_property.h"
58 #include "BKE_utildefines.h"
59
60 #include "BIF_gl.h"
61 #include "BIF_glutil.h"
62
63 #include "UI_resources.h"
64
65 #include "GPU_buffers.h"
66 #include "GPU_extensions.h"
67 #include "GPU_draw.h"
68
69 #include "ED_mesh.h"
70
71 #include "view3d_intern.h"      // own include
72
73 /***/
74
75         /* Flags for marked edges */
76 enum {
77         eEdge_Visible = (1<<0),
78         eEdge_Select = (1<<1),
79 };
80
81         /* Creates a hash of edges to flags indicating
82          * adjacent tface select/active/etc flags.
83          */
84 static void get_marked_edge_info__orFlags(EdgeHash *eh, int v0, int v1, int flags)
85 {
86         int *flags_p;
87
88         if (!BLI_edgehash_haskey(eh, v0, v1)) {
89                 BLI_edgehash_insert(eh, v0, v1, 0);
90         }
91
92         flags_p = (int*) BLI_edgehash_lookup_p(eh, v0, v1);
93         *flags_p |= flags;
94 }
95
96 static EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me)
97 {
98         EdgeHash *eh = BLI_edgehash_new();
99         int i;
100         MFace *mf;
101         MTFace *tf = NULL;
102         
103         for (i=0; i<me->totface; i++) {
104                 mf = &me->mface[i];
105                 if (me->mtface)
106                         tf = &me->mtface[i];
107                 
108                 if (mf->v3) {
109                         if (!(mf->flag&ME_HIDE)) {
110                                 unsigned int flags = eEdge_Visible;
111                                 if (mf->flag&ME_FACE_SEL) flags |= eEdge_Select;
112
113                                 get_marked_edge_info__orFlags(eh, mf->v1, mf->v2, flags);
114                                 get_marked_edge_info__orFlags(eh, mf->v2, mf->v3, flags);
115                                 if (mf->v4) {
116                                         get_marked_edge_info__orFlags(eh, mf->v3, mf->v4, flags);
117                                         get_marked_edge_info__orFlags(eh, mf->v4, mf->v1, flags);
118                                 } else {
119                                         get_marked_edge_info__orFlags(eh, mf->v3, mf->v1, flags);
120                                 }
121                         }
122                 }
123         }
124
125         return eh;
126 }
127
128
129 static int draw_tfaces3D__setHiddenOpts(void *userData, int index)
130 {
131         struct { Mesh *me; EdgeHash *eh; } *data = userData;
132         Mesh *me= data->me;
133         MEdge *med = &me->medge[index];
134         uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
135
136         if((me->drawflag & ME_DRAWSEAMS) && (med->flag&ME_SEAM)) {
137                 return 0;
138         } else if(me->drawflag & ME_DRAWEDGES){ 
139                 if (me->drawflag & ME_HIDDENEDGES) {
140                         return 1;
141                 } else {
142                         return (flags & eEdge_Visible);
143                 }
144         } else {
145                 return (flags & eEdge_Select);
146         }
147 }
148
149 static int draw_tfaces3D__setSeamOpts(void *userData, int index)
150 {
151         struct { Mesh *me; EdgeHash *eh; } *data = userData;
152         Mesh *me= data->me;
153         MEdge *med = &data->me->medge[index];
154         uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
155
156         if (med->flag & ME_SEAM) {
157                 if (me->drawflag & ME_HIDDENEDGES) {
158                         return 1;
159                 } else {
160                         return (flags & eEdge_Visible);
161                 }
162         } else {
163                 return 0;
164         }
165 }
166
167 static int draw_tfaces3D__setSelectOpts(void *userData, int index)
168 {
169         struct { Mesh *me; EdgeHash *eh; } *data = userData;
170         MEdge *med = &data->me->medge[index];
171         uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
172
173         return flags & eEdge_Select;
174 }
175
176 static int draw_tfaces3D__setActiveOpts(void *userData, int index)
177 {
178         struct { Mesh *me; EdgeHash *eh; } *data = userData;
179         MEdge *med = &data->me->medge[index];
180         uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
181
182         if (flags & eEdge_Select) {
183                 return 1;
184         } else {
185                 return 0;
186         }
187 }
188
189 static int draw_tfaces3D__drawFaceOpts(void *userData, int index)
190 {
191         Mesh *me = (Mesh*)userData;
192
193         MFace *mface = &me->mface[index];
194         if (!(mface->flag&ME_HIDE) && (mface->flag&ME_FACE_SEL))
195                 return 2; /* Don't set color */
196         else
197                 return 0;
198 }
199
200 static void draw_tfaces3D(RegionView3D *rv3d, Object *ob, Mesh *me, DerivedMesh *dm)
201 {
202         struct { Mesh *me; EdgeHash *eh; } data;
203
204         data.me = me;
205         data.eh = get_tface_mesh_marked_edge_info(me);
206
207         glEnable(GL_DEPTH_TEST);
208         glDisable(GL_LIGHTING);
209         bglPolygonOffset(rv3d->dist, 1.0);
210
211                 /* Draw (Hidden) Edges */
212         UI_ThemeColor(TH_EDGE_FACESEL);
213         dm->drawMappedEdges(dm, draw_tfaces3D__setHiddenOpts, &data);
214
215                 /* Draw Seams */
216         if(me->drawflag & ME_DRAWSEAMS) {
217                 UI_ThemeColor(TH_EDGE_SEAM);
218                 glLineWidth(2);
219
220                 dm->drawMappedEdges(dm, draw_tfaces3D__setSeamOpts, &data);
221
222                 glLineWidth(1);
223         }
224
225         /* Draw Selected Faces */
226         if(me->drawflag & ME_DRAWFACES) {
227                 glEnable(GL_BLEND);
228                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
229                 UI_ThemeColor4(TH_FACE_SELECT);
230
231                 dm->drawMappedFacesTex(dm, draw_tfaces3D__drawFaceOpts, (void*)me);
232
233                 glDisable(GL_BLEND);
234         }
235         
236         bglPolygonOffset(rv3d->dist, 1.0);
237
238                 /* Draw Stippled Outline for selected faces */
239         glColor3ub(255, 255, 255);
240         setlinestyle(1);
241         dm->drawMappedEdges(dm, draw_tfaces3D__setSelectOpts, &data);
242         setlinestyle(0);
243
244         dm->drawMappedEdges(dm, draw_tfaces3D__setActiveOpts, &data);
245
246         bglPolygonOffset(rv3d->dist, 0.0);      // resets correctly now, even after calling accumulated offsets
247
248         BLI_edgehash_free(data.eh, NULL);
249 }
250
251 static Material *give_current_material_or_def(Object *ob, int matnr)
252 {
253         extern Material defmaterial;    // render module abuse...
254         Material *ma= give_current_material(ob, matnr);
255
256         return ma?ma:&defmaterial;
257 }
258
259 static int set_draw_settings_cached(int clearcache, int textured, MTFace *texface, int lit, Object *litob, int litmatnr, int doublesided)
260 {
261         static int c_textured;
262         static int c_lit;
263         static int c_doublesided;
264         static MTFace *c_texface;
265         static Object *c_litob;
266         static int c_litmatnr;
267         static int c_badtex;
268
269         if (clearcache) {
270                 c_textured= c_lit= c_doublesided= -1;
271                 c_texface= (MTFace*) -1;
272                 c_litob= (Object*) -1;
273                 c_litmatnr= -1;
274                 c_badtex= 0;
275         }
276
277         if (texface) {
278                 lit = lit && (lit==-1 || texface->mode&TF_LIGHT);
279                 textured = textured && (texface->mode&TF_TEX);
280                 doublesided = texface->mode&TF_TWOSIDE;
281         } else {
282                 textured = 0;
283         }
284
285         if (doublesided!=c_doublesided) {
286                 if (doublesided) glDisable(GL_CULL_FACE);
287                 else glEnable(GL_CULL_FACE);
288
289                 c_doublesided= doublesided;
290         }
291
292         if (textured!=c_textured || texface!=c_texface) {
293                 if (textured ) {
294                         c_badtex= !GPU_set_tpage(texface, !(litob->mode & OB_MODE_TEXTURE_PAINT));
295                 } else {
296                         GPU_set_tpage(NULL, 0);
297                         c_badtex= 0;
298                 }
299                 c_textured= textured;
300                 c_texface= texface;
301         }
302
303         if (c_badtex) lit= 0;
304         if (lit!=c_lit || litob!=c_litob || litmatnr!=c_litmatnr) {
305                 if (lit) {
306                         Material *ma= give_current_material_or_def(litob, litmatnr+1);
307                         float spec[4];
308
309                         spec[0]= ma->spec*ma->specr;
310                         spec[1]= ma->spec*ma->specg;
311                         spec[2]= ma->spec*ma->specb;
312                         spec[3]= 1.0;
313
314                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
315                         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
316                         glEnable(GL_LIGHTING);
317                         glEnable(GL_COLOR_MATERIAL);
318                 }
319                 else {
320                         glDisable(GL_LIGHTING); 
321                         glDisable(GL_COLOR_MATERIAL);
322                 }
323                 c_lit= lit;
324                 c_litob= litob;
325                 c_litmatnr= litmatnr;
326         }
327
328         return c_badtex;
329 }
330
331 /* Icky globals, fix with userdata parameter */
332
333 struct TextureDrawState {
334         Object *ob;
335         int islit, istex;
336         int color_profile;
337         unsigned char obcol[4];
338 } Gtexdraw = {NULL, 0, 0, 0, {0, 0, 0, 0}};
339
340 static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
341 {
342         unsigned char obcol[4];
343         int istex, solidtex= 0;
344
345         // XXX scene->obedit warning
346         if(v3d->drawtype==OB_SOLID || ((ob->mode & OB_MODE_EDIT) && v3d->drawtype!=OB_TEXTURE)) {
347                 /* draw with default lights in solid draw mode and edit mode */
348                 solidtex= 1;
349                 Gtexdraw.islit= -1;
350         }
351         else {
352                 /* draw with lights in the scene otherwise */
353                 Gtexdraw.islit= GPU_scene_object_lights(scene, ob, v3d->lay, rv3d->viewmat, get_view3d_ortho(v3d, rv3d));
354         }
355         
356         obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255);
357         obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255);
358         obcol[2]= CLAMPIS(ob->col[2]*255, 0, 255);
359         obcol[3]= CLAMPIS(ob->col[3]*255, 0, 255);
360         
361         glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
362         if(solidtex || v3d->drawtype==OB_TEXTURE) istex= 1;
363         else istex= 0;
364
365         Gtexdraw.ob = ob;
366         Gtexdraw.istex = istex;
367         Gtexdraw.color_profile = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT;
368         memcpy(Gtexdraw.obcol, obcol, sizeof(obcol));
369         set_draw_settings_cached(1, 0, 0, Gtexdraw.islit, 0, 0, 0);
370         glShadeModel(GL_SMOOTH);
371 }
372
373 static void draw_textured_end()
374 {
375         /* switch off textures */
376         GPU_set_tpage(NULL, 0);
377
378         glShadeModel(GL_FLAT);
379         glDisable(GL_CULL_FACE);
380
381         /* XXX, bad patch - GPU_default_lights() calls
382          * glLightfv(GL_LIGHT_POSITION, ...) which
383          * is transformed by the current matrix... we
384          * need to make sure that matrix is identity.
385          * 
386          * It would be better if drawmesh.c kept track
387          * of and restored the light settings it changed.
388          *  - zr
389          */
390         glPushMatrix();
391         glLoadIdentity();       
392         GPU_default_lights();
393         glPopMatrix();
394 }
395
396 static int draw_tface__set_draw_legacy(MTFace *tface, MCol *mcol, int matnr)
397 {
398         if (tface && (tface->mode&TF_INVISIBLE)) return 0;
399
400         if (tface && set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE)) {
401                 glColor3ub(0xFF, 0x00, 0xFF);
402                 return 2; /* Don't set color */
403         } else if (tface && tface->mode&TF_OBCOL) {
404                 glColor3ubv(Gtexdraw.obcol);
405                 return 2; /* Don't set color */
406         } else if (!mcol) {
407                 if (tface) glColor3f(1.0, 1.0, 1.0);
408                 else {
409                         Material *ma= give_current_material(Gtexdraw.ob, matnr+1);
410                         if(ma) {
411                                 float col[3];
412                                 if(Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
413                                 else copy_v3_v3(col, &ma->r);
414                                 
415                                 glColor3fv(col);
416                         }
417                         else glColor3f(1.0, 1.0, 1.0);
418                 }
419                 return 2; /* Don't set color */
420         } else {
421                 return 1; /* Set color from mcol */
422         }
423 }
424 static int draw_tface__set_draw(MTFace *tface, MCol *mcol, int matnr)
425 {
426         if (tface && (tface->mode&TF_INVISIBLE)) return 0;
427
428         if (tface && set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE)) {
429                 return 2; /* Don't set color */
430         } else if (tface && tface->mode&TF_OBCOL) {
431                 return 2; /* Don't set color */
432         } else if (!mcol) {
433                 return 1; /* Don't set color */
434         } else {
435                 return 1; /* Set color from mcol */
436         }
437 }
438 static void add_tface_color_layer(DerivedMesh *dm)
439 {
440         MTFace *tface = DM_get_face_data_layer(dm, CD_MTFACE);
441         MFace *mface = DM_get_face_data_layer(dm, CD_MFACE);
442         MCol *finalCol;
443         int i,j;
444         MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
445         if(!mcol)
446                 mcol = dm->getFaceDataArray(dm, CD_MCOL);
447
448         finalCol = MEM_mallocN(sizeof(MCol)*4*dm->getNumFaces(dm),"add_tface_color_layer");
449         for(i=0;i<dm->getNumFaces(dm);i++) {
450                 if (tface && (tface->mode&TF_INVISIBLE)) {
451                         if( mcol )
452                                 memcpy(&finalCol[i*4],&mcol[i*4],sizeof(MCol)*4);
453                         else
454                                 for(j=0;j<4;j++) {
455                                         finalCol[i*4+j].b = 255;
456                                         finalCol[i*4+j].g = 255;
457                                         finalCol[i*4+j].r = 255;
458                                 }
459                 }
460                 else if (tface && mface && set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, mface[i].mat_nr, TF_TWOSIDE)) {
461                         for(j=0;j<4;j++) {
462                                 finalCol[i*4+j].b = 255;
463                                 finalCol[i*4+j].g = 0;
464                                 finalCol[i*4+j].r = 255;
465                         }
466                 } else if (tface && tface->mode&TF_OBCOL) {
467                         for(j=0;j<4;j++) {
468                                 finalCol[i*4+j].r = FTOCHAR(Gtexdraw.obcol[0]);
469                                 finalCol[i*4+j].g = FTOCHAR(Gtexdraw.obcol[1]);
470                                 finalCol[i*4+j].b = FTOCHAR(Gtexdraw.obcol[2]);
471                         }
472                 } else if (!mcol) {
473                         if (tface) {
474                                 for(j=0;j<4;j++) {
475                                         finalCol[i*4+j].b = 255;
476                                         finalCol[i*4+j].g = 255;
477                                         finalCol[i*4+j].r = 255;
478                                 }
479                         }
480                         else {
481                                 float col[3];
482                                 Material *ma= give_current_material(Gtexdraw.ob, mface[i].mat_nr+1);
483                                 
484                                 if(ma) {
485                                         if(Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
486                                         else copy_v3_v3(col, &ma->r);
487                                         
488                                         for(j=0;j<4;j++) {
489                                                 finalCol[i*4+j].b = FTOCHAR(col[2]);
490                                                 finalCol[i*4+j].g = FTOCHAR(col[1]);
491                                                 finalCol[i*4+j].r = FTOCHAR(col[0]);
492                                         }
493                                 }
494                                 else
495                                         for(j=0;j<4;j++) {
496                                                 finalCol[i*4+j].b = 255;
497                                                 finalCol[i*4+j].g = 255;
498                                                 finalCol[i*4+j].r = 255;
499                                         }
500                         }
501                 } else {
502                         for(j=0;j<4;j++) {
503                                 finalCol[i*4+j].b = mcol[i*4+j].r;
504                                 finalCol[i*4+j].g = mcol[i*4+j].g;
505                                 finalCol[i*4+j].r = mcol[i*4+j].b;
506                         }
507                 }
508         }
509         CustomData_add_layer( &dm->faceData, CD_TEXTURE_MCOL, CD_ASSIGN, finalCol, dm->numFaceData );
510 }
511
512 static int draw_tface_mapped__set_draw(void *userData, int index)
513 {
514         Mesh *me = (Mesh*)userData;
515         MTFace *tface = (me->mtface)? &me->mtface[index]: NULL;
516         MFace *mface = (me->mface)? &me->mface[index]: NULL;
517         MCol *mcol = (me->mcol)? &me->mcol[index]: NULL;
518         int matnr = me->mface[index].mat_nr;
519         if (mface && mface->flag&ME_HIDE) return 0;
520         return draw_tface__set_draw(tface, mcol, matnr);
521 }
522
523 static int draw_em_tf_mapped__set_draw(void *userData, int index)
524 {
525         EditMesh *em = userData;
526         EditFace *efa= EM_get_face_for_index(index);
527         MTFace *tface;
528         MCol *mcol;
529         int matnr;
530
531         if (efa==NULL || efa->h)
532                 return 0;
533
534         tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
535         mcol = CustomData_em_get(&em->fdata, efa->data, CD_MCOL);
536         matnr = efa->mat_nr;
537
538         return draw_tface__set_draw_legacy(tface, mcol, matnr);
539 }
540
541 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
542 {
543         Mesh *me = (Mesh*)userData;
544         MTFace *tface = (me->mtface)? &me->mtface[index]: NULL;
545         MFace *mface = (me->mface)? &me->mface[index]: NULL;
546         
547         if ((mface->flag&ME_HIDE) || (tface && (tface->mode&TF_INVISIBLE))) 
548                         return 0;
549         
550         *drawSmooth_r = 1;
551         return 1;
552 }
553
554 void draw_mesh_text(Scene *scene, Object *ob, int glsl)
555 {
556         Mesh *me = ob->data;
557         DerivedMesh *ddm;
558         MFace *mf, *mface= me->mface;
559         MTFace *tface= me->mtface;
560         MCol *mcol= me->mcol;   /* why does mcol exist? */
561         bProperty *prop = get_ob_property(ob, "Text");
562         GPUVertexAttribs gattribs;
563         int a, totface= me->totface;
564
565         /* don't draw without tfaces */
566         if(!tface)
567                 return;
568
569         /* don't draw when editing */
570         if(ob->mode & OB_MODE_EDIT)
571                 return;
572         else if(ob==OBACT)
573                 if(paint_facesel_test(ob))
574                         return;
575
576         ddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
577
578         for(a=0, mf=mface; a<totface; a++, tface++, mf++) {
579                 int mode= tface->mode;
580                 int matnr= mf->mat_nr;
581                 int mf_smooth= mf->flag & ME_SMOOTH;
582
583                 if (!(mf->flag&ME_HIDE) && !(mode&TF_INVISIBLE) && (mode&TF_BMFONT)) {
584                         float v1[3], v2[3], v3[3], v4[3];
585                         char string[MAX_PROPSTRING];
586                         int characters, i, glattrib= -1, badtex= 0;
587
588                         if(glsl) {
589                                 GPU_enable_material(matnr+1, &gattribs);
590
591                                 for(i=0; i<gattribs.totlayer; i++) {
592                                         if(gattribs.layer[i].type == CD_MTFACE) {
593                                                 glattrib = gattribs.layer[i].glindex;
594                                                 break;
595                                         }
596                                 }
597                         }
598                         else {
599                                 badtex = set_draw_settings_cached(0, Gtexdraw.istex, tface, Gtexdraw.islit, Gtexdraw.ob, matnr, TF_TWOSIDE);
600                                 if (badtex) {
601                                         if (mcol) mcol+=4;
602                                         continue;
603                                 }
604                         }
605
606                         ddm->getVertCo(ddm, mf->v1, v1);
607                         ddm->getVertCo(ddm, mf->v2, v2);
608                         ddm->getVertCo(ddm, mf->v3, v3);
609                         if (mf->v4) ddm->getVertCo(ddm, mf->v4, v4);
610
611                         // The BM_FONT handling is in the gpu module, shared with the
612                         // game engine, was duplicated previously
613
614                         set_property_valstr(prop, string);
615                         characters = strlen(string);
616                         
617                         if(!BKE_image_get_ibuf(tface->tpage, NULL))
618                                 characters = 0;
619
620                         if (!mf_smooth) {
621                                 float nor[3];
622
623                                 normal_tri_v3( nor,v1, v2, v3);
624
625                                 glNormal3fv(nor);
626                         }
627
628                         GPU_render_text(tface, tface->mode, string, characters,
629                                 (unsigned int*)mcol, v1, v2, v3, (mf->v4? v4: NULL), glattrib);
630                 }
631                 if (mcol) {
632                         mcol+=4;
633                 }
634         }
635
636         ddm->release(ddm);
637 }
638
639 void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int faceselect)
640 {
641         Mesh *me= ob->data;
642         
643         /* correct for negative scale */
644         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
645         else glFrontFace(GL_CCW);
646         
647         /* draw the textured mesh */
648         draw_textured_begin(scene, v3d, rv3d, ob);
649
650         if(ob->mode & OB_MODE_EDIT) {
651                 glColor4f(1.0f,1.0f,1.0f,1.0f);
652                 dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, me->edit_mesh);
653         } else if(faceselect) {
654                 if(ob->mode & OB_MODE_WEIGHT_PAINT)
655                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, me, 1);
656                 else
657                         dm->drawMappedFacesTex(dm, draw_tface_mapped__set_draw, me);
658         }
659         else {
660                 if( GPU_buffer_legacy(dm) )
661                         dm->drawFacesTex(dm, draw_tface__set_draw_legacy);
662                 else {
663                         glColor4f(1.0f,1.0f,1.0f,1.0f);
664                         if( !CustomData_has_layer(&dm->faceData,CD_TEXTURE_MCOL) )
665                                 add_tface_color_layer(dm);
666                         dm->drawFacesTex(dm, draw_tface__set_draw);
667                 }
668         }
669
670         /* draw game engine text hack */
671         if(get_ob_property(ob, "Text")) 
672                 draw_mesh_text(scene, ob, 0);
673
674         draw_textured_end();
675         
676         /* draw edges and selected faces over textured mesh */
677         if(!(ob == scene->obedit) && faceselect)
678                 draw_tfaces3D(rv3d, ob, me, dm);
679
680         /* reset from negative scale correction */
681         glFrontFace(GL_CCW);
682         
683         /* in editmode, the blend mode needs to be set incase it was ADD */
684         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
685 }
686