style cleanup: follow style guide for formatting of if/for/while loops, and else...
[blender.git] / source / blender / editors / space_view3d / drawmesh.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, full update, glsl support
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/space_view3d/drawmesh.c
27  *  \ingroup spview3d
28  */
29
30 #include <string.h>
31 #include <math.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "BLI_utildefines.h"
36 #include "BLI_blenlib.h"
37 #include "BLI_math.h"
38 #include "BLI_edgehash.h"
39 #include "BLI_utildefines.h"
40
41 #include "DNA_material_types.h"
42 #include "DNA_mesh_types.h"
43 #include "DNA_meshdata_types.h"
44 #include "DNA_node_types.h"
45 #include "DNA_object_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_windowmanager_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 #include "BKE_tessmesh.h"
59 #include "BKE_scene.h"
60
61 #include "BIF_gl.h"
62 #include "BIF_glutil.h"
63
64 #include "UI_resources.h"
65
66 #include "GPU_buffers.h"
67 #include "GPU_extensions.h"
68 #include "GPU_draw.h"
69 #include "GPU_material.h"
70
71 #include "ED_mesh.h"
72 #include "ED_uvedit.h"
73
74 #include "view3d_intern.h"      // own include
75
76 /* user data structures for derived mesh callbacks */
77 typedef struct drawMeshFaceSelect_userData {
78         Mesh *me;
79         EdgeHash *eh;
80 } drawMeshFaceSelect_userData;
81
82 typedef struct drawEMTFMapped_userData {
83         BMEditMesh *em;
84         short has_mcol;
85         short has_mtface;
86         MFace *mf;
87         MTFace *tf;
88 } drawEMTFMapped_userData;
89
90 typedef struct drawTFace_userData {
91         MFace *mf;
92         MTFace *tf;
93 } drawTFace_userData;
94
95 /**************************** Face Select Mode *******************************/
96
97 /* Flags for marked edges */
98 enum {
99         eEdge_Visible = (1<<0),
100         eEdge_Select = (1<<1),
101 };
102
103 /* Creates a hash of edges to flags indicating selected/visible */
104 static void get_marked_edge_info__orFlags(EdgeHash *eh, int v0, int v1, int flags)
105 {
106         int *flags_p;
107
108         if (!BLI_edgehash_haskey(eh, v0, v1))
109                 BLI_edgehash_insert(eh, v0, v1, NULL);
110
111         flags_p = (int*) BLI_edgehash_lookup_p(eh, v0, v1);
112         *flags_p |= flags;
113 }
114
115 static EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me)
116 {
117         EdgeHash *eh = BLI_edgehash_new();
118         MPoly *mp;
119         MLoop *ml;
120         MLoop *ml_next;
121         int i, j;
122         
123         for (i=0; i<me->totpoly; i++) {
124                 mp = &me->mpoly[i];
125
126                 if (!(mp->flag & ME_HIDE)) {
127                         unsigned int flags = eEdge_Visible;
128                         if (mp->flag & ME_FACE_SEL) flags |= eEdge_Select;
129
130                         ml = me->mloop + mp->loopstart;
131                         for (j=0; j<mp->totloop; j++, ml++) {
132                                 ml_next = ME_POLY_LOOP_NEXT(me->mloop, mp, j);
133                                 get_marked_edge_info__orFlags(eh, ml->v, ml_next->v, flags);
134                         }
135                 }
136         }
137
138         return eh;
139 }
140
141
142 static DMDrawOption draw_mesh_face_select__setHiddenOpts(void *userData, int index)
143 {
144         drawMeshFaceSelect_userData *data = userData;
145         Mesh *me= data->me;
146         MEdge *med = &me->medge[index];
147         uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
148
149         if (me->drawflag & ME_DRAWEDGES) {
150                 if ((me->drawflag & ME_HIDDENEDGES) || (flags & eEdge_Visible))
151                         return DM_DRAW_OPTION_NORMAL;
152                 else
153                         return DM_DRAW_OPTION_SKIP;
154         }
155         else if (flags & eEdge_Select)
156                 return DM_DRAW_OPTION_NORMAL;
157         else
158                 return DM_DRAW_OPTION_SKIP;
159 }
160
161 static DMDrawOption draw_mesh_face_select__setSelectOpts(void *userData, int index)
162 {
163         drawMeshFaceSelect_userData *data = userData;
164         MEdge *med = &data->me->medge[index];
165         uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
166
167         return (flags & eEdge_Select) ? DM_DRAW_OPTION_NORMAL : DM_DRAW_OPTION_SKIP;
168 }
169
170 /* draws unselected */
171 static DMDrawOption draw_mesh_face_select__drawFaceOptsInv(void *userData, int index)
172 {
173         Mesh *me = (Mesh*)userData;
174
175         MPoly *mface = &me->mpoly[index];
176         if (!(mface->flag&ME_HIDE) && !(mface->flag&ME_FACE_SEL))
177                 return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
178         else
179                 return DM_DRAW_OPTION_SKIP;
180 }
181
182 static void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm)
183 {
184         drawMeshFaceSelect_userData data;
185
186         data.me = me;
187         data.eh = get_tface_mesh_marked_edge_info(me);
188
189         glEnable(GL_DEPTH_TEST);
190         glDisable(GL_LIGHTING);
191         bglPolygonOffset(rv3d->dist, 1.0);
192
193         /* Draw (Hidden) Edges */
194         setlinestyle(1);
195         UI_ThemeColor(TH_EDGE_FACESEL);
196         dm->drawMappedEdges(dm, draw_mesh_face_select__setHiddenOpts, &data);
197         setlinestyle(0);
198
199         /* Draw Selected Faces */
200         if (me->drawflag & ME_DRAWFACES) {
201                 glEnable(GL_BLEND);
202                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
203                 /* dull unselected faces so as not to get in the way of seeing color */
204                 glColor4ub(96, 96, 96, 64);
205                 dm->drawMappedFacesTex(dm, draw_mesh_face_select__drawFaceOptsInv, NULL, (void*)me);
206                 
207                 glDisable(GL_BLEND);
208         }
209         
210         bglPolygonOffset(rv3d->dist, 1.0);
211
212                 /* Draw Stippled Outline for selected faces */
213         glColor3ub(255, 255, 255);
214         setlinestyle(1);
215         dm->drawMappedEdges(dm, draw_mesh_face_select__setSelectOpts, &data);
216         setlinestyle(0);
217
218         bglPolygonOffset(rv3d->dist, 0.0);      // resets correctly now, even after calling accumulated offsets
219
220         BLI_edgehash_free(data.eh, NULL);
221 }
222
223 /***************************** Texture Drawing ******************************/
224
225 static Material *give_current_material_or_def(Object *ob, int matnr)
226 {
227         extern Material defmaterial;    // render module abuse...
228         Material *ma= give_current_material(ob, matnr);
229
230         return ma?ma:&defmaterial;
231 }
232
233 /* Icky globals, fix with userdata parameter */
234
235 static struct TextureDrawState {
236         Object *ob;
237         int islit, istex;
238         int color_profile;
239         unsigned char obcol[4];
240 } Gtexdraw = {NULL, 0, 0, 0, {0, 0, 0, 0}};
241
242 static int set_draw_settings_cached(int clearcache, MTFace *texface, Material *ma, struct TextureDrawState gtexdraw)
243 {
244         static Material *c_ma;
245         static int c_textured;
246         static MTFace *c_texface;
247         static int c_backculled;
248         static int c_badtex;
249         static int c_lit;
250
251         Object *litob = NULL; //to get mode to turn off mipmap in painting mode
252         int backculled = GEMAT_BACKCULL;
253         int alphablend = 0;
254         int textured = 0;
255         int lit = 0;
256         
257         if (clearcache) {
258                 c_textured= c_lit= c_backculled= -1;
259                 c_texface= (MTFace*) -1;
260                 c_badtex= 0;
261         }
262         else {
263                 textured = gtexdraw.istex;
264                 litob = gtexdraw.ob;
265         }
266
267         /* convert number of lights into boolean */
268         if (gtexdraw.islit) lit = 1;
269
270         if (ma) {
271                 alphablend = ma->game.alpha_blend;
272                 if (ma->mode & MA_SHLESS) lit = 0;
273                 backculled = ma->game.flag & GEMAT_BACKCULL;
274         }
275
276         if (texface) {
277                 textured = textured && (texface->tpage);
278
279                 /* no material, render alpha if texture has depth=32 */
280                 if (!ma && BKE_image_has_alpha(texface->tpage))
281                         alphablend = GPU_BLEND_ALPHA;
282         }
283
284         else
285                 textured = 0;
286
287         if (backculled!=c_backculled) {
288                 if (backculled) glEnable(GL_CULL_FACE);
289                 else glDisable(GL_CULL_FACE);
290
291                 c_backculled= backculled;
292         }
293
294         if (textured!=c_textured || texface!=c_texface) {
295                 if (textured ) {
296                         c_badtex= !GPU_set_tpage(texface, !(litob->mode & OB_MODE_TEXTURE_PAINT), alphablend);
297                 }else {
298                         GPU_set_tpage(NULL, 0, 0);
299                         c_badtex= 0;
300                 }
301                 c_textured= textured;
302                 c_texface= texface;
303         }
304
305         if (c_badtex) lit= 0;
306         if (lit!=c_lit || ma!=c_ma) {
307                 if (lit) {
308                         float spec[4];
309                         if (!ma)ma= give_current_material_or_def(NULL, 0); //default material
310
311                         spec[0]= ma->spec*ma->specr;
312                         spec[1]= ma->spec*ma->specg;
313                         spec[2]= ma->spec*ma->specb;
314                         spec[3]= 1.0;
315
316                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
317                         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
318                         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(ma->har, 0, 128));
319                         glEnable(GL_LIGHTING);
320                         glEnable(GL_COLOR_MATERIAL);
321                 }
322                 else {
323                         glDisable(GL_LIGHTING); 
324                         glDisable(GL_COLOR_MATERIAL);
325                 }
326                 c_lit= lit;
327         }
328
329         return c_badtex;
330 }
331
332 static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
333 {
334         unsigned char obcol[4];
335         int istex, solidtex;
336
337         // XXX scene->obedit warning
338
339         /* texture draw is abused for mask selection mode, do this so wire draw
340          * with face selection in weight paint is not lit. */
341         if ((v3d->drawtype <= OB_WIRE) && (ob->mode & OB_MODE_WEIGHT_PAINT)) {
342                 solidtex= FALSE;
343                 Gtexdraw.islit= 0;
344         }
345         else if (v3d->drawtype==OB_SOLID || ((ob->mode & OB_MODE_EDIT) && v3d->drawtype!=OB_TEXTURE)) {
346                 /* draw with default lights in solid draw mode and edit mode */
347                 solidtex= TRUE;
348                 Gtexdraw.islit= -1;
349         }
350         else {
351                 /* draw with lights in the scene otherwise */
352                 solidtex= FALSE;
353                 Gtexdraw.islit= GPU_scene_object_lights(scene, ob, v3d->lay, rv3d->viewmat, !rv3d->is_persp);
354         }
355         
356         rgba_float_to_uchar(obcol, ob->col);
357
358         glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
359         if (solidtex || v3d->drawtype==OB_TEXTURE) istex= 1;
360         else istex= 0;
361
362         Gtexdraw.ob = ob;
363         Gtexdraw.istex = istex;
364         Gtexdraw.color_profile = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT;
365         memcpy(Gtexdraw.obcol, obcol, sizeof(obcol));
366         set_draw_settings_cached(1, NULL, NULL, Gtexdraw);
367         glShadeModel(GL_SMOOTH);
368 }
369
370 static void draw_textured_end(void)
371 {
372         /* switch off textures */
373         GPU_set_tpage(NULL, 0, 0);
374
375         glShadeModel(GL_FLAT);
376         glDisable(GL_CULL_FACE);
377
378         /* XXX, bad patch - GPU_default_lights() calls
379          * glLightfv(GL_LIGHT_POSITION, ...) which
380          * is transformed by the current matrix... we
381          * need to make sure that matrix is identity.
382          * 
383          * It would be better if drawmesh.c kept track
384          * of and restored the light settings it changed.
385          *  - zr
386          */
387         glPushMatrix();
388         glLoadIdentity();       
389         GPU_default_lights();
390         glPopMatrix();
391 }
392
393 static DMDrawOption draw_tface__set_draw_legacy(MTFace *tface, int has_mcol, int matnr)
394 {
395         Material *ma= give_current_material(Gtexdraw.ob, matnr+1);
396         int validtexture=0;
397
398         if (ma && (ma->game.flag & GEMAT_INVISIBLE))
399                 return DM_DRAW_OPTION_SKIP;
400
401         validtexture = set_draw_settings_cached(0, tface, ma, Gtexdraw);
402
403         if (tface && validtexture) {
404                 glColor3ub(0xFF, 0x00, 0xFF);
405                 return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
406         }
407         else if (ma && (ma->shade_flag&MA_OBCOLOR)) {
408                 glColor3ubv(Gtexdraw.obcol);
409                 return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
410         }
411         else if (!has_mcol) {
412                 if (tface) glColor3f(1.0, 1.0, 1.0);
413                 else {
414                         if (ma) {
415                                 float col[3];
416                                 if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
417                                 else copy_v3_v3(col, &ma->r);
418                                 
419                                 glColor3fv(col);
420                         }
421                         else glColor3f(1.0, 1.0, 1.0);
422                 }
423                 return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
424         }
425         else {
426                 return DM_DRAW_OPTION_NORMAL; /* Set color from mcol */
427         }
428 }
429
430 static DMDrawOption draw_mcol__set_draw_legacy(MTFace *UNUSED(tface), int has_mcol, int UNUSED(matnr))
431 {
432         if (has_mcol)
433                 return DM_DRAW_OPTION_NORMAL;
434         else
435                 return DM_DRAW_OPTION_NO_MCOL;
436 }
437
438 static DMDrawOption draw_tface__set_draw(MTFace *tface, int has_mcol, int matnr)
439 {
440         Material *ma= give_current_material(Gtexdraw.ob, matnr+1);
441
442         if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0;
443
444         if (tface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) {
445                 return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
446         }
447         else if (tface && (tface->mode & TF_OBCOL)) {
448                 return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
449         }
450         else if (!has_mcol) {
451                 /* XXX: this return value looks wrong (and doesn't match comment) */
452                 return DM_DRAW_OPTION_NORMAL; /* Don't set color */
453         }
454         else {
455                 return DM_DRAW_OPTION_NORMAL; /* Set color from mcol */
456         }
457 }
458 static void add_tface_color_layer(DerivedMesh *dm)
459 {
460         MTFace *tface = DM_get_poly_data_layer(dm, CD_MTFACE);
461         MFace *mface = dm->getTessFaceArray(dm);
462         MCol *finalCol;
463         int i,j;
464         MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
465         if (!mcol)
466                 mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
467
468         finalCol = MEM_mallocN(sizeof(MCol)*4*dm->getNumTessFaces(dm),"add_tface_color_layer");
469         for (i=0;i<dm->getNumTessFaces(dm);i++) {
470                 Material *ma= give_current_material(Gtexdraw.ob, mface[i].mat_nr+1);
471
472                 if (ma && (ma->game.flag&GEMAT_INVISIBLE)) {
473                         if ( mcol )
474                                 memcpy(&finalCol[i*4],&mcol[i*4],sizeof(MCol)*4);
475                         else
476                                 for (j=0;j<4;j++) {
477                                         finalCol[i*4+j].b = 255;
478                                         finalCol[i*4+j].g = 255;
479                                         finalCol[i*4+j].r = 255;
480                                 }
481                 }
482                 else if (tface && mface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) {
483                         for (j=0;j<4;j++) {
484                                 finalCol[i*4+j].b = 255;
485                                 finalCol[i*4+j].g = 0;
486                                 finalCol[i*4+j].r = 255;
487                         }
488                 }
489                 else if (tface && (tface->mode & TF_OBCOL)) {
490                         for (j=0;j<4;j++) {
491                                 finalCol[i*4+j].b = FTOCHAR(Gtexdraw.obcol[0]);
492                                 finalCol[i*4+j].g = FTOCHAR(Gtexdraw.obcol[1]);
493                                 finalCol[i*4+j].r = FTOCHAR(Gtexdraw.obcol[2]);
494                         }
495                 }
496                 else if (!mcol) {
497                         if (tface) {
498                                 for (j=0;j<4;j++) {
499                                         finalCol[i*4+j].b = 255;
500                                         finalCol[i*4+j].g = 255;
501                                         finalCol[i*4+j].r = 255;
502                                 }
503                         }
504                         else {
505                                 float col[3];
506                                 Material *ma= give_current_material(Gtexdraw.ob, mface[i].mat_nr+1);
507                                 
508                                 if (ma) {
509                                         if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
510                                         else copy_v3_v3(col, &ma->r);
511                                         
512                                         for (j=0;j<4;j++) {
513                                                 finalCol[i*4+j].b = FTOCHAR(col[0]);
514                                                 finalCol[i*4+j].g = FTOCHAR(col[1]);
515                                                 finalCol[i*4+j].r = FTOCHAR(col[2]);
516                                         }
517                                 }
518                                 else
519                                         for (j=0;j<4;j++) {
520                                                 finalCol[i*4+j].b = 255;
521                                                 finalCol[i*4+j].g = 255;
522                                                 finalCol[i*4+j].r = 255;
523                                         }
524                         }
525                 }
526                 else {
527                         for (j=0;j<4;j++) {
528                                 finalCol[i*4+j].r = mcol[i*4+j].r;
529                                 finalCol[i*4+j].g = mcol[i*4+j].g;
530                                 finalCol[i*4+j].b = mcol[i*4+j].b;
531                         }
532                 }
533         }
534         CustomData_add_layer( &dm->faceData, CD_TEXTURE_MCOL, CD_ASSIGN, finalCol, dm->numTessFaceData );
535 }
536
537 static DMDrawOption draw_tface_mapped__set_draw(void *userData, int index)
538 {
539         Mesh *me = (Mesh *)userData;
540
541         /* array checked for NULL before calling */
542         MPoly *mpoly = &me->mpoly[index];
543
544         BLI_assert(index >= 0 && index < me->totpoly);
545
546         if (mpoly->flag & ME_HIDE) {
547                 return DM_DRAW_OPTION_SKIP;
548         }
549         else {
550                 MTexPoly *tpoly = (me->mtpoly) ? &me->mtpoly[index] : NULL;
551                 MTFace mtf= {{{0}}};
552                 int matnr = mpoly->mat_nr;
553
554                 if (tpoly) {
555                         ME_MTEXFACE_CPY(&mtf, tpoly);
556                 }
557
558                 return draw_tface__set_draw(&mtf, (me->mloopcol != NULL), matnr);
559         }
560 }
561
562 static DMDrawOption draw_em_tf_mapped__set_draw(void *userData, int index)
563 {
564         drawEMTFMapped_userData *data = userData;
565         BMEditMesh *em = data->em;
566         BMFace *efa= EDBM_get_face_for_index(em, index);
567
568         if (efa==NULL || BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
569                 return DM_DRAW_OPTION_SKIP;
570         }
571         else {
572                 MTFace mtf= {{{0}}};
573                 int matnr = efa->mat_nr;
574
575                 if (data->has_mtface) {
576                         MTexPoly *tpoly = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
577                         ME_MTEXFACE_CPY(&mtf, tpoly);
578                 }
579
580                 return draw_tface__set_draw_legacy(data->has_mtface ? &mtf : NULL,
581                                                                                    data->has_mcol, matnr);
582         }
583 }
584
585 static DMDrawOption wpaint__setSolidDrawOptions_material(void *userData, int index)
586 {
587         Mesh *me = (Mesh*)userData;
588
589         if (me->mat && me->mpoly) {
590                 Material *ma= me->mat[me->mpoly[index].mat_nr];
591                 if (ma && (ma->game.flag & GEMAT_INVISIBLE)) {
592                         return DM_DRAW_OPTION_SKIP;
593                 }
594         }
595
596         return DM_DRAW_OPTION_NORMAL;
597 }
598
599 /* when face select is on, use face hidden flag */
600 static DMDrawOption wpaint__setSolidDrawOptions_facemask(void *userData, int index)
601 {
602         Mesh *me = (Mesh*)userData;
603         MPoly *mp = &me->mpoly[index];
604         if (mp->flag & ME_HIDE)
605                 return DM_DRAW_OPTION_SKIP;
606         return DM_DRAW_OPTION_NORMAL;
607 }
608
609 static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
610 {
611         Mesh *me = ob->data;
612         DerivedMesh *ddm;
613         MPoly *mp, *mface  = me->mpoly;
614         MTexPoly *mtpoly   = me->mtpoly;
615         MLoopUV *mloopuv   = me->mloopuv;
616         MLoopUV *luv;
617         MLoopCol *mloopcol = me->mloopcol;      /* why does mcol exist? */
618         MLoopCol *lcol;
619
620         bProperty *prop = get_ob_property(ob, "Text");
621         GPUVertexAttribs gattribs;
622         int a, totpoly = me->totpoly;
623
624         /* fake values to pass to GPU_render_text() */
625         MCol  tmp_mcol[4]  = {{0}};
626         MCol *tmp_mcol_pt  = mloopcol ? tmp_mcol : NULL;
627         MTFace tmp_tf      = {{{0}}};
628
629         /* don't draw without tfaces */
630         if (!mtpoly || !mloopuv)
631                 return;
632
633         /* don't draw when editing */
634         if (ob->mode & OB_MODE_EDIT)
635                 return;
636         else if (ob==OBACT)
637                 if (paint_facesel_test(ob) || paint_vertsel_test(ob))
638                         return;
639
640         ddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
641
642         for (a=0, mp=mface; a<totpoly ; a++, mtpoly++, mp++) {
643                 short matnr= mp->mat_nr;
644                 int mf_smooth= mp->flag & ME_SMOOTH;
645                 Material *mat = me->mat[matnr];
646                 int mode= mat->game.flag;
647
648                 if (!(mode&GEMAT_INVISIBLE) && (mode&GEMAT_TEXT) && mp->totloop >= 3) {
649                         /* get the polygon as a tri/quad */
650                         int mp_vi[4];
651                         float v1[3], v2[3], v3[3], v4[3];
652                         char string[MAX_PROPSTRING];
653                         int characters, i, glattrib= -1, badtex= 0;
654
655
656                         /* TEXFACE */
657                         ME_MTEXFACE_CPY(&tmp_tf, mtpoly);
658
659                         if (glsl) {
660                                 GPU_enable_material(matnr+1, &gattribs);
661
662                                 for (i=0; i<gattribs.totlayer; i++) {
663                                         if (gattribs.layer[i].type == CD_MTFACE) {
664                                                 glattrib = gattribs.layer[i].glindex;
665                                                 break;
666                                         }
667                                 }
668                         }
669                         else {
670                                 badtex = set_draw_settings_cached(0, &tmp_tf, mat, Gtexdraw);
671                                 if (badtex) {
672                                         continue;
673                                 }
674                         }
675
676                         mp_vi[0] = me->mloop[mp->loopstart + 0].v;
677                     mp_vi[1] = me->mloop[mp->loopstart + 1].v;
678                     mp_vi[2] = me->mloop[mp->loopstart + 2].v;
679                     mp_vi[3] = (mp->totloop >= 4) ? me->mloop[mp->loopstart + 3].v : 0;
680
681                         /* UV */
682                         luv = &mloopuv[mp->loopstart];
683                         copy_v2_v2(tmp_tf.uv[0], luv->uv); luv++;
684                         copy_v2_v2(tmp_tf.uv[1], luv->uv); luv++;
685                         copy_v2_v2(tmp_tf.uv[2], luv->uv); luv++;
686                         if (mp->totloop >= 4) {
687                                 copy_v2_v2(tmp_tf.uv[3], luv->uv);
688                         }
689
690                         /* COLOR */
691                         if (mloopcol) {
692                                 unsigned int totloop_clamp = MIN2(4, mp->totloop);
693                                 unsigned int j;
694                                 lcol = &mloopcol[mp->loopstart];
695
696                                 for (j = 0; j <= totloop_clamp; j++, lcol++) {
697                                         MESH_MLOOPCOL_TO_MCOL(lcol, &tmp_mcol[j]);
698                                 }
699                         }
700
701                         /* LOCATION */
702                         ddm->getVertCo(ddm, mp_vi[0], v1);
703                         ddm->getVertCo(ddm, mp_vi[1], v2);
704                         ddm->getVertCo(ddm, mp_vi[2], v3);
705                         if (mp->totloop >= 4) {
706                                 ddm->getVertCo(ddm, mp_vi[3], v4);
707                         }
708
709
710
711                         // The BM_FONT handling is in the gpu module, shared with the
712                         // game engine, was duplicated previously
713
714                         set_property_valstr(prop, string);
715                         characters = strlen(string);
716                         
717                         if (!BKE_image_get_ibuf(mtpoly->tpage, NULL))
718                                 characters = 0;
719
720                         if (!mf_smooth) {
721                                 float nor[3];
722
723                                 normal_tri_v3( nor,v1, v2, v3);
724
725                                 glNormal3fv(nor);
726                         }
727
728                         GPU_render_text(&tmp_tf, mode, string, characters,
729                                 (unsigned int*)tmp_mcol_pt, v1, v2, v3, (mp->totloop >= 4 ? v4: NULL), glattrib);
730                 }
731         }
732
733         ddm->release(ddm);
734 }
735
736 static int compareDrawOptions(void *userData, int cur_index, int next_index)
737 {
738         drawTFace_userData *data = userData;
739
740         if (data->mf && data->mf[cur_index].mat_nr != data->mf[next_index].mat_nr)
741                 return 0;
742
743         if (data->tf && data->tf[cur_index].tpage != data->tf[next_index].tpage)
744                 return 0;
745
746         return 1;
747 }
748
749 static int compareDrawOptionsEm(void *userData, int cur_index, int next_index)
750 {
751         drawEMTFMapped_userData *data= userData;
752
753         if (data->mf && data->mf[cur_index].mat_nr != data->mf[next_index].mat_nr)
754                 return 0;
755
756         if (data->tf && data->tf[cur_index].tpage != data->tf[next_index].tpage)
757                 return 0;
758
759         return 1;
760 }
761
762 void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int draw_flags)
763 {
764         Mesh *me= ob->data;
765         
766         /* correct for negative scale */
767         if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
768         else glFrontFace(GL_CCW);
769         
770         /* draw the textured mesh */
771         draw_textured_begin(scene, v3d, rv3d, ob);
772
773         glColor4f(1.0f,1.0f,1.0f,1.0f);
774
775         if (ob->mode & OB_MODE_EDIT) {
776                 drawEMTFMapped_userData data;
777
778                 data.em= me->edit_btmesh;
779                 data.has_mcol= CustomData_has_layer(&me->edit_btmesh->bm->ldata, CD_MLOOPCOL);
780                 data.has_mtface= CustomData_has_layer(&me->edit_btmesh->bm->pdata, CD_MTEXPOLY);
781                 data.mf= DM_get_tessface_data_layer(dm, CD_MFACE);
782                 data.tf= DM_get_tessface_data_layer(dm, CD_MTFACE);
783
784                 dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data);
785         }
786         else if (draw_flags & DRAW_FACE_SELECT) {
787                 if (ob->mode & OB_MODE_WEIGHT_PAINT)
788                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions_facemask, GPU_enable_material, NULL, me,
789                                                                 DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH);
790                 else
791                         dm->drawMappedFacesTex(dm, me->mpoly ? draw_tface_mapped__set_draw : NULL, NULL, me);
792         }
793         else {
794                 if (GPU_buffer_legacy(dm)) {
795                         if (draw_flags & DRAW_MODIFIERS_PREVIEW)
796                                 dm->drawFacesTex(dm, draw_mcol__set_draw_legacy, NULL, NULL);
797                         else 
798                                 dm->drawFacesTex(dm, draw_tface__set_draw_legacy, NULL, NULL);
799                 }
800                 else {
801                         drawTFace_userData userData;
802
803                         if (!CustomData_has_layer(&dm->faceData,CD_TEXTURE_MCOL))
804                                 add_tface_color_layer(dm);
805
806                         userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
807                         userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
808
809                         dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData);
810                 }
811         }
812
813         /* draw game engine text hack */
814         if (get_ob_property(ob, "Text"))
815                 draw_mesh_text(scene, ob, 0);
816
817         draw_textured_end();
818         
819         /* draw edges and selected faces over textured mesh */
820         if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT))
821                 draw_mesh_face_select(rv3d, me, dm);
822
823         /* reset from negative scale correction */
824         glFrontFace(GL_CCW);
825         
826         /* in editmode, the blend mode needs to be set in case it was ADD */
827         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
828 }
829
830 /************************** NEW SHADING NODES ********************************/
831
832 typedef struct TexMatCallback {
833         Scene *scene;
834         Object *ob;
835         Mesh *me;
836         DerivedMesh *dm;
837 } TexMatCallback;
838
839 static void tex_mat_set_material_cb(void *UNUSED(userData), int mat_nr, void *attribs)
840 {
841         /* all we have to do here is simply enable the GLSL material, but note
842          * that the GLSL code will give different result depending on the drawtype,
843          * in texture draw mode it will output the active texture node, in material
844          * draw mode it will show the full material. */
845         GPU_enable_material(mat_nr, attribs);
846 }
847
848 static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs)
849 {
850         /* texture draw mode without GLSL */
851         TexMatCallback *data= (TexMatCallback*)userData;
852         GPUVertexAttribs *gattribs = attribs;
853         Image *ima;
854         ImageUser *iuser;
855         bNode *node;
856         int texture_set= 0;
857
858         /* draw image texture if we find one */
859         if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node)) {
860                 /* get openl texture */
861                 int mipmap= 1;
862                 int bindcode= (ima)? GPU_verify_image(ima, iuser, 0, 0, mipmap): 0;
863                 float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
864
865                 if (bindcode) {
866                         NodeTexBase *texbase= node->storage;
867
868                         /* disable existing material */
869                         GPU_disable_material();
870                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero);
871                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
872                         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0);
873
874                         /* bind texture */
875                         glEnable(GL_COLOR_MATERIAL);
876                         glEnable(GL_TEXTURE_2D);
877
878                         glBindTexture(GL_TEXTURE_2D, ima->bindcode);
879                         glColor3f(1.0f, 1.0f, 1.0f);
880
881                         glMatrixMode(GL_TEXTURE);
882                         glLoadMatrixf(texbase->tex_mapping.mat);
883                         glMatrixMode(GL_MODELVIEW);
884
885                         /* use active UV texture layer */
886                         memset(gattribs, 0, sizeof(*gattribs));
887
888                         gattribs->layer[0].type= CD_MTFACE;
889                         gattribs->layer[0].name[0]= '\0';
890                         gattribs->layer[0].gltexco= 1;
891                         gattribs->totlayer= 1;
892
893                         texture_set= 1;
894                 }
895         }
896
897         if (!texture_set) {
898                 glMatrixMode(GL_TEXTURE);
899                 glLoadIdentity();
900                 glMatrixMode(GL_MODELVIEW);
901
902                 /* disable texture */
903                 glDisable(GL_TEXTURE_2D);
904                 glDisable(GL_COLOR_MATERIAL);
905
906                 /* draw single color */
907                 GPU_enable_material(mat_nr, attribs);
908         }
909 }
910
911 static int tex_mat_set_face_mesh_cb(void *userData, int index)
912 {
913         /* faceselect mode face hiding */
914         TexMatCallback *data= (TexMatCallback*)userData;
915         Mesh *me = (Mesh*)data->me;
916         MPoly *mp = &me->mpoly[index];
917
918         return !(mp->flag & ME_HIDE);
919 }
920
921 static int tex_mat_set_face_editmesh_cb(void *userData, int index)
922 {
923         /* editmode face hiding */
924         TexMatCallback *data= (TexMatCallback*)userData;
925         Mesh *me = (Mesh*)data->me;
926         BMFace *efa= EDBM_get_face_for_index(me->edit_btmesh, index);
927
928         return !BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
929 }
930
931 void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int draw_flags)
932 {
933         if ((!scene_use_new_shading_nodes(scene)) || (draw_flags & DRAW_MODIFIERS_PREVIEW)) {
934                 draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags);
935                 return;
936         }
937
938         /* set opengl state for negative scale & color */
939         if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
940         else glFrontFace(GL_CCW);
941
942         glEnable(GL_LIGHTING);
943
944         if (ob->mode & OB_MODE_WEIGHT_PAINT) {
945                 /* weight paint mode exception */
946                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions_material,
947                         GPU_enable_material, NULL, ob->data, DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH);
948         }
949         else {
950                 Mesh *me= ob->data;
951                 TexMatCallback data = {scene, ob, me, dm};
952                 int (*set_face_cb)(void*, int);
953                 int glsl;
954                 
955                 /* face hiding callback depending on mode */
956                 if (ob == scene->obedit)
957                         set_face_cb= tex_mat_set_face_editmesh_cb;
958                 else if (draw_flags & DRAW_FACE_SELECT)
959                         set_face_cb= tex_mat_set_face_mesh_cb;
960                 else
961                         set_face_cb= NULL;
962
963                 /* test if we can use glsl */
964                 glsl= (v3d->drawtype == OB_MATERIAL) && GPU_glsl_support();
965
966                 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
967
968                 if (glsl) {
969                         /* draw glsl */
970                         dm->drawMappedFacesMat(dm,
971                                 tex_mat_set_material_cb,
972                                 set_face_cb, &data);
973                 }
974                 else {
975                         float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
976
977                         /* draw textured */
978                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero);
979                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
980                         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0);
981
982                         dm->drawMappedFacesMat(dm,
983                                 tex_mat_set_texture_cb,
984                                 set_face_cb, &data);
985                 }
986
987                 GPU_end_object_materials();
988         }
989
990         /* reset opengl state */
991         glDisable(GL_COLOR_MATERIAL);
992         glDisable(GL_TEXTURE_2D);
993         glDisable(GL_LIGHTING);
994         glBindTexture(GL_TEXTURE_2D, 0);
995         glFrontFace(GL_CCW);
996
997         glMatrixMode(GL_TEXTURE);
998         glLoadIdentity();
999         glMatrixMode(GL_MODELVIEW);
1000
1001         /* faceselect mode drawing over textured mesh */
1002         if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT))
1003                 draw_mesh_face_select(rv3d, ob->data, dm);
1004 }
1005