Mesh drawing optimization and fixes:
[blender-staging.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_blenlib.h"
36 #include "BLI_math.h"
37 #include "BLI_edgehash.h"
38 #include "BLI_editVert.h"
39 #include "BLI_utildefines.h"
40
41 #include "DNA_material_types.h"
42 #include "DNA_meshdata_types.h"
43 #include "DNA_node_types.h"
44 #include "DNA_object_types.h"
45 #include "DNA_property_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_screen_types.h"
48 #include "DNA_view3d_types.h"
49
50 #include "BKE_DerivedMesh.h"
51 #include "BKE_effect.h"
52 #include "BKE_image.h"
53 #include "BKE_material.h"
54 #include "BKE_paint.h"
55 #include "BKE_property.h"
56 #include "BKE_scene.h"
57
58 #include "BIF_gl.h"
59 #include "BIF_glutil.h"
60
61 #include "UI_resources.h"
62
63 #include "GPU_buffers.h"
64 #include "GPU_extensions.h"
65 #include "GPU_draw.h"
66 #include "GPU_material.h"
67
68 #include "ED_mesh.h"
69 #include "ED_uvedit.h"
70
71 #include "view3d_intern.h"      // own include
72
73 /**************************** Face Select Mode *******************************/
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 selected/visible */
82 static void get_marked_edge_info__orFlags(EdgeHash *eh, int v0, int v1, int flags)
83 {
84         int *flags_p;
85
86         if(!BLI_edgehash_haskey(eh, v0, v1))
87                 BLI_edgehash_insert(eh, v0, v1, NULL);
88
89         flags_p = (int*) BLI_edgehash_lookup_p(eh, v0, v1);
90         *flags_p |= flags;
91 }
92
93 static EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me)
94 {
95         EdgeHash *eh = BLI_edgehash_new();
96         MFace *mf;
97         int i;
98         
99         for(i=0; i<me->totface; i++) {
100                 mf = &me->mface[i];
101
102                 if(!(mf->flag & ME_HIDE)) {
103                         unsigned int flags = eEdge_Visible;
104                         if(mf->flag & ME_FACE_SEL) flags |= eEdge_Select;
105
106                         get_marked_edge_info__orFlags(eh, mf->v1, mf->v2, flags);
107                         get_marked_edge_info__orFlags(eh, mf->v2, mf->v3, flags);
108
109                         if(mf->v4) {
110                                 get_marked_edge_info__orFlags(eh, mf->v3, mf->v4, flags);
111                                 get_marked_edge_info__orFlags(eh, mf->v4, mf->v1, flags);
112                         }
113                         else
114                                 get_marked_edge_info__orFlags(eh, mf->v3, mf->v1, flags);
115                 }
116         }
117
118         return eh;
119 }
120
121
122 static int draw_mesh_face_select__setHiddenOpts(void *userData, int index)
123 {
124         struct { Mesh *me; EdgeHash *eh; } *data = userData;
125         Mesh *me= data->me;
126         MEdge *med = &me->medge[index];
127         uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
128
129         if(me->drawflag & ME_DRAWEDGES) { 
130                 if(me->drawflag & ME_HIDDENEDGES)
131                         return 1;
132                 else
133                         return (flags & eEdge_Visible);
134         }
135         else
136                 return (flags & eEdge_Select);
137 }
138
139 static int draw_mesh_face_select__setSelectOpts(void *userData, int index)
140 {
141         struct { Mesh *me; EdgeHash *eh; } *data = userData;
142         MEdge *med = &data->me->medge[index];
143         uintptr_t flags = (intptr_t) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
144
145         return flags & eEdge_Select;
146 }
147
148 /* draws unselected */
149 static int draw_mesh_face_select__drawFaceOptsInv(void *userData, int index)
150 {
151         Mesh *me = (Mesh*)userData;
152
153         MFace *mface = &me->mface[index];
154         if(!(mface->flag&ME_HIDE) && !(mface->flag&ME_FACE_SEL))
155                 return 2; /* Don't set color */
156         else
157                 return 0;
158 }
159
160 static void draw_mesh_face_select(RegionView3D *rv3d, Mesh *me, DerivedMesh *dm)
161 {
162         struct { Mesh *me; EdgeHash *eh; } data;
163
164         data.me = me;
165         data.eh = get_tface_mesh_marked_edge_info(me);
166
167         glEnable(GL_DEPTH_TEST);
168         glDisable(GL_LIGHTING);
169         bglPolygonOffset(rv3d->dist, 1.0);
170
171         /* Draw (Hidden) Edges */
172         setlinestyle(1);
173         UI_ThemeColor(TH_EDGE_FACESEL);
174         dm->drawMappedEdges(dm, draw_mesh_face_select__setHiddenOpts, &data);
175         setlinestyle(0);
176
177         /* Draw Selected Faces */
178         if(me->drawflag & ME_DRAWFACES) {
179                 glEnable(GL_BLEND);
180                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
181                 /* dull unselected faces so as not to get in the way of seeing color */
182                 glColor4ub(96, 96, 96, 64);
183                 dm->drawMappedFacesTex(dm, draw_mesh_face_select__drawFaceOptsInv, NULL, (void*)me);
184                 
185                 glDisable(GL_BLEND);
186         }
187         
188         bglPolygonOffset(rv3d->dist, 1.0);
189
190                 /* Draw Stippled Outline for selected faces */
191         glColor3ub(255, 255, 255);
192         setlinestyle(1);
193         dm->drawMappedEdges(dm, draw_mesh_face_select__setSelectOpts, &data);
194         setlinestyle(0);
195
196         bglPolygonOffset(rv3d->dist, 0.0);      // resets correctly now, even after calling accumulated offsets
197
198         BLI_edgehash_free(data.eh, NULL);
199 }
200
201 /***************************** Texture Drawing ******************************/
202
203 static Material *give_current_material_or_def(Object *ob, int matnr)
204 {
205         extern Material defmaterial;    // render module abuse...
206         Material *ma= give_current_material(ob, matnr);
207
208         return ma?ma:&defmaterial;
209 }
210
211 /* Icky globals, fix with userdata parameter */
212
213 static struct TextureDrawState {
214         Object *ob;
215         int islit, istex;
216         int color_profile;
217         unsigned char obcol[4];
218 } Gtexdraw = {NULL, 0, 0, 0, {0, 0, 0, 0}};
219
220 static int set_draw_settings_cached(int clearcache, MTFace *texface, Material *ma, struct TextureDrawState gtexdraw)
221 {
222         static Material *c_ma;
223         static int c_textured;
224         static MTFace *c_texface;
225         static int c_backculled;
226         static int c_badtex;
227         static int c_lit;
228
229         Object *litob = NULL; //to get mode to turn off mipmap in painting mode
230         int backculled = GEMAT_BACKCULL;
231         int alphablend = 0;
232         int textured = 0;
233         int lit = 0;
234         
235         if (clearcache) {
236                 c_textured= c_lit= c_backculled= -1;
237                 c_texface= (MTFace*) -1;
238                 c_badtex= 0;
239         } else {
240                 textured = gtexdraw.istex;
241                 litob = gtexdraw.ob;
242         }
243
244         /* convert number of lights into boolean */
245         if (gtexdraw.islit) lit = 1;
246
247         if (ma) {
248                 alphablend = ma->game.alpha_blend;
249                 if (ma->mode & MA_SHLESS) lit = 0;
250                 backculled = ma->game.flag & GEMAT_BACKCULL;
251         }
252
253         if (texface) {
254                 textured = textured && (texface->tpage);
255
256                 /* no material, render alpha if texture has depth=32 */
257                 if (!ma && BKE_image_has_alpha(texface->tpage))
258                         alphablend = GPU_BLEND_ALPHA;
259         }
260
261         else
262                 textured = 0;
263
264         if (backculled!=c_backculled) {
265                 if (backculled) glEnable(GL_CULL_FACE);
266                 else glDisable(GL_CULL_FACE);
267
268                 c_backculled= backculled;
269         }
270
271         if (textured!=c_textured || texface!=c_texface) {
272                 if (textured ) {
273                         c_badtex= !GPU_set_tpage(texface, !(litob->mode & OB_MODE_TEXTURE_PAINT), alphablend);
274                 } else {
275                         GPU_set_tpage(NULL, 0, 0);
276                         c_badtex= 0;
277                 }
278                 c_textured= textured;
279                 c_texface= texface;
280         }
281
282         if (c_badtex) lit= 0;
283         if (lit!=c_lit || ma!=c_ma) {
284                 if (lit) {
285                         float spec[4];
286                         if (!ma)ma= give_current_material_or_def(NULL, 0); //default material
287
288                         spec[0]= ma->spec*ma->specr;
289                         spec[1]= ma->spec*ma->specg;
290                         spec[2]= ma->spec*ma->specb;
291                         spec[3]= 1.0;
292
293                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
294                         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
295                         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(ma->har, 0, 128));
296                         glEnable(GL_LIGHTING);
297                         glEnable(GL_COLOR_MATERIAL);
298                 }
299                 else {
300                         glDisable(GL_LIGHTING); 
301                         glDisable(GL_COLOR_MATERIAL);
302                 }
303                 c_lit= lit;
304         }
305
306         return c_badtex;
307 }
308
309 static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
310 {
311         unsigned char obcol[4];
312         int istex, solidtex;
313
314         // XXX scene->obedit warning
315
316         /* texture draw is abused for mask selection mode, do this so wire draw
317          * with face selection in weight paint is not lit. */
318         if((v3d->drawtype <= OB_WIRE) && (ob->mode & OB_MODE_WEIGHT_PAINT)) {
319                 solidtex= FALSE;
320                 Gtexdraw.islit= 0;
321         }
322         else if(v3d->drawtype==OB_SOLID || ((ob->mode & OB_MODE_EDIT) && v3d->drawtype!=OB_TEXTURE)) {
323                 /* draw with default lights in solid draw mode and edit mode */
324                 solidtex= TRUE;
325                 Gtexdraw.islit= -1;
326         }
327         else {
328                 /* draw with lights in the scene otherwise */
329                 solidtex= FALSE;
330                 Gtexdraw.islit= GPU_scene_object_lights(scene, ob, v3d->lay, rv3d->viewmat, !rv3d->is_persp);
331         }
332         
333         obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255);
334         obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255);
335         obcol[2]= CLAMPIS(ob->col[2]*255, 0, 255);
336         obcol[3]= CLAMPIS(ob->col[3]*255, 0, 255);
337         
338         glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
339         if(solidtex || v3d->drawtype==OB_TEXTURE) istex= 1;
340         else istex= 0;
341
342         Gtexdraw.ob = ob;
343         Gtexdraw.istex = istex;
344         Gtexdraw.color_profile = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT;
345         memcpy(Gtexdraw.obcol, obcol, sizeof(obcol));
346         set_draw_settings_cached(1, NULL, NULL, Gtexdraw);
347         glShadeModel(GL_SMOOTH);
348 }
349
350 static void draw_textured_end(void)
351 {
352         /* switch off textures */
353         GPU_set_tpage(NULL, 0, 0);
354
355         glShadeModel(GL_FLAT);
356         glDisable(GL_CULL_FACE);
357
358         /* XXX, bad patch - GPU_default_lights() calls
359          * glLightfv(GL_LIGHT_POSITION, ...) which
360          * is transformed by the current matrix... we
361          * need to make sure that matrix is identity.
362          * 
363          * It would be better if drawmesh.c kept track
364          * of and restored the light settings it changed.
365          *  - zr
366          */
367         glPushMatrix();
368         glLoadIdentity();       
369         GPU_default_lights();
370         glPopMatrix();
371 }
372
373 static int draw_tface__set_draw_legacy(MTFace *tface, int has_mcol, int matnr)
374 {
375         Material *ma= give_current_material(Gtexdraw.ob, matnr+1);
376         int validtexture=0;
377
378         if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0;
379
380         validtexture = set_draw_settings_cached(0, tface, ma, Gtexdraw);
381
382         if (tface && validtexture) {
383                 glColor3ub(0xFF, 0x00, 0xFF);
384                 return 2; /* Don't set color */
385         } else if (ma && ma->shade_flag&MA_OBCOLOR) {
386                 glColor3ubv(Gtexdraw.obcol);
387                 return 2; /* Don't set color */
388         } else if (!has_mcol) {
389                 if (tface) glColor3f(1.0, 1.0, 1.0);
390                 else {
391                         if(ma) {
392                                 float col[3];
393                                 if(Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
394                                 else copy_v3_v3(col, &ma->r);
395                                 
396                                 glColor3fv(col);
397                         }
398                         else glColor3f(1.0, 1.0, 1.0);
399                 }
400                 return 2; /* Don't set color */
401         } else {
402                 return 1; /* Set color from mcol */
403         }
404 }
405
406 static int draw_mcol__set_draw_legacy(MTFace *UNUSED(tface), int has_mcol, int UNUSED(matnr))
407 {
408         if (has_mcol) return 1;
409         else return 2;
410 }
411
412 static int draw_tface__set_draw(MTFace *tface, int has_mcol, int matnr)
413 {
414         Material *ma= give_current_material(Gtexdraw.ob, matnr+1);
415
416         if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0;
417
418         if (tface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) {
419                 return 2; /* Don't set color */
420         } else if (tface && tface->mode&TF_OBCOL) {
421                 return 2; /* Don't set color */
422         } else if (!has_mcol) {
423                 return 1; /* Don't set color */
424         } else {
425                 return 1; /* Set color from mcol */
426         }
427 }
428 static void add_tface_color_layer(DerivedMesh *dm)
429 {
430         MTFace *tface = DM_get_face_data_layer(dm, CD_MTFACE);
431         MFace *mface = DM_get_face_data_layer(dm, CD_MFACE);
432         MCol *finalCol;
433         int i,j;
434         MCol *mcol = dm->getFaceDataArray(dm, CD_WEIGHT_MCOL);
435         if(!mcol)
436                 mcol = dm->getFaceDataArray(dm, CD_MCOL);
437
438         finalCol = MEM_mallocN(sizeof(MCol)*4*dm->getNumFaces(dm),"add_tface_color_layer");
439         for(i=0;i<dm->getNumFaces(dm);i++) {
440                 Material *ma= give_current_material(Gtexdraw.ob, mface[i].mat_nr+1);
441
442                 if (ma && (ma->game.flag&GEMAT_INVISIBLE)) {
443                         if( mcol )
444                                 memcpy(&finalCol[i*4],&mcol[i*4],sizeof(MCol)*4);
445                         else
446                                 for(j=0;j<4;j++) {
447                                         finalCol[i*4+j].b = 255;
448                                         finalCol[i*4+j].g = 255;
449                                         finalCol[i*4+j].r = 255;
450                                 }
451                 }
452                 else if (tface && mface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) {
453                         for(j=0;j<4;j++) {
454                                 finalCol[i*4+j].b = 255;
455                                 finalCol[i*4+j].g = 0;
456                                 finalCol[i*4+j].r = 255;
457                         }
458                 } else if (tface && tface->mode&TF_OBCOL) {
459                         for(j=0;j<4;j++) {
460                                 finalCol[i*4+j].b = FTOCHAR(Gtexdraw.obcol[0]);
461                                 finalCol[i*4+j].g = FTOCHAR(Gtexdraw.obcol[1]);
462                                 finalCol[i*4+j].r = FTOCHAR(Gtexdraw.obcol[2]);
463                         }
464                 } else if (!mcol) {
465                         if (tface) {
466                                 for(j=0;j<4;j++) {
467                                         finalCol[i*4+j].b = 255;
468                                         finalCol[i*4+j].g = 255;
469                                         finalCol[i*4+j].r = 255;
470                                 }
471                         }
472                         else {
473                                 float col[3];
474                                 Material *ma= give_current_material(Gtexdraw.ob, mface[i].mat_nr+1);
475                                 
476                                 if(ma) {
477                                         if(Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
478                                         else copy_v3_v3(col, &ma->r);
479                                         
480                                         for(j=0;j<4;j++) {
481                                                 finalCol[i*4+j].b = FTOCHAR(col[0]);
482                                                 finalCol[i*4+j].g = FTOCHAR(col[1]);
483                                                 finalCol[i*4+j].r = FTOCHAR(col[2]);
484                                         }
485                                 }
486                                 else
487                                         for(j=0;j<4;j++) {
488                                                 finalCol[i*4+j].b = 255;
489                                                 finalCol[i*4+j].g = 255;
490                                                 finalCol[i*4+j].r = 255;
491                                         }
492                         }
493                 } else {
494                         for(j=0;j<4;j++) {
495                                 finalCol[i*4+j].r = mcol[i*4+j].r;
496                                 finalCol[i*4+j].g = mcol[i*4+j].g;
497                                 finalCol[i*4+j].b = mcol[i*4+j].b;
498                         }
499                 }
500         }
501         CustomData_add_layer( &dm->faceData, CD_TEXTURE_MCOL, CD_ASSIGN, finalCol, dm->numFaceData );
502 }
503
504 static int draw_tface_mapped__set_draw(void *userData, int index)
505 {
506         Mesh *me = (Mesh*)userData;
507         MTFace *tface = (me->mtface)? &me->mtface[index]: NULL;
508         MFace *mface = &me->mface[index];
509         const int matnr = mface->mat_nr;
510         if (mface->flag & ME_HIDE) return 0;
511         return draw_tface__set_draw(tface, (me->mcol != NULL), matnr);
512 }
513
514 static int draw_em_tf_mapped__set_draw(void *userData, int index)
515 {
516         struct {EditMesh *em; short has_mcol; short has_mtface; MFace *mf; MTFace *tf;} *data = userData;
517         EditMesh *em = data->em;
518         EditFace *efa= EM_get_face_for_index(index);
519         MTFace *tface;
520         int matnr;
521
522         if (efa->h)
523                 return 0;
524
525         tface = data->has_mtface ? CustomData_em_get(&em->fdata, efa->data, CD_MTFACE) : NULL;
526         matnr = efa->mat_nr;
527
528         return draw_tface__set_draw_legacy(tface, data->has_mcol, matnr);
529 }
530
531 static int wpaint__setSolidDrawOptions(void *userData, int index, int *drawSmooth_r)
532 {
533         Mesh *me = (Mesh*)userData;
534
535         if (me->mat && me->mface) {
536                 Material *ma= me->mat[me->mface[index].mat_nr];
537                 if (ma && (ma->game.flag & GEMAT_INVISIBLE)) {
538                         return 0;
539                 }
540         }
541
542         *drawSmooth_r = 1;
543         return 1;
544 }
545
546 static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
547 {
548         Mesh *me = ob->data;
549         DerivedMesh *ddm;
550         MFace *mf, *mface= me->mface;
551         MTFace *tface= me->mtface;
552         MCol *mcol= me->mcol;   /* why does mcol exist? */
553         bProperty *prop = get_ob_property(ob, "Text");
554         GPUVertexAttribs gattribs;
555         int a, totface= me->totface;
556
557         /* don't draw without tfaces */
558         if(!tface)
559                 return;
560
561         /* don't draw when editing */
562         if(ob->mode & OB_MODE_EDIT)
563                 return;
564         else if(ob==OBACT)
565                 if(paint_facesel_test(ob) || paint_vertsel_test(ob))
566                         return;
567
568         ddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
569
570         for(a=0, mf=mface; a<totface; a++, tface++, mf++) {
571                 short matnr= mf->mat_nr;
572                 int mf_smooth= mf->flag & ME_SMOOTH;
573                 Material *mat = me->mat[matnr];
574                 int mode= mat->game.flag;
575
576                 if (!(mode&GEMAT_INVISIBLE) && (mode&GEMAT_TEXT)) {
577                         float v1[3], v2[3], v3[3], v4[3];
578                         char string[MAX_PROPSTRING];
579                         int characters, i, glattrib= -1, badtex= 0;
580
581                         if(glsl) {
582                                 GPU_enable_material(matnr+1, &gattribs);
583
584                                 for(i=0; i<gattribs.totlayer; i++) {
585                                         if(gattribs.layer[i].type == CD_MTFACE) {
586                                                 glattrib = gattribs.layer[i].glindex;
587                                                 break;
588                                         }
589                                 }
590                         }
591                         else {
592                                 badtex = set_draw_settings_cached(0, tface, mat, Gtexdraw);
593                                 if (badtex) {
594                                         if (mcol) mcol+=4;
595                                         continue;
596                                 }
597                         }
598
599                         ddm->getVertCo(ddm, mf->v1, v1);
600                         ddm->getVertCo(ddm, mf->v2, v2);
601                         ddm->getVertCo(ddm, mf->v3, v3);
602                         if (mf->v4) ddm->getVertCo(ddm, mf->v4, v4);
603
604                         // The BM_FONT handling is in the gpu module, shared with the
605                         // game engine, was duplicated previously
606
607                         set_property_valstr(prop, string);
608                         characters = strlen(string);
609                         
610                         if(!BKE_image_get_ibuf(tface->tpage, NULL))
611                                 characters = 0;
612
613                         if (!mf_smooth) {
614                                 float nor[3];
615
616                                 normal_tri_v3( nor,v1, v2, v3);
617
618                                 glNormal3fv(nor);
619                         }
620
621                         GPU_render_text(tface, mode, string, characters,
622                                 (unsigned int*)mcol, v1, v2, v3, (mf->v4? v4: NULL), glattrib);
623                 }
624                 if (mcol) {
625                         mcol+=4;
626                 }
627         }
628
629         ddm->release(ddm);
630 }
631
632 static int compareDrawOptions(void *userData, int cur_index, int next_index)
633 {
634         struct { MFace *mf; MTFace *tf; } *data = userData;
635
636         if(data->mf && data->mf[cur_index].mat_nr != data->mf[next_index].mat_nr)
637                 return 0;
638
639         if(data->tf && data->tf[cur_index].tpage != data->tf[next_index].tpage)
640                 return 0;
641
642         return 1;
643 }
644
645 static int compareDrawOptionsEm(void *userData, int cur_index, int next_index)
646 {
647         struct {EditMesh *em; short has_mcol; short has_mtface; MFace *mf; MTFace *tf;} *data= userData;
648
649         if(data->mf && data->mf[cur_index].mat_nr != data->mf[next_index].mat_nr)
650                 return 0;
651
652         if(data->tf && data->tf[cur_index].tpage != data->tf[next_index].tpage)
653                 return 0;
654
655         return 1;
656 }
657
658 void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int draw_flags)
659 {
660         Mesh *me= ob->data;
661         
662         /* correct for negative scale */
663         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
664         else glFrontFace(GL_CCW);
665         
666         /* draw the textured mesh */
667         draw_textured_begin(scene, v3d, rv3d, ob);
668
669         glColor4f(1.0f,1.0f,1.0f,1.0f);
670
671         if(ob->mode & OB_MODE_EDIT) {
672                 struct {EditMesh *em; short has_mcol; short has_mtface; MFace *mf; MTFace *tf;} data;
673
674                 data.em= me->edit_mesh;
675                 data.has_mcol= CustomData_has_layer(&me->edit_mesh->fdata, CD_MCOL);
676                 data.has_mtface= CustomData_has_layer(&me->edit_mesh->fdata, CD_MTFACE);
677                 data.mf= DM_get_face_data_layer(dm, CD_MFACE);
678                 data.tf= DM_get_face_data_layer(dm, CD_MTFACE);
679
680                 dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data);
681         }
682         else if(draw_flags & DRAW_FACE_SELECT) {
683                 if(ob->mode & OB_MODE_WEIGHT_PAINT)
684                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions, GPU_enable_material, NULL, me, 1);
685                 else
686                         dm->drawMappedFacesTex(dm, me->mface ? draw_tface_mapped__set_draw : NULL, NULL, me);
687         }
688         else {
689                 if(GPU_buffer_legacy(dm)) {
690                         if (draw_flags & DRAW_DYNAMIC_PAINT_PREVIEW)
691                                 dm->drawFacesTex(dm, draw_mcol__set_draw_legacy, NULL, NULL);
692                         else 
693                                 dm->drawFacesTex(dm, draw_tface__set_draw_legacy, NULL, NULL);
694                 }
695                 else {
696                         struct { MFace *mf; MTFace *tf; } userData;
697
698                         if(!CustomData_has_layer(&dm->faceData,CD_TEXTURE_MCOL))
699                                 add_tface_color_layer(dm);
700
701                         userData.mf = DM_get_face_data_layer(dm, CD_MFACE);
702                         userData.tf = DM_get_face_data_layer(dm, CD_MTFACE);
703
704                         dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData);
705                 }
706         }
707
708         /* draw game engine text hack */
709         if(get_ob_property(ob, "Text")) 
710                 draw_mesh_text(scene, ob, 0);
711
712         draw_textured_end();
713         
714         /* draw edges and selected faces over textured mesh */
715         if(!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT))
716                 draw_mesh_face_select(rv3d, me, dm);
717
718         /* reset from negative scale correction */
719         glFrontFace(GL_CCW);
720         
721         /* in editmode, the blend mode needs to be set incase it was ADD */
722         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
723 }
724
725 /************************** NEW SHADING NODES ********************************/
726
727 typedef struct TexMatCallback {
728         Scene *scene;
729         Object *ob;
730         Mesh *me;
731         DerivedMesh *dm;
732 } TexMatCallback;
733
734 static void tex_mat_set_material_cb(void *UNUSED(userData), int mat_nr, void *attribs)
735 {
736         /* all we have to do here is simply enable the GLSL material, but note
737            that the GLSL code will give different result depending on the drawtype,
738            in texture draw mode it will output the active texture node, in material
739            draw mode it will show the full material. */
740         GPU_enable_material(mat_nr, attribs);
741 }
742
743 static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs)
744 {
745         /* texture draw mode without GLSL */
746         TexMatCallback *data= (TexMatCallback*)userData;
747         GPUVertexAttribs *gattribs = attribs;
748         Image *ima;
749         ImageUser *iuser;
750         bNode *node;
751         int texture_set= 0;
752
753         /* draw image texture if we find one */
754         if(ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node)) {
755                 /* get openl texture */
756                 int mipmap= 1;
757                 int bindcode= (ima)? GPU_verify_image(ima, iuser, 0, 0, mipmap): 0;
758                 float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
759
760                 if(bindcode) {
761                         NodeTexBase *texbase= node->storage;
762
763                         /* disable existing material */
764                         GPU_disable_material();
765                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero);
766                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
767                         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0);
768
769                         /* bind texture */
770                         glEnable(GL_COLOR_MATERIAL);
771                         glEnable(GL_TEXTURE_2D);
772
773                         glBindTexture(GL_TEXTURE_2D, ima->bindcode);
774                         glColor3f(1.0f, 1.0f, 1.0f);
775
776                         glMatrixMode(GL_TEXTURE);
777                         glLoadMatrixf(texbase->tex_mapping.mat);
778                         glMatrixMode(GL_MODELVIEW);
779
780                         /* use active UV texture layer */
781                         memset(gattribs, 0, sizeof(*gattribs));
782
783                         gattribs->layer[0].type= CD_MTFACE;
784                         gattribs->layer[0].name[0]= '\0';
785                         gattribs->layer[0].gltexco= 1;
786                         gattribs->totlayer= 1;
787
788                         texture_set= 1;
789                 }
790         }
791
792         if(!texture_set) {
793                 glMatrixMode(GL_TEXTURE);
794                 glLoadIdentity();
795                 glMatrixMode(GL_MODELVIEW);
796
797                 /* disable texture */
798                 glDisable(GL_TEXTURE_2D);
799                 glDisable(GL_COLOR_MATERIAL);
800
801                 /* draw single color */
802                 GPU_enable_material(mat_nr, attribs);
803         }
804 }
805
806 static int tex_mat_set_face_mesh_cb(void *userData, int index)
807 {
808         /* faceselect mode face hiding */
809         TexMatCallback *data= (TexMatCallback*)userData;
810         Mesh *me = (Mesh*)data->me;
811         MFace *mface = &me->mface[index];
812
813         return !(mface->flag & ME_HIDE);
814 }
815
816 static int tex_mat_set_face_editmesh_cb(void *UNUSED(userData), int index)
817 {
818         /* editmode face hiding */
819         EditFace *efa= EM_get_face_for_index(index);
820
821         return !(efa->h);
822 }
823
824 void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob, DerivedMesh *dm, int draw_flags)
825 {
826         if((!scene_use_new_shading_nodes(scene)) || (draw_flags & DRAW_DYNAMIC_PAINT_PREVIEW)) {
827                 draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags);
828                 return;
829         }
830
831         /* set opengl state for negative scale & color */
832         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
833         else glFrontFace(GL_CCW);
834
835         glEnable(GL_LIGHTING);
836
837         if(ob->mode & OB_MODE_WEIGHT_PAINT) {
838                 /* weight paint mode exception */
839                 int useColors= 1;
840
841                 dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions,
842                         GPU_enable_material, NULL, ob->data, useColors);
843         }
844         else {
845                 Mesh *me= ob->data;
846                 TexMatCallback data = {scene, ob, me, dm};
847                 int (*set_face_cb)(void*, int);
848                 int glsl;
849                 
850                 /* face hiding callback depending on mode */
851                 if(ob == scene->obedit)
852                         set_face_cb= tex_mat_set_face_editmesh_cb;
853                 else if(draw_flags & DRAW_FACE_SELECT)
854                         set_face_cb= tex_mat_set_face_mesh_cb;
855                 else
856                         set_face_cb= NULL;
857
858                 /* test if we can use glsl */
859                 glsl= (v3d->drawtype == OB_MATERIAL) && GPU_glsl_support();
860
861                 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
862
863                 if(glsl) {
864                         /* draw glsl */
865                         dm->drawMappedFacesMat(dm,
866                                 tex_mat_set_material_cb,
867                                 set_face_cb, &data);
868                 }
869                 else {
870                         float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
871
872                         /* draw textured */
873                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero);
874                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
875                         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0);
876
877                         dm->drawMappedFacesMat(dm,
878                                 tex_mat_set_texture_cb,
879                                 set_face_cb, &data);
880                 }
881
882                 GPU_end_object_materials();
883         }
884
885         /* reset opengl state */
886         glDisable(GL_COLOR_MATERIAL);
887         glDisable(GL_TEXTURE_2D);
888         glDisable(GL_LIGHTING);
889         glBindTexture(GL_TEXTURE_2D, 0);
890         glFrontFace(GL_CCW);
891
892         glMatrixMode(GL_TEXTURE);
893         glLoadIdentity();
894         glMatrixMode(GL_MODELVIEW);
895
896         /* faceselect mode drawing over textured mesh */
897         if(!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT))
898                 draw_mesh_face_select(rv3d, ob->data, dm);
899 }
900