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