• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 extern void R_InitBubble();
25 
26 /*
27 ==================
28 R_InitTextures
29 ==================
30 */
R_InitTextures(void)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 
45 	for (m=0 ; m<4 ; m++)
46 	{
47 		dest = (byte *)r_notexture_mip + r_notexture_mip->offsets[m];
48 		for (y=0 ; y< (16>>m) ; y++)
49 			for (x=0 ; x< (16>>m) ; x++)
50 			{
51 				if (  (y< (8>>m) ) ^ (x< (8>>m) ) )
52 					*dest++ = 0;
53 				else
54 					*dest++ = 0xff;
55 			}
56 	}
57 }
58 
59 byte	dottexture[8][8] =
60 {
61 	{0,1,1,0,0,0,0,0},
62 	{1,1,1,1,0,0,0,0},
63 	{1,1,1,1,0,0,0,0},
64 	{0,1,1,0,0,0,0,0},
65 	{0,0,0,0,0,0,0,0},
66 	{0,0,0,0,0,0,0,0},
67 	{0,0,0,0,0,0,0,0},
68 	{0,0,0,0,0,0,0,0},
69 };
R_InitParticleTexture(void)70 void R_InitParticleTexture (void)
71 {
72 	int		x,y;
73 	byte	data[8][8][4];
74 
75 	//
76 	// particle texture
77 	//
78 	particletexture = texture_extension_number++;
79     GL_Bind(particletexture);
80 
81 	for (x=0 ; x<8 ; x++)
82 	{
83 		for (y=0 ; y<8 ; y++)
84 		{
85 			data[y][x][0] = 255;
86 			data[y][x][1] = 255;
87 			data[y][x][2] = 255;
88 			data[y][x][3] = dottexture[x][y]*255;
89 		}
90 	}
91 	glTexImage2DHelper (GL_TEXTURE_2D, 0, gl_alpha_format, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
92 
93 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
94 
95 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
96 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
97 }
98 
99 /*
100 ===============
101 R_Envmap_f
102 
103 Grab six views for environment mapping tests
104 ===============
105 */
R_Envmap_f(void)106 void R_Envmap_f (void)
107 {
108 #ifdef USE_OPENGLES
109 	// Not implemented
110 #else
111 	byte	buffer[256*256*4];
112 
113 	glDrawBuffer  (GL_FRONT);
114 	glReadBuffer  (GL_FRONT);
115 	envmap = true;
116 
117 	r_refdef.vrect.x = 0;
118 	r_refdef.vrect.y = 0;
119 	r_refdef.vrect.width = 256;
120 	r_refdef.vrect.height = 256;
121 
122 	r_refdef.viewangles[0] = 0;
123 	r_refdef.viewangles[1] = 0;
124 	r_refdef.viewangles[2] = 0;
125 	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
126 	R_RenderView ();
127 	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
128 	COM_WriteFile ("env0.rgb", buffer, sizeof(buffer));
129 
130 	r_refdef.viewangles[1] = 90;
131 	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
132 	R_RenderView ();
133 	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
134 	COM_WriteFile ("env1.rgb", buffer, sizeof(buffer));
135 
136 	r_refdef.viewangles[1] = 180;
137 	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
138 	R_RenderView ();
139 	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
140 	COM_WriteFile ("env2.rgb", buffer, sizeof(buffer));
141 
142 	r_refdef.viewangles[1] = 270;
143 	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
144 	R_RenderView ();
145 	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
146 	COM_WriteFile ("env3.rgb", buffer, sizeof(buffer));
147 
148 	r_refdef.viewangles[0] = -90;
149 	r_refdef.viewangles[1] = 0;
150 	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
151 	R_RenderView ();
152 	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
153 	COM_WriteFile ("env4.rgb", buffer, sizeof(buffer));
154 
155 	r_refdef.viewangles[0] = 90;
156 	r_refdef.viewangles[1] = 0;
157 	GL_BeginRendering (&glx, &gly, &glwidth, &glheight);
158 	R_RenderView ();
159 	glReadPixels (0, 0, 256, 256, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
160 	COM_WriteFile ("env5.rgb", buffer, sizeof(buffer));
161 
162 	envmap = false;
163 	glDrawBuffer  (GL_BACK);
164 	glReadBuffer  (GL_BACK);
165 	GL_EndRendering ();
166 #endif
167 }
168 
169 /*
170 ===============
171 R_Init
172 ===============
173 */
R_Init(void)174 void R_Init (void)
175 {
176 	Cmd_AddCommand ("timerefresh", R_TimeRefresh_f);
177 	Cmd_AddCommand ("envmap", R_Envmap_f);
178 	Cmd_AddCommand ("pointfile", R_ReadPointFile_f);
179 
180 	Cvar_RegisterVariable (&r_norefresh);
181 	Cvar_RegisterVariable (&r_lightmap);
182 	Cvar_RegisterVariable (&r_fullbright);
183 	Cvar_RegisterVariable (&r_drawentities);
184 	Cvar_RegisterVariable (&r_drawviewmodel);
185 	Cvar_RegisterVariable (&r_shadows);
186 	Cvar_RegisterVariable (&r_mirroralpha);
187 	Cvar_RegisterVariable (&r_wateralpha);
188 	Cvar_RegisterVariable (&r_dynamic);
189 	Cvar_RegisterVariable (&r_novis);
190 	Cvar_RegisterVariable (&r_speeds);
191 	Cvar_RegisterVariable (&r_netgraph);
192 
193 	Cvar_RegisterVariable (&gl_clear);
194 	Cvar_RegisterVariable (&gl_texsort);
195 
196  	if (gl_mtexable)
197 		Cvar_SetValue ("gl_texsort", 0.0);
198 
199 	Cvar_RegisterVariable (&gl_cull);
200 	Cvar_RegisterVariable (&gl_smoothmodels);
201 	Cvar_RegisterVariable (&gl_affinemodels);
202 	Cvar_RegisterVariable (&gl_polyblend);
203 	Cvar_RegisterVariable (&gl_flashblend);
204 	Cvar_RegisterVariable (&gl_playermip);
205 	Cvar_RegisterVariable (&gl_nocolors);
206 	Cvar_RegisterVariable (&gl_finish);
207 
208 	Cvar_RegisterVariable (&gl_keeptjunctions);
209 	Cvar_RegisterVariable (&gl_reporttjunctions);
210 
211 	R_InitBubble();
212 
213 	R_InitParticles ();
214 	R_InitParticleTexture ();
215 
216 #ifdef GLTEST
217 	Test_Init ();
218 #endif
219 
220 	netgraphtexture = texture_extension_number;
221 	texture_extension_number++;
222 
223 	playertextures = texture_extension_number;
224 	texture_extension_number += MAX_CLIENTS;
225 }
226 
227 /*
228 ===============
229 R_TranslatePlayerSkin
230 
231 Translates a skin texture by the per-player color lookup
232 ===============
233 */
R_TranslatePlayerSkin(int playernum)234 void R_TranslatePlayerSkin (int playernum)
235 {
236 	int		top, bottom;
237 	byte	translate[256];
238 	unsigned	translate32[256];
239 	int		i, j;
240 	byte	*original;
241 	unsigned	pixels[512*256], *out;
242 	unsigned	scaled_width, scaled_height;
243 	int			inwidth, inheight;
244 	int			tinwidth, tinheight;
245 	byte		*inrow;
246 	unsigned	frac, fracstep;
247 	player_info_t *player;
248 	extern	byte		player_8bit_texels[320*200];
249 	char s[512];
250 
251 	GL_DisableMultitexture();
252 
253 	player = &cl.players[playernum];
254 	if (!player->name[0])
255 		return;
256 
257 	strcpy(s, Info_ValueForKey(player->userinfo, "skin"));
258 	COM_StripExtension(s, s);
259 	if (player->skin && !stricmp(s, player->skin->name))
260 		player->skin = NULL;
261 
262 	if (player->_topcolor != player->topcolor ||
263 		player->_bottomcolor != player->bottomcolor || !player->skin) {
264 		player->_topcolor = player->topcolor;
265 		player->_bottomcolor = player->bottomcolor;
266 
267 		top = player->topcolor;
268 		bottom = player->bottomcolor;
269 		top = (top < 0) ? 0 : ((top > 13) ? 13 : top);
270 		bottom = (bottom < 0) ? 0 : ((bottom > 13) ? 13 : bottom);
271 		top *= 16;
272 		bottom *= 16;
273 
274 		for (i=0 ; i<256 ; i++)
275 			translate[i] = i;
276 
277 		for (i=0 ; i<16 ; i++)
278 		{
279 			if (top < 128)	// the artists made some backwards ranges.  sigh.
280 				translate[TOP_RANGE+i] = top+i;
281 			else
282 				translate[TOP_RANGE+i] = top+15-i;
283 
284 			if (bottom < 128)
285 				translate[BOTTOM_RANGE+i] = bottom+i;
286 			else
287 				translate[BOTTOM_RANGE+i] = bottom+15-i;
288 		}
289 
290 		//
291 		// locate the original skin pixels
292 		//
293 		// real model width
294 		tinwidth = 296;
295 		tinheight = 194;
296 
297 		if (!player->skin)
298 			Skin_Find(player);
299 		if ((original = Skin_Cache(player->skin)) != NULL) {
300 			//skin data width
301 			inwidth = 320;
302 			inheight = 200;
303 		} else {
304 			original = player_8bit_texels;
305 			inwidth = 296;
306 			inheight = 194;
307 		}
308 
309 
310 		// because this happens during gameplay, do it fast
311 		// instead of sending it through gl_upload 8
312 		GL_Bind(playertextures + playernum);
313 
314 	#if 0
315 		s = 320*200;
316 		byte	translated[320*200];
317 
318 		for (i=0 ; i<s ; i+=4)
319 		{
320 			translated[i] = translate[original[i]];
321 			translated[i+1] = translate[original[i+1]];
322 			translated[i+2] = translate[original[i+2]];
323 			translated[i+3] = translate[original[i+3]];
324 		}
325 
326 
327 		// don't mipmap these, because it takes too long
328 		GL_Upload8 (translated, paliashdr->skinwidth, paliashdr->skinheight,
329 			false, false, true);
330 	#endif
331 
332 		scaled_width = gl_max_size.value < 512 ? gl_max_size.value : 512;
333 		scaled_height = gl_max_size.value < 256 ? gl_max_size.value : 256;
334 		// allow users to crunch sizes down even more if they want
335 		scaled_width >>= (int)gl_playermip.value;
336 		scaled_height >>= (int)gl_playermip.value;
337 
338 		if (VID_Is8bit()) { // 8bit texture upload
339 			byte *out2;
340 
341 			out2 = (byte *)pixels;
342 			memset(pixels, 0, sizeof(pixels));
343 			fracstep = tinwidth*0x10000/scaled_width;
344 			for (i=0 ; i< (int) scaled_height ; i++, out2 += scaled_width)
345 			{
346 				inrow = original + inwidth*(i*tinheight/scaled_height);
347 				frac = fracstep >> 1;
348 				for (j=0 ; j< (int) scaled_width ; j+=4)
349 				{
350 					out2[j] = translate[inrow[frac>>16]];
351 					frac += fracstep;
352 					out2[j+1] = translate[inrow[frac>>16]];
353 					frac += fracstep;
354 					out2[j+2] = translate[inrow[frac>>16]];
355 					frac += fracstep;
356 					out2[j+3] = translate[inrow[frac>>16]];
357 					frac += fracstep;
358 				}
359 			}
360 
361 			GL_Upload8_EXT ((byte *)pixels, scaled_width, scaled_height, false, false);
362 			return;
363 		}
364 
365 		for (i=0 ; i<256 ; i++)
366 			translate32[i] = d_8to24table[translate[i]];
367 
368 		out = pixels;
369 		memset(pixels, 0, sizeof(pixels));
370 		fracstep = tinwidth*0x10000/scaled_width;
371 		for (i=0 ; i< (int) scaled_height ; i++, out += scaled_width)
372 		{
373 			inrow = original + inwidth*(i*tinheight/scaled_height);
374 			frac = fracstep >> 1;
375 			for (j=0 ; j< (int) scaled_width ; j+=4)
376 			{
377 				out[j] = translate32[inrow[frac>>16]];
378 				frac += fracstep;
379 				out[j+1] = translate32[inrow[frac>>16]];
380 				frac += fracstep;
381 				out[j+2] = translate32[inrow[frac>>16]];
382 				frac += fracstep;
383 				out[j+3] = translate32[inrow[frac>>16]];
384 				frac += fracstep;
385 			}
386 		}
387 
388 		glTexImage2DHelper (GL_TEXTURE_2D, 0, gl_solid_format,
389 			scaled_width, scaled_height, 0, GL_RGBA,
390 			GL_UNSIGNED_BYTE, pixels);
391 
392 		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
393 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
394 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
395 	}
396 }
397 
398 /*
399 ===============
400 R_NewMap
401 ===============
402 */
R_NewMap(void)403 void R_NewMap (void)
404 {
405 	int		i;
406 
407 	for (i=0 ; i<256 ; i++)
408 		d_lightstylevalue[i] = 264;		// normal light value
409 
410 	memset (&r_worldentity, 0, sizeof(r_worldentity));
411 	r_worldentity.model = cl.worldmodel;
412 
413 // clear out efrags in case the level hasn't been reloaded
414 // FIXME: is this one short?
415 	for (i=0 ; i<cl.worldmodel->numleafs ; i++)
416 		cl.worldmodel->leafs[i].efrags = NULL;
417 
418 	r_viewleaf = NULL;
419 	R_ClearParticles ();
420 
421 	GL_BuildLightmaps ();
422 
423 	// identify sky texture
424 	skytexturenum = -1;
425 	mirrortexturenum = -1;
426 	for (i=0 ; i<cl.worldmodel->numtextures ; i++)
427 	{
428 		if (!cl.worldmodel->textures[i])
429 			continue;
430 		if (!Q_strncmp(cl.worldmodel->textures[i]->name,"sky",3) )
431 			skytexturenum = i;
432 		if (!Q_strncmp(cl.worldmodel->textures[i]->name,"window02_1",10) )
433 			mirrortexturenum = i;
434  		cl.worldmodel->textures[i]->texturechain = NULL;
435 	}
436 #ifdef QUAKE2
437 	R_LoadSkys ();
438 #endif
439 }
440 
441 
442 /*
443 ====================
444 R_TimeRefresh_f
445 
446 For program optimization
447 ====================
448 */
R_TimeRefresh_f(void)449 void R_TimeRefresh_f (void)
450 {
451 #ifdef USE_OPENGLES
452 	// Not implemented
453 	Con_Printf("TimeRefresh not implemented.\n");
454 #else
455 	int			i;
456 	float		start, stop, time;
457 
458 	glDrawBuffer  (GL_FRONT);
459 	glFinish ();
460 
461 	start = Sys_DoubleTime ();
462 	for (i=0 ; i<128 ; i++)
463 	{
464 		r_refdef.viewangles[1] = i/128.0*360.0;
465 		R_RenderView ();
466 	}
467 
468 	glFinish ();
469 	stop = Sys_DoubleTime ();
470 	time = stop-start;
471 	Con_Printf ("%f seconds (%f fps)\n", time, 128/time);
472 
473 	glDrawBuffer  (GL_BACK);
474 	GL_EndRendering ();
475 #endif
476 }
477 
D_FlushCaches(void)478 void D_FlushCaches (void)
479 {
480 }
481 
482 
483