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 #include "neh.h"
24
25 entity_t r_worldentity;
26
27 qboolean r_cache_thrash; // compatability
28
29 vec3_t modelorg, r_entorigin;
30 entity_t *currententity;
31
32 int r_visframecount; // bumped when going to a new PVS
33 int r_framecount; // used for dlight push checking
34
35 mplane_t frustum[4];
36
37 int c_brush_polys, c_alias_polys;
38
39 qboolean envmap; // true during envmap command capture
40
41 int currenttexture = -1; // to avoid unnecessary texture sets
42
43 int cnttextures[2] = {-1, -1}; // cached
44
45 int particletexture; // little dot for particles
46 int playertextures; // up to 16 color translated skins
47 int skyboxtextures;
48
49 int mirrortexturenum; // quake texturenum, not gltexturenum
50 qboolean mirror;
51 mplane_t *mirror_plane;
52
53 //
54 // view origin
55 //
56 vec3_t vup;
57 vec3_t vpn;
58 vec3_t vright;
59 vec3_t r_origin;
60
61 float r_world_matrix[16];
62 float r_base_world_matrix[16];
63
64 //
65 // screen size info
66 //
67 refdef_t r_refdef;
68
69 mleaf_t *r_viewleaf, *r_oldviewleaf;
70
71 texture_t *r_notexture_mip;
72
73 int d_lightstylevalue[256]; // 8.8 fraction of base light value
74
75
76 void R_MarkLeaves (void);
77
78 // Nehahra - Interpolation
79 void GL_DrawAliasBlendedShadow (aliashdr_t *paliashdr, int pose1, int pose2, entity_t* e);
80 void R_BlendedRotateForEntity (entity_t *e);
81 void R_SetupAliasBlendedFrame (int frame, aliashdr_t *paliashdr, entity_t* e);
82 void GL_DrawAliasBlendedFrame (aliashdr_t *paliashdr, int pose1, int pose2, float blend);
83 // Nehahra - End
84
85 cvar_t r_norefresh = {"r_norefresh","0"};
86 cvar_t r_drawentities = {"r_drawentities","1"};
87 cvar_t r_drawviewmodel = {"r_drawviewmodel","1"};
88 cvar_t r_speeds = {"r_speeds","0"};
89 cvar_t r_fullbright = {"r_fullbright","0"};
90 cvar_t r_lightmap = {"r_lightmap","0"};
91 cvar_t r_shadows = {"r_shadows","0"};
92 cvar_t r_mirroralpha = {"r_mirroralpha","1"};
93 cvar_t r_wateralpha = {"r_wateralpha","1"};
94 cvar_t r_dynamic = {"r_dynamic","1"};
95 cvar_t r_novis = {"r_novis","0"};
96 cvar_t r_flatlightstyles = {"r_flatlightstyles", "0"};
97 cvar_t r_clearcolor = {"r_clearcolor", "251"}; // Closest to the original
98 cvar_t r_oldsky = {"r_oldsky", "1"};
99
100 cvar_t gl_finish = {"gl_finish","0"};
101 cvar_t gl_clear = {"gl_clear","0"};
102 cvar_t gl_cull = {"gl_cull","1"};
103 cvar_t gl_texsort = {"gl_texsort","1"};
104 cvar_t gl_smoothmodels = {"gl_smoothmodels","1"};
105 cvar_t gl_affinemodels = {"gl_affinemodels","0"};
106 cvar_t gl_polyblend = {"gl_polyblend","1"};
107 cvar_t gl_flashblend = {"gl_flashblend","0"};
108 cvar_t gl_playermip = {"gl_playermip","0"};
109 cvar_t gl_nocolors = {"gl_nocolors","0"};
110 cvar_t gl_keeptjunctions = {"gl_keeptjunctions","1"};
111 cvar_t gl_doubleeyes = {"gl_doubleeys", "1"};
112
113 extern cvar_t gl_ztrick;
114
115 // Nehahra - ender: Disabled. Now a define in neh.h
116 /*
117 =================
118 R_CullBox
119
120 Returns true if the box is completely outside the frustom
121 =================
122 */
R_CullBox(vec3_t mins,vec3_t maxs)123 qboolean R_CullBox (vec3_t mins, vec3_t maxs)
124 {
125 int i;
126
127 for (i=0 ; i<4 ; i++)
128 if (BoxOnPlaneSide (mins, maxs, &frustum[i]) == 2)
129 return true;
130 return false;
131 }
132
133
R_RotateForEntity(entity_t * e)134 void R_RotateForEntity (entity_t *e)
135 {
136 glTranslatef (e->origin[0], e->origin[1], e->origin[2]);
137
138 glRotatef (e->angles[1], 0, 0, 1);
139 glRotatef (-e->angles[0], 0, 1, 0);
140 glRotatef (e->angles[2], 1, 0, 0);
141 }
142
143 /*
144 =============================================================
145
146 SPRITE MODELS
147
148 =============================================================
149 */
150
151 /*
152 ================
153 R_GetSpriteFrame
154 ================
155 */
R_GetSpriteFrame(entity_t * currententity)156 mspriteframe_t *R_GetSpriteFrame (entity_t *currententity)
157 {
158 msprite_t *psprite;
159 mspritegroup_t *pspritegroup;
160 mspriteframe_t *pspriteframe;
161 int i, numframes, frame;
162 float *pintervals, fullinterval, targettime, time;
163 static float lastmsg = 0;
164
165 psprite = currententity->model->cache.data;
166 frame = currententity->frame;
167
168 if (frame >= psprite->numframes || frame < 0)
169 {
170 if (IsTimeout (&lastmsg, 2))
171 Con_Printf ("R_GetSpriteFrame: no such frame %d (%d frames) in %s\n", frame, psprite->numframes, currententity->model->name);
172
173 frame = 0;
174 }
175
176 if (psprite->frames[frame].type == SPR_SINGLE)
177 {
178 pspriteframe = psprite->frames[frame].frameptr;
179 }
180 else
181 {
182 pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr;
183 pintervals = pspritegroup->intervals;
184 numframes = pspritegroup->numframes;
185 fullinterval = pintervals[numframes-1];
186
187 time = cl.time + currententity->syncbase;
188
189 // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values
190 // are positive, so we don't have to worry about division by 0
191 targettime = time - ((int)(time / fullinterval)) * fullinterval;
192
193 for (i=0 ; i<(numframes-1) ; i++)
194 {
195 if (pintervals[i] > targettime)
196 break;
197 }
198
199 pspriteframe = pspritegroup->frames[i];
200 }
201
202 return pspriteframe;
203 }
204
205
206 /*
207 =================
208 R_DrawSpriteModel
209
210 =================
211 */
R_DrawSpriteModel(entity_t * e)212 void R_DrawSpriteModel (entity_t *e)
213 {
214 vec3_t point;
215 mspriteframe_t *frame;
216 float *up, *right;
217 vec3_t v_forward, v_right, v_up;
218 msprite_t *psprite;
219
220 // if (currententity->effects & EF_ADDITIVE)
221 // glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
222 // else
223 // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
224
225 // glEnable(GL_BLEND);
226 // glDepthMask(0); // disable zbuffer updates
227
228 // don't even bother culling, because it's just a single
229 // polygon without a surface cache
230 frame = R_GetSpriteFrame (e);
231 psprite = currententity->model->cache.data;
232
233 if (psprite->type == SPR_ORIENTED)
234 { // bullet marks on walls
235 AngleVectors (currententity->angles, v_forward, v_right, v_up);
236 up = v_up;
237 right = v_right;
238 }
239 else
240 { // normal sprite
241 up = vup;
242 right = vright;
243 }
244
245 glColor3f (1,1,1);
246
247 GL_DisableMultitexture();
248
249 GL_Bind(frame->gl_texturenum);
250
251 glEnable (GL_ALPHA_TEST);
252 glBegin (GL_QUADS);
253
254 glTexCoord2f (0, 1);
255 VectorMA (e->origin, frame->down, up, point);
256 VectorMA (point, frame->left, right, point);
257 glVertex3fv (point);
258
259 glTexCoord2f (0, 0);
260 VectorMA (e->origin, frame->up, up, point);
261 VectorMA (point, frame->left, right, point);
262 glVertex3fv (point);
263
264 glTexCoord2f (1, 0);
265 VectorMA (e->origin, frame->up, up, point);
266 VectorMA (point, frame->right, right, point);
267 glVertex3fv (point);
268
269 glTexCoord2f (1, 1);
270 VectorMA (e->origin, frame->down, up, point);
271 VectorMA (point, frame->right, right, point);
272 glVertex3fv (point);
273
274 glEnd ();
275
276 glDisable (GL_ALPHA_TEST);
277
278 // if (currententity->effects & EF_ADDITIVE)
279 // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // normal alpha blend
280 // glDisable(GL_BLEND);
281 // glDepthMask(1); // enable zbuffer updates
282 }
283
284 /*
285 =============================================================
286
287 ALIAS MODELS
288
289 =============================================================
290 */
291
292
293 #define NUMVERTEXNORMALS 162
294
295 float r_avertexnormals[NUMVERTEXNORMALS][3] = {
296 #include "anorms.h"
297 };
298
299 vec3_t shadevector;
300 float shadelight, ambientlight;
301
302 // precalculated dot products for quantized angles
303 #define SHADEDOT_QUANT 16
304 float r_avertexnormal_dots[SHADEDOT_QUANT][256] =
305 #include "anorm_dots.h"
306 ;
307
308 float *shadedots = r_avertexnormal_dots[0];
309
310 int lastposenum;
311 int lastposenum0; // Nehahra - Interpolation
312
313 /*
314 =============
315 GL_DrawAliasFrame
316 =============
317 */
GL_DrawAliasFrame(aliashdr_t * paliashdr,int posenum)318 void GL_DrawAliasFrame (aliashdr_t *paliashdr, int posenum)
319 {
320 float s, t;
321 float l;
322 int i, j;
323 int index;
324 trivertx_t *v, *verts;
325 int list;
326 int *order;
327 vec3_t point;
328 float *normal;
329 int count;
330
331 lastposenum = posenum;
332
333 verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
334 verts += posenum * paliashdr->poseverts;
335 order = (int *)((byte *)paliashdr + paliashdr->commands);
336
337 while (1)
338 {
339 // get the vertex count and primitive type
340 count = *order++;
341 if (!count)
342 break; // done
343 if (count < 0)
344 {
345 count = -count;
346 glBegin (GL_TRIANGLE_FAN);
347 }
348 else
349 glBegin (GL_TRIANGLE_STRIP);
350
351 do
352 {
353 // texture coordinates come from the draw list
354 glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
355 order += 2;
356
357 if (r_fullbright.value || !cl.worldmodel->lightdata)
358 l = 1;
359 else
360 // normals and vertexes come from the frame list
361 l = shadedots[verts->lightnormalindex] * shadelight;
362
363 // Nehahra - Model_alpha
364 if (model_alpha != 1.0)
365 glColor4f (l, l, l, model_alpha);
366 else
367 glColor3f (l, l, l);
368 // Nehahra - End
369
370 glVertex3f (verts->v[0], verts->v[1], verts->v[2]);
371 verts++;
372 } while (--count);
373
374 glEnd ();
375 }
376 }
377
378
379 /*
380 =============
381 GL_DrawAliasShadow
382 =============
383 */
384 extern vec3_t lightspot;
385
GL_DrawAliasShadow(aliashdr_t * paliashdr,int posenum)386 void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum)
387 {
388 float s, t, l;
389 int i, j;
390 int index;
391 trivertx_t *v, *verts;
392 int list;
393 int *order;
394 vec3_t point;
395 float *normal;
396 float height, lheight;
397 int count;
398
399 lheight = currententity->origin[2] - lightspot[2];
400
401 height = 0;
402 verts = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
403 verts += posenum * paliashdr->poseverts;
404 order = (int *)((byte *)paliashdr + paliashdr->commands);
405
406 height = -lheight + 1.0;
407
408 while (1)
409 {
410 // get the vertex count and primitive type
411 count = *order++;
412 if (!count)
413 break; // done
414 if (count < 0)
415 {
416 count = -count;
417 glBegin (GL_TRIANGLE_FAN);
418 }
419 else
420 glBegin (GL_TRIANGLE_STRIP);
421
422 do
423 {
424 // texture coordinates come from the draw list
425 // (skipped for shadows) glTexCoord2fv ((float *)order);
426 order += 2;
427
428 // normals and vertexes come from the frame list
429 point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
430 point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
431 point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
432
433 point[0] -= shadevector[0]*(point[2]+lheight);
434 point[1] -= shadevector[1]*(point[2]+lheight);
435 point[2] = height;
436 // height -= 0.001;
437 glVertex3fv (point);
438
439 verts++;
440 } while (--count);
441
442 glEnd ();
443 }
444 }
445
446 /*
447 =================
448 R_ChkFrame
449 =================
450 */
R_ChkFrame(char * function,int frame,aliashdr_t * pahdr,float * plastmsg)451 int R_ChkFrame (char *function, int frame, aliashdr_t *pahdr, float *plastmsg)
452 {
453 if (frame >= pahdr->numframes || frame < 0)
454 {
455 if (IsTimeout (plastmsg, 2))
456 {
457 Con_DPrintf ("%s: no such frame ", function);
458
459 // Single frame?
460 if (pahdr->frames[0].name[0])
461 Con_DPrintf ("%d ('%s', %d frames)", frame, pahdr->frames[0].name, pahdr->numframes);
462 else
463 Con_DPrintf ("group %d (%d groups)", frame, pahdr->numframes);
464
465 Con_DPrintf (" in %s\n", currententity->model->name);
466 }
467
468 frame = 0;
469 }
470
471 return frame;
472 }
473
474 /*
475 =================
476 R_SetupAliasFrame
477
478 =================
479 */
R_SetupAliasFrame(int frame,aliashdr_t * paliashdr)480 void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr)
481 {
482 int pose, numposes;
483 float interval;
484 static float lastmsg = 0;
485
486 frame = R_ChkFrame ("R_SetupAliasFrame", frame, paliashdr, &lastmsg);
487
488 pose = paliashdr->frames[frame].firstpose;
489 numposes = paliashdr->frames[frame].numposes;
490
491 if (numposes > 1)
492 {
493 int firstpose = pose;
494
495 pose = numposes * currententity->syncbase; // Hack to make flames unsynchronized
496 interval = paliashdr->frames[frame].interval;
497 pose += (int)(cl.time / interval) % numposes;
498 pose = firstpose + pose % numposes;
499 }
500
501 GL_DrawAliasFrame (paliashdr, pose);
502 }
503
504 /*
505 =================
506 R_DrawAliasModel
507
508 =================
509 */
R_DrawAliasModel(entity_t * e,int cull)510 void R_DrawAliasModel (entity_t *e, int cull)
511 {
512 int i, j;
513 int lnum;
514 vec3_t dist;
515 float add;
516 model_t *clmodel;
517 vec3_t mins, maxs;
518 aliashdr_t *paliashdr;
519 trivertx_t *verts, *v;
520 int index;
521 float s, t, an;
522 int anim;
523 qboolean torch = false;
524 int skinnum;
525 static float lastmsg = 0;
526
527 clmodel = currententity->model;
528 // Nehahra - Model_Alpha
529 if (!gl_notrans.value)
530 {
531 model_alpha = currententity->transparency;
532 if (model_alpha == 0)
533 model_alpha = 1;
534 }
535 else
536 model_alpha = 1;
537 // Nehahra - End
538
539 if (e == &cl.viewent)
540 if (cl.items & IT_INVISIBILITY)
541 model_alpha = 0.2;
542
543 VectorAdd (currententity->origin, clmodel->mins, mins);
544 VectorAdd (currententity->origin, clmodel->maxs, maxs);
545
546 if (cull && R_CullBox (mins, maxs))
547 return;
548
549
550 VectorCopy (currententity->origin, r_entorigin);
551 VectorSubtract (r_origin, r_entorigin, modelorg);
552
553 //
554 // get lighting information
555 //
556
557 ambientlight = shadelight = R_LightPoint (currententity->origin);
558
559 // allways give the gun some light
560 if (e == &cl.viewent && ambientlight < 24)
561 ambientlight = shadelight = 24;
562
563 for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++)
564 {
565 if (cl_dlights[lnum].die >= cl.time)
566 {
567 VectorSubtract (currententity->origin,
568 cl_dlights[lnum].origin,
569 dist);
570 add = cl_dlights[lnum].radius - Length(dist);
571
572 if (add > 0) {
573 ambientlight += add;
574 //ZOID models should be affected by dlights as well
575 shadelight += add;
576 }
577 }
578 }
579
580 // clamp lighting so it doesn't overbright as much
581 if (ambientlight > 128)
582 ambientlight = 128;
583 if (ambientlight + shadelight > 192)
584 shadelight = 192 - ambientlight;
585
586 // ZOID: never allow players to go totally black
587 i = currententity - cl_entities;
588 if (i >= 1 && i<=cl.maxclients)
589 if (ambientlight < 8)
590 ambientlight = shadelight = 8;
591
592 if (clmodel->fullbright)
593 {
594 ambientlight = shadelight = 255;
595 torch = true;
596 }
597 else if (gl_autobright.value)
598 {
599 int autobright = gl_autobright.value - 1;
600
601 // Clamp
602 if (autobright < 0)
603 autobright = 0;
604 else if (autobright > AUTOBRIGHTS - 1)
605 autobright = AUTOBRIGHTS - 1;
606
607 autobright = clmodel->autobright[autobright];
608
609 if (autobright)
610 {
611 if (autobright == 255)
612 torch = true;
613
614 if (gl_autobright.value > AUTOBRIGHTS)
615 {
616 // High intensity
617 autobright += 50;
618
619 if (autobright > 255)
620 autobright = 255;
621 }
622
623 ambientlight = shadelight = autobright;
624 }
625 }
626
627 shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
628 shadelight = shadelight / 200.0;
629
630 an = e->angles[1]/180*M_PI;
631 shadevector[0] = cos(-an);
632 shadevector[1] = sin(-an);
633 shadevector[2] = 1;
634 VectorNormalize (shadevector);
635
636 //
637 // locate the proper data
638 //
639 paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
640
641 c_alias_polys += paliashdr->numtris;
642
643 skinnum = currententity->skinnum;
644
645 // check skin bounds
646 if (skinnum >= paliashdr->numskins || skinnum < 0)
647 {
648 if (IsTimeout (&lastmsg, 2))
649 Con_DPrintf ("R_DrawAliasModel: no such skin %d (%d skins) in %s\n", skinnum, paliashdr->numskins, clmodel->name);
650
651 skinnum = 0;
652 }
653
654 //
655 // draw all the triangles
656 //
657
658 GL_DisableMultitexture();
659
660 glPushMatrix ();
661 // fenix@io.com: model transform interpolation
662 if (r_interpolate_model_transform.value && !torch) {
663 R_BlendedRotateForEntity (e);
664 } else {
665 R_RotateForEntity (e);
666 }
667
668 if (clmodel->eyes && gl_doubleeyes.value) {
669 glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8));
670 // double size of eyes, since they are really hard to see in gl
671 glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2);
672 } else {
673 glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]);
674 glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]);
675 }
676
677 anim = (int)(cl.time*10) & 3;
678 GL_Bind(paliashdr->gl_texturenum[skinnum][anim]);
679
680 // we can't dynamically colormap textures, so they are cached
681 // seperately for the players. Heads are just uncolored.
682 if (currententity->colormap != vid.colormap && !gl_nocolors.value)
683 {
684 i = currententity - cl_entities;
685 if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */)
686 GL_Bind(playertextures - 1 + i);
687 }
688
689 if (gl_smoothmodels.value)
690 glShadeModel (GL_SMOOTH);
691 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
692
693 if (gl_affinemodels.value)
694 glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
695
696 // fenix@io.com: model animation interpolation
697 if (r_interpolate_model_animation.value)
698 {
699 R_SetupAliasBlendedFrame (currententity->frame, paliashdr, currententity);
700 }
701 else
702 {
703 R_SetupAliasFrame (currententity->frame, paliashdr);
704 }
705
706 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
707
708 glShadeModel (GL_FLAT);
709 if (gl_affinemodels.value)
710 glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
711
712 glPopMatrix ();
713
714 // Nehahra - Model_Alpha
715 if (model_alpha != 1.0) {
716 glDisable (GL_BLEND);
717 glColor4f (1,1,1,1);
718 }
719 // Nehahra - End
720
721 if (!gl_glows.value)
722 return;
723
724 if (torch || (clmodel->candle || clmodel->lantern) && gl_autobright.value ||
725 clmodel->bolt || clmodel->missile || clmodel->quaddama || clmodel->invulner)
726 {
727
728 const int TORCH_STYLE = 1; // Flicker.
729 vec3_t lightorigin; // Origin of glow.
730 vec3_t v; // Vector to torch.
731 float radius; // Radius of torch flare.
732 float distance; // Vector distance to torch.
733 float intensity; // Intensity of torch flare.
734
735 VectorCopy(currententity->origin, lightorigin);
736
737 //set radius based on what model we are doing here
738 //jf 00-05-28 set the radius large when missile first appears
739 if (torch)
740 radius = 30.0;
741 else if (clmodel->candle)
742 radius = 15.0;
743 else if (clmodel->lantern)
744 radius = 25.0;
745 else if (clmodel->missile)
746 {
747 if (currententity->forcelink)
748 radius = 80.0f;
749 else
750 radius = 20.0f;
751 }
752 else if (clmodel->bolt)
753 radius = 30.0f;
754 else if (clmodel->quaddama || clmodel->invulner)
755 radius = 50.0f;
756
757 VectorSubtract(lightorigin, r_origin, v);
758
759 // See if view is outside the light.
760 distance = Length(v);
761 if (distance > radius) {
762
763 glDepthMask (0);
764 glDisable (GL_TEXTURE_2D);
765 glShadeModel (GL_SMOOTH);
766 glEnable (GL_BLEND);
767 glBlendFunc (GL_ONE, GL_ONE);
768
769 //2000-04-29 Translate the glow to coincide with the flame. KH
770 // or be at the tail of the missile - muff
771 // or the Quad or Pent - muff
772 glPushMatrix();
773 if (torch)
774 glTranslatef(0.0f, 0.0f, 10.0f); //jf 2000-04-10 was 0,0,8... up a tad.
775 else if (clmodel->candle)
776 glTranslatef(0.0f, 0.0f, clmodel->maxs[2] - 5.0f); // Adapt to model
777 else if (clmodel->lantern)
778 glTranslatef (0.0f, 0.0f, clmodel->maxs[2] - 35.0f);
779 else if (clmodel->missile)
780 {
781 //move the glow behind the rocket
782 glTranslatef (cos( e->angles[1]/180*M_PI)*(-20.0f),
783 sin( e->angles[1]/180*M_PI)*(-20.0f),
784 sin( e->angles[0]/180*M_PI)*(-20.0f));
785 }
786 else if (clmodel->quaddama || clmodel->invulner)
787 glTranslatef(0.0f, 0.0f, 20.0f);
788
789 glBegin(GL_TRIANGLE_FAN);
790
791
792 // Invert (fades as you approach) - if we are a torch
793 if (torch || clmodel->candle || clmodel->lantern)
794 {
795 // Diminish torch flare inversely with distance.
796 intensity = (1024.0f - distance) / 1024.0f;
797 intensity = (1.0f - intensity);
798 }
799 // or fix settings if lightning or missile
800 else if (clmodel->bolt)
801 intensity = 0.2f;
802 else if (clmodel->missile)
803 intensity = 0.4f;
804 else if (clmodel->quaddama || clmodel->invulner)
805 intensity = 0.3f;
806
807 // Clamp, but don't let the flare disappear.
808 if (intensity > 1.0f) intensity = 1.0f;
809 if (intensity < 0.0f) intensity = 0.0f;
810
811 // Now modulate with flicker.
812 i = (int)(cl.time*10);
813 if (!cl_lightstyle[TORCH_STYLE].length) {
814 j = 256;
815 }
816 else {
817 j = i % cl_lightstyle[TORCH_STYLE].length;
818 j = cl_lightstyle[TORCH_STYLE].map[j] - 'a';
819 j = j*22;
820 }
821 intensity *= ((float)j / 255.0f);
822
823 // Set yellow intensity
824
825 //2000-04-10 set the colour of the glow - muff
826 if (torch || clmodel->candle || clmodel->lantern)
827 glColor3f(0.4f*intensity, 0.2f*intensity, 0.05f);
828 else if (clmodel->missile)
829 glColor3f(0.9f*intensity, 0.2f*intensity, 0.1f*intensity);
830 else if (clmodel->bolt)
831 glColor3f(0.2f*intensity, 0.2f*intensity, 0.8f*intensity);
832 else if (clmodel->quaddama)
833 glColor3f(0.8f*intensity, 0.8f*intensity, 0.1f*intensity);
834 else if (clmodel->invulner)
835 glColor3f(0.8f*intensity, 0.1f*intensity, 0.1f*intensity);
836
837 for (i=0 ; i<3 ; i++)
838 v[i] = lightorigin[i] - vpn[i]*radius;
839 glVertex3fv(v);
840 glColor3f(0.0f, 0.0f, 0.0f);
841 for (i=16; i>=0; i--) {
842 float a = i/16.0f * M_PI*2;
843 for (j=0; j<3; j++)
844 v[j] = lightorigin[j] +
845 vright[j]*cos(a)*radius +
846 vup[j]*sin(a)*radius;
847 glVertex3fv(v);
848 }
849 glEnd();
850
851 // Restore previous matrix! KH
852 glPopMatrix();
853
854 glColor3f (1,1,1);
855 glDisable (GL_BLEND);
856 glEnable (GL_TEXTURE_2D);
857 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
858 glDepthMask (1);
859
860 }
861 }
862
863 }
864
865 //==================================================================================
866
867 /*
868 =============
869 R_DrawEntitiesOnList
870 =============
871 */
R_DrawEntitiesOnList(void)872 void R_DrawEntitiesOnList (void)
873 {
874 int i;
875
876 if (!r_drawentities.value)
877 return;
878
879 // draw sprites seperately, because of alpha blending
880 for (i=0 ; i<cl_numvisedicts ; i++)
881 {
882 if ((i + 1) % 100 == 0)
883 S_ExtraUpdateTime (); // don't let sound get messed up if going slow
884
885 currententity = cl_visedicts[i];
886
887 if (currententity == &cl_entities[cl.viewentity])
888 {
889 // chase_active.value not checked as player model is necessary for shadows
890 currententity->angles[0] *= 0.3;
891 }
892
893 // Nehahra - Model_Alpha
894
895 if (currententity->transparency != 1 && currententity->transparency != 0 && !gl_notrans.value)
896 {
897 currententity->transignore = false;//model_alpha
898 continue; // draw transparent entities last (?)
899 }
900 // Nehahra - End
901
902 switch (currententity->model->type)
903 {
904 case mod_alias:
905 #ifdef _WIN32
906 R_DrawAliasModel (currententity, TRUE);
907 #else
908 R_DrawAliasModel (currententity, true);
909 #endif
910 break;
911
912 case mod_brush:
913 R_DrawBrushModel (currententity);
914 break;
915
916 default:
917 break;
918 }
919 }
920
921 for (i=0 ; i<cl_numvisedicts ; i++)
922 {
923 currententity = cl_visedicts[i];
924
925 switch (currententity->model->type)
926 {
927 case mod_sprite:
928 R_DrawSpriteModel (currententity);
929 break;
930 }
931 }
932 }
933
934 // Nehahra - Model_Alpha (Function by FrikaC)
935 /*
936 =============
937 R_DrawTransEntities
938 =============
939 */
R_DrawTransEntities(void)940 void R_DrawTransEntities (void)
941 {
942 // need to draw back to front
943 // fixme: this isn't my favorite option
944 int i;
945 float bestdist, dist;
946 entity_t *bestent;
947 vec3_t start, test;
948
949 VectorCopy(r_refdef.vieworg, start);
950
951 if (!r_drawentities.value)
952 return;
953
954 transgetent:
955 bestdist = 0;
956 for (i=0 ; i<cl_numvisedicts ; i++)
957 {
958 currententity = cl_visedicts[i];
959 if (currententity->transignore)
960 continue;
961 if (currententity->transparency == 1 || currententity->transparency ==0)
962 continue;
963
964 VectorCopy(currententity->origin, test);
965 if (currententity->model->type == mod_brush)
966 {
967 test[0] += currententity->model->mins[0];
968 test[1] += currententity->model->mins[1];
969 test[2] += currententity->model->mins[2];
970 }
971 dist = (((test[0] - start[0]) * (test[0] - start[0])) +
972 ((test[1] - start[1]) * (test[1] - start[1])) +
973 ((test[2] - start[2]) * (test[2] - start[2])));
974
975 if (dist > bestdist)
976 {
977 bestdist = dist;
978 bestent = currententity;
979
980 }
981 }
982 if (bestdist == 0)
983 return;
984 bestent->transignore = true;
985
986 currententity = bestent;
987 switch (currententity->model->type)
988 {
989 case mod_alias:
990 #ifdef _WIN32
991 R_DrawAliasModel (currententity, TRUE);
992 #else
993 R_DrawAliasModel (currententity, true);
994 #endif
995 break;
996 case mod_brush:
997 R_DrawBrushModel (currententity);
998 break;
999 default:
1000 break;
1001 }
1002
1003 goto transgetent;
1004
1005 }
1006
1007 /*
1008 =============
1009 R_DrawViewModel
1010 =============
1011 */
R_DrawViewModel(void)1012 void R_DrawViewModel (void)
1013 {
1014 float old_interpolate_model_transform;
1015
1016 if (!r_drawviewmodel.value)
1017 return;
1018
1019 if (chase_active.value)
1020 return;
1021
1022 if (envmap)
1023 return;
1024
1025 if (!r_drawentities.value)
1026 return;
1027
1028 if (cl.items & IT_INVISIBILITY)
1029 return;
1030
1031 if (cl.stats[STAT_HEALTH] <= 0)
1032 return;
1033
1034 currententity = &cl.viewent;
1035 if (!currententity->model)
1036 return;
1037
1038 // Prevent weapon model error
1039 if (currententity->model->name[0] == '*')
1040 {
1041 Con_Printf ("\x02R_DrawViewModel: ");
1042 Con_Printf ("viewmodel %s invalid\n", currententity->model->name);
1043 Cvar_Set ("r_drawviewmodel", "0");
1044 return;
1045 }
1046
1047 currententity->transparency = model_alpha = cl_entities[cl.viewentity].transparency; // LordHavoc: if the player is transparent, so is his gun
1048 currententity->effects = cl_entities[cl.viewentity].effects;
1049
1050 // hack the depth range to prevent view model from poking into walls
1051 glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
1052
1053 // fenix@io.com: model transform interpolation
1054 old_interpolate_model_transform = r_interpolate_model_transform.value;
1055 r_interpolate_model_transform.value = false;
1056 #ifdef _WIN32
1057 R_DrawAliasModel (currententity, FALSE);
1058 #else
1059 R_DrawAliasModel (currententity, false);
1060 #endif
1061 r_interpolate_model_transform.value = old_interpolate_model_transform;
1062
1063 glDepthRange (gldepthmin, gldepthmax);
1064 }
1065
1066
1067 /*
1068 ============
1069 R_PolyBlend
1070 ============
1071 */
R_PolyBlend(void)1072 void R_PolyBlend (void)
1073 {
1074 if (!gl_polyblend.value)
1075 return;
1076 if (!v_blend[3])
1077 return;
1078
1079 GL_DisableMultitexture();
1080
1081 glDisable (GL_ALPHA_TEST);
1082 glEnable (GL_BLEND);
1083 glDisable (GL_DEPTH_TEST);
1084 glDisable (GL_TEXTURE_2D);
1085
1086 glLoadIdentity ();
1087
1088 glRotatef (-90, 1, 0, 0); // put Z going up
1089 glRotatef (90, 0, 0, 1); // put Z going up
1090
1091 glColor4fv (v_blend);
1092
1093 glBegin (GL_QUADS);
1094
1095 glVertex3f (10, 100, 100);
1096 glVertex3f (10, -100, 100);
1097 glVertex3f (10, -100, -100);
1098 glVertex3f (10, 100, -100);
1099 glEnd ();
1100
1101 glDisable (GL_BLEND);
1102 glEnable (GL_TEXTURE_2D);
1103 glEnable (GL_ALPHA_TEST);
1104 }
1105
1106
SignbitsForPlane(mplane_t * out)1107 int SignbitsForPlane (mplane_t *out)
1108 {
1109 int bits, j;
1110
1111 // for fast box on planeside test
1112
1113 bits = 0;
1114 for (j=0 ; j<3 ; j++)
1115 {
1116 if (out->normal[j] < 0)
1117 bits |= 1<<j;
1118 }
1119 return bits;
1120 }
1121
1122 /*
1123 ===============
1124 TurnVector
1125
1126 turn forward towards side on the plane defined by forward and side
1127 if angle = 90, the result will be equal to side
1128 assumes side and forward are perpendicular, and normalized
1129 to turn away from side, use a negative angle
1130 ===============
1131 */
TurnVector(vec3_t out,vec3_t forward,vec3_t side,float angle)1132 void TurnVector (vec3_t out, vec3_t forward, vec3_t side, float angle)
1133 {
1134 float scale_forward, scale_side;
1135
1136 scale_forward = cos (DEG2RAD(angle));
1137 scale_side = sin (DEG2RAD(angle));
1138
1139 out[0] = scale_forward*forward[0] + scale_side*side[0];
1140 out[1] = scale_forward*forward[1] + scale_side*side[1];
1141 out[2] = scale_forward*forward[2] + scale_side*side[2];
1142 }
1143
1144 /*
1145 ===============
1146 R_SetFrustum
1147 ===============
1148 */
R_SetFrustum(void)1149 void R_SetFrustum (void)
1150 {
1151 int i;
1152
1153 TurnVector (frustum[0].normal, vpn, vright, r_refdef.fov_x/2 - 90); //left plane
1154 TurnVector (frustum[1].normal, vpn, vright, 90 - r_refdef.fov_x/2); //right plane
1155 TurnVector (frustum[2].normal, vpn, vup, 90 - r_refdef.fov_y/2); //bottom plane
1156 TurnVector (frustum[3].normal, vpn, vup, r_refdef.fov_y/2 - 90); //top plane
1157
1158 for (i=0 ; i<4 ; i++)
1159 {
1160 frustum[i].type = PLANE_ANYZ;
1161 frustum[i].dist = DotProduct (r_origin, frustum[i].normal);
1162 frustum[i].signbits = SignbitsForPlane (&frustum[i]);
1163 }
1164 }
1165
1166 /*
1167 ===============
1168 R_CheckVariables
1169 ===============
1170 */
R_CheckVariables(void)1171 void R_CheckVariables (void)
1172 {
1173 static float oldbright = 0, oldclear = 0, oldgamma = 0, oldmodvolume = 0;
1174
1175 if (r_fullbright.value != oldbright)
1176 {
1177 oldbright = r_fullbright.value;
1178
1179 // Refresh view
1180 GL_RefreshLightMaps ();
1181 }
1182
1183 if (r_clearcolor.value != oldclear)
1184 {
1185 byte *rgb;
1186
1187 oldclear = r_clearcolor.value;
1188
1189 // Refresh view
1190 rgb = (byte *)(d_8to24table + ((int)r_clearcolor.value & 0xFF));
1191 glClearColor (rgb[0] / 255.0, rgb[1] / 255.0, rgb[2] / 255.0, 0);
1192 }
1193
1194 if (v_gamma.value != oldgamma)
1195 {
1196 oldgamma = v_gamma.value;
1197 #ifdef _WIN32
1198 // Refresh view
1199 VID_Gamma_f ();
1200 #endif
1201 }
1202
1203 if (modvolume.value != oldmodvolume)
1204 {
1205 oldmodvolume = modvolume.value;
1206
1207 // Refresh
1208 MOD_SetVolume_f ();
1209 }
1210 }
1211
1212 /*
1213 ===============
1214 R_SetupFrame
1215 ===============
1216 */
R_SetupFrame(void)1217 void R_SetupFrame (void)
1218 {
1219 int edgecount;
1220 vrect_t vrect;
1221 float w, h;
1222
1223 // don't allow cheats in multiplayer
1224 if (cl.maxclients > 1)
1225 Cvar_Set ("r_fullbright", "0");
1226
1227 R_CheckVariables ();
1228
1229 R_AnimateLight ();
1230
1231 r_framecount++;
1232
1233 // build the transformation matrix for the given view angles
1234 VectorCopy (r_refdef.vieworg, r_origin);
1235
1236 AngleVectors (r_refdef.viewangles, vpn, vright, vup);
1237
1238 // current viewleaf
1239 r_oldviewleaf = r_viewleaf;
1240 r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel);
1241
1242 V_SetContentsColor (r_viewleaf->contents);
1243 V_CalcBlend ();
1244
1245 r_cache_thrash = false;
1246
1247 c_brush_polys = 0;
1248 c_alias_polys = 0;
1249
1250 }
1251
1252
MYgluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)1253 void MYgluPerspective( GLdouble fovy, GLdouble aspect,
1254 GLdouble zNear, GLdouble zFar )
1255 {
1256 GLdouble xmin, xmax, ymin, ymax;
1257
1258 ymax = zNear * tan( fovy * M_PI / 360.0 );
1259 ymin = -ymax;
1260
1261 xmin = ymin * aspect;
1262 xmax = ymax * aspect;
1263
1264 glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
1265 }
1266
1267
1268 /*
1269 =============
1270 R_SetupGL
1271 =============
1272 */
R_SetupGL(void)1273 void R_SetupGL (void)
1274 {
1275 float screenaspect;
1276 float yfov;
1277 int i;
1278 extern int glwidth, glheight;
1279 int x, x2, y2, y, w, h;
1280
1281 //
1282 // set up viewpoint
1283 //
1284 glMatrixMode(GL_PROJECTION);
1285 glLoadIdentity ();
1286 x = r_refdef.vrect.x * glwidth/vid.width;
1287 x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * glwidth/vid.width;
1288 y = (vid.height-r_refdef.vrect.y) * glheight/vid.height;
1289 y2 = (vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * glheight/vid.height;
1290
1291 // fudge around because of frac screen scale
1292 if (x > 0)
1293 x--;
1294 if (x2 < glwidth)
1295 x2++;
1296 if (y2 < 0)
1297 y2--;
1298 if (y < glheight)
1299 y++;
1300
1301 w = x2 - x;
1302 h = y - y2;
1303
1304 if (envmap)
1305 {
1306 x = y2 = 0;
1307 w = h = 256;
1308 }
1309
1310 glViewport (glx + x, gly + y2, w, h);
1311 screenaspect = (float)r_refdef.vrect.width/r_refdef.vrect.height;
1312 // yfov = 2*atan((float)r_refdef.vrect.height/r_refdef.vrect.width)*180/M_PI;
1313 MYgluPerspective (r_refdef.fov_y, screenaspect, 4, GL_FARCLIP); //6144
1314
1315 if (mirror)
1316 {
1317 if (mirror_plane->normal[2])
1318 glScalef (1, -1, 1);
1319 else
1320 glScalef (-1, 1, 1);
1321 glCullFace(GL_BACK);
1322 }
1323 else
1324 glCullFace(GL_FRONT);
1325
1326 glMatrixMode(GL_MODELVIEW);
1327 glLoadIdentity ();
1328
1329 glRotatef (-90, 1, 0, 0); // put Z going up
1330 glRotatef (90, 0, 0, 1); // put Z going up
1331 glRotatef (-r_refdef.viewangles[2], 1, 0, 0);
1332 glRotatef (-r_refdef.viewangles[0], 0, 1, 0);
1333 glRotatef (-r_refdef.viewangles[1], 0, 0, 1);
1334 glTranslatef (-r_refdef.vieworg[0], -r_refdef.vieworg[1], -r_refdef.vieworg[2]);
1335
1336 glGetFloatv (GL_MODELVIEW_MATRIX, r_world_matrix);
1337
1338 //
1339 // set drawing parms
1340 //
1341 if (gl_cull.value)
1342 glEnable(GL_CULL_FACE);
1343 else
1344 glDisable(GL_CULL_FACE);
1345
1346 glDisable(GL_BLEND);
1347 glDisable(GL_ALPHA_TEST);
1348 glEnable(GL_DEPTH_TEST);
1349 }
1350
1351 /*
1352 ================
1353 R_RenderScene
1354
1355 r_refdef must be set before the first call
1356 ================
1357 */
R_RenderScene(void)1358 void R_RenderScene (void)
1359 {
1360 S_ExtraUpdateTime (); // don't let sound get messed up if going slow
1361
1362 R_SetupFrame ();
1363
1364 R_SetFrustum ();
1365
1366 R_SetupGL ();
1367
1368 R_MarkLeaves (); // done here so we know if we're in water
1369
1370 R_DrawWorld (); // adds static entities to the list
1371
1372 S_ExtraUpdateTime (); // don't let sound get messed up if going slow
1373
1374 R_DrawEntitiesOnList ();
1375
1376 GL_DisableMultitexture();
1377
1378 R_RenderDlights ();
1379
1380 // EnderTest R_DrawParticles ();
1381
1382 S_ExtraUpdateTime (); // don't let sound get messed up if going slow
1383
1384 #ifdef GLTEST
1385 Test_Draw ();
1386 #endif
1387
1388 }
1389
1390
1391 /*
1392 =============
1393 R_Clear
1394 =============
1395 */
R_Clear(void)1396 void R_Clear (void)
1397 {
1398 if (r_mirroralpha.value != 1.0)
1399 {
1400 if (gl_clear.value)
1401 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1402 else
1403 glClear (GL_DEPTH_BUFFER_BIT);
1404 gldepthmin = 0;
1405 gldepthmax = 0.5;
1406 glDepthFunc (GL_LEQUAL);
1407 }
1408 else if (gl_ztrick.value)
1409 {
1410 static int trickframe;
1411
1412 if (gl_clear.value)
1413 glClear (GL_COLOR_BUFFER_BIT);
1414
1415 trickframe++;
1416 if (trickframe & 1)
1417 {
1418 gldepthmin = 0;
1419 gldepthmax = 0.49999;
1420 glDepthFunc (GL_LEQUAL);
1421 }
1422 else
1423 {
1424 gldepthmin = 1;
1425 gldepthmax = 0.5;
1426 glDepthFunc (GL_GEQUAL);
1427 }
1428 }
1429 else
1430 {
1431 if (gl_clear.value)
1432 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1433 else
1434 glClear (GL_DEPTH_BUFFER_BIT);
1435 gldepthmin = 0;
1436 gldepthmax = 1;
1437 glDepthFunc (GL_LEQUAL);
1438 }
1439
1440 glDepthRange (gldepthmin, gldepthmax);
1441 }
1442
1443 /*
1444 =============
1445 R_Mirror
1446 =============
1447 */
R_Mirror(void)1448 void R_Mirror (void)
1449 {
1450 float d;
1451 msurface_t *s;
1452 entity_t *ent;
1453
1454 if (!mirror)
1455 return;
1456
1457 memcpy (r_base_world_matrix, r_world_matrix, sizeof(r_base_world_matrix));
1458
1459 d = DotProduct (r_refdef.vieworg, mirror_plane->normal) - mirror_plane->dist;
1460 VectorMA (r_refdef.vieworg, -2*d, mirror_plane->normal, r_refdef.vieworg);
1461
1462 d = DotProduct (vpn, mirror_plane->normal);
1463 VectorMA (vpn, -2*d, mirror_plane->normal, vpn);
1464
1465 r_refdef.viewangles[0] = -asin (vpn[2])/M_PI*180;
1466 r_refdef.viewangles[1] = atan2 (vpn[1], vpn[0])/M_PI*180;
1467 r_refdef.viewangles[2] = -r_refdef.viewangles[2];
1468
1469 ent = &cl_entities[cl.viewentity];
1470 if (cl_numvisedicts < MAX_VISEDICTS)
1471 {
1472 cl_visedicts[cl_numvisedicts] = ent;
1473 cl_numvisedicts++;
1474 }
1475
1476 gldepthmin = 0.5;
1477 gldepthmax = 1;
1478 glDepthRange (gldepthmin, gldepthmax);
1479 glDepthFunc (GL_LEQUAL);
1480
1481 R_RenderScene ();
1482 R_DrawWaterSurfaces ();
1483
1484 gldepthmin = 0;
1485 gldepthmax = 0.5;
1486 glDepthRange (gldepthmin, gldepthmax);
1487 glDepthFunc (GL_LEQUAL);
1488
1489 // blend on top
1490 glEnable (GL_BLEND);
1491 glMatrixMode(GL_PROJECTION);
1492 if (mirror_plane->normal[2])
1493 glScalef (1,-1,1);
1494 else
1495 glScalef (-1,1,1);
1496 glCullFace(GL_FRONT);
1497 glMatrixMode(GL_MODELVIEW);
1498
1499 glLoadMatrixf (r_base_world_matrix);
1500
1501 glColor4f (1,1,1,r_mirroralpha.value);
1502 s = cl.worldmodel->textures[mirrortexturenum]->texturechain;
1503 for ( ; s ; s=s->texturechain)
1504 R_RenderBrushPoly (s);
1505 cl.worldmodel->textures[mirrortexturenum]->texturechain = NULL;
1506 glDisable (GL_BLEND);
1507 glColor4f (1,1,1,1);
1508 }
1509
1510 /*
1511 ================
1512 R_RenderView
1513
1514 r_refdef must be set before the first call
1515 ================
1516 */
1517
1518 // Nehahra: Altered significantly. Move glFinish etc to SCR_UpdateScreen
R_RenderView(void)1519 void R_RenderView (void) {
1520 if (!r_worldentity.model || !cl.worldmodel)
1521 Sys_Error ("R_RenderView: NULL worldmodel");
1522
1523
1524 R_Clear ();
1525
1526 Neh_BeginFrame();
1527
1528 R_RenderScene ();
1529 R_DrawViewModel ();
1530 R_DrawWaterSurfaces ();
1531
1532 if (!gl_notrans.value) // Nehahra - Model_Alpha
1533 R_DrawTransEntities();
1534
1535 Neh_EndFrame();
1536
1537 R_DrawParticles (); // Nehahra - Model_Alpha
1538 R_PolyBlend ();
1539 }
1540
1541 /*
1542 =============
1543 GL_DrawAliasBlendedFrame
1544
1545 fenix@io.com: model animation interpolation
1546 =============
1547 */
GL_DrawAliasBlendedFrame(aliashdr_t * paliashdr,int pose1,int pose2,float blend)1548 void GL_DrawAliasBlendedFrame (aliashdr_t *paliashdr, int pose1, int pose2, float blend)
1549 {
1550 float l;
1551 trivertx_t* verts1;
1552 trivertx_t* verts2;
1553 int* order;
1554 int count;
1555 vec3_t d;
1556
1557 #ifdef D3DQuake
1558 if ( gNoAlias ) return; // D3DQuake
1559 #endif
1560
1561 if (model_alpha != 1.0)
1562 glEnable (GL_BLEND);
1563
1564 lastposenum0 = pose1;
1565 lastposenum = pose2;
1566 verts1 = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
1567 verts2 = verts1;
1568
1569 verts1 += pose1 * paliashdr->poseverts;
1570 verts2 += pose2 * paliashdr->poseverts;
1571
1572 order = (int *)((byte *)paliashdr + paliashdr->commands);
1573
1574 for (;;)
1575 {
1576 // get the vertex count and primitive type
1577 count = *order++;
1578
1579 if (!count) break;
1580
1581 if (count < 0)
1582 {
1583 count = -count;
1584 glBegin (GL_TRIANGLE_FAN);
1585 }
1586 else
1587 glBegin (GL_TRIANGLE_STRIP);
1588
1589 do
1590 {
1591 // texture coordinates come from the draw list
1592 glTexCoord2f (((float *)order)[0], ((float *)order)[1]);
1593 order += 2;
1594
1595 // normals and vertexes come from the frame list
1596 // blend the light intensity from the two frames together
1597 d[0] = shadedots[verts2->lightnormalindex] -
1598 shadedots[verts1->lightnormalindex];
1599
1600 if (r_fullbright.value || !cl.worldmodel->lightdata)
1601 l = 1;
1602 else
1603 l = shadelight * (shadedots[verts1->lightnormalindex] + (blend * d[0]));
1604
1605 if (model_alpha != 1.0)
1606 glColor4f (l, l, l, model_alpha);
1607 else
1608 glColor3f (l, l, l);
1609
1610 VectorSubtract(verts2->v, verts1->v, d);
1611
1612 // blend the vertex positions from each frame together
1613 glVertex3f (verts1->v[0] + (blend * d[0]),
1614 verts1->v[1] + (blend * d[1]),
1615 verts1->v[2] + (blend * d[2]));
1616
1617 verts1++;
1618 verts2++;
1619 }
1620 while (--count);
1621
1622 glEnd ();
1623 }
1624 }
1625
1626 /*
1627 =================
1628 R_SetupAliasBlendedFrame
1629
1630 fenix@io.com: model animation interpolation
1631 =================
1632 */
R_SetupAliasBlendedFrame(int frame,aliashdr_t * paliashdr,entity_t * e)1633 void R_SetupAliasBlendedFrame (int frame, aliashdr_t *paliashdr, entity_t* e)
1634 {
1635 int pose;
1636 int numposes;
1637 float blend;
1638 static float lastmsg = 0;
1639
1640 frame = R_ChkFrame ("R_SetupAliasBlendedFrame", frame, paliashdr, &lastmsg);
1641
1642 pose = paliashdr->frames[frame].firstpose;
1643 numposes = paliashdr->frames[frame].numposes;
1644
1645 if (numposes > 1)
1646 {
1647 int firstpose = pose;
1648
1649 pose = numposes * currententity->syncbase; // Hack to make flames unsynchronized
1650 e->frame_interval = paliashdr->frames[frame].interval;
1651 pose += (int)(cl.time / e->frame_interval) % numposes;
1652 pose = firstpose + pose % numposes;
1653 }
1654 else
1655 {
1656 /* One tenth of a second is a good for most Quake animations.
1657 If the nextthink is longer then the animation is usually meant to pause
1658 (e.g. check out the shambler magic animation in shambler.qc). If its
1659 shorter then things will still be smoothed partly, and the jumps will be
1660 less noticable because of the shorter time. So, this is probably a good
1661 assumption. */
1662 e->frame_interval = 0.1;
1663 }
1664
1665 if (e->pose2 != pose)
1666 {
1667 e->frame_start_time = realtime;
1668 e->pose1 = e->pose2;
1669 e->pose2 = pose;
1670 blend = 0;
1671 }
1672 else
1673 blend = (realtime - e->frame_start_time) / e->frame_interval;
1674
1675 // wierd things start happening if blend passes 1
1676 if (cl.paused || blend > 1)
1677 blend = 1;
1678
1679 GL_DrawAliasBlendedFrame (paliashdr, e->pose1, e->pose2, blend);
1680 }
1681
1682 /*
1683 =============
1684 R_BlendedRotateForEntity
1685
1686 fenix@io.com: model transform interpolation
1687 =============
1688 */
R_BlendedRotateForEntity(entity_t * e)1689 void R_BlendedRotateForEntity (entity_t *e)
1690 {
1691 float timepassed;
1692 float blend;
1693 vec3_t d;
1694 int i;
1695
1696 // positional interpolation
1697
1698 timepassed = realtime - e->translate_start_time;
1699
1700 if (e->translate_start_time == 0 || timepassed > 1)
1701 {
1702 e->translate_start_time = realtime;
1703 VectorCopy (e->origin, e->origin1);
1704 VectorCopy (e->origin, e->origin2);
1705 }
1706
1707 if (!VectorCompare (e->origin, e->origin2))
1708 {
1709 e->translate_start_time = realtime;
1710 VectorCopy (e->origin2, e->origin1);
1711 VectorCopy (e->origin, e->origin2);
1712 blend = 0;
1713 }
1714 else
1715 {
1716 blend = timepassed / 0.1;
1717
1718 if (cl.paused || blend > 1)
1719 blend = 1;
1720 }
1721
1722 VectorSubtract (e->origin2, e->origin1, d);
1723
1724 glTranslatef (e->origin1[0] + (blend * d[0]),
1725 e->origin1[1] + (blend * d[1]),
1726 e->origin1[2] + (blend * d[2]));
1727
1728 // orientation interpolation (Euler angles, yuck!)
1729
1730 timepassed = realtime - e->rotate_start_time;
1731
1732 if (e->rotate_start_time == 0 || timepassed > 1)
1733 {
1734 e->rotate_start_time = realtime;
1735 VectorCopy (e->angles, e->angles1);
1736 VectorCopy (e->angles, e->angles2);
1737 }
1738
1739 if (!VectorCompare (e->angles, e->angles2))
1740 {
1741 e->rotate_start_time = realtime;
1742 VectorCopy (e->angles2, e->angles1);
1743 VectorCopy (e->angles, e->angles2);
1744 blend = 0;
1745 }
1746 else
1747 {
1748 blend = timepassed / 0.1;
1749
1750 if (cl.paused || blend > 1)
1751 blend = 1;
1752 }
1753
1754 VectorSubtract (e->angles2, e->angles1, d);
1755
1756 // always interpolate along the shortest path
1757 for (i = 0; i < 3; i++)
1758 {
1759 if (d[i] > 180)
1760 d[i] -= 360;
1761 else if (d[i] < -180)
1762 d[i] += 360;
1763 }
1764
1765 glRotatef ( e->angles1[1] + ( blend * d[1]), 0, 0, 1);
1766 glRotatef (-e->angles1[0] + (-blend * d[0]), 0, 1, 0);
1767 glRotatef ( e->angles1[2] + ( blend * d[2]), 1, 0, 0);
1768 }
1769
1770 /*
1771 =============
1772 GL_DrawAliasBlendedShadow
1773
1774 fenix@io.com: model animation interpolation
1775 =============
1776 */
GL_DrawAliasBlendedShadow(aliashdr_t * paliashdr,int pose1,int pose2,entity_t * e)1777 void GL_DrawAliasBlendedShadow (aliashdr_t *paliashdr, int pose1, int pose2, entity_t* e)
1778 {
1779 trivertx_t* verts1;
1780 trivertx_t* verts2;
1781 int* order;
1782 vec3_t point1;
1783 vec3_t point2;
1784 vec3_t d;
1785 float height;
1786 float lheight;
1787 int count;
1788 float blend;
1789
1790 blend = (realtime - e->frame_start_time) / e->frame_interval;
1791
1792 if (blend > 1)
1793 blend = 1;
1794
1795 lheight = e->origin[2] - lightspot[2];
1796 height = -lheight + 1.0;
1797
1798 verts1 = (trivertx_t *)((byte *)paliashdr + paliashdr->posedata);
1799 verts2 = verts1;
1800
1801 verts1 += pose1 * paliashdr->poseverts;
1802 verts2 += pose2 * paliashdr->poseverts;
1803
1804 order = (int *)((byte *)paliashdr + paliashdr->commands);
1805
1806 for (;;)
1807 {
1808 // get the vertex count and primitive type
1809 count = *order++;
1810
1811 if (!count)
1812 break;
1813
1814 if (count < 0)
1815 {
1816 count = -count;
1817 glBegin (GL_TRIANGLE_FAN);
1818 }
1819 else
1820 glBegin (GL_TRIANGLE_STRIP);
1821
1822 do
1823 {
1824 order += 2;
1825
1826 point1[0] = verts1->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
1827 point1[1] = verts1->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
1828 point1[2] = verts1->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
1829
1830 point1[0] -= shadevector[0]*(point1[2]+lheight);
1831 point1[1] -= shadevector[1]*(point1[2]+lheight);
1832
1833 point2[0] = verts2->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0];
1834 point2[1] = verts2->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1];
1835 point2[2] = verts2->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2];
1836
1837 point2[0] -= shadevector[0]*(point2[2]+lheight);
1838 point2[1] -= shadevector[1]*(point2[2]+lheight);
1839
1840 VectorSubtract(point2, point1, d);
1841
1842 glVertex3f (point1[0] + (blend * d[0]),
1843 point1[1] + (blend * d[1]),
1844 height);
1845
1846 verts1++;
1847 verts2++;
1848 } while (--count);
1849
1850 glEnd ();
1851 }
1852 }
1853