1 /*
2 Copyright (C) 1997-2001 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 // cl_view.c -- player rendering positioning
21
22 #include "client.h"
23
24 //=============
25 //
26 // development tools for weapons
27 //
28 int gun_frame;
29 struct model_s *gun_model;
30 struct model_s *clientGun;
31 extern cvar_t *skin;
32
33 //=============
34
35 cvar_t *crosshair;
36 cvar_t *crosshair_scale;
37 cvar_t *gl_transrendersort;
38 cvar_t *gl_particle_lighting;
39 cvar_t *gl_particle_min;
40 cvar_t *gl_particle_max;
41 cvar_t *cl_testparticles;
42 cvar_t *cl_testentities;
43 cvar_t *cl_testlights;
44 cvar_t *cl_testblend;
45
46 cvar_t *cl_stats;
47
48 cvar_t *hand;
49
50
51 int r_numdlights;
52 dlight_t r_dlights[MAX_DLIGHTS];
53
54 int r_numentities;
55 entity_t r_entities[MAX_ENTITIES];
56
57 int r_numparticles;
58 particle_t r_particles[MAX_PARTICLES];
59
60 lightstyle_t r_lightstyles[MAX_LIGHTSTYLES];
61
62 char cl_weaponmodels[MAX_CLIENTWEAPONMODELS][MAX_QPATH];
63 int num_cl_weaponmodels;
64
65
66
67 /*
68 ====================
69 CL_Trace
70
71 ====================
72 */
73
CL_Trace(vec3_t start,vec3_t end,float size,int contentmask)74 trace_t CL_Trace (vec3_t start, vec3_t end, float size, int contentmask)
75 {
76 vec3_t maxs, mins;
77
78 VectorSet(maxs, size, size, size);
79 VectorSet(mins, -size, -size, -size);
80
81 return CM_BoxTrace (start, end, mins, maxs, 0, contentmask);
82 }
83
84 /*
85 ====================
86 V_ClearScene
87
88 Specifies the model that will be used as the world
89 ====================
90 */
V_ClearScene(void)91 void V_ClearScene (void)
92 {
93 r_numdlights = 0;
94 r_numentities = 0;
95 r_numparticles = 0;
96 }
97
98 /*
99 =====================
100 3D Cam Stuff -psychospaz
101
102 =====================
103 */
104
105 #define CAM_MAXALPHADIST 0.000111
106
107 float viewermodelalpha;
108
AddViewerEntAlpha(entity_t * ent)109 void AddViewerEntAlpha (entity_t *ent)
110 {
111 if (viewermodelalpha==1 || !cl_3dcam_alpha->value)
112 return;
113
114 ent->alpha *= viewermodelalpha;
115 if (ent->alpha<.9)
116 ent->flags |= RF_TRANSLUCENT;
117 }
118
119 #define ANGLEMAX 90.0
CalcViewerCamTrans(float distance)120 void CalcViewerCamTrans (float distance)
121 {
122 float alphacalc = cl_3dcam_dist->value;
123
124 //no div by 0
125 if (alphacalc<1)
126 alphacalc=1;
127
128 viewermodelalpha = distance/alphacalc;
129
130 if (viewermodelalpha>1)
131 viewermodelalpha = 1;
132 }
133
134 /*
135 =====================
136 V_AddEntity
137
138 =====================
139 */
V_AddEntity(entity_t * ent)140 void V_AddEntity (entity_t *ent)
141 {
142 if (ent->flags&RF_VIEWERMODEL) //here is our client
143 {
144 int i;
145 vec3_t oldorgdiff;
146
147 VectorSubtract(ent->oldorigin, ent->origin, oldorgdiff);
148
149 //what was i thinking before!?
150 for (i=0;i<3;i++)
151 clientOrg[i] = ent->oldorigin[i] = ent->origin[i] = cl.predicted_origin[i];
152
153 VectorAdd(ent->oldorigin, oldorgdiff, ent->oldorigin);
154
155 if (hand->value==1) //lefthanded
156 {
157 ent->renderfx |= RF_MIRRORMODEL;
158 }
159
160 //saber hack
161 if (ent->renderfx&RF2_CAMERAMODEL)
162 ent->flags&=~RF_VIEWERMODEL;
163
164 if (cl_3dcam->value && !(cl.attractloop && !(cl.cinematictime > 0 && cls.realtime - cl.cinematictime > 1000)))
165 {
166 AddViewerEntAlpha(ent);
167 ent->flags&=~RF_VIEWERMODEL;
168 ent->renderfx|=RF2_FORCE_SHADOW|RF2_CAMERAMODEL;
169 }
170 else if (ent->renderfx&RF2_CAMERAMODEL)
171 {
172 ent->flags &= ~RF_VIEWERMODEL;
173 ent->renderfx|=RF2_FORCE_SHADOW|RF2_CAMERAMODEL;
174 }
175 }
176
177 if (r_numentities >= MAX_ENTITIES)
178 return;
179 r_entities[r_numentities++] = *ent;
180 }
181
182
183 /*
184 =====================
185 V_AddParticle
186
187 =====================
188 */
V_AddParticle(vec3_t org,vec3_t angle,vec3_t color,float alpha,int alpha_src,int alpha_dst,float size,int image,int flags,decalpolys_t * decal)189 void V_AddParticle (vec3_t org, vec3_t angle, vec3_t color, float alpha, int alpha_src, int alpha_dst, float size, int image, int flags, decalpolys_t *decal)
190 {
191 int i;
192 particle_t *p;
193
194 if (r_numparticles >= MAX_PARTICLES)
195 return;
196 p = &r_particles[r_numparticles++];
197
198 for (i=0;i<3;i++)
199 {
200 p->origin[i] = org[i];
201 p->angle[i] = angle[i];
202 }
203 p->red = color[0];
204 p->green = color[1];
205 p->blue = color[2];
206 p->alpha = alpha;
207 p->image = image;
208 p->flags = flags;
209 p->size = size;
210 p->decal = decal;
211
212 p->blendfunc_src = alpha_src;
213 p->blendfunc_dst = alpha_dst;
214 }
215
216 /*
217 =====================
218 V_AddLight
219
220 =====================
221 */
V_AddLight(vec3_t org,float intensity,float r,float g,float b)222 void V_AddLight (vec3_t org, float intensity, float r, float g, float b)
223 {
224 dlight_t *dl;
225
226 if (r_numdlights >= MAX_DLIGHTS)
227 return;
228 dl = &r_dlights[r_numdlights++];
229 VectorCopy (org, dl->origin);
230 VectorCopy (vec3_origin, dl->direction);
231 dl->intensity = intensity;
232 dl->color[0] = r;
233 dl->color[1] = g;
234 dl->color[2] = b;
235
236 dl->spotlight = false;
237 }
238
239
240 /*
241 =====================
242 V_AddSpotLight
243
244 =====================
245 */
V_AddSpotLight(vec3_t org,vec3_t direction,float intensity,float r,float g,float b)246 void V_AddSpotLight (vec3_t org, vec3_t direction, float intensity, float r, float g, float b)
247 {
248 dlight_t *dl;
249
250 if (r_numdlights >= MAX_DLIGHTS)
251 return;
252 dl = &r_dlights[r_numdlights++];
253 VectorCopy (org, dl->origin);
254 VectorCopy(direction, dl->direction);
255 dl->intensity = intensity;
256 dl->color[0] = r;
257 dl->color[1] = g;
258 dl->color[2] = b;
259
260 dl->spotlight=true;
261 }
262
263
264 /*
265 =====================
266 V_AddLightStyle
267
268 =====================
269 */
V_AddLightStyle(int style,float r,float g,float b)270 void V_AddLightStyle (int style, float r, float g, float b)
271 {
272 lightstyle_t *ls;
273
274 if (style < 0 || style > MAX_LIGHTSTYLES)
275 Com_Error (ERR_DROP, "Bad light style %i", style);
276 ls = &r_lightstyles[style];
277
278 ls->white = r+g+b;
279 ls->rgb[0] = r;
280 ls->rgb[1] = g;
281 ls->rgb[2] = b;
282 }
283
284 /*
285 ================
286 V_TestParticles
287
288 If cl_testparticles is set, create 4096 particles in the view
289 ================
290 */
V_TestParticles(void)291 void V_TestParticles (void)
292 {
293 particle_t *p;
294 int i, j;
295 float d, r, u;
296
297 r_numparticles = MAX_PARTICLES;
298 for (i=0 ; i<r_numparticles ; i++)
299 {
300 d = i*0.25;
301 r = 4*((i&7)-3.5);
302 u = 4*(((i>>3)&7)-3.5);
303 p = &r_particles[i];
304
305 for (j=0 ; j<3 ; j++)
306 p->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*d +
307 cl.v_right[j]*r + cl.v_up[j]*u;
308
309 p->color = 8;
310 p->alpha = cl_testparticles->value;
311 }
312 }
313
314 /*
315 ================
316 V_TestEntities
317
318 If cl_testentities is set, create 32 player models
319 ================
320 */
V_TestEntities(void)321 void V_TestEntities (void)
322 {
323 int i, j;
324 float f, r;
325 entity_t *ent;
326
327 r_numentities = 32;
328 memset (r_entities, 0, sizeof(r_entities));
329
330 for (i=0 ; i<r_numentities ; i++)
331 {
332 ent = &r_entities[i];
333
334 r = 64 * ( (i%4) - 1.5 );
335 f = 64 * (i/4) + 128;
336
337 for (j=0 ; j<3 ; j++)
338 ent->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*f +
339 cl.v_right[j]*r;
340
341 ent->model = cl.baseclientinfo.model;
342 ent->skin = cl.baseclientinfo.skin;
343 }
344 }
345
346 /*
347 ================
348 V_TestLights
349
350 If cl_testlights is set, create 32 lights models
351 ================
352 */
V_TestLights(void)353 void V_TestLights (void)
354 {
355 int i, j;
356 float f, r;
357 dlight_t *dl;
358
359 r_numdlights = 32;
360 memset (r_dlights, 0, sizeof(r_dlights));
361
362 for (i=0 ; i<r_numdlights ; i++)
363 {
364 dl = &r_dlights[i];
365
366 r = 64 * ( (i%4) - 1.5 );
367 f = 64 * (i/4) + 128;
368
369 for (j=0 ; j<3 ; j++)
370 dl->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*f +
371 cl.v_right[j]*r;
372 dl->color[0] = ((i%6)+1) & 1;
373 dl->color[1] = (((i%6)+1) & 2)>>1;
374 dl->color[2] = (((i%6)+1) & 4)>>2;
375 dl->intensity = 200;
376 dl->spotlight=true;
377 }
378 }
379
380 //===================================================================
381
382 /*
383 =================
384 CL_PrepRefresh
385
386 Call before entering a new level, or after changing dlls
387 =================
388 */
389 qboolean needLoadingPlaque (void);
CL_PrepRefresh()390 void CL_PrepRefresh ()
391 {
392 char mapname[32];
393 int i, max;
394 char name[MAX_QPATH];
395 float rotate;
396 vec3_t axis;
397 qboolean newPlaque = needLoadingPlaque();
398
399 if (!cl.configstrings[CS_MODELS+1][0])
400 return; // no map loaded
401
402 if (newPlaque)
403 SCR_BeginLoadingPlaque();
404
405 loadingMessage = true;
406 Com_sprintf (loadingMessages[0], sizeof(loadingMessages[0]), "^2loading map...");
407 Com_sprintf (loadingMessages[1], sizeof(loadingMessages[1]), "^2loading models...");
408 Com_sprintf (loadingMessages[2], sizeof(loadingMessages[2]), "^2loading pics...");
409 Com_sprintf (loadingMessages[3], sizeof(loadingMessages[3]), "^2loading clients...");
410 loadingPercent = 0;
411
412 SCR_AddDirtyPoint (0, 0);
413 SCR_AddDirtyPoint (viddef.width-1, viddef.height-1);
414
415 // let the render dll load the map
416 strcpy (mapname, cl.configstrings[CS_MODELS+1] + 5); // skip "maps/"
417 mapname[strlen(mapname)-4] = 0; // cut off ".bsp"
418
419 // register models, pics, and skins
420 Com_Printf ("Map: %s\r", mapname);
421 SCR_UpdateScreen ();
422 re.BeginRegistration (mapname);
423 Com_Printf (" \r");
424 Com_sprintf (loadingMessages[0], sizeof(loadingMessages[0]), "^i^0loading map...done");
425 loadingPercent += 20;
426
427 // precache status bar pics
428 Com_Printf ("pics\r");
429 SCR_UpdateScreen ();
430 SCR_TouchPics ();
431 Com_Printf (" \r");
432
433 CL_RegisterTEntModels ();
434
435 num_cl_weaponmodels = 1;
436 strcpy(cl_weaponmodels[0], "weapon.md2");
437
438 for (i=1, max=0 ; i<MAX_MODELS && cl.configstrings[CS_MODELS+i][0] ; i++)
439 max++;
440 for (i=1 ; i<MAX_MODELS && cl.configstrings[CS_MODELS+i][0] ; i++)
441 {
442 strcpy (name, cl.configstrings[CS_MODELS+i]);
443 name[37] = 0; // never go beyond one line
444 if (name[0] != '*')
445 {
446 Com_Printf ("%s\r", name);
447
448 //only make max of 20 chars long
449 Com_sprintf (loadingMessages[1], sizeof(loadingMessages[1]), "^2loading models...%s",
450 (strlen(name)>20)? &name[strlen(name)-20]: name);
451 }
452
453 SCR_UpdateScreen ();
454 Sys_SendKeyEvents (); // pump message loop
455 if (name[0] == '#')
456 {
457 // special player weapon model
458 if (num_cl_weaponmodels < MAX_CLIENTWEAPONMODELS)
459 {
460 strncpy(cl_weaponmodels[num_cl_weaponmodels], cl.configstrings[CS_MODELS+i]+1,
461 sizeof(cl_weaponmodels[num_cl_weaponmodels]) - 1);
462 num_cl_weaponmodels++;
463 }
464 }
465 else
466 {
467 cl.model_draw[i] = re.RegisterModel (cl.configstrings[CS_MODELS+i]);
468 if (name[0] == '*')
469 cl.model_clip[i] = CM_InlineModel (cl.configstrings[CS_MODELS+i]);
470 else
471 cl.model_clip[i] = NULL;
472 }
473 if (name[0] != '*')
474 Com_Printf (" \r");
475
476 loadingPercent += 60.0f/(float)max;
477 }
478 Com_sprintf (loadingMessages[1], sizeof(loadingMessages[1]), "^i^0loading models...done");
479
480 Com_Printf ("images\r", i);
481 SCR_UpdateScreen ();
482
483 for (i=1, max=0 ; i<MAX_IMAGES && cl.configstrings[CS_IMAGES+i][0] ; i++)
484 max++;
485 for (i=1 ; i<MAX_IMAGES && cl.configstrings[CS_IMAGES+i][0] ; i++)
486 {
487 cl.image_precache[i] = re.RegisterPic (cl.configstrings[CS_IMAGES+i]);
488 Sys_SendKeyEvents (); // pump message loop
489 loadingPercent += 10.0f/(float)max;
490 }
491 Com_sprintf (loadingMessages[2], sizeof(loadingMessages[2]), "^i^0loading pics...done");
492
493 Com_Printf (" \r");
494
495 //refresh the player model/skin info
496 CL_LoadClientinfo (&cl.baseclientinfo, va("unnamed\\%s\\%s", DEFAULTMODEL, DEFAULTSKIN));
497
498 for (i=1, max=0 ; i<MAX_CLIENTS ; i++)
499 if (cl.configstrings[CS_PLAYERSKINS+i][0])
500 max++;
501 for (i=0 ; i<MAX_CLIENTS ; i++)
502 {
503 if (!cl.configstrings[CS_PLAYERSKINS+i][0])
504 continue;
505
506 Com_sprintf (loadingMessages[3], sizeof(loadingMessages[3]), "^2loading clients...%i", i);
507 Com_Printf ("client %i\r", i);
508 SCR_UpdateScreen ();
509 Sys_SendKeyEvents (); // pump message loop
510 CL_ParseClientinfo (i);
511 Com_Printf (" \r");
512 loadingPercent += 10.0f/(float)max;
513 }
514 Com_sprintf (loadingMessages[3], sizeof(loadingMessages[3]), "^i^0loading clients...done");
515
516 //hack hack hack - psychospaz
517 loadingPercent = 100;
518
519 // set sky textures and speed
520 Com_Printf ("sky\r", i);
521 SCR_UpdateScreen ();
522 rotate = atof (cl.configstrings[CS_SKYROTATE]);
523 sscanf (cl.configstrings[CS_SKYAXIS], "%f %f %f",
524 &axis[0], &axis[1], &axis[2]);
525 re.SetSky (cl.configstrings[CS_SKY], rotate, axis);
526 Com_Printf (" \r");
527
528 // the renderer can now free unneeded stuff
529 re.EndRegistration ();
530
531 // clear any lines of console text
532 Con_ClearNotify ();
533
534 SCR_UpdateScreen ();
535 cl.refresh_prepped = true;
536 cl.force_refdef = true; // make sure we have a valid refdef
537
538 // start the cd track
539 CDAudio_Play (atoi(cl.configstrings[CS_CDTRACK]), true);
540
541 loadingMessage = false;
542
543 if (newPlaque)
544 SCR_EndLoadingPlaque();
545 else
546 Cvar_Set ("paused", "0");
547 }
548
549 /*
550 ====================
551 CalcFov
552 ====================
553 */
CalcFov(float fov_x,float width,float height)554 float CalcFov (float fov_x, float width, float height)
555 {
556 float a;
557 float x;
558
559 if (fov_x < 1 || fov_x > 179)
560 Com_Error (ERR_DROP, "Bad fov: %f", fov_x);
561
562 x = width/tan(fov_x/360*M_PI);
563
564 a = atan (height/x);
565
566 a = a*360/M_PI;
567
568 return a;
569 }
570
571 //============================================================================
572
573 // gun frame debugging functions
V_Gun_Next_f(void)574 void V_Gun_Next_f (void)
575 {
576 gun_frame++;
577 Com_Printf ("frame %i\n", gun_frame);
578 }
579
V_Gun_Prev_f(void)580 void V_Gun_Prev_f (void)
581 {
582 gun_frame--;
583 if (gun_frame < 0)
584 gun_frame = 0;
585 Com_Printf ("frame %i\n", gun_frame);
586 }
587
V_Gun_Model_f(void)588 void V_Gun_Model_f (void)
589 {
590 char name[MAX_QPATH];
591
592 if (Cmd_Argc() != 2)
593 {
594 gun_model = NULL;
595 return;
596 }
597 Com_sprintf (name, sizeof(name), "models/%s/tris.md2", Cmd_Argv(1));
598 gun_model = re.RegisterModel (name);
599 }
600
601 //============================================================================
602
603
604 /*
605 =================
606 SCR_DrawCrosshair
607 =================
608 */
609 #define DIV640 0.0015625
610
SCR_DrawCrosshair(void)611 void SCR_DrawCrosshair (void)
612 {
613 float scale;
614 int x, y, w, h;
615
616 if (!crosshair->value)
617 return;
618
619 if (crosshair->modified)
620 {
621 crosshair->modified = false;
622 SCR_TouchPics ();
623 }
624
625 if (crosshair_scale->modified)
626 {
627 crosshair_scale->modified=false;
628 if (crosshair_scale->value>10)
629 Cvar_SetValue("crosshair_scale", 10);
630 else if (crosshair_scale->value<0.25)
631 Cvar_SetValue("crosshair_scale", 0.25);
632 }
633
634 if (!crosshair_pic[0])
635 return;
636
637 scale = crosshair_scale->value * (viddef.width*DIV640);
638
639 w = crosshair_width * scale;
640 h = crosshair_height * scale;
641
642 x = (viddef.width)*0.5;
643 y = (viddef.height)*0.5;
644
645 re.DrawStretchPic (
646 x-w*0.5, y-h*0.5,
647 w, h,
648 crosshair_pic);
649 /*
650 re.DrawScaledPic (scr_vrect.x + ((scr_vrect.width - crosshair_width)>>1) //width
651 , scr_vrect.y + ((scr_vrect.height - crosshair_height)>>1) //height
652 , scale //scale
653 , crosshair_pic); //pic*/
654 }
655
SCR_DrawIRGoggles(void)656 void SCR_DrawIRGoggles (void)
657 {
658 re.DrawStretchPic (0, 0, viddef.width, viddef.height, "ir_crosshair");
659 }
660
SCR_DrawSniperCrosshair(void)661 void SCR_DrawSniperCrosshair (void)
662 {
663 /* if (modType("dday"))
664 {
665 if (!clientGun)
666 return;
667 if (cl.refdef.fov_x>=85)
668 return;
669
670 //continue if model is sniper
671 if ((int)(clientGun)!=(int)(re.RegisterModel("models/weapons/usa/v_m1903/tris.md2")) &&
672 (int)(clientGun)!=(int)(re.RegisterModel("models/weapons/grm/v_m98ks/tris.md2")) &&
673 (int)(clientGun)!=(int)(re.RegisterModel("models/weapons/gbr/v_303s/tris.md2")) &&
674 (int)(clientGun)!=(int)(re.RegisterModel("models/weapons/rus/v_m9130s/tris.md2")))
675 return;
676 }
677 else */if (modType("swq"))
678 {
679 if (clientGun)
680 return;
681 if (cl.refdef.fov_x>=90)
682 return;
683 }
684 else if (modType("action"))
685 {
686 if (clientGun)
687 return;
688 if (cl.refdef.fov_x>=85)
689 return;
690 }
691 else return;
692
693
694 re.DrawStretchPic (0, 0, viddef.width, viddef.height, "sniper");
695 }
696
697 /*
698 ==================
699 V_RenderView
700
701 ==================
702 */
703
704 //dirty hack for gloom!!!
705 cvar_t *r_overbrightbits;
706 cvar_t *r_celshading;
707 cvar_t *gl_modulate;
GloomRenderCheck(void)708 void GloomRenderCheck(void)
709 {
710 if (!r_celshading)
711 r_celshading = Cvar_Get( "r_celshading", "0", CVAR_ARCHIVE );
712 if (!gl_modulate)
713 gl_modulate = Cvar_Get( "gl_modulate", "1", CVAR_ARCHIVE );
714
715 if (gl_modulate && gl_modulate->value>1)
716 Cvar_SetValue( "gl_modulate", 1 );
717
718 if (r_celshading && r_celshading->value)
719 Cvar_SetValue( "r_celshading", 0 );
720
721 if (cl_3dcam && cl_3dcam->value)
722 Cvar_SetValue( "cl_3dcam", 0 );
723 }
724
V_RenderView(float stereo_separation)725 void V_RenderView( float stereo_separation )
726 {
727 extern int entitycmpfnc( const entity_t *, const entity_t * );
728
729 if (cls.state != ca_active)
730 return;
731
732 if (!cl.refresh_prepped)
733 return; // still loading
734
735 if (cl_timedemo->value)
736 {
737 if (!cl.timedemo_start)
738 cl.timedemo_start = Sys_Milliseconds ();
739 cl.timedemo_frames++;
740 }
741
742 // an invalid frame will just use the exact previous refdef
743 // we can't use the old frame if the video mode has changed, though...
744 if ( cl.frame.valid && (cl.force_refdef || !cl_paused->value) )
745 {
746 cl.force_refdef = false;
747 V_ClearScene ();
748
749 if (cl_testparticles->value)
750 V_TestParticles ();
751 if (cl_testentities->value)
752 V_TestEntities ();
753 if (cl_testlights->value)
754 V_TestLights ();
755 if (cl_testblend->value)
756 {
757 cl.refdef.blend[0] = 1;
758 cl.refdef.blend[1] = 0.5;
759 cl.refdef.blend[2] = 0.25;
760 cl.refdef.blend[3] = 0.5;
761 }
762
763 // offset vieworg appropriately if we're doing stereo separation
764 if ( stereo_separation != 0 )
765 {
766 vec3_t tmp;
767
768 VectorScale( cl.v_right, stereo_separation, tmp );
769 VectorAdd( cl.refdef.vieworg, tmp, cl.refdef.vieworg );
770 }
771
772 // never let it sit exactly on a node line, because a water plane can
773 // dissapear when viewed with the eye exactly on it.
774 // the server protocol only specifies to 1/8 pixel, so add 1/16 in each axis
775 cl.refdef.vieworg[0] += 1.0/16;
776 cl.refdef.vieworg[1] += 1.0/16;
777 cl.refdef.vieworg[2] += 1.0/16;
778
779 // build a refresh entity list and calc cl.sim*
780 // this also calls CL_CalcViewValues which loads
781 // v_forward, etc.
782 CL_AddEntities ();
783
784 cl.refdef.x = scr_vrect.x;
785 cl.refdef.y = scr_vrect.y;
786 cl.refdef.width = scr_vrect.width;
787 cl.refdef.height = scr_vrect.height;
788 cl.refdef.fov_y = CalcFov (cl.refdef.fov_x, cl.refdef.width, cl.refdef.height);
789 cl.refdef.time = cl.time*0.001;
790
791 cl.refdef.areabits = cl.frame.areabits;
792
793 if (!cl_add_entities->value)
794 r_numentities = 0;
795 if (!cl_add_particles->value)
796 r_numparticles = 0;
797 if (!cl_add_lights->value)
798 r_numdlights = 0;
799 if (!cl_add_blend->value)
800 {
801 VectorClear (cl.refdef.blend);
802 }
803
804 cl.refdef.num_entities = r_numentities;
805 cl.refdef.entities = r_entities;
806
807 cl.refdef.num_particles = r_numparticles;
808 cl.refdef.particles = r_particles;
809
810 cl.refdef.num_dlights = r_numdlights;
811 cl.refdef.dlights = r_dlights;
812 cl.refdef.lightstyles = r_lightstyles;
813
814 cl.refdef.rdflags = cl.frame.playerstate.rdflags;
815
816 // sort entities for better cache locality
817 if (!gl_transrendersort->value)
818 qsort( cl.refdef.entities, cl.refdef.num_entities, sizeof( cl.refdef.entities[0] ), (int (*)(const void *, const void *))entitycmpfnc );
819 }
820
821 re.RenderFrame (&cl.refdef);
822 if (cl_stats->value)
823 Com_Printf ("ent:%i lt:%i part:%i\n", r_numentities, r_numdlights, r_numparticles);
824 if ( log_stats->value && ( log_stats_file != 0 ) )
825 fprintf( log_stats_file, "%i,%i,%i,",r_numentities, r_numdlights, r_numparticles);
826
827
828 SCR_AddDirtyPoint (scr_vrect.x, scr_vrect.y);
829 SCR_AddDirtyPoint (scr_vrect.x+scr_vrect.width-1,
830 scr_vrect.y+scr_vrect.height-1);
831
832 if (!modType("dday")) //dday has no crosshair (FORCED)
833 SCR_DrawCrosshair ();
834
835 SCR_DrawSniperCrosshair();
836
837 //hack for gloom
838 if (modType("gloom"))
839 GloomRenderCheck();
840 }
841
842
843 /*
844 =============
845 V_Viewpos_f
846 =============
847 */
V_Viewpos_f(void)848 void V_Viewpos_f (void)
849 {
850 Com_Printf ("(%i %i %i) : %i\n", (int)cl.refdef.vieworg[0],
851 (int)cl.refdef.vieworg[1], (int)cl.refdef.vieworg[2],
852 (int)cl.refdef.viewangles[YAW]);
853 }
854
855 /*
856 =============
857 V_Init
858 =============
859 */
V_Init(void)860 void V_Init (void)
861 {
862 Cmd_AddCommand ("gun_next", V_Gun_Next_f);
863 Cmd_AddCommand ("gun_prev", V_Gun_Prev_f);
864 Cmd_AddCommand ("gun_model", V_Gun_Model_f);
865
866 Cmd_AddCommand ("viewpos", V_Viewpos_f);
867
868 gl_transrendersort = Cvar_Get ("gl_transrendersort", "1", CVAR_ARCHIVE );
869 gl_particle_lighting = Cvar_Get ("gl_particle_lighting", "0.75", CVAR_ARCHIVE );
870 gl_particle_min = Cvar_Get ("gl_particle_min", "0", CVAR_ARCHIVE );
871 gl_particle_max = Cvar_Get ("gl_particle_max", "0", CVAR_ARCHIVE );
872
873 hand = Cvar_Get ("hand", "0", CVAR_ARCHIVE);
874 if (!strcmp("swq",Cvar_Get ("game", "0", CVAR_ARCHIVE)->string)||!strcmp("cotf",Cvar_Get ("game", "0", CVAR_ARCHIVE)->string))
875 Cvar_SetValue("hand", 0);
876
877 crosshair = Cvar_Get ("crosshair", "0", CVAR_ARCHIVE);
878 crosshair_scale = Cvar_Get ("crosshair_scale", "1", CVAR_ARCHIVE);
879
880 cl_testblend = Cvar_Get ("cl_testblend", "0", 0);
881 cl_testparticles = Cvar_Get ("cl_testparticles", "0", 0);
882 cl_testentities = Cvar_Get ("cl_testentities", "0", 0);
883 cl_testlights = Cvar_Get ("cl_testlights", "0", 0);
884
885 cl_stats = Cvar_Get ("cl_stats", "0", 0);
886 }
887