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
34 mplane_t frustum[4];
35
36 int c_brush_polys, c_alias_polys;
37
38 qboolean envmap; // true during envmap command capture
39
40 int currenttexture = -1; // to avoid unnecessary texture sets
41
42 int cnttextures[2] = {-1, -1}; // cached
43
44 int particletexture; // little dot for particles
45 int playertextures; // up to 16 color translated skins
46
47 int mirrortexturenum; // quake texturenum, not gltexturenum
48 qboolean mirror;
49 mplane_t *mirror_plane;
50
51 //
52 // view origin
53 //
54 vec3_t vup;
55 vec3_t vpn;
56 vec3_t vright;
57 vec3_t r_origin;
58
59 float r_world_matrix[16];
60 float r_base_world_matrix[16];
61
62 //
63 // screen size info
64 //
65 refdef_t r_refdef;
66
67 mleaf_t *r_viewleaf, *r_oldviewleaf;
68
69 texture_t *r_notexture_mip;
70
71 int d_lightstylevalue[256]; // 8.8 fraction of base light value
72
73
74 void R_MarkLeaves (void);
75
76 cvar_t r_norefresh = CVAR2("r_norefresh","0");
77 cvar_t r_drawentities = CVAR2("r_drawentities","1");
78 cvar_t r_drawviewmodel = CVAR2("r_drawviewmodel","1");
79 cvar_t r_speeds = CVAR2("r_speeds","0");
80 cvar_t r_fullbright = CVAR2("r_fullbright","0");
81 cvar_t r_lightmap = CVAR2("r_lightmap","0");
82 cvar_t r_shadows = CVAR2("r_shadows","0");
83 cvar_t r_mirroralpha = CVAR2("r_mirroralpha","1");
84 cvar_t r_wateralpha = CVAR2("r_wateralpha","1");
85 cvar_t r_dynamic = CVAR2("r_dynamic","1");
86 cvar_t r_novis = CVAR2("r_novis","0");
87
88 cvar_t gl_finish = CVAR2("gl_finish","0");
89 cvar_t gl_clear = CVAR2("gl_clear","0");
90 cvar_t gl_cull = CVAR2("gl_cull","1");
91 cvar_t gl_texsort = CVAR2("gl_texsort","1");
92 cvar_t gl_smoothmodels = CVAR2("gl_smoothmodels","1");
93 cvar_t gl_affinemodels = CVAR2("gl_affinemodels","1");
94 cvar_t gl_polyblend = CVAR2("gl_polyblend","1");
95 cvar_t gl_flashblend = CVAR2("gl_flashblend","1");
96 cvar_t gl_playermip = CVAR2("gl_playermip","0");
97 cvar_t gl_nocolors = CVAR2("gl_nocolors","0");
98 cvar_t gl_keeptjunctions = CVAR2("gl_keeptjunctions","1");
99 cvar_t gl_reporttjunctions = CVAR2("gl_reporttjunctions","0");
100 cvar_t gl_doubleeyes = CVAR2("gl_doubleeys", "1");
101
102 extern cvar_t gl_ztrick;
103
104 /*
105 =================
106 R_CullBox
107
108 Returns true if the box is completely outside the frustom
109 =================
110 */
R_CullBox(vec3_t mins,vec3_t maxs)111 qboolean R_CullBox (vec3_t mins, vec3_t maxs)
112 {
113 int i;
114
115 for (i=0 ; i<4 ; i++)
116 if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2)
117 return true;
118 return false;
119 }
120
121
R_RotateForEntity(entity_t * e)122 void R_RotateForEntity (entity_t *e)
123 {
124 glTranslatef (e->origin[0], e->origin[1], e->origin[2]);
125
126 glRotatef (e->angles[1], 0, 0, 1);
127 glRotatef (-e->angles[0], 0, 1, 0);
128 glRotatef (e->angles[2], 1, 0, 0);
129 }
130
131 /*
132 =============================================================
133
134 SPRITE MODELS
135
136 =============================================================
137 */
138
139 /*
140 ================
141 R_GetSpriteFrame
142 ================
143 */
R_GetSpriteFrame(entity_t * currententity)144 mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
145 {
146 msprite_t *psprite;
147 mspritegroup_t *pspritegroup;
148 mspriteframe_t *pspriteframe;
149 int i, numframes, frame;
150 float *pintervals, fullinterval, targettime, time;
151
152 psprite = (msprite_t*) currententity->model->cache.data;
153 frame = currententity->frame;
154
155 if ((frame >= psprite->numframes) || (frame < 0))
156 {
157 Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
158 frame = 0;
159 }
160
161 if (psprite->frames[frame].type == SPR_SINGLE)
162 {
163 pspriteframe = psprite->frames[frame].frameptr;
164 }
165 else
166 {
167 pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
168 pintervals = pspritegroup->intervals;
169 numframes = pspritegroup->numframes;
170 fullinterval = pintervals[numframes-1];
171
172 time = cl.time + currententity->syncbase;
173
174 // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
175 // are positive, so we don't have to worry about division by 0
176 targettime = time - ((int)(time / fullinterval)) * fullinterval;
177
178 for (i=0 ; i<(numframes-1) ; i++)
179 {
180 if (pintervals[i] > targettime)
181 break;
182 }
183
184 pspriteframe = pspritegroup->frames[i];
185 }
186
187 return pspriteframe;
188 }
189
190
191 /*
192 =================
193 R_DrawSpriteModel
194
195 =================
196 */
R_DrawSpriteModel(entity_t * e)197 void R_DrawSpriteModel (entity_t *e)
198 {
199 vec3_t point;
200 mspriteframe_t *frame;
201 float *up, *right;
202 vec3_t v_forward, v_right, v_up;
203 msprite_t *psprite;
204
205 // don't even bother culling, because it's just a single
206 // polygon without a surface cache
207 frame = R_GetSpriteFrame (e);
208 psprite = (msprite_t*) currententity->model->cache.data;
209
210 if (psprite->type == SPR_ORIENTED)
211 { // bullet marks on walls
212 AngleVectors (currententity->angles, v_forward, v_right, v_up);
213 up = v_up;
214 right = v_right;
215 }
216 else
217 { // normal sprite
218 up = vup;
219 right = vright;
220 }
221
222 glColor3f (1,1,1);
223
224 GL_DisableMultitexture();
225
226 GL_Bind(frame->gl_texturenum);
227
228 glEnable (GL_ALPHA_TEST);
229
230 #ifdef USE_OPENGLES
231
232 {
233 float* pPoint = gVertexBuffer;
234 float texCoords[] = {
235 0, 1,
236 0, 0,
237 1, 0,
238 1, 1
239 };
240
241 VectorMA (e->origin, frame->down, up, point);
242 VectorMA (point, frame->left, right, pPoint);
243 pPoint += 3;
244
245 VectorMA (e->origin, frame->up, up, point);
246 VectorMA (point, frame->left, right, pPoint);
247 pPoint += 3;
248
249 VectorMA (e->origin, frame->up, up, point);
250 VectorMA (point, frame->right, right, pPoint);
251 pPoint += 3;
252
253 VectorMA (e->origin, frame->down, up, point);
254 VectorMA (point, frame->right, right, pPoint);
255
256 glVertexPointer(3, GL_FLOAT, 0, gVertexBuffer);
257 glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
258 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
259 }
260
261 #else
262 glBegin (GL_QUADS);
263
264 glTexCoord2f (0, 1);
265 VectorMA (e->origin, frame->down, up, point);
266 VectorMA (point, frame->left, right, point);
267 glVertex3fv (point);
268
269 glTexCoord2f (0, 0);
270 VectorMA (e->origin, frame->up, up, point);
271 VectorMA (point, frame->left, right, point);
272 glVertex3fv (point);
273
274 glTexCoord2f (1, 0);
275 VectorMA (e->origin, frame->up, up, point);
276 VectorMA (point, frame->right, right, point);
277 glVertex3fv (point);
278
279 glTexCoord2f (1, 1);
280 VectorMA (e->origin, frame->down, up, point);
281 VectorMA (point, frame->right, right, point);
282 glVertex3fv (point);
283
284 glEnd ();
285 #endif
286
287 glDisable (GL_ALPHA_TEST);
288 }
289
290 /*
291 =============================================================
292
293 ALIAS MODELS
294
295 =============================================================
296 */
297
298
299 #define NUMVERTEXNORMALS 162
300
301 float r_avertexnormals[NUMVERTEXNORMALS][3] = {
302 #include "anorms.h"
303 };
304
305 vec3_t shadevector;
306 float shadelight, ambientlight;
307
308 // precalculated dot products for quantized angles
309 #define SHADEDOT_QUANT 16
310 float r_avertexnormal_dots[SHADEDOT_QUANT][256] =
311 #include "anorm_dots.h"
312 ;
313
314 float *shadedots = r_avertexnormal_dots[0];
315
316 int lastposenum;
317
318 /*
319 =============
320 GL_DrawAliasFrame
321 =============
322 */
GL_DrawAliasFrame(aliashdr_t * paliashdr,int posenum)323 void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum)
324 {
325 float s, t;
326 float l;
327 int i, j;
328 int index;
329 trivertx_t *v, *verts;
330 int list;
331 int *order;
332 vec3_t point;
333 float *normal;
334 int count;
335
336 #ifdef USE_OPENGLES
337 glEnableClientState(GL_COLOR_ARRAY);
338 #endif
339
340 lastposenum = posenum;
341
342 verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
343 verts += posenum * paliashdr->poseverts;
344 order = (int *)((byte *)paliashdr + paliashdr->commands);
345
346 while (1)
347 {
348 // get the vertex count and primitive type
349 count = *order++;
350 if (!count)
351 break; // done
352
353 #ifdef USE_OPENGLES
354 {
355 int primType;
356 int c;
357 float* pColor;
358 float* pTexCoord;
359 float* pPos;
360
361 if (count < 0)
362 {
363 count = -count;
364 primType = GL_TRIANGLE_FAN;
365 }
366 else
367 primType = GL_TRIANGLE_STRIP;
368
369 // texture coordinates come from the draw list
370 glTexCoordPointer(2, GL_FLOAT, 0, gTexCoordBuffer);
371 glVertexPointer(3, GL_FLOAT, 0, gVertexBuffer);
372 glColorPointer(4, GL_FLOAT, 0, gColorBuffer);
373
374 pColor = gColorBuffer;
375 pPos = gVertexBuffer;
376 pTexCoord = gTexCoordBuffer;
377 c = count;
378 do
379 {
380 // texture coordinates come from the draw list
381 *pTexCoord++ = ((float *)order)[0];
382 *pTexCoord++ = ((float *)order)[1];
383 order += 2;
384
385 // normals and vertexes come from the frame list
386 l = shadedots[verts->lightnormalindex] * shadelight;
387 *pColor++ = l;
388 *pColor++ = l;
389 *pColor++ = l;
390 *pColor++ = 1.0f;
391 *pPos++ = verts->v[0];
392 *pPos++ = verts->v[1];
393 *pPos++ = verts->v[2];
394 verts++;
395 } while (--c);
396
397 glDrawArrays(primType, 0, count);
398 }
399
400 #else
401 if (count < 0)
402 {
403 count = -count;
404 glBegin (GL_TRIANGLE_FAN);
405 }
406 else
407 glBegin (GL_TRIANGLE_STRIP);
408
409 do
410 {
411 // texture coordinates come from the draw list
412 glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
413 order += 2;
414
415 // normals and vertexes come from the frame list
416 l = shadedots[verts->lightnormalindex] * shadelight;
417 glColor3f (l, l, l);
418 glVertex3f (verts->v[0], verts->v[1], verts->v[2]);
419 verts++;
420 } while (--count);
421
422 glEnd ();
423 #endif
424 }
425
426 #ifdef USE_OPENGLES
427 glDisableClientState(GL_COLOR_ARRAY);
428 #endif
429
430 }
431
432
433 /*
434 =============
435 GL_DrawAliasShadow
436 =============
437 */
438 extern vec3_t lightspot;
439
GL_DrawAliasShadow(aliashdr_t * paliashdr,int posenum)440 void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
441 {
442 float s, t, l;
443 int i, j;
444 int index;
445 trivertx_t *v, *verts;
446 int list;
447 int *order;
448 vec3_t point;
449 float *normal;
450 float height, lheight;
451 int count;
452
453 lheight = currententity->origin[2] - lightspot[2];
454
455 height = 0;
456 verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
457 verts += posenum * paliashdr->poseverts;
458 order = (int *)((byte *)paliashdr + paliashdr->commands);
459
460 height = -lheight + 1.0;
461
462 while (1)
463 {
464 // get the vertex count and primitive type
465 count = *order++;
466 if (!count)
467 break; // done
468
469 #ifdef USE_OPENGLES
470
471 {
472 int primType;
473 int c;
474 float* pVertex;
475
476 if (count < 0)
477 {
478 count = -count;
479 primType = GL_TRIANGLE_FAN;
480 }
481 else
482 primType = GL_TRIANGLE_STRIP;
483
484 pVertex = gVertexBuffer;
485 for(c = 0; c < count; c++)
486 {
487 // texture coordinates come from the draw list
488 // (skipped for shadows) glTexCoord2fv ((float *)order);
489 order += 2;
490
491 // normals and vertexes come from the frame list
492 pVertex[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
493 pVertex[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
494 pVertex[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
495
496 pVertex[0] -= shadevector[0]*(pVertex[2]+lheight);
497 pVertex[1] -= shadevector[1]*(pVertex[2]+lheight);
498 pVertex[2] = height;
499 // height -= 0.001;
500
501 pVertex += 3;
502 verts++;
503 }
504
505 glVertexPointer(3, GL_FLOAT, 0, gVertexBuffer);
506 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
507 glDrawArrays(primType, 0, count);
508 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
509 }
510
511 #else
512
513 if (count < 0)
514 {
515 count = -count;
516 glBegin (GL_TRIANGLE_FAN);
517 }
518 else
519 glBegin (GL_TRIANGLE_STRIP);
520
521 do
522 {
523 // texture coordinates come from the draw list
524 // (skipped for shadows) glTexCoord2fv ((float *)order);
525 order += 2;
526
527 // normals and vertexes come from the frame list
528 point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
529 point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
530 point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
531
532 point[0] -= shadevector[0]*(point[2]+lheight);
533 point[1] -= shadevector[1]*(point[2]+lheight);
534 point[2] = height;
535 // height -= 0.001;
536 glVertex3fv (point);
537
538 verts++;
539 } while (--count);
540
541 glEnd ();
542
543 #endif
544
545 }
546 }
547
548
549
550 /*
551 =================
552 R_SetupAliasFrame
553
554 =================
555 */
R_SetupAliasFrame(int frame,aliashdr_t * paliashdr)556 void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr)
557 {
558 int pose, numposes;
559 float interval;
560
561 if ((frame >= paliashdr->numframes) || (frame < 0))
562 {
563 Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
564 frame = 0;
565 }
566
567 pose = paliashdr->frames[frame].firstpose;
568 numposes = paliashdr->frames[frame].numposes;
569
570 if (numposes > 1)
571 {
572 interval = paliashdr->frames[frame].interval;
573 pose += (int)(cl.time / interval) % numposes;
574 }
575
576 GL_DrawAliasFrame (paliashdr, pose);
577 }
578
579
580
581 /*
582 =================
583 R_DrawAliasModel
584
585 =================
586 */
R_DrawAliasModel(entity_t * e)587 void R_DrawAliasModel (entity_t *e)
588 {
589 int i, j;
590 int lnum;
591 vec3_t dist;
592 float add;
593 model_t *clmodel;
594 vec3_t mins, maxs;
595 aliashdr_t *paliashdr;
596 trivertx_t *verts, *v;
597 int index;
598 float s, t, an;
599 int anim;
600
601 clmodel = currententity->model;
602
603 VectorAdd (currententity->origin, clmodel->mins, mins);
604 VectorAdd (currententity->origin, clmodel->maxs, maxs);
605
606 if (R_CullBox (mins, maxs))
607 return;
608
609
610 VectorCopy (currententity->origin, r_entorigin);
611 VectorSubtract (r_origin, r_entorigin, modelorg);
612
613 //
614 // get lighting information
615 //
616
617 ambientlight = shadelight = R_LightPoint (currententity->origin);
618
619 // allways give the gun some light
620 if (e == &cl.viewent && ambientlight < 24)
621 ambientlight = shadelight = 24;
622
623 for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
624 {
625 if (cl_dlights[lnum].die >= cl.time)
626 {
627 VectorSubtract (currententity->origin,
628 cl_dlights[lnum].origin,
629 dist);
630 add = cl_dlights[lnum].radius - Length(dist);
631
632 if (add > 0) {
633 ambientlight += add;
634 //ZOID models should be affected by dlights as well
635 shadelight += add;
636 }
637 }
638 }
639
640 // clamp lighting so it doesn't overbright as much
641 if (ambientlight > 128)
642 ambientlight = 128;
643 if (ambientlight + shadelight > 192)
644 shadelight = 192 - ambientlight;
645
646 // ZOID: never allow players to go totally black
647 i = currententity - cl_entities;
648 if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
649 if (ambientlight < 8)
650 ambientlight = shadelight = 8;
651
652 // HACK HACK HACK -- no fullbright colors, so make torches full light
653 if (!strcmp (clmodel->name, "progs/flame2.mdl")
654 || !strcmp (clmodel->name, "progs/flame.mdl") )
655 ambientlight = shadelight = 256;
656
657 shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
658 shadelight = shadelight / 200.0;
659
660 an = e->angles[1]/180*M_PI;
661 shadevector[0] = cos(-an);
662 shadevector[1] = sin(-an);
663 shadevector[2] = 1;
664 VectorNormalize (shadevector);
665
666 //
667 // locate the proper data
668 //
669 paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
670
671 c_alias_polys += paliashdr->numtris;
672
673 //
674 // draw all the triangles
675 //
676
677 GL_DisableMultitexture();
678
679 glPushMatrix ();
680 R_RotateForEntity (e);
681
682 if (!strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes.value) {
683 glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8));
684 // double size of eyes, since they are really hard to see in gl
685 glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2);
686 } else {
687 glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
688 glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
689 }
690
691 anim = (int)(cl.time*10) & 3;
692 GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]);
693
694 // we can't dynamically colormap textures, so they are cached
695 // seperately for the players. Heads are just uncolored.
696 if (currententity->colormap != vid.colormap && !gl_nocolors.value)
697 {
698 i = currententity - cl_entities;
699 if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
700 GL_Bind(playertextures - 1 + i);
701 }
702
703 if (gl_smoothmodels.value)
704 glShadeModel (GL_SMOOTH);
705 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
706
707 if (gl_affinemodels.value)
708 glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
709
710 R_SetupAliasFrame (currententity->frame, paliashdr);
711
712 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
713
714 glShadeModel (GL_FLAT);
715 if (gl_affinemodels.value)
716 glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
717
718 glPopMatrix ();
719
720 if (r_shadows.value)
721 {
722 glPushMatrix ();
723 R_RotateForEntity (e);
724 glDisable (GL_TEXTURE_2D);
725 glEnable (GL_BLEND);
726 glColor4f (0,0,0,0.5);
727 GL_DrawAliasShadow (paliashdr, lastposenum);
728 glEnable (GL_TEXTURE_2D);
729 glDisable (GL_BLEND);
730 glColor4f (1,1,1,1);
731 glPopMatrix ();
732 }
733
734 }
735
736 //==================================================================================
737
738 /*
739 =============
740 R_DrawEntitiesOnList
741 =============
742 */
R_DrawEntitiesOnList(void)743 void R_DrawEntitiesOnList (void)
744 {
745 int i;
746
747 if (!r_drawentities.value)
748 return;
749
750 // draw sprites seperately, because of alpha blending
751 for (i=0 ; i<cl_numvisedicts ; i++)
752 {
753 currententity = cl_visedicts[i];
754
755 switch (currententity->model->type)
756 {
757 case mod_alias:
758 R_DrawAliasModel (currententity);
759 break;
760
761 case mod_brush:
762 R_DrawBrushModel (currententity);
763 break;
764
765 default:
766 break;
767 }
768 }
769
770 for (i=0 ; i<cl_numvisedicts ; i++)
771 {
772 currententity = cl_visedicts[i];
773
774 switch (currententity->model->type)
775 {
776 case mod_sprite:
777 R_DrawSpriteModel (currententity);
778 break;
779
780 default :
781 break;
782 }
783 }
784 }
785
786 /*
787 =============
788 R_DrawViewModel
789 =============
790 */
R_DrawViewModel(void)791 void R_DrawViewModel (void)
792 {
793 float ambient[4], diffuse[4];
794 int j;
795 int lnum;
796 vec3_t dist;
797 float add;
798 dlight_t *dl;
799 int ambientlight, shadelight;
800
801 if (!r_drawviewmodel.value)
802 return;
803
804 if (chase_active.value)
805 return;
806
807 if (envmap)
808 return;
809
810 if (!r_drawentities.value)
811 return;
812
813 if (cl.items & IT_INVISIBILITY)
814 return;
815
816 if (cl.stats[STAT_HEALTH] <= 0)
817 return;
818
819 currententity = &cl.viewent;
820 if (!currententity->model)
821 return;
822
823 j = R_LightPoint (currententity->origin);
824
825 if (j < 24)
826 j = 24; // allways give some light on gun
827 ambientlight = j;
828 shadelight = j;
829
830 // add dynamic lights
831 for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
832 {
833 dl = &cl_dlights[lnum];
834 if (!dl->radius)
835 continue;
836 if (!dl->radius)
837 continue;
838 if (dl->die < cl.time)
839 continue;
840
841 VectorSubtract (currententity->origin, dl->origin, dist);
842 add = dl->radius - Length(dist);
843 if (add > 0)
844 ambientlight += (int) add;
845 }
846
847 ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128;
848 diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128;
849
850 // hack the depth range to prevent view model from poking into walls
851 #ifdef USE_OPENGLES
852 glDepthRangef(gldepthmin, gldepthmin + 0.3f*(gldepthmax-gldepthmin));
853 R_DrawAliasModel (currententity);
854 glDepthRangef(gldepthmin, gldepthmax);
855 #else
856 glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
857 R_DrawAliasModel (currententity);
858 glDepthRange (gldepthmin, gldepthmax);
859 #endif
860 }
861
862
863 /*
864 ============
865 R_PolyBlend
866 ============
867 */
R_PolyBlend(void)868 void R_PolyBlend (void)
869 {
870 if (!gl_polyblend.value)
871 return;
872 if (!v_blend[3])
873 return;
874
875 GL_DisableMultitexture();
876
877 glDisable (GL_ALPHA_TEST);
878 glEnable (GL_BLEND);
879 glDisable (GL_DEPTH_TEST);
880 glDisable (GL_TEXTURE_2D);
881
882 glLoadIdentity ();
883
884 glRotatef (-90, 1, 0, 0); // put Z going up
885 glRotatef (90, 0, 0, 1); // put Z going up
886
887 glColor4fv (v_blend);
888
889 #ifdef USE_OPENGLES
890 float vertex[3*4] = {
891 10, 100, 100,
892 10, -100, 100,
893 10, -100, -100,
894 10, 100, -100
895 };
896 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
897 glVertexPointer( 3, GL_FLOAT, 0, vertex);
898 glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
899 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
900 #else
901 glBegin (GL_QUADS);
902
903 glVertex3f (10, 100, 100);
904 glVertex3f (10, -100, 100);
905 glVertex3f (10, -100, -100);
906 glVertex3f (10, 100, -100);
907 glEnd ();
908 #endif
909
910 glDisable (GL_BLEND);
911 glEnable (GL_TEXTURE_2D);
912 glEnable (GL_ALPHA_TEST);
913 }
914
915
SignbitsForPlane(mplane_t * out)916 int SignbitsForPlane (mplane_t *out)
917 {
918 int bits, j;
919
920 // for fast box on planeside test
921
922 bits = 0;
923 for (j=0 ; j<3 ; j++)
924 {
925 if (out->normal[j] < 0)
926 bits |= 1<<j;
927 }
928 return bits;
929 }
930
931
R_SetFrustum(void)932 void R_SetFrustum (void)
933 {
934 int i;
935
936 if (r_refdef.fov_x == 90)
937 {
938 // front side is visible
939
940 VectorAdd (vpn, vright, frustum[0].normal);
941 VectorSubtract (vpn, vright, frustum[1].normal);
942
943 VectorAdd (vpn, vup, frustum[2].normal);
944 VectorSubtract (vpn, vup, frustum[3].normal);
945 }
946 else
947 {
948 // rotate VPN right by FOV_X/2 degrees
949 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
950 // rotate VPN left by FOV_X/2 degrees
951 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
952 // rotate VPN up by FOV_X/2 degrees
953 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
954 // rotate VPN down by FOV_X/2 degrees
955 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
956 }
957
958 for (i=0 ; i<4 ; i++)
959 {
960 frustum[i].type = PLANE_ANYZ;
961 frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
962 frustum[i].signbits = SignbitsForPlane (&frustum[i]);
963 }
964 }
965
966
967
968 /*
969 ===============
970 R_SetupFrame
971 ===============
972 */
R_SetupFrame(void)973 void R_SetupFrame (void)
974 {
975 int edgecount;
976 vrect_t vrect;
977 float w, h;
978
979 // don't allow cheats in multiplayer
980 if (cl.maxclients > 1)
981 Cvar_Set ("r_fullbright", "0");
982
983 R_AnimateLight ();
984
985 r_framecount++;
986
987 // build the transformation matrix for the given view angles
988 VectorCopy (r_refdef.vieworg, r_origin);
989
990 AngleVectors (r_refdef.viewangles, vpn, vright, vup);
991
992 // current viewleaf
993 r_oldviewleaf = r_viewleaf;
994 r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
995
996 V_SetContentsColor (r_viewleaf->contents);
997 V_CalcBlend ();
998
999 r_cache_thrash = false;
1000
1001 c_brush_polys = 0;
1002 c_alias_polys = 0;
1003
1004 }
1005
1006 #ifdef USE_OPENGLES
1007
MYgluPerspective(float fovy,float aspect,float zNear,float zFar)1008 void MYgluPerspective( float fovy, float aspect,
1009 float zNear, float zFar )
1010 {
1011 float xmin, xmax, ymin, ymax;
1012
1013 ymax = zNear * tan( fovy * M_PI / 360.0f );
1014 ymin = -ymax;
1015
1016 xmin = ymin * aspect;
1017 xmax = ymax * aspect;
1018
1019 glFrustumf( xmin, xmax, ymin, ymax, zNear, zFar );
1020 }
1021
1022 #else
1023
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)1024 void MYgluPerspective( GLdouble fovy, GLdouble aspect,
1025 GLdouble zNear, GLdouble zFar )
1026 {
1027 GLdouble xmin, xmax, ymin, ymax;
1028
1029 ymax = zNear * tan( fovy * M_PI / 360.0 );
1030 ymin = -ymax;
1031
1032 xmin = ymin * aspect;
1033 xmax = ymax * aspect;
1034
1035 glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
1036 }
1037 #endif
1038
1039 #define DO_OWN_MATRIX_MATH
1040 #ifdef DO_OWN_MATRIX_MATH
1041 // We can't count on being able to read back the model view matrix, so calculate it ourselves.
1042
1043 #define I(_i, _j) ((_j)+ 4*(_i))
1044
mulMM(float * r,const float * lhs,const float * rhs)1045 void mulMM(float* r, const float* lhs, const float* rhs)
1046 {
1047 float const* const m = lhs;
1048 for (int i=0 ; i<4 ; i++) {
1049 register const float rhs_i0 = rhs[ I(i,0) ];
1050 register float ri0 = m[ I(0,0) ] * rhs_i0;
1051 register float ri1 = m[ I(0,1) ] * rhs_i0;
1052 register float ri2 = m[ I(0,2) ] * rhs_i0;
1053 register float ri3 = m[ I(0,3) ] * rhs_i0;
1054 for (int j=1 ; j<4 ; j++) {
1055 register const float rhs_ij = rhs[ I(i,j) ];
1056 ri0 += m[ I(j,0) ] * rhs_ij;
1057 ri1 += m[ I(j,1) ] * rhs_ij;
1058 ri2 += m[ I(j,2) ] * rhs_ij;
1059 ri3 += m[ I(j,3) ] * rhs_ij;
1060 }
1061 r[ I(i,0) ] = ri0;
1062 r[ I(i,1) ] = ri1;
1063 r[ I(i,2) ] = ri2;
1064 r[ I(i,3) ] = ri3;
1065 }
1066 }
1067
setIdentityM(float * sm,int smOffset)1068 static void setIdentityM(float* sm, int smOffset) {
1069 for (int i=0 ; i<16 ; i++) {
1070 sm[smOffset + i] = 0;
1071 }
1072 for(int i = 0; i < 16; i += 5) {
1073 sm[smOffset + i] = 1.0f;
1074 }
1075 }
1076
translateM(float * m,int mOffset,float x,float y,float z)1077 static void translateM(float* m, int mOffset,
1078 float x, float y, float z) {
1079 for (int i=0 ; i<4 ; i++) {
1080 int mi = mOffset + i;
1081 m[12 + mi] += m[mi] * x + m[4 + mi] * y + m[8 + mi] * z;
1082 }
1083 }
1084
length(float x,float y,float z)1085 static float length(float x, float y, float z) {
1086 return (float) sqrtf(x * x + y * y + z * z);
1087 }
1088
setRotateM(float * rm,int rmOffset,float a,float x,float y,float z)1089 static void setRotateM(float* rm, int rmOffset,
1090 float a, float x, float y, float z)
1091 {
1092 rm[rmOffset + 3] = 0;
1093 rm[rmOffset + 7] = 0;
1094 rm[rmOffset + 11]= 0;
1095 rm[rmOffset + 12]= 0;
1096 rm[rmOffset + 13]= 0;
1097 rm[rmOffset + 14]= 0;
1098 rm[rmOffset + 15]= 1;
1099 a *= (float) (M_PI / 180.0f);
1100 float s = (float) sinf(a);
1101 float c = (float) cosf(a);
1102 if (1.0f == x && 0.0f == y && 0.0f == z) {
1103 rm[rmOffset + 5] = c; rm[rmOffset + 10]= c;
1104 rm[rmOffset + 6] = s; rm[rmOffset + 9] = -s;
1105 rm[rmOffset + 1] = 0; rm[rmOffset + 2] = 0;
1106 rm[rmOffset + 4] = 0; rm[rmOffset + 8] = 0;
1107 rm[rmOffset + 0] = 1;
1108 } else if (0.0f == x && 1.0f == y && 0.0f == z) {
1109 rm[rmOffset + 0] = c; rm[rmOffset + 10]= c;
1110 rm[rmOffset + 8] = s; rm[rmOffset + 2] = -s;
1111 rm[rmOffset + 1] = 0; rm[rmOffset + 4] = 0;
1112 rm[rmOffset + 6] = 0; rm[rmOffset + 9] = 0;
1113 rm[rmOffset + 5] = 1;
1114 } else if (0.0f == x && 0.0f == y && 1.0f == z) {
1115 rm[rmOffset + 0] = c; rm[rmOffset + 5] = c;
1116 rm[rmOffset + 1] = s; rm[rmOffset + 4] = -s;
1117 rm[rmOffset + 2] = 0; rm[rmOffset + 6] = 0;
1118 rm[rmOffset + 8] = 0; rm[rmOffset + 9] = 0;
1119 rm[rmOffset + 10]= 1;
1120 } else {
1121 float len = length(x, y, z);
1122 if (1.0f != len) {
1123 float recipLen = 1.0f / len;
1124 x *= recipLen;
1125 y *= recipLen;
1126 z *= recipLen;
1127 }
1128 float nc = 1.0f - c;
1129 float xy = x * y;
1130 float yz = y * z;
1131 float zx = z * x;
1132 float xs = x * s;
1133 float ys = y * s;
1134 float zs = z * s;
1135 rm[rmOffset + 0] = x*x*nc + c;
1136 rm[rmOffset + 4] = xy*nc - zs;
1137 rm[rmOffset + 8] = zx*nc + ys;
1138 rm[rmOffset + 1] = xy*nc + zs;
1139 rm[rmOffset + 5] = y*y*nc + c;
1140 rm[rmOffset + 9] = yz*nc - xs;
1141 rm[rmOffset + 2] = zx*nc - ys;
1142 rm[rmOffset + 6] = yz*nc + xs;
1143 rm[rmOffset + 10] = z*z*nc + c;
1144 }
1145 }
1146
rotateM(float * m,float a,float x,float y,float z)1147 static void rotateM(float* m,
1148 float a, float x, float y, float z) {
1149 float temp[16];
1150 float temp2[16];
1151 setRotateM(temp, 0, a, x, y, z);
1152 mulMM(temp2, m, temp);
1153 memcpy(m, temp2, 16 * sizeof(float));
1154 }
1155
1156 #undef I
1157
1158 #endif // DO_OWN_MATRIX_MATH
1159
1160 /*
1161 =============
1162 R_SetupGL
1163 =============
1164 */
R_SetupGL(void)1165 void R_SetupGL (void)
1166 {
1167 float screenaspect;
1168 float yfov;
1169 int i;
1170 extern int glwidth, glheight;
1171 int x, x2, y2, y, w, h;
1172
1173 //
1174 // set up viewpoint
1175 //
1176 glMatrixMode(GL_PROJECTION);
1177 glLoadIdentity ();
1178 x = r_refdef.vrect.x * glwidth/vid.width;
1179 x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
1180 y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
1181 y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
1182
1183 // fudge around because of frac screen scale
1184 if (x > 0)
1185 x--;
1186 if (x2 < glwidth)
1187 x2++;
1188 if (y2 < 0)
1189 y2--;
1190 if (y < glheight)
1191 y++;
1192
1193 w = x2 - x;
1194 h = y - y2;
1195
1196 if (envmap)
1197 {
1198 x = y2 = 0;
1199 w = h = 256;
1200 }
1201
1202 glViewport (glx + x, gly + y2, w, h);
1203 screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
1204 // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
1205 MYgluPerspective (r_refdef.fov_y, screenaspect, 4, 4096);
1206
1207 if (mirror)
1208 {
1209 if (mirror_plane->normal[2])
1210 glScalef (1, -1, 1);
1211 else
1212 glScalef (-1, 1, 1);
1213 glCullFace(GL_BACK);
1214 }
1215 else
1216 glCullFace(GL_FRONT);
1217
1218 glMatrixMode(GL_MODELVIEW);
1219
1220 #ifdef DO_OWN_MATRIX_MATH
1221
1222 float mv[16];
1223 setIdentityM(mv, 0);
1224
1225 rotateM(mv, -90, 1, 0, 0); // put Z going up
1226 rotateM(mv, 90, 0, 0, 1); // put Z going up
1227 rotateM(mv, -r_refdef.viewangles[2], 1, 0, 0);
1228 rotateM(mv, -r_refdef.viewangles[0], 0, 1, 0);
1229 rotateM(mv, -r_refdef.viewangles[1], 0, 0, 1);
1230 translateM(mv, 0, -r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
1231
1232 glLoadMatrixf(mv);
1233
1234 memcpy(r_world_matrix, mv, sizeof(r_world_matrix));
1235
1236 #else
1237 glLoadIdentity ();
1238
1239 glRotatef (-90, 1, 0, 0); // put Z going up
1240 glRotatef (90, 0, 0, 1); // put Z going up
1241 glRotatef (-r_refdef.viewangles[2], 1, 0, 0);
1242 glRotatef (-r_refdef.viewangles[0], 0, 1, 0);
1243 glRotatef (-r_refdef.viewangles[1], 0, 0, 1);
1244 glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
1245
1246 #ifdef USE_OPENGLES
1247
1248 static qboolean initialized;
1249 static qboolean haveGL_OES_matrix_get;
1250 static qboolean haveGL_OES_query_matrix;
1251
1252 #if 0
1253 if (! initialized) {
1254 const char* extensions = (const char*) glGetString(GL_EXTENSIONS);
1255 haveGL_OES_matrix_get =
1256 strstr(extensions, "GL_OES_matrix_get") != NULL;
1257 haveGL_OES_query_matrix =
1258 strstr(extensions, "GL_OES_query_matrix") != NULL;
1259 initialized = true;
1260 }
1261 if (haveGL_OES_query_matrix) {
1262 GLfixed mantissa[16];
1263 GLint exponent[16];
1264 glQueryMatrixxOES( mantissa, exponent );
1265 for(int i = 0; i < 16; i++) {
1266 r_world_matrix[i] = scalbnf(mantissa[i], exponent[i]-16);
1267 }
1268 }
1269 else if (haveGL_OES_matrix_get) {
1270 glGetIntegerv (MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES,
1271 (GLint*) r_world_matrix);
1272 }
1273 else
1274 #endif
1275 {
1276 // No way to get the world matix, set to identity
1277 memset(r_world_matrix, 0, sizeof(r_world_matrix));
1278 for(i = 0; i < 16; i += 5) {
1279 r_world_matrix[i] = 1.0f;
1280 }
1281 }
1282 #else
1283 glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
1284 #endif
1285 #endif // DO_OWN_MATRIX_MATH
1286 //
1287 // set drawing parms
1288 //
1289 if (gl_cull.value)
1290 glEnable(GL_CULL_FACE);
1291 else
1292 glDisable(GL_CULL_FACE);
1293
1294 glDisable(GL_BLEND);
1295 glDisable(GL_ALPHA_TEST);
1296 glEnable(GL_DEPTH_TEST);
1297 }
1298
1299 /*
1300 ================
1301 R_RenderScene
1302
1303 r_refdef must be set before the first call
1304 ================
1305 */
R_RenderScene(void)1306 void R_RenderScene (void)
1307 {
1308 R_SetupFrame ();
1309
1310 R_SetFrustum ();
1311
1312 R_SetupGL ();
1313
1314 R_MarkLeaves (); // done here so we know if we're in water
1315
1316 R_DrawWorld (); // adds static entities to the list
1317
1318 S_ExtraUpdate (); // don't let sound get messed up if going slow
1319
1320 R_DrawEntitiesOnList ();
1321
1322 GL_DisableMultitexture();
1323
1324 R_RenderDlights ();
1325
1326 R_DrawParticles ();
1327
1328 #ifdef GLTEST
1329 Test_Draw ();
1330 #endif
1331
1332 }
1333
1334
1335 /*
1336 =============
1337 R_Clear
1338 =============
1339 */
R_Clear(void)1340 void R_Clear (void)
1341 {
1342 if (r_mirroralpha.value != 1.0)
1343 {
1344 if (gl_clear.value)
1345 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1346 else
1347 glClear (GL_DEPTH_BUFFER_BIT);
1348 gldepthmin = 0;
1349 gldepthmax = 0.5;
1350 glDepthFunc (GL_LEQUAL);
1351 }
1352 else if (gl_ztrick.value)
1353 {
1354 static int trickframe;
1355
1356 if (gl_clear.value)
1357 glClear (GL_COLOR_BUFFER_BIT);
1358
1359 trickframe++;
1360 if (trickframe & 1)
1361 {
1362 gldepthmin = 0;
1363 gldepthmax = 0.49999;
1364 glDepthFunc (GL_LEQUAL);
1365 }
1366 else
1367 {
1368 gldepthmin = 1;
1369 gldepthmax = 0.5;
1370 glDepthFunc (GL_GEQUAL);
1371 }
1372 }
1373 else
1374 {
1375 if (gl_clear.value)
1376 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1377 else
1378 glClear (GL_DEPTH_BUFFER_BIT);
1379 gldepthmin = 0;
1380 gldepthmax = 1;
1381 glDepthFunc (GL_LEQUAL);
1382 }
1383
1384 #ifdef USE_OPENGLES
1385 glDepthRangef (gldepthmin, gldepthmax);
1386 #else
1387 glDepthRange (gldepthmin, gldepthmax);
1388 #endif
1389 }
1390
1391 /*
1392 =============
1393 R_Mirror
1394 =============
1395 */
R_Mirror(void)1396 void R_Mirror (void)
1397 {
1398 float d;
1399 msurface_t *s;
1400 entity_t *ent;
1401
1402 if (!mirror)
1403 return;
1404
1405 memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix));
1406
1407 d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist;
1408 VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg);
1409
1410 d = DotProduct (vpn, mirror_plane->normal);
1411 VectorMA (vpn, -2*d, mirror_plane->normal, vpn);
1412
1413 r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180;
1414 r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180;
1415 r_refdef.viewangles[2] = -r_refdef.viewangles[2];
1416
1417 ent = &cl_entities[cl.viewentity];
1418 if (cl_numvisedicts < MAX_VISEDICTS)
1419 {
1420 cl_visedicts[cl_numvisedicts] = ent;
1421 cl_numvisedicts++;
1422 }
1423
1424 gldepthmin = 0.5;
1425 gldepthmax = 1;
1426 #ifdef USE_OPENGLES
1427 glDepthRangef (gldepthmin, gldepthmax);
1428 #else
1429 glDepthRange (gldepthmin, gldepthmax);
1430 #endif
1431 glDepthFunc (GL_LEQUAL);
1432
1433 R_RenderScene ();
1434 R_DrawWaterSurfaces ();
1435
1436 gldepthmin = 0;
1437 gldepthmax = 0.5;
1438 #ifdef USE_OPENGLES
1439 glDepthRangef (gldepthmin, gldepthmax);
1440 #else
1441 glDepthRange (gldepthmin, gldepthmax);
1442 #endif
1443 glDepthFunc (GL_LEQUAL);
1444
1445 // blend on top
1446 glEnable (GL_BLEND);
1447 glMatrixMode(GL_PROJECTION);
1448 if (mirror_plane->normal[2])
1449 glScalef (1,-1,1);
1450 else
1451 glScalef (-1,1,1);
1452 glCullFace(GL_FRONT);
1453 glMatrixMode(GL_MODELVIEW);
1454
1455 glLoadMatrixf (r_base_world_matrix);
1456
1457 glColor4f (1,1,1,r_mirroralpha.value);
1458 s = cl.worldmodel->textures[mirrortexturenum]->texturechain;
1459 for ( ; s ; s=s->texturechain)
1460 R_RenderBrushPoly (s);
1461 cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL;
1462 glDisable (GL_BLEND);
1463 glColor4f (1,1,1,1);
1464 }
1465
1466 /*
1467 ================
1468 R_RenderView
1469
1470 r_refdef must be set before the first call
1471 ================
1472 */
R_RenderView(void)1473 void R_RenderView (void)
1474 {
1475 double time1 = 0.0;
1476 double time2;
1477 GLfloat colors[4] = {(GLfloat) 0.0, (GLfloat) 0.0, (GLfloat) 1, (GLfloat) 0.20};
1478
1479 if (r_norefresh.value)
1480 return;
1481
1482 if (!r_worldentity.model || !cl.worldmodel)
1483 Sys_Error ("R_RenderView: NULL worldmodel");
1484
1485 if (r_speeds.value)
1486 {
1487 glFinish ();
1488 time1 = Sys_FloatTime ();
1489 c_brush_polys = 0;
1490 c_alias_polys = 0;
1491 }
1492
1493 mirror = false;
1494
1495 if (gl_finish.value)
1496 glFinish ();
1497
1498 R_Clear ();
1499
1500 // render normal view
1501
1502 /***** Experimental silly looking fog ******
1503 ****** Use r_fullbright if you enable ******
1504 glFogi(GL_FOG_MODE, GL_LINEAR);
1505 glFogfv(GL_FOG_COLOR, colors);
1506 glFogf(GL_FOG_END, 512.0);
1507 glEnable(GL_FOG);
1508 ********************************************/
1509
1510 R_RenderScene ();
1511 R_DrawViewModel ();
1512 R_DrawWaterSurfaces ();
1513
1514 // More fog right here :)
1515 // glDisable(GL_FOG);
1516 // End of all fog code...
1517
1518 // render mirror view
1519 R_Mirror ();
1520
1521 R_PolyBlend ();
1522
1523 if (r_speeds.value)
1524 {
1525 // glFinish ();
1526 time2 = Sys_FloatTime ();
1527 Con_Printf ("%3i ms %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys);
1528 }
1529 }
1530