From 9adb98d87e1175dc553b20dd7d51b648d5d49fc3 Mon Sep 17 00:00:00 2001 From: Joseph Carter Date: Fri, 12 May 2000 23:19:23 +0000 Subject: [PATCH] A little more progress --- include/glquake.h | 11 +- include/quakedef.h | 18 +- source/Makefile | 16 +- source/gl_part.c | 606 +++++++++++++++++++++++ source/{view.c => gl_view.c} | 85 ---- source/r_part.c | 56 --- source/r_view.c | 921 +++++++++++++++++++++++++++++++++++ 7 files changed, 1557 insertions(+), 156 deletions(-) create mode 100644 source/gl_part.c rename source/{view.c => gl_view.c} (92%) create mode 100644 source/r_view.c diff --git a/include/glquake.h b/include/glquake.h index 4a8ab8e..e5f11ca 100644 --- a/include/glquake.h +++ b/include/glquake.h @@ -20,6 +20,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // disable data conversion warnings #ifdef _WIN32 +#pragma warning(disable : 4244) // MIPS +#pragma warning(disable : 4136) // X86 +#pragma warning(disable : 4051) // ALPHA + #include #endif @@ -235,8 +239,8 @@ void GL_Bind (int texnum); #define TEXTURE1_SGIS 0x835F #ifdef _WIN32 -typedef void (APIENTRY *lpMTexFUNC) (GLenum, GLfloat, GLfloat); -typedef void (APIENTRY *lpSelTexFUNC) (GLenum); +typedef void (GLAPIENTRY *lpMTexFUNC) (GLenum, GLfloat, GLfloat); +typedef void (GLAPIENTRY *lpSelTexFUNC) (GLenum); extern lpMTexFUNC qglMTexCoord2fSGIS; extern lpSelTexFUNC qglSelectTextureSGIS; #endif @@ -270,6 +274,9 @@ void R_RotateForEntity (entity_t *e); // // gl_rlight.c // + +extern float v_blend[4]; + void R_MarkLights (dlight_t *light, int bit, mnode_t *node); void R_AnimateLight (void); void R_RenderDlights (void); diff --git a/include/quakedef.h b/include/quakedef.h index 2a69d7e..7c00de9 100644 --- a/include/quakedef.h +++ b/include/quakedef.h @@ -56,12 +56,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "render.h" #include "client.h" -#ifdef GLQUAKE -#include "gl_model.h" -#else -#include "model.h" -#include "d_iface.h" -#endif +//#ifdef GLQUAKE +//#include "gl_model.h" +//#else +//#include "model.h" +//#include "d_iface.h" +//#endif #include "input.h" #include "keys.h" @@ -72,9 +72,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "cdaudio.h" #include "pmove.h" -#ifdef GLQUAKE -#include "glquake.h" -#endif +//#ifdef GLQUAKE +//#include "glquake.h" +//#endif #ifndef max #define max(a,b) ((a) > (b) ? (a) : (b)) diff --git a/source/Makefile b/source/Makefile index 7ee47db..f2d9ecc 100644 --- a/source/Makefile +++ b/source/Makefile @@ -10,12 +10,16 @@ CL_X11_name=qw-client-x11 CL_X11_libs=-lX11 -lXext CL_GLX_name=qw-client-glx -CL_GLX_libs=-lX11 -lXext +CL_GLX_libs=-lX11 -lXext -lGL DIRECTORIES= vpath %.a $(patsubst @%,%,$(DIRECTORIES)) /usr/lib CPPFLAGS=-I . -I ../include -DELF -Did386=1 -MMD -Dstricmp=strcasecmp + +gcc -I . -I ../include -DELF -Did386=1 -MMD -Dstricmp=strcasecmp -c -o gl_draw.o gl_draw.c + + CFLAGS=-Wall -Werror CXXFLAGS=-Wall -Werror LDFLAGS=-L/usr/X11R6/lib @@ -96,10 +100,12 @@ CL_SW_sources=\ r_light.c \ r_main.c \ r_misc.c \ + r_part.c \ r_sky.c \ r_sprite.c \ r_surf.c \ r_vars.c \ + r_view.c \ screen.c \ d_copy.S \ d_draw.S \ @@ -140,13 +146,11 @@ CL_sources=\ sys_linux.c \ cd_linux.c \ wad.c \ - view.c \ snd_dma.c \ snd_mem.c \ snd_mix.c \ skin.c \ sbar.c \ - r_part.c \ nonintel.c \ menu.c \ keys.c \ @@ -172,12 +176,14 @@ CL_GLX_sources=\ gl_mesh.c \ gl_model.c \ gl_ngraph.c \ + gl_part.c \ gl_refrag.c \ gl_rlight.c \ gl_rmain.c \ gl_rmisc.c \ gl_rsurf.c \ gl_screen.c \ + gl_view.c \ gl_warp.c \ gl_vidlinuxglx.c @@ -197,6 +203,8 @@ $(CL_SVGA_name): $(COM_objects) $(CL_objects) $(CL_SW_objects) $(CL_SVGA_objects $(CL_X11_name): $(COM_objects) $(CL_objects) $(CL_SW_objects) $(CL_X11_objects) $(CC) $(LDFLAGS) -o $@ $^ -lm $(CL_X11_libs) +$(CL_GLX_objects): CPPFLAGS += -I/usr/include/GL + $(CL_GLX_name): $(COM_objects) $(CL_objects) $(CL_GL_objects) $(CL_GLX_objects) $(CC) $(LDFLAGS) -o $@ $^ -lm $(CL_GLX_libs) @@ -208,7 +216,7 @@ clean: -include $(COM_dependencies) -include $(SV_dependencies) -include $(CL_dependencies) --include $(CL_GL_dependencies) +#-include $(CL_GL_dependencies) -include $(CL_SVGA_dependencies) -include $(CL_X11_dependencies) -include $(CL_GLX_dependencies) diff --git a/source/gl_part.c b/source/gl_part.c new file mode 100644 index 0000000..de1a181 --- /dev/null +++ b/source/gl_part.c @@ -0,0 +1,606 @@ +/* + r_part.c + + (description) + + Copyright (C) 1996-1997 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +#include "quakedef.h" +#include "glquake.h" + +#define MAX_PARTICLES 2048 // default max # of particles at one + // time +#define ABSOLUTE_MIN_PARTICLES 512 // no fewer than this no matter what's + // on the command line + +int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61}; +int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66}; +int ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3}; + +particle_t *active_particles, *free_particles; + +particle_t *particles; +int r_numparticles; + +vec3_t r_pright, r_pup, r_ppn; + + +/* +=============== +R_InitParticles +=============== +*/ +void R_InitParticles (void) +{ + int i; + + i = COM_CheckParm ("-particles"); + + if (i) + { + r_numparticles = (int)(Q_atoi(com_argv[i+1])); + if (r_numparticles < ABSOLUTE_MIN_PARTICLES) + r_numparticles = ABSOLUTE_MIN_PARTICLES; + } + else + { + r_numparticles = MAX_PARTICLES; + } + + particles = (particle_t *) + Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles"); +} + + +/* +=============== +R_ClearParticles +=============== +*/ +void R_ClearParticles (void) +{ + int i; + + free_particles = &particles[0]; + active_particles = NULL; + + for (i=0 ;inext; + p->next = active_particles; + active_particles = p; + + p->die = 99999; + p->color = (-c)&15; + p->type = pt_static; + VectorCopy (vec3_origin, p->vel); + VectorCopy (org, p->org); + } + + fclose (f); + Con_Printf ("%i points read\n", c); +} + +/* +=============== +R_ParticleExplosion + +=============== +*/ +void R_ParticleExplosion (vec3_t org) +{ + int i, j; + particle_t *p; + + for (i=0 ; i<1024 ; i++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 5; + p->color = ramp1[0]; + p->ramp = rand()&3; + if (i & 1) + { + p->type = pt_explode; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + else + { + p->type = pt_explode2; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + } +} + +/* +=============== +R_BlobExplosion + +=============== +*/ +void R_BlobExplosion (vec3_t org) +{ + int i, j; + particle_t *p; + + for (i=0 ; i<1024 ; i++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 1 + (rand()&8)*0.05; + + if (i & 1) + { + p->type = pt_blob; + p->color = 66 + rand()%6; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + else + { + p->type = pt_blob2; + p->color = 150 + rand()%6; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + ((rand()%32)-16); + p->vel[j] = (rand()%512)-256; + } + } + } +} + +/* +=============== +R_RunParticleEffect + +=============== +*/ +void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count) +{ + int i, j; + particle_t *p; + int scale; + + if (count > 130) + scale = 3; + else if (count > 20) + scale = 2; + else + scale = 1; + + for (i=0 ; inext; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 0.1*(rand()%5); + p->color = (color&~7) + (rand()&7); + p->type = pt_grav; + for (j=0 ; j<3 ; j++) + { + p->org[j] = org[j] + scale*((rand()&15)-8); + p->vel[j] = dir[j]*15;// + (rand()%300)-150; + } + } +} + + +/* +=============== +R_LavaSplash + +=============== +*/ +void R_LavaSplash (vec3_t org) +{ + int i, j, k; + particle_t *p; + float vel; + vec3_t dir; + + for (i=-16 ; i<16 ; i++) + for (j=-16 ; j<16 ; j++) + for (k=0 ; k<1 ; k++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 2 + (rand()&31) * 0.02; + p->color = 224 + (rand()&7); + p->type = pt_grav; + + dir[0] = j*8 + (rand()&7); + dir[1] = i*8 + (rand()&7); + dir[2] = 256; + + p->org[0] = org[0] + dir[0]; + p->org[1] = org[1] + dir[1]; + p->org[2] = org[2] + (rand()&63); + + VectorNormalize (dir); + vel = 50 + (rand()&63); + VectorScale (dir, vel, p->vel); + } +} + +/* +=============== +R_TeleportSplash + +=============== +*/ +void R_TeleportSplash (vec3_t org) +{ + int i, j, k; + particle_t *p; + float vel; + vec3_t dir; + + for (i=-16 ; i<16 ; i+=4) + for (j=-16 ; j<16 ; j+=4) + for (k=-24 ; k<32 ; k+=4) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 0.2 + (rand()&7) * 0.02; + p->color = 7 + (rand()&7); + p->type = pt_grav; + + dir[0] = j*8; + dir[1] = i*8; + dir[2] = k*8; + + p->org[0] = org[0] + i + (rand()&3); + p->org[1] = org[1] + j + (rand()&3); + p->org[2] = org[2] + k + (rand()&3); + + VectorNormalize (dir); + vel = 50 + (rand()&63); + VectorScale (dir, vel, p->vel); + } +} + +void R_RocketTrail (vec3_t start, vec3_t end, int type) +{ + vec3_t vec; + float len; + int j; + particle_t *p; + + VectorSubtract (end, start, vec); + len = VectorNormalize (vec); + while (len > 0) + { + len -= 3; + + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + VectorCopy (vec3_origin, p->vel); + p->die = cl.time + 2; + + if (type == 4) + { // slight blood + p->type = pt_slowgrav; + p->color = 67 + (rand()&3); + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()%6)-3); + len -= 3; + } + else if (type == 2) + { // blood + p->type = pt_slowgrav; + p->color = 67 + (rand()&3); + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()%6)-3); + } + else if (type == 6) + { // voor trail + p->color = 9*16 + 8 + (rand()&3); + p->type = pt_static; + p->die = cl.time + 0.3; + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()&15)-8); + } + else if (type == 1) + { // smoke smoke + p->ramp = (rand()&3) + 2; + p->color = ramp3[(int)p->ramp]; + p->type = pt_fire; + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()%6)-3); + } + else if (type == 0) + { // rocket trail + p->ramp = (rand()&3); + p->color = ramp3[(int)p->ramp]; + p->type = pt_fire; + for (j=0 ; j<3 ; j++) + p->org[j] = start[j] + ((rand()%6)-3); + } + else if (type == 3 || type == 5) + { // tracer + static int tracercount; + + p->die = cl.time + 0.5; + p->type = pt_static; + if (type == 3) + p->color = 52 + ((tracercount&4)<<1); + else + p->color = 230 + ((tracercount&4)<<1); + + tracercount++; + + VectorCopy (start, p->org); + if (tracercount & 1) + { + p->vel[0] = 30*vec[1]; + p->vel[1] = 30*-vec[0]; + } + else + { + p->vel[0] = 30*-vec[1]; + p->vel[1] = 30*vec[0]; + } + + } + + + VectorAdd (start, vec, start); + } +} + + +/* +=============== +R_DrawParticles +=============== +*/ +void R_DrawParticles (void) +{ + particle_t *p, *kill; + float grav; + int i; + float time2, time3; + float time1; + float dvel; + float frametime; + unsigned char *at; + unsigned char theAlpha; + vec3_t up, right; + float scale; + qboolean alphaTestEnabled; + + GL_Bind(particletexture); + alphaTestEnabled = glIsEnabled(GL_ALPHA_TEST); + + if (alphaTestEnabled) + glDisable(GL_ALPHA_TEST); + glEnable (GL_BLEND); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glBegin (GL_TRIANGLES); + + VectorScale (vup, 1.5, up); + VectorScale (vright, 1.5, right); + + frametime = host_frametime; + time3 = frametime * 15; + time2 = frametime * 10; // 15; + time1 = frametime * 5; + grav = frametime * 800 * 0.05; + dvel = 4*frametime; + + for ( ;; ) + { + kill = active_particles; + if (kill && kill->die < cl.time) + { + active_particles = kill->next; + kill->next = free_particles; + free_particles = kill; + continue; + } + break; + } + + for (p=active_particles ; p ; p=p->next) + { + for ( ;; ) + { + kill = p->next; + if (kill && kill->die < cl.time) + { + p->next = kill->next; + kill->next = free_particles; + free_particles = kill; + continue; + } + break; + } + + // hack a scale up to keep particles from disapearing + scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] + + (p->org[2] - r_origin[2])*vpn[2]; + if (scale < 20) + scale = 1; + else + scale = 1 + scale * 0.004; + at = (byte *)&d_8to24table[(int)p->color]; + if (p->type==pt_fire) + theAlpha = 255*(6-p->ramp)/6; +// theAlpha = 192; +// else if (p->type==pt_explode || p->type==pt_explode2) +// theAlpha = 255*(8-p->ramp)/8; + else + theAlpha = 255; + glColor4ub (*at, *(at+1), *(at+2), theAlpha); +// glColor3ubv (at); +// glColor3ubv ((byte *)&d_8to24table[(int)p->color]); + glTexCoord2f (0,0); + glVertex3fv (p->org); + glTexCoord2f (1,0); + glVertex3f (p->org[0] + up[0]*scale, p->org[1] + up[1]*scale, p->org[2] + up[2]*scale); + glTexCoord2f (0,1); + glVertex3f (p->org[0] + right[0]*scale, p->org[1] + right[1]*scale, p->org[2] + right[2]*scale); + + p->org[0] += p->vel[0]*frametime; + p->org[1] += p->vel[1]*frametime; + p->org[2] += p->vel[2]*frametime; + + switch (p->type) + { + case pt_static: + break; + case pt_fire: + p->ramp += time1; + if (p->ramp >= 6) + p->die = -1; + else + p->color = ramp3[(int)p->ramp]; + p->vel[2] += grav; + break; + + case pt_explode: + p->ramp += time2; + if (p->ramp >=8) + p->die = -1; + else + p->color = ramp1[(int)p->ramp]; + for (i=0 ; i<3 ; i++) + p->vel[i] += p->vel[i]*dvel; + p->vel[2] -= grav; + break; + + case pt_explode2: + p->ramp += time3; + if (p->ramp >=8) + p->die = -1; + else + p->color = ramp2[(int)p->ramp]; + for (i=0 ; i<3 ; i++) + p->vel[i] -= p->vel[i]*frametime; + p->vel[2] -= grav; + break; + + case pt_blob: + for (i=0 ; i<3 ; i++) + p->vel[i] += p->vel[i]*dvel; + p->vel[2] -= grav; + break; + + case pt_blob2: + for (i=0 ; i<2 ; i++) + p->vel[i] -= p->vel[i]*dvel; + p->vel[2] -= grav; + break; + + case pt_slowgrav: + case pt_grav: + p->vel[2] -= grav; + break; + } + } + + glEnd (); + glDisable (GL_BLEND); + if (alphaTestEnabled) + glEnable(GL_ALPHA_TEST); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); +} + diff --git a/source/view.c b/source/gl_view.c similarity index 92% rename from source/view.c rename to source/gl_view.c index 96a5caa..eff44aa 100644 --- a/source/view.c +++ b/source/gl_view.c @@ -67,9 +67,7 @@ cvar_t crosshaircolor = {"crosshaircolor", "79", true}; cvar_t cl_crossx = {"cl_crossx", "0", true}; cvar_t cl_crossy = {"cl_crossy", "0", true}; -#ifdef GLQUAKE cvar_t gl_cshiftpercent = {"gl_cshiftpercent", "100", false}; -#endif cvar_t v_contentblend = {"v_contentblend", "1", false}; @@ -275,10 +273,8 @@ cvar_t v_gamma = {"gamma", "1", true}; byte gammatable[256]; // palette is sent through this -#ifdef GLQUAKE byte ramps[3][256]; float v_blend[4]; // rgba 0.0 - 1.0 -#endif // GLQUAKE void BuildGammaTable (float g) { @@ -496,7 +492,6 @@ void V_CalcPowerupCshift (void) V_CalcBlend ============= */ -#ifdef GLQUAKE void V_CalcBlend (void) { float r, g, b, a, a2; @@ -534,14 +529,12 @@ void V_CalcBlend (void) if (v_blend[3] < 0) v_blend[3] = 0; } -#endif /* ============= V_UpdatePalette ============= */ -#ifdef GLQUAKE void V_UpdatePalette (void) { int i, j; @@ -630,81 +623,7 @@ void V_UpdatePalette (void) VID_ShiftPalette (pal); } -#else // !GLQUAKE -/* -============= -V_UpdatePalette -============= -*/ -void V_UpdatePalette (void) -{ - int i, j; - qboolean new; - byte *basepal, *newpal; - byte pal[768]; - int r,g,b; - qboolean force; - V_CalcPowerupCshift (); - - new = false; - - for (i=0 ; i>8; - g += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[1]-g))>>8; - b += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[2]-b))>>8; - } - - newpal[0] = gammatable[r]; - newpal[1] = gammatable[g]; - newpal[2] = gammatable[b]; - newpal += 3; - } - - VID_ShiftPalette (pal); -} - -#endif // !GLQUAKE /* ============================================================================== @@ -1022,10 +941,8 @@ cl.simangles[ROLL] = 0; // FIXME @@@ R_PushDlights (); R_RenderView (); -#ifndef GLQUAKE if (crosshair.value) Draw_Crosshair(); -#endif } @@ -1059,9 +976,7 @@ void V_Init (void) Cvar_RegisterVariable (&crosshair); Cvar_RegisterVariable (&cl_crossx); Cvar_RegisterVariable (&cl_crossy); -#ifdef GLQUAKE Cvar_RegisterVariable (&gl_cshiftpercent); -#endif Cvar_RegisterVariable (&cl_rollspeed); Cvar_RegisterVariable (&cl_rollangle); diff --git a/source/r_part.c b/source/r_part.c index bcc90b6..6c1c83c 100644 --- a/source/r_part.c +++ b/source/r_part.c @@ -461,31 +461,11 @@ void R_DrawParticles (void) float time1; float dvel; float frametime; -#ifdef GLQUAKE - unsigned char *at; - unsigned char theAlpha; - vec3_t up, right; - float scale; - qboolean alphaTestEnabled; - - GL_Bind(particletexture); - alphaTestEnabled = glIsEnabled(GL_ALPHA_TEST); - - if (alphaTestEnabled) - glDisable(GL_ALPHA_TEST); - glEnable (GL_BLEND); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glBegin (GL_TRIANGLES); - - VectorScale (vup, 1.5, up); - VectorScale (vright, 1.5, right); -#else D_StartParticles (); VectorScale (vright, xscaleshrink, r_pright); VectorScale (vup, yscaleshrink, r_pup); VectorCopy (vpn, r_ppn); -#endif frametime = host_frametime; time3 = frametime * 15; @@ -522,35 +502,7 @@ void R_DrawParticles (void) break; } -#ifdef GLQUAKE - // hack a scale up to keep particles from disapearing - scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] - + (p->org[2] - r_origin[2])*vpn[2]; - if (scale < 20) - scale = 1; - else - scale = 1 + scale * 0.004; - at = (byte *)&d_8to24table[(int)p->color]; - if (p->type==pt_fire) - theAlpha = 255*(6-p->ramp)/6; -// theAlpha = 192; -// else if (p->type==pt_explode || p->type==pt_explode2) -// theAlpha = 255*(8-p->ramp)/8; - else - theAlpha = 255; - glColor4ub (*at, *(at+1), *(at+2), theAlpha); -// glColor3ubv (at); -// glColor3ubv ((byte *)&d_8to24table[(int)p->color]); - glTexCoord2f (0,0); - glVertex3fv (p->org); - glTexCoord2f (1,0); - glVertex3f (p->org[0] + up[0]*scale, p->org[1] + up[1]*scale, p->org[2] + up[2]*scale); - glTexCoord2f (0,1); - glVertex3f (p->org[0] + right[0]*scale, p->org[1] + right[1]*scale, p->org[2] + right[2]*scale); - -#else D_DrawParticle (p); -#endif p->org[0] += p->vel[0]*frametime; p->org[1] += p->vel[1]*frametime; @@ -610,14 +562,6 @@ void R_DrawParticles (void) } } -#ifdef GLQUAKE - glEnd (); - glDisable (GL_BLEND); - if (alphaTestEnabled) - glEnable(GL_ALPHA_TEST); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); -#else D_EndParticles (); -#endif } diff --git a/source/r_view.c b/source/r_view.c new file mode 100644 index 0000000..636ce54 --- /dev/null +++ b/source/r_view.c @@ -0,0 +1,921 @@ +/* + view.c + + (description) + + Copyright (C) 1996-1997 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: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ +// view.c -- player eye positioning + +#include "quakedef.h" +#include "r_local.h" + +/* + +The view is allowed to move slightly from it's true position for bobbing, +but if it exceeds 8 pixels linear distance (spherical, not box), the list of +entities sent from the server may not include everything in the pvs, especially +when crossing a water boudnary. + +*/ + +cvar_t lcd_x = {"lcd_x", "0"}; // FIXME: make this work sometime... + +cvar_t cl_rollspeed = {"cl_rollspeed", "200"}; +cvar_t cl_rollangle = {"cl_rollangle", "2.0"}; + +cvar_t cl_bob = {"cl_bob","0.02", false}; +cvar_t cl_bobcycle = {"cl_bobcycle","0.6", false}; +cvar_t cl_bobup = {"cl_bobup","0.5", false}; + +cvar_t v_kicktime = {"v_kicktime", "0.5", false}; +cvar_t v_kickroll = {"v_kickroll", "0.6", false}; +cvar_t v_kickpitch = {"v_kickpitch", "0.6", false}; + +cvar_t v_iyaw_cycle = {"v_iyaw_cycle", "2", false}; +cvar_t v_iroll_cycle = {"v_iroll_cycle", "0.5", false}; +cvar_t v_ipitch_cycle = {"v_ipitch_cycle", "1", false}; +cvar_t v_iyaw_level = {"v_iyaw_level", "0.3", false}; +cvar_t v_iroll_level = {"v_iroll_level", "0.1", false}; +cvar_t v_ipitch_level = {"v_ipitch_level", "0.3", false}; + +cvar_t v_idlescale = {"v_idlescale", "0", false}; + +cvar_t crosshair = {"crosshair", "0", true}; +cvar_t crosshaircolor = {"crosshaircolor", "79", true}; + +cvar_t cl_crossx = {"cl_crossx", "0", true}; +cvar_t cl_crossy = {"cl_crossy", "0", true}; + +cvar_t v_contentblend = {"v_contentblend", "1", false}; + +float v_dmg_time, v_dmg_roll, v_dmg_pitch; + +extern int in_forward, in_forward2, in_back; + +frame_t *view_frame; +player_state_t *view_message; + +/* +=============== +V_CalcRoll + +=============== +*/ +float V_CalcRoll (vec3_t angles, vec3_t velocity) +{ + vec3_t forward, right, up; + float sign; + float side; + float value; + + AngleVectors (angles, forward, right, up); + side = DotProduct (velocity, right); + sign = side < 0 ? -1 : 1; + side = fabs(side); + + value = cl_rollangle.value; + + if (side < cl_rollspeed.value) + side = side * value / cl_rollspeed.value; + else + side = value; + + return side*sign; + +} + + +/* +=============== +V_CalcBob + +=============== +*/ +float V_CalcBob (void) +{ + static double bobtime; + static float bob; + float cycle; + + if (cl.spectator) + return 0; + + if (onground == -1) + return bob; // just use old value + + bobtime += host_frametime; + cycle = bobtime - (int)(bobtime/cl_bobcycle.value)*cl_bobcycle.value; + cycle /= cl_bobcycle.value; + if (cycle < cl_bobup.value) + cycle = M_PI * cycle / cl_bobup.value; + else + cycle = M_PI + M_PI*(cycle-cl_bobup.value)/(1.0 - cl_bobup.value); + +// bob is proportional to simulated velocity in the xy plane +// (don't count Z, or jumping messes it up) + + bob = sqrt(cl.simvel[0]*cl.simvel[0] + cl.simvel[1]*cl.simvel[1]) * cl_bob.value; + bob = bob*0.3 + bob*0.7*sin(cycle); + if (bob > 4) + bob = 4; + else if (bob < -7) + bob = -7; + return bob; + +} + + +//============================================================================= + + +cvar_t v_centermove = {"v_centermove", "0.15", false}; +cvar_t v_centerspeed = {"v_centerspeed","500"}; + + +void V_StartPitchDrift (void) +{ +#if 1 + if (cl.laststop == cl.time) + { + return; // something else is keeping it from drifting + } +#endif + if (cl.nodrift || !cl.pitchvel) + { + cl.pitchvel = v_centerspeed.value; + cl.nodrift = false; + cl.driftmove = 0; + } +} + +void V_StopPitchDrift (void) +{ + cl.laststop = cl.time; + cl.nodrift = true; + cl.pitchvel = 0; +} + +/* +=============== +V_DriftPitch + +Moves the client pitch angle towards cl.idealpitch sent by the server. + +If the user is adjusting pitch manually, either with lookup/lookdown, +mlook and mouse, or klook and keyboard, pitch drifting is constantly stopped. + +Drifting is enabled when the center view key is hit, mlook is released and +lookspring is non 0, or when +=============== +*/ +void V_DriftPitch (void) +{ + float delta, move; + + if (view_message->onground == -1 || cls.demoplayback ) + { + cl.driftmove = 0; + cl.pitchvel = 0; + return; + } + +// don't count small mouse motion + if (cl.nodrift) + { + if ( fabs(cl.frames[(cls.netchan.outgoing_sequence-1)&UPDATE_MASK].cmd.forwardmove) < 200) + cl.driftmove = 0; + else + cl.driftmove += host_frametime; + + if ( cl.driftmove > v_centermove.value) + { + V_StartPitchDrift (); + } + return; + } + + delta = 0 - cl.viewangles[PITCH]; + + if (!delta) + { + cl.pitchvel = 0; + return; + } + + move = host_frametime * cl.pitchvel; + cl.pitchvel += host_frametime * v_centerspeed.value; + +//Con_Printf ("move: %f (%f)\n", move, host_frametime); + + if (delta > 0) + { + if (move > delta) + { + cl.pitchvel = 0; + move = delta; + } + cl.viewangles[PITCH] += move; + } + else if (delta < 0) + { + if (move > -delta) + { + cl.pitchvel = 0; + move = -delta; + } + cl.viewangles[PITCH] -= move; + } +} + + + + + +/* +============================================================================== + + PALETTE FLASHES + +============================================================================== +*/ + + +cshift_t cshift_empty = { {130,80,50}, 0 }; +cshift_t cshift_water = { {130,80,50}, 128 }; +cshift_t cshift_slime = { {0,25,5}, 150 }; +cshift_t cshift_lava = { {255,80,0}, 150 }; + +cvar_t v_gamma = {"gamma", "1", true}; + +byte gammatable[256]; // palette is sent through this + + +void BuildGammaTable (float g) +{ + int i, inf; + + if (g == 1.0) + { + for (i=0 ; i<256 ; i++) + gammatable[i] = i; + return; + } + + for (i=0 ; i<256 ; i++) + { + inf = 255 * pow ( (i+0.5)/255.5 , g ) + 0.5; + if (inf < 0) + inf = 0; + if (inf > 255) + inf = 255; + gammatable[i] = inf; + } +} + +/* +================= +V_CheckGamma +================= +*/ +qboolean V_CheckGamma (void) +{ + static float oldgammavalue; + + if (v_gamma.value == oldgammavalue) + return false; + oldgammavalue = v_gamma.value; + + BuildGammaTable (v_gamma.value); + vid.recalc_refdef = 1; // force a surface cache flush + + return true; +} + + + +/* +=============== +V_ParseDamage +=============== +*/ +void V_ParseDamage (void) +{ + int armor, blood; + vec3_t from; + int i; + vec3_t forward, right, up; + float side; + float count; + + armor = MSG_ReadByte (); + blood = MSG_ReadByte (); + for (i=0 ; i<3 ; i++) + from[i] = MSG_ReadCoord (); + + count = blood*0.5 + armor*0.5; + if (count < 10) + count = 10; + + cl.faceanimtime = cl.time + 0.2; // but sbar face into pain frame + + cl.cshifts[CSHIFT_DAMAGE].percent += 3*count; + if (cl.cshifts[CSHIFT_DAMAGE].percent < 0) + cl.cshifts[CSHIFT_DAMAGE].percent = 0; + if (cl.cshifts[CSHIFT_DAMAGE].percent > 150) + cl.cshifts[CSHIFT_DAMAGE].percent = 150; + + if (armor > blood) + { + cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 200; + cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 100; + cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 100; + } + else if (armor) + { + cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 220; + cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 50; + cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 50; + } + else + { + cl.cshifts[CSHIFT_DAMAGE].destcolor[0] = 255; + cl.cshifts[CSHIFT_DAMAGE].destcolor[1] = 0; + cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0; + } + +// +// calculate view angle kicks +// + VectorSubtract (from, cl.simorg, from); + VectorNormalize (from); + + AngleVectors (cl.simangles, forward, right, up); + + side = DotProduct (from, right); + v_dmg_roll = count*side*v_kickroll.value; + + side = DotProduct (from, forward); + v_dmg_pitch = count*side*v_kickpitch.value; + + v_dmg_time = v_kicktime.value; +} + + +/* +================== +V_cshift_f +================== +*/ +void V_cshift_f (void) +{ + cshift_empty.destcolor[0] = atoi(Cmd_Argv(1)); + cshift_empty.destcolor[1] = atoi(Cmd_Argv(2)); + cshift_empty.destcolor[2] = atoi(Cmd_Argv(3)); + cshift_empty.percent = atoi(Cmd_Argv(4)); +} + + +/* +================== +V_BonusFlash_f + +When you run over an item, the server sends this command +================== +*/ +void V_BonusFlash_f (void) +{ + cl.cshifts[CSHIFT_BONUS].destcolor[0] = 215; + cl.cshifts[CSHIFT_BONUS].destcolor[1] = 186; + cl.cshifts[CSHIFT_BONUS].destcolor[2] = 69; + cl.cshifts[CSHIFT_BONUS].percent = 50; +} + +/* +============= +V_SetContentsColor + +Underwater, lava, etc each has a color shift +============= +*/ +void V_SetContentsColor (int contents) +{ + if (!v_contentblend.value) { + cl.cshifts[CSHIFT_CONTENTS] = cshift_empty; + return; + } + + switch (contents) + { + case CONTENTS_EMPTY: + cl.cshifts[CSHIFT_CONTENTS] = cshift_empty; + break; + case CONTENTS_LAVA: + cl.cshifts[CSHIFT_CONTENTS] = cshift_lava; + break; + case CONTENTS_SOLID: + case CONTENTS_SLIME: + cl.cshifts[CSHIFT_CONTENTS] = cshift_slime; + break; + default: + cl.cshifts[CSHIFT_CONTENTS] = cshift_water; + } +} + +/* +============= +V_CalcPowerupCshift +============= +*/ +void V_CalcPowerupCshift (void) +{ + if (cl.stats[STAT_ITEMS] & IT_QUAD) + { + cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; + cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 0; + cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 255; + cl.cshifts[CSHIFT_POWERUP].percent = 30; + } + else if (cl.stats[STAT_ITEMS] & IT_SUIT) + { + cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 0; + cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; + cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; + cl.cshifts[CSHIFT_POWERUP].percent = 20; + } + else if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) + { + cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 100; + cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 100; + cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 100; + cl.cshifts[CSHIFT_POWERUP].percent = 100; + } + else if (cl.stats[STAT_ITEMS] & IT_INVULNERABILITY) + { + cl.cshifts[CSHIFT_POWERUP].destcolor[0] = 255; + cl.cshifts[CSHIFT_POWERUP].destcolor[1] = 255; + cl.cshifts[CSHIFT_POWERUP].destcolor[2] = 0; + cl.cshifts[CSHIFT_POWERUP].percent = 30; + } + else + cl.cshifts[CSHIFT_POWERUP].percent = 0; +} + + +/* +============= +V_UpdatePalette +============= +*/ +void V_UpdatePalette (void) +{ + int i, j; + qboolean new; + byte *basepal, *newpal; + byte pal[768]; + int r,g,b; + qboolean force; + + V_CalcPowerupCshift (); + + new = false; + + for (i=0 ; i>8; + g += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[1]-g))>>8; + b += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[2]-b))>>8; + } + + newpal[0] = gammatable[r]; + newpal[1] = gammatable[g]; + newpal[2] = gammatable[b]; + newpal += 3; + } + + VID_ShiftPalette (pal); +} + + +/* +============================================================================== + + VIEW RENDERING + +============================================================================== +*/ + +float angledelta (float a) +{ + a = anglemod(a); + if (a > 180) + a -= 360; + return a; +} + +/* +================== +CalcGunAngle +================== +*/ +void CalcGunAngle (void) +{ + float yaw, pitch, move; + static float oldyaw = 0; + static float oldpitch = 0; + + yaw = r_refdef.viewangles[YAW]; + pitch = -r_refdef.viewangles[PITCH]; + + yaw = angledelta(yaw - r_refdef.viewangles[YAW]) * 0.4; + if (yaw > 10) + yaw = 10; + if (yaw < -10) + yaw = -10; + pitch = angledelta(-pitch - r_refdef.viewangles[PITCH]) * 0.4; + if (pitch > 10) + pitch = 10; + if (pitch < -10) + pitch = -10; + move = host_frametime*20; + if (yaw > oldyaw) + { + if (oldyaw + move < yaw) + yaw = oldyaw + move; + } + else + { + if (oldyaw - move > yaw) + yaw = oldyaw - move; + } + + if (pitch > oldpitch) + { + if (oldpitch + move < pitch) + pitch = oldpitch + move; + } + else + { + if (oldpitch - move > pitch) + pitch = oldpitch - move; + } + + oldyaw = yaw; + oldpitch = pitch; + + cl.viewent.angles[YAW] = r_refdef.viewangles[YAW] + yaw; + cl.viewent.angles[PITCH] = - (r_refdef.viewangles[PITCH] + pitch); +} + +/* +============== +V_BoundOffsets +============== +*/ +void V_BoundOffsets (void) +{ +// absolutely bound refresh reletive to entity clipping hull +// so the view can never be inside a solid wall + + if (r_refdef.vieworg[0] < cl.simorg[0] - 14) + r_refdef.vieworg[0] = cl.simorg[0] - 14; + else if (r_refdef.vieworg[0] > cl.simorg[0] + 14) + r_refdef.vieworg[0] = cl.simorg[0] + 14; + if (r_refdef.vieworg[1] < cl.simorg[1] - 14) + r_refdef.vieworg[1] = cl.simorg[1] - 14; + else if (r_refdef.vieworg[1] > cl.simorg[1] + 14) + r_refdef.vieworg[1] = cl.simorg[1] + 14; + if (r_refdef.vieworg[2] < cl.simorg[2] - 22) + r_refdef.vieworg[2] = cl.simorg[2] - 22; + else if (r_refdef.vieworg[2] > cl.simorg[2] + 30) + r_refdef.vieworg[2] = cl.simorg[2] + 30; +} + +/* +============== +V_AddIdle + +Idle swaying +============== +*/ +void V_AddIdle (void) +{ + r_refdef.viewangles[ROLL] += v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value; + r_refdef.viewangles[PITCH] += v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value; + r_refdef.viewangles[YAW] += v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value; + + cl.viewent.angles[ROLL] -= v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value; + cl.viewent.angles[PITCH] -= v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value; + cl.viewent.angles[YAW] -= v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value; +} + + +/* +============== +V_CalcViewRoll + +Roll is induced by movement and damage +============== +*/ +void V_CalcViewRoll (void) +{ + float side; + + side = V_CalcRoll (cl.simangles, cl.simvel); + r_refdef.viewangles[ROLL] += side; + + if (v_dmg_time > 0) + { + r_refdef.viewangles[ROLL] += v_dmg_time/v_kicktime.value*v_dmg_roll; + r_refdef.viewangles[PITCH] += v_dmg_time/v_kicktime.value*v_dmg_pitch; + v_dmg_time -= host_frametime; + } + +} + + +/* +================== +V_CalcIntermissionRefdef + +================== +*/ +void V_CalcIntermissionRefdef (void) +{ + entity_t *view; + float old; + +// view is the weapon model + view = &cl.viewent; + + VectorCopy (cl.simorg, r_refdef.vieworg); + VectorCopy (cl.simangles, r_refdef.viewangles); + view->model = NULL; + +// allways idle in intermission + old = v_idlescale.value; + v_idlescale.value = 1; + V_AddIdle (); + v_idlescale.value = old; +} + +/* +================== +V_CalcRefdef + +================== +*/ +void V_CalcRefdef (void) +{ + entity_t *view; + int i; + vec3_t forward, right, up; + float bob; + static float oldz = 0; + + V_DriftPitch (); + +// view is the weapon model (only visible from inside body) + view = &cl.viewent; + + bob = V_CalcBob (); + +// refresh position from simulated origin + VectorCopy (cl.simorg, r_refdef.vieworg); + + r_refdef.vieworg[2] += bob; + +// 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 + r_refdef.vieworg[0] += 1.0/16; + r_refdef.vieworg[1] += 1.0/16; + r_refdef.vieworg[2] += 1.0/16; + + VectorCopy (cl.simangles, r_refdef.viewangles); + V_CalcViewRoll (); + V_AddIdle (); + + if (view_message->flags & PF_GIB) + r_refdef.vieworg[2] += 8; // gib view height + else if (view_message->flags & PF_DEAD) + r_refdef.vieworg[2] -= 16; // corpse view height + else + r_refdef.vieworg[2] += 22; // view height + + if (view_message->flags & PF_DEAD) // PF_GIB will also set PF_DEAD + r_refdef.viewangles[ROLL] = 80; // dead view angle + + +// offsets + AngleVectors (cl.simangles, forward, right, up); + +// set up gun position + VectorCopy (cl.simangles, view->angles); + + CalcGunAngle (); + + VectorCopy (cl.simorg, view->origin); + view->origin[2] += 22; + + for (i=0 ; i<3 ; i++) + { + view->origin[i] += forward[i]*bob*0.4; +// view->origin[i] += right[i]*bob*0.4; +// view->origin[i] += up[i]*bob*0.8; + } + view->origin[2] += bob; + +// fudge position around to keep amount of weapon visible +// roughly equal with different FOV + if (scr_viewsize.value == 110) + view->origin[2] += 1; + else if (scr_viewsize.value == 100) + view->origin[2] += 2; + else if (scr_viewsize.value == 90) + view->origin[2] += 1; + else if (scr_viewsize.value == 80) + view->origin[2] += 0.5; + + if (view_message->flags & (PF_GIB|PF_DEAD) ) + view->model = NULL; + else + view->model = cl.model_precache[cl.stats[STAT_WEAPON]]; + view->frame = view_message->weaponframe; + view->colormap = vid.colormap; + +// set up the refresh position + r_refdef.viewangles[PITCH] += cl.punchangle; + +// smooth out stair step ups + if ( (view_message->onground != -1) && (cl.simorg[2] - oldz > 0) ) + { + float steptime; + + steptime = host_frametime; + + oldz += steptime * 80; + if (oldz > cl.simorg[2]) + oldz = cl.simorg[2]; + if (cl.simorg[2] - oldz > 12) + oldz = cl.simorg[2] - 12; + r_refdef.vieworg[2] += oldz - cl.simorg[2]; + view->origin[2] += oldz - cl.simorg[2]; + } + else + oldz = cl.simorg[2]; +} + +/* +============= +DropPunchAngle +============= +*/ +void DropPunchAngle (void) +{ + cl.punchangle -= 10*host_frametime; + if (cl.punchangle < 0) + cl.punchangle = 0; +} + +/* +================== +V_RenderView + +The player's clipping box goes from (-16 -16 -24) to (16 16 32) from +the entity origin, so any view position inside that will be valid +================== +*/ +extern vrect_t scr_vrect; + +void V_RenderView (void) +{ +// if (cl.simangles[ROLL]) +// Sys_Error ("cl.simangles[ROLL]"); // DEBUG +cl.simangles[ROLL] = 0; // FIXME @@@ + + if (cls.state != ca_active) + return; + + view_frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK]; + view_message = &view_frame->playerstate[cl.playernum]; + + DropPunchAngle (); + if (cl.intermission) + { // intermission / finale rendering + V_CalcIntermissionRefdef (); + } + else + { + V_CalcRefdef (); + } + + R_PushDlights (); + R_RenderView (); +} + +//============================================================================ + +/* +============= +V_Init +============= +*/ +void V_Init (void) +{ + Cmd_AddCommand ("v_cshift", V_cshift_f); + Cmd_AddCommand ("bf", V_BonusFlash_f); + Cmd_AddCommand ("centerview", V_StartPitchDrift); + + Cvar_RegisterVariable (&v_centermove); + Cvar_RegisterVariable (&v_centerspeed); + + Cvar_RegisterVariable (&v_iyaw_cycle); + Cvar_RegisterVariable (&v_iroll_cycle); + Cvar_RegisterVariable (&v_ipitch_cycle); + Cvar_RegisterVariable (&v_iyaw_level); + Cvar_RegisterVariable (&v_iroll_level); + Cvar_RegisterVariable (&v_ipitch_level); + + Cvar_RegisterVariable (&v_contentblend); + + Cvar_RegisterVariable (&v_idlescale); + Cvar_RegisterVariable (&crosshaircolor); + Cvar_RegisterVariable (&crosshair); + Cvar_RegisterVariable (&cl_crossx); + Cvar_RegisterVariable (&cl_crossy); + + Cvar_RegisterVariable (&cl_rollspeed); + Cvar_RegisterVariable (&cl_rollangle); + Cvar_RegisterVariable (&cl_bob); + Cvar_RegisterVariable (&cl_bobcycle); + Cvar_RegisterVariable (&cl_bobup); + + Cvar_RegisterVariable (&v_kicktime); + Cvar_RegisterVariable (&v_kickroll); + Cvar_RegisterVariable (&v_kickpitch); + + BuildGammaTable (1.0); // no gamma yet + Cvar_RegisterVariable (&v_gamma); +} + +