Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 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_surf.c: surface-related refresh code
21
 
22
#include "quakedef.h"
23
 
24
int			skytexturenum;
25
 
26
#ifndef GL_RGBA4
27
#define	GL_RGBA4	0
28
#endif
29
 
30
 
31
int		lightmap_bytes;		// 1, 2, or 4
32
 
33
int		lightmap_textures;
34
 
35
unsigned		blocklights[18*18];
36
 
37
#define	BLOCK_WIDTH		128
38
#define	BLOCK_HEIGHT	128
39
 
40
#define	MAX_LIGHTMAPS	64
41
int			active_lightmaps;
42
 
43
typedef struct glRect_s {
44
	unsigned char l,t,w,h;
45
} glRect_t;
46
 
47
glpoly_t	*lightmap_polys[MAX_LIGHTMAPS];
48
qboolean	lightmap_modified[MAX_LIGHTMAPS];
49
glRect_t	lightmap_rectchange[MAX_LIGHTMAPS];
50
 
51
int			allocated[MAX_LIGHTMAPS][BLOCK_WIDTH];
52
 
53
// the lightmap texture data needs to be kept in
54
// main memory so texsubimage can update properly
55
byte		lightmaps[4*MAX_LIGHTMAPS*BLOCK_WIDTH*BLOCK_HEIGHT];
56
 
57
// For gl_texsort 0
58
msurface_t  *skychain = NULL;
59
msurface_t  *waterchain = NULL;
60
 
61
void R_RenderDynamicLightmaps (msurface_t *fa);
62
 
63
/*
64
===============
65
R_AddDynamicLights
66
===============
67
*/
68
void R_AddDynamicLights (msurface_t *surf)
69
{
70
	int			lnum;
71
	int			sd, td;
72
	float		dist, rad, minlight;
73
	vec3_t		impact, local;
74
	int			s, t;
75
	int			i;
76
	int			smax, tmax;
77
	mtexinfo_t	*tex;
78
 
79
	smax = (surf->extents[0]>>4)+1;
80
	tmax = (surf->extents[1]>>4)+1;
81
	tex = surf->texinfo;
82
 
83
	for (lnum=0 ; lnum
84
	{
85
		if ( !(surf->dlightbits & (1<
86
			continue;		// not lit by this light
87
 
88
		rad = cl_dlights[lnum].radius;
89
		dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) -
90
				surf->plane->dist;
91
		rad -= fabs(dist);
92
		minlight = cl_dlights[lnum].minlight;
93
		if (rad < minlight)
94
			continue;
95
		minlight = rad - minlight;
96
 
97
		for (i=0 ; i<3 ; i++)
98
		{
99
			impact[i] = cl_dlights[lnum].origin[i] -
100
					surf->plane->normal[i]*dist;
101
		}
102
 
103
		local[0] = DotProduct (impact, tex->vecs[0]) + tex->vecs[0][3];
104
		local[1] = DotProduct (impact, tex->vecs[1]) + tex->vecs[1][3];
105
 
106
		local[0] -= surf->texturemins[0];
107
		local[1] -= surf->texturemins[1];
108
 
109
		for (t = 0 ; t
110
		{
111
			td = local[1] - t*16;
112
			if (td < 0)
113
				td = -td;
114
			for (s=0 ; s
115
			{
116
				sd = local[0] - s*16;
117
				if (sd < 0)
118
					sd = -sd;
119
				if (sd > td)
120
					dist = sd + (td>>1);
121
				else
122
					dist = td + (sd>>1);
123
				if (dist < minlight)
124
					blocklights[t*smax + s] += (rad - dist)*256;
125
			}
126
		}
127
	}
128
}
129
 
130
 
131
/*
132
===============
133
R_BuildLightMap
134
 
135
Combine and scale multiple lightmaps into the 8.8 format in blocklights
136
===============
137
*/
138
void R_BuildLightMap (msurface_t *surf, byte *dest, int stride)
139
{
140
	int			smax, tmax;
141
	int			t;
142
	int			i, j, size;
143
	byte		*lightmap;
144
	unsigned	scale;
145
	int			maps;
146
	int			lightadj[4];
147
	unsigned	*bl;
148
 
149
	surf->cached_dlight = (surf->dlightframe == r_framecount);
150
 
151
	smax = (surf->extents[0]>>4)+1;
152
	tmax = (surf->extents[1]>>4)+1;
153
	size = smax*tmax;
154
	lightmap = surf->samples;
155
 
156
// set to full bright if no light data
157
	if (r_fullbright.value || !cl.worldmodel->lightdata)
158
	{
159
		for (i=0 ; i
160
			blocklights[i] = 255*256;
161
		goto store;
162
	}
163
 
164
// clear to no light
165
	for (i=0 ; i
166
		blocklights[i] = 0;
167
 
168
// add all the lightmaps
169
	if (lightmap)
170
		for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ;
171
			 maps++)
172
		{
173
			scale = d_lightstylevalue[surf->styles[maps]];
174
			surf->cached_light[maps] = scale;	// 8.8 fraction
175
			for (i=0 ; i
176
				blocklights[i] += lightmap[i] * scale;
177
			lightmap += size;	// skip to next lightmap
178
		}
179
 
180
// add all the dynamic lights
181
	if (surf->dlightframe == r_framecount)
182
		R_AddDynamicLights (surf);
183
 
184
// bound, invert, and shift
185
store:
186
	switch (gl_lightmap_format)
187
	{
188
	case GL_RGBA:
189
		stride -= (smax<<2);
190
		bl = blocklights;
191
		for (i=0 ; i
192
		{
193
			for (j=0 ; j
194
			{
195
				t = *bl++;
196
				t >>= 7;
197
				if (t > 255)
198
					t = 255;
199
				dest[3] = 255-t;
200
				dest += 4;
201
			}
202
		}
203
		break;
204
	case GL_ALPHA:
205
	case GL_LUMINANCE:
206
	case GL_INTENSITY:
207
		bl = blocklights;
208
		for (i=0 ; i
209
		{
210
			for (j=0 ; j
211
			{
212
				t = *bl++;
213
				t >>= 7;
214
				if (t > 255)
215
					t = 255;
216
				dest[j] = 255-t;
217
			}
218
		}
219
		break;
220
	default:
221
		Sys_Error ("Bad lightmap format");
222
	}
223
}
224
 
225
 
226
/*
227
===============
228
R_TextureAnimation
229
 
230
Returns the proper texture for a given time and base texture
231
===============
232
*/
233
texture_t *R_TextureAnimation (texture_t *base)
234
{
235
	int		reletive;
236
	int		count;
237
 
238
	if (currententity->frame)
239
	{
240
		if (base->alternate_anims)
241
			base = base->alternate_anims;
242
	}
243
 
244
	if (!base->anim_total)
245
		return base;
246
 
247
	reletive = (int)(cl.time*10) % base->anim_total;
248
 
249
	count = 0;
250
	while (base->anim_min > reletive || base->anim_max <= reletive)
251
	{
252
		base = base->anim_next;
253
		if (!base)
254
			Sys_Error ("R_TextureAnimation: broken cycle");
255
		if (++count > 100)
256
			Sys_Error ("R_TextureAnimation: infinite cycle");
257
	}
258
 
259
	return base;
260
}
261
 
262
 
263
/*
264
=============================================================
265
 
266
	BRUSH MODELS
267
 
268
=============================================================
269
*/
270
 
271
 
272
extern	int		solidskytexture;
273
extern	int		alphaskytexture;
274
extern	float	speedscale;		// for top sky and bottom sky
275
 
276
void DrawGLWaterPoly (glpoly_t *p);
277
void DrawGLWaterPolyLightmap (glpoly_t *p);
278
 
279
lpMTexFUNC qglMTexCoord2fSGIS = NULL;
280
lpSelTexFUNC qglSelectTextureSGIS = NULL;
281
 
282
qboolean mtexenabled = false;
283
 
284
void GL_SelectTexture (GLenum target);
285
 
286
void GL_DisableMultitexture(void)
287
{
288
	if (mtexenabled) {
289
		glDisable(GL_TEXTURE_2D);
290
		GL_SelectTexture(TEXTURE0_SGIS);
291
		mtexenabled = false;
292
	}
293
}
294
 
295
void GL_EnableMultitexture(void)
296
{
297
	if (gl_mtexable) {
298
		GL_SelectTexture(TEXTURE1_SGIS);
299
		glEnable(GL_TEXTURE_2D);
300
		mtexenabled = true;
301
	}
302
}
303
 
304
#if 0
305
/*
306
================
307
R_DrawSequentialPoly
308
 
309
Systems that have fast state and texture changes can
310
just do everything as it passes with no need to sort
311
================
312
*/
313
void R_DrawSequentialPoly (msurface_t *s)
314
{
315
	glpoly_t	*p;
316
	float		*v;
317
	int			i;
318
	texture_t	*t;
319
 
320
	//
321
	// normal lightmaped poly
322
	//
323
	if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) )
324
	{
325
		p = s->polys;
326
 
327
		t = R_TextureAnimation (s->texinfo->texture);
328
		GL_Bind (t->gl_texturenum);
329
		glBegin (GL_POLYGON);
330
		v = p->verts[0];
331
		for (i=0 ; inumverts ; i++, v+= VERTEXSIZE)
332
		{
333
			glTexCoord2f (v[3], v[4]);
334
			glVertex3fv (v);
335
		}
336
		glEnd ();
337
 
338
		GL_Bind (lightmap_textures + s->lightmaptexturenum);
339
		glEnable (GL_BLEND);
340
		glBegin (GL_POLYGON);
341
		v = p->verts[0];
342
		for (i=0 ; inumverts ; i++, v+= VERTEXSIZE)
343
		{
344
			glTexCoord2f (v[5], v[6]);
345
			glVertex3fv (v);
346
		}
347
		glEnd ();
348
 
349
		glDisable (GL_BLEND);
350
 
351
		return;
352
	}
353
 
354
	//
355
	// subdivided water surface warp
356
	//
357
	if (s->flags & SURF_DRAWTURB)
358
	{
359
		GL_Bind (s->texinfo->texture->gl_texturenum);
360
		EmitWaterPolys (s);
361
		return;
362
	}
363
 
364
	//
365
	// subdivided sky warp
366
	//
367
	if (s->flags & SURF_DRAWSKY)
368
	{
369
		GL_Bind (solidskytexture);
370
		speedscale = realtime*8;
371
		speedscale -= (int)speedscale;
372
 
373
		EmitSkyPolys (s);
374
 
375
		glEnable (GL_BLEND);
376
		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
377
		GL_Bind (alphaskytexture);
378
		speedscale = realtime*16;
379
		speedscale -= (int)speedscale;
380
		EmitSkyPolys (s);
381
		if (gl_lightmap_format == GL_LUMINANCE)
382
			glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
383
 
384
		glDisable (GL_BLEND);
385
	}
386
 
387
	//
388
	// underwater warped with lightmap
389
	//
390
	p = s->polys;
391
 
392
	t = R_TextureAnimation (s->texinfo->texture);
393
	GL_Bind (t->gl_texturenum);
394
	DrawGLWaterPoly (p);
395
 
396
	GL_Bind (lightmap_textures + s->lightmaptexturenum);
397
	glEnable (GL_BLEND);
398
	DrawGLWaterPolyLightmap (p);
399
	glDisable (GL_BLEND);
400
}
401
#else
402
/*
403
================
404
R_DrawSequentialPoly
405
 
406
Systems that have fast state and texture changes can
407
just do everything as it passes with no need to sort
408
================
409
*/
410
void R_DrawSequentialPoly (msurface_t *s)
411
{
412
	glpoly_t	*p;
413
	float		*v;
414
	int			i;
415
	texture_t	*t;
416
	vec3_t		nv, dir;
417
	float		ss, ss2, length;
418
	float		s1, t1;
419
	glRect_t	*theRect;
420
 
421
	//
422
	// normal lightmaped poly
423
	//
424
 
425
	if (! (s->flags & (SURF_DRAWSKY|SURF_DRAWTURB|SURF_UNDERWATER) ) )
426
	{
427
		R_RenderDynamicLightmaps (s);
428
		if (gl_mtexable) {
429
			p = s->polys;
430
 
431
			t = R_TextureAnimation (s->texinfo->texture);
432
			// Binds world to texture env 0
433
			GL_SelectTexture(TEXTURE0_SGIS);
434
			GL_Bind (t->gl_texturenum);
435
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
436
			// Binds lightmap to texenv 1
437
			GL_EnableMultitexture(); // Same as SelectTexture (TEXTURE1)
438
			GL_Bind (lightmap_textures + s->lightmaptexturenum);
439
			i = s->lightmaptexturenum;
440
			if (lightmap_modified[i])
441
			{
442
				lightmap_modified[i] = false;
443
				theRect = &lightmap_rectchange[i];
444
				glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t,
445
					BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
446
					lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
447
				theRect->l = BLOCK_WIDTH;
448
				theRect->t = BLOCK_HEIGHT;
449
				theRect->h = 0;
450
				theRect->w = 0;
451
			}
452
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
453
			glBegin(GL_POLYGON);
454
			v = p->verts[0];
455
			for (i=0 ; inumverts ; i++, v+= VERTEXSIZE)
456
			{
457
				qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]);
458
				qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]);
459
				glVertex3fv (v);
460
			}
461
			glEnd ();
462
			return;
463
		} else {
464
			p = s->polys;
465
 
466
			t = R_TextureAnimation (s->texinfo->texture);
467
			GL_Bind (t->gl_texturenum);
468
			glBegin (GL_POLYGON);
469
			v = p->verts[0];
470
			for (i=0 ; inumverts ; i++, v+= VERTEXSIZE)
471
			{
472
				glTexCoord2f (v[3], v[4]);
473
				glVertex3fv (v);
474
			}
475
			glEnd ();
476
 
477
			GL_Bind (lightmap_textures + s->lightmaptexturenum);
478
			glEnable (GL_BLEND);
479
			glBegin (GL_POLYGON);
480
			v = p->verts[0];
481
			for (i=0 ; inumverts ; i++, v+= VERTEXSIZE)
482
			{
483
				glTexCoord2f (v[5], v[6]);
484
				glVertex3fv (v);
485
			}
486
			glEnd ();
487
 
488
			glDisable (GL_BLEND);
489
		}
490
 
491
		return;
492
	}
493
 
494
	//
495
	// subdivided water surface warp
496
	//
497
 
498
	if (s->flags & SURF_DRAWTURB)
499
	{
500
		GL_DisableMultitexture();
501
		GL_Bind (s->texinfo->texture->gl_texturenum);
502
		EmitWaterPolys (s);
503
		return;
504
	}
505
 
506
	//
507
	// subdivided sky warp
508
	//
509
	if (s->flags & SURF_DRAWSKY)
510
	{
511
		GL_DisableMultitexture();
512
		GL_Bind (solidskytexture);
513
		speedscale = realtime*8;
514
		speedscale -= (int)speedscale & ~127;
515
 
516
		EmitSkyPolys (s);
517
 
518
		glEnable (GL_BLEND);
519
		GL_Bind (alphaskytexture);
520
		speedscale = realtime*16;
521
		speedscale -= (int)speedscale & ~127;
522
		EmitSkyPolys (s);
523
 
524
		glDisable (GL_BLEND);
525
		return;
526
	}
527
 
528
	//
529
	// underwater warped with lightmap
530
	//
531
	R_RenderDynamicLightmaps (s);
532
	if (gl_mtexable) {
533
		p = s->polys;
534
 
535
		t = R_TextureAnimation (s->texinfo->texture);
536
		GL_SelectTexture(TEXTURE0_SGIS);
537
		GL_Bind (t->gl_texturenum);
538
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
539
		GL_EnableMultitexture();
540
		GL_Bind (lightmap_textures + s->lightmaptexturenum);
541
		i = s->lightmaptexturenum;
542
		if (lightmap_modified[i])
543
		{
544
			lightmap_modified[i] = false;
545
			theRect = &lightmap_rectchange[i];
546
			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t,
547
				BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
548
				lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
549
			theRect->l = BLOCK_WIDTH;
550
			theRect->t = BLOCK_HEIGHT;
551
			theRect->h = 0;
552
			theRect->w = 0;
553
		}
554
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
555
		glBegin (GL_TRIANGLE_FAN);
556
		v = p->verts[0];
557
		for (i=0 ; inumverts ; i++, v+= VERTEXSIZE)
558
		{
559
			qglMTexCoord2fSGIS (TEXTURE0_SGIS, v[3], v[4]);
560
			qglMTexCoord2fSGIS (TEXTURE1_SGIS, v[5], v[6]);
561
 
562
			nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
563
			nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
564
			nv[2] = v[2];
565
 
566
			glVertex3fv (nv);
567
		}
568
		glEnd ();
569
 
570
	} else {
571
		p = s->polys;
572
 
573
		t = R_TextureAnimation (s->texinfo->texture);
574
		GL_Bind (t->gl_texturenum);
575
		DrawGLWaterPoly (p);
576
 
577
		GL_Bind (lightmap_textures + s->lightmaptexturenum);
578
		glEnable (GL_BLEND);
579
		DrawGLWaterPolyLightmap (p);
580
		glDisable (GL_BLEND);
581
	}
582
}
583
#endif
584
 
585
 
586
/*
587
================
588
DrawGLWaterPoly
589
 
590
Warp the vertex coordinates
591
================
592
*/
593
void DrawGLWaterPoly (glpoly_t *p)
594
{
595
	int		i;
596
	float	*v;
597
	float	s, t, os, ot;
598
	vec3_t	nv;
599
 
600
	GL_DisableMultitexture();
601
 
602
	glBegin (GL_TRIANGLE_FAN);
603
	v = p->verts[0];
604
	for (i=0 ; inumverts ; i++, v+= VERTEXSIZE)
605
	{
606
		glTexCoord2f (v[3], v[4]);
607
 
608
		nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
609
		nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
610
		nv[2] = v[2];
611
 
612
		glVertex3fv (nv);
613
	}
614
	glEnd ();
615
}
616
 
617
void DrawGLWaterPolyLightmap (glpoly_t *p)
618
{
619
	int		i;
620
	float	*v;
621
	float	s, t, os, ot;
622
	vec3_t	nv;
623
 
624
	GL_DisableMultitexture();
625
 
626
	glBegin (GL_TRIANGLE_FAN);
627
	v = p->verts[0];
628
	for (i=0 ; inumverts ; i++, v+= VERTEXSIZE)
629
	{
630
		glTexCoord2f (v[5], v[6]);
631
 
632
		nv[0] = v[0] + 8*sin(v[1]*0.05+realtime)*sin(v[2]*0.05+realtime);
633
		nv[1] = v[1] + 8*sin(v[0]*0.05+realtime)*sin(v[2]*0.05+realtime);
634
		nv[2] = v[2];
635
 
636
		glVertex3fv (nv);
637
	}
638
	glEnd ();
639
}
640
 
641
/*
642
================
643
DrawGLPoly
644
================
645
*/
646
void DrawGLPoly (glpoly_t *p)
647
{
648
	int		i;
649
	float	*v;
650
 
651
	glBegin (GL_POLYGON);
652
	v = p->verts[0];
653
	for (i=0 ; inumverts ; i++, v+= VERTEXSIZE)
654
	{
655
		glTexCoord2f (v[3], v[4]);
656
		glVertex3fv (v);
657
	}
658
	glEnd ();
659
}
660
 
661
 
662
/*
663
================
664
R_BlendLightmaps
665
================
666
*/
667
void R_BlendLightmaps (void)
668
{
669
	int			i, j;
670
	glpoly_t	*p;
671
	float		*v;
672
	glRect_t	*theRect;
673
 
674
	if (r_fullbright.value)
675
		return;
676
	if (!gl_texsort.value)
677
		return;
678
 
679
	glDepthMask (0);		// don't bother writing Z
680
 
681
	if (gl_lightmap_format == GL_LUMINANCE)
682
		glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
683
	else if (gl_lightmap_format == GL_INTENSITY)
684
	{
685
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
686
		glColor4f (0,0,0,1);
687
		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
688
	}
689
 
690
	if (!r_lightmap.value)
691
	{
692
		glEnable (GL_BLEND);
693
	}
694
 
695
	for (i=0 ; i
696
	{
697
		p = lightmap_polys[i];
698
		if (!p)
699
			continue;
700
		GL_Bind(lightmap_textures+i);
701
		if (lightmap_modified[i])
702
		{
703
			lightmap_modified[i] = false;
704
			theRect = &lightmap_rectchange[i];
705
//			glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
706
//			, BLOCK_WIDTH, BLOCK_HEIGHT, 0,
707
//			gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes);
708
//			glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
709
//				, BLOCK_WIDTH, theRect->h, 0,
710
//				gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+(i*BLOCK_HEIGHT+theRect->t)*BLOCK_WIDTH*lightmap_bytes);
711
			glTexSubImage2D(GL_TEXTURE_2D, 0, 0, theRect->t,
712
				BLOCK_WIDTH, theRect->h, gl_lightmap_format, GL_UNSIGNED_BYTE,
713
				lightmaps+(i* BLOCK_HEIGHT + theRect->t) *BLOCK_WIDTH*lightmap_bytes);
714
			theRect->l = BLOCK_WIDTH;
715
			theRect->t = BLOCK_HEIGHT;
716
			theRect->h = 0;
717
			theRect->w = 0;
718
		}
719
		for ( ; p ; p=p->chain)
720
		{
721
			if (p->flags & SURF_UNDERWATER)
722
				DrawGLWaterPolyLightmap (p);
723
			else
724
			{
725
				glBegin (GL_POLYGON);
726
				v = p->verts[0];
727
				for (j=0 ; jnumverts ; j++, v+= VERTEXSIZE)
728
				{
729
					glTexCoord2f (v[5], v[6]);
730
					glVertex3fv (v);
731
				}
732
				glEnd ();
733
			}
734
		}
735
	}
736
 
737
	glDisable (GL_BLEND);
738
	if (gl_lightmap_format == GL_LUMINANCE)
739
		glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
740
	else if (gl_lightmap_format == GL_INTENSITY)
741
	{
742
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
743
		glColor4f (1,1,1,1);
744
	}
745
 
746
	glDepthMask (1);		// back to normal Z buffering
747
}
748
 
749
/*
750
================
751
R_RenderBrushPoly
752
================
753
*/
754
void R_RenderBrushPoly (msurface_t *fa)
755
{
756
	texture_t	*t;
757
	byte		*base;
758
	int			maps;
759
	glRect_t    *theRect;
760
	int smax, tmax;
761
 
762
	c_brush_polys++;
763
 
764
	if (fa->flags & SURF_DRAWSKY)
765
	{	// warp texture, no lightmaps
766
		EmitBothSkyLayers (fa);
767
		return;
768
	}
769
 
770
	t = R_TextureAnimation (fa->texinfo->texture);
771
	GL_Bind (t->gl_texturenum);
772
 
773
	if (fa->flags & SURF_DRAWTURB)
774
	{	// warp texture, no lightmaps
775
		EmitWaterPolys (fa);
776
		return;
777
	}
778
 
779
	if (fa->flags & SURF_UNDERWATER)
780
		DrawGLWaterPoly (fa->polys);
781
	else
782
		DrawGLPoly (fa->polys);
783
 
784
	// add the poly to the proper lightmap chain
785
 
786
	fa->polys->chain = lightmap_polys[fa->lightmaptexturenum];
787
	lightmap_polys[fa->lightmaptexturenum] = fa->polys;
788
 
789
	// check for lightmap modification
790
	for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ;
791
		 maps++)
792
		if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps])
793
			goto dynamic;
794
 
795
	if (fa->dlightframe == r_framecount	// dynamic this frame
796
		|| fa->cached_dlight)			// dynamic previously
797
	{
798
dynamic:
799
		if (r_dynamic.value)
800
		{
801
			lightmap_modified[fa->lightmaptexturenum] = true;
802
			theRect = &lightmap_rectchange[fa->lightmaptexturenum];
803
			if (fa->light_t < theRect->t) {
804
				if (theRect->h)
805
					theRect->h += theRect->t - fa->light_t;
806
				theRect->t = fa->light_t;
807
			}
808
			if (fa->light_s < theRect->l) {
809
				if (theRect->w)
810
					theRect->w += theRect->l - fa->light_s;
811
				theRect->l = fa->light_s;
812
			}
813
			smax = (fa->extents[0]>>4)+1;
814
			tmax = (fa->extents[1]>>4)+1;
815
			if ((theRect->w + theRect->l) < (fa->light_s + smax))
816
				theRect->w = (fa->light_s-theRect->l)+smax;
817
			if ((theRect->h + theRect->t) < (fa->light_t + tmax))
818
				theRect->h = (fa->light_t-theRect->t)+tmax;
819
			base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
820
			base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes;
821
			R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes);
822
		}
823
	}
824
}
825
 
826
/*
827
================
828
R_RenderDynamicLightmaps
829
Multitexture
830
================
831
*/
832
void R_RenderDynamicLightmaps (msurface_t *fa)
833
{
834
	texture_t	*t;
835
	byte		*base;
836
	int			maps;
837
	glRect_t    *theRect;
838
	int smax, tmax;
839
 
840
	c_brush_polys++;
841
 
842
	if (fa->flags & ( SURF_DRAWSKY | SURF_DRAWTURB) )
843
		return;
844
 
845
	fa->polys->chain = lightmap_polys[fa->lightmaptexturenum];
846
	lightmap_polys[fa->lightmaptexturenum] = fa->polys;
847
 
848
	// check for lightmap modification
849
	for (maps = 0 ; maps < MAXLIGHTMAPS && fa->styles[maps] != 255 ;
850
		 maps++)
851
		if (d_lightstylevalue[fa->styles[maps]] != fa->cached_light[maps])
852
			goto dynamic;
853
 
854
	if (fa->dlightframe == r_framecount	// dynamic this frame
855
		|| fa->cached_dlight)			// dynamic previously
856
	{
857
dynamic:
858
		if (r_dynamic.value)
859
		{
860
			lightmap_modified[fa->lightmaptexturenum] = true;
861
			theRect = &lightmap_rectchange[fa->lightmaptexturenum];
862
			if (fa->light_t < theRect->t) {
863
				if (theRect->h)
864
					theRect->h += theRect->t - fa->light_t;
865
				theRect->t = fa->light_t;
866
			}
867
			if (fa->light_s < theRect->l) {
868
				if (theRect->w)
869
					theRect->w += theRect->l - fa->light_s;
870
				theRect->l = fa->light_s;
871
			}
872
			smax = (fa->extents[0]>>4)+1;
873
			tmax = (fa->extents[1]>>4)+1;
874
			if ((theRect->w + theRect->l) < (fa->light_s + smax))
875
				theRect->w = (fa->light_s-theRect->l)+smax;
876
			if ((theRect->h + theRect->t) < (fa->light_t + tmax))
877
				theRect->h = (fa->light_t-theRect->t)+tmax;
878
			base = lightmaps + fa->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
879
			base += fa->light_t * BLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes;
880
			R_BuildLightMap (fa, base, BLOCK_WIDTH*lightmap_bytes);
881
		}
882
	}
883
}
884
 
885
/*
886
================
887
R_MirrorChain
888
================
889
*/
890
void R_MirrorChain (msurface_t *s)
891
{
892
	if (mirror)
893
		return;
894
	mirror = true;
895
	mirror_plane = s->plane;
896
}
897
 
898
 
899
#if 0
900
/*
901
================
902
R_DrawWaterSurfaces
903
================
904
*/
905
void R_DrawWaterSurfaces (void)
906
{
907
	int			i;
908
	msurface_t	*s;
909
	texture_t	*t;
910
 
911
	if (r_wateralpha.value == 1.0)
912
		return;
913
 
914
	//
915
	// go back to the world matrix
916
	//
917
    glLoadMatrixf (r_world_matrix);
918
 
919
	glEnable (GL_BLEND);
920
	glColor4f (1,1,1,r_wateralpha.value);
921
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
922
 
923
	for (i=0 ; inumtextures ; i++)
924
	{
925
		t = cl.worldmodel->textures[i];
926
		if (!t)
927
			continue;
928
		s = t->texturechain;
929
		if (!s)
930
			continue;
931
		if ( !(s->flags & SURF_DRAWTURB) )
932
			continue;
933
 
934
		// set modulate mode explicitly
935
		GL_Bind (t->gl_texturenum);
936
 
937
		for ( ; s ; s=s->texturechain)
938
			R_RenderBrushPoly (s);
939
 
940
		t->texturechain = NULL;
941
	}
942
 
943
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
944
 
945
	glColor4f (1,1,1,1);
946
	glDisable (GL_BLEND);
947
}
948
#else
949
/*
950
================
951
R_DrawWaterSurfaces
952
================
953
*/
954
void R_DrawWaterSurfaces (void)
955
{
956
	int			i;
957
	msurface_t	*s;
958
	texture_t	*t;
959
 
960
	if (r_wateralpha.value == 1.0 && gl_texsort.value)
961
		return;
962
 
963
	//
964
	// go back to the world matrix
965
	//
966
 
967
    glLoadMatrixf (r_world_matrix);
968
 
969
	if (r_wateralpha.value < 1.0) {
970
		glEnable (GL_BLEND);
971
		glColor4f (1,1,1,r_wateralpha.value);
972
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
973
	}
974
 
975
	if (!gl_texsort.value) {
976
		if (!waterchain)
977
			return;
978
 
979
		for ( s = waterchain ; s ; s=s->texturechain) {
980
			GL_Bind (s->texinfo->texture->gl_texturenum);
981
			EmitWaterPolys (s);
982
		}
983
 
984
		waterchain = NULL;
985
	} else {
986
 
987
		for (i=0 ; inumtextures ; i++)
988
		{
989
			t = cl.worldmodel->textures[i];
990
			if (!t)
991
				continue;
992
			s = t->texturechain;
993
			if (!s)
994
				continue;
995
			if ( !(s->flags & SURF_DRAWTURB ) )
996
				continue;
997
 
998
			// set modulate mode explicitly
999
 
1000
			GL_Bind (t->gl_texturenum);
1001
 
1002
			for ( ; s ; s=s->texturechain)
1003
				EmitWaterPolys (s);
1004
 
1005
			t->texturechain = NULL;
1006
		}
1007
 
1008
	}
1009
 
1010
	if (r_wateralpha.value < 1.0) {
1011
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1012
 
1013
		glColor4f (1,1,1,1);
1014
		glDisable (GL_BLEND);
1015
	}
1016
 
1017
}
1018
 
1019
#endif
1020
 
1021
/*
1022
================
1023
DrawTextureChains
1024
================
1025
*/
1026
void DrawTextureChains (void)
1027
{
1028
	int		i;
1029
	msurface_t	*s;
1030
	texture_t	*t;
1031
 
1032
	if (!gl_texsort.value) {
1033
		GL_DisableMultitexture();
1034
 
1035
		if (skychain) {
1036
			R_DrawSkyChain(skychain);
1037
			skychain = NULL;
1038
		}
1039
 
1040
		return;
1041
	}
1042
 
1043
	for (i=0 ; inumtextures ; i++)
1044
	{
1045
		t = cl.worldmodel->textures[i];
1046
		if (!t)
1047
			continue;
1048
		s = t->texturechain;
1049
		if (!s)
1050
			continue;
1051
		if (i == skytexturenum)
1052
			R_DrawSkyChain (s);
1053
		else if (i == mirrortexturenum && r_mirroralpha.value != 1.0)
1054
		{
1055
			R_MirrorChain (s);
1056
			continue;
1057
		}
1058
		else
1059
		{
1060
			if ((s->flags & SURF_DRAWTURB) && r_wateralpha.value != 1.0)
1061
				continue;	// draw translucent water later
1062
			for ( ; s ; s=s->texturechain)
1063
				R_RenderBrushPoly (s);
1064
		}
1065
 
1066
		t->texturechain = NULL;
1067
	}
1068
}
1069
 
1070
/*
1071
=================
1072
R_DrawBrushModel
1073
=================
1074
*/
1075
void R_DrawBrushModel (entity_t *e)
1076
{
1077
	int			j, k;
1078
	vec3_t		mins, maxs;
1079
	int			i, numsurfaces;
1080
	msurface_t	*psurf;
1081
	float		dot;
1082
	mplane_t	*pplane;
1083
	model_t		*clmodel;
1084
	qboolean	rotated;
1085
 
1086
	currententity = e;
1087
	currenttexture = -1;
1088
 
1089
	clmodel = e->model;
1090
 
1091
	if (e->angles[0] || e->angles[1] || e->angles[2])
1092
	{
1093
		rotated = true;
1094
		for (i=0 ; i<3 ; i++)
1095
		{
1096
			mins[i] = e->origin[i] - clmodel->radius;
1097
			maxs[i] = e->origin[i] + clmodel->radius;
1098
		}
1099
	}
1100
	else
1101
	{
1102
		rotated = false;
1103
		VectorAdd (e->origin, clmodel->mins, mins);
1104
		VectorAdd (e->origin, clmodel->maxs, maxs);
1105
	}
1106
 
1107
	if (R_CullBox (mins, maxs))
1108
		return;
1109
 
1110
	glColor3f (1,1,1);
1111
	memset (lightmap_polys, 0, sizeof(lightmap_polys));
1112
 
1113
	VectorSubtract (r_refdef.vieworg, e->origin, modelorg);
1114
	if (rotated)
1115
	{
1116
		vec3_t	temp;
1117
		vec3_t	forward, right, up;
1118
 
1119
		VectorCopy (modelorg, temp);
1120
		AngleVectors (e->angles, forward, right, up);
1121
		modelorg[0] = DotProduct (temp, forward);
1122
		modelorg[1] = -DotProduct (temp, right);
1123
		modelorg[2] = DotProduct (temp, up);
1124
	}
1125
 
1126
	psurf = &clmodel->surfaces[clmodel->firstmodelsurface];
1127
 
1128
// calculate dynamic lighting for bmodel if it's not an
1129
// instanced model
1130
	if (clmodel->firstmodelsurface != 0 && !gl_flashblend.value)
1131
	{
1132
		for (k=0 ; k
1133
		{
1134
			if ((cl_dlights[k].die < cl.time) ||
1135
				(!cl_dlights[k].radius))
1136
				continue;
1137
 
1138
			R_MarkLights (&cl_dlights[k], 1<
1139
				clmodel->nodes + clmodel->hulls[0].firstclipnode);
1140
		}
1141
	}
1142
 
1143
    glPushMatrix ();
1144
e->angles[0] = -e->angles[0];	// stupid quake bug
1145
	R_RotateForEntity (e);
1146
e->angles[0] = -e->angles[0];	// stupid quake bug
1147
 
1148
	//
1149
	// draw texture
1150
	//
1151
	for (i=0 ; inummodelsurfaces ; i++, psurf++)
1152
	{
1153
	// find which side of the node we are on
1154
		pplane = psurf->plane;
1155
 
1156
		dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
1157
 
1158
	// draw the polygon
1159
		if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
1160
			(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
1161
		{
1162
			if (gl_texsort.value)
1163
				R_RenderBrushPoly (psurf);
1164
			else
1165
				R_DrawSequentialPoly (psurf);
1166
		}
1167
	}
1168
 
1169
	R_BlendLightmaps ();
1170
 
1171
	glPopMatrix ();
1172
}
1173
 
1174
/*
1175
=============================================================
1176
 
1177
	WORLD MODEL
1178
 
1179
=============================================================
1180
*/
1181
 
1182
/*
1183
================
1184
R_RecursiveWorldNode
1185
================
1186
*/
1187
void R_RecursiveWorldNode (mnode_t *node)
1188
{
1189
	int			i, c, side, *pindex;
1190
	vec3_t		acceptpt, rejectpt;
1191
	mplane_t	*plane;
1192
	msurface_t	*surf, **mark;
1193
	mleaf_t		*pleaf;
1194
	double		d, dot;
1195
	vec3_t		mins, maxs;
1196
 
1197
	if (node->contents == CONTENTS_SOLID)
1198
		return;		// solid
1199
 
1200
	if (node->visframe != r_visframecount)
1201
		return;
1202
	if (R_CullBox (node->minmaxs, node->minmaxs+3))
1203
		return;
1204
 
1205
// if a leaf node, draw stuff
1206
	if (node->contents < 0)
1207
	{
1208
		pleaf = (mleaf_t *)node;
1209
 
1210
		mark = pleaf->firstmarksurface;
1211
		c = pleaf->nummarksurfaces;
1212
 
1213
		if (c)
1214
		{
1215
			do
1216
			{
1217
				(*mark)->visframe = r_framecount;
1218
				mark++;
1219
			} while (--c);
1220
		}
1221
 
1222
	// deal with model fragments in this leaf
1223
		if (pleaf->efrags)
1224
			R_StoreEfrags (&pleaf->efrags);
1225
 
1226
		return;
1227
	}
1228
 
1229
// node is just a decision point, so go down the apropriate sides
1230
 
1231
// find which side of the node we are on
1232
	plane = node->plane;
1233
 
1234
	switch (plane->type)
1235
	{
1236
	case PLANE_X:
1237
		dot = modelorg[0] - plane->dist;
1238
		break;
1239
	case PLANE_Y:
1240
		dot = modelorg[1] - plane->dist;
1241
		break;
1242
	case PLANE_Z:
1243
		dot = modelorg[2] - plane->dist;
1244
		break;
1245
	default:
1246
		dot = DotProduct (modelorg, plane->normal) - plane->dist;
1247
		break;
1248
	}
1249
 
1250
	if (dot >= 0)
1251
		side = 0;
1252
	else
1253
		side = 1;
1254
 
1255
// recurse down the children, front side first
1256
	R_RecursiveWorldNode (node->children[side]);
1257
 
1258
// draw stuff
1259
	c = node->numsurfaces;
1260
 
1261
	if (c)
1262
	{
1263
		surf = cl.worldmodel->surfaces + node->firstsurface;
1264
 
1265
		if (dot < 0 -BACKFACE_EPSILON)
1266
			side = SURF_PLANEBACK;
1267
		else if (dot > BACKFACE_EPSILON)
1268
			side = 0;
1269
		{
1270
			for ( ; c ; c--, surf++)
1271
			{
1272
				if (surf->visframe != r_framecount)
1273
					continue;
1274
 
1275
				// don't backface underwater surfaces, because they warp
1276
				if ( !(surf->flags & SURF_UNDERWATER) && ( (dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) )
1277
					continue;		// wrong side
1278
 
1279
				// if sorting by texture, just store it out
1280
				if (gl_texsort.value)
1281
				{
1282
					if (!mirror
1283
					|| surf->texinfo->texture != cl.worldmodel->textures[mirrortexturenum])
1284
					{
1285
						surf->texturechain = surf->texinfo->texture->texturechain;
1286
						surf->texinfo->texture->texturechain = surf;
1287
					}
1288
				} else if (surf->flags & SURF_DRAWSKY) {
1289
					surf->texturechain = skychain;
1290
					skychain = surf;
1291
				} else if (surf->flags & SURF_DRAWTURB) {
1292
					surf->texturechain = waterchain;
1293
					waterchain = surf;
1294
				} else
1295
					R_DrawSequentialPoly (surf);
1296
 
1297
			}
1298
		}
1299
 
1300
	}
1301
 
1302
// recurse down the back side
1303
	R_RecursiveWorldNode (node->children[!side]);
1304
}
1305
 
1306
 
1307
 
1308
/*
1309
=============
1310
R_DrawWorld
1311
=============
1312
*/
1313
void R_DrawWorld (void)
1314
{
1315
	entity_t	ent;
1316
	int			i;
1317
 
1318
	memset (&ent, 0, sizeof(ent));
1319
	ent.model = cl.worldmodel;
1320
 
1321
	VectorCopy (r_refdef.vieworg, modelorg);
1322
 
1323
	currententity = &ent;
1324
	currenttexture = -1;
1325
 
1326
	glColor3f (1,1,1);
1327
	memset (lightmap_polys, 0, sizeof(lightmap_polys));
1328
#ifdef QUAKE2
1329
	R_ClearSkyBox ();
1330
#endif
1331
 
1332
	R_RecursiveWorldNode (cl.worldmodel->nodes);
1333
 
1334
	DrawTextureChains ();
1335
 
1336
	R_BlendLightmaps ();
1337
 
1338
#ifdef QUAKE2
1339
	R_DrawSkyBox ();
1340
#endif
1341
}
1342
 
1343
 
1344
/*
1345
===============
1346
R_MarkLeaves
1347
===============
1348
*/
1349
void R_MarkLeaves (void)
1350
{
1351
	byte	*vis;
1352
	mnode_t	*node;
1353
	int		i;
1354
	byte	solid[4096];
1355
 
1356
	if (r_oldviewleaf == r_viewleaf && !r_novis.value)
1357
		return;
1358
 
1359
	if (mirror)
1360
		return;
1361
 
1362
	r_visframecount++;
1363
	r_oldviewleaf = r_viewleaf;
1364
 
1365
	if (r_novis.value)
1366
	{
1367
		vis = solid;
1368
		memset (solid, 0xff, (cl.worldmodel->numleafs+7)>>3);
1369
	}
1370
	else
1371
		vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel);
1372
 
1373
	for (i=0 ; inumleafs ; i++)
1374
	{
1375
		if (vis[i>>3] & (1<<(i&7)))
1376
		{
1377
			node = (mnode_t *)&cl.worldmodel->leafs[i+1];
1378
			do
1379
			{
1380
				if (node->visframe == r_visframecount)
1381
					break;
1382
				node->visframe = r_visframecount;
1383
				node = node->parent;
1384
			} while (node);
1385
		}
1386
	}
1387
}
1388
 
1389
 
1390
 
1391
/*
1392
=============================================================================
1393
 
1394
  LIGHTMAP ALLOCATION
1395
 
1396
=============================================================================
1397
*/
1398
 
1399
// returns a texture number and the position inside it
1400
int AllocBlock (int w, int h, int *x, int *y)
1401
{
1402
	int		i, j;
1403
	int		best, best2;
1404
	int		bestx;
1405
	int		texnum;
1406
 
1407
	for (texnum=0 ; texnum
1408
	{
1409
		best = BLOCK_HEIGHT;
1410
 
1411
		for (i=0 ; i
1412
		{
1413
			best2 = 0;
1414
 
1415
			for (j=0 ; j
1416
			{
1417
				if (allocated[texnum][i+j] >= best)
1418
					break;
1419
				if (allocated[texnum][i+j] > best2)
1420
					best2 = allocated[texnum][i+j];
1421
			}
1422
			if (j == w)
1423
			{	// this is a valid spot
1424
				*x = i;
1425
				*y = best = best2;
1426
			}
1427
		}
1428
 
1429
		if (best + h > BLOCK_HEIGHT)
1430
			continue;
1431
 
1432
		for (i=0 ; i
1433
			allocated[texnum][*x + i] = best + h;
1434
 
1435
		return texnum;
1436
	}
1437
 
1438
	Sys_Error ("AllocBlock: full");
1439
}
1440
 
1441
 
1442
mvertex_t	*r_pcurrentvertbase;
1443
model_t		*currentmodel;
1444
 
1445
int	nColinElim;
1446
 
1447
/*
1448
================
1449
BuildSurfaceDisplayList
1450
================
1451
*/
1452
void BuildSurfaceDisplayList (msurface_t *fa)
1453
{
1454
	int			i, lindex, lnumverts, s_axis, t_axis;
1455
	float		dist, lastdist, lzi, scale, u, v, frac;
1456
	unsigned	mask;
1457
	vec3_t		local, transformed;
1458
	medge_t		*pedges, *r_pedge;
1459
	mplane_t	*pplane;
1460
	int			vertpage, newverts, newpage, lastvert;
1461
	qboolean	visible;
1462
	float		*vec;
1463
	float		s, t;
1464
	glpoly_t	*poly;
1465
 
1466
// reconstruct the polygon
1467
	pedges = currentmodel->edges;
1468
	lnumverts = fa->numedges;
1469
	vertpage = 0;
1470
 
1471
	//
1472
	// draw texture
1473
	//
1474
	poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float));
1475
	poly->next = fa->polys;
1476
	poly->flags = fa->flags;
1477
	fa->polys = poly;
1478
	poly->numverts = lnumverts;
1479
 
1480
	for (i=0 ; i
1481
	{
1482
		lindex = currentmodel->surfedges[fa->firstedge + i];
1483
 
1484
		if (lindex > 0)
1485
		{
1486
			r_pedge = &pedges[lindex];
1487
			vec = r_pcurrentvertbase[r_pedge->v[0]].position;
1488
		}
1489
		else
1490
		{
1491
			r_pedge = &pedges[-lindex];
1492
			vec = r_pcurrentvertbase[r_pedge->v[1]].position;
1493
		}
1494
		s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
1495
		s /= fa->texinfo->texture->width;
1496
 
1497
		t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
1498
		t /= fa->texinfo->texture->height;
1499
 
1500
		VectorCopy (vec, poly->verts[i]);
1501
		poly->verts[i][3] = s;
1502
		poly->verts[i][4] = t;
1503
 
1504
		//
1505
		// lightmap texture coordinates
1506
		//
1507
		s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
1508
		s -= fa->texturemins[0];
1509
		s += fa->light_s*16;
1510
		s += 8;
1511
		s /= BLOCK_WIDTH*16; //fa->texinfo->texture->width;
1512
 
1513
		t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
1514
		t -= fa->texturemins[1];
1515
		t += fa->light_t*16;
1516
		t += 8;
1517
		t /= BLOCK_HEIGHT*16; //fa->texinfo->texture->height;
1518
 
1519
		poly->verts[i][5] = s;
1520
		poly->verts[i][6] = t;
1521
	}
1522
 
1523
	//
1524
	// remove co-linear points - Ed
1525
	//
1526
	if (!gl_keeptjunctions.value && !(fa->flags & SURF_UNDERWATER) )
1527
	{
1528
		for (i = 0 ; i < lnumverts ; ++i)
1529
		{
1530
			vec3_t v1, v2;
1531
			float *prev, *this, *next;
1532
			float f;
1533
 
1534
			prev = poly->verts[(i + lnumverts - 1) % lnumverts];
1535
			this = poly->verts[i];
1536
			next = poly->verts[(i + 1) % lnumverts];
1537
 
1538
			VectorSubtract( this, prev, v1 );
1539
			VectorNormalize( v1 );
1540
			VectorSubtract( next, prev, v2 );
1541
			VectorNormalize( v2 );
1542
 
1543
			// skip co-linear points
1544
			#define COLINEAR_EPSILON 0.001
1545
			if ((fabs( v1[0] - v2[0] ) <= COLINEAR_EPSILON) &&
1546
				(fabs( v1[1] - v2[1] ) <= COLINEAR_EPSILON) &&
1547
				(fabs( v1[2] - v2[2] ) <= COLINEAR_EPSILON))
1548
			{
1549
				int j;
1550
				for (j = i + 1; j < lnumverts; ++j)
1551
				{
1552
					int k;
1553
					for (k = 0; k < VERTEXSIZE; ++k)
1554
						poly->verts[j - 1][k] = poly->verts[j][k];
1555
				}
1556
				--lnumverts;
1557
				++nColinElim;
1558
				// retry next vertex next time, which is now current vertex
1559
				--i;
1560
			}
1561
		}
1562
	}
1563
	poly->numverts = lnumverts;
1564
 
1565
}
1566
 
1567
/*
1568
========================
1569
GL_CreateSurfaceLightmap
1570
========================
1571
*/
1572
void GL_CreateSurfaceLightmap (msurface_t *surf)
1573
{
1574
	int		smax, tmax, s, t, l, i;
1575
	byte	*base;
1576
 
1577
	if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB))
1578
		return;
1579
 
1580
	smax = (surf->extents[0]>>4)+1;
1581
	tmax = (surf->extents[1]>>4)+1;
1582
 
1583
	surf->lightmaptexturenum = AllocBlock (smax, tmax, &surf->light_s, &surf->light_t);
1584
	base = lightmaps + surf->lightmaptexturenum*lightmap_bytes*BLOCK_WIDTH*BLOCK_HEIGHT;
1585
	base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * lightmap_bytes;
1586
	R_BuildLightMap (surf, base, BLOCK_WIDTH*lightmap_bytes);
1587
}
1588
 
1589
 
1590
/*
1591
==================
1592
GL_BuildLightmaps
1593
 
1594
Builds the lightmap texture
1595
with all the surfaces from all brush models
1596
==================
1597
*/
1598
void GL_BuildLightmaps (void)
1599
{
1600
	int		i, j;
1601
	model_t	*m;
1602
	extern qboolean isPermedia;
1603
 
1604
	memset (allocated, 0, sizeof(allocated));
1605
 
1606
	r_framecount = 1;		// no dlightcache
1607
 
1608
	if (!lightmap_textures)
1609
	{
1610
		lightmap_textures = texture_extension_number;
1611
		texture_extension_number += MAX_LIGHTMAPS;
1612
	}
1613
 
1614
	gl_lightmap_format = GL_LUMINANCE;
1615
	// default differently on the Permedia
1616
	if (isPermedia)
1617
		gl_lightmap_format = GL_RGBA;
1618
 
1619
	if (COM_CheckParm ("-lm_1"))
1620
		gl_lightmap_format = GL_LUMINANCE;
1621
	if (COM_CheckParm ("-lm_a"))
1622
		gl_lightmap_format = GL_ALPHA;
1623
	if (COM_CheckParm ("-lm_i"))
1624
		gl_lightmap_format = GL_INTENSITY;
1625
	if (COM_CheckParm ("-lm_2"))
1626
		gl_lightmap_format = GL_RGBA4;
1627
	if (COM_CheckParm ("-lm_4"))
1628
		gl_lightmap_format = GL_RGBA;
1629
 
1630
	switch (gl_lightmap_format)
1631
	{
1632
	case GL_RGBA:
1633
		lightmap_bytes = 4;
1634
		break;
1635
	case GL_RGBA4:
1636
		lightmap_bytes = 2;
1637
		break;
1638
	case GL_LUMINANCE:
1639
	case GL_INTENSITY:
1640
	case GL_ALPHA:
1641
		lightmap_bytes = 1;
1642
		break;
1643
	}
1644
 
1645
	for (j=1 ; j
1646
	{
1647
		m = cl.model_precache[j];
1648
		if (!m)
1649
			break;
1650
		if (m->name[0] == '*')
1651
			continue;
1652
		r_pcurrentvertbase = m->vertexes;
1653
		currentmodel = m;
1654
		for (i=0 ; inumsurfaces ; i++)
1655
		{
1656
			GL_CreateSurfaceLightmap (m->surfaces + i);
1657
			if ( m->surfaces[i].flags & SURF_DRAWTURB )
1658
				continue;
1659
#ifndef QUAKE2
1660
			if ( m->surfaces[i].flags & SURF_DRAWSKY )
1661
				continue;
1662
#endif
1663
			BuildSurfaceDisplayList (m->surfaces + i);
1664
		}
1665
	}
1666
 
1667
 	if (!gl_texsort.value)
1668
 		GL_SelectTexture(TEXTURE1_SGIS);
1669
 
1670
	//
1671
	// upload all lightmaps that were filled
1672
	//
1673
	for (i=0 ; i
1674
	{
1675
		if (!allocated[i][0])
1676
			break;		// no more used
1677
		lightmap_modified[i] = false;
1678
		lightmap_rectchange[i].l = BLOCK_WIDTH;
1679
		lightmap_rectchange[i].t = BLOCK_HEIGHT;
1680
		lightmap_rectchange[i].w = 0;
1681
		lightmap_rectchange[i].h = 0;
1682
		GL_Bind(lightmap_textures + i);
1683
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1684
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1685
		glTexImage2D (GL_TEXTURE_2D, 0, lightmap_bytes
1686
		, BLOCK_WIDTH, BLOCK_HEIGHT, 0,
1687
		gl_lightmap_format, GL_UNSIGNED_BYTE, lightmaps+i*BLOCK_WIDTH*BLOCK_HEIGHT*lightmap_bytes);
1688
	}
1689
 
1690
 	if (!gl_texsort.value)
1691
 		GL_SelectTexture(TEXTURE0_SGIS);
1692
 
1693
}
1694