]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmisc.c
pmodel fixes (now works properly in listen/singleplayer)
[xonotic/darkplaces.git] / gl_rmisc.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 // r_misc.c
21
22 #include "quakedef.h"
23
24
25
26 /*
27 ==================
28 R_InitTextures
29 ==================
30 */
31 void    R_InitTextures (void)
32 {
33         int             x,y, m;
34         byte    *dest;
35
36 // create a simple checkerboard texture for the default
37         r_notexture_mip = Hunk_AllocName (sizeof(texture_t) + 16*16+8*8+4*4+2*2, "notexture");
38         
39         r_notexture_mip->width = r_notexture_mip->height = 16;
40         r_notexture_mip->offsets[0] = sizeof(texture_t);
41         r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16*16;
42         r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8*8;
43         r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4*4;
44         r_notexture_mip->transparent = FALSE;
45         
46         for (m=0 ; m<4 ; m++)
47         {
48                 dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m];
49                 for (y=0 ; y< (16>>m) ; y++)
50                         for (x=0 ; x< (16>>m) ; x++)
51                         {
52                                 if (  (y< (8>>m) ) ^ (x< (8>>m) ) )
53                                         *dest++ = 0;
54                                 else
55                                         *dest++ = 0xff;
56                         }
57         }       
58 }
59
60 /*
61 ===============
62 R_Envmap_f
63
64 Grab six views for environment mapping tests
65 ===============
66 */
67 void R_Envmap_f (void)
68 {
69         byte    buffer[256*256*4];
70
71         glDrawBuffer  (GL_FRONT);
72         glReadBuffer  (GL_FRONT);
73         envmap = true;
74
75         r_refdef.vrect.x = 0;
76         r_refdef.vrect.y = 0;
77         r_refdef.vrect.width = 256;
78         r_refdef.vrect.height = 256;
79
80         r_refdef.viewangles[0] = 0;
81         r_refdef.viewangles[1] = 0;
82         r_refdef.viewangles[2] = 0;
83         GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
84         R_RenderView ();
85         glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
86         COM_WriteFile ("env0.rgb", buffer, sizeof(buffer));             
87
88         r_refdef.viewangles[1] = 90;
89         GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
90         R_RenderView ();
91         glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
92         COM_WriteFile ("env1.rgb", buffer, sizeof(buffer));             
93
94         r_refdef.viewangles[1] = 180;
95         GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
96         R_RenderView ();
97         glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
98         COM_WriteFile ("env2.rgb", buffer, sizeof(buffer));             
99
100         r_refdef.viewangles[1] = 270;
101         GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
102         R_RenderView ();
103         glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
104         COM_WriteFile ("env3.rgb", buffer, sizeof(buffer));             
105
106         r_refdef.viewangles[0] = -90;
107         r_refdef.viewangles[1] = 0;
108         GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
109         R_RenderView ();
110         glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
111         COM_WriteFile ("env4.rgb", buffer, sizeof(buffer));             
112
113         r_refdef.viewangles[0] = 90;
114         r_refdef.viewangles[1] = 0;
115         GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
116         R_RenderView ();
117         glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
118         COM_WriteFile ("env5.rgb", buffer, sizeof(buffer));             
119
120         envmap = false;
121         glDrawBuffer  (GL_BACK);
122         glReadBuffer  (GL_BACK);
123         GL_EndRendering ();
124 }
125
126 void R_InitParticles (void);
127
128 /*
129 ===============
130 R_Init
131 ===============
132 */
133 void R_Init (void)
134 {       
135         extern byte *hunk_base;
136 //      extern cvar_t gl_finish;
137
138         Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);        
139         Cmd_AddCommand ("envmap", R_Envmap_f);  
140         Cmd_AddCommand ("pointfile", R_ReadPointFile_f);        
141
142 //      Cvar_RegisterVariable (&r_norefresh);
143 //      Cvar_RegisterVariable (&r_lightmap);
144         Cvar_RegisterVariable (&r_drawentities);
145         Cvar_RegisterVariable (&r_drawviewmodel);
146 //      Cvar_RegisterVariable (&r_shadows);
147         Cvar_RegisterVariable (&r_wateralpha);
148 //      Cvar_RegisterVariable (&r_dynamic);
149         Cvar_RegisterVariable (&r_novis);
150         Cvar_RegisterVariable (&r_speeds);
151         Cvar_RegisterVariable (&r_waterripple); // LordHavoc: added waterripple
152
153 //      Cvar_RegisterVariable (&gl_cull);
154 //      Cvar_RegisterVariable (&gl_affinemodels);
155 //      Cvar_RegisterVariable (&gl_polyblend);
156 //      Cvar_RegisterVariable (&gl_flashblend);
157         Cvar_RegisterVariable (&gl_playermip);
158 //      Cvar_RegisterVariable (&gl_nocolors);
159
160 //      Cvar_RegisterVariable (&gl_keeptjunctions);
161 //      Cvar_RegisterVariable (&gl_reporttjunctions);
162
163         R_InitParticles ();
164
165         playertextures = texture_extension_number;
166         texture_extension_number += 64; // LordHavoc: increased number of players from 16 to 64
167 }
168
169 qboolean VID_Is8bit(void);
170 void GL_Upload8_EXT (byte *data, int width, int height,  qboolean mipmap, qboolean alpha);
171
172 /*
173 ===============
174 R_TranslatePlayerSkin
175
176 Translates a skin texture by the per-player color lookup
177 ===============
178 */
179 void R_TranslatePlayerSkin (int playernum)
180 {
181         int             top, bottom;
182         byte    translate[256];
183         unsigned        translate32[256];
184         int             i, j, s;
185         model_t *model;
186         aliashdr_t *paliashdr;
187         byte    *original;
188         unsigned        pixels[512*256], *out;
189         unsigned        scaled_width, scaled_height;
190         int                     inwidth, inheight;
191         byte            *inrow;
192         unsigned        frac, fracstep;
193         extern  byte            **player_8bit_texels_tbl;
194
195         top = cl.scores[playernum].colors & 0xf0;
196         bottom = (cl.scores[playernum].colors &15)<<4;
197
198         for (i=0 ; i<256 ; i++)
199                 translate[i] = i;
200
201         for (i=0 ; i<16 ; i++)
202         {
203                 // LordHavoc: corrected color ranges
204                 if (top < 128 || (top >= 224 && top < 240))     // the artists made some backwards ranges.  sigh.
205                         translate[TOP_RANGE+i] = top+i;
206                 else
207                         translate[TOP_RANGE+i] = top+15-i;
208
209                 // LordHavoc: corrected color ranges
210                 if (bottom < 128 || (bottom >= 224 && bottom < 240))
211                         translate[BOTTOM_RANGE+i] = bottom+i;
212                 else
213                         translate[BOTTOM_RANGE+i] = bottom+15-i;
214         }
215
216         //
217         // locate the original skin pixels
218         //
219         currententity = &cl_entities[1+playernum];
220         model = currententity->model;
221         if (!model)
222                 return;         // player doesn't have a model yet
223         if (model->type != mod_alias)
224                 return; // only translate skins on alias models
225
226         paliashdr = (aliashdr_t *)Mod_Extradata (model);
227         s = paliashdr->skinwidth * paliashdr->skinheight;
228         if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->numskins)
229         {
230                 Con_Printf("(%d): Invalid player skin #%d\n", playernum, currententity->skinnum);
231                 original = (byte *)paliashdr + paliashdr->texels[0];
232         }
233         else
234                 original = (byte *)paliashdr + paliashdr->texels[currententity->skinnum];
235         if (s & 3)
236                 Sys_Error ("R_TranslateSkin: s&3");
237
238         inwidth = paliashdr->skinwidth;
239         inheight = paliashdr->skinheight;
240
241         // because this happens during gameplay, do it fast
242         // instead of sending it through gl_upload 8
243     glBindTexture(GL_TEXTURE_2D, playertextures + playernum);
244
245 #if 0
246         byte    translated[320*200];
247
248         for (i=0 ; i<s ; i+=4)
249         {
250                 translated[i] = translate[original[i]];
251                 translated[i+1] = translate[original[i+1]];
252                 translated[i+2] = translate[original[i+2]];
253                 translated[i+3] = translate[original[i+3]];
254         }
255
256
257         // don't mipmap these, because it takes too long
258         GL_Upload8 (translated, paliashdr->skinwidth, paliashdr->skinheight, false, false, true);
259 #else
260         scaled_width = gl_max_size.value < 512 ? gl_max_size.value : 512;
261         scaled_height = gl_max_size.value < 256 ? gl_max_size.value : 256;
262
263         // allow users to crunch sizes down even more if they want
264         scaled_width >>= (int)gl_playermip.value;
265         scaled_height >>= (int)gl_playermip.value;
266
267         if (VID_Is8bit())
268         { // 8bit texture upload
269                 byte *out2;
270
271                 out2 = (byte *)pixels;
272                 memset(pixels, 0, sizeof(pixels));
273                 fracstep = inwidth*0x10000/scaled_width;
274                 for (i=0 ; i<scaled_height ; i++, out2 += scaled_width)
275                 {
276                         inrow = original + inwidth*(i*inheight/scaled_height);
277                         frac = fracstep >> 1;
278                         for (j=0 ; j<scaled_width ; j+=4)
279                         {
280                                 out2[j] = translate[inrow[frac>>16]];
281                                 frac += fracstep;
282                                 out2[j+1] = translate[inrow[frac>>16]];
283                                 frac += fracstep;
284                                 out2[j+2] = translate[inrow[frac>>16]];
285                                 frac += fracstep;
286                                 out2[j+3] = translate[inrow[frac>>16]];
287                                 frac += fracstep;
288                         }
289                 }
290
291                 GL_Upload8_EXT ((byte *)pixels, scaled_width, scaled_height, false, false);
292                 return;
293         }
294
295         for (i=0 ; i<256 ; i++)
296                 translate32[i] = d_8to24table[translate[i]];
297
298         out = pixels;
299         fracstep = inwidth*0x10000/scaled_width;
300         for (i=0 ; i<scaled_height ; i++, out += scaled_width)
301         {
302                 inrow = original + inwidth*(i*inheight/scaled_height);
303                 frac = fracstep >> 1;
304                 for (j=0 ; j<scaled_width ; j+=4)
305                 {
306                         out[j] = translate32[inrow[frac>>16]];
307                         frac += fracstep;
308                         out[j+1] = translate32[inrow[frac>>16]];
309                         frac += fracstep;
310                         out[j+2] = translate32[inrow[frac>>16]];
311                         frac += fracstep;
312                         out[j+3] = translate32[inrow[frac>>16]];
313                         frac += fracstep;
314                 }
315         }
316         glTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
317
318         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
319         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
320         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
321 #endif
322
323 }
324
325 void R_ClearParticles (void);
326 void GL_BuildLightmaps (void);
327
328 /*
329 ===============
330 R_NewMap
331 ===============
332 */
333 void SHOWLMP_clear();
334 void R_NewMap (void)
335 {
336         int             i;
337         
338         for (i=0 ; i<256 ; i++)
339                 d_lightstylevalue[i] = 264;             // normal light value
340
341         memset (&r_worldentity, 0, sizeof(r_worldentity));
342         r_worldentity.model = cl.worldmodel;
343         currententity = &r_worldentity;
344
345 // clear out efrags in case the level hasn't been reloaded
346 // FIXME: is this one short?
347         for (i=0 ; i<cl.worldmodel->numleafs ; i++)
348                 cl.worldmodel->leafs[i].efrags = NULL;
349                         
350         r_viewleaf = NULL;
351         R_ClearParticles ();
352
353         GL_BuildLightmaps ();
354
355         // identify sky texture
356         skytexturenum = -1;
357         for (i=0 ; i<cl.worldmodel->numtextures ; i++)
358         {
359                 if (!cl.worldmodel->textures[i])
360                         continue;
361                 if (!strncmp(cl.worldmodel->textures[i]->name,"sky",3) )
362                         skytexturenum = i;
363                 cl.worldmodel->textures[i]->texturechain = NULL;
364         }
365         SHOWLMP_clear();
366 }
367
368
369 /*
370 ====================
371 R_TimeRefresh_f
372
373 For program optimization
374 ====================
375 */
376 void R_TimeRefresh_f (void)
377 {
378         int                     i;
379         float           start, stop, time;
380
381         start = Sys_FloatTime ();
382         for (i=0 ; i<128 ; i++)
383         {
384                 r_refdef.viewangles[1] = i/128.0*360.0;
385                 SCR_UpdateScreen();
386         }
387
388         stop = Sys_FloatTime ();
389         time = stop-start;
390         Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
391 }
392
393 void D_FlushCaches (void)
394 {
395 }
396
397