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