123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 |
- /*
- Copyright (C) 1997-2001 Id Software, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- // cl_view.c -- player rendering positioning
- #include "client.h"
- //=============
- //
- // development tools for weapons
- //
- int gun_frame;
- struct model_s *gun_model;
- //=============
- cvar_t *crosshair;
- cvar_t *cl_testparticles;
- cvar_t *cl_testentities;
- cvar_t *cl_testlights;
- cvar_t *cl_testblend;
- cvar_t *cl_stats;
- int r_numdlights;
- dlight_t r_dlights[MAX_DLIGHTS];
- int r_numentities;
- entity_t r_entities[MAX_ENTITIES];
- int r_numparticles;
- particle_t r_particles[MAX_PARTICLES];
- lightstyle_t r_lightstyles[MAX_LIGHTSTYLES];
- char cl_weaponmodels[MAX_CLIENTWEAPONMODELS][MAX_QPATH];
- int num_cl_weaponmodels;
- /*
- ====================
- V_ClearScene
- Specifies the model that will be used as the world
- ====================
- */
- void V_ClearScene (void)
- {
- r_numdlights = 0;
- r_numentities = 0;
- r_numparticles = 0;
- }
- /*
- =====================
- V_AddEntity
- =====================
- */
- void V_AddEntity (entity_t *ent)
- {
- if (r_numentities >= MAX_ENTITIES)
- return;
- r_entities[r_numentities++] = *ent;
- }
- /*
- =====================
- V_AddParticle
- =====================
- */
- void V_AddParticle (vec3_t org, int color, float alpha)
- {
- particle_t *p;
- if (r_numparticles >= MAX_PARTICLES)
- return;
- p = &r_particles[r_numparticles++];
- VectorCopy (org, p->origin);
- p->color = color;
- p->alpha = alpha;
- }
- /*
- =====================
- V_AddLight
- =====================
- */
- void V_AddLight (vec3_t org, float intensity, float r, float g, float b)
- {
- dlight_t *dl;
- if (r_numdlights >= MAX_DLIGHTS)
- return;
- dl = &r_dlights[r_numdlights++];
- VectorCopy (org, dl->origin);
- dl->intensity = intensity;
- dl->color[0] = r;
- dl->color[1] = g;
- dl->color[2] = b;
- }
- /*
- =====================
- V_AddLightStyle
- =====================
- */
- void V_AddLightStyle (int style, float r, float g, float b)
- {
- lightstyle_t *ls;
- if (style < 0 || style > MAX_LIGHTSTYLES)
- Com_Error (ERR_DROP, "Bad light style %i", style);
- ls = &r_lightstyles[style];
- ls->white = r+g+b;
- ls->rgb[0] = r;
- ls->rgb[1] = g;
- ls->rgb[2] = b;
- }
- /*
- ================
- V_TestParticles
- If cl_testparticles is set, create 4096 particles in the view
- ================
- */
- void V_TestParticles (void)
- {
- particle_t *p;
- int i, j;
- float d, r, u;
- r_numparticles = MAX_PARTICLES;
- for (i=0 ; i<r_numparticles ; i++)
- {
- d = i*0.25;
- r = 4*((i&7)-3.5);
- u = 4*(((i>>3)&7)-3.5);
- p = &r_particles[i];
- for (j=0 ; j<3 ; j++)
- p->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*d +
- cl.v_right[j]*r + cl.v_up[j]*u;
- p->color = 8;
- p->alpha = cl_testparticles->value;
- }
- }
- /*
- ================
- V_TestEntities
- If cl_testentities is set, create 32 player models
- ================
- */
- void V_TestEntities (void)
- {
- int i, j;
- float f, r;
- entity_t *ent;
- r_numentities = 32;
- memset (r_entities, 0, sizeof(r_entities));
- for (i=0 ; i<r_numentities ; i++)
- {
- ent = &r_entities[i];
- r = 64 * ( (i%4) - 1.5 );
- f = 64 * (i/4) + 128;
- for (j=0 ; j<3 ; j++)
- ent->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*f +
- cl.v_right[j]*r;
- ent->model = cl.baseclientinfo.model;
- ent->skin = cl.baseclientinfo.skin;
- }
- }
- /*
- ================
- V_TestLights
- If cl_testlights is set, create 32 lights models
- ================
- */
- void V_TestLights (void)
- {
- int i, j;
- float f, r;
- dlight_t *dl;
- r_numdlights = 32;
- memset (r_dlights, 0, sizeof(r_dlights));
- for (i=0 ; i<r_numdlights ; i++)
- {
- dl = &r_dlights[i];
- r = 64 * ( (i%4) - 1.5 );
- f = 64 * (i/4) + 128;
- for (j=0 ; j<3 ; j++)
- dl->origin[j] = cl.refdef.vieworg[j] + cl.v_forward[j]*f +
- cl.v_right[j]*r;
- dl->color[0] = ((i%6)+1) & 1;
- dl->color[1] = (((i%6)+1) & 2)>>1;
- dl->color[2] = (((i%6)+1) & 4)>>2;
- dl->intensity = 200;
- }
- }
- //===================================================================
- /*
- =================
- CL_PrepRefresh
- Call before entering a new level, or after changing dlls
- =================
- */
- void CL_PrepRefresh (void)
- {
- char mapname[32];
- int i;
- char name[MAX_QPATH];
- float rotate;
- vec3_t axis;
- if (!cl.configstrings[CS_MODELS+1][0])
- return; // no map loaded
- SCR_AddDirtyPoint (0, 0);
- SCR_AddDirtyPoint (viddef.width-1, viddef.height-1);
- // let the render dll load the map
- strcpy (mapname, cl.configstrings[CS_MODELS+1] + 5); // skip "maps/"
- mapname[strlen(mapname)-4] = 0; // cut off ".bsp"
- // register models, pics, and skins
- Com_Printf ("Map: %s\r", mapname);
- SCR_UpdateScreen ();
- re.BeginRegistration (mapname);
- Com_Printf (" \r");
- // precache status bar pics
- Com_Printf ("pics\r");
- SCR_UpdateScreen ();
- SCR_TouchPics ();
- Com_Printf (" \r");
- CL_RegisterTEntModels ();
- num_cl_weaponmodels = 1;
- strcpy(cl_weaponmodels[0], "weapon.md2");
- for (i=1 ; i<MAX_MODELS && cl.configstrings[CS_MODELS+i][0] ; i++)
- {
- strcpy (name, cl.configstrings[CS_MODELS+i]);
- name[37] = 0; // never go beyond one line
- if (name[0] != '*')
- Com_Printf ("%s\r", name);
- SCR_UpdateScreen ();
- Sys_SendKeyEvents (); // pump message loop
- if (name[0] == '#')
- {
- // special player weapon model
- if (num_cl_weaponmodels < MAX_CLIENTWEAPONMODELS)
- {
- strncpy(cl_weaponmodels[num_cl_weaponmodels], cl.configstrings[CS_MODELS+i]+1,
- sizeof(cl_weaponmodels[num_cl_weaponmodels]) - 1);
- num_cl_weaponmodels++;
- }
- }
- else
- {
- cl.model_draw[i] = re.RegisterModel (cl.configstrings[CS_MODELS+i]);
- if (name[0] == '*')
- cl.model_clip[i] = CM_InlineModel (cl.configstrings[CS_MODELS+i]);
- else
- cl.model_clip[i] = NULL;
- }
- if (name[0] != '*')
- Com_Printf (" \r");
- }
- Com_Printf ("images\r", i);
- SCR_UpdateScreen ();
- for (i=1 ; i<MAX_IMAGES && cl.configstrings[CS_IMAGES+i][0] ; i++)
- {
- cl.image_precache[i] = re.RegisterPic (cl.configstrings[CS_IMAGES+i]);
- Sys_SendKeyEvents (); // pump message loop
- }
-
- Com_Printf (" \r");
- for (i=0 ; i<MAX_CLIENTS ; i++)
- {
- if (!cl.configstrings[CS_PLAYERSKINS+i][0])
- continue;
- Com_Printf ("client %i\r", i);
- SCR_UpdateScreen ();
- Sys_SendKeyEvents (); // pump message loop
- CL_ParseClientinfo (i);
- Com_Printf (" \r");
- }
- CL_LoadClientinfo (&cl.baseclientinfo, "unnamed\\male/grunt");
- // set sky textures and speed
- Com_Printf ("sky\r", i);
- SCR_UpdateScreen ();
- rotate = atof (cl.configstrings[CS_SKYROTATE]);
- sscanf (cl.configstrings[CS_SKYAXIS], "%f %f %f",
- &axis[0], &axis[1], &axis[2]);
- re.SetSky (cl.configstrings[CS_SKY], rotate, axis);
- Com_Printf (" \r");
- // the renderer can now free unneeded stuff
- re.EndRegistration ();
- // clear any lines of console text
- Con_ClearNotify ();
- SCR_UpdateScreen ();
- cl.refresh_prepped = true;
- cl.force_refdef = true; // make sure we have a valid refdef
- // start the cd track
- CDAudio_Play (atoi(cl.configstrings[CS_CDTRACK]), true);
- }
- /*
- ====================
- CalcFov
- ====================
- */
- float CalcFov (float fov_x, float width, float height)
- {
- float a;
- float x;
- if (fov_x < 1 || fov_x > 179)
- Com_Error (ERR_DROP, "Bad fov: %f", fov_x);
- x = width/tan(fov_x/360*M_PI);
- a = atan (height/x);
- a = a*360/M_PI;
- return a;
- }
- //============================================================================
- // gun frame debugging functions
- void V_Gun_Next_f (void)
- {
- gun_frame++;
- Com_Printf ("frame %i\n", gun_frame);
- }
- void V_Gun_Prev_f (void)
- {
- gun_frame--;
- if (gun_frame < 0)
- gun_frame = 0;
- Com_Printf ("frame %i\n", gun_frame);
- }
- void V_Gun_Model_f (void)
- {
- char name[MAX_QPATH];
- if (Cmd_Argc() != 2)
- {
- gun_model = NULL;
- return;
- }
- Com_sprintf (name, sizeof(name), "models/%s/tris.md2", Cmd_Argv(1));
- gun_model = re.RegisterModel (name);
- }
- //============================================================================
- /*
- =================
- SCR_DrawCrosshair
- =================
- */
- void SCR_DrawCrosshair (void)
- {
- if (!crosshair->value)
- return;
- if (crosshair->modified)
- {
- crosshair->modified = false;
- SCR_TouchPics ();
- }
- if (!crosshair_pic[0])
- return;
- re.DrawPic (scr_vrect.x + ((scr_vrect.width - crosshair_width)>>1)
- , scr_vrect.y + ((scr_vrect.height - crosshair_height)>>1), crosshair_pic);
- }
- /*
- ==================
- V_RenderView
- ==================
- */
- void V_RenderView( float stereo_separation )
- {
- extern int entitycmpfnc( const entity_t *, const entity_t * );
- if (cls.state != ca_active)
- return;
- if (!cl.refresh_prepped)
- return; // still loading
- if (cl_timedemo->value)
- {
- if (!cl.timedemo_start)
- cl.timedemo_start = Sys_Milliseconds ();
- cl.timedemo_frames++;
- }
- // an invalid frame will just use the exact previous refdef
- // we can't use the old frame if the video mode has changed, though...
- if ( cl.frame.valid && (cl.force_refdef || !cl_paused->value) )
- {
- cl.force_refdef = false;
- V_ClearScene ();
- // build a refresh entity list and calc cl.sim*
- // this also calls CL_CalcViewValues which loads
- // v_forward, etc.
- CL_AddEntities ();
- if (cl_testparticles->value)
- V_TestParticles ();
- if (cl_testentities->value)
- V_TestEntities ();
- if (cl_testlights->value)
- V_TestLights ();
- if (cl_testblend->value)
- {
- cl.refdef.blend[0] = 1;
- cl.refdef.blend[1] = 0.5;
- cl.refdef.blend[2] = 0.25;
- cl.refdef.blend[3] = 0.5;
- }
- // offset vieworg appropriately if we're doing stereo separation
- if ( stereo_separation != 0 )
- {
- vec3_t tmp;
- VectorScale( cl.v_right, stereo_separation, tmp );
- VectorAdd( cl.refdef.vieworg, tmp, cl.refdef.vieworg );
- }
- // never let it sit exactly on a node line, because a water plane can
- // dissapear when viewed with the eye exactly on it.
- // the server protocol only specifies to 1/8 pixel, so add 1/16 in each axis
- cl.refdef.vieworg[0] += 1.0/16;
- cl.refdef.vieworg[1] += 1.0/16;
- cl.refdef.vieworg[2] += 1.0/16;
- cl.refdef.x = scr_vrect.x;
- cl.refdef.y = scr_vrect.y;
- cl.refdef.width = scr_vrect.width;
- cl.refdef.height = scr_vrect.height;
- cl.refdef.fov_y = CalcFov (cl.refdef.fov_x, cl.refdef.width, cl.refdef.height);
- cl.refdef.time = cl.time*0.001;
- cl.refdef.areabits = cl.frame.areabits;
- if (!cl_add_entities->value)
- r_numentities = 0;
- if (!cl_add_particles->value)
- r_numparticles = 0;
- if (!cl_add_lights->value)
- r_numdlights = 0;
- if (!cl_add_blend->value)
- {
- VectorClear (cl.refdef.blend);
- }
- cl.refdef.num_entities = r_numentities;
- cl.refdef.entities = r_entities;
- cl.refdef.num_particles = r_numparticles;
- cl.refdef.particles = r_particles;
- cl.refdef.num_dlights = r_numdlights;
- cl.refdef.dlights = r_dlights;
- cl.refdef.lightstyles = r_lightstyles;
- cl.refdef.rdflags = cl.frame.playerstate.rdflags;
- // sort entities for better cache locality
- qsort( cl.refdef.entities, cl.refdef.num_entities, sizeof( cl.refdef.entities[0] ), (int (*)(const void *, const void *))entitycmpfnc );
- }
- re.RenderFrame (&cl.refdef);
- if (cl_stats->value)
- Com_Printf ("ent:%i lt:%i part:%i\n", r_numentities, r_numdlights, r_numparticles);
- if ( log_stats->value && ( log_stats_file != 0 ) )
- fprintf( log_stats_file, "%i,%i,%i,",r_numentities, r_numdlights, r_numparticles);
- SCR_AddDirtyPoint (scr_vrect.x, scr_vrect.y);
- SCR_AddDirtyPoint (scr_vrect.x+scr_vrect.width-1,
- scr_vrect.y+scr_vrect.height-1);
- SCR_DrawCrosshair ();
- }
- /*
- =============
- V_Viewpos_f
- =============
- */
- void V_Viewpos_f (void)
- {
- Com_Printf ("(%i %i %i) : %i\n", (int)cl.refdef.vieworg[0],
- (int)cl.refdef.vieworg[1], (int)cl.refdef.vieworg[2],
- (int)cl.refdef.viewangles[YAW]);
- }
- /*
- =============
- V_Init
- =============
- */
- void V_Init (void)
- {
- Cmd_AddCommand ("gun_next", V_Gun_Next_f);
- Cmd_AddCommand ("gun_prev", V_Gun_Prev_f);
- Cmd_AddCommand ("gun_model", V_Gun_Model_f);
- Cmd_AddCommand ("viewpos", V_Viewpos_f);
- crosshair = Cvar_Get ("crosshair", "0", CVAR_ARCHIVE);
- cl_testblend = Cvar_Get ("cl_testblend", "0", 0);
- cl_testparticles = Cvar_Get ("cl_testparticles", "0", 0);
- cl_testentities = Cvar_Get ("cl_testentities", "0", 0);
- cl_testlights = Cvar_Get ("cl_testlights", "0", 0);
- cl_stats = Cvar_Get ("cl_stats", "0", 0);
- }
|