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