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