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 cvar_t r_netgraph = CVAR2("r_netgraph","0");
88
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","0");
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_finish = CVAR2("gl_finish","0");
101
102 extern cvar_t gl_ztrick;
103 extern cvar_t scr_fov;
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 //ZOID: fixed z angle
129 glRotatef (e->angles[2], 1, 0, 0);
130 }
131
132 /*
133 =============================================================
134
135 SPRITE MODELS
136
137 =============================================================
138 */
139
140 /*
141 ================
142 R_GetSpriteFrame
143 ================
144 */
R_GetSpriteFrame(entity_t * currententity)145 mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
146 {
147 msprite_t *psprite;
148 mspritegroup_t *pspritegroup;
149 mspriteframe_t *pspriteframe;
150 int i, numframes, frame;
151 float *pintervals, fullinterval, targettime, time;
152
153 psprite = currententity->model->cache.data;
154 frame = currententity->frame;
155
156 if ((frame >= psprite->numframes) || (frame < 0))
157 {
158 Con_Printf ("R_DrawSprite: no such frame %d\n", frame);
159 frame = 0;
160 }
161
162 if (psprite->frames[frame].type == SPR_SINGLE)
163 {
164 pspriteframe = psprite->frames[frame].frameptr;
165 }
166 else
167 {
168 pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
169 pintervals = pspritegroup->intervals;
170 numframes = pspritegroup->numframes;
171 fullinterval = pintervals[numframes-1];
172
173 time = cl.time + currententity->syncbase;
174
175 // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
176 // are positive, so we don't have to worry about division by 0
177 targettime = time - ((int)(time / fullinterval)) * fullinterval;
178
179 for (i=0 ; i<(numframes-1) ; i++)
180 {
181 if (pintervals[i] > targettime)
182 break;
183 }
184
185 pspriteframe = pspritegroup->frames[i];
186 }
187
188 return pspriteframe;
189 }
190
191
192 /*
193 =================
194 R_DrawSpriteModel
195
196 =================
197 */
R_DrawSpriteModel(entity_t * e)198 void R_DrawSpriteModel (entity_t *e)
199 {
200 vec3_t point;
201 mspriteframe_t *frame;
202 float *up, *right;
203 vec3_t v_forward, v_right, v_up;
204 msprite_t *psprite;
205
206 // don't even bother culling, because it's just a single
207 // polygon without a surface cache
208 frame = R_GetSpriteFrame (e);
209 psprite = currententity->model->cache.data;
210
211 if (psprite->type == SPR_ORIENTED)
212 { // bullet marks on walls
213 AngleVectors (currententity->angles, v_forward, v_right, v_up);
214 up = v_up;
215 right = v_right;
216 }
217 else
218 { // normal sprite
219 up = vup;
220 right = vright;
221 }
222
223 glColor3f (1,1,1);
224
225 GL_DisableMultitexture();
226
227 GL_Bind(frame->gl_texturenum);
228
229 glEnable (GL_ALPHA_TEST);
230
231 #ifdef USE_OPENGLES
232 // !!! Need to implement this !!!
233
234 #else
235 glBegin (GL_QUADS);
236
237 glTexCoord2f (0, 1);
238 VectorMA (e->origin, frame->down, up, point);
239 VectorMA (point, frame->left, right, point);
240 glVertex3fv (point);
241
242 glTexCoord2f (0, 0);
243 VectorMA (e->origin, frame->up, up, point);
244 VectorMA (point, frame->left, right, point);
245 glVertex3fv (point);
246
247 glTexCoord2f (1, 0);
248 VectorMA (e->origin, frame->up, up, point);
249 VectorMA (point, frame->right, right, point);
250 glVertex3fv (point);
251
252 glTexCoord2f (1, 1);
253 VectorMA (e->origin, frame->down, up, point);
254 VectorMA (point, frame->right, right, point);
255 glVertex3fv (point);
256
257 glEnd ();
258 #endif
259
260 glDisable (GL_ALPHA_TEST);
261 }
262
263 /*
264 =============================================================
265
266 ALIAS MODELS
267
268 =============================================================
269 */
270
271
272 #define NUMVERTEXNORMALS 162
273
274 float r_avertexnormals[NUMVERTEXNORMALS][3] = {
275 #include "anorms.h"
276 };
277
278 vec3_t shadevector;
279 float shadelight, ambientlight;
280
281 // precalculated dot products for quantized angles
282 #define SHADEDOT_QUANT 16
283 float r_avertexnormal_dots[SHADEDOT_QUANT][256] =
284 #include "anorm_dots.h"
285 ;
286
287 float *shadedots = r_avertexnormal_dots[0];
288
289 int lastposenum;
290
291 /*
292 =============
293 GL_DrawAliasFrame
294 =============
295 */
GL_DrawAliasFrame(aliashdr_t * paliashdr,int posenum)296 void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum)
297 {
298 float l;
299 trivertx_t *verts;
300 int *order;
301 int count;
302
303 lastposenum = posenum;
304
305 verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
306 verts += posenum * paliashdr->poseverts;
307 order = (int *)((byte *)paliashdr + paliashdr->commands);
308
309 while (1)
310 {
311 // get the vertex count and primitive type
312 count = *order++;
313 if (!count)
314 break; // done
315
316 #ifdef USE_OPENGLES
317 {
318 int primType;
319 float color[3*256];
320 float vertex[3*256];
321 int c;
322 float* pColor;
323 float* pVertex;
324
325 if (count < 0)
326 {
327 count = -count;
328 primType = GL_TRIANGLE_FAN;
329 }
330 else
331 primType = GL_TRIANGLE_STRIP;
332
333 // texture coordinates come from the draw list
334 glTexCoordPointer(2, GL_FLOAT, 0, order);
335
336 pColor = color;
337 pVertex = vertex;
338 for(c = 0; c < count; c++)
339 {
340 // normals and vertexes come from the frame list
341 l = shadedots[verts->lightnormalindex] * shadelight;
342 *pColor++ = l;
343 *pColor++ = l;
344 *pColor++ = l;
345 *pVertex++ = verts->v[0];
346 *pVertex++ = verts->v[1];
347 *pVertex++ = verts->v[2];
348 verts++;
349 }
350
351 glColorPointer(3, GL_FLOAT, 0, color);
352 glVertexPointer(3, GL_FLOAT, 0, vertex);
353
354 glDrawArrays(primType, 0, count);
355
356 order += 2 * count;
357 }
358
359 #else
360 if (count < 0)
361 {
362 count = -count;
363 glBegin (GL_TRIANGLE_FAN);
364 }
365 else
366 glBegin (GL_TRIANGLE_STRIP);
367
368 do
369 {
370 // texture coordinates come from the draw list
371 glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
372 order += 2;
373
374 // normals and vertexes come from the frame list
375 l = shadedots[verts->lightnormalindex] * shadelight;
376 glColor3f (l, l, l);
377 glVertex3f (verts->v[0], verts->v[1], verts->v[2]);
378 verts++;
379 } while (--count);
380
381 glEnd ();
382 #endif
383 }
384 }
385
386
387 /*
388 =============
389 GL_DrawAliasShadow
390 =============
391 */
392 extern vec3_t lightspot;
393
GL_DrawAliasShadow(aliashdr_t * paliashdr,int posenum)394 void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
395 {
396 trivertx_t *verts;
397 int *order;
398 vec3_t point;
399 float height, lheight;
400 int count;
401
402 lheight = currententity->origin[2] - lightspot[2];
403
404 height = 0;
405 verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
406 verts += posenum * paliashdr->poseverts;
407 order = (int *)((byte *)paliashdr + paliashdr->commands);
408
409 height = -lheight + 1.0;
410
411 while (1)
412 {
413 // get the vertex count and primitive type
414 count = *order++;
415 if (!count)
416 break; // done
417
418 #ifdef USE_OPENGLES
419
420 // !!! Implement this (based on GL_DrawAlias)
421 break;
422 #else
423
424 if (count < 0)
425 {
426 count = -count;
427 glBegin (GL_TRIANGLE_FAN);
428 }
429 else
430 glBegin (GL_TRIANGLE_STRIP);
431
432 do
433 {
434 // texture coordinates come from the draw list
435 // (skipped for shadows) glTexCoord2fv ((float *)order);
436 order += 2;
437
438 // normals and vertexes come from the frame list
439 point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
440 point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
441 point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
442
443 point[0] -= shadevector[0]*(point[2]+lheight);
444 point[1] -= shadevector[1]*(point[2]+lheight);
445 point[2] = height;
446 // height -= 0.001;
447 glVertex3fv (point);
448
449 verts++;
450 } while (--count);
451
452 glEnd ();
453
454 #endif
455
456 }
457 }
458
459
460
461 /*
462 =================
463 R_SetupAliasFrame
464
465 =================
466 */
R_SetupAliasFrame(int frame,aliashdr_t * paliashdr)467 void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr)
468 {
469 int pose, numposes;
470 float interval;
471
472 if ((frame >= paliashdr->numframes) || (frame < 0))
473 {
474 Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
475 frame = 0;
476 }
477
478 pose = paliashdr->frames[frame].firstpose;
479 numposes = paliashdr->frames[frame].numposes;
480
481 if (numposes > 1)
482 {
483 interval = paliashdr->frames[frame].interval;
484 pose += (int)(cl.time / interval) % numposes;
485 }
486
487 GL_DrawAliasFrame (paliashdr, pose);
488 }
489
490
491
492 /*
493 =================
494 R_DrawAliasModel
495
496 =================
497 */
R_DrawAliasModel(entity_t * e)498 void R_DrawAliasModel (entity_t *e)
499 {
500 int i;
501 int lnum;
502 vec3_t dist;
503 float add;
504 model_t *clmodel;
505 vec3_t mins, maxs;
506 aliashdr_t *paliashdr;
507 float an;
508 int anim;
509
510 clmodel = currententity->model;
511
512 VectorAdd (currententity->origin, clmodel->mins, mins);
513 VectorAdd (currententity->origin, clmodel->maxs, maxs);
514
515 if (R_CullBox (mins, maxs))
516 return;
517
518
519 VectorCopy (currententity->origin, r_entorigin);
520 VectorSubtract (r_origin, r_entorigin, modelorg);
521
522 //
523 // get lighting information
524 //
525
526 ambientlight = shadelight = R_LightPoint (currententity->origin);
527
528 // allways give the gun some light
529 if (e == &cl.viewent && ambientlight < 24)
530 ambientlight = shadelight = 24;
531
532 for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
533 {
534 if (cl_dlights[lnum].die >= cl.time)
535 {
536 VectorSubtract (currententity->origin,
537 cl_dlights[lnum].origin,
538 dist);
539 add = cl_dlights[lnum].radius - Length(dist);
540
541 if (add > 0) {
542 ambientlight += add;
543 //ZOID models should be affected by dlights as well
544 shadelight += add;
545 }
546 }
547 }
548
549 // clamp lighting so it doesn't overbright as much
550 if (ambientlight > 128)
551 ambientlight = 128;
552 if (ambientlight + shadelight > 192)
553 shadelight = 192 - ambientlight;
554
555 // ZOID: never allow players to go totally black
556 if (!strcmp(clmodel->name, "progs/player.mdl")) {
557 if (ambientlight < 8)
558 ambientlight = shadelight = 8;
559
560 } else if (!strcmp (clmodel->name, "progs/flame2.mdl")
561 || !strcmp (clmodel->name, "progs/flame.mdl") )
562 // HACK HACK HACK -- no fullbright colors, so make torches full light
563 ambientlight = shadelight = 256;
564
565 shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
566 shadelight = shadelight / 200.0;
567
568 an = e->angles[1]/180*M_PI;
569 shadevector[0] = cos(-an);
570 shadevector[1] = sin(-an);
571 shadevector[2] = 1;
572 VectorNormalize (shadevector);
573
574 //
575 // locate the proper data
576 //
577 paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
578
579 c_alias_polys += paliashdr->numtris;
580
581 //
582 // draw all the triangles
583 //
584
585 GL_DisableMultitexture();
586
587 glPushMatrix ();
588 R_RotateForEntity (e);
589
590 if (!strcmp (clmodel->name, "progs/eyes.mdl") ) {
591 glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8));
592 // double size of eyes, since they are really hard to see in gl
593 glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2);
594 } else {
595 glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
596 glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
597 }
598
599 anim = (int)(cl.time*10) & 3;
600 GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]);
601
602 // we can't dynamically colormap textures, so they are cached
603 // seperately for the players. Heads are just uncolored.
604 if (currententity->scoreboard && !gl_nocolors.value)
605 {
606 i = currententity->scoreboard - cl.players;
607 if (!currententity->scoreboard->skin) {
608 Skin_Find(currententity->scoreboard);
609 R_TranslatePlayerSkin(i);
610 }
611 if (i >= 0 && i<MAX_CLIENTS)
612 GL_Bind(playertextures + i);
613 }
614
615 if (gl_smoothmodels.value)
616 glShadeModel (GL_SMOOTH);
617 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
618
619 if (gl_affinemodels.value)
620 glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
621
622 R_SetupAliasFrame (currententity->frame, paliashdr);
623
624 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
625
626 glShadeModel (GL_FLAT);
627 if (gl_affinemodels.value)
628 glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
629
630 glPopMatrix ();
631
632 if (r_shadows.value)
633 {
634 glPushMatrix ();
635 R_RotateForEntity (e);
636 glDisable (GL_TEXTURE_2D);
637 glEnable (GL_BLEND);
638 glColor4f (0,0,0,0.5);
639 GL_DrawAliasShadow (paliashdr, lastposenum);
640 glEnable (GL_TEXTURE_2D);
641 glDisable (GL_BLEND);
642 glColor4f (1,1,1,1);
643 glPopMatrix ();
644 }
645
646 }
647
648 //==================================================================================
649
650 /*
651 =============
652 R_DrawEntitiesOnList
653 =============
654 */
R_DrawEntitiesOnList(void)655 void R_DrawEntitiesOnList (void)
656 {
657 int i;
658
659 if (!r_drawentities.value)
660 return;
661
662 // draw sprites seperately, because of alpha blending
663 for (i=0 ; i<cl_numvisedicts ; i++)
664 {
665 currententity = &cl_visedicts[i];
666
667 switch (currententity->model->type)
668 {
669 case mod_alias:
670 R_DrawAliasModel (currententity);
671 break;
672
673 case mod_brush:
674 R_DrawBrushModel (currententity);
675 break;
676
677 default:
678 break;
679 }
680 }
681
682 for (i=0 ; i<cl_numvisedicts ; i++)
683 {
684 currententity = &cl_visedicts[i];
685
686 switch (currententity->model->type)
687 {
688 case mod_sprite:
689 R_DrawSpriteModel (currententity);
690 break;
691
692 default :
693 break;
694 }
695 }
696 }
697
698 /*
699 =============
700 R_DrawViewModel
701 =============
702 */
R_DrawViewModel(void)703 void R_DrawViewModel (void)
704 {
705 float ambient[4], diffuse[4];
706 int j;
707 int lnum;
708 vec3_t dist;
709 float add;
710 dlight_t *dl;
711 int ambientlight, shadelight;
712
713 if (!r_drawviewmodel.value || !Cam_DrawViewModel())
714 return;
715
716 if (envmap)
717 return;
718
719 if (!r_drawentities.value)
720 return;
721
722 if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY)
723 return;
724
725 if (cl.stats[STAT_HEALTH] <= 0)
726 return;
727
728 currententity = &cl.viewent;
729 if (!currententity->model)
730 return;
731
732 j = R_LightPoint (currententity->origin);
733
734 if (j < 24)
735 j = 24; // allways give some light on gun
736 ambientlight = j;
737 shadelight = j;
738
739 // add dynamic lights
740 for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
741 {
742 dl = &cl_dlights[lnum];
743 if (!dl->radius)
744 continue;
745 if (!dl->radius)
746 continue;
747 if (dl->die < cl.time)
748 continue;
749
750 VectorSubtract (currententity->origin, dl->origin, dist);
751 add = dl->radius - Length(dist);
752 if (add > 0)
753 ambientlight += add;
754 }
755
756 ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128;
757 diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128;
758
759 // hack the depth range to prevent view model from poking into walls
760 #ifdef USE_OPENGLES
761 glDepthRangef(gldepthmin, gldepthmin + 0.3f*(gldepthmax-gldepthmin));
762 R_DrawAliasModel (currententity);
763 glDepthRangef(gldepthmin, gldepthmax);
764 #else
765 glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
766 R_DrawAliasModel (currententity);
767 glDepthRange (gldepthmin, gldepthmax);
768 #endif
769 }
770
771
772 /*
773 ============
774 R_PolyBlend
775 ============
776 */
R_PolyBlend(void)777 void R_PolyBlend (void)
778 {
779 if (!gl_polyblend.value)
780 return;
781 if (!v_blend[3])
782 return;
783
784 //Con_Printf("R_PolyBlend(): %4.2f %4.2f %4.2f %4.2f\n",v_blend[0], v_blend[1], v_blend[2], v_blend[3]);
785
786 GL_DisableMultitexture();
787
788 glDisable (GL_ALPHA_TEST);
789 glEnable (GL_BLEND);
790 glDisable (GL_DEPTH_TEST);
791 glDisable (GL_TEXTURE_2D);
792
793 glLoadIdentity ();
794
795 glRotatef (-90, 1, 0, 0); // put Z going up
796 glRotatef (90, 0, 0, 1); // put Z going up
797
798 glColor4fv (v_blend);
799
800 #ifdef USE_OPENGLES
801 // !!! Implement this
802 #else
803 glBegin (GL_QUADS);
804
805 glVertex3f (10, 100, 100);
806 glVertex3f (10, -100, 100);
807 glVertex3f (10, -100, -100);
808 glVertex3f (10, 100, -100);
809 glEnd ();
810 #endif
811
812 glDisable (GL_BLEND);
813 glEnable (GL_TEXTURE_2D);
814 glEnable (GL_ALPHA_TEST);
815 }
816
817
SignbitsForPlane(mplane_t * out)818 int SignbitsForPlane (mplane_t *out)
819 {
820 int bits, j;
821
822 // for fast box on planeside test
823
824 bits = 0;
825 for (j=0 ; j<3 ; j++)
826 {
827 if (out->normal[j] < 0)
828 bits |= 1<<j;
829 }
830 return bits;
831 }
832
833
R_SetFrustum(void)834 void R_SetFrustum (void)
835 {
836 int i;
837
838 if (r_refdef.fov_x == 90)
839 {
840 // front side is visible
841
842 VectorAdd (vpn, vright, frustum[0].normal);
843 VectorSubtract (vpn, vright, frustum[1].normal);
844
845 VectorAdd (vpn, vup, frustum[2].normal);
846 VectorSubtract (vpn, vup, frustum[3].normal);
847 }
848 else
849 {
850
851 // rotate VPN right by FOV_X/2 degrees
852 RotatePointAroundVector( frustum[0].normal, vup, vpn, -(90-r_refdef.fov_x / 2 ) );
853 // rotate VPN left by FOV_X/2 degrees
854 RotatePointAroundVector( frustum[1].normal, vup, vpn, 90-r_refdef.fov_x / 2 );
855 // rotate VPN up by FOV_X/2 degrees
856 RotatePointAroundVector( frustum[2].normal, vright, vpn, 90-r_refdef.fov_y / 2 );
857 // rotate VPN down by FOV_X/2 degrees
858 RotatePointAroundVector( frustum[3].normal, vright, vpn, -( 90 - r_refdef.fov_y / 2 ) );
859 }
860
861 for (i=0 ; i<4 ; i++)
862 {
863 frustum[i].type = PLANE_ANYZ;
864 frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
865 frustum[i].signbits = SignbitsForPlane (&frustum[i]);
866 }
867 }
868
869
870
871 /*
872 ===============
873 R_SetupFrame
874 ===============
875 */
R_SetupFrame(void)876 void R_SetupFrame (void)
877 {
878 // don't allow cheats in multiplayer
879 r_fullbright.value = 0;
880 r_lightmap.value = 0;
881 if (!atoi(Info_ValueForKey(cl.serverinfo, "watervis")))
882 r_wateralpha.value = 1;
883
884 R_AnimateLight ();
885
886 r_framecount++;
887
888 // build the transformation matrix for the given view angles
889 VectorCopy (r_refdef.vieworg, r_origin);
890
891 AngleVectors (r_refdef.viewangles, vpn, vright, vup);
892
893 // current viewleaf
894 r_oldviewleaf = r_viewleaf;
895 r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
896
897 V_SetContentsColor (r_viewleaf->contents);
898 V_CalcBlend ();
899
900 r_cache_thrash = false;
901
902 c_brush_polys = 0;
903 c_alias_polys = 0;
904
905 }
906
907 #ifdef USE_OPENGLES
908
MYgluPerspective(float fovy,float aspect,float zNear,float zFar)909 void MYgluPerspective( float fovy, float aspect,
910 float zNear, float zFar )
911 {
912 float xmin, xmax, ymin, ymax;
913
914 ymax = zNear * tan( fovy * M_PI / 360.0f );
915 ymin = -ymax;
916
917 xmin = ymin * aspect;
918 xmax = ymax * aspect;
919
920 glFrustumf( xmin, xmax, ymin, ymax, zNear, zFar );
921 }
922
923 #else
924
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)925 void MYgluPerspective( GLdouble fovy, GLdouble aspect,
926 GLdouble zNear, GLdouble zFar )
927 {
928 GLdouble xmin, xmax, ymin, ymax;
929
930 ymax = zNear * tan( fovy * M_PI / 360.0 );
931 ymin = -ymax;
932
933 xmin = ymin * aspect;
934 xmax = ymax * aspect;
935
936 glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
937 }
938 #endif
939
940 /*
941 =============
942 R_SetupGL
943 =============
944 */
R_SetupGL(void)945 void R_SetupGL (void)
946 {
947 float screenaspect;
948 extern int glwidth, glheight;
949 int x, x2, y2, y, w, h;
950
951 //
952 // set up viewpoint
953 //
954 glMatrixMode(GL_PROJECTION);
955 glLoadIdentity ();
956 x = r_refdef.vrect.x * glwidth/vid.width;
957 x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
958 y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
959 y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
960
961 // fudge around because of frac screen scale
962 if (x > 0)
963 x--;
964 if (x2 < glwidth)
965 x2++;
966 if (y2 < 0)
967 y2--;
968 if (y < glheight)
969 y++;
970
971 w = x2 - x;
972 h = y - y2;
973
974 if (envmap)
975 {
976 x = y2 = 0;
977 w = h = 256;
978 }
979
980 glViewport (glx + x, gly + y2, w, h);
981 screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
982 // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
983 // yfov = (2.0 * tan (scr_fov.value/360*M_PI)) / screenaspect;
984 // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*(scr_fov.value*2)/M_PI;
985 // MYgluPerspective (yfov, screenaspect, 4, 4096);
986 MYgluPerspective (r_refdef.fov_y, screenaspect, 4, 4096);
987
988 if (mirror)
989 {
990 if (mirror_plane->normal[2])
991 glScalef (1, -1, 1);
992 else
993 glScalef (-1, 1, 1);
994 glCullFace(GL_BACK);
995 }
996 else
997 glCullFace(GL_FRONT);
998
999 glMatrixMode(GL_MODELVIEW);
1000 glLoadIdentity ();
1001
1002 glRotatef (-90, 1, 0, 0); // put Z going up
1003 glRotatef (90, 0, 0, 1); // put Z going up
1004 glRotatef (-r_refdef.viewangles[2], 1, 0, 0);
1005 glRotatef (-r_refdef.viewangles[0], 0, 1, 0);
1006 glRotatef (-r_refdef.viewangles[1], 0, 0, 1);
1007 glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
1008
1009 #ifdef USE_OPENGLES
1010 glGetIntegerv (MODELVIEW_MATRIX_FLOAT_AS_INT_BITS_OES, (GLint*) r_world_matrix);
1011 #else
1012 glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
1013 #endif
1014
1015 //
1016 // set drawing parms
1017 //
1018 if (gl_cull.value)
1019 glEnable(GL_CULL_FACE);
1020 else
1021 glDisable(GL_CULL_FACE);
1022
1023 glDisable(GL_BLEND);
1024 glDisable(GL_ALPHA_TEST);
1025 glEnable(GL_DEPTH_TEST);
1026 }
1027
1028 /*
1029 ================
1030 R_RenderScene
1031
1032 r_refdef must be set before the first call
1033 ================
1034 */
R_RenderScene(void)1035 void R_RenderScene (void)
1036 {
1037 R_SetupFrame ();
1038
1039 R_SetFrustum ();
1040
1041 R_SetupGL ();
1042
1043 R_MarkLeaves (); // done here so we know if we're in water
1044
1045 R_DrawWorld (); // adds static entities to the list
1046
1047 S_ExtraUpdate (); // don't let sound get messed up if going slow
1048
1049 R_DrawEntitiesOnList ();
1050
1051 GL_DisableMultitexture();
1052
1053 R_RenderDlights ();
1054
1055 R_DrawParticles ();
1056
1057 #ifdef GLTEST
1058 Test_Draw ();
1059 #endif
1060
1061 }
1062
1063
1064 /*
1065 =============
1066 R_Clear
1067 =============
1068 */
R_Clear(void)1069 void R_Clear (void)
1070 {
1071 if (r_mirroralpha.value != 1.0)
1072 {
1073 if (gl_clear.value)
1074 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1075 else
1076 glClear (GL_DEPTH_BUFFER_BIT);
1077 gldepthmin = 0;
1078 gldepthmax = 0.5;
1079 glDepthFunc (GL_LEQUAL);
1080 }
1081 else if (gl_ztrick.value)
1082 {
1083 static int trickframe;
1084
1085 if (gl_clear.value)
1086 glClear (GL_COLOR_BUFFER_BIT);
1087
1088 trickframe++;
1089 if (trickframe & 1)
1090 {
1091 gldepthmin = 0;
1092 gldepthmax = 0.49999;
1093 glDepthFunc (GL_LEQUAL);
1094 }
1095 else
1096 {
1097 gldepthmin = 1;
1098 gldepthmax = 0.5;
1099 glDepthFunc (GL_GEQUAL);
1100 }
1101 }
1102 else
1103 {
1104 if (gl_clear.value)
1105 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1106 else
1107 glClear (GL_DEPTH_BUFFER_BIT);
1108 gldepthmin = 0;
1109 gldepthmax = 1;
1110 glDepthFunc (GL_LEQUAL);
1111 }
1112
1113 #ifdef USE_OPENGLES
1114 glDepthRangef (gldepthmin, gldepthmax);
1115 #else
1116 glDepthRange (gldepthmin, gldepthmax);
1117 #endif
1118 }
1119
1120 #if 0 //!!! FIXME, Zoid, mirror is disabled for now
1121 /*
1122 =============
1123 R_Mirror
1124 =============
1125 */
1126 void R_Mirror (void)
1127 {
1128 float d;
1129 msurface_t *s;
1130 entity_t *ent;
1131
1132 if (!mirror)
1133 return;
1134
1135 memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix));
1136
1137 d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist;
1138 VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg);
1139
1140 d = DotProduct (vpn, mirror_plane->normal);
1141 VectorMA (vpn, -2*d, mirror_plane->normal, vpn);
1142
1143 r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180;
1144 r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180;
1145 r_refdef.viewangles[2] = -r_refdef.viewangles[2];
1146
1147 ent = &cl_entities[cl.viewentity];
1148 if (cl_numvisedicts < MAX_VISEDICTS)
1149 {
1150 cl_visedicts[cl_numvisedicts] = ent;
1151 cl_numvisedicts++;
1152 }
1153
1154 gldepthmin = 0.5;
1155 gldepthmax = 1;
1156 glDepthRange (gldepthmin, gldepthmax);
1157 glDepthFunc (GL_LEQUAL);
1158
1159 R_RenderScene ();
1160 R_DrawWaterSurfaces ();
1161
1162
1163 gldepthmin = 0;
1164 gldepthmax = 0.5;
1165 glDepthRange (gldepthmin, gldepthmax);
1166 glDepthFunc (GL_LEQUAL);
1167
1168 // blend on top
1169 glEnable (GL_BLEND);
1170 glMatrixMode(GL_PROJECTION);
1171 if (mirror_plane->normal[2])
1172 glScalef (1,-1,1);
1173 else
1174 glScalef (-1,1,1);
1175 glCullFace(GL_FRONT);
1176 glMatrixMode(GL_MODELVIEW);
1177
1178 glLoadMatrixf (r_base_world_matrix);
1179
1180 glColor4f (1,1,1,r_mirroralpha.value);
1181 s = cl.worldmodel->textures[mirrortexturenum]->texturechain;
1182 for ( ; s ; s=s->texturechain)
1183 R_RenderBrushPoly (s);
1184 cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL;
1185 glDisable (GL_BLEND);
1186 glColor4f (1,1,1,1);
1187 }
1188 #endif
1189
1190 /*
1191 ================
1192 R_RenderView
1193
1194 r_refdef must be set before the first call
1195 ================
1196 */
R_RenderView(void)1197 void R_RenderView (void)
1198 {
1199 double time1 = 0, time2;
1200
1201 if (r_norefresh.value)
1202 return;
1203
1204 if (!r_worldentity.model || !cl.worldmodel)
1205 Sys_Error ("R_RenderView: NULL worldmodel");
1206
1207 if (r_speeds.value)
1208 {
1209 glFinish ();
1210 time1 = Sys_DoubleTime ();
1211 c_brush_polys = 0;
1212 c_alias_polys = 0;
1213 }
1214
1215 mirror = false;
1216
1217 if (gl_finish.value)
1218 glFinish ();
1219
1220 R_Clear ();
1221
1222 // render normal view
1223 R_RenderScene ();
1224 R_DrawViewModel ();
1225 R_DrawWaterSurfaces ();
1226
1227 // render mirror view
1228 // R_Mirror ();
1229
1230 R_PolyBlend ();
1231
1232 if (r_speeds.value)
1233 {
1234 // glFinish ();
1235 time2 = Sys_DoubleTime ();
1236 Con_Printf ("%3i ms %4i wpoly %4i epoly\n", (int)((time2-time1)*1000), c_brush_polys, c_alias_polys);
1237 }
1238 }
1239