Updated the embedded font to contain the 2 top rows of signs/chars/thingies. Also...
[divverent/darkplaces.git] / gl_draw.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
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.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20
21 #include "quakedef.h"
22 #include "image.h"
23 #include "wad.h"
24
25 #include "cl_video.h"
26
27
28 static rtexture_t *char_texture;
29
30 //=============================================================================
31 /* Support Routines */
32
33 #define MAX_CACHED_PICS 256
34 #define CACHEPICHASHSIZE 256
35 static cachepic_t *cachepichash[CACHEPICHASHSIZE];
36 static cachepic_t cachepics[MAX_CACHED_PICS];
37 static int numcachepics;
38
39 static rtexturepool_t *drawtexturepool;
40
41 static qbyte concharimage[13396] =
42 {
43 #include "lhfont.h"
44 };
45
46 extern qbyte *LoadTGA (qbyte *f, int matchwidth, int matchheight);
47
48 static rtexture_t *draw_generateconchars(void)
49 {
50         int i;
51         qbyte buffer[65536][4], *data = NULL;
52
53         fs_filesize = 13396;
54         data = LoadTGA (concharimage, 256, 256);
55         fs_filesize = -1;
56 // Gold numbers
57         for (i = 0;i < 8192;i++)
58         {
59                 buffer[i][0] = 115;
60                 buffer[i][1] = 87;
61                 buffer[i][2] = 31;
62                 buffer[i][3] = data[i*4+0];
63         }
64 // White chars
65         for (i = 8192;i < 32768;i++)
66         {
67                 buffer[i][0] = 123;
68                 buffer[i][1] = 123;
69                 buffer[i][2] = 123;
70                 buffer[i][3] = data[i*4+0];
71         }
72 // Gold numbers
73         for (i = 32768;i < 40960;i++)
74         {
75                 buffer[i][0] = 115;
76                 buffer[i][1] = 87;
77                 buffer[i][2] = 31;
78                 buffer[i][3] = data[i*4+0];
79         }
80 // Red chars
81         for (i = 40960;i < 65536;i++)
82         {
83                 buffer[i][0] = 143;
84                 buffer[i][1] = 67;
85                 buffer[i][2] = 51;
86                 buffer[i][3] = data[i*4+0];
87         }
88
89         Mem_Free(data);
90         return R_LoadTexture2D(drawtexturepool, "conchars", 256, 256, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
91 }
92
93 static qbyte pointerimage[256] =
94 {
95         "333333332......."
96         "26777761........"
97         "2655541........."
98         "265541.........."
99         "2654561........."
100         "26414561........"
101         "251.14561......."
102         "21...14561......"
103         "1.....141......."
104         ".......1........"
105         "................"
106         "................"
107         "................"
108         "................"
109         "................"
110         "................"
111 };
112
113 static rtexture_t *draw_generatemousepointer(void)
114 {
115         int i;
116         qbyte buffer[256][4];
117         for (i = 0;i < 256;i++)
118         {
119                 if (pointerimage[i] == '.')
120                 {
121                         buffer[i][0] = 0;
122                         buffer[i][1] = 0;
123                         buffer[i][2] = 0;
124                         buffer[i][3] = 0;
125                 }
126                 else
127                 {
128                         buffer[i][0] = (pointerimage[i] - '0') * 16;
129                         buffer[i][1] = (pointerimage[i] - '0') * 16;
130                         buffer[i][2] = (pointerimage[i] - '0') * 16;
131                         buffer[i][3] = 255;
132                 }
133         }
134         return R_LoadTexture2D(drawtexturepool, "mousepointer", 16, 16, &buffer[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
135 }
136
137 // must match NUMCROSSHAIRS in r_crosshairs.c
138 #define NUMCROSSHAIRS 5
139
140 static qbyte *crosshairtexdata[NUMCROSSHAIRS] =
141 {
142         "................"
143         "................"
144         "................"
145         "...33......33..."
146         "...355....553..."
147         "....577..775...."
148         ".....77..77....."
149         "................"
150         "................"
151         ".....77..77....."
152         "....577..775...."
153         "...355....553..."
154         "...33......33..."
155         "................"
156         "................"
157         "................"
158         ,
159         "................"
160         "................"
161         "................"
162         "...3........3..."
163         "....5......5...."
164         ".....7....7....."
165         "......7..7......"
166         "................"
167         "................"
168         "......7..7......"
169         ".....7....7....."
170         "....5......5...."
171         "...3........3..."
172         "................"
173         "................"
174         "................"
175         ,
176         "................"
177         ".......77......."
178         ".......77......."
179         "................"
180         "................"
181         ".......44......."
182         ".......44......."
183         ".77..44..44..77."
184         ".77..44..44..77."
185         ".......44......."
186         ".......44......."
187         "................"
188         ".......77......."
189         ".......77......."
190         "................"
191         "................"
192         ,
193         "................"
194         "................"
195         "................"
196         "................"
197         "................"
198         "................"
199         "................"
200         "................"
201         "........7777777."
202         "........752....."
203         "........72......"
204         "........7......."
205         "........7......."
206         "........7......."
207         "................"
208         "................"
209         ,
210         "................"
211         "................"
212         "................"
213         "................"
214         "................"
215         "........7......."
216         "................"
217         "........4......."
218         ".....7.4.4.7...."
219         "........4......."
220         "................"
221         "........7......."
222         "................"
223         "................"
224         "................"
225         "................"
226 };
227
228 static rtexture_t *draw_generatecrosshair(int num)
229 {
230         int i;
231         char *in;
232         qbyte data[16*16][4];
233         in = crosshairtexdata[num];
234         for (i = 0;i < 16*16;i++)
235         {
236                 if (in[i] == '.')
237                 {
238                         data[i][0] = 255;
239                         data[i][1] = 255;
240                         data[i][2] = 255;
241                         data[i][3] = 0;
242                 }
243                 else
244                 {
245                         data[i][0] = 255;
246                         data[i][1] = 255;
247                         data[i][2] = 255;
248                         data[i][3] = (qbyte) ((int) (in[i] - '0') * 255 / 7);
249                 }
250         }
251         return R_LoadTexture2D(drawtexturepool, va("crosshair%i", num), 16, 16, &data[0][0], TEXTYPE_RGBA, TEXF_ALPHA | TEXF_PRECACHE, NULL);
252 }
253
254 static rtexture_t *draw_generateditherpattern(void)
255 {
256 #if 1
257         int x, y;
258         qbyte data[8*8*4];
259         for (y = 0;y < 8;y++)
260         {
261                 for (x = 0;x < 8;x++)
262                 {
263                         data[(y*8+x)*4+0] = data[(y*8+x)*4+1] = data[(y*8+x)*4+2] = ((x^y) & 4) ? 255 : 0;
264                         data[(y*8+x)*4+3] = 255;
265                 }
266         }
267         return R_LoadTexture2D(drawtexturepool, "ditherpattern", 8, 8, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
268 #else
269         qbyte data[16];
270         memset(data, 255, sizeof(data));
271         data[0] = data[1] = data[2] = data[12] = data[13] = data[14] = 0;
272         return R_LoadTexture2D(drawtexturepool, "ditherpattern", 2, 2, data, TEXTYPE_RGBA, TEXF_FORCENEAREST | TEXF_PRECACHE, NULL);
273 #endif
274 }
275
276 /*
277 ================
278 Draw_CachePic
279 ================
280 */
281 // FIXME: move this to client somehow
282 cachepic_t      *Draw_CachePic (const char *path, qboolean persistent)
283 {
284         int i, crc, hashkey;
285         cachepic_t *pic;
286         qpic_t *p;
287         int persistentflag;
288
289     if (!strncmp(CLVIDEOPREFIX, path, sizeof(CLVIDEOPREFIX) - 1)) {
290                 clvideo_t *video;
291
292                 video = CL_GetVideo(path);
293                 if( video )
294                         return &video->cpif;
295         }
296
297         if (persistent) {
298                 persistentflag = TEXF_PRECACHE;
299         } else {
300                 persistentflag = 0;
301         }
302
303         crc = CRC_Block(path, strlen(path));
304         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
305         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
306                 if (!strcmp (path, pic->name))
307                         return pic;
308
309         if (numcachepics == MAX_CACHED_PICS)
310                 Sys_Error ("numcachepics == MAX_CACHED_PICS");
311         pic = cachepics + (numcachepics++);
312         strlcpy (pic->name, path, sizeof(pic->name));
313         // link into list
314         pic->chain = cachepichash[hashkey];
315         cachepichash[hashkey] = pic;
316
317         // load the pic from disk
318         pic->tex = loadtextureimage(drawtexturepool, path, 0, 0, false, TEXF_ALPHA | persistentflag);
319         if (pic->tex == NULL && !strncmp(path, "gfx/", 4))
320         {
321                 // compatibility with older versions
322                 pic->tex = loadtextureimage(drawtexturepool, path + 4, 0, 0, false, TEXF_ALPHA | persistentflag);
323                 // failed to find gfx/whatever.tga or similar, try the wad
324                 if (pic->tex == NULL && (p = W_GetLumpName (path + 4)))
325                 {
326                         if (!strcmp(path, "gfx/conchars"))
327                         {
328                                 qbyte *pix;
329                                 // conchars is a raw image and with the wrong transparent color
330                                 pix = (qbyte *)p;
331                                 for (i = 0;i < 128 * 128;i++)
332                                         if (pix[i] == 0)
333                                                 pix[i] = 255;
334                                 pic->tex = R_LoadTexture2D(drawtexturepool, path, 128, 128, pix, TEXTYPE_PALETTE, TEXF_ALPHA | persistentflag, palette_complete);
335                         }
336                         else
337                                 pic->tex = R_LoadTexture2D(drawtexturepool, path, p->width, p->height, p->data, TEXTYPE_PALETTE, TEXF_ALPHA | persistentflag, palette_complete);
338                 }
339         }
340
341         if (pic->tex == NULL && !strcmp(path, "gfx/conchars"))
342                 pic->tex = draw_generateconchars();
343         if (pic->tex == NULL && !strcmp(path, "ui/mousepointer.tga"))
344                 pic->tex = draw_generatemousepointer();
345         if (pic->tex == NULL && !strcmp(path, "gfx/prydoncursor001.tga"))
346                 pic->tex = draw_generatemousepointer();
347         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair1.tga"))
348                 pic->tex = draw_generatecrosshair(0);
349         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair2.tga"))
350                 pic->tex = draw_generatecrosshair(1);
351         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair3.tga"))
352                 pic->tex = draw_generatecrosshair(2);
353         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair4.tga"))
354                 pic->tex = draw_generatecrosshair(3);
355         if (pic->tex == NULL && !strcmp(path, "gfx/crosshair5.tga"))
356                 pic->tex = draw_generatecrosshair(4);
357         if (pic->tex == NULL && !strcmp(path, "gfx/colorcontrol/ditherpattern.tga"))
358                 pic->tex = draw_generateditherpattern();
359         if (pic->tex == NULL)
360         {
361                 Con_Printf("Draw_CachePic: failed to load %s\n", path);
362                 pic->tex = r_texture_notexture;
363         }
364
365         pic->width = R_TextureWidth(pic->tex);
366         pic->height = R_TextureHeight(pic->tex);
367         return pic;
368 }
369
370 cachepic_t *Draw_NewPic(const char *picname, int width, int height, int alpha, qbyte *pixels)
371 {
372         int crc, hashkey;
373         cachepic_t *pic;
374
375         crc = CRC_Block(picname, strlen(picname));
376         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
377         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
378                 if (!strcmp (picname, pic->name))
379                         break;
380
381         if (pic)
382         {
383                 if (pic->tex && pic->width == width && pic->height == height)
384                 {
385                         R_UpdateTexture(pic->tex, pixels);
386                         return pic;
387                 }
388         }
389         else
390         {
391                 if (pic == NULL)
392                 {
393                         if (numcachepics == MAX_CACHED_PICS)
394                                 Sys_Error ("numcachepics == MAX_CACHED_PICS");
395                         pic = cachepics + (numcachepics++);
396                         strcpy (pic->name, picname);
397                         // link into list
398                         pic->chain = cachepichash[hashkey];
399                         cachepichash[hashkey] = pic;
400                 }
401         }
402
403         pic->width = width;
404         pic->height = height;
405         if (pic->tex)
406                 R_FreeTexture(pic->tex);
407         pic->tex = R_LoadTexture2D(drawtexturepool, picname, width, height, pixels, TEXTYPE_RGBA, alpha ? TEXF_ALPHA : 0, NULL);
408         return pic;
409 }
410
411 void Draw_FreePic(const char *picname)
412 {
413         int crc;
414         int hashkey;
415         cachepic_t *pic;
416         // this doesn't really free the pic, but does free it's texture
417         crc = CRC_Block(picname, strlen(picname));
418         hashkey = ((crc >> 8) ^ crc) % CACHEPICHASHSIZE;
419         for (pic = cachepichash[hashkey];pic;pic = pic->chain)
420         {
421                 if (!strcmp (picname, pic->name) && pic->tex)
422                 {
423                         R_FreeTexture(pic->tex);
424                         pic->width = 0;
425                         pic->height = 0;
426                         return;
427                 }
428         }
429 }
430
431 /*
432 ===============
433 Draw_Init
434 ===============
435 */
436 static void gl_draw_start(void)
437 {
438         drawtexturepool = R_AllocTexturePool();
439
440         numcachepics = 0;
441         memset(cachepichash, 0, sizeof(cachepichash));
442
443         char_texture = Draw_CachePic("gfx/conchars", true)->tex;
444 }
445
446 static void gl_draw_shutdown(void)
447 {
448         R_FreeTexturePool(&drawtexturepool);
449
450         numcachepics = 0;
451         memset(cachepichash, 0, sizeof(cachepichash));
452 }
453
454 static void gl_draw_newmap(void)
455 {
456 }
457
458 void GL_Draw_Init (void)
459 {
460         numcachepics = 0;
461         memset(cachepichash, 0, sizeof(cachepichash));
462
463         R_RegisterModule("GL_Draw", gl_draw_start, gl_draw_shutdown, gl_draw_newmap);
464 }
465
466 float blendvertex3f[9] = {-5000, -5000, 10, 10000, -5000, 10, -5000, 10000, 10};
467
468 int quadelements[768];
469 void R_DrawQueue(void)
470 {
471         int pos, num, chartexnum, texnum, batch;
472         float x, y, w, h, s, t, u, v, *av, *at, c[4];
473         cachepic_t *pic;
474         drawqueue_t *dq;
475         char *str;
476         int batchcount;
477         unsigned int color;
478         drawqueuemesh_t *mesh;
479         rmeshstate_t m;
480
481         if (!r_render.integer)
482                 return;
483
484         if (!quadelements[1])
485         {
486                 // elements for rendering a series of quads as triangles
487                 for (batch = 0, pos = 0, num = 0;batch < 128;batch++, num += 4)
488                 {
489                         quadelements[pos++] = num;
490                         quadelements[pos++] = num + 1;
491                         quadelements[pos++] = num + 2;
492                         quadelements[pos++] = num;
493                         quadelements[pos++] = num + 2;
494                         quadelements[pos++] = num + 3;
495                 }
496         }
497
498         r_view_width = bound(0, r_refdef.width, vid.width);
499         r_view_height = bound(0, r_refdef.height, vid.height);
500         r_view_depth = 1;
501         r_view_x = bound(0, r_refdef.x, vid.width - r_refdef.width);
502         r_view_y = bound(0, r_refdef.y, vid.height - r_refdef.height);
503         r_view_z = 0;
504         r_view_fov_x = bound(0.1, r_refdef.fov_x, 170);
505         r_view_fov_y = bound(0.1, r_refdef.fov_y, 170);
506         r_view_matrix = r_refdef.viewentitymatrix;
507         GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
508
509         qglViewport(r_view_x, vid.height - (r_view_y + r_view_height), r_view_width, r_view_height);
510         GL_SetupView_Mode_Ortho(0, 0, vid_conwidth.integer, vid_conheight.integer, -10, 100);
511         qglDepthFunc(GL_LEQUAL);
512         R_Mesh_Matrix(&r_identitymatrix);
513
514         chartexnum = R_GetTexture(char_texture);
515
516         memset(&m, 0, sizeof(m));
517
518         pic = NULL;
519         texnum = 0;
520         color = 0;
521         GL_Color(1,1,1,1);
522
523         batch = false;
524         batchcount = 0;
525         for (pos = 0;pos < r_refdef.drawqueuesize;pos += ((drawqueue_t *)(r_refdef.drawqueue + pos))->size)
526         {
527                 dq = (drawqueue_t *)(r_refdef.drawqueue + pos);
528                 color = dq->color;
529
530                 if(dq->flags == DRAWFLAG_ADDITIVE)
531                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
532                 else if(dq->flags == DRAWFLAG_MODULATE)
533                         GL_BlendFunc(GL_DST_COLOR, GL_ZERO);
534                 else if(dq->flags == DRAWFLAG_2XMODULATE)
535                         GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR);
536                 else
537                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
538
539                 GL_DepthMask(true);
540                 GL_DepthTest(false);
541
542                 c[0] = (float) ((color >> 24) & 0xFF) * (1.0f / 255.0f);
543                 c[1] = (float) ((color >> 16) & 0xFF) * (1.0f / 255.0f);
544                 c[2] = (float) ((color >>  8) & 0xFF) * (1.0f / 255.0f);
545                 c[3] = (float) ( color        & 0xFF) * (1.0f / 255.0f);
546                 x = dq->x;
547                 y = dq->y;
548                 w = dq->scalex;
549                 h = dq->scaley;
550
551                 switch(dq->command)
552                 {
553                 case DRAWQUEUE_STRING:
554                         GL_Color(c[0], c[1], c[2], c[3]);
555                         str = (char *)(dq + 1);
556                         batchcount = 0;
557                         m.pointer_vertex = varray_vertex3f;
558                         m.pointer_color = NULL;
559                         m.pointer_texcoord[0] = varray_texcoord2f[0];
560                         m.tex[0] = chartexnum;
561                         R_Mesh_State(&m);
562                         at = varray_texcoord2f[0];
563                         av = varray_vertex3f;
564                         while ((num = *str++) && x < vid_conwidth.integer)
565                         {
566                                 if (num != ' ')
567                                 {
568                                         s = (num & 15)*0.0625f + (0.5f / 256.0f);
569                                         t = (num >> 4)*0.0625f + (0.5f / 256.0f);
570                                         u = 0.0625f - (1.0f / 256.0f);
571                                         v = 0.0625f - (1.0f / 256.0f);
572                                         at[ 0] = s  ;at[ 1] = t  ;
573                                         at[ 2] = s+u;at[ 3] = t  ;
574                                         at[ 4] = s+u;at[ 5] = t+v;
575                                         at[ 6] = s  ;at[ 7] = t+v;
576                                         av[ 0] = x  ;av[ 1] = y  ;av[ 2] = 10;
577                                         av[ 3] = x+w;av[ 4] = y  ;av[ 5] = 10;
578                                         av[ 6] = x+w;av[ 7] = y+h;av[ 8] = 10;
579                                         av[ 9] = x  ;av[10] = y+h;av[11] = 10;
580                                         at += 8;
581                                         av += 12;
582                                         batchcount++;
583                                         if (batchcount >= 128)
584                                         {
585                                                 GL_LockArrays(0, batchcount * 4);
586                                                 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements);
587                                                 GL_LockArrays(0, 0);
588                                                 batchcount = 0;
589                                                 at = varray_texcoord2f[0];
590                                                 av = varray_vertex3f;
591                                         }
592                                 }
593                                 x += w;
594                         }
595                         if (batchcount > 0)
596                         {
597                                 GL_LockArrays(0, batchcount * 4);
598                                 R_Mesh_Draw(0, batchcount * 4, batchcount * 2, quadelements);
599                                 GL_LockArrays(0, 0);
600                         }
601                         break;
602                 case DRAWQUEUE_MESH:
603                         mesh = (void *)(dq + 1);
604                         m.pointer_vertex = mesh->data_vertex3f;
605                         m.pointer_color = mesh->data_color4f;
606                         m.pointer_texcoord[0] = mesh->data_texcoord2f;
607                         m.tex[0] = R_GetTexture(mesh->texture);
608                         if (!m.tex[0])
609                                 m.pointer_texcoord[0] = NULL;
610                         R_Mesh_State(&m);
611                         GL_LockArrays(0, mesh->num_vertices);
612                         R_Mesh_Draw(0, mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
613                         GL_LockArrays(0, 0);
614                         break;
615                 case DRAWQUEUE_SETCLIP:
616                         {
617                                 // We have to convert the con coords into real coords
618                                 int x , y, width, height;
619                                 x = dq->x * ((float)vid.width / vid_conwidth.integer);
620                                 // OGL uses top to bottom
621                                 y = dq->y * ((float) vid.height / vid_conheight.integer);
622                                 width = dq->scalex * ((float)vid.width / vid_conwidth.integer);
623                                 height = dq->scaley * ((float)vid.height / vid_conheight.integer);
624
625                                 GL_Scissor(x, y, width, height);
626
627                                 GL_ScissorTest(true);
628                         }
629                         break;
630                 case DRAWQUEUE_RESETCLIP:
631                         GL_ScissorTest(false);
632                         break;
633                 }
634         }
635
636         if (!vid_usinghwgamma)
637         {
638                 // all the blends ignore depth
639                 memset(&m, 0, sizeof(m));
640                 m.pointer_vertex = blendvertex3f;
641                 R_Mesh_State(&m);
642                 GL_DepthMask(true);
643                 GL_DepthTest(false);
644                 if (v_color_enable.integer)
645                 {
646                         c[0] = v_color_white_r.value;
647                         c[1] = v_color_white_g.value;
648                         c[2] = v_color_white_b.value;
649                 }
650                 else
651                         c[0] = c[1] = c[2] = v_contrast.value;
652                 if (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
653                 {
654                         GL_BlendFunc(GL_DST_COLOR, GL_ONE);
655                         while (c[0] >= 1.01f || c[1] >= 1.01f || c[2] >= 1.01f)
656                         {
657                                 GL_Color(bound(0, c[0] - 1, 1), bound(0, c[1] - 1, 1), bound(0, c[2] - 1, 1), 1);
658                                 R_Mesh_Draw(0, 3, 1, polygonelements);
659                                 VectorScale(c, 0.5, c);
660                         }
661                 }
662                 if (v_color_enable.integer)
663                 {
664                         c[0] = v_color_black_r.value;
665                         c[1] = v_color_black_g.value;
666                         c[2] = v_color_black_b.value;
667                 }
668                 else
669                         c[0] = c[1] = c[2] = v_brightness.value;
670                 if (c[0] >= 0.01f || c[1] >= 0.01f || c[2] >= 0.01f)
671                 {
672                         GL_BlendFunc(GL_ONE, GL_ONE);
673                         GL_Color(c[0], c[1], c[2], 1);
674                         R_Mesh_Draw(0, 3, 1, polygonelements);
675                 }
676         }
677 }
678