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_main.c
21
22 #include "quakedef.h"
23
24 entity_t r_worldentity;
25
26 qboolean r_cache_thrash; // compatability
27
28 vec3_t modelorg, r_entorigin;
29 entity_t *currententity;
30
31 int r_visframecount; // bumped when going to a new PVS
32 int r_framecount; // used for dlight push checking
33 int r_lightTimestamp; // PENTA: incresed when next light is started
34
35 mplane_t frustum[4];
36
37 int c_brush_polys, c_alias_polys;
38
39 qboolean envmap; // true during envmap command capture
40
41 int currenttexture = -1; // to avoid unnecessary texture sets
42
43 int cnttextures[16] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; // cached
44
45 int particletexture; // little dot for particles
46 int particletexture_smoke;
47 int particletexture_glow;
48 int particletexture_glow2;
49 int particletexture_tele;
50 int particletexture_blood;
51 int particletexture_dirblood;
52 int playertextures; // up to 16 color translated skins
53
54 int mirrortexturenum; // quake texturenum, not gltexturenum
55 qboolean mirror;
56 qboolean glare;
57 mplane_t *mirror_plane;
58 mplane_t mirror_far_plane; //far plane of the view frustum for mirrors
59 int mirror_clipside;
60 msurface_t *causticschain;
61 int caustics_textures[8];
62 qboolean busy_caustics = false;
63
64 //
65 // view origin
66 //
67 vec3_t vup;
68 vec3_t vpn;
69 vec3_t vright;
70 vec3_t r_origin;
71
72 float r_projection_matrix[16];
73 float r_world_matrix[16];
74 float r_base_world_matrix[16];
75 double r_Dproject_matrix[16];//PENTA
76 double r_Dworld_matrix[16];//PENTA
77 int r_Iviewport[4];//PENTA
78 int numClearsSaved;//PENTA
79
80 float color_black[4] = {0.0, 0.0, 0.0, 0.0};
81
82 //
83 // screen size info
84 //
85 refdef_t r_refdef;
86
87 mleaf_t *r_viewleaf, *r_oldviewleaf;
88
89 texture_t *r_notexture_mip;
90
91 int d_lightstylevalue[256]; // 8.8 fraction of base light value
92
93
94 void R_MarkLeaves (void);
95 void R_Clear (void);
96
97 cvar_t r_norefresh = {"r_norefresh","0"};
98 cvar_t r_drawentities = {"r_drawentities","1"};
99 cvar_t r_drawviewmodel = {"r_drawviewmodel","1"};
100 cvar_t r_fullbright = {"r_fullbright","0"};
101 cvar_t r_lightmap = {"r_lightmap","0"};
102 cvar_t r_shadows = {"r_shadows","0"};
103 //cvar_t r_mirroralpha = {"r_mirroralpha","1"};
104 cvar_t r_wateralpha = {"r_wateralpha","0.5"};//PENTA: different default
105 cvar_t r_dynamic = {"r_dynamic","1"};
106 cvar_t r_novis = {"r_novis","0"};
107
108 cvar_t gl_finish = {"gl_finish","0"};
109 cvar_t gl_clear = {"gl_clear","0"};
110 cvar_t gl_cull = {"gl_cull","1"};
111 //cvar_t gl_texsort = {"gl_texsort","1"};
112 cvar_t gl_smoothmodels = {"gl_smoothmodels","1"};
113 cvar_t gl_affinemodels = {"gl_affinemodels","0"};
114 cvar_t gl_polyblend = {"gl_polyblend","1"};
115 cvar_t gl_flashblend = {"gl_flashblend","1"};
116 cvar_t gl_playermip = {"gl_playermip","0"};
117 cvar_t gl_nocolors = {"gl_nocolors","0"};
118 //cvar_t gl_keeptjunctions = {"gl_keeptjunctions","0"}; PENTA: Don't remove t-junctions
119 cvar_t gl_reporttjunctions = {"gl_reporttjunctions","0"};
120 cvar_t gl_doubleeyes = {"gl_doubleeys", "1"};
121
122 cvar_t gl_watershader = {"gl_watershader","1"};//PENTA: water shaders ON/OFF
123 cvar_t gl_calcdepth = {"gl_calcdepth","0"};
124
125 cvar_t sh_lightmapbright = {"sh_lightmapbright","0.5"};//PENTA: brightness of lightmaps
126 cvar_t sh_radiusscale = {"sh_radiusscale","0.5"};//PENTA: brightness of lightmaps
127 cvar_t sh_visiblevolumes = {"sh_visiblevolumes","0"};//PENTA: draw shadow volumes on/off
128 cvar_t sh_entityshadows = {"sh_entityshadows","1"};//PENTA: entities cast shadows on/off
129 cvar_t sh_worldshadows = {"sh_worldshadows","1"};//PENTA: brushes cast shadows on/off
130 cvar_t sh_showlightnum = {"sh_showlightnum","0"};//PENTA: draw numer of lights used this frame
131 cvar_t sh_glows = {"sh_glows","1"};//PENTA: draw glows around some light sources
132 cvar_t sh_fps = {"sh_fps","0", true}; // set for running times - muff
133 cvar_t sh_debuginfo = {"sh_debuginfo","0"};
134 cvar_t sh_norevis = {"sh_norevis","0"};//PENTA: no recalculating the vis for light positions
135 cvar_t sh_nosvbsp = {"sh_nosvbsp","0"};//PENTA: no shadow bsp
136 cvar_t sh_noeclip = {"sh_noeclip","0"};//PENTA: no entity/leaf clipping for shadows
137 cvar_t sh_infinitevolumes = {"sh_infinitevolumes","0", true};//PENTA: Nvidia infinite volumes
138 cvar_t sh_noscissor = {"sh_noscissor","0"};//PENTA: no scissoring
139 cvar_t sh_nocleversave = {"sh_nocleversave","0"};//PENTA: don't change light drawing order to reduce stencil clears
140 cvar_t sh_bumpmaps = {"sh_bumpmaps","1"};//PENTA: enable disable bump mapping
141 cvar_t sh_colormaps = {"sh_colormaps","1"};//PENTA: enable disable textures on the world (light will remain)
142 cvar_t sh_playershadow = {"sh_playershadow","1"};//PENTA: the player casts a shadow (the one YOU are playing with, others always cast shadows)
143 cvar_t sh_nocache = {"sh_nocache","0"};
144 cvar_t sh_glares = {"sh_glares","0",true};
145 cvar_t sh_noefrags = {"sh_noefrags","0",true};
146 cvar_t sh_showtangent = {"sh_showtangent","0"};
147 cvar_t sh_noshadowpopping = {"sh_noshadowpopping","1"};
148
149 cvar_t mir_detail = {"mir_detail","1",true};
150 cvar_t mir_frameskip = {"mir_frameskip","1",true};
151 cvar_t mir_forcewater = {"mir_forcewater","0"};
152 cvar_t mir_distance = {"mir_distance","400",true};
153 cvar_t gl_wireframe = {"gl_wireframe","0"};
154 cvar_t gl_caustics = {"gl_caustics","1"};
155 cvar_t gl_truform = {"gl_truform","0"};
156 cvar_t gl_truform_tesselation = {"gl_truform_tesselation","4"};
157 cvar_t gl_transformlerp = {"gl_transformlerp","0",true};//Erad - transform interpolation cvar (off by default due to bugs)
158
159 cvar_t fog_r = {"fog_r","0.2"};
160 cvar_t fog_g = {"fog_g","0.1"};
161 cvar_t fog_b = {"fog_b","0.0"};
162 cvar_t fog_start = {"fog_start","256"};
163 cvar_t fog_end = {"fog_end","700"};
164 cvar_t fog_enabled = {"fog_enabled","1"};
165 cvar_t fog_waterfog = {"fog_waterfog","1"};
166 float fog_color[4];
167
168 mirrorplane_t mirrorplanes[NUM_MIRROR_PLANES];
169 int mirror_contents;
170
171 #ifndef GL_ATI_pn_triangles
172 #define GL_PN_TRIANGLES_ATI 0x87F0
173 #define GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F1
174 #define GL_PN_TRIANGLES_POINT_MODE_ATI 0x87F2
175 #define GL_PN_TRIANGLES_NORMAL_MODE_ATI 0x87F3
176 #define GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI 0x87F4
177 #define GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI 0x87F5
178 #define GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI 0x87F6
179 #define GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI 0x87F7
180 #define GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI 0x87F8
181
182 typedef void (APIENTRY *PFNGLPNTRIANGLESIATIPROC)(GLenum pname, GLint param);
183 typedef void (APIENTRY *PFNGLPNTRIANGLESFATIPROC)(GLenum pname, GLfloat param);
184 #endif
185
186 // actually in gl_bumpradeon (duh...)
187 extern PFNGLPNTRIANGLESIATIPROC qglPNTrianglesiATI;
188 extern PFNGLPNTRIANGLESFATIPROC qglPNTrianglesfATI;
189
190 #define GL_INCR_WRAP_EXT 0x8507
191 #define GL_DECR_WRAP_EXT 0x8508
192
193
194 #define MIN_PLAYER_MIRROR 48 //max size of player bounding box
195
196 //extern cvar_t gl_ztrick; PENTA: Removed
197
198 /*
199 =================
200 R_CullBox
201
202 Returns true if the box is completely outside the frustom
203 =================
204 */
R_CullBox(vec3_t mins,vec3_t maxs)205 qboolean R_CullBox (vec3_t mins, vec3_t maxs)
206 {
207 int i;
208
209 for (i=0 ; i<4 ; i++)
210 if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2)
211 return true;
212 return false;
213 }
214
215
216 /*
217 =============
218 R_RotateForEntity
219
220 Erad - transform interpolation
221 =============
222 */
R_RotateForEntity(entity_t * e)223 void R_RotateForEntity (entity_t *e)
224 {
225 float timepassed;
226 float blend;
227 vec3_t d;
228 int i;
229
230 //Hack to stop t lerping view models and player - Eradicator
231 if ((!strcmp (e->model->name, "progs/v_shot.mdl")) || (!strcmp (e->model->name, "progs/v_shot2.mdl"))
232 || (!strcmp (e->model->name, "progs/v_nail.mdl")) || (!strcmp (e->model->name, "progs/v_nail2.mdl"))
233 || (!strcmp (e->model->name, "progs/v_rock.mdl")) || (!strcmp (e->model->name, "progs/v_rock2.mdl"))
234 || (!strcmp (e->model->name, "progs/v_axe.mdl")) || (!strcmp (e->model->name, "progs/v_light.mdl"))
235 || (!strcmp (e->model->name, "progs/players.mdl")) || (!gl_transformlerp.value))
236 {
237 R_UnlerpedRotateForEntity(e);
238 return;
239 }
240
241 timepassed = realtime - e->translate_start_time;
242
243 if (e->translate_start_time == 0 || timepassed > 1)
244 {
245 e->translate_start_time = realtime;
246 VectorCopy (e->origin, e->origin1);
247 VectorCopy (e->origin, e->origin2);
248 }
249
250 if (!VectorCompare (e->origin, e->origin2))
251 {
252 e->translate_start_time = realtime;
253 VectorCopy (e->origin2, e->origin1);
254 VectorCopy (e->origin, e->origin2);
255 blend = 0;
256 }
257 else
258 {
259 blend = timepassed / 0.1;
260
261 if (cl.paused || blend > 1) blend = 1;
262 }
263
264 VectorSubtract (e->origin2, e->origin1, d);
265
266 glTranslatef (
267 e->origin1[0] + (blend * d[0]),
268 e->origin1[1] + (blend * d[1]),
269 e->origin1[2] + (blend * d[2]));
270
271 timepassed = realtime - e->rotate_start_time;
272
273 if (e->rotate_start_time == 0 || timepassed > 1)
274 {
275 e->rotate_start_time = realtime;
276 VectorCopy (e->angles, e->angles1);
277 VectorCopy (e->angles, e->angles2);
278 }
279
280 if (!VectorCompare (e->angles, e->angles2))
281 {
282 e->rotate_start_time = realtime;
283 VectorCopy (e->angles2, e->angles1);
284 VectorCopy (e->angles, e->angles2);
285 blend = 0;
286 }
287 else
288 {
289 blend = timepassed / 0.1;
290
291 if (cl.paused || blend > 1) blend = 1;
292 }
293 VectorSubtract (e->angles2, e->angles1, d);
294
295 for (i = 0; i < 3; i++)
296 {
297 if (d[i] > 180)
298 {
299 d[i] -= 360;
300 }
301 else if (d[i] < -180)
302 {
303 d[i] += 360;
304 }
305 }
306 glRotatef ( e->angles1[1] + ( blend * d[1]), 0, 0, 1);
307 glRotatef (-e->angles1[0] + (-blend * d[0]), 0, 1, 0);
308 glRotatef ( e->angles1[2] + ( blend * d[2]), 1, 0, 0);
309 }
310
R_UnlerpedRotateForEntity(entity_t * e)311 void R_UnlerpedRotateForEntity (entity_t *e)
312 {
313 glTranslatef (e->origin[0], e->origin[1], e->origin[2]);
314
315 glRotatef (e->angles[1], 0, 0, 1);
316 glRotatef (-e->angles[0], 0, 1, 0);
317 glRotatef (e->angles[2], 1, 0, 0);
318 }
319
CL_PointContents(vec3_t p)320 int CL_PointContents (vec3_t p)
321 {
322 int cont;
323
324 cont = SV_HullPointContents (&cl.worldmodel->hulls[0], 0, p);
325 if (cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN)
326 cont = CONTENTS_WATER;
327 return cont;
328 }
329
330 /*
331 =============================================================
332
333 SPRITE MODELS
334
335 =============================================================
336 */
337
338 /*
339 ================
340 R_GetSpriteFrame
341 ================
342 */
R_GetSpriteFrame(entity_t * currententity)343 mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
344 {
345 msprite_t *psprite;
346 mspritegroup_t *pspritegroup;
347 mspriteframe_t *pspriteframe;
348 int i, numframes, frame;
349 float *pintervals, fullinterval, targettime, time;
350
351 psprite = currententity->model->cache.data;
352 frame = currententity->frame;
353
354 if ((frame >= psprite->numframes) || (frame < 0))
355 {
356 Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
357 frame = 0;
358 }
359
360 if (psprite->frames[frame].type == SPR_SINGLE)
361 {
362 pspriteframe = psprite->frames[frame].frameptr;
363 }
364 else
365 {
366 pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
367 pintervals = pspritegroup->intervals;
368 numframes = pspritegroup->numframes;
369 fullinterval = pintervals[numframes-1];
370
371 time = cl.time + currententity->syncbase;
372
373 // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
374 // are positive, so we don't have to worry about division by 0
375 targettime = time - ((int)(time / fullinterval)) * fullinterval;
376
377 for (i=0 ; i<(numframes-1) ; i++)
378 {
379 if (pintervals[i] > targettime)
380 break;
381 }
382
383 pspriteframe = pspritegroup->frames[i];
384 }
385
386 return pspriteframe;
387 }
388
389 /*
390 =================
391 R_DrawSpriteModel
392
393 =================
394 */
395 #define VectorScalarMult(a,b,c) {c[0]=a[0]*b;c[1]=a[1]*b;c[2]=a[2]*b;}
R_DrawSpriteModel(entity_t * e)396 void R_DrawSpriteModel (entity_t *e) //Oriented Sprite Fix - Eradicator
397 {
398 vec3_t point;
399 mspriteframe_t *frame;
400 float *up, *right;
401 vec3_t v_forward, v_right, v_up;
402 msprite_t *psprite;
403 vec3_t fixed_origin;
404 vec3_t temp;
405
406 // don't even bother culling, because it's just a single
407 // polygon without a surface cache
408 frame = R_GetSpriteFrame (e);
409 psprite = currententity->model->cache.data;
410
411 VectorCopy(e->origin,fixed_origin);
412
413 if (psprite->type == SPR_ORIENTED)
414 { // bullet marks on walls
415 AngleVectors (currententity->angles, v_forward, v_right, v_up);
416 VectorScalarMult(v_forward,-2,temp);
417 VectorAdd(temp,fixed_origin,fixed_origin);
418 up = v_up;
419 right = v_right;
420 }
421 else
422 { // normal sprite
423 up = vup;
424 right = vright;
425 }
426
427 GL_DisableMultitexture();
428
429 GL_Bind(frame->gl_texturenum);
430
431 glEnable (GL_ALPHA_TEST);
432 glBegin (GL_QUADS);
433
434 glTexCoord2f (0, 1);
435 //VectorMA (e->origin, frame->down, up, point); //Old
436 VectorMA (fixed_origin, frame->down, up, point); //Fixed Origin
437 VectorMA (point, frame->left, right, point);
438 glVertex3fv (point);
439
440 glTexCoord2f (0, 0);
441 VectorMA (fixed_origin, frame->up, up, point);
442 VectorMA (point, frame->left, right, point);
443 glVertex3fv (point);
444
445 glTexCoord2f (1, 0);
446 VectorMA (fixed_origin, frame->up, up, point);
447 VectorMA (point, frame->right, right, point);
448 glVertex3fv (point);
449
450 glTexCoord2f (1, 1);
451 VectorMA (fixed_origin, frame->down, up, point);
452 VectorMA (point, frame->right, right, point);
453 glVertex3fv (point);
454
455 glEnd ();
456
457 glDisable (GL_ALPHA_TEST);
458 }
459
460 /*
461 =============================================================
462
463 ALIAS MODELS
464
465 =============================================================
466 */
467
468
469 float r_avertexnormals[NUMVERTEXNORMALS][3] = {
470 #include "anorms.h"
471 };
472
473 vec3_t shadevector;
474 float shadelight, ambientlight;
475
476 // precalculated dot products for quantized angles
477 #define SHADEDOT_QUANT 16
478 float r_avertexnormal_dots[SHADEDOT_QUANT][256] =
479 #include "anorm_dots.h"
480 ;
481
482 float *shadedots = r_avertexnormal_dots[0];
483
484 int lastposenum;
485
486 void GL_DrawPentaAliasFrame (aliashdr_t *paliashdr, int posenum);
487 /*
488 =============
489 GL_DrawAliasFrame
490 =============
491 */
492
GL_DrawAliasFrame(aliashdr_t * paliashdr,int posenum)493 void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum)
494 {
495 //Crappy
496 }
497
498
499 ftrivertx_t *apverts;
GL_DrawPentaAliasFrame(aliashdr_t * paliashdr,int posenum)500 void GL_DrawPentaAliasFrame (aliashdr_t *paliashdr, int posenum) {
501
502 mtriangle_t *ptri;
503 ftrivertx_t *verts;
504 plane_t *planes;
505 int i,j;
506
507 return;
508
509 //verts = apverts;
510 verts = (ftrivertx_t *)((byte *)paliashdr + paliashdr->posedata);
511 verts += posenum * paliashdr->poseverts;
512 ptri = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles);
513 planes = (plane_t *)((byte *)paliashdr + paliashdr->planes);
514 planes += posenum * paliashdr->numtris;
515
516 for (i=0 ; i<paliashdr->numtris ; i++, ptri++, planes++)
517 {
518 glBegin(GL_TRIANGLES);
519 //Con_Printf("%i %i %i\n", (int)ptri->vertindex[0], (int)ptri->vertindex[1], (int)ptri->vertindex[2]);
520 glTexCoord2f(0.5, 0.5);
521 for (j=0; j<3; j++) {
522 glVertex3f(verts[ptri->vertindex[j]].v[0],
523 verts[ptri->vertindex[j]].v[1],
524 verts[ptri->vertindex[j]].v[2]);
525 //Con_Printf("%i \n",ptri->vertindex[j]);
526 }
527 glEnd();
528 }
529
530 }
531
532 extern vec3_t lightspot;
533
534
535 int extrudeTimeStamp;
536 vec3_t extrudedVerts[MAXALIASVERTS]; //PENTA: Temp buffer for extruded vertices
537 int extrudedTimestamp[MAXALIASVERTS]; //PENTA: Temp buffer for extruded vertices
538 qboolean triangleVis[MAXALIASTRIS]; //PENTA: Temp buffer for light facingness of triangles
539
R_CalcAliasFrameShadowVolume(aliashdr_t * paliashdr,int posenum)540 void R_CalcAliasFrameShadowVolume (aliashdr_t *paliashdr,int posenum) {
541
542 plane_t *planes;
543 ftrivertx_t *verts;
544 mtriangle_t *tris, *triangle;
545 float d, scale;
546 int i, j;
547 vec3_t v2, *v1;
548
549 planes = (plane_t *)((byte *)paliashdr + paliashdr->planes);
550 planes += posenum * paliashdr->numtris;
551 verts = (ftrivertx_t *)((byte *)paliashdr + paliashdr->posedata);
552 verts += posenum * paliashdr->poseverts;
553 tris = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles);
554
555 extrudeTimeStamp++;
556 //calculate visibility
557 for (i=0; i<paliashdr->numtris; i++) {
558 d = DotProduct(planes[i].normal, currentshadowlight->origin) - planes[i].dist;
559 if (d > 0)
560 triangleVis[i] = true;
561 else
562 triangleVis[i] = false;
563 }
564
565
566 //extude vertices
567 triangle = tris;
568 for (i=0; i<paliashdr->numtris; i++, triangle++) {
569
570 if (triangleVis[i]) {//backfacing extrude it!
571
572 for (j=0; j<3; j++) {
573
574 int index = triangle->vertindex[j];
575 if (extrudedTimestamp[index] == extrudeTimeStamp) continue;
576 extrudedTimestamp[index] = extrudeTimeStamp;
577
578 v1 = &extrudedVerts[index];
579
580 /*
581 for (k=0; k<3; k++)
582 v2[k] = (verts[index].v[k] * paliashdr->scale[k]) + paliashdr->scale_origin[k];
583 */
584 VectorCopy(verts[index].v,v2);
585
586 VectorSubtract (v2, currentshadowlight->origin, (*v1));
587 scale = Length ((*v1));
588
589 if (sh_visiblevolumes.value) {
590 //make them short so that we see them
591 VectorScale ((*v1), (1/scale)* 70, (*v1));
592 } else {
593 //we don't have to be afraid they will clip with the far plane
594 //since we use the infinite matrix trick
595 VectorScale ((*v1), (1/scale)* currentshadowlight->radius*10, (*v1));
596 }
597 VectorAdd ((*v1), v2 ,(*v1));
598 }
599 }
600 }
601 }
602
R_DrawAliasFrameShadowVolume2(aliashdr_t * paliashdr,aliasframeinstant_t * instant)603 void R_DrawAliasFrameShadowVolume2 (aliashdr_t *paliashdr,aliasframeinstant_t *instant) {
604
605 mtriangle_t *tris, *triangle;
606 int i, j;
607 aliaslightinstant_t *linstant = instant->lightinstant;
608
609 tris = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles);
610
611
612 //FIXME: what's faster? less begin/ends or iterating the list multiple times?
613 //extude vertices
614 triangle = tris;
615 for (i=0; i<paliashdr->numtris; i++, triangle++) {
616
617 if (linstant->triangleVis[i]) {
618
619 for (j=0; j<3; j++) {
620
621 qboolean shadow = false;
622 if (triangle->neighbours[j] == -1) {
623 shadow = true;
624 } else if (!linstant->triangleVis[triangle->neighbours[j]]) {
625 shadow = true;
626 }
627
628 if (shadow) {
629 int index = triangle->vertindex[j];
630 glBegin(GL_QUAD_STRIP);
631
632 /*
633 glVertex3f(verts[index].v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0],
634 verts[index].v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1],
635 verts[index].v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2]
636 );
637 */
638 glVertex3fv(&instant->vertices[index][0]);
639 glVertex3fv(&linstant->extvertices[index][0]);
640
641 index = triangle->vertindex[(j+1)%3];
642 /*glVertex3f(verts[index].v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0],
643 verts[index].v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1],
644 verts[index].v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2]
645 );
646 */
647 glVertex3fv(&instant->vertices[index][0]);
648 glVertex3fv(&linstant->extvertices[index][0]);
649 glEnd();
650
651 }
652 }
653
654
655 glBegin(GL_TRIANGLES);
656 for (j=0; j<3; j++) {
657 int index = triangle->vertindex[j];
658 /*
659 glVertex3f(verts[index].v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0],
660 verts[index].v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1],
661 verts[index].v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2]
662 );
663 */
664 glVertex3fv(&instant->vertices[index][0]);
665 }
666 glEnd();
667
668 glBegin(GL_TRIANGLES);
669 for (j=2; j>=0; j--) {
670 glVertex3fv(&linstant->extvertices[triangle->vertindex[j]][0]);
671 }
672 glEnd();
673
674 }
675
676 /*
677 glBegin(GL_LINES);
678 for (j=0; j<3; j++) {
679 v2[j] = verts[ triangle->vertindex[0]].v[j] * paliashdr->scale[j] + paliashdr->scale_origin[j];
680 }
681 glVertex3fv(&v2[0]);
682 VectorMA(v2, 5, planes[i].normal, v2);
683 glVertex3fv(&v2[0]);
684 glEnd();
685 */
686 }
687 }
688 /*
689 =============
690 R_DrawAliasFrameShadowVolume
691 =============
692 */
693 extern vec3_t lightspot;
694
695 /*
696 void R_DrawAliasFrameShadowVolume (aliashdr_t *paliashdr, int posenum)
697 {
698 float s, t, l;
699 int i, j;
700 int index;
701 ftrivertx_t *v, *verts;
702 int list;
703 int *order;
704 vec3_t point,dir;
705 vec3_t *normal;
706 int count;
707 vec3_t fnormal;
708 verts = (ftrivertx_t *)((byte *)paliashdr + paliashdr->posedata);
709 verts += posenum * paliashdr->poseverts;
710 order = (int *)((byte *)paliashdr + paliashdr->commands);
711
712 while (1)
713 {
714 // get the vertex count and primitive type
715 count = *order++;
716 if (!count)
717 break; // done
718 if (count < 0)
719 {
720 count = -count;
721 glBegin (GL_TRIANGLE_FAN);
722 }
723 else
724 glBegin (GL_TRIANGLE_STRIP);
725
726 do
727 {
728 // texture coordinates come from the draw list
729 // (skipped for shadow volumes) glTexCoord2fv ((float *)order);
730 order += 2;
731
732 // normals and vertexes come from the frame list
733
734 //point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
735 //point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
736 //point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
737
738
739 normal = &r_avertexnormals[verts->lightnormalindex];
740
741 //VectorSubtract(point,currentshadowlight->origin,dir);
742 VectorSubtract(verts->v,currentshadowlight->origin,dir);
743 VectorNormalize(dir);
744
745 if (DotProduct(dir,(*normal)) <= 0) {
746 //etrude to "infinity"
747 if (sh_visiblevolumes.value) {
748 VectorScale(dir,50,dir);
749 } else {
750 VectorScale(dir,currentshadowlight->radius*10,dir);
751 }
752 //VectorAdd(point,dir,point);
753 VectorAdd(verts->v,dir,point);
754 } else
755 VectorCopy(verts->v,point);
756
757 glVertex3fv (point);
758 verts++;
759 } while (--count);
760
761 glEnd ();
762 }
763 }
764 */
765
766 /*
767 =================
768 R_DrawAliasShadowVolume
769
770 =================
771 */
772
R_DrawAliasSurfaceShadowVolume(aliashdr_t * paliashdr,aliasframeinstant_t * aliasframeinstant)773 void R_DrawAliasSurfaceShadowVolume (aliashdr_t *paliashdr, aliasframeinstant_t *aliasframeinstant)
774 {
775 #if 1
776 //
777 //Pass 1 increase
778 //
779 glCullFace(GL_BACK);
780 glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
781 glCullFace(GL_FRONT);
782
783 R_DrawAliasFrameShadowVolume2 (paliashdr, aliasframeinstant);
784
785 //
786 // Second Pass. Decrease Stencil Value In The Shadow
787 //
788 glCullFace(GL_FRONT);
789 glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
790 glCullFace(GL_BACK);
791
792 R_DrawAliasFrameShadowVolume2 (paliashdr, aliasframeinstant);
793 #else
794 glDisable(GL_CULL_FACE);
795 glCullFace(GL_FRONT_AND_BACK);
796 checkerror();
797 glStencilOp(GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
798 checkerror();
799 qglStencilFuncSeparateATI(GL_ALWAYS, GL_ALWAYS, 0, ~0);
800 checkerror();
801 qglStencilOpSeparateATI(GL_FRONT, GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP);
802 checkerror();
803 qglStencilOpSeparateATI(GL_BACK, GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
804 checkerror();
805 R_DrawAliasFrameShadowVolume2 (paliashdr, aliasframeinstant);
806
807 glEnable(GL_CULL_FACE);
808 glCullFace(GL_BACK);
809 #endif
810 }
811
812
R_DrawAliasShadowVolume(entity_t * e)813 void R_DrawAliasShadowVolume (entity_t *e)
814 {
815 model_t *clmodel;
816 aliashdr_t *paliashdr;
817 alias3data_t *data;
818 aliasframeinstant_t *aliasframeinstant;
819 int i,maxnumsurf;
820 //vec3_t oldlightpos;
821
822 currententity = e;
823
824 clmodel = currententity->model;
825
826 /* no shadows casting for these */
827 if (clmodel->flags & EF_NOSHADOW)
828 return;
829
830 //
831 // locate the proper data
832 //
833 if (!e->aliasframeinstant) {
834 Con_Printf("no instant for ent %s\n", clmodel->name);
835 return;
836 }
837
838 /*
839 Don't cull to frustum models behind you may still cast shadows
840
841 if (R_CullBox (mins, maxs))
842 return;
843 */
844
845 VectorCopy (currententity->origin, r_entorigin);
846 VectorSubtract (r_origin, r_entorigin, modelorg);
847
848 //
849 // locate the proper data
850 //
851 // data = (alias3data_t *)Mod_Extradata (e->model);
852
853 aliasframeinstant = e->aliasframeinstant;
854
855 data = (alias3data_t *)Mod_Extradata (e->model);
856 maxnumsurf = data->numSurfaces;
857
858 glPushMatrix ();
859 R_RotateForEntity (e);
860
861 for (i=0;i<maxnumsurf;++i)
862 {
863 paliashdr = (aliashdr_t *)((char*)data + data->ofsSurfaces[i]);
864
865 if (!aliasframeinstant) {
866 glPopMatrix ();
867 Con_Printf("R_DrawAliasShadowVolume: missing instant for ent %s\n", e->model->name);
868 return;
869 }
870
871 /* doesn't fit with new structs
872 if (paliashdr != ((aliasframeinstant_t *)e->model->aliasframeinstant)->paliashdr) {
873 //Sys_Error("Cache trashed");
874 r_cache_thrash = true;
875 ((aliasframeinstant_t *)e->model->aliasframeinstant)->paliashdr = paliashdr;
876 }
877 */
878
879 if ((e->frame >= paliashdr->numframes) || (e->frame < 0))
880 {
881 glPopMatrix ();
882 return;
883 }
884
885 //
886 // draw all the triangles
887 //
888 R_DrawAliasSurfaceShadowVolume(paliashdr,aliasframeinstant);
889 aliasframeinstant = aliasframeinstant->_next;
890 //VectorCopy(oldlightpos,currentshadowlight->origin);
891 } /* for paliashdr */
892
893 glPopMatrix();
894 }
895
896 /*
897 =================
898 R_SetupAliasFrame
899
900 =================
901 */
902
R_SetupAliasFrame(aliashdr_t * paliashdr,aliasframeinstant_t * instant)903 void R_SetupAliasFrame (aliashdr_t *paliashdr, aliasframeinstant_t *instant)
904 {
905 float* texcoos;
906 int* indecies;
907 /*
908 if ((frame >= paliashdr->numframes) || (frame < 0))
909 {
910 Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
911 frame = 0;
912 }
913
914 pose = paliashdr->frames[frame].firstpose;
915 numposes = paliashdr->frames[frame].numposes;
916
917 apverts = (ftrivertx_t *)((byte *)paliashdr + paliashdr->frames[frame].frame);
918
919 if (numposes > 1)
920 {
921 interval = paliashdr->frames[frame].interval;
922 pose += (int)(cl.time / interval) % numposes;
923 }
924 */
925
926 texcoos = (float *)((byte *)paliashdr + paliashdr->texcoords);
927 indecies = (int *)((byte *)paliashdr + paliashdr->indecies);
928 //GL_DrawAliasFrame (paliashdr, pose);
929 glVertexPointer(3, GL_FLOAT, 0, instant->vertices);
930 glEnableClientState(GL_VERTEX_ARRAY);
931 glNormalPointer(GL_FLOAT, 0, instant->normals);
932 glEnableClientState(GL_NORMAL_ARRAY);
933 glTexCoordPointer(2, GL_FLOAT, 0, texcoos);
934 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
935
936 glDrawElements(GL_TRIANGLES,paliashdr->numtris*3,GL_UNSIGNED_INT,indecies);
937
938 glDisableClientState(GL_VERTEX_ARRAY);
939 glDisableClientState(GL_NORMAL_ARRAY);
940 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
941 }
942
943 /*
944 Draws the tangent space of the model
945 */
R_DrawAliasTangent(aliashdr_t * paliashdr,aliasframeinstant_t * instant)946 void R_DrawAliasTangent (aliashdr_t *paliashdr, aliasframeinstant_t *instant)
947 {
948 float* texcoos;
949 int* indecies;
950 vec3_t extr;
951 int i;
952
953 texcoos = (float *)((byte *)paliashdr + paliashdr->texcoords);
954 indecies = (int *)((byte *)paliashdr + paliashdr->indecies);
955 //GL_DrawAliasFrame (paliashdr, pose);
956
957 for (i=0; i<paliashdr->poseverts; i++) {
958
959 glColor3ub(255,0,0);
960 glBegin(GL_LINES);
961 glVertex3fv(&instant->vertices[i][0]);
962 VectorMA(instant->vertices[i],1,instant->normals[i],extr);
963 glVertex3fv(&extr[0]);
964 glEnd();
965
966 glColor3ub(0,255,0);
967 glBegin(GL_LINES);
968 glVertex3fv(&instant->vertices[i][0]);
969 VectorMA(instant->vertices[i],1,instant->tangents[i],extr);
970 glVertex3fv(&extr[0]);
971 glEnd();
972
973 glColor3ub(0,0,255);
974 glBegin(GL_LINES);
975 glVertex3fv(&instant->vertices[i][0]);
976 VectorMA(instant->vertices[i],1,instant->binomials[i],extr);
977 glVertex3fv(&extr[0]);
978 glEnd();
979 }
980 }
981
982
983 /*
984 =================
985 R_DrawAliasSurface
986 DC : draw one surface from a model
987
988 =================
989 */
990
991
992
R_DrawAliasSurface(aliashdr_t * paliashdr,float bright,aliasframeinstant_t * instant)993 void R_DrawAliasSurface (aliashdr_t *paliashdr, float bright, aliasframeinstant_t *instant)
994 {
995 int i;
996 int anim;
997
998 //
999 // draw all the triangles
1000 //
1001
1002 if (!busy_caustics) {
1003 anim = (int)(cl.time*10) & 3;
1004 GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]);
1005
1006 // we can't dynamically colormap textures, so they are cached
1007 // seperately for the players. Heads are just uncolored.
1008 if (currententity->colormap != vid.colormap && !gl_nocolors.value)
1009 {
1010 i = currententity - cl_entities;
1011 if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
1012 GL_Bind(playertextures - 1 + i);
1013 }
1014 }
1015
1016 //XYZ
1017 if (gl_wireframe.value) {
1018 glDisable(GL_TEXTURE_2D);
1019 }
1020
1021 if ( gl_truform.value )
1022 {
1023 glEnable(GL_PN_TRIANGLES_ATI);
1024 qglPNTrianglesiATI(GL_PN_TRIANGLES_POINT_MODE_ATI, GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI);
1025 qglPNTrianglesiATI(GL_PN_TRIANGLES_NORMAL_MODE_ATI, GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI);
1026 qglPNTrianglesiATI(GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, gl_truform_tesselation.value);
1027 }
1028
1029
1030
1031 glColor3f(bright, bright, bright);
1032 //if (busy_caustics)
1033 // glColor3f(1,1,1);
1034 R_SetupAliasFrame (paliashdr, instant);
1035
1036 // Draw luma if present
1037 if ( !busy_caustics )
1038 {
1039 anim = (int)(cl.time*10) & 3;
1040 if ( paliashdr->gl_lumatex[currententity->skinnum][anim] != 0)
1041 {
1042 glFogfv(GL_FOG_COLOR, color_black);
1043 glEnable(GL_BLEND);
1044 glBlendFunc(GL_ONE, GL_ONE);
1045 GL_SelectTexture(GL_TEXTURE1_ARB);
1046 glDisable(GL_TEXTURE_2D);
1047 GL_SelectTexture(GL_TEXTURE0_ARB);
1048 glColor3f(1, 1, 1);
1049
1050 GL_Bind( paliashdr->gl_lumatex[currententity->skinnum][anim] );
1051
1052 R_SetupAliasFrame (paliashdr, instant);
1053
1054
1055 glColor3f(sh_lightmapbright.value,sh_lightmapbright.value,sh_lightmapbright.value);
1056 GL_SelectTexture(GL_TEXTURE1_ARB);
1057 glEnable(GL_TEXTURE_2D);
1058 GL_SelectTexture(GL_TEXTURE0_ARB);
1059 GL_SelectTexture(GL_TEXTURE1_ARB);
1060 glDisable(GL_BLEND);
1061 glFogfv(GL_FOG_COLOR, fog_color);
1062 }
1063 }
1064
1065 if ((sh_showtangent.value) && (!busy_caustics)) {
1066 glDisable(GL_TEXTURE_2D);
1067 R_DrawAliasTangent(paliashdr, instant);
1068 glEnable(GL_TEXTURE_2D);
1069 }
1070
1071 c_alias_polys += paliashdr->numtris;
1072
1073
1074 if ( gl_truform.value )
1075 {
1076 glDisable(GL_PN_TRIANGLES_ATI);
1077 }
1078 }
1079
1080
1081
1082 /*
1083 =================
1084 R_DrawAliasModel
1085
1086 =================
1087 */
1088
1089 /*
1090 void R_PrepareEntityForDraw (float bright)
1091 {
1092 float an;
1093
1094
1095
1096 model_t *clmodel;
1097
1098 clmodel = currententity->model;
1099
1100 VectorAdd (currententity->origin, clmodel->mins, mins);
1101 VectorAdd (currententity->origin, clmodel->maxs, maxs);
1102
1103 if (R_CullBox (mins, maxs))
1104 return;
1105
1106
1107 VectorCopy (currententity->origin, r_entorigin);
1108 VectorSubtract (r_origin, r_entorigin, modelorg);
1109
1110 shadelight = bright;
1111
1112 an = currententity->angles[1]/180*M_PI;
1113 shadevector[0] = cos(-an);
1114 shadevector[1] = sin(-an);
1115 shadevector[2] = 1;
1116 VectorNormalize (shadevector);
1117
1118 }
1119 */
1120
R_DrawAliasModel(float bright)1121 void R_DrawAliasModel (float bright)
1122 {
1123 int i,maxnumsurf;
1124 aliashdr_t *paliashdr;
1125 aliasframeinstant_t *aliasframeinstant;
1126 alias3data_t *data;
1127 vec3_t mins,maxs;
1128
1129 //R_PrepareEntityForDraw (bright);
1130
1131 GL_DisableMultitexture();
1132
1133 glPushMatrix ();
1134
1135 R_RotateForEntity (currententity);
1136
1137 data = (alias3data_t *)Mod_Extradata (currententity->model);
1138 maxnumsurf = data->numSurfaces;
1139
1140 aliasframeinstant = currententity->aliasframeinstant;
1141
1142 if (gl_smoothmodels.value)
1143 glShadeModel (GL_SMOOTH);
1144 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1145
1146 if (gl_affinemodels.value)
1147 glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1148
1149 for (i=0;i<maxnumsurf;++i){
1150
1151 paliashdr = (aliashdr_t *)((char*)data + data->ofsSurfaces[i]);
1152
1153 if (!aliasframeinstant) {
1154 glPopMatrix();
1155 Con_Printf("R_DrawAliasModel: missing instant for ent %s\n", currententity->model->name);
1156 return;
1157 }
1158
1159 /* disabled for now because it doesn't work with viewent
1160 VectorAdd (currententity->origin,paliashdr->mins, mins);
1161 VectorAdd (currententity->origin,paliashdr->maxs, maxs);
1162
1163 if (!R_CullBox (mins, maxs)) */
1164 R_DrawAliasSurface (paliashdr, bright, aliasframeinstant);
1165 aliasframeinstant = aliasframeinstant->_next;
1166 }
1167
1168 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1169
1170 glShadeModel (GL_FLAT);
1171
1172 if (gl_affinemodels.value)
1173 glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1174
1175 glPopMatrix ();
1176
1177 }
1178
1179 //==================================================================================
1180
1181
R_DrawAmbientAlias(void (* r_func)(float bright))1182 void R_DrawAmbientAlias (void (*r_func)(float bright))
1183 {
1184 float brightness;
1185 if (currententity->model->flags & EF_FULLBRIGHT)
1186 {
1187 r_func ( 1.0);
1188 //XYZ
1189 } else if (gl_wireframe.value) {
1190 r_func ( 0.0);
1191 }else {
1192 brightness = (R_LightPoint (currententity->origin)/255.0) * sh_lightmapbright.value;
1193 r_func (brightness);
1194 }
1195 }
1196
1197
1198 /*
1199 =============
1200 PENTA:
1201 R_DrawAmbientEntities
1202 =============
1203 */
R_DrawAmbientEntities()1204 void R_DrawAmbientEntities ()
1205 {
1206 int i;
1207 vec3_t mins,maxs;
1208
1209 if (!r_drawentities.value)
1210 return;
1211
1212 //We don't draw sprites they do not cast shadows
1213 for (i=0 ; i<cl_numvisedicts ; i++)
1214 {
1215 currententity = cl_visedicts[i];
1216
1217 if (currententity->angles[0] || currententity->angles[1] || currententity->angles[2])
1218 {
1219 int i;
1220 for (i=0 ; i<3 ; i++)
1221 {
1222 mins[i] = currententity->origin[i] - currententity->model->radius;
1223 maxs[i] = currententity->origin[i] + currententity->model->radius;
1224 }
1225 } else {
1226 VectorAdd (currententity->origin,currententity->model->mins, mins);
1227 VectorAdd (currententity->origin,currententity->model->maxs, maxs);
1228 }
1229
1230 if (R_CullBox (mins, maxs))
1231 continue;
1232
1233 if (mirror) {
1234 if (mirror_clipside == BoxOnPlaneSide(mins, maxs, mirror_plane)) {
1235 continue;
1236 }
1237
1238 if ( BoxOnPlaneSide(mins, maxs, &mirror_far_plane) == 1) {
1239 return;
1240 }
1241 }
1242
1243 switch (currententity->model->type)
1244 {
1245 case mod_alias:
1246 R_DrawAmbientAlias (R_DrawAliasModel);
1247 break;
1248 case mod_brush:
1249 glColor3f(sh_lightmapbright.value,sh_lightmapbright.value,sh_lightmapbright.value);
1250 R_DrawBrushModel(currententity);
1251 break;
1252
1253 default:
1254 break;
1255 }
1256 }
1257 }
1258
1259 /*
1260 =============
1261 PENTA:
1262 R_DrawLightEntities
1263 -> moved to gl_bumpdriver.c
1264 =============
1265 */
1266
1267
1268 /*
1269 =============
1270 R_DrawEntitiesOnList
1271
1272 Post multiply the textures with the frame buff.
1273 =============
1274 */
R_DrawEntitiesOnList(void)1275 void R_DrawEntitiesOnList (void)
1276 {
1277 int i;
1278
1279 if (!r_drawentities.value)
1280 return;
1281
1282 if ( cl_numvisedicts == 0 )
1283 return;
1284
1285 glBlendFunc(GL_ZERO,GL_SRC_COLOR);
1286 glEnable(GL_BLEND);
1287
1288 glColor3f(1.0f, 1.0f, 1.0f);
1289
1290 //Con_Printf("cl_numvisedicts %d\n",cl_numvisedicts);
1291 // draw sprites seperately, because of alpha blending
1292 for (i=0 ; i<cl_numvisedicts ; i++)
1293 {
1294 currententity = cl_visedicts[i];
1295
1296 switch (currententity->model->type)
1297 {
1298 case mod_alias:
1299 R_DrawAliasModel (1.0);
1300 break;
1301
1302 case mod_brush:
1303 //glColor3f(1.0,1.0,1.0);
1304 //R_DrawBrushModel (currententity);
1305 break;
1306
1307 default:
1308 break;
1309 }
1310 }
1311
1312
1313 glDisable(GL_BLEND);
1314 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1315
1316 //sprites are drawn the usual way
1317 for (i=0 ; i<cl_numvisedicts ; i++)
1318 {
1319 currententity = cl_visedicts[i];
1320
1321 switch (currententity->model->type)
1322 {
1323 case mod_sprite:
1324 R_DrawSpriteModel (currententity);
1325 default: // <AWE> added default to suppress compiler warning.
1326 break;
1327 }
1328 }
1329
1330
1331 }
1332
1333
1334 /*
1335 =============
1336 R_MarkEntitiesOnList
1337 =============
1338 */
R_MarkEntitiesOnList(void)1339 void R_MarkEntitiesOnList (void)
1340 {
1341 int i;
1342 float angle;
1343
1344 if (!r_drawentities.value)
1345 return;
1346
1347 for (i=0 ; i<cl_numlightvisedicts ; i++)
1348 {
1349 currententity = cl_lightvisedicts[i];
1350
1351 switch (currententity->model->type)
1352 {
1353 case mod_brush:
1354 //R_MarkBrushModelSurfaces(currententity);
1355 R_SetupBrushInstantForLight(currententity);
1356 break;
1357 case mod_alias:
1358 R_SetupInstantForLight(currententity);
1359 break;
1360 default:
1361 break;
1362 }
1363 }
1364
1365 if (cl.viewent.model)
1366 R_SetupInstantForLight(&cl.viewent);
1367 //for player Hack: Dont let it rotate when player looks up/down this looks
1368 //very unrealistic
1369
1370 if (mirror) return;
1371 if (!cl_entities[cl.viewentity].model) return;
1372 if (cl_entities[cl.viewentity].model->type != mod_alias) return;
1373
1374 angle = cl_entities[cl.viewentity].angles[0];
1375 cl_entities[cl.viewentity].angles[0] = 0;
1376 R_SetupInstantForLight(&cl_entities[cl.viewentity]);
1377 cl_entities[cl.viewentity].angles[0] = angle;
1378 }
1379
1380 /*
1381 =============
1382 R_DrawEntitiesShadowVolumes
1383 =============
1384 */
R_DrawEntitiesShadowVolumes(int type)1385 void R_DrawEntitiesShadowVolumes (int type)
1386 {
1387 int i;
1388 float colorscale;
1389 vec3_t dist;
1390 vec3_t angles;
1391 if (!r_drawentities.value)
1392 return;
1393
1394
1395 for (i=0 ; i<cl_numlightvisedicts ; i++)
1396 {
1397 currententity = cl_lightvisedicts[i];
1398
1399 if (currententity->model->type != type) continue;
1400
1401 switch (currententity->model->type)
1402 {
1403 case mod_alias:
1404
1405 VectorSubtract (currententity->origin, currentshadowlight->origin,dist);
1406 colorscale = 1 - (Length(dist) / currentshadowlight->radius);
1407
1408 //it will be a verry faint shadow
1409 if (colorscale < 0.1) continue;
1410 R_DrawAliasShadowVolume(currententity);
1411
1412 break;
1413
1414 case mod_brush:
1415 R_DrawBrushModelVolumes(currententity);
1416 break;
1417
1418 default:
1419 break;
1420 }
1421 }
1422
1423 if (mirror) return;
1424 currententity = &cl_entities[cl.viewentity];
1425 VectorCopy(currententity->angles,angles);
1426 //during intermissions the viewent model is nil
1427 if (currententity->model)
1428 if ((currententity->model->type == type)
1429 && (type == mod_alias)
1430 && (sh_playershadow.value)
1431 && (!chase_active.value)) { //Fix for two player shadows in chase cam - Eradicator
1432 //for lights cast by the player don't add the player's shadow
1433 if (currentshadowlight->owner != currententity) {
1434 //HACK: only horizontal angle this looks better
1435 currententity->angles[0] = 0;
1436 currententity->angles[2] = 0;
1437 R_DrawAliasShadowVolume(currententity);
1438 }
1439 }
1440 VectorCopy(angles,currententity->angles);
1441
1442 }
1443
1444 /*
1445 =============
1446 R_DrawLightSprites
1447
1448 Draw the overriden sprites that are lit by a cube map
1449 =============
1450 */
R_DrawLightSprites(void)1451 void R_DrawLightSprites (void)
1452 {
1453 int i;
1454 vec3_t dist;
1455 float colorscale;
1456
1457 if (!r_drawentities.value)
1458 return;
1459
1460 if ( cl_numlightvisedicts == 0 )
1461 return;
1462
1463 glEnable(GL_BLEND);
1464 glBlendFunc(GL_ONE,GL_ONE);
1465 glDepthMask(0);
1466
1467 if ( currentshadowlight->filtercube )
1468 {
1469 glMatrixMode(GL_TEXTURE);
1470 glPushMatrix();
1471 GL_SetupCubeMapMatrix(true);
1472
1473 GL_EnableColorShader (false);
1474 }
1475 else
1476 {
1477 GL_SelectTexture(GL_TEXTURE0_ARB);
1478 glEnable(GL_TEXTURE_2D);
1479 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
1480 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
1481 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
1482 glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE);
1483 }
1484
1485 for ( i = 0; i < cl_numlightvisedicts; i++ )
1486 {
1487 currententity = cl_lightvisedicts[i];
1488
1489 if (currententity->model->type == mod_sprite)
1490 {
1491 if (((msprite_t *)currententity->model->cache.data)->type
1492 >= SPR_VP_PARALLEL_UPRIGHT_OVER)
1493 {
1494 if (currententity->light_lev)
1495 continue;
1496
1497 //We do attent instead of opengl since gl doesn't seem to do
1498 //what we want, it never really gets to zero.
1499 VectorSubtract (currententity->origin, currentshadowlight->origin,
1500 dist);
1501 colorscale = 1 - (Length(dist) / currentshadowlight->radius);
1502
1503 //if it's to dark we save time by not drawing it
1504 if (colorscale < 0.1)
1505 continue;
1506
1507 glColor3f(currentshadowlight->color[0]*colorscale,
1508 currentshadowlight->color[1]*colorscale,
1509 currentshadowlight->color[2]*colorscale);
1510
1511 if ( currentshadowlight->filtercube )
1512 R_DrawSpriteModelWV(currententity);
1513 else
1514 R_DrawSpriteModel(currententity);
1515
1516 }
1517 }
1518 }
1519
1520 glDisable(GL_BLEND);
1521
1522 if ( currentshadowlight->filtercube )
1523 {
1524 GL_DisableColorShader (false);
1525
1526 glPopMatrix();
1527 glMatrixMode(GL_MODELVIEW);
1528 }
1529 }
1530
1531 /*
1532 =============
1533
1534 =============
1535 */
R_DrawFullbrightSprites(void)1536 void R_DrawFullbrightSprites (void)
1537 {
1538 int i;
1539
1540 if (!r_drawentities.value)
1541 return;
1542
1543 if ( cl_numvisedicts == 0 )
1544 return;
1545
1546 glEnable(GL_BLEND);
1547 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
1548 glDepthMask(0);
1549 GL_DisableMultitexture();
1550 for (i=0 ; i<cl_numvisedicts ; i++)
1551 {
1552 currententity = cl_visedicts[i];
1553
1554 if (currententity->model->type == mod_sprite) {
1555 if (((msprite_t *)currententity->model->cache.data)->type >= SPR_VP_PARALLEL_UPRIGHT_OVER) {
1556 if (currententity->light_lev) {
1557
1558 glColor3fv(¤tentity->color[0]);
1559 R_DrawSpriteModel(currententity);
1560 }
1561 } else {
1562 glColor3f(1.0f,1.0f,1.0f);
1563 R_DrawSpriteModel(currententity);
1564 }
1565 }
1566 }
1567
1568 glDisable(GL_BLEND);
1569 glDepthMask(1);
1570 }
1571
1572 /*
1573 =============
1574 R_DrawViewModel
1575
1576 Gunnetje
1577
1578 =============
1579 */
R_DrawViewModel(void)1580 void R_DrawViewModel (void)
1581 {
1582
1583 /*
1584 if (!r_drawviewmodel.value)
1585 return;
1586
1587 if (chase_active.value)
1588 return;
1589
1590 if (envmap)
1591 return;
1592
1593 if (!r_drawentities.value)
1594 return;
1595
1596 if (cl.items & IT_INVISIBILITY)
1597 return;
1598
1599 if (cl.stats[STAT_HEALTH] <= 0)
1600 return;
1601
1602 if (mirror)
1603 return;
1604
1605 currententity = &cl.viewent;
1606 if (!currententity->model)
1607 return;
1608
1609 if (currententity->model->type != mod_alias) return;
1610 */
1611
1612 if (!R_ShouldDrawViewModel()) return;
1613
1614 // hack the depth range to prevent view model from poking into walls
1615 //PENTA: would this work with stencil shadows?
1616 if ( gl_calcdepth.value ) //Calc Depth (disables shadows on v_ models,
1617 //but they don't poke into walls) - Eradicator
1618 glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
1619
1620 //Erad - don't want to lerp view models (disable this to see why ;)
1621 if (gl_transformlerp.value)
1622 {
1623 gl_transformlerp.value = 0;
1624 R_DrawAliasModel (0.1);
1625 gl_transformlerp.value = 1;
1626 }
1627 else
1628 R_DrawAliasModel (0.1);
1629
1630 if ( gl_calcdepth.value ) //Calc Depth - Eradicator
1631 glDepthRange (gldepthmin, gldepthmax);
1632 }
1633
1634 /*
1635 =============
1636 R_DrawViewModel
1637
1638 Gunnetje
1639
1640 =============
1641 */
R_DrawViewModelLight(void)1642 void R_DrawViewModelLight (void)
1643 {
1644 float colorscale;
1645 vec3_t dist;
1646
1647 /*
1648 if (!r_drawviewmodel.value)
1649 return;
1650
1651 if (chase_active.value)
1652 return;
1653
1654 if (envmap)
1655 return;
1656
1657 if (!r_drawentities.value)
1658 return;
1659
1660 if (cl.items & IT_INVISIBILITY)
1661 return;
1662
1663 if (cl.stats[STAT_HEALTH] <= 0)
1664 return;
1665
1666 if (mirror)
1667 return;
1668
1669 currententity = &cl.viewent;
1670 if (!currententity->model)
1671 return;
1672 */
1673 if (!R_ShouldDrawViewModel()) return;
1674
1675 //We do attent instead of opengl since gl doesn't seem to do
1676 //what we want, it never really gets to zero.
1677 VectorSubtract (currententity->origin,currentshadowlight->origin,dist);
1678 colorscale = 1 - (Length(dist) / currentshadowlight->radius);
1679
1680 //if it's to dark we save time by not drawing it
1681 if (colorscale < 0.1) return;
1682
1683 glColor4f(colorscale,colorscale,colorscale,colorscale);
1684
1685 R_DrawAliasObjectLight(currententity,R_DrawAliasBumped);
1686 }
1687
1688 /*
1689 Returns true if we should draw the view model
1690 */
R_ShouldDrawViewModel(void)1691 qboolean R_ShouldDrawViewModel (void)
1692 {
1693 if (!r_drawviewmodel.value)
1694 return false;
1695
1696 if (chase_active.value)
1697 return false;
1698
1699 if (envmap)
1700 return false;
1701
1702 if (!r_drawentities.value)
1703 return false;
1704
1705 if (cl.items & IT_INVISIBILITY)
1706 return false;
1707
1708 if (cl.stats[STAT_HEALTH] <= 0)
1709 return false;
1710
1711 if (mirror)
1712 return false;
1713 currententity = &cl.viewent;
1714 if (!currententity->model)
1715 return false;
1716
1717 if (currententity->model->type != mod_alias)
1718 return false;
1719
1720 return true;
1721 }
1722
1723 extern cvar_t v_gamma;
1724 /*
1725 ============
1726 R_AdjustGamma
1727 ============
1728 */
R_AdjustGamma(void)1729 void R_AdjustGamma(void) //Gamma - Eradicator
1730 {
1731 if (v_gamma.value < 0.2f)
1732 v_gamma.value = 0.2f;
1733 if (v_gamma.value >= 1)
1734 {
1735 v_gamma.value = 1;
1736 return;
1737 }
1738
1739 glBlendFunc (GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
1740 glColor4f (1, 1, 1, v_gamma.value );
1741 glBegin (GL_QUADS);
1742 glVertex3f (10, 100, 100);
1743 glVertex3f (10, -100, 100);
1744 glVertex3f (10, -100, -100);
1745 glVertex3f (10, 100, -100);
1746
1747 glVertex3f (11, 100, 100);
1748 glVertex3f (11, -100, 100);
1749 glVertex3f (11, -100, -100);
1750 glVertex3f (11, 100, -100);
1751
1752 glEnd ();
1753 }
1754
1755 /*
1756 ============
1757 R_PolyBlend
1758 ============
1759 */
R_PolyBlend(void)1760 void R_PolyBlend (void)
1761 {
1762 if (!gl_polyblend.value)
1763 return;
1764
1765 GL_DisableMultitexture();
1766
1767 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1768
1769 glEnable (GL_BLEND);
1770 glDisable (GL_DEPTH_TEST);
1771 glDisable (GL_TEXTURE_2D);
1772
1773 glLoadIdentity ();
1774
1775 glRotatef (-90, 1, 0, 0); // put Z going up
1776 glRotatef (90, 0, 0, 1); // put Z going up
1777
1778 if (v_blend[3])
1779 {
1780 glColor4fv (v_blend);
1781
1782 glBegin (GL_QUADS);
1783
1784 glVertex3f (10, 100, 100);
1785 glVertex3f (10, -100, 100);
1786 glVertex3f (10, -100, -100);
1787 glVertex3f (10, 100, -100);
1788 glEnd ();
1789
1790 }
1791
1792 if (v_gamma.value != 1) //Gamma - Eradicator
1793 R_AdjustGamma();
1794
1795 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1796 glDisable (GL_BLEND);
1797 glEnable (GL_TEXTURE_2D);
1798 glEnable (GL_ALPHA_TEST);
1799 }
1800
1801
SignbitsForPlane(mplane_t * out)1802 int SignbitsForPlane (mplane_t *out)
1803 {
1804 int bits, j;
1805
1806 // for fast box on planeside test
1807
1808 bits = 0;
1809 for (j=0 ; j<3 ; j++)
1810 {
1811 if (out->normal[j] < 0)
1812 bits |= 1<<j;
1813 }
1814 return bits;
1815 }
1816
1817
R_SetFrustum(void)1818 void R_SetFrustum (void)
1819 {
1820 int i;
1821
1822 if (r_refdef.fov_x == 90)
1823 {
1824 // front side is visible
1825
1826 VectorAdd (vpn, vright, frustum[0].normal);
1827 VectorSubtract (vpn, vright, frustum[1].normal);
1828
1829 VectorAdd (vpn, vup, frustum[2].normal);
1830 VectorSubtract (vpn, vup, frustum[3].normal);
1831 }
1832 else
1833 {
1834 //Spedup Small Calculations - Eradicator
1835 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x * 0.5 ) );
1836 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x * 0.5 );
1837 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y * 0.5 );
1838 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y * 0.5 ) );
1839 }
1840
1841 for (i=0 ; i<4 ; i++)
1842 {
1843 frustum[i].type = PLANE_ANYZ;
1844 frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
1845 frustum[i].signbits = SignbitsForPlane (&frustum[i]);
1846 }
1847 }
1848
1849
1850
1851 /*
1852 ===============
1853 R_SetupFrame
1854 ===============
1855 */
R_SetupFrame(void)1856 void R_SetupFrame (void)
1857 {
1858
1859 // don't allow cheats in multiplayer
1860 if (cl.maxclients > 1)
1861 {
1862 Cvar_Set ("r_fullbright", "0");
1863 Cvar_Set ("gl_wireframe", "0"); //Disable this is multiplayer - Eradicator
1864 }
1865
1866 R_AnimateLight ();
1867
1868 r_framecount++;
1869
1870 // build the transformation matrix for the given view angles
1871 VectorCopy (r_refdef.vieworg, r_origin);
1872
1873 AngleVectors (r_refdef.viewangles, vpn, vright, vup);
1874
1875 // current viewleaf
1876 r_oldviewleaf = r_viewleaf;
1877 r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
1878
1879 V_SetContentsColor (r_viewleaf->contents);
1880 V_CalcBlend ();
1881
1882 r_cache_thrash = false;
1883
1884 c_brush_polys = 0;
1885 c_alias_polys = 0;
1886
1887 }
1888
1889 //PENTA: wasnt in math
1890 //<AWE> Unused. Remove it?
cotan(GLdouble angle)1891 GLdouble cotan(GLdouble angle) {
1892 return (cos(angle))/sin(angle);
1893 }
1894
1895 //PENTA: Matrix with infinite far clipping plane
1896 //<AWE> - optimized with static matrix.
1897 // - "nudge" is now defined as static const.
1898 // - p[2][3] was "-nudge" [causing heavy z-fighting on MacOS X], but has to be -1.0.
1899 // This issue indicates less precision on the Windows side.
1900 // - replaced the custom cotan () with 1.0 / tan () [cotan () = cos () / sin ()].
1901
1902 static const GLdouble nudge = 1.0 - 1.0 / ((GLdouble) (1<<23));
1903
pentaGlPerspective(GLdouble fov,GLdouble aspectr,GLdouble zNear)1904 void pentaGlPerspective (GLdouble fov, GLdouble aspectr, GLdouble zNear)
1905 {
1906 static GLdouble p[4][4] = {
1907 { 0.0, 0.0, 0.0, 0.0 },
1908 { 0.0, 0.0, 0.0, 0.0 },
1909 { 0.0, 0.0, 0.0, -1.0 },
1910 { 0.0, 0.0, 0.0, 0.0 }
1911 };
1912
1913 p[0][0] = 1.0 / (aspectr * tan (fov)); // <AWE> was: p[0][0] = cotan (fov) / aspectr;
1914 p[1][1] = 1.0 / tan (fov); // <AWE> was: p[1][1] = cotan (fov);
1915 p[2][2] = -nudge; // PM: changed again compile error otherwise
1916 p[3][2] = -2.0 * zNear * nudge;
1917
1918 glLoadMatrixd (&p[0][0]);
1919 }
1920
1921 //PENTA: Matrix with infinite far clipping plane
1922 //<AWE> Updated with "nudge". Unused. Remove it?
pentaGlFrustum(GLdouble xmin,GLdouble xmax,GLdouble ymin,GLdouble ymax,GLdouble zNear)1923 void pentaGlFrustum( GLdouble xmin, GLdouble xmax, GLdouble ymin, GLdouble ymax, GLdouble zNear)
1924 {
1925 static GLdouble p[4][4] = {
1926 { 0.0, 0.0, 0.0, 0.0 },
1927 { 0.0, 0.0, 0.0, 0.0 },
1928 { 0.0, 0.0, 0.0, -1.0 },
1929 { 0.0, 0.0, 0.0, 0.0 }
1930 };
1931
1932 p[0][0] = 2 * zNear / (xmax - xmin);
1933 p[1][1] = 2 * zNear / (ymax - ymin);
1934 p[2][2] = -nudge; // PM: changed again compile error otherwise
1935 p[2][0] = (xmax + xmin) / (xmax - xmin);
1936 p[2][1] = (ymax + ymin) / (ymax - ymin);
1937 p[3][2] = -2.0 * zNear * nudge; // <AWE> updated with MUL "nudge".
1938
1939 glLoadMatrixd(&p[0][0]);
1940 }
1941
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)1942 void MYgluPerspective( GLdouble fovy, GLdouble aspect,
1943 GLdouble zNear, GLdouble zFar )
1944 {
1945 /*
1946 <AWE> Unused. Can be removed.
1947 GLdouble xmin, xmax, ymin, ymax;
1948
1949 ymax = zNear * tan (fovy * M_PI / 360.0);
1950 ymin = -ymax;
1951
1952 xmin = ymin * aspect;
1953 xmax = ymax * aspect;
1954
1955 pentaGlFrustum( xmin, xmax, ymin, ymax, zNear);
1956 */
1957 pentaGlPerspective(fovy * M_PI / 360.0, aspect, zNear);
1958 }
1959
1960 /*
1961 PENTA:
1962 from http://www.markmorley.com/opengl/frustumculling.html
1963 Should clean it up by using procedures.
1964 */
1965 float frustumPlanes[6][4];
1966
ExtractFrustum()1967 void ExtractFrustum() // <AWE> added return type.
1968 {
1969 float proj[16];
1970 float modl[16];
1971 float clip[16];
1972 float t;
1973
1974 /* Get the current PROJECTION matrix from OpenGL */
1975 glGetFloatv( GL_PROJECTION_MATRIX, proj );
1976
1977 /* Get the current MODELVIEW matrix from OpenGL */
1978 glGetFloatv( GL_MODELVIEW_MATRIX, modl );
1979
1980 /* Combine the two matrices (multiply projection by modelview) */
1981 clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];
1982 clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];
1983 clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];
1984 clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];
1985
1986 clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];
1987 clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];
1988 clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];
1989 clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];
1990
1991 clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];
1992 clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];
1993 clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];
1994 clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];
1995
1996 clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];
1997 clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];
1998 clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];
1999 clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];
2000
2001 /* Extract the numbers for the RIGHT plane */
2002 frustumPlanes[0][0] = clip[ 3] - clip[ 0];
2003 frustumPlanes[0][1] = clip[ 7] - clip[ 4];
2004 frustumPlanes[0][2] = clip[11] - clip[ 8];
2005 frustumPlanes[0][3] = clip[15] - clip[12];
2006
2007 /* Normalize the result */
2008 t = sqrt( frustumPlanes[0][0] * frustumPlanes[0][0] + frustumPlanes[0][1] * frustumPlanes[0][1] + frustumPlanes[0][2] * frustumPlanes[0][2] );
2009 frustumPlanes[0][0] /= t;
2010 frustumPlanes[0][1] /= t;
2011 frustumPlanes[0][2] /= t;
2012 frustumPlanes[0][3] /= t;
2013
2014 /* Extract the numbers for the LEFT plane */
2015 frustumPlanes[1][0] = clip[ 3] + clip[ 0];
2016 frustumPlanes[1][1] = clip[ 7] + clip[ 4];
2017 frustumPlanes[1][2] = clip[11] + clip[ 8];
2018 frustumPlanes[1][3] = clip[15] + clip[12];
2019
2020 /* Normalize the result */
2021 t = sqrt( frustumPlanes[1][0] * frustumPlanes[1][0] + frustumPlanes[1][1] * frustumPlanes[1][1] + frustumPlanes[1][2] * frustumPlanes[1][2] );
2022 frustumPlanes[1][0] /= t;
2023 frustumPlanes[1][1] /= t;
2024 frustumPlanes[1][2] /= t;
2025 frustumPlanes[1][3] /= t;
2026
2027 /* Extract the BOTTOM plane */
2028 frustumPlanes[2][0] = clip[ 3] + clip[ 1];
2029 frustumPlanes[2][1] = clip[ 7] + clip[ 5];
2030 frustumPlanes[2][2] = clip[11] + clip[ 9];
2031 frustumPlanes[2][3] = clip[15] + clip[13];
2032
2033 /* Normalize the result */
2034 t = sqrt( frustumPlanes[2][0] * frustumPlanes[2][0] + frustumPlanes[2][1] * frustumPlanes[2][1] + frustumPlanes[2][2] * frustumPlanes[2][2] );
2035 frustumPlanes[2][0] /= t;
2036 frustumPlanes[2][1] /= t;
2037 frustumPlanes[2][2] /= t;
2038 frustumPlanes[2][3] /= t;
2039
2040 /* Extract the TOP plane */
2041 frustumPlanes[3][0] = clip[ 3] - clip[ 1];
2042 frustumPlanes[3][1] = clip[ 7] - clip[ 5];
2043 frustumPlanes[3][2] = clip[11] - clip[ 9];
2044 frustumPlanes[3][3] = clip[15] - clip[13];
2045
2046 /* Normalize the result */
2047 t = sqrt( frustumPlanes[3][0] * frustumPlanes[3][0] + frustumPlanes[3][1] * frustumPlanes[3][1] + frustumPlanes[3][2] * frustumPlanes[3][2] );
2048 frustumPlanes[3][0] /= t;
2049 frustumPlanes[3][1] /= t;
2050 frustumPlanes[3][2] /= t;
2051 frustumPlanes[3][3] /= t;
2052
2053 /* Extract the FAR plane */
2054 frustumPlanes[4][0] = clip[ 3] - clip[ 2];
2055 frustumPlanes[4][1] = clip[ 7] - clip[ 6];
2056 frustumPlanes[4][2] = clip[11] - clip[10];
2057 frustumPlanes[4][3] = clip[15] - clip[14];
2058
2059 /* Normalize the result */
2060 t = sqrt( frustumPlanes[4][0] * frustumPlanes[4][0] + frustumPlanes[4][1] * frustumPlanes[4][1] + frustumPlanes[4][2] * frustumPlanes[4][2] );
2061 frustumPlanes[4][0] /= t;
2062 frustumPlanes[4][1] /= t;
2063 frustumPlanes[4][2] /= t;
2064 frustumPlanes[4][3] /= t;
2065
2066 /* Extract the NEAR plane */
2067 frustumPlanes[5][0] = clip[ 3] + clip[ 2];
2068 frustumPlanes[5][1] = clip[ 7] + clip[ 6];
2069 frustumPlanes[5][2] = clip[11] + clip[10];
2070 frustumPlanes[5][3] = clip[15] + clip[14];
2071
2072 /* Normalize the result */
2073 t = sqrt( frustumPlanes[5][0] * frustumPlanes[5][0] + frustumPlanes[5][1] * frustumPlanes[5][1] + frustumPlanes[5][2] * frustumPlanes[5][2] );
2074 frustumPlanes[5][0] /= t;
2075 frustumPlanes[5][1] /= t;
2076 frustumPlanes[5][2] /= t;
2077 frustumPlanes[5][3] /= t;
2078 }
2079
2080 /*
2081 =============
2082 R_SetupGL
2083 =============
2084 */
R_SetupGL(void)2085 void R_SetupGL (void)
2086 {
2087 float screenaspect;
2088 extern int glwidth, glheight;
2089 int x, x2, y2, y, w, h;
2090
2091 //
2092 // set up viewpoint
2093 //
2094 glMatrixMode(GL_PROJECTION);
2095 glLoadIdentity ();
2096 x = r_refdef.vrect.x * glwidth/vid.width;
2097 x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
2098 y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
2099 y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
2100
2101 // fudge around because of frac screen scale
2102 if (x > 0)
2103 x--;
2104 if (x2 < glwidth)
2105 x2++;
2106 if (y2 < 0)
2107 y2--;
2108 if (y < glheight)
2109 y++;
2110
2111 w = x2 - x;
2112 h = y - y2;
2113
2114 if (envmap || mirror || glare)
2115 {
2116 x = y2 = 0;
2117 w = r_refdef.vrect.width;
2118 h = r_refdef.vrect.height;
2119 }
2120
2121 glViewport (glx + x, gly + y2, w, h);
2122
2123 screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
2124 if (mirror) screenaspect = 1.0;
2125 // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
2126 //PENTA: decreased zfar from 4096 to reduce z-fighting on alias models
2127 // is this ok for quake or do we need to be able to look that far??
2128 // seems to work, I incr. znear to 5 instead of 4
2129 MYgluPerspective (2.0 *atan((GLdouble) r_refdef.vrect.height / (GLdouble) r_refdef.vrect.width) * 180.0 / M_PI /* r_refdef.fov_y */, screenaspect, 5.0, 2048.0);
2130
2131 if (mirror || glare)
2132 {
2133 //If we are mirroring we want to use the screen projection matrix
2134 //not the texture (=> we just calculated this) one.
2135 glLoadIdentity();
2136 glMultMatrixf(r_projection_matrix);
2137
2138 if (mirror){
2139 if (mirror_plane->normal[2])
2140 glScalef (1, -1, 1);
2141 else
2142 glScalef (-1, 1, 1);
2143 }
2144 } else {
2145 //Store it for later mirror use
2146 glGetFloatv (GL_PROJECTION_MATRIX, r_projection_matrix);
2147 }
2148
2149
2150 glMatrixMode(GL_MODELVIEW);
2151 glLoadIdentity ();
2152
2153 glRotatef (-90, 1, 0, 0); // put Z going up
2154 glRotatef (90, 0, 0, 1); // put Z going up
2155 glRotatef (-r_refdef.viewangles[2], 1, 0, 0);
2156 glRotatef (-r_refdef.viewangles[0], 0, 1, 0);
2157 glRotatef (-r_refdef.viewangles[1], 0, 0, 1);
2158 glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
2159
2160 glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
2161 glGetDoublev (GL_MODELVIEW_MATRIX, r_Dworld_matrix);
2162 glGetDoublev (GL_PROJECTION_MATRIX, r_Dproject_matrix);
2163 glGetIntegerv (GL_VIEWPORT, (GLint *) r_Iviewport); // <AWE> added cast.
2164 ExtractFrustum();
2165 //
2166 // set drawing parms
2167 //
2168 if (gl_cull.value)
2169 glEnable(GL_CULL_FACE);
2170 else
2171 glDisable(GL_CULL_FACE);
2172
2173 glDisable(GL_BLEND);
2174 glDisable(GL_ALPHA_TEST);
2175 glEnable(GL_DEPTH_TEST);
2176 }
2177
2178 /*
2179 ================
2180 R_RenderScene
2181
2182 r_refdef must be set before the first call
2183 ================
2184 */
R_RenderScene(void)2185 void R_RenderScene (void)
2186 {
2187 int i, j;
2188 shadowlight_t *l = NULL;
2189
2190 R_SetupFrame ();
2191
2192 R_SetFrustum ();
2193
2194 R_SetupGL ();
2195
2196 R_MarkLeaves (); // done here so we know if we're in water, gaat visible leafs marken
2197
2198 //if (!mirror)
2199 R_InitShadowsForFrame ();
2200
2201 R_InitDrawWorld();
2202
2203 //if (!mirror) {
2204 //To ensure invariance we have to enable scissoring even for the ambient term
2205 //But in reality this doen't work (at least on my Geforce2 card) and you still
2206 //get (few) z-buffer fighting.
2207 if (!sh_noscissor.value) {
2208 glScissor(r_Iviewport[0], r_Iviewport[1], r_Iviewport[2], r_Iviewport[3]);
2209 glEnable(GL_SCISSOR_TEST);
2210 }
2211
2212 //Ambient light drawing
2213 //this uses the light maps as an ambient term
2214 //it fills the z buffer
2215 R_SetupInstants();
2216
2217
2218 //XYZ - moved upwards
2219 if (gl_wireframe.value) {
2220 float old = sh_lightmapbright.value;
2221 sh_lightmapbright.value = 1.0;
2222 glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
2223
2224 R_DrawAmbientEntities();
2225 //glDisable(GL_TEXTURE_2D);
2226 R_WorldMultiplyTextures();
2227 glEnable(GL_TEXTURE_2D);
2228 sh_lightmapbright.value = old;
2229 glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
2230 return;
2231 }
2232
2233 R_DrawViewModel();
2234 R_DrawAmbientEntities();
2235 glDepthFunc(GL_LEQUAL);
2236
2237 R_WorldMultiplyTextures();
2238
2239 //if (mirror) {
2240 // sh_lightmapbright.value = 0.3;
2241 // return;
2242 //}
2243
2244 if (!sh_noscissor.value) {
2245 glClear(GL_STENCIL_BUFFER_BIT);
2246 R_ClearRectList();
2247 }
2248
2249 numClearsSaved = 0;
2250 aliasCacheRequests = aliasFullCacheHits = aliasPartialCacheHits = 0;
2251 brushCacheRequests = brushFullCacheHits = brushPartialCacheHits = 0;
2252
2253 glFogfv(GL_FOG_COLOR, color_black);
2254
2255 for (i=0; i<numUsedShadowLights; i++) {
2256
2257 //find a lights that still fits on our current screen plane
2258 //using the first fit method.
2259 //Other methods may give better results (exhaustive for example)
2260 //but i'm convinced you can't save more clears than those that you
2261 //save with this.
2262 if ((!sh_nocleversave.value) && (!sh_noscissor.value)) {
2263 qboolean foundone = false;
2264 for (j=0; j<numUsedShadowLights; j++) {
2265
2266 if (!usedshadowlights[j]->visible) continue;
2267
2268 l = usedshadowlights[j];
2269 currentshadowlight = l;
2270 if (R_CheckRectList(&l->scizz)) {
2271 foundone = true;
2272 break;
2273 }
2274 }
2275
2276 if (!foundone) {
2277 R_SetTotalRect(); //Only clear dirty part
2278 glClear(GL_STENCIL_BUFFER_BIT);
2279 R_ClearRectList();
2280 for (j=0; j<numUsedShadowLights; j++) {
2281 l = usedshadowlights[j];
2282 currentshadowlight = l;
2283 if (usedshadowlights[j]->visible) break;
2284 }
2285 }
2286
2287 } else {
2288 l = usedshadowlights[i];
2289 currentshadowlight = l;
2290 }
2291
2292 //Find the polygons that cast shadows for this light
2293 if (!R_FillShadowChain(l))
2294 continue;
2295
2296 if (sh_visiblevolumes.value) {
2297 glDepthFunc(GL_LEQUAL);
2298 glDepthMask(GL_TRUE);
2299 } else {
2300 glDepthMask(GL_FALSE);
2301
2302 if (l->castShadow) {
2303 glDepthFunc(GL_LESS);
2304 glEnable(GL_STENCIL_TEST);
2305 //glClear(GL_STENCIL_BUFFER_BIT);
2306 glColorMask(false, false, false, false);
2307 glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
2308 if (!sh_noscissor.value) {
2309 if (R_CheckRectList(&l->scizz)) {
2310 //we can have another go without clearing
2311 R_AddRectList(&l->scizz);
2312 numClearsSaved++;
2313
2314 } else {
2315 R_SetTotalRect(); //Only clear dirty part
2316 glClear(GL_STENCIL_BUFFER_BIT);
2317 R_ClearRectList();
2318 R_AddRectList(&l->scizz);
2319 }
2320 } else {
2321 glClear(GL_STENCIL_BUFFER_BIT);
2322 }
2323 }
2324 }
2325
2326 //All right now the shadow stuff
2327
2328 glScissor(l->scizz.coords[0], l->scizz.coords[1],
2329 l->scizz.coords[2]-l->scizz.coords[0], l->scizz.coords[3]-l->scizz.coords[1]);
2330
2331 R_MarkEntitiesOnList();
2332
2333 //Shadow casting is on by default
2334 if (l->castShadow) {
2335 //Calculate the shadow volume (does nothing when static)
2336 R_ConstructShadowVolume(l);
2337
2338 #if 1
2339 //Pass 1 increase
2340 glCullFace(GL_BACK);
2341 glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
2342 if (sh_worldshadows.value) R_DrawShadowVolume(l);
2343
2344 // Second Pass. Decrease Stencil Value In The Shadow
2345 glCullFace(GL_FRONT);
2346 glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
2347 if (sh_worldshadows.value) R_DrawShadowVolume(l);
2348
2349 //PENTA: we could do the same thing for brushes as for aliasses
2350 //Pass 1 increase
2351 glCullFace(GL_BACK);
2352 glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
2353 if (sh_entityshadows.value) R_DrawEntitiesShadowVolumes(mod_brush);
2354
2355 // Second Pass. Decrease Stencil Value In The Shadow
2356 glCullFace(GL_FRONT);
2357 glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
2358 if (sh_entityshadows.value) R_DrawEntitiesShadowVolumes(mod_brush);
2359
2360 #else
2361 // glCullFace(GL_FRONT_AND_BACK);
2362 glDisable(GL_CULL_FACE);
2363 checkerror();
2364 glStencilOp(GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
2365 checkerror();
2366 qglStencilFuncSeparateATI(GL_ALWAYS, GL_ALWAYS, 0, ~0);
2367 checkerror();
2368 qglStencilOpSeparateATI(GL_FRONT, GL_KEEP, GL_DECR_WRAP_EXT, GL_KEEP);
2369 checkerror();
2370 qglStencilOpSeparateATI(GL_BACK, GL_KEEP, GL_INCR_WRAP_EXT, GL_KEEP);
2371 checkerror();
2372
2373 if (sh_worldshadows.value) R_DrawShadowVolume(l);
2374
2375 //PENTA: we could do the same thing for brushes as for aliasses
2376 //Pass 1 increase
2377 if (sh_entityshadows.value) R_DrawEntitiesShadowVolumes(mod_brush);
2378
2379 glEnable(GL_CULL_FACE);
2380 #endif
2381 if (sh_entityshadows.value)
2382 R_DrawEntitiesShadowVolumes(mod_alias);
2383
2384 //Reenable drawing
2385 glCullFace(GL_FRONT);
2386 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2387 glDepthFunc(GL_LEQUAL);
2388 glStencilFunc(GL_EQUAL, 0, 0xffffffff);
2389 }
2390 if (!sh_visiblevolumes.value) {
2391 R_DrawWorldBumped();
2392 glPolygonOffset(0,-5);
2393 glEnable(GL_POLYGON_OFFSET_FILL);
2394 R_DrawLightEntities(l);
2395 glDisable(GL_POLYGON_OFFSET_FILL);
2396 }
2397 glDisable (GL_BLEND);
2398 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2399 glDisable(GL_STENCIL_TEST);
2400
2401 //sprites only recive "shadows" from the cubemap not the stencil
2402
2403 if (!sh_visiblevolumes.value) {
2404 R_DrawLightSprites ();
2405 }
2406
2407 glDepthMask(GL_TRUE);
2408
2409 if ((i%8) == 0)
2410 // don't let sound get messed up if going slow
2411 S_ExtraUpdate ();
2412
2413 l->visible = false;
2414 }
2415
2416 glScissor(0, 0, r_Iviewport[2], r_Iviewport[3]);
2417 glDisable(GL_SCISSOR_TEST);
2418
2419 glDepthFunc(GL_LEQUAL);
2420
2421 GL_DisableMultitexture();
2422
2423 glFogfv(GL_FOG_COLOR, color_black);
2424
2425 R_DrawFullbrightSprites();
2426
2427 if (skytexturenum >= 0) {
2428 glColor3f(1,1,1);
2429 R_DrawSkyChain (cl.worldmodel->textures[skytexturenum]->texturechain);
2430 cl.worldmodel->textures[skytexturenum]->texturechain = NULL;
2431 }
2432
2433
2434 R_DrawCaustics();
2435
2436 //Removed to fix particle & water bug (see R_RenderView) - Eradicator
2437 //R_DrawParticles (); //to fix the particles triangles showing up after water
2438 //put this behind the water drawing#ifdef GLTEST
2439 R_DrawDecals();
2440
2441 glFogfv(GL_FOG_COLOR, fog_color);
2442 }
2443
R_InitMirrorChains()2444 void R_InitMirrorChains()
2445 {
2446 int i;
2447
2448 for (i=0; i<NUM_MIRROR_PLANES; i++) {
2449 mirrorplanes[i].texture_object = EasyTgaLoad("penta/mirrordummy.tga");
2450 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
2451 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
2452 }
2453
2454 }
2455
2456
R_NewMirrorChains()2457 void R_NewMirrorChains()
2458 {
2459 int i;
2460
2461 for (i=0; i<NUM_MIRROR_PLANES; i++) {
2462 mirrorplanes[i].lockframe = 0;
2463 mirrorplanes[i].updateframe = 0;
2464 mirrorplanes[i].chain = NULL;
2465 }
2466
2467 }
2468
2469
R_ClearMirrorChains()2470 void R_ClearMirrorChains()
2471 {
2472 int i;
2473
2474 for (i=0; i<NUM_MIRROR_PLANES; i++) {
2475 mirrorplanes[i].chain = NULL;
2476 }
2477
2478 for (i=0 ; i<cl.worldmodel->numtextures ; i++)
2479 {
2480 if (!cl.worldmodel->textures[i])
2481 continue;
2482 cl.worldmodel->textures[i]->texturechain = NULL;
2483 }
2484 }
2485
R_AllocateMirror(msurface_t * surf)2486 void R_AllocateMirror(msurface_t *surf)
2487 {
2488 int i,oldest,oindex;
2489 mirrorplane_t *mir = NULL;
2490 vec3_t tempnormal;
2491
2492 //#define NUM_MIRROR_PLANES 8
2493 //extern mirrorplane_t mirrorplanes[NUM_MIRROR_PLANES];
2494
2495 //see if surface is part of an existing mirror
2496 for (i=0; i<NUM_MIRROR_PLANES; i++) {
2497
2498 VectorCopy(surf->plane->normal,tempnormal);
2499 //if (surf->flags & SURF_PLANEBACK) {
2500 // VectorInverse(tempnormal);
2501 //}
2502
2503 if ((tempnormal[0] == mirrorplanes[i].plane.normal[0]) &&
2504 (tempnormal[1] == mirrorplanes[i].plane.normal[1]) &&
2505 (tempnormal[2] == mirrorplanes[i].plane.normal[2]) &&
2506 (surf->plane->dist == mirrorplanes[i].plane.dist))
2507 {
2508 mir = &mirrorplanes[i];
2509 //Con_Printf("reuse mir %i\n",i);
2510 break;
2511 }
2512 }
2513
2514 //allocate new mirror
2515 if (!mir) {
2516 oldest = r_framecount;
2517 oindex = -1;
2518 for (i=0; i<NUM_MIRROR_PLANES; i++) {
2519 if (mirrorplanes[i].lockframe < oldest) {
2520 oldest = mirrorplanes[i].lockframe;
2521 oindex = i;
2522 }
2523 }
2524
2525 if (oindex == -1) {
2526 //Be silent about this
2527 return;
2528 }
2529
2530 mir = &mirrorplanes[oindex];
2531 VectorCopy(surf->plane->normal,mir->plane.normal);
2532 //if (surf->flags & SURF_PLANEBACK) {
2533 // VectorInverse(mir->plane.normal);
2534 //}
2535 mir->plane.dist = surf->plane->dist;
2536 mir->plane.type = surf->plane->type;
2537 mir->plane.signbits = surf->plane->signbits;
2538 //Con_Printf("New mirror: n: %f %f %f d:%f\n i: %i",mir->plane.normal[0],mir->plane.normal[1],mir->plane.normal[2],mir->plane.dist,oindex);
2539 }
2540
2541 mir->lockframe = r_framecount;
2542 surf->texturechain = mir->chain;
2543 mir->chain = surf;
2544 }
2545 /*
2546 =============
2547 R_Mirror
2548 =============
2549 */
R_Mirror(mirrorplane_t * mir)2550 void R_Mirror (mirrorplane_t *mir)
2551 {
2552 float d, olddrawents = 0.0f;
2553 entity_t *ent;
2554 int ox, oy, ow, oh, ofovx, ofovy, cl_oldvisedicts;
2555 vec3_t oang, oorg;
2556 qboolean drawplayer;
2557
2558 if (mirror) {
2559 Con_Printf("Warning: Resursive mirrors\n");
2560 return;
2561 }
2562
2563 mirror = true;
2564 mirror_plane = &mir->plane;
2565 memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix));
2566
2567 AngleVectors (r_refdef.viewangles, vpn, vright, vup);
2568
2569 //setup mirrored view origin & direction
2570 VectorCopy(r_refdef.vieworg, oorg);
2571 d = DotProduct (r_refdef.vieworg, mir->plane.normal) - mir->plane.dist;
2572
2573 //camera is to far away from mirror don't update it...
2574 if (abs(d) > mir_distance.value) {
2575 mirror = false;
2576 return;
2577 }
2578
2579 //player is very close to mirror don't draw it since he interects it and this gives bad artefacts
2580 if (abs(d) < MIN_PLAYER_MIRROR) {
2581 drawplayer = false;
2582 } else {
2583 drawplayer = true;
2584 }
2585
2586 //calculate a far plane for the mirror, stuff to far away from mirrors is not drawn anymore...
2587 VectorCopy(mir->plane.normal,mirror_far_plane.normal);
2588 //VectorInverse(mirror_far_plane.normal);
2589 mirror_far_plane.dist = DotProduct(r_refdef.vieworg,mir->plane.normal) + mir_distance.value;
2590
2591 VectorMA (r_refdef.vieworg, -2*d, mir->plane.normal, r_refdef.vieworg);
2592
2593 if (d < 0) {
2594 mirror_clipside = 1;
2595 } else {
2596 mirror_clipside = 2;
2597 }
2598
2599 d = DotProduct (vpn, mir->plane.normal);
2600 VectorMA (vpn, -2*d, mir->plane.normal, vpn);
2601
2602 VectorCopy(r_refdef.viewangles, oang);
2603 r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180;
2604 r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180;
2605 r_refdef.viewangles[2] = -r_refdef.viewangles[2];
2606
2607 //Render to a small view rectangle
2608 ox = r_refdef.vrect.x;
2609 oy = r_refdef.vrect.y;
2610 ow = r_refdef.vrect.width;
2611 oh = r_refdef.vrect.height;
2612 ofovx = r_refdef.fov_x;
2613 ofovy = r_refdef.fov_y;
2614 r_refdef.vrect.x = 0;
2615 r_refdef.vrect.y = 0;
2616 r_refdef.vrect.width = 256;
2617 r_refdef.vrect.height = 256;
2618
2619
2620 // r_refdef.fov_x = 90.0;
2621 // r_refdef.fov_y = 90.0;//CalcFov (90.0, r_refdef.vrect.width, r_refdef.vrect.height);
2622 r_refdef.fov_x = scr_fov.value;
2623 r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.vrect.width, r_refdef.vrect.height);
2624
2625
2626 //Note: This was probably already a problem with the original quake mirrors
2627 //the static entities are added in all mirror passes making that by the end of
2628 //mirror rendering we are rendering the statics multiple times.
2629 //so we back up the number of entities (dynamics are in front) and later restore it
2630 cl_oldvisedicts = cl_numvisedicts;
2631
2632
2633 olddrawents = r_drawentities.value;
2634 if (mir_detail.value < 2) {
2635 //Don't draw entities
2636 r_drawentities.value = 0;
2637 } else {
2638 //Hack add player to back of list
2639 if (drawplayer && cl_entities[cl.viewentity].model && cl_entities[cl.viewentity].model->type == mod_alias) {
2640 ent = &cl_entities[cl.viewentity];
2641 if (cl_numvisedicts < MAX_VISEDICTS)
2642 {
2643 cl_visedicts[cl_numvisedicts] = ent;
2644 cl_numvisedicts++;
2645 }
2646 }
2647 }
2648 //r_drawentities.value = 0;
2649
2650 glFrontFace(GL_CW);
2651 //R_RenderView ();
2652 //Con_Printf("Render mirror\n");
2653
2654 //olddrawents = r_drawentities.value;
2655 //r_drawentities.value = mir_detail.value-1;
2656
2657
2658 R_RenderScene ();
2659
2660 r_drawentities.value = olddrawents;
2661
2662 Q_memcpy (mir->matrix, r_world_matrix, sizeof(r_world_matrix));
2663
2664 GL_Bind(mir->texture_object);
2665 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 256, 256);
2666 glClear (GL_DEPTH_BUFFER_BIT);
2667
2668
2669 if (mir_detail.value < 2) {
2670 r_drawentities.value = olddrawents;
2671 }
2672
2673 // r_drawentities.value = 1;
2674
2675 r_refdef.vrect.x = ox;
2676 r_refdef.vrect.y = oy;
2677 r_refdef.vrect.width = ow;
2678 r_refdef.vrect.height = oh;
2679 r_refdef.fov_x = ofovx;
2680 r_refdef.fov_y = ofovy;
2681
2682 cl_numvisedicts = cl_oldvisedicts;
2683
2684 VectorCopy(oorg, r_refdef.vieworg);
2685 VectorCopy(oang, r_refdef.viewangles);
2686
2687 // blend on top
2688 /*
2689 glMatrixMode(GL_PROJECTION);
2690 if (mir->plane.normal[2])
2691 glScalef (1,-1,1);
2692 else
2693 glScalef (-1,1,1);
2694 */
2695 glFrontFace(GL_CCW);
2696 glMatrixMode(GL_MODELVIEW);
2697
2698 //glLoadMatrixf (r_base_world_matrix);
2699 memcpy(r_world_matrix, r_base_world_matrix, sizeof(r_base_world_matrix));
2700
2701 mirror = false;
2702 Sbar_Changed ();
2703 }
2704
R_RenderMirrors()2705 void R_RenderMirrors()
2706 {
2707 int i;
2708 for (i=0; i<NUM_MIRROR_PLANES; i++) {
2709 if (mirrorplanes[i].chain && ((r_framecount - mirrorplanes[i].updateframe) > mir_frameskip.value)) {
2710 R_Mirror(&mirrorplanes[i]);
2711 mirrorplanes[i].lockframe = r_framecount;
2712 mirrorplanes[i].updateframe = r_framecount;
2713 }
2714 }
2715 }
2716
R_SetupMirrorShader(msurface_t * surf,mirrorplane_t * mir)2717 void R_SetupMirrorShader(msurface_t *surf,mirrorplane_t *mir) {
2718
2719 if (mir_detail.value < 1) {
2720 GL_Bind(newenvmap);
2721 } else
2722 GL_Bind(mir->texture_object);
2723
2724 if ((surf->flags & SURF_DRAWTURB) && !(surf->flags & SURF_GLASS)) {
2725 //it is water
2726 //glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
2727 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
2728 glEnable(GL_BLEND);
2729 return;
2730 } else {
2731
2732 if (surf->flags & SURF_DRAWTURB) {
2733 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
2734 glEnable(GL_BLEND);
2735 return;
2736 }
2737
2738 //it is glass or a mirror
2739 //GL_EnableMultiTexture();
2740 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
2741 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);
2742 glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
2743
2744 GL_EnableMultitexture();
2745 GL_Bind(surf->texinfo->texture->gl_texturenum);
2746
2747 //No colormaps: Color maps are bound on tmu 0 so disable it
2748 //and let tu1 modulate itself with the light map brightness
2749 glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
2750 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB);
2751 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_TEXTURE);
2752 glTexEnvf (GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);
2753 glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_INTERPOLATE_ARB);
2754 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_ALPHA);
2755
2756 GL_Bind(surf->texinfo->texture->gl_texturenum);
2757 }
2758 }
2759
R_DisableMirrorShader(msurface_t * surf,mirrorplane_t * mir)2760 void R_DisableMirrorShader(msurface_t *surf,mirrorplane_t *mir) {
2761
2762
2763 if ((surf->flags & SURF_DRAWTURB) && !(surf->flags & SURF_GLASS)) {
2764 //it is water
2765 glDisable(GL_BLEND);
2766 return;
2767 } else {
2768
2769 if (surf->flags & SURF_DRAWTURB) {
2770 glDisable(GL_BLEND);
2771 return;
2772 }
2773
2774 glTexEnvf (GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, GL_SRC_COLOR);
2775 GL_DisableMultitexture();
2776 }
2777 }
2778
R_DrawMirrorSurfaces()2779 void R_DrawMirrorSurfaces()
2780 {
2781 int i;
2782 msurface_t *s;
2783
2784 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
2785 for (i=0; i<NUM_MIRROR_PLANES; i++) {
2786 if (mirrorplanes[i].chain) {
2787
2788 glMatrixMode(GL_TEXTURE);
2789
2790 glPushMatrix();
2791 if (mir_detail.value > 0) {
2792 glLoadIdentity();
2793 glTranslatef(0.5, 0.5, 0);
2794 glScalef(0.5, 0.5, 0);
2795 glMultMatrixf (r_projection_matrix);
2796 glMultMatrixf (r_world_matrix);
2797 } else {
2798 //glMultMatrixf (r_projection_matrix);
2799 glTranslatef(r_refdef.vieworg[0]/1000,r_refdef.vieworg[1]/1000,r_refdef.vieworg[2]/1000);
2800 glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
2801 glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP);
2802 glEnable(GL_TEXTURE_GEN_S);
2803 glEnable(GL_TEXTURE_GEN_T);
2804 }
2805
2806 R_SetupMirrorShader(mirrorplanes[i].chain,&mirrorplanes[i]);
2807
2808 s = mirrorplanes[i].chain;
2809
2810 glNormal3fv(mirrorplanes[i].plane.normal);
2811 for ( ; s ; s=s->texturechain) {
2812 if ((s->flags & SURF_GLASS) && (s->flags & SURF_DRAWTURB)) {
2813 glColor4f(1,1,1,0.5);
2814 EmitMirrorPolys (s);
2815 } else if (s->flags & SURF_DRAWTURB) {
2816 glColor4f(1,1,1,r_wateralpha.value);
2817 EmitMirrorWaterPolys (s);
2818 } else {
2819 glColor4f(1,1,1,1);
2820 EmitMirrorPolys (s);
2821 }
2822 }
2823
2824 R_DisableMirrorShader(mirrorplanes[i].chain,&mirrorplanes[i]);
2825
2826 glPopMatrix();
2827 if (mir_detail.value == 0) {
2828 glDisable(GL_TEXTURE_GEN_S);
2829 glDisable(GL_TEXTURE_GEN_T);
2830 }
2831 glMatrixMode(GL_MODELVIEW);
2832 }
2833 }
2834 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
2835 }
2836
2837 /*
2838 =============
2839 R_Clear
2840 =============
2841 */
R_Clear(void)2842 void R_Clear (void)
2843 {
2844 /*if (r_mirroralpha.value != 1.0)
2845 {
2846 if (gl_clear.value)
2847 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2848 else
2849 glClear (GL_DEPTH_BUFFER_BIT);
2850 gldepthmin = 0;
2851 gldepthmax = 0.5;
2852 glDepthFunc (GL_LEQUAL);
2853 }
2854 else if (gl_ztrick.value) PENTA: Removed
2855 {
2856 static int trickframe;
2857
2858 if (gl_clear.value)
2859 glClear (GL_COLOR_BUFFER_BIT);
2860
2861 trickframe++;
2862 if (trickframe & 1)
2863 {
2864 gldepthmin = 0;
2865 gldepthmax = 0.49999;
2866 glDepthFunc (GL_LEQUAL);
2867 }
2868 else
2869 {
2870 gldepthmin = 1;
2871 gldepthmax = 0.5;
2872 glDepthFunc (GL_GEQUAL);
2873 }
2874 }
2875 else*/
2876
2877 {
2878 if (gl_clear.value || gl_wireframe.value)
2879 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2880 else
2881 glClear (GL_DEPTH_BUFFER_BIT);
2882 gldepthmin = 0;
2883 gldepthmax = 1;
2884 glDepthFunc (GL_LEQUAL);
2885 }
2886
2887 glDepthRange (gldepthmin, gldepthmax);
2888 }
2889
2890 /*
2891 ================
2892 R_RenderView
2893
2894 r_refdef must be set before the first call
2895 ================
2896 */
R_RenderView(void)2897 void R_RenderView (void)
2898 {
2899 double time1 = 0.0, time2;
2900 GLfloat colors[4] = {(GLfloat) 0.2, (GLfloat) 0.1, (GLfloat) 0.0, (GLfloat) 0.20};
2901 float oldfogen;
2902 int viewcont;
2903
2904 if (r_norefresh.value)
2905 return;
2906
2907 if (!r_worldentity.model || !cl.worldmodel)
2908 Sys_Error ("R_RenderView: NULL worldmodel");
2909
2910 mirror = false;
2911
2912
2913 if (gl_finish.value)
2914 glFinish ();
2915
2916 R_Clear ();
2917
2918 viewcont = CL_PointContents(r_origin);
2919 fog_color[3] = 1.0;
2920 if ((viewcont == CONTENTS_WATER) && (fog_waterfog.value)){
2921 glFogi(GL_FOG_MODE, GL_LINEAR);
2922 fog_color[0] = 64/255.0;
2923 fog_color[1] = 48/255.0;
2924 fog_color[2] = 0.0;
2925 glFogfv(GL_FOG_COLOR, fog_color);
2926 glFogf(GL_FOG_END, 512);
2927 glFogf(GL_FOG_START, 0);
2928 glEnable(GL_FOG);
2929 oldfogen = fog_enabled.value;
2930 fog_enabled.value = 1.0;
2931 } else if ((viewcont == CONTENTS_SLIME) && (fog_waterfog.value)){
2932 glFogi(GL_FOG_MODE, GL_LINEAR);
2933 fog_color[0] = 0.0;
2934 fog_color[1] = 128/255.0;
2935 fog_color[2] = 32/255.0;
2936 glFogfv(GL_FOG_COLOR, fog_color);
2937 glFogf(GL_FOG_END, 256);
2938 glFogf(GL_FOG_START, 0);
2939 glEnable(GL_FOG);
2940 oldfogen = fog_enabled.value;
2941 fog_enabled.value = 1.0;
2942 } else if ((viewcont == CONTENTS_LAVA) && (fog_waterfog.value)){
2943 glFogi(GL_FOG_MODE, GL_LINEAR);
2944 fog_color[0] = 255/255.0;
2945 fog_color[1] = 64/255.0;
2946 fog_color[2] = 0.0;
2947 glFogfv(GL_FOG_COLOR, fog_color);
2948 glFogf(GL_FOG_END, 256);
2949 glFogf(GL_FOG_START, 0);
2950 glEnable(GL_FOG);
2951 oldfogen = fog_enabled.value;
2952 fog_enabled.value = 1.0;
2953
2954 } else {
2955 glFogi(GL_FOG_MODE, GL_LINEAR);
2956 fog_color[0] = fog_r.value/255.0;
2957 fog_color[1] = fog_g.value/255.0;
2958 fog_color[2] = fog_b.value/255.0;
2959 glFogfv(GL_FOG_COLOR, fog_color);
2960 glFogf(GL_FOG_END, fog_end.value);
2961 glFogf(GL_FOG_START, fog_start.value);
2962 if (fog_enabled.value && !gl_wireframe.value)
2963 glEnable(GL_FOG);
2964 }
2965
2966 if (mir_detail.value > 0) {
2967 R_RenderMirrors();
2968 // glClear (GL_DEPTH_BUFFER_BIT);
2969 }
2970
2971 R_ClearMirrorChains();
2972
2973 R_Glare ();
2974
2975 R_ClearMirrorChains();
2976
2977 // render normal view
2978
2979 R_RenderScene ();
2980 //R_DrawViewModel ();
2981
2982 /*Rendering fog in black for particles is done to stop triangle effect on the
2983 particles. It is done right before and fixed after each particle draw function
2984 to avoid effection fog on the water. A particle draw is done after the water
2985 draw to make sure particles are rendered over the surface of the water. - Eradicator*/
2986
2987 R_DrawWaterSurfaces ();
2988 R_DrawMirrorSurfaces ();
2989
2990 // More fog right here :)
2991
2992 if ((viewcont == CONTENTS_WATER) && (fog_waterfog.value)){
2993 fog_enabled.value = oldfogen;
2994 }
2995 glDisable(GL_FOG);
2996 // End of all fog code...
2997
2998 //glFogfv(GL_FOG_COLOR, color_black); //Stops triangle effect on particles
2999 R_DrawParticles (); //Fixes particle & water bug
3000 //glFogfv(GL_FOG_COLOR, fog_color); //Real fog colour
3001
3002 //Draw a poly over the screen (underwater, slime, blood hit)
3003 R_DrawGlare() ;
3004 R_PolyBlend ();
3005 }
3006