Color Management, Stage 2: Switch color pipeline to use OpenColorIO
[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 *mpoly = &me->mpoly[index];
176         if (!(mpoly->flag & ME_HIDE) && !(mpoly->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->drawMappedFaces(dm, draw_mesh_face_select__drawFaceOptsInv, NULL, NULL, (void *)me, 0);
206                 glDisable(GL_BLEND);
207         }
208         
209         bglPolygonOffset(rv3d->dist, 1.0);
210
211         /* Draw Stippled Outline for selected faces */
212         glColor3ub(255, 255, 255);
213         setlinestyle(1);
214         dm->drawMappedEdges(dm, draw_mesh_face_select__setSelectOpts, &data);
215         setlinestyle(0);
216
217         bglPolygonOffset(rv3d->dist, 0.0);  /* resets correctly now, even after calling accumulated offsets */
218
219         BLI_edgehash_free(data.eh, NULL);
220 }
221
222 /***************************** Texture Drawing ******************************/
223
224 static Material *give_current_material_or_def(Object *ob, int matnr)
225 {
226         extern Material defmaterial;  /* render module abuse... */
227         Material *ma = give_current_material(ob, matnr);
228
229         return ma ? ma : &defmaterial;
230 }
231
232 /* Icky globals, fix with userdata parameter */
233
234 static struct TextureDrawState {
235         Object *ob;
236         int is_lit, is_tex;
237         int color_profile;
238         unsigned char obcol[4];
239 } Gtexdraw = {NULL, 0, 0, 0, {0, 0, 0, 0}};
240
241 static int set_draw_settings_cached(int clearcache, MTFace *texface, Material *ma, struct TextureDrawState gtexdraw)
242 {
243         static Material *c_ma;
244         static int c_textured;
245         static MTFace c_texface;
246         static int c_backculled;
247         static int c_badtex;
248         static int c_lit;
249         static int c_has_texface;
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         int has_texface = texface != NULL;
257         int need_set_tpage = FALSE;
258
259         if (clearcache) {
260                 c_textured = c_lit = c_backculled = -1;
261                 memset(&c_texface, 0, sizeof(MTFace));
262                 c_badtex = 0;
263                 c_has_texface = -1;
264         }
265         else {
266                 textured = gtexdraw.is_tex;
267                 litob = gtexdraw.ob;
268         }
269
270         /* convert number of lights into boolean */
271         if (gtexdraw.is_lit) lit = 1;
272
273         if (ma) {
274                 alphablend = ma->game.alpha_blend;
275                 if (ma->mode & MA_SHLESS) lit = 0;
276                 backculled = ma->game.flag & GEMAT_BACKCULL;
277         }
278
279         if (texface) {
280                 textured = textured && (texface->tpage);
281
282                 /* no material, render alpha if texture has depth=32 */
283                 if (!ma && BKE_image_has_alpha(texface->tpage))
284                         alphablend = GPU_BLEND_ALPHA;
285         }
286
287         else
288                 textured = 0;
289
290         if (backculled != c_backculled) {
291                 if (backculled) glEnable(GL_CULL_FACE);
292                 else glDisable(GL_CULL_FACE);
293
294                 c_backculled = backculled;
295         }
296
297         /* need to re-set tpage if textured flag changed or existsment of texface changed..  */
298         need_set_tpage = textured != c_textured || has_texface != c_has_texface;
299         /* ..or if settings inside texface were changed (if texface was used) */
300         need_set_tpage |= texface && memcmp(&c_texface, texface, sizeof(c_texface));
301
302         if (need_set_tpage) {
303                 if (textured) {
304                         c_badtex = !GPU_set_tpage(texface, !(litob->mode & OB_MODE_TEXTURE_PAINT), alphablend);
305                 }
306                 else {
307                         GPU_set_tpage(NULL, 0, 0);
308                         c_badtex = 0;
309                 }
310                 c_textured = textured;
311                 c_has_texface = has_texface;
312                 if (texface)
313                         memcpy(&c_texface, texface, sizeof(c_texface));
314         }
315
316         if (c_badtex) lit = 0;
317         if (lit != c_lit || ma != c_ma) {
318                 if (lit) {
319                         float spec[4];
320                         if (!ma) ma = give_current_material_or_def(NULL, 0);  /* default material */
321
322                         spec[0] = ma->spec * ma->specr;
323                         spec[1] = ma->spec * ma->specg;
324                         spec[2] = ma->spec * ma->specb;
325                         spec[3] = 1.0;
326
327                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
328                         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
329                         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(ma->har, 0, 128));
330                         glEnable(GL_LIGHTING);
331                         glEnable(GL_COLOR_MATERIAL);
332                 }
333                 else {
334                         glDisable(GL_LIGHTING); 
335                         glDisable(GL_COLOR_MATERIAL);
336                 }
337                 c_lit = lit;
338         }
339
340         return c_badtex;
341 }
342
343 static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object *ob)
344 {
345         unsigned char obcol[4];
346         int is_tex, solidtex;
347         Mesh *me = ob->data;
348
349         /* XXX scene->obedit warning */
350
351         /* texture draw is abused for mask selection mode, do this so wire draw
352          * with face selection in weight paint is not lit. */
353         if ((v3d->drawtype <= OB_WIRE) && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT))) {
354                 solidtex = FALSE;
355                 Gtexdraw.is_lit = 0;
356         }
357         else if (v3d->drawtype == OB_SOLID || ((ob->mode & OB_MODE_EDIT) && v3d->drawtype != OB_TEXTURE)) {
358                 /* draw with default lights in solid draw mode and edit mode */
359                 solidtex = TRUE;
360                 Gtexdraw.is_lit = -1;
361         }
362         else {
363                 /* draw with lights in the scene otherwise */
364                 solidtex = FALSE;
365                 Gtexdraw.is_lit = GPU_scene_object_lights(scene, ob, v3d->lay, rv3d->viewmat, !rv3d->is_persp);
366         }
367         
368         rgba_float_to_uchar(obcol, ob->col);
369
370         if (solidtex || v3d->drawtype == OB_TEXTURE) is_tex = 1;
371         else is_tex = 0;
372
373         Gtexdraw.ob = ob;
374         Gtexdraw.is_tex = is_tex;
375
376         /* OCIO_TODO: for now assume OpenGL is always doing color management and working in sRGB space
377          *            supporting for real display conversion could be nice here, but it's a bit challenging
378          *            since all the shaders should be aware of such a transform
379          *            perhaps this flag could be completely removed before release in separated commit and
380          *            be re-implemented if real display transform would be needed
381          */
382         Gtexdraw.color_profile = TRUE;
383
384         memcpy(Gtexdraw.obcol, obcol, sizeof(obcol));
385         set_draw_settings_cached(1, NULL, NULL, Gtexdraw);
386         glShadeModel(GL_SMOOTH);
387         if (v3d->flag2 & V3D_BACKFACE_CULLING) {
388                 glEnable(GL_CULL_FACE);
389                 glCullFace(GL_BACK);
390         }
391         else {          
392                 glDisable(GL_CULL_FACE);
393         }
394         glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, (me->flag & ME_TWOSIDED) ? GL_TRUE : GL_FALSE);
395 }
396
397 static void draw_textured_end(void)
398 {
399         /* switch off textures */
400         GPU_set_tpage(NULL, 0, 0);
401
402         glShadeModel(GL_FLAT);
403         glDisable(GL_CULL_FACE);
404
405         /* XXX, bad patch - GPU_default_lights() calls
406          * glLightfv(GL_POSITION, ...) which
407          * is transformed by the current matrix... we
408          * need to make sure that matrix is identity.
409          * 
410          * It would be better if drawmesh.c kept track
411          * of and restored the light settings it changed.
412          *  - zr
413          */
414         glPushMatrix();
415         glLoadIdentity();       
416         GPU_default_lights();
417         glPopMatrix();
418 }
419
420 static DMDrawOption draw_tface__set_draw_legacy(MTFace *tface, int has_mcol, int matnr)
421 {
422         Material *ma = give_current_material(Gtexdraw.ob, matnr + 1);
423         int validtexture = 0;
424
425         if (ma && (ma->game.flag & GEMAT_INVISIBLE))
426                 return DM_DRAW_OPTION_SKIP;
427
428         validtexture = set_draw_settings_cached(0, tface, ma, Gtexdraw);
429
430         if (tface && validtexture) {
431                 glColor3ub(0xFF, 0x00, 0xFF);
432                 return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
433         }
434         else if (ma && (ma->shade_flag & MA_OBCOLOR)) {
435                 glColor3ubv(Gtexdraw.obcol);
436                 return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
437         }
438         else if (!has_mcol) {
439                 if (tface) glColor3f(1.0, 1.0, 1.0);
440                 else {
441                         if (ma) {
442                                 float col[3];
443                                 if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
444                                 else copy_v3_v3(col, &ma->r);
445                                 
446                                 glColor3fv(col);
447                         }
448                         else glColor3f(1.0, 1.0, 1.0);
449                 }
450                 return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
451         }
452         else {
453                 return DM_DRAW_OPTION_NORMAL; /* Set color from mcol */
454         }
455 }
456
457 static DMDrawOption draw_mcol__set_draw_legacy(MTFace *UNUSED(tface), int has_mcol, int UNUSED(matnr))
458 {
459         if (has_mcol)
460                 return DM_DRAW_OPTION_NORMAL;
461         else
462                 return DM_DRAW_OPTION_NO_MCOL;
463 }
464
465 static DMDrawOption draw_tface__set_draw(MTFace *tface, int has_mcol, int matnr)
466 {
467         Material *ma = give_current_material(Gtexdraw.ob, matnr + 1);
468
469         if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return 0;
470
471         if (tface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) {
472                 return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
473         }
474         else if (tface && (tface->mode & TF_OBCOL)) {
475                 return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
476         }
477         else if (!has_mcol) {
478                 /* XXX: this return value looks wrong (and doesn't match comment) */
479                 return DM_DRAW_OPTION_NORMAL; /* Don't set color */
480         }
481         else {
482                 return DM_DRAW_OPTION_NORMAL; /* Set color from mcol */
483         }
484 }
485
486 static void update_tface_color_layer(DerivedMesh *dm)
487 {
488         MTFace *tface = DM_get_tessface_data_layer(dm, CD_MTFACE);
489         MFace *mface = dm->getTessFaceArray(dm);
490         MCol *finalCol;
491         int i, j;
492         MCol *mcol = dm->getTessFaceDataArray(dm, CD_PREVIEW_MCOL);
493         if (!mcol)
494                 mcol = dm->getTessFaceDataArray(dm, CD_MCOL);
495
496         if (CustomData_has_layer(&dm->faceData, CD_TEXTURE_MCOL)) {
497                 finalCol = CustomData_get_layer(&dm->faceData, CD_TEXTURE_MCOL);
498         }
499         else {
500                 finalCol = MEM_mallocN(sizeof(MCol) * 4 * dm->getNumTessFaces(dm), "add_tface_color_layer");
501
502                 CustomData_add_layer(&dm->faceData, CD_TEXTURE_MCOL, CD_ASSIGN, finalCol, dm->numTessFaceData);
503         }
504
505         for (i = 0; i < dm->getNumTessFaces(dm); i++) {
506                 Material *ma = give_current_material(Gtexdraw.ob, mface[i].mat_nr + 1);
507
508                 if (ma && (ma->game.flag & GEMAT_INVISIBLE)) {
509                         if (mcol)
510                                 memcpy(&finalCol[i * 4], &mcol[i * 4], sizeof(MCol) * 4);
511                         else
512                                 for (j = 0; j < 4; j++) {
513                                         finalCol[i * 4 + j].b = 255;
514                                         finalCol[i * 4 + j].g = 255;
515                                         finalCol[i * 4 + j].r = 255;
516                                 }
517                 }
518                 else if (tface && set_draw_settings_cached(0, tface, ma, Gtexdraw)) {
519                         for (j = 0; j < 4; j++) {
520                                 finalCol[i * 4 + j].b = 255;
521                                 finalCol[i * 4 + j].g = 0;
522                                 finalCol[i * 4 + j].r = 255;
523                         }
524                 }
525                 else if (tface && (tface->mode & TF_OBCOL)) {
526                         for (j = 0; j < 4; j++) {
527                                 finalCol[i * 4 + j].b = FTOCHAR(Gtexdraw.obcol[0]);
528                                 finalCol[i * 4 + j].g = FTOCHAR(Gtexdraw.obcol[1]);
529                                 finalCol[i * 4 + j].r = FTOCHAR(Gtexdraw.obcol[2]);
530                         }
531                 }
532                 else if (!mcol) {
533                         if (tface) {
534                                 for (j = 0; j < 4; j++) {
535                                         finalCol[i * 4 + j].b = 255;
536                                         finalCol[i * 4 + j].g = 255;
537                                         finalCol[i * 4 + j].r = 255;
538                                 }
539                         }
540                         else {
541                                 float col[3];
542                                 Material *ma = give_current_material(Gtexdraw.ob, mface[i].mat_nr + 1);
543                                 
544                                 if (ma) {
545                                         if (Gtexdraw.color_profile) linearrgb_to_srgb_v3_v3(col, &ma->r);
546                                         else copy_v3_v3(col, &ma->r);
547                                         
548                                         for (j = 0; j < 4; j++) {
549                                                 finalCol[i * 4 + j].b = FTOCHAR(col[0]);
550                                                 finalCol[i * 4 + j].g = FTOCHAR(col[1]);
551                                                 finalCol[i * 4 + j].r = FTOCHAR(col[2]);
552                                         }
553                                 }
554                                 else
555                                         for (j = 0; j < 4; j++) {
556                                                 finalCol[i * 4 + j].b = 255;
557                                                 finalCol[i * 4 + j].g = 255;
558                                                 finalCol[i * 4 + j].r = 255;
559                                         }
560                         }
561                 }
562                 else {
563                         for (j = 0; j < 4; j++) {
564                                 finalCol[i * 4 + j].r = mcol[i * 4 + j].r;
565                                 finalCol[i * 4 + j].g = mcol[i * 4 + j].g;
566                                 finalCol[i * 4 + j].b = mcol[i * 4 + j].b;
567                         }
568                 }
569         }
570 }
571
572 static DMDrawOption draw_tface_mapped__set_draw(void *userData, int index)
573 {
574         Mesh *me = (Mesh *)userData;
575
576         /* array checked for NULL before calling */
577         MPoly *mpoly = &me->mpoly[index];
578
579         BLI_assert(index >= 0 && index < me->totpoly);
580
581         if (mpoly->flag & ME_HIDE) {
582                 return DM_DRAW_OPTION_SKIP;
583         }
584         else {
585                 MTexPoly *tpoly = (me->mtpoly) ? &me->mtpoly[index] : NULL;
586                 MTFace mtf = {{{0}}};
587                 int matnr = mpoly->mat_nr;
588
589                 if (tpoly) {
590                         ME_MTEXFACE_CPY(&mtf, tpoly);
591                 }
592
593                 return draw_tface__set_draw(&mtf, (me->mloopcol != NULL), matnr);
594         }
595 }
596
597 static DMDrawOption draw_em_tf_mapped__set_draw(void *userData, int index)
598 {
599         drawEMTFMapped_userData *data = userData;
600         BMEditMesh *em = data->em;
601         BMFace *efa = EDBM_face_at_index(em, index);
602
603         if (efa == NULL || BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
604                 return DM_DRAW_OPTION_SKIP;
605         }
606         else {
607                 MTFace mtf = {{{0}}};
608                 int matnr = efa->mat_nr;
609
610                 if (data->has_mtface) {
611                         MTexPoly *tpoly = CustomData_bmesh_get(&em->bm->pdata, efa->head.data, CD_MTEXPOLY);
612                         ME_MTEXFACE_CPY(&mtf, tpoly);
613                 }
614
615                 return draw_tface__set_draw_legacy(data->has_mtface ? &mtf : NULL,
616                                                    data->has_mcol, matnr);
617         }
618 }
619
620 /* when face select is on, use face hidden flag */
621 static DMDrawOption wpaint__setSolidDrawOptions_facemask(void *userData, int index)
622 {
623         Mesh *me = (Mesh *)userData;
624         MPoly *mp = &me->mpoly[index];
625         if (mp->flag & ME_HIDE)
626                 return DM_DRAW_OPTION_SKIP;
627         return DM_DRAW_OPTION_NORMAL;
628 }
629
630 static void draw_mesh_text(Scene *scene, Object *ob, int glsl)
631 {
632         Mesh *me = ob->data;
633         DerivedMesh *ddm;
634         MPoly *mp, *mface  = me->mpoly;
635         MTexPoly *mtpoly   = me->mtpoly;
636         MLoopUV *mloopuv   = me->mloopuv;
637         MLoopUV *luv;
638         MLoopCol *mloopcol = me->mloopcol;  /* why does mcol exist? */
639         MLoopCol *lcol;
640
641         bProperty *prop = get_ob_property(ob, "Text");
642         GPUVertexAttribs gattribs;
643         int a, totpoly = me->totpoly;
644
645         /* fake values to pass to GPU_render_text() */
646         MCol tmp_mcol[4]  = {{0}};
647         MCol *tmp_mcol_pt  = mloopcol ? tmp_mcol : NULL;
648         MTFace tmp_tf      = {{{0}}};
649
650         /* don't draw without tfaces */
651         if (!mtpoly || !mloopuv)
652                 return;
653
654         /* don't draw when editing */
655         if (ob->mode & OB_MODE_EDIT)
656                 return;
657         else if (ob == OBACT)
658                 if (paint_facesel_test(ob) || paint_vertsel_test(ob))
659                         return;
660
661         ddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
662
663         for (a = 0, mp = mface; a < totpoly; a++, mtpoly++, mp++) {
664                 short matnr = mp->mat_nr;
665                 int mf_smooth = mp->flag & ME_SMOOTH;
666                 Material *mat = me->mat[matnr];
667                 int mode = mat ? mat->game.flag : GEMAT_INVISIBLE;
668
669                 if (!(mode & GEMAT_INVISIBLE) && (mode & GEMAT_TEXT) && mp->totloop >= 3) {
670                         /* get the polygon as a tri/quad */
671                         int mp_vi[4];
672                         float v1[3], v2[3], v3[3], v4[3];
673                         char string[MAX_PROPSTRING];
674                         int characters, i, glattrib = -1, badtex = 0;
675
676
677                         /* TEXFACE */
678                         ME_MTEXFACE_CPY(&tmp_tf, mtpoly);
679
680                         if (glsl) {
681                                 GPU_enable_material(matnr + 1, &gattribs);
682
683                                 for (i = 0; i < gattribs.totlayer; i++) {
684                                         if (gattribs.layer[i].type == CD_MTFACE) {
685                                                 glattrib = gattribs.layer[i].glindex;
686                                                 break;
687                                         }
688                                 }
689                         }
690                         else {
691                                 badtex = set_draw_settings_cached(0, &tmp_tf, mat, Gtexdraw);
692                                 if (badtex) {
693                                         continue;
694                                 }
695                         }
696
697                         mp_vi[0] = me->mloop[mp->loopstart + 0].v;
698                         mp_vi[1] = me->mloop[mp->loopstart + 1].v;
699                         mp_vi[2] = me->mloop[mp->loopstart + 2].v;
700                         mp_vi[3] = (mp->totloop >= 4) ? me->mloop[mp->loopstart + 3].v : 0;
701
702                         /* UV */
703                         luv = &mloopuv[mp->loopstart];
704                         copy_v2_v2(tmp_tf.uv[0], luv->uv); luv++;
705                         copy_v2_v2(tmp_tf.uv[1], luv->uv); luv++;
706                         copy_v2_v2(tmp_tf.uv[2], luv->uv); luv++;
707                         if (mp->totloop >= 4) {
708                                 copy_v2_v2(tmp_tf.uv[3], luv->uv);
709                         }
710
711                         /* COLOR */
712                         if (mloopcol) {
713                                 unsigned int totloop_clamp = MIN2(4, mp->totloop);
714                                 unsigned int j;
715                                 lcol = &mloopcol[mp->loopstart];
716
717                                 for (j = 0; j <= totloop_clamp; j++, lcol++) {
718                                         MESH_MLOOPCOL_TO_MCOL(lcol, &tmp_mcol[j]);
719                                 }
720                         }
721
722                         /* LOCATION */
723                         ddm->getVertCo(ddm, mp_vi[0], v1);
724                         ddm->getVertCo(ddm, mp_vi[1], v2);
725                         ddm->getVertCo(ddm, mp_vi[2], v3);
726                         if (mp->totloop >= 4) {
727                                 ddm->getVertCo(ddm, mp_vi[3], v4);
728                         }
729
730
731
732                         /* The BM_FONT handling is in the gpu module, shared with the
733                          * game engine, was duplicated previously */
734
735                         set_property_valstr(prop, string);
736                         characters = strlen(string);
737                         
738                         if (!BKE_image_get_ibuf(mtpoly->tpage, NULL))
739                                 characters = 0;
740
741                         if (!mf_smooth) {
742                                 float nor[3];
743
744                                 normal_tri_v3(nor, v1, v2, v3);
745
746                                 glNormal3fv(nor);
747                         }
748
749                         GPU_render_text(&tmp_tf, mode, string, characters,
750                                         (unsigned int *)tmp_mcol_pt, v1, v2, v3, (mp->totloop >= 4 ? v4 : NULL), glattrib);
751                 }
752         }
753
754         ddm->release(ddm);
755 }
756
757 static int compareDrawOptions(void *userData, int cur_index, int next_index)
758 {
759         drawTFace_userData *data = userData;
760
761         if (data->mf && data->mf[cur_index].mat_nr != data->mf[next_index].mat_nr)
762                 return 0;
763
764         if (data->tf && data->tf[cur_index].tpage != data->tf[next_index].tpage)
765                 return 0;
766
767         return 1;
768 }
769
770 static int compareDrawOptionsEm(void *userData, int cur_index, int next_index)
771 {
772         drawEMTFMapped_userData *data = userData;
773
774         if (data->mf && data->mf[cur_index].mat_nr != data->mf[next_index].mat_nr)
775                 return 0;
776
777         if (data->tf && data->tf[cur_index].tpage != data->tf[next_index].tpage)
778                 return 0;
779
780         return 1;
781 }
782
783 static void draw_mesh_textured_old(Scene *scene, View3D *v3d, RegionView3D *rv3d,
784                                    Object *ob, DerivedMesh *dm, const int draw_flags)
785 {
786         Mesh *me = ob->data;
787         
788         /* correct for negative scale */
789         if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
790         else glFrontFace(GL_CCW);
791         
792         /* draw the textured mesh */
793         draw_textured_begin(scene, v3d, rv3d, ob);
794
795         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
796
797         if (ob->mode & OB_MODE_EDIT) {
798                 drawEMTFMapped_userData data;
799
800                 data.em = me->edit_btmesh;
801                 data.has_mcol = CustomData_has_layer(&me->edit_btmesh->bm->ldata, CD_MLOOPCOL);
802                 data.has_mtface = CustomData_has_layer(&me->edit_btmesh->bm->pdata, CD_MTEXPOLY);
803                 data.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
804                 data.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
805
806                 dm->drawMappedFacesTex(dm, draw_em_tf_mapped__set_draw, compareDrawOptionsEm, &data);
807         }
808         else if (draw_flags & DRAW_FACE_SELECT) {
809                 if (ob->mode & OB_MODE_WEIGHT_PAINT)
810                         dm->drawMappedFaces(dm, wpaint__setSolidDrawOptions_facemask, GPU_enable_material, NULL, me,
811                                             DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH);
812                 else
813                         dm->drawMappedFacesTex(dm, me->mpoly ? draw_tface_mapped__set_draw : NULL, NULL, me);
814         }
815         else {
816                 if (GPU_buffer_legacy(dm)) {
817                         if (draw_flags & DRAW_MODIFIERS_PREVIEW)
818                                 dm->drawFacesTex(dm, draw_mcol__set_draw_legacy, NULL, NULL);
819                         else 
820                                 dm->drawFacesTex(dm, draw_tface__set_draw_legacy, NULL, NULL);
821                 }
822                 else {
823                         drawTFace_userData userData;
824
825                         update_tface_color_layer(dm);
826
827                         userData.mf = DM_get_tessface_data_layer(dm, CD_MFACE);
828                         userData.tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
829
830                         dm->drawFacesTex(dm, draw_tface__set_draw, compareDrawOptions, &userData);
831                 }
832         }
833
834         /* draw game engine text hack */
835         if (get_ob_property(ob, "Text"))
836                 draw_mesh_text(scene, ob, 0);
837
838         draw_textured_end();
839         
840         /* draw edges and selected faces over textured mesh */
841         if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT))
842                 draw_mesh_face_select(rv3d, me, dm);
843
844         /* reset from negative scale correction */
845         glFrontFace(GL_CCW);
846         
847         /* in editmode, the blend mode needs to be set in case it was ADD */
848         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
849 }
850
851 /************************** NEW SHADING NODES ********************************/
852
853 typedef struct TexMatCallback {
854         Scene *scene;
855         Object *ob;
856         Mesh *me;
857         DerivedMesh *dm;
858 } TexMatCallback;
859
860 static void tex_mat_set_material_cb(void *UNUSED(userData), int mat_nr, void *attribs)
861 {
862         /* all we have to do here is simply enable the GLSL material, but note
863          * that the GLSL code will give different result depending on the drawtype,
864          * in texture draw mode it will output the active texture node, in material
865          * draw mode it will show the full material. */
866         GPU_enable_material(mat_nr, attribs);
867 }
868
869 static void tex_mat_set_texture_cb(void *userData, int mat_nr, void *attribs)
870 {
871         /* texture draw mode without GLSL */
872         TexMatCallback *data = (TexMatCallback *)userData;
873         GPUVertexAttribs *gattribs = attribs;
874         Image *ima;
875         ImageUser *iuser;
876         bNode *node;
877         int texture_set = 0;
878
879         /* draw image texture if we find one */
880         if (ED_object_get_active_image(data->ob, mat_nr, &ima, &iuser, &node)) {
881                 /* get openl texture */
882                 int mipmap = 1;
883                 int bindcode = (ima) ? GPU_verify_image(ima, iuser, 0, 0, mipmap, FALSE) : 0;
884                 float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
885
886                 if (bindcode) {
887                         NodeTexBase *texbase = node->storage;
888
889                         /* disable existing material */
890                         GPU_disable_material();
891                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero);
892                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
893                         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0);
894
895                         /* bind texture */
896                         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
897                         glEnable(GL_COLOR_MATERIAL);
898                         glEnable(GL_TEXTURE_2D);
899
900                         glBindTexture(GL_TEXTURE_2D, ima->bindcode);
901                         glColor3f(1.0f, 1.0f, 1.0f);
902
903                         glMatrixMode(GL_TEXTURE);
904                         glLoadMatrixf(texbase->tex_mapping.mat);
905                         glMatrixMode(GL_MODELVIEW);
906
907                         /* use active UV texture layer */
908                         memset(gattribs, 0, sizeof(*gattribs));
909
910                         gattribs->layer[0].type = CD_MTFACE;
911                         gattribs->layer[0].name[0] = '\0';
912                         gattribs->layer[0].gltexco = 1;
913                         gattribs->totlayer = 1;
914
915                         texture_set = 1;
916                 }
917         }
918
919         if (!texture_set) {
920                 glMatrixMode(GL_TEXTURE);
921                 glLoadIdentity();
922                 glMatrixMode(GL_MODELVIEW);
923
924                 /* disable texture */
925                 glDisable(GL_TEXTURE_2D);
926                 glDisable(GL_COLOR_MATERIAL);
927
928                 /* draw single color */
929                 GPU_enable_material(mat_nr, attribs);
930         }
931 }
932
933 static int tex_mat_set_face_mesh_cb(void *userData, int index)
934 {
935         /* faceselect mode face hiding */
936         TexMatCallback *data = (TexMatCallback *)userData;
937         Mesh *me = (Mesh *)data->me;
938         MPoly *mp = &me->mpoly[index];
939
940         return !(mp->flag & ME_HIDE);
941 }
942
943 static int tex_mat_set_face_editmesh_cb(void *userData, int index)
944 {
945         /* editmode face hiding */
946         TexMatCallback *data = (TexMatCallback *)userData;
947         Mesh *me = (Mesh *)data->me;
948         BMFace *efa = EDBM_face_at_index(me->edit_btmesh, index);
949
950         return !BM_elem_flag_test(efa, BM_ELEM_HIDDEN);
951 }
952
953 void draw_mesh_textured(Scene *scene, View3D *v3d, RegionView3D *rv3d,
954                         Object *ob, DerivedMesh *dm, const int draw_flags)
955 {
956         if ((!BKE_scene_use_new_shading_nodes(scene)) || (draw_flags & DRAW_MODIFIERS_PREVIEW)) {
957                 draw_mesh_textured_old(scene, v3d, rv3d, ob, dm, draw_flags);
958                 return;
959         }
960         else if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) {
961                 draw_mesh_paint(v3d, rv3d, ob, dm, draw_flags);
962                 return;
963         }
964
965         /* set opengl state for negative scale & color */
966         if (ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
967         else glFrontFace(GL_CCW);
968
969         glEnable(GL_LIGHTING);
970
971         {
972                 Mesh *me = ob->data;
973                 TexMatCallback data = {scene, ob, me, dm};
974                 int (*set_face_cb)(void *, int);
975                 int glsl;
976                 
977                 /* face hiding callback depending on mode */
978                 if (ob == scene->obedit)
979                         set_face_cb = tex_mat_set_face_editmesh_cb;
980                 else if (draw_flags & DRAW_FACE_SELECT)
981                         set_face_cb = tex_mat_set_face_mesh_cb;
982                 else
983                         set_face_cb = NULL;
984
985                 /* test if we can use glsl */
986                 glsl = (v3d->drawtype == OB_MATERIAL) && GPU_glsl_support();
987
988                 GPU_begin_object_materials(v3d, rv3d, scene, ob, glsl, NULL);
989
990                 if (glsl) {
991                         /* draw glsl */
992                         dm->drawMappedFacesMat(dm,
993                                                tex_mat_set_material_cb,
994                                                set_face_cb, &data);
995                 }
996                 else {
997                         float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f};
998
999                         /* draw textured */
1000                         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero);
1001                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
1002                         glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 0);
1003
1004                         dm->drawMappedFacesMat(dm,
1005                                                tex_mat_set_texture_cb,
1006                                                set_face_cb, &data);
1007                 }
1008
1009                 GPU_end_object_materials();
1010         }
1011
1012         /* reset opengl state */
1013         glDisable(GL_COLOR_MATERIAL);
1014         glDisable(GL_TEXTURE_2D);
1015         glDisable(GL_LIGHTING);
1016         glBindTexture(GL_TEXTURE_2D, 0);
1017         glFrontFace(GL_CCW);
1018
1019         glMatrixMode(GL_TEXTURE);
1020         glLoadIdentity();
1021         glMatrixMode(GL_MODELVIEW);
1022
1023         /* faceselect mode drawing over textured mesh */
1024         if (!(ob == scene->obedit) && (draw_flags & DRAW_FACE_SELECT))
1025                 draw_mesh_face_select(rv3d, ob->data, dm);
1026 }
1027
1028 /* Vertex Paint and Weight Paint */
1029
1030 void draw_mesh_paint(View3D *v3d, RegionView3D *rv3d,
1031                      Object *ob, DerivedMesh *dm, const int draw_flags)
1032 {
1033         DMSetDrawOptions facemask = NULL;
1034         Mesh *me = ob->data;
1035         const short do_light = (v3d->drawtype >= OB_SOLID);
1036
1037         /* hide faces in face select mode */
1038         if (draw_flags & DRAW_FACE_SELECT)
1039                 facemask = wpaint__setSolidDrawOptions_facemask;
1040
1041         if (ob->mode & OB_MODE_WEIGHT_PAINT) {
1042
1043                 if (do_light) {
1044                         const float spec[4] = {0.47f, 0.47f, 0.47f, 0.47f};
1045
1046                         /* enforce default material settings */
1047                         GPU_enable_material(0, NULL);
1048                 
1049                         /* but set default spec */
1050                         glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1051                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
1052
1053                         /* diffuse */
1054                         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1055                         glEnable(GL_LIGHTING);
1056                         glEnable(GL_COLOR_MATERIAL);
1057                 }
1058
1059                 dm->drawMappedFaces(dm, facemask, GPU_enable_material, NULL, me,
1060                                     DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH);
1061
1062                 if (do_light) {
1063                         glDisable(GL_COLOR_MATERIAL);
1064                         glDisable(GL_LIGHTING);
1065
1066                         GPU_disable_material();
1067                 }
1068         }
1069         else if (ob->mode & OB_MODE_VERTEX_PAINT) {
1070                 if (me->mloopcol) {
1071                         dm->drawMappedFaces(dm, facemask, GPU_enable_material, NULL, me,
1072                                             DM_DRAW_USE_COLORS | DM_DRAW_ALWAYS_SMOOTH);
1073                 }
1074                 else {
1075                         glColor3f(1.0f, 1.0f, 1.0f);
1076                         dm->drawMappedFaces(dm, facemask, GPU_enable_material, NULL, me,
1077                                             DM_DRAW_ALWAYS_SMOOTH);
1078                 }
1079         }
1080
1081         /* draw face selection on top */
1082         if (draw_flags & DRAW_FACE_SELECT) {
1083                 draw_mesh_face_select(rv3d, me, dm);
1084         }
1085         else if ((do_light == FALSE) || (ob->dtx & OB_DRAWWIRE)) {
1086
1087                 /* weight paint in solid mode, special case. focus on making the weights clear
1088                  * rather than the shading, this is also forced in wire view */
1089
1090                 bglPolygonOffset(rv3d->dist, 1.0);
1091                 glDepthMask(0);  /* disable write in zbuffer, selected edge wires show better */
1092
1093                 glEnable(GL_BLEND);
1094                 glColor4ub(255, 255, 255, 96);
1095                 glEnable(GL_LINE_STIPPLE);
1096                 glLineStipple(1, 0xAAAA);
1097
1098                 dm->drawEdges(dm, 1, 1);
1099
1100                 bglPolygonOffset(rv3d->dist, 0.0);
1101                 glDepthMask(1);
1102                 glDisable(GL_LINE_STIPPLE);
1103                 glDisable(GL_BLEND);
1104         }
1105 }
1106