summaryrefslogtreecommitdiff
path: root/source/cl_view.c
diff options
context:
space:
mode:
authorAndrey Nazarov <skuller@skuller.net>2007-08-14 20:18:08 +0000
committerAndrey Nazarov <skuller@skuller.net>2007-08-14 20:18:08 +0000
commitf294db4ccf45f6274e65260dd6f9a2c5faa94313 (patch)
treee8cf1ba2bfe9c8417eec17faf912442f52fc4ef2 /source/cl_view.c
Initial import of the new Q2PRO tree.
Diffstat (limited to 'source/cl_view.c')
-rw-r--r--source/cl_view.c544
1 files changed, 544 insertions, 0 deletions
diff --git a/source/cl_view.c b/source/cl_view.c
new file mode 100644
index 0000000..a9f1dd4
--- /dev/null
+++ b/source/cl_view.c
@@ -0,0 +1,544 @@
+/*
+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 "cl_local.h"
+
+//=============
+//
+// development tools for weapons
+//
+int gun_frame;
+qhandle_t gun_model;
+
+//=============
+
+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];
+
+/*
+====================
+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( particle_t *p )
+{
+ if (r_numparticles >= MAX_PARTICLES)
+ return;
+ r_particles[r_numparticles++] = *p;
+
+}
+
+/*
+=====================
+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, vec4_t value)
+{
+ 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] = value[0];
+ ls->rgb[1] = value[1];
+ ls->rgb[2] = value[2];
+ ls->white = value[3];
+}
+
+/*
+================
+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;
+
+ if( cl_testlights->integer == 2 ) {
+ dl = &r_dlights[0];
+ r_numdlights = 1;
+
+ VectorMA( cl.refdef.vieworg, 256, cl.v_forward, dl->origin );
+ VectorSet( dl->color, 1, 1, 1 );
+ dl->intensity = 256;
+ return;
+ }
+
+ 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)
+{
+ int i;
+ char *name;
+ float rotate;
+ vec3_t axis;
+ int time_start, time_map, time_models, time_clients, time_total;
+
+ if (!cl.mapname[0])
+ return; // no map loaded
+
+ time_start = Sys_Milliseconds();
+
+ Con_Close();
+ UI_OpenMenu( UIMENU_NONE );
+
+ // register models, pics, and skins
+ SCR_LoadingString( cl.configstrings[CS_MODELS+1] );
+ ref.BeginRegistration( cl.mapname );
+ time_map = Sys_Milliseconds();
+
+ // precache status bar pics
+ SCR_LoadingString( "pics" );
+ SCR_TouchPics ();
+
+ SCR_LoadingString( "models" );
+
+ CL_RegisterTEntModels ();
+
+ cl.numWeaponModels = 1;
+ strcpy(cl.weaponModels[0], "weapon.md2");
+
+ for (i=1 ; i<MAX_MODELS ; i++) {
+ name = cl.configstrings[CS_MODELS+i];
+ if( !name[0] ) {
+ break;
+ }
+ if (name[0] == '#') {
+ // special player weapon model
+ if (cl.numWeaponModels < MAX_CLIENTWEAPONMODELS) {
+ strcpy( cl.weaponModels[cl.numWeaponModels++], name + 1 );
+ }
+ } else {
+ cl.model_draw[i] = ref.RegisterModel( name );
+ if( name[0] == '*' )
+ cl.model_clip[i] = CM_InlineModel( &cl.cm, name );
+ else
+ cl.model_clip[i] = NULL;
+ }
+ }
+ time_models = Sys_Milliseconds();
+
+ SCR_LoadingString( "images" );
+ for (i=1 ; i<MAX_IMAGES; i++) {
+ name = cl.configstrings[CS_IMAGES+i];
+ if( !name[0] ) {
+ break;
+ }
+ cl.image_precache[i] = ref.RegisterPic (name);
+ }
+
+ SCR_LoadingString( "clients" );
+ for (i=0 ; i<MAX_CLIENTS ; i++)
+ {
+ name = cl.configstrings[CS_PLAYERSKINS+i];
+ if( !name[0] )
+ continue;
+
+ CL_LoadClientinfo( &cl.clientinfo[i], name );
+ }
+
+ CL_LoadClientinfo (&cl.baseclientinfo, "unnamed\\male/grunt");
+ time_clients = Sys_Milliseconds();
+
+ SCR_LoadingString( "sky" );
+
+ // set sky textures and speed
+ rotate = atof (cl.configstrings[CS_SKYROTATE]);
+ sscanf (cl.configstrings[CS_SKYAXIS], "%f %f %f",
+ &axis[0], &axis[1], &axis[2]);
+ ref.SetSky (cl.configstrings[CS_SKY], rotate, axis);
+
+ SCR_LoadingString( "" );
+
+ // the renderer can now free unneeded stuff
+ ref.EndRegistration ();
+
+ FS_FlushCache();
+
+ // clear any lines of console text
+ Con_ClearNotify_f ();
+
+ SCR_UpdateScreen ();
+
+ time_total = Sys_Milliseconds();
+ Com_DPrintf( "Map loaded in %d msec (%d,%d,%d,%d)\n", time_total - time_start,
+ time_map - time_start, time_models - time_map, time_clients - time_models,
+ time_total - time_clients );
+}
+
+
+//============================================================================
+
+// 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 = 0;
+ return;
+ }
+ Com_sprintf (name, sizeof(name), "models/%s/tris.md2", Cmd_Argv(1));
+ gun_model = ref.RegisterModel (name);
+}
+
+//============================================================================
+
+static int entitycmpfnc( const entity_t *a, const entity_t *b )
+{
+ /*
+ ** all other models are sorted by model then skin
+ */
+ if ( a->model == b->model )
+ {
+ return ( ( int ) a->skin - ( int ) b->skin );
+ }
+ else
+ {
+ return ( ( int ) a->model - ( int ) b->model );
+ }
+}
+
+void V_SetLightLevel( void ) {
+ vec3_t shadelight;
+
+ // save off light value for server to look at (BIG HACK!)
+ ref.LightPoint( cl.refdef.vieworg, shadelight );
+
+ // pick the greatest component, which should be the same
+ // as the mono value returned by software
+ if( shadelight[0] > shadelight[1] ) {
+ if( shadelight[0] > shadelight[2] ) {
+ cl.lightlevel = 150.0f*shadelight[0];
+ } else {
+ cl.lightlevel = 150.0f*shadelight[2];
+ }
+ } else {
+ if( shadelight[1] > shadelight[2] ) {
+ cl.lightlevel = 150.0f*shadelight[1];
+ } else {
+ cl.lightlevel = 150.0f*shadelight[2];
+ }
+ }
+}
+
+/*
+==================
+V_RenderView
+
+==================
+*/
+void V_RenderView( void ) {
+ // 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 ) {
+ 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->integer)
+ V_TestParticles ();
+ if (cl_testentities->integer)
+ V_TestEntities ();
+ if (cl_testlights->integer)
+ V_TestLights ();
+ if (cl_testblend->integer)
+ {
+ cl.refdef.blend[0] = 1;
+ cl.refdef.blend[1] = 0.5;
+ cl.refdef.blend[2] = 0.25;
+ cl.refdef.blend[3] = 0.5;
+ }
+
+ // 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 = Com_CalcFov (cl.refdef.fov_x, cl.refdef.width, cl.refdef.height);
+ cl.refdef.time = cl.time*0.001;
+
+ if( cl.frame.areabytes ) {
+ cl.refdef.areabits = cl.frame.areabits;
+ } else {
+ cl.refdef.areabits = NULL;
+ }
+
+ if (!cl_add_entities->integer)
+ r_numentities = 0;
+ if (!cl_add_particles->integer)
+ r_numparticles = 0;
+ if (!cl_add_lights->integer)
+ 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.ps.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 );
+ }
+
+ ref.RenderFrame (&cl.refdef);
+ if (cl_stats->integer)
+ Com_Printf ("ent:%i lt:%i part:%i\n", r_numentities, r_numdlights, r_numparticles);
+
+ V_SetLightLevel();
+
+}
+
+
+/*
+=============
+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", CVAR_CHEAT);
+
+ cl_stats = Cvar_Get ("cl_stats", "0", 0);
+}
+
+