12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073 |
- /*
- 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 the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- // 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};
- #ifdef GLQUAKE
- cvar_t gl_cshiftpercent = {"gl_cshiftpercent", "100", false};
- #endif
- 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
- #ifdef GLQUAKE
- byte ramps[3][256];
- float v_blend[4]; // rgba 0.0 - 1.0
- #endif // GLQUAKE
- 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_CalcBlend
- =============
- */
- #ifdef GLQUAKE
- void V_CalcBlend (void)
- {
- float r, g, b, a, a2;
- int j;
- r = 0;
- g = 0;
- b = 0;
- a = 0;
- for (j=0 ; j<NUM_CSHIFTS ; j++)
- {
- if (!gl_cshiftpercent.value)
- continue;
- a2 = ((cl.cshifts[j].percent * gl_cshiftpercent.value) / 100.0) / 255.0;
- // a2 = (cl.cshifts[j].percent/2)/255.0;
- if (!a2)
- continue;
- a = a + a2*(1-a);
- //Con_Printf ("j:%i a:%f\n", j, a);
- a2 = a2/a;
- r = r*(1-a2) + cl.cshifts[j].destcolor[0]*a2;
- g = g*(1-a2) + cl.cshifts[j].destcolor[1]*a2;
- b = b*(1-a2) + cl.cshifts[j].destcolor[2]*a2;
- }
- v_blend[0] = r/255.0;
- v_blend[1] = g/255.0;
- v_blend[2] = b/255.0;
- v_blend[3] = a;
- if (v_blend[3] > 1)
- v_blend[3] = 1;
- if (v_blend[3] < 0)
- v_blend[3] = 0;
- }
- #endif
- /*
- =============
- V_UpdatePalette
- =============
- */
- #ifdef GLQUAKE
- void V_UpdatePalette (void)
- {
- int i, j;
- qboolean new;
- byte *basepal, *newpal;
- byte pal[768];
- float r,g,b,a;
- int ir, ig, ib;
- qboolean force;
- V_CalcPowerupCshift ();
-
- new = false;
-
- for (i=0 ; i<NUM_CSHIFTS ; i++)
- {
- if (cl.cshifts[i].percent != cl.prev_cshifts[i].percent)
- {
- new = true;
- cl.prev_cshifts[i].percent = cl.cshifts[i].percent;
- }
- for (j=0 ; j<3 ; j++)
- if (cl.cshifts[i].destcolor[j] != cl.prev_cshifts[i].destcolor[j])
- {
- new = true;
- cl.prev_cshifts[i].destcolor[j] = cl.cshifts[i].destcolor[j];
- }
- }
- // drop the damage value
- cl.cshifts[CSHIFT_DAMAGE].percent -= host_frametime*150;
- if (cl.cshifts[CSHIFT_DAMAGE].percent <= 0)
- cl.cshifts[CSHIFT_DAMAGE].percent = 0;
- // drop the bonus value
- cl.cshifts[CSHIFT_BONUS].percent -= host_frametime*100;
- if (cl.cshifts[CSHIFT_BONUS].percent <= 0)
- cl.cshifts[CSHIFT_BONUS].percent = 0;
- force = V_CheckGamma ();
- if (!new && !force)
- return;
- V_CalcBlend ();
- //Con_Printf("b: %4.2f %4.2f %4.2f %4.6f\n", v_blend[0], v_blend[1], v_blend[2], v_blend[3]);
- a = v_blend[3];
- r = 255*v_blend[0]*a;
- g = 255*v_blend[1]*a;
- b = 255*v_blend[2]*a;
- a = 1-a;
- for (i=0 ; i<256 ; i++)
- {
- ir = i*a + r;
- ig = i*a + g;
- ib = i*a + b;
- if (ir > 255)
- ir = 255;
- if (ig > 255)
- ig = 255;
- if (ib > 255)
- ib = 255;
- ramps[0][i] = gammatable[ir];
- ramps[1][i] = gammatable[ig];
- ramps[2][i] = gammatable[ib];
- }
- basepal = host_basepal;
- newpal = pal;
-
- for (i=0 ; i<256 ; i++)
- {
- ir = basepal[0];
- ig = basepal[1];
- ib = basepal[2];
- basepal += 3;
-
- newpal[0] = ramps[0][ir];
- newpal[1] = ramps[1][ig];
- newpal[2] = ramps[2][ib];
- newpal += 3;
- }
- 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<NUM_CSHIFTS ; i++)
- {
- if (cl.cshifts[i].percent != cl.prev_cshifts[i].percent)
- {
- new = true;
- cl.prev_cshifts[i].percent = cl.cshifts[i].percent;
- }
- for (j=0 ; j<3 ; j++)
- if (cl.cshifts[i].destcolor[j] != cl.prev_cshifts[i].destcolor[j])
- {
- new = true;
- cl.prev_cshifts[i].destcolor[j] = cl.cshifts[i].destcolor[j];
- }
- }
-
- // drop the damage value
- cl.cshifts[CSHIFT_DAMAGE].percent -= host_frametime*150;
- if (cl.cshifts[CSHIFT_DAMAGE].percent <= 0)
- cl.cshifts[CSHIFT_DAMAGE].percent = 0;
- // drop the bonus value
- cl.cshifts[CSHIFT_BONUS].percent -= host_frametime*100;
- if (cl.cshifts[CSHIFT_BONUS].percent <= 0)
- cl.cshifts[CSHIFT_BONUS].percent = 0;
- force = V_CheckGamma ();
- if (!new && !force)
- return;
-
- basepal = host_basepal;
- newpal = pal;
-
- for (i=0 ; i<256 ; i++)
- {
- r = basepal[0];
- g = basepal[1];
- b = basepal[2];
- basepal += 3;
-
- for (j=0 ; j<NUM_CSHIFTS ; j++)
- {
- r += (cl.cshifts[j].percent*(cl.cshifts[j].destcolor[0]-r))>>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
- /*
- ==============================================================================
-
- 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 ();
-
- #ifndef GLQUAKE
- if (crosshair.value)
- Draw_Crosshair();
- #endif
-
- }
- //============================================================================
- /*
- =============
- 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);
- #ifdef GLQUAKE
- Cvar_RegisterVariable (&gl_cshiftpercent);
- #endif
- 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);
- }
|