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