|
|
1.1 root 1: // cl_view.c -- player rendering positioning
1.1.1.2 root 2:
1.1 root 3: #include "client.h"
1.1.1.2 root 4:
1.1 root 5: //=============
6: //
7: // development tools for weapons
8: //
9: int gun_frame;
10: struct model_s *gun_model;
1.1.1.2 root 11:
1.1 root 12: //=============
1.1.1.2 root 13:
1.1 root 14: cvar_t *crosshair;
15: cvar_t *cl_testparticles;
16: cvar_t *cl_testentities;
17: cvar_t *cl_testlights;
18: cvar_t *cl_testblend;
1.1.1.2 root 19:
1.1 root 20: cvar_t *cl_stats;
1.1.1.2 root 21:
22:
1.1 root 23: int r_numdlights;
24: dlight_t r_dlights[MAX_DLIGHTS];
1.1.1.2 root 25:
1.1 root 26: int r_numentities;
27: entity_t r_entities[MAX_ENTITIES];
1.1.1.2 root 28:
1.1 root 29: int r_numparticles;
30: particle_t r_particles[MAX_PARTICLES];
1.1.1.2 root 31:
1.1 root 32: lightstyle_t r_lightstyles[MAX_LIGHTSTYLES];
1.1.1.2 root 33:
34: char cl_weaponmodels[MAX_CLIENTWEAPONMODELS][MAX_QPATH];
35: int num_cl_weaponmodels;
36:
1.1 root 37: /*
38: ====================
39: V_ClearScene
1.1.1.2 root 40:
1.1 root 41: Specifies the model that will be used as the world
42: ====================
43: */
44: void V_ClearScene (void)
45: {
46: r_numdlights = 0;
47: r_numentities = 0;
48: r_numparticles = 0;
49: }
1.1.1.2 root 50:
51:
1.1 root 52: /*
53: =====================
54: V_AddEntity
1.1.1.2 root 55:
1.1 root 56: =====================
57: */
58: void V_AddEntity (entity_t *ent)
59: {
60: if (r_numentities >= MAX_ENTITIES)
61: return;
62: r_entities[r_numentities++] = *ent;
63: }
1.1.1.2 root 64:
65:
1.1 root 66: /*
67: =====================
68: V_AddParticle
1.1.1.2 root 69:
1.1 root 70: =====================
71: */
72: void V_AddParticle (vec3_t org, int color, float alpha)
73: {
74: particle_t *p;
1.1.1.2 root 75:
1.1 root 76: if (r_numparticles >= MAX_PARTICLES)
77: return;
78: p = &r_particles[r_numparticles++];
79: VectorCopy (org, p->origin);
80: p->color = color;
81: p->alpha = alpha;
82: }
1.1.1.2 root 83:
1.1 root 84: /*
85: =====================
86: V_AddLight
1.1.1.2 root 87:
1.1 root 88: =====================
89: */
90: void V_AddLight (vec3_t org, float intensity, float r, float g, float b)
91: {
92: dlight_t *dl;
1.1.1.2 root 93:
1.1 root 94: if (r_numdlights >= MAX_DLIGHTS)
95: return;
96: dl = &r_dlights[r_numdlights++];
97: VectorCopy (org, dl->origin);
98: dl->intensity = intensity;
99: dl->color[0] = r;
100: dl->color[1] = g;
101: dl->color[2] = b;
102: }
1.1.1.2 root 103:
104:
1.1 root 105: /*
106: =====================
107: V_AddLightStyle
1.1.1.2 root 108:
1.1 root 109: =====================
110: */
111: void V_AddLightStyle (int style, float r, float g, float b)
112: {
113: lightstyle_t *ls;
1.1.1.2 root 114:
1.1 root 115: if (style < 0 || style > MAX_LIGHTSTYLES)
116: Com_Error (ERR_DROP, "Bad light style %i", style);
117: ls = &r_lightstyles[style];
1.1.1.2 root 118:
1.1 root 119: ls->white = r+g+b;
120: ls->rgb[0] = r;
121: ls->rgb[1] = g;
122: ls->rgb[2] = b;
123: }
1.1.1.2 root 124:
1.1 root 125: /*
126: ================
127: V_TestParticles
1.1.1.2 root 128:
1.1 root 129: If cl_testparticles is set, create 4096 particles in the view
130: ================
131: */
132: void V_TestParticles (void)
133: {
134: particle_t *p;
135: int i, j;
136: float d, r, u;
1.1.1.2 root 137:
1.1 root 138: r_numparticles = MAX_PARTICLES;
139: for (i=0 ; i<r_numparticles ; i++)
140: {
141: d = i*0.25;
142: r = 4*((i&7)-3.5);
143: u = 4*(((i>>3)&7)-3.5);
144: p = &r_particles[i];
1.1.1.2 root 145:
1.1 root 146: for (j=0 ; j<3 ; j++)
147: p->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*d +
148: cl.v_right[j]*r + cl.v_up[j]*u;
1.1.1.2 root 149:
1.1 root 150: p->color = 8;
151: p->alpha = cl_testparticles->value;
152: }
153: }
1.1.1.2 root 154:
1.1 root 155: /*
156: ================
157: V_TestEntities
158:
159: If cl_testentities is set, create 32 player models
160: ================
161: */
162: void V_TestEntities (void)
163: {
164: int i, j;
165: float f, r;
166: entity_t *ent;
167:
168: r_numentities = 32;
169: memset (r_entities, 0, sizeof(r_entities));
170:
171: for (i=0 ; i<r_numentities ; i++)
172: {
173: ent = &r_entities[i];
174:
175: r = 64 * ( (i%4) - 1.5 );
176: f = 64 * (i/4) + 128;
177:
178: for (j=0 ; j<3 ; j++)
179: ent->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*f +
180: cl.v_right[j]*r;
181:
182: ent->model = cl.baseclientinfo.model;
183: ent->skin = cl.baseclientinfo.skin;
184: }
185: }
186:
187: /*
188: ================
189: V_TestLights
190:
191: If cl_testlights is set, create 32 lights models
192: ================
193: */
194: void V_TestLights (void)
195: {
196: int i, j;
197: float f, r;
198: dlight_t *dl;
199:
200: r_numdlights = 32;
201: memset (r_dlights, 0, sizeof(r_dlights));
202:
203: for (i=0 ; i<r_numdlights ; i++)
204: {
205: dl = &r_dlights[i];
206:
207: r = 64 * ( (i%4) - 1.5 );
208: f = 64 * (i/4) + 128;
209:
210: for (j=0 ; j<3 ; j++)
211: dl->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*f +
212: cl.v_right[j]*r;
213: dl->color[0] = ((i%6)+1) & 1;
214: dl->color[1] = (((i%6)+1) & 2)>>1;
215: dl->color[2] = (((i%6)+1) & 4)>>2;
216: dl->intensity = 200;
217: }
218: }
219:
220: //===================================================================
1.1.1.2 root 221:
1.1 root 222: /*
223: =================
224: CL_PrepRefresh
1.1.1.2 root 225:
1.1 root 226: Call before entering a new level, or after changing dlls
227: =================
228: */
229: void CL_PrepRefresh (void)
230: {
231: char mapname[32];
232: int i;
233: char name[MAX_QPATH];
234: float rotate;
235: vec3_t axis;
1.1.1.2 root 236:
1.1 root 237: if (!cl.configstrings[CS_MODELS+1][0])
238: return; // no map loaded
1.1.1.2 root 239:
1.1 root 240: SCR_AddDirtyPoint (0, 0);
241: SCR_AddDirtyPoint (viddef.width-1, viddef.height-1);
1.1.1.2 root 242:
1.1 root 243: // let the render dll load the map
244: strcpy (mapname, cl.configstrings[CS_MODELS+1] + 5); // skip "maps/"
245: mapname[strlen(mapname)-4] = 0; // cut off ".bsp"
1.1.1.2 root 246:
1.1 root 247: // register models, pics, and skins
248: Com_Printf ("Map: %s\r", mapname);
249: SCR_UpdateScreen ();
250: re.BeginRegistration (mapname);
251: Com_Printf (" \r");
1.1.1.2 root 252:
1.1 root 253: // precache status bar pics
254: Com_Printf ("pics\r");
255: SCR_UpdateScreen ();
256: SCR_TouchPics ();
257: Com_Printf (" \r");
258:
259: CL_RegisterTEntModels ();
1.1.1.2 root 260:
261: num_cl_weaponmodels = 1;
262: strcpy(cl_weaponmodels[0], "weapon.md2");
263:
1.1 root 264: for (i=1 ; i<MAX_MODELS && cl.configstrings[CS_MODELS+i][0] ; i++)
265: {
266: strcpy (name, cl.configstrings[CS_MODELS+i]);
267: name[37] = 0; // never go beyond one line
268: if (name[0] != '*')
269: Com_Printf ("%s\r", name);
270: SCR_UpdateScreen ();
271: Sys_SendKeyEvents (); // pump message loop
1.1.1.3 ! root 272: if (name[0] == '#')
! 273: {
1.1.1.2 root 274: // special player weapon model
1.1.1.3 ! root 275: if (num_cl_weaponmodels < MAX_CLIENTWEAPONMODELS)
! 276: {
1.1.1.2 root 277: strncpy(cl_weaponmodels[num_cl_weaponmodels], cl.configstrings[CS_MODELS+i]+1,
278: sizeof(cl_weaponmodels[num_cl_weaponmodels]) - 1);
279: num_cl_weaponmodels++;
280: }
1.1.1.3 ! root 281: }
! 282: else
! 283: {
1.1.1.2 root 284: cl.model_draw[i] = re.RegisterModel (cl.configstrings[CS_MODELS+i]);
285: if (name[0] == '*')
286: cl.model_clip[i] = CM_InlineModel (cl.configstrings[CS_MODELS+i]);
287: else
288: cl.model_clip[i] = NULL;
289: }
1.1 root 290: if (name[0] != '*')
291: Com_Printf (" \r");
292: }
1.1.1.3 ! root 293:
1.1 root 294: Com_Printf ("images\r", i);
295: SCR_UpdateScreen ();
296: for (i=1 ; i<MAX_IMAGES && cl.configstrings[CS_IMAGES+i][0] ; i++)
297: {
298: cl.image_precache[i] = re.RegisterPic (cl.configstrings[CS_IMAGES+i]);
299: Sys_SendKeyEvents (); // pump message loop
300: }
1.1.1.3 ! root 301:
1.1 root 302: Com_Printf (" \r");
303: for (i=0 ; i<MAX_CLIENTS ; i++)
304: {
305: if (!cl.configstrings[CS_PLAYERSKINS+i][0])
306: continue;
307: Com_Printf ("client %i\r", i);
308: SCR_UpdateScreen ();
309: Sys_SendKeyEvents (); // pump message loop
310: CL_ParseClientinfo (i);
311: Com_Printf (" \r");
312: }
1.1.1.2 root 313:
1.1 root 314: CL_LoadClientinfo (&cl.baseclientinfo, "unnamed\\male/grunt");
1.1.1.2 root 315:
1.1 root 316: // set sky textures and speed
317: Com_Printf ("sky\r", i);
318: SCR_UpdateScreen ();
319: rotate = atof (cl.configstrings[CS_SKYROTATE]);
320: sscanf (cl.configstrings[CS_SKYAXIS], "%f %f %f",
321: &axis[0], &axis[1], &axis[2]);
322: re.SetSky (cl.configstrings[CS_SKY], rotate, axis);
323: Com_Printf (" \r");
1.1.1.2 root 324:
1.1 root 325: // the renderer can now free unneeded stuff
326: re.EndRegistration ();
1.1.1.2 root 327:
1.1 root 328: // clear any lines of console text
329: Con_ClearNotify ();
1.1.1.2 root 330:
1.1 root 331: SCR_UpdateScreen ();
332: cl.refresh_prepped = true;
333: cl.force_refdef = true; // make sure we have a valid refdef
334:
335: // start the cd track
336: CDAudio_Play (atoi(cl.configstrings[CS_CDTRACK]), true);
337: }
1.1.1.2 root 338:
1.1 root 339: /*
340: ====================
341: CalcFov
342: ====================
343: */
344: float CalcFov (float fov_x, float width, float height)
345: {
346: float a;
347: float x;
1.1.1.2 root 348:
1.1 root 349: if (fov_x < 1 || fov_x > 179)
350: Com_Error (ERR_DROP, "Bad fov: %f", fov_x);
1.1.1.2 root 351:
1.1 root 352: x = width/tan(fov_x/360*M_PI);
1.1.1.2 root 353:
1.1 root 354: a = atan (height/x);
1.1.1.2 root 355:
1.1 root 356: a = a*360/M_PI;
1.1.1.2 root 357:
1.1 root 358: return a;
359: }
1.1.1.2 root 360:
1.1 root 361: //============================================================================
1.1.1.2 root 362:
1.1 root 363: // gun frame debugging functions
364: void V_Gun_Next_f (void)
365: {
366: gun_frame++;
367: Com_Printf ("frame %i\n", gun_frame);
368: }
1.1.1.2 root 369:
1.1 root 370: void V_Gun_Prev_f (void)
371: {
372: gun_frame--;
373: if (gun_frame < 0)
374: gun_frame = 0;
375: Com_Printf ("frame %i\n", gun_frame);
376: }
1.1.1.2 root 377:
1.1 root 378: void V_Gun_Model_f (void)
379: {
380: char name[MAX_QPATH];
1.1.1.2 root 381:
1.1 root 382: if (Cmd_Argc() != 2)
383: {
384: gun_model = NULL;
385: return;
386: }
387: Com_sprintf (name, sizeof(name), "models/%s/tris.md2", Cmd_Argv(1));
388: gun_model = re.RegisterModel (name);
389: }
1.1.1.2 root 390:
1.1 root 391: //============================================================================
392:
1.1.1.2 root 393:
1.1 root 394: /*
395: =================
396: SCR_DrawCrosshair
397: =================
398: */
399: void SCR_DrawCrosshair (void)
400: {
401: if (!crosshair->value)
402: return;
403:
404: if (crosshair->modified)
405: {
406: crosshair->modified = false;
407: SCR_TouchPics ();
408: }
409:
410: if (!crosshair_pic[0])
411: return;
412:
413: re.DrawPic (scr_vrect.x + ((scr_vrect.width - crosshair_width)>>1)
414: , scr_vrect.y + ((scr_vrect.height - crosshair_height)>>1), crosshair_pic);
415: }
1.1.1.2 root 416:
1.1 root 417: /*
418: ==================
419: V_RenderView
1.1.1.2 root 420:
1.1 root 421: ==================
422: */
423: void V_RenderView( float stereo_separation )
424: {
425: extern int entitycmpfnc( const entity_t *, const entity_t * );
426:
427: if (cls.state != ca_active)
428: return;
1.1.1.2 root 429:
1.1 root 430: if (!cl.refresh_prepped)
431: return; // still loading
432:
433: if (cl_timedemo->value)
434: {
435: if (!cl.timedemo_start)
436: cl.timedemo_start = Sys_Milliseconds ();
437: cl.timedemo_frames++;
438: }
439:
440: // an invalid frame will just use the exact previous refdef
441: // we can't use the old frame if the video mode has changed, though...
442: if ( cl.frame.valid && (cl.force_refdef || !cl_paused->value) )
443: {
444: cl.force_refdef = false;
1.1.1.2 root 445:
1.1 root 446: V_ClearScene ();
447:
448: // build a refresh entity list and calc cl.sim*
449: // this also calls CL_CalcViewValues which loads
450: // v_forward, etc.
451: CL_AddEntities ();
1.1.1.2 root 452:
1.1 root 453: if (cl_testparticles->value)
454: V_TestParticles ();
455: if (cl_testentities->value)
456: V_TestEntities ();
457: if (cl_testlights->value)
458: V_TestLights ();
459: if (cl_testblend->value)
460: {
461: cl.refdef.blend[0] = 1;
462: cl.refdef.blend[1] = 0.5;
463: cl.refdef.blend[2] = 0.25;
464: cl.refdef.blend[3] = 0.5;
465: }
1.1.1.2 root 466:
1.1 root 467: // offset vieworg appropriately if we're doing stereo separation
468: if ( stereo_separation != 0 )
469: {
470: vec3_t tmp;
471:
472: VectorScale( cl.v_right, stereo_separation, tmp );
473: VectorAdd( cl.refdef.vieworg, tmp, cl.refdef.vieworg );
474: }
1.1.1.2 root 475:
1.1 root 476: // never let it sit exactly on a node line, because a water plane can
477: // dissapear when viewed with the eye exactly on it.
478: // the server protocol only specifies to 1/8 pixel, so add 1/16 in each axis
479: cl.refdef.vieworg[0] += 1.0/16;
480: cl.refdef.vieworg[1] += 1.0/16;
481: cl.refdef.vieworg[2] += 1.0/16;
482:
483: cl.refdef.x = scr_vrect.x;
484: cl.refdef.y = scr_vrect.y;
485: cl.refdef.width = scr_vrect.width;
486: cl.refdef.height = scr_vrect.height;
487: cl.refdef.fov_y = CalcFov (cl.refdef.fov_x, cl.refdef.width, cl.refdef.height);
488: cl.refdef.time = cl.time*0.001;
1.1.1.2 root 489:
1.1 root 490: cl.refdef.areabits = cl.frame.areabits;
491:
492: if (!cl_add_entities->value)
493: r_numentities = 0;
494: if (!cl_add_particles->value)
495: r_numparticles = 0;
496: if (!cl_add_lights->value)
497: r_numdlights = 0;
498: if (!cl_add_blend->value)
499: {
500: VectorClear (cl.refdef.blend);
501: }
1.1.1.2 root 502:
1.1 root 503: cl.refdef.num_entities = r_numentities;
504: cl.refdef.entities = r_entities;
505: cl.refdef.num_particles = r_numparticles;
506: cl.refdef.particles = r_particles;
507: cl.refdef.num_dlights = r_numdlights;
508: cl.refdef.dlights = r_dlights;
509: cl.refdef.lightstyles = r_lightstyles;
1.1.1.2 root 510:
1.1 root 511: cl.refdef.rdflags = cl.frame.playerstate.rdflags;
1.1.1.2 root 512:
1.1 root 513: // sort entities for better cache locality
514: qsort( cl.refdef.entities, cl.refdef.num_entities, sizeof( cl.refdef.entities[0] ), (int (*)(const void *, const void *))entitycmpfnc );
515: }
1.1.1.2 root 516:
1.1 root 517: re.RenderFrame (&cl.refdef);
518: if (cl_stats->value)
519: Com_Printf ("ent:%i lt:%i part:%i\n", r_numentities, r_numdlights, r_numparticles);
520: if ( log_stats->value && ( log_stats_file != 0 ) )
521: fprintf( log_stats_file, "%i,%i,%i,",r_numentities, r_numdlights, r_numparticles);
522:
523:
524: SCR_AddDirtyPoint (scr_vrect.x, scr_vrect.y);
525: SCR_AddDirtyPoint (scr_vrect.x+scr_vrect.width-1,
526: scr_vrect.y+scr_vrect.height-1);
527:
528: SCR_DrawCrosshair ();
529: }
530:
1.1.1.2 root 531:
1.1 root 532: /*
533: =============
534: V_Viewpos_f
535: =============
536: */
537: void V_Viewpos_f (void)
538: {
539: Com_Printf ("(%i %i %i) : %i\n", (int)cl.refdef.vieworg[0],
540: (int)cl.refdef.vieworg[1], (int)cl.refdef.vieworg[2],
541: (int)cl.refdef.viewangles[YAW]);
542: }
1.1.1.2 root 543:
1.1 root 544: /*
545: =============
546: V_Init
547: =============
548: */
549: void V_Init (void)
550: {
551: Cmd_AddCommand ("gun_next", V_Gun_Next_f);
552: Cmd_AddCommand ("gun_prev", V_Gun_Prev_f);
553: Cmd_AddCommand ("gun_model", V_Gun_Model_f);
554:
555: Cmd_AddCommand ("viewpos", V_Viewpos_f);
1.1.1.2 root 556:
1.1 root 557: crosshair = Cvar_Get ("crosshair", "0", CVAR_ARCHIVE);
1.1.1.2 root 558:
1.1 root 559: cl_testblend = Cvar_Get ("cl_testblend", "0", 0);
560: cl_testparticles = Cvar_Get ("cl_testparticles", "0", 0);
561: cl_testentities = Cvar_Get ("cl_testentities", "0", 0);
562: cl_testlights = Cvar_Get ("cl_testlights", "0", 0);
563:
564: cl_stats = Cvar_Get ("cl_stats", "0", 0);
565: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.