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