Fix for bug #3802: Display problems with modifiers and uv face select
[blender.git] / source / blender / src / drawmesh.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <string.h>
34 #include <math.h>
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include "MEM_guardedalloc.h"
41
42 #include "BLI_blenlib.h"
43 #include "BLI_arithb.h"
44 #include "BLI_edgehash.h"
45
46 #include "IMB_imbuf_types.h"
47
48 #include "DNA_image_types.h"
49 #include "DNA_lamp_types.h"
50 #include "DNA_material_types.h"
51 #include "DNA_mesh_types.h"
52 #include "DNA_meshdata_types.h"
53 #include "DNA_object_types.h"
54 #include "DNA_property_types.h"
55 #include "DNA_scene_types.h"
56 #include "DNA_view3d_types.h"
57
58 #include "BKE_bmfont.h"
59 #include "BKE_displist.h"
60 #include "BKE_DerivedMesh.h"
61 #include "BKE_effect.h"
62 #include "BKE_global.h"
63 #include "BKE_image.h"
64 #include "BKE_main.h"
65 #include "BKE_material.h"
66 #include "BKE_mesh.h"
67 #include "BKE_object.h"
68 #include "BKE_property.h"
69 #include "BKE_utildefines.h"
70
71 #include "BIF_resources.h"
72 #include "BIF_gl.h"
73 #include "BIF_glutil.h"
74 #include "BIF_mywindow.h"
75 #include "BIF_resources.h"
76
77 #include "BDR_editface.h"
78 #include "BDR_vpaint.h"
79 #include "BDR_drawmesh.h"
80
81 #include "BSE_drawview.h"
82
83 #include "blendef.h"
84 #include "nla.h"
85
86 //#include "glext.h"
87 /* some local functions */
88 #if defined(GL_EXT_texture_object) && (!defined(__sun__) || (!defined(__sun))) && !defined(__APPLE__) && !defined(__linux__) && !defined(WIN32)
89         #define glBindTexture(A,B)     glBindTextureEXT(A,B)
90         #define glGenTextures(A,B)     glGenTexturesEXT(A,B)
91         #define glDeleteTextures(A,B)  glDeleteTexturesEXT(A,B)
92         #define glPolygonOffset(A,B)  glPolygonOffsetEXT(A,B)
93
94 #else
95
96 /* #define GL_FUNC_ADD_EXT                                      GL_FUNC_ADD */
97 /* #define GL_FUNC_REVERSE_SUBTRACT_EXT GL_FUNC_REVERSE_SUBTRACT */
98 /* #define GL_POLYGON_OFFSET_EXT                        GL_POLYGON_OFFSET */
99
100 #endif
101
102         /* (n&(n-1)) zeros the least significant bit of n */
103 static int is_pow2(int num) {
104         return ((num)&(num-1))==0;
105 }
106 static int smaller_pow2(int num) {
107         while (!is_pow2(num))
108                 num= num&(num-1);
109         return num;     
110 }
111
112 static int fCurtile=0, fCurmode=0,fCurtileXRep=0,fCurtileYRep=0;
113 static Image *fCurpage=0;
114 static short fTexwindx, fTexwindy, fTexwinsx, fTexwinsy;
115 static int fDoMipMap = 1;
116 static int fLinearMipMap = 0;
117
118 /* local prototypes --------------- */
119 void update_realtime_textures(void);
120
121
122 /*  static int source, dest; also not used */
123
124 /**
125  * Enables or disable mipmapping for realtime images.
126  * @param mipmap Turn mipmapping on (mipmap!=0) or off (mipmap==0).
127  */
128 void set_mipmap(int mipmap)
129 {
130         if (fDoMipMap != (mipmap != 0)) {
131                 free_all_realtime_images();
132                 fDoMipMap = mipmap != 0;
133         }
134 }
135
136
137 /**
138  * Returns the current setting for mipmapping.
139  */
140 int get_mipmap(void)
141 {
142         return fDoMipMap;
143 }
144
145 /**
146  * Enables or disable linear mipmap setting for realtime images (textures).
147  * Note that this will will destroy all texture bindings in OpenGL.
148  * @see free_realtime_image()
149  * @param mipmap Turn linear mipmapping on (linear!=0) or off (linear==0).
150  */
151 void set_linear_mipmap(int linear)
152 {
153         if (fLinearMipMap != (linear != 0)) {
154                 free_all_realtime_images();
155                 fLinearMipMap = linear != 0;
156         }
157 }
158
159 /**
160  * Returns the current setting for linear mipmapping.
161  */
162 int get_linear_mipmap(void)
163 {
164         return fLinearMipMap;
165 }
166
167
168 /**
169  * Resets the realtime image cache variables.
170  */
171 void clear_realtime_image_cache()
172 {
173         fCurpage = NULL;
174         fCurtile = 0;
175         fCurmode = 0;
176         fCurtileXRep = 0;
177         fCurtileYRep = 0;
178 }
179
180 /* REMEMBER!  Changes here must go into my_set_tpage() as well */
181 int set_tpage(TFace *tface)
182 {       
183         static int alphamode= -1;
184         static TFace *lasttface= 0;
185         Image *ima;
186         unsigned int *rect=NULL, *bind;
187         int tpx=0, tpy=0, tilemode, tileXRep,tileYRep;
188         
189         /* disable */
190         if(tface==0) {
191                 if(lasttface==0) return 0;
192                 
193                 lasttface= 0;
194                 fCurtile= 0;
195                 fCurpage= 0;
196                 if(fCurmode!=0) {
197                         glMatrixMode(GL_TEXTURE);
198                         glLoadIdentity();
199                         glMatrixMode(GL_MODELVIEW);
200                 }
201                 fCurmode= 0;
202                 fCurtileXRep=0;
203                 fCurtileYRep=0;
204                 alphamode= -1;
205                 
206                 glDisable(GL_BLEND);
207                 glDisable(GL_TEXTURE_2D);
208                 glDisable(GL_TEXTURE_GEN_S);
209                 glDisable(GL_TEXTURE_GEN_T);
210
211                 return 0;
212         }
213         lasttface= tface;
214
215         if( alphamode != tface->transp) {
216                 alphamode= tface->transp;
217
218                 if(alphamode) {
219                         glEnable(GL_BLEND);
220                         
221                         if(alphamode==TF_ADD) {
222                                 glBlendFunc(GL_ONE, GL_ONE);
223                         /*      glBlendEquationEXT(GL_FUNC_ADD_EXT); */
224                         }
225                         else if(alphamode==TF_ALPHA) {
226                                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
227                         /*      glBlendEquationEXT(GL_FUNC_ADD_EXT); */
228                         }
229                         /* else { */
230                         /*      glBlendFunc(GL_ONE, GL_ONE); */
231                         /*      glBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT_EXT); */
232                         /* } */
233                 }
234                 else glDisable(GL_BLEND);
235         }
236
237         ima= tface->tpage;
238
239         /* Enable or disable reflection mapping */
240         if (ima && (ima->flag & IMA_REFLECT)){
241
242 //              glActiveTextureARB(GL_TEXTURE0_ARB);
243                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
244                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
245
246                 glEnable(GL_TEXTURE_GEN_S);
247                 glEnable(GL_TEXTURE_GEN_T);
248
249                 /* Handle multitexturing here */
250         }
251         else{
252                 glDisable(GL_TEXTURE_GEN_S);
253                 glDisable(GL_TEXTURE_GEN_T);
254         }
255
256         tilemode= tface->mode & TF_TILES;
257         tileXRep = 0;
258         tileYRep = 0;
259         if (ima)
260         {
261                 tileXRep = ima->xrep;
262                 tileYRep = ima->yrep;
263         }
264
265
266         if(ima==fCurpage && fCurtile==tface->tile && tilemode==fCurmode && fCurtileXRep==tileXRep && fCurtileYRep == tileYRep) return ima!=0;
267
268         if(tilemode!=fCurmode || fCurtileXRep!=tileXRep || fCurtileYRep != tileYRep)
269         {
270                 glMatrixMode(GL_TEXTURE);
271                 glLoadIdentity();
272                 
273                 if(tilemode && ima!=0)
274                         glScalef(ima->xrep, ima->yrep, 1.0);
275
276                 glMatrixMode(GL_MODELVIEW);
277         }
278
279         if(ima==0 || ima->ok==0) {
280                 glDisable(GL_TEXTURE_2D);
281                 
282                 fCurtile= tface->tile;
283                 fCurpage= 0;
284                 fCurmode= tilemode;
285                 fCurtileXRep = tileXRep;
286                 fCurtileYRep = tileYRep;
287
288                 return 0;
289         }
290
291         if(ima->ibuf==0) {
292                 load_image(ima, IB_rect, G.sce, G.scene->r.cfra);
293
294                 if(ima->ibuf==0) {
295                         ima->ok= 0;
296
297                         fCurtile= tface->tile;
298                         fCurpage= 0;
299                         fCurmode= tilemode;
300                         fCurtileXRep = tileXRep;
301                         fCurtileYRep = tileYRep;
302                         
303                         glDisable(GL_TEXTURE_2D);
304                         return 0;
305                 }
306                 
307         }
308
309         if(ima->tpageflag & IMA_TWINANIM) fCurtile= ima->lastframe;
310         else fCurtile= tface->tile;
311
312         if(tilemode) {
313
314                 if(ima->repbind==0) make_repbind(ima);
315                 
316                 if(fCurtile>=ima->totbind) fCurtile= 0;
317                 
318                 /* this happens when you change repeat buttons */
319                 if(ima->repbind) bind= ima->repbind+fCurtile;
320                 else bind= &ima->bindcode;
321                 
322                 if(*bind==0) {
323                         
324                         fTexwindx= ima->ibuf->x/ima->xrep;
325                         fTexwindy= ima->ibuf->y/ima->yrep;
326                         
327                         if(fCurtile>=ima->xrep*ima->yrep) fCurtile= ima->xrep*ima->yrep-1;
328         
329                         fTexwinsy= fCurtile / ima->xrep;
330                         fTexwinsx= fCurtile - fTexwinsy*ima->xrep;
331         
332                         fTexwinsx*= fTexwindx;
333                         fTexwinsy*= fTexwindy;
334         
335                         tpx= fTexwindx;
336                         tpy= fTexwindy;
337
338                         rect= ima->ibuf->rect + fTexwinsy*ima->ibuf->x + fTexwinsx;
339                 }
340         }
341         else {
342                 bind= &ima->bindcode;
343                 
344                 if(*bind==0) {
345                         tpx= ima->ibuf->x;
346                         tpy= ima->ibuf->y;
347                         rect= ima->ibuf->rect;
348                 }
349         }
350
351         if(*bind==0) {
352                 int rectw= tpx, recth= tpy;
353                 unsigned int *tilerect= NULL, *scalerect= NULL;
354
355                 /*
356                  * Maarten:
357                  * According to Ton this code is not needed anymore. It was used only
358                  * in really old Blenders.
359                  * Reevan:
360                  * Actually it is needed for backwards compatibility.  Simpledemo 6 does not display correctly without it.
361                  */
362 #if 1
363                 if (tilemode) {
364                         int y;
365                                 
366                         tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
367                         for (y=0; y<recth; y++) {
368                                 unsigned int *rectrow= &rect[y*ima->ibuf->x];
369                                 unsigned int *tilerectrow= &tilerect[y*rectw];
370                                         
371                                 memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow));
372                         }
373                                 
374                         rect= tilerect;
375                 }
376 #endif
377                 if (!is_pow2(rectw) || !is_pow2(recth)) {
378                         rectw= smaller_pow2(rectw);
379                         recth= smaller_pow2(recth);
380                         
381                         scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect");
382                         gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, rect, rectw, recth, GL_UNSIGNED_BYTE, scalerect);
383                         rect= scalerect;
384                 }
385
386                 glGenTextures(1, (GLuint *)bind);
387                 
388                 if((G.f & G_DEBUG) || !*bind) {
389                         GLenum error = glGetError();
390                         printf("Texture: %s\n", ima->id.name+2);
391                         printf("name: %d, tpx: %d\n", *bind, tpx);
392                         printf("tile: %d, mode: %d\n", fCurtile, tilemode);
393                         if (error)
394                                 printf("error: %s\n", gluErrorString(error));
395                 }
396                 glBindTexture( GL_TEXTURE_2D, *bind);
397
398                 if (!fDoMipMap)
399                 {
400                         glTexImage2D(GL_TEXTURE_2D, 0,  GL_RGBA,  rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
401                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
402                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
403                 } else
404                 {
405                         int minfilter= fLinearMipMap?GL_LINEAR_MIPMAP_LINEAR:GL_LINEAR_MIPMAP_NEAREST;
406                         
407                         gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect);
408                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minfilter);
409                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
410                 }
411
412                 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
413                         
414                 if (tilerect)
415                         MEM_freeN(tilerect);
416                 if (scalerect)
417                         MEM_freeN(scalerect);
418         }
419         else glBindTexture( GL_TEXTURE_2D, *bind);
420         
421         tag_image_time(ima);
422
423         glEnable(GL_TEXTURE_2D);
424
425         fCurpage= ima;
426         fCurmode= tilemode;
427         fCurtileXRep = tileXRep;
428         fCurtileYRep = tileYRep;
429
430         return 1;
431 }
432
433 void free_realtime_image(Image *ima)
434 {
435         if(ima->bindcode) {
436                 glDeleteTextures(1, (GLuint *)&ima->bindcode);
437                 ima->bindcode= 0;
438         }
439         if(ima->repbind) {
440                 glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
441         
442                 MEM_freeN(ima->repbind);
443                 ima->repbind= 0;
444         }
445 }
446
447 void free_all_realtime_images(void)
448 {
449         Image* ima;
450
451         ima= G.main->image.first;
452         while(ima) {
453                 free_realtime_image(ima);
454                 ima= ima->id.next;
455         }
456 }
457
458 void make_repbind(Image *ima)
459 {
460         if(ima==0 || ima->ibuf==0) return;
461
462         if(ima->repbind) {
463                 glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
464                 MEM_freeN(ima->repbind);
465                 ima->repbind= 0;
466         }
467         ima->totbind= ima->xrep*ima->yrep;
468         if(ima->totbind>1) {
469                 ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind");
470         }
471 }
472
473 void update_realtime_textures()
474 {
475         Image *ima;
476         
477         ima= G.main->image.first;
478         while(ima) {
479                 if(ima->tpageflag & IMA_TWINANIM) {
480                         if(ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1;
481                 
482                         /* check: is bindcode not in the array? Free. (to do) */
483                         
484                         ima->lastframe++;
485                         if(ima->lastframe > ima->twend) ima->lastframe= ima->twsta;
486                         
487                 }
488                 ima= ima->id.next;
489         }
490 }
491
492 /***/
493
494         /* Flags for marked edges */
495 enum {
496         eEdge_Visible = (1<<0),
497         eEdge_Select = (1<<1),
498         eEdge_Active = (1<<2),
499         eEdge_SelectAndActive = (1<<3),
500         eEdge_ActiveFirst = (1<<4),
501         eEdge_ActiveLast = (1<<5)
502 };
503
504         /* Creates a hash of edges to flags indicating
505          * adjacent tface select/active/etc flags.
506          */
507 static void get_marked_edge_info__orFlags(EdgeHash *eh, int v0, int v1, int flags)
508 {
509         int *flags_p;
510
511         if (!BLI_edgehash_haskey(eh, v0, v1)) {
512                 BLI_edgehash_insert(eh, v0, v1, 0);
513         }
514
515         flags_p = (int*) BLI_edgehash_lookup_p(eh, v0, v1);
516         *flags_p |= flags;
517 }
518
519 EdgeHash *get_tface_mesh_marked_edge_info(Mesh *me)
520 {
521         EdgeHash *eh = BLI_edgehash_new();
522         int i;
523
524         for (i=0; i<me->totface; i++) {
525                 MFace *mf = &me->mface[i];
526                 TFace *tf = &me->tface[i];
527                 
528                 if (mf->v3) {
529                         if (!(tf->flag&TF_HIDE)) {
530                                 unsigned int flags = eEdge_Visible;
531                                 if (tf->flag&TF_SELECT) flags |= eEdge_Select;
532                                 if (tf->flag&TF_ACTIVE) {
533                                         flags |= eEdge_Active;
534                                         if (tf->flag&TF_SELECT) flags |= eEdge_SelectAndActive;
535                                 }
536
537                                 get_marked_edge_info__orFlags(eh, mf->v1, mf->v2, flags);
538                                 get_marked_edge_info__orFlags(eh, mf->v2, mf->v3, flags);
539                                 if (mf->v4) {
540                                         get_marked_edge_info__orFlags(eh, mf->v3, mf->v4, flags);
541                                         get_marked_edge_info__orFlags(eh, mf->v4, mf->v1, flags);
542                                 } else {
543                                         get_marked_edge_info__orFlags(eh, mf->v3, mf->v1, flags);
544                                 }
545
546                                 if (tf->flag&TF_ACTIVE) {
547                                         get_marked_edge_info__orFlags(eh, mf->v1, mf->v2, eEdge_ActiveFirst);
548                                         get_marked_edge_info__orFlags(eh, mf->v1, mf->v4?mf->v4:mf->v3, eEdge_ActiveLast);
549                                 }
550                         }
551                 }
552         }
553
554         return eh;
555 }
556
557
558 static int draw_tfaces3D__setHiddenOpts(void *userData, int index)
559 {
560         struct { Mesh *me; EdgeHash *eh; } *data = userData;
561         MEdge *med = &data->me->medge[index];
562         unsigned int flags = (int) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
563
564         if((G.f & G_DRAWSEAMS) && (med->flag&ME_SEAM)) {
565                 return 0;
566         } else if(G.f & G_DRAWEDGES){ 
567                 if (G.f&G_HIDDENEDGES) {
568                         return 1;
569                 } else {
570                         return (flags & eEdge_Visible);
571                 }
572         } else {
573                 return (flags & eEdge_Select);
574         }
575 }
576 static int draw_tfaces3D__setSeamOpts(void *userData, int index)
577 {
578         struct { Mesh *me; EdgeHash *eh; } *data = userData;
579         MEdge *med = &data->me->medge[index];
580         unsigned int flags = (int) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
581
582         if (med->flag&ME_SEAM) {
583                 if (G.f&G_HIDDENEDGES) {
584                         return 1;
585                 } else {
586                         return (flags & eEdge_Visible);
587                 }
588         } else {
589                 return 0;
590         }
591 }
592 static int draw_tfaces3D__setSelectOpts(void *userData, int index)
593 {
594         struct { Mesh *me; EdgeHash *eh; } *data = userData;
595         MEdge *med = &data->me->medge[index];
596         unsigned int flags = (int) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
597
598         return flags & eEdge_Select;
599 }
600 static int draw_tfaces3D__setActiveOpts(void *userData, int index)
601 {
602         struct { Mesh *me; EdgeHash *eh; } *data = userData;
603         MEdge *med = &data->me->medge[index];
604         unsigned int flags = (int) BLI_edgehash_lookup(data->eh, med->v1, med->v2);
605
606         if (flags & eEdge_Active) {
607                 if (flags & eEdge_ActiveLast) {
608                         glColor3ub(255, 0, 0);
609                 } else if (flags & eEdge_ActiveFirst) {
610                         glColor3ub(0, 255, 0);
611                 } else if (flags & eEdge_SelectAndActive) {
612                         glColor3ub(255, 255, 0);
613                 } else {
614                         glColor3ub(255, 0, 255);
615                 }
616
617                 return 1;
618         } else {
619                 return 0;
620         }
621 }
622 static int draw_tfaces3D__drawFaceOpts(void *userData, int index)
623 {
624         Mesh *me = (Mesh*)userData;
625
626         if (me->tface) {
627                 TFace *tface = &me->tface[index];
628                 if (!(tface->flag&TF_HIDE) && (tface->flag&TF_SELECT))
629                         return 2; /* Don't set color */
630                 else
631                         return 0;
632         } else
633                 return 0;
634 }
635 static void draw_tfaces3D(Object *ob, Mesh *me, DerivedMesh *dm)
636 {
637         struct { Mesh *me; EdgeHash *eh; } data;
638
639         data.me = me;
640         data.eh = get_tface_mesh_marked_edge_info(me);
641
642         glEnable(GL_DEPTH_TEST);
643         glDisable(GL_LIGHTING);
644         bglPolygonOffset(1.0);
645
646                 /* Draw (Hidden) Edges */
647         BIF_ThemeColor(TH_EDGE_FACESEL);
648         dm->drawMappedEdges(dm, draw_tfaces3D__setHiddenOpts, &data);
649
650                 /* Draw Seams */
651         if(G.f & G_DRAWSEAMS) {
652                 BIF_ThemeColor(TH_EDGE_SEAM);
653                 glLineWidth(2);
654
655                 dm->drawMappedEdges(dm, draw_tfaces3D__setSeamOpts, &data);
656
657                 glLineWidth(1);
658         }
659
660                 /* Draw Selected Faces */
661         if(G.f & G_DRAWFACES) {
662                 glEnable(GL_BLEND);
663                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
664                 BIF_ThemeColor4(TH_FACE_SELECT);
665
666                 dm->drawMappedFacesTex(dm, draw_tfaces3D__drawFaceOpts, (void*)me);
667
668                 glDisable(GL_BLEND);
669         }
670         
671         bglPolygonOffset(1.0);
672
673                 /* Draw Stippled Outline for selected faces */
674         glColor3ub(255, 255, 255);
675         setlinestyle(1);
676         dm->drawMappedEdges(dm, draw_tfaces3D__setSelectOpts, &data);
677         setlinestyle(0);
678
679         dm->drawMappedEdges(dm, draw_tfaces3D__setActiveOpts, &data);
680
681         bglPolygonOffset(0.0);  // resets correctly now, even after calling accumulated offsets
682
683         BLI_edgehash_free(data.eh, NULL);
684 }
685
686 static int set_gl_light(Object *ob)
687 {
688         Base *base;
689         Lamp *la;
690         int count;
691         /* float zero[4]= {0.0, 0.0, 0.0, 0.0};  */
692         float vec[4];
693         
694         vec[3]= 1.0;
695         
696         for(count=0; count<8; count++) glDisable(GL_LIGHT0+count);
697         
698         count= 0;
699         
700         base= FIRSTBASE;
701         while(base) {
702                 if(base->object->type==OB_LAMP ) {
703                         if(base->lay & G.vd->lay) {
704                                 if(base->lay & ob->lay) 
705                                 {
706                                         la= base->object->data;
707                                         
708                                         glPushMatrix();
709                                         glLoadMatrixf((float *)G.vd->viewmat);
710                                         
711                                         where_is_object_simul(base->object);
712                                         VECCOPY(vec, base->object->obmat[3]);
713                                         
714                                         if(la->type==LA_SUN) {
715                                                 vec[0]= base->object->obmat[2][0];
716                                                 vec[1]= base->object->obmat[2][1];
717                                                 vec[2]= base->object->obmat[2][2];
718                                                 vec[3]= 0.0;
719                                                 glLightfv(GL_LIGHT0+count, GL_POSITION, vec); 
720                                         }
721                                         else {
722                                                 vec[3]= 1.0;
723                                                 glLightfv(GL_LIGHT0+count, GL_POSITION, vec); 
724                                                 glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0);
725                                                 glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist);
726                                                 /* post 2.25 engine supports quad lights */
727                                                 glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist));
728                                                 
729                                                 if(la->type==LA_SPOT) {
730                                                         vec[0]= -base->object->obmat[2][0];
731                                                         vec[1]= -base->object->obmat[2][1];
732                                                         vec[2]= -base->object->obmat[2][2];
733                                                         glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, vec);
734                                                         glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, la->spotsize/2.0);
735                                                         glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0*la->spotblend);
736                                                 }
737                                                 else glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0);
738                                         }
739                                         
740                                         vec[0]= la->energy*la->r;
741                                         vec[1]= la->energy*la->g;
742                                         vec[2]= la->energy*la->b;
743                                         vec[3]= 1.0;
744                                         glLightfv(GL_LIGHT0+count, GL_DIFFUSE, vec); 
745                                         glLightfv(GL_LIGHT0+count, GL_SPECULAR, vec);//zero); 
746                                         glEnable(GL_LIGHT0+count);
747                                         
748                                         glPopMatrix();                                  
749                                         
750                                         count++;
751                                         if(count>7) break;
752                                 }
753                         }
754                 }
755                 base= base->next;
756         }
757
758         return count;
759 }
760
761 static Material *give_current_material_or_def(Object *ob, int matnr)
762 {
763         extern Material defmaterial;    // render module abuse...
764         Material *ma= give_current_material(ob, matnr);
765
766         return ma?ma:&defmaterial;
767 }
768
769 static int set_draw_settings_cached(int clearcache, int textured, TFace *texface, int lit, Object *litob, int litmatnr, int doublesided)
770 {
771         static int c_textured;
772         static int c_lit;
773         static int c_doublesided;
774         static TFace *c_texface;
775         static Object *c_litob;
776         static int c_litmatnr;
777         static int c_badtex;
778
779         if (clearcache) {
780                 c_textured= c_lit= c_doublesided= -1;
781                 c_texface= (TFace*) -1;
782                 c_litob= (Object*) -1;
783                 c_litmatnr= -1;
784                 c_badtex= 0;
785         }
786
787         if (texface) {
788                 lit = lit && (texface->mode&TF_LIGHT);
789                 textured = textured && (texface->mode&TF_TEX);
790                 doublesided = texface->mode&TF_TWOSIDE;
791         } else {
792                 textured = 0;
793         }
794
795         if (doublesided!=c_doublesided) {
796                 if (doublesided) glDisable(GL_CULL_FACE);
797                 else glEnable(GL_CULL_FACE);
798
799                 c_doublesided= doublesided;
800         }
801
802         if (textured!=c_textured || texface!=c_texface) {
803                 if (textured ) {
804                         c_badtex= !set_tpage(texface);
805                 } else {
806                         set_tpage(0);
807                         c_badtex= 0;
808                 }
809                 c_textured= textured;
810                 c_texface= texface;
811         }
812
813         if (c_badtex) lit= 0;
814         if (lit!=c_lit || litob!=c_litob || litmatnr!=c_litmatnr) {
815                 if (lit) {
816                         Material *ma= give_current_material_or_def(litob, litmatnr);
817                         float spec[4];
818
819                         spec[0]= ma->spec*ma->specr;
820                         spec[1]= ma->spec*ma->specg;
821                         spec[2]= ma->spec*ma->specb;
822                         spec[3]= 1.0;
823
824                         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
825                         glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
826                         glEnable(GL_LIGHTING);
827                         glEnable(GL_COLOR_MATERIAL);
828                 }
829                 else {
830                         glDisable(GL_LIGHTING); 
831                         glDisable(GL_COLOR_MATERIAL);
832                 }
833                 c_lit= lit;
834                 c_litob= litob;
835                 c_litmatnr= litmatnr;
836         }
837
838         return c_badtex;
839 }
840
841 /* Icky globals, fix with userdata parameter */
842
843 static Object *g_draw_tface_mesh_ob = NULL;
844 static int g_draw_tface_mesh_islight = 0;
845 static int g_draw_tface_mesh_istex = 0;
846 static unsigned char g_draw_tface_mesh_obcol[4];
847 static int draw_tface__set_draw(TFace *tface, int matnr)
848 {
849         if (tface && ((tface->flag&TF_HIDE) || (tface->mode&TF_INVISIBLE))) return 0;
850
851         if (set_draw_settings_cached(0, g_draw_tface_mesh_istex, tface, g_draw_tface_mesh_islight, g_draw_tface_mesh_ob, matnr, TF_TWOSIDE)) {
852                 glColor3ub(0xFF, 0x00, 0xFF);
853                 return 2; /* Don't set color */
854         } else if (tface && tface->mode&TF_OBCOL) {
855                 glColor3ubv(g_draw_tface_mesh_obcol);
856                 return 2; /* Don't set color */
857         } else if (!tface) {
858                 Material *ma= give_current_material(g_draw_tface_mesh_ob, matnr);
859                 if(ma) glColor3f(ma->r, ma->g, ma->b);
860                 else glColor3f(0.5, 0.5, 0.5);
861                 return 1; /* Set color from mcol if available */
862         } else {
863                 return 1; /* Set color from tface */
864         }
865 }
866 static int draw_tface_mapped__set_draw(void *userData, int index)
867 {
868         Mesh *me = (Mesh*)userData;
869         TFace *tface = (me->tface)? &me->tface[index]: NULL;
870         int matnr = me->mface[index].mat_nr;
871
872         draw_tface__set_draw(tface, matnr);
873 }
874
875 void draw_tface_mesh(Object *ob, Mesh *me, int dt)
876 /* maximum dt (drawtype): exactly according values that have been set */
877 {
878         unsigned char obcol[4];
879         int a;
880         short islight, istex;
881         DerivedMesh *dm;
882         int dmNeedsFree;
883         
884         if(me==NULL) return;
885
886         dm = mesh_get_derived_final(ob, &dmNeedsFree);
887
888         glShadeModel(GL_SMOOTH);
889
890         islight= set_gl_light(ob);
891         
892         obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255);
893         obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255);
894         obcol[2]= CLAMPIS(ob->col[2]*255, 0, 255);
895         obcol[3]= CLAMPIS(ob->col[3]*255, 0, 255);
896         
897         /* first all texture polys */
898         
899         if(ob->transflag & OB_NEG_SCALE) glFrontFace(GL_CW);
900         else glFrontFace(GL_CCW);
901         
902         glCullFace(GL_BACK); glEnable(GL_CULL_FACE);
903         if(G.vd->drawtype==OB_TEXTURE) istex= 1;
904         else istex= 0;
905
906         g_draw_tface_mesh_ob = ob;
907         g_draw_tface_mesh_islight = islight;
908         g_draw_tface_mesh_istex = istex;
909         memcpy(g_draw_tface_mesh_obcol, obcol, sizeof(obcol));
910         set_draw_settings_cached(1, 0, 0, 0, 0, 0, 0);
911
912         if(dt > OB_SOLID) {
913                 TFace *tface= me->tface;
914                 MFace *mface= me->mface;
915                 bProperty *prop = get_property(ob, "Text");
916                 int editing= (G.f & (G_VERTEXPAINT+G_FACESELECT+G_TEXTUREPAINT+G_WEIGHTPAINT)) && (ob==((G.scene->basact) ? (G.scene->basact->object) : 0));
917                 int start, totface;
918
919                 if(ob==OBACT && (G.f & G_FACESELECT) && me && me->tface)
920                         dm->drawMappedFacesTex(dm, draw_tface_mapped__set_draw, (void*)me);
921                 else
922                         dm->drawFacesTex(dm, draw_tface__set_draw);
923
924                 start = 0;
925                 totface = me->totface;
926
927                 if (!editing && prop && tface) {
928                         int dmNeedsFree;
929                         DerivedMesh *dm = mesh_get_derived_deform(ob, &dmNeedsFree);
930
931                         tface+= start;
932                         for (a=start; a<totface; a++, tface++) {
933                                 MFace *mf= &mface[a];
934                                 int mode= tface->mode;
935                                 int matnr= mf->mat_nr;
936                                 int mf_smooth= mf->flag & ME_SMOOTH;
937
938                                 if (!(tface->flag&TF_HIDE) && !(mode&TF_INVISIBLE) && (mode&TF_BMFONT)) {
939                                         int badtex= set_draw_settings_cached(0, g_draw_tface_mesh_istex, tface, g_draw_tface_mesh_islight, g_draw_tface_mesh_ob, matnr, TF_TWOSIDE);
940                                         float v1[3], v2[3], v3[3], v4[3];
941                                         char string[MAX_PROPSTRING];
942                                         int characters, index;
943                                         Image *ima;
944                                         float curpos;
945
946                                         if (badtex)
947                                                 continue;
948
949                                         dm->getVertCo(dm, mf->v1, v1);
950                                         dm->getVertCo(dm, mf->v2, v2);
951                                         dm->getVertCo(dm, mf->v3, v3);
952                                         if (mf->v4) dm->getVertCo(dm, mf->v4, v4);
953
954                                         // The BM_FONT handling code is duplicated in the gameengine
955                                         // Search for 'Frank van Beek' ;-)
956                                         // string = "Frank van Beek";
957
958                                         set_property_valstr(prop, string);
959                                         characters = strlen(string);
960                                         
961                                         ima = tface->tpage;
962                                         if (ima == NULL) {
963                                                 characters = 0;
964                                         }
965
966                                         if (!mf_smooth) {
967                                                 float nor[3];
968
969                                                 CalcNormFloat(v1, v2, v3, nor);
970
971                                                 glNormal3fv(nor);
972                                         }
973
974                                         curpos= 0.0;
975                                         glBegin(mf->v4?GL_QUADS:GL_TRIANGLES);
976                                         for (index = 0; index < characters; index++) {
977                                                 float centerx, centery, sizex, sizey, transx, transy, movex, movey, advance;
978                                                 int character = string[index];
979                                                 char *cp= NULL;
980
981                                                 // lets calculate offset stuff
982                                                 // space starts at offset 1
983                                                 // character = character - ' ' + 1;
984                                                 
985                                                 matrixGlyph(ima->ibuf, character, & centerx, &centery, &sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
986                                                 movex+= curpos;
987
988                                                 if (tface->mode & TF_OBCOL) glColor3ubv(obcol);
989                                                 else cp= (char *)&(tface->col[0]);
990
991                                                 glTexCoord2f((tface->uv[0][0] - centerx) * sizex + transx, (tface->uv[0][1] - centery) * sizey + transy);
992                                                 if (cp) glColor3ub(cp[3], cp[2], cp[1]);
993                                                 glVertex3f(sizex * v1[0] + movex, sizey * v1[1] + movey, v1[2]);
994                                                 
995                                                 glTexCoord2f((tface->uv[1][0] - centerx) * sizex + transx, (tface->uv[1][1] - centery) * sizey + transy);
996                                                 if (cp) glColor3ub(cp[7], cp[6], cp[5]);
997                                                 glVertex3f(sizex * v2[0] + movex, sizey * v2[1] + movey, v2[2]);
998                         
999                                                 glTexCoord2f((tface->uv[2][0] - centerx) * sizex + transx, (tface->uv[2][1] - centery) * sizey + transy);
1000                                                 if (cp) glColor3ub(cp[11], cp[10], cp[9]);
1001                                                 glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]);
1002                         
1003                                                 if(mf->v4) {
1004                                                         glTexCoord2f((tface->uv[3][0] - centerx) * sizex + transx, (tface->uv[3][1] - centery) * sizey + transy);
1005                                                         if (cp) glColor3ub(cp[15], cp[14], cp[13]);
1006                                                         glVertex3f(sizex * v4[0] + movex, sizey * v4[1] + movey, v4[2]);
1007                                                 }
1008
1009                                                 curpos+= advance;
1010                                         }
1011                                         glEnd();
1012                                 }
1013                         }
1014
1015                         if (dmNeedsFree) dm->release(dm);
1016                 }
1017
1018                 /* switch off textures */
1019                 set_tpage(0);
1020         }
1021         glShadeModel(GL_FLAT);
1022         glDisable(GL_CULL_FACE);
1023         
1024         if(ob==OBACT && (G.f & G_FACESELECT) && me && me->tface) {
1025                 draw_tfaces3D(ob, me, dm);
1026         }
1027         
1028                 /* XXX, bad patch - default_gl_light() calls
1029                  * glLightfv(GL_LIGHT_POSITION, ...) which
1030                  * is transformed by the current matrix... we
1031                  * need to make sure that matrix is identity.
1032                  * 
1033                  * It would be better if drawmesh.c kept track
1034                  * of and restored the light settings it changed.
1035                  *  - zr
1036                  */
1037         glPushMatrix();
1038         glLoadIdentity();       
1039         default_gl_light();
1040         glPopMatrix();
1041         
1042         glFrontFace(GL_CCW);
1043
1044         if(dt > OB_SOLID && !(ob==OBACT && (G.f & G_FACESELECT) && me && me->tface)) {
1045                 if(ob->flag & SELECT) {
1046                         BIF_ThemeColor((ob==OBACT)?TH_ACTIVE:TH_SELECT);
1047                 } else {
1048                         BIF_ThemeColor(TH_WIRE);
1049                 }
1050                 dm->drawLooseEdges(dm);
1051         }
1052 }
1053
1054 void init_realtime_GL(void)
1055 {               
1056         glMatrixMode(GL_TEXTURE);
1057         glLoadIdentity();
1058         glMatrixMode(GL_MODELVIEW);
1059
1060 }
1061