|
|
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.2 ! root 272: if (name[0] == '#') { ! 273: // special player weapon model ! 274: if (num_cl_weaponmodels < MAX_CLIENTWEAPONMODELS) { ! 275: strncpy(cl_weaponmodels[num_cl_weaponmodels], cl.configstrings[CS_MODELS+i]+1, ! 276: sizeof(cl_weaponmodels[num_cl_weaponmodels]) - 1); ! 277: num_cl_weaponmodels++; ! 278: } ! 279: } else { ! 280: cl.model_draw[i] = re.RegisterModel (cl.configstrings[CS_MODELS+i]); ! 281: if (name[0] == '*') ! 282: cl.model_clip[i] = CM_InlineModel (cl.configstrings[CS_MODELS+i]); ! 283: else ! 284: cl.model_clip[i] = NULL; ! 285: } 1.1 root 286: if (name[0] != '*') 287: Com_Printf (" \r"); 288: } 289: Com_Printf ("images\r", i); 290: SCR_UpdateScreen (); 291: for (i=1 ; i<MAX_IMAGES && cl.configstrings[CS_IMAGES+i][0] ; i++) 292: { 293: cl.image_precache[i] = re.RegisterPic (cl.configstrings[CS_IMAGES+i]); 294: Sys_SendKeyEvents (); // pump message loop 295: } 296: Com_Printf (" \r"); 297: for (i=0 ; i<MAX_CLIENTS ; i++) 298: { 299: if (!cl.configstrings[CS_PLAYERSKINS+i][0]) 300: continue; 301: Com_Printf ("client %i\r", i); 302: SCR_UpdateScreen (); 303: Sys_SendKeyEvents (); // pump message loop 304: CL_ParseClientinfo (i); 305: Com_Printf (" \r"); 306: } 1.1.1.2 ! root 307: 1.1 root 308: CL_LoadClientinfo (&cl.baseclientinfo, "unnamed\\male/grunt"); 1.1.1.2 ! root 309: 1.1 root 310: // set sky textures and speed 311: Com_Printf ("sky\r", i); 312: SCR_UpdateScreen (); 313: rotate = atof (cl.configstrings[CS_SKYROTATE]); 314: sscanf (cl.configstrings[CS_SKYAXIS], "%f %f %f", 315: &axis[0], &axis[1], &axis[2]); 316: re.SetSky (cl.configstrings[CS_SKY], rotate, axis); 317: Com_Printf (" \r"); 1.1.1.2 ! root 318: 1.1 root 319: // the renderer can now free unneeded stuff 320: re.EndRegistration (); 1.1.1.2 ! root 321: 1.1 root 322: // clear any lines of console text 323: Con_ClearNotify (); 1.1.1.2 ! root 324: 1.1 root 325: SCR_UpdateScreen (); 326: cl.refresh_prepped = true; 327: cl.force_refdef = true; // make sure we have a valid refdef 328: 329: // start the cd track 330: CDAudio_Play (atoi(cl.configstrings[CS_CDTRACK]), true); 331: } 1.1.1.2 ! root 332: 1.1 root 333: /* 334: ==================== 335: CalcFov 336: ==================== 337: */ 338: float CalcFov (float fov_x, float width, float height) 339: { 340: float a; 341: float x; 1.1.1.2 ! root 342: 1.1 root 343: if (fov_x < 1 || fov_x > 179) 344: Com_Error (ERR_DROP, "Bad fov: %f", fov_x); 1.1.1.2 ! root 345: 1.1 root 346: x = width/tan(fov_x/360*M_PI); 1.1.1.2 ! root 347: 1.1 root 348: a = atan (height/x); 1.1.1.2 ! root 349: 1.1 root 350: a = a*360/M_PI; 1.1.1.2 ! root 351: 1.1 root 352: return a; 353: } 1.1.1.2 ! root 354: 1.1 root 355: //============================================================================ 1.1.1.2 ! root 356: 1.1 root 357: // gun frame debugging functions 358: void V_Gun_Next_f (void) 359: { 360: gun_frame++; 361: Com_Printf ("frame %i\n", gun_frame); 362: } 1.1.1.2 ! root 363: 1.1 root 364: void V_Gun_Prev_f (void) 365: { 366: gun_frame--; 367: if (gun_frame < 0) 368: gun_frame = 0; 369: Com_Printf ("frame %i\n", gun_frame); 370: } 1.1.1.2 ! root 371: 1.1 root 372: void V_Gun_Model_f (void) 373: { 374: char name[MAX_QPATH]; 1.1.1.2 ! root 375: 1.1 root 376: if (Cmd_Argc() != 2) 377: { 378: gun_model = NULL; 379: return; 380: } 381: Com_sprintf (name, sizeof(name), "models/%s/tris.md2", Cmd_Argv(1)); 382: gun_model = re.RegisterModel (name); 383: } 1.1.1.2 ! root 384: 1.1 root 385: //============================================================================ 386: 1.1.1.2 ! root 387: 1.1 root 388: /* 389: ================= 390: SCR_DrawCrosshair 391: ================= 392: */ 393: void SCR_DrawCrosshair (void) 394: { 395: if (!crosshair->value) 396: return; 397: 398: if (crosshair->modified) 399: { 400: crosshair->modified = false; 401: SCR_TouchPics (); 402: } 403: 404: if (!crosshair_pic[0]) 405: return; 406: 407: re.DrawPic (scr_vrect.x + ((scr_vrect.width - crosshair_width)>>1) 408: , scr_vrect.y + ((scr_vrect.height - crosshair_height)>>1), crosshair_pic); 409: } 1.1.1.2 ! root 410: 1.1 root 411: /* 412: ================== 413: V_RenderView 1.1.1.2 ! root 414: 1.1 root 415: ================== 416: */ 417: void V_RenderView( float stereo_separation ) 418: { 419: extern int entitycmpfnc( const entity_t *, const entity_t * ); 420: 421: if (cls.state != ca_active) 422: return; 1.1.1.2 ! root 423: 1.1 root 424: if (!cl.refresh_prepped) 425: return; // still loading 426: 427: if (cl_timedemo->value) 428: { 429: if (!cl.timedemo_start) 430: cl.timedemo_start = Sys_Milliseconds (); 431: cl.timedemo_frames++; 432: } 433: 434: // an invalid frame will just use the exact previous refdef 435: // we can't use the old frame if the video mode has changed, though... 436: if ( cl.frame.valid && (cl.force_refdef || !cl_paused->value) ) 437: { 438: cl.force_refdef = false; 1.1.1.2 ! root 439: 1.1 root 440: V_ClearScene (); 441: 442: // build a refresh entity list and calc cl.sim* 443: // this also calls CL_CalcViewValues which loads 444: // v_forward, etc. 445: CL_AddEntities (); 1.1.1.2 ! root 446: 1.1 root 447: if (cl_testparticles->value) 448: V_TestParticles (); 449: if (cl_testentities->value) 450: V_TestEntities (); 451: if (cl_testlights->value) 452: V_TestLights (); 453: if (cl_testblend->value) 454: { 455: cl.refdef.blend[0] = 1; 456: cl.refdef.blend[1] = 0.5; 457: cl.refdef.blend[2] = 0.25; 458: cl.refdef.blend[3] = 0.5; 459: } 1.1.1.2 ! root 460: 1.1 root 461: // offset vieworg appropriately if we're doing stereo separation 462: if ( stereo_separation != 0 ) 463: { 464: vec3_t tmp; 465: 466: VectorScale( cl.v_right, stereo_separation, tmp ); 467: VectorAdd( cl.refdef.vieworg, tmp, cl.refdef.vieworg ); 468: } 1.1.1.2 ! root 469: 1.1 root 470: // never let it sit exactly on a node line, because a water plane can 471: // dissapear when viewed with the eye exactly on it. 472: // the server protocol only specifies to 1/8 pixel, so add 1/16 in each axis 473: cl.refdef.vieworg[0] += 1.0/16; 474: cl.refdef.vieworg[1] += 1.0/16; 475: cl.refdef.vieworg[2] += 1.0/16; 476: 477: cl.refdef.x = scr_vrect.x; 478: cl.refdef.y = scr_vrect.y; 479: cl.refdef.width = scr_vrect.width; 480: cl.refdef.height = scr_vrect.height; 481: cl.refdef.fov_y = CalcFov (cl.refdef.fov_x, cl.refdef.width, cl.refdef.height); 482: cl.refdef.time = cl.time*0.001; 1.1.1.2 ! root 483: 1.1 root 484: cl.refdef.areabits = cl.frame.areabits; 485: 486: if (!cl_add_entities->value) 487: r_numentities = 0; 488: if (!cl_add_particles->value) 489: r_numparticles = 0; 490: if (!cl_add_lights->value) 491: r_numdlights = 0; 492: if (!cl_add_blend->value) 493: { 494: VectorClear (cl.refdef.blend); 495: } 1.1.1.2 ! root 496: 1.1 root 497: cl.refdef.num_entities = r_numentities; 498: cl.refdef.entities = r_entities; 499: cl.refdef.num_particles = r_numparticles; 500: cl.refdef.particles = r_particles; 501: cl.refdef.num_dlights = r_numdlights; 502: cl.refdef.dlights = r_dlights; 503: cl.refdef.lightstyles = r_lightstyles; 1.1.1.2 ! root 504: 1.1 root 505: cl.refdef.rdflags = cl.frame.playerstate.rdflags; 1.1.1.2 ! root 506: 1.1 root 507: // sort entities for better cache locality 508: qsort( cl.refdef.entities, cl.refdef.num_entities, sizeof( cl.refdef.entities[0] ), (int (*)(const void *, const void *))entitycmpfnc ); 509: } 1.1.1.2 ! root 510: 1.1 root 511: re.RenderFrame (&cl.refdef); 512: if (cl_stats->value) 513: Com_Printf ("ent:%i lt:%i part:%i\n", r_numentities, r_numdlights, r_numparticles); 514: if ( log_stats->value && ( log_stats_file != 0 ) ) 515: fprintf( log_stats_file, "%i,%i,%i,",r_numentities, r_numdlights, r_numparticles); 516: 517: 518: SCR_AddDirtyPoint (scr_vrect.x, scr_vrect.y); 519: SCR_AddDirtyPoint (scr_vrect.x+scr_vrect.width-1, 520: scr_vrect.y+scr_vrect.height-1); 521: 522: SCR_DrawCrosshair (); 523: } 524: 1.1.1.2 ! root 525: 1.1 root 526: /* 527: ============= 528: V_Viewpos_f 529: ============= 530: */ 531: void V_Viewpos_f (void) 532: { 533: Com_Printf ("(%i %i %i) : %i\n", (int)cl.refdef.vieworg[0], 534: (int)cl.refdef.vieworg[1], (int)cl.refdef.vieworg[2], 535: (int)cl.refdef.viewangles[YAW]); 536: } 1.1.1.2 ! root 537: 1.1 root 538: /* 539: ============= 540: V_Init 541: ============= 542: */ 543: void V_Init (void) 544: { 545: Cmd_AddCommand ("gun_next", V_Gun_Next_f); 546: Cmd_AddCommand ("gun_prev", V_Gun_Prev_f); 547: Cmd_AddCommand ("gun_model", V_Gun_Model_f); 548: 549: Cmd_AddCommand ("viewpos", V_Viewpos_f); 1.1.1.2 ! root 550: 1.1 root 551: crosshair = Cvar_Get ("crosshair", "0", CVAR_ARCHIVE); 1.1.1.2 ! root 552: 1.1 root 553: cl_testblend = Cvar_Get ("cl_testblend", "0", 0); 554: cl_testparticles = Cvar_Get ("cl_testparticles", "0", 0); 555: cl_testentities = Cvar_Get ("cl_testentities", "0", 0); 556: cl_testlights = Cvar_Get ("cl_testlights", "0", 0); 557: 558: cl_stats = Cvar_Get ("cl_stats", "0", 0); 559: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.