X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=view.c;h=94fe265d6490cac6a8b0c765cbaf8c00370dce02;hp=4839e64ef1357a55e054ad29fbc5a9108160c907;hb=b3895a134a65c7be9ccfe2db7cf7132d5934f316;hpb=127c0d85081316ab9299b9912a36b11c4c22e3f8 diff --git a/view.c b/view.c index 4839e64e..94fe265d 100644 --- a/view.c +++ b/view.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // view.c -- player eye positioning #include "quakedef.h" +#include "cl_collision.h" /* @@ -71,7 +72,7 @@ float V_CalcRoll (vec3_t angles, vec3_t velocity) float sign; float side; float value; - + AngleVectors (angles, NULL, right, NULL); side = DotProduct (velocity, right); sign = side < 0 ? -1 : 1; @@ -88,34 +89,6 @@ float V_CalcRoll (vec3_t angles, vec3_t velocity) } -static float V_CalcBob (void) -{ - double bob, cycle; - - // LordHavoc: easy case - if (cl_bob.value == 0) - return 0; - if (cl_bobcycle.value == 0) - return 0; - - // LordHavoc: FIXME: this code is *weird*, redesign it sometime - cycle = cl.time / cl_bobcycle.value; - cycle -= (int) cycle; - 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 velocity in the xy plane - // (don't count Z, or jumping messes it up) - - bob = sqrt(cl.velocity[0]*cl.velocity[0] + cl.velocity[1]*cl.velocity[1]) * cl_bob.value; - bob = bob*0.3 + bob*0.7*sin(cycle); - bob = bound(-7, bob, 4); - return bob; - -} - void V_StartPitchDrift (void) { if (cl.laststop == cl.time) @@ -149,7 +122,7 @@ Drifting is enabled when the center view key is hit, mlook is released and lookspring is non 0, or when =============== */ -static void V_DriftPitch (void) +void V_DriftPitch (void) { float delta, move; @@ -224,9 +197,12 @@ V_ParseDamage void V_ParseDamage (void) { int i, armor, blood; - vec3_t from, forward, right; + vec3_t from; + //vec3_t forward, right; + vec3_t localfrom; entity_t *ent; - float side, count; + //float side; + float count; armor = MSG_ReadByte (); blood = MSG_ReadByte (); @@ -264,23 +240,16 @@ void V_ParseDamage (void) cl.cshifts[CSHIFT_DAMAGE].destcolor[2] = 0; } -// -// calculate view angle kicks -// - ent = &cl_entities[cl.viewentity]; - - VectorSubtract (from, ent->render.origin, from); - VectorNormalize (from); - - AngleVectors (ent->render.angles, forward, right, NULL); - - 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; + // calculate view angle kicks + if (cl.viewentity >= 0 && cl.viewentity < MAX_EDICTS && cl_entities[cl.viewentity].state_current.active) + { + ent = &cl_entities[cl.viewentity]; + Matrix4x4_Transform(&ent->render.inversematrix, from, localfrom); + VectorNormalize(localfrom); + v_dmg_pitch = count * localfrom[0] * v_kickpitch.value; + v_dmg_roll = count * localfrom[1] * v_kickroll.value; + v_dmg_time = v_kicktime.value; + } } static cshift_t v_cshift; @@ -314,133 +283,6 @@ static void V_BonusFlash_f (void) cl.cshifts[CSHIFT_BONUS].percent = 50; } -/* -============= -V_UpdateBlends -============= -*/ -void V_UpdateBlends (void) -{ - float r, g, b, a, a2; - int j; - - if (cl.worldmodel == NULL) - { - cl.cshifts[CSHIFT_DAMAGE].percent = 0; - cl.cshifts[CSHIFT_BONUS].percent = 0; - cl.cshifts[CSHIFT_CONTENTS].percent = 0; - cl.cshifts[CSHIFT_POWERUP].percent = 0; - r_refdef.viewblend[0] = 0; - r_refdef.viewblend[1] = 0; - r_refdef.viewblend[2] = 0; - r_refdef.viewblend[3] = 0; - return; - } - - // drop the damage value - cl.cshifts[CSHIFT_DAMAGE].percent -= (cl.time - cl.oldtime)*150; - if (cl.cshifts[CSHIFT_DAMAGE].percent <= 0) - cl.cshifts[CSHIFT_DAMAGE].percent = 0; - - // drop the bonus value - cl.cshifts[CSHIFT_BONUS].percent -= (cl.time - cl.oldtime)*100; - if (cl.cshifts[CSHIFT_BONUS].percent <= 0) - cl.cshifts[CSHIFT_BONUS].percent = 0; - - // set contents color - switch (Mod_PointInLeaf (r_refdef.vieworg, cl.worldmodel)->contents) - { - case CONTENTS_EMPTY: - case CONTENTS_SOLID: - cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = v_cshift.destcolor[0]; - cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = v_cshift.destcolor[1]; - cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = v_cshift.destcolor[2]; - cl.cshifts[CSHIFT_CONTENTS].percent = v_cshift.percent; - break; - case CONTENTS_LAVA: - cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 255; - cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 80; - cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 0; - cl.cshifts[CSHIFT_CONTENTS].percent = 150 >> 1; - break; - case CONTENTS_SLIME: - cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 0; - cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 25; - cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 5; - cl.cshifts[CSHIFT_CONTENTS].percent = 150 >> 1; - break; - default: - cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 130; - cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 80; - cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 50; - cl.cshifts[CSHIFT_CONTENTS].percent = 128 >> 1; - } - - if (cl.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.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.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.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; - - // LordHavoc: fixed V_CalcBlend - r = 0; - g = 0; - b = 0; - a = 0; - - for (j=0 ; j 1) - a2 = 1; - r += (cl.cshifts[j].destcolor[0]-r) * a2; - g += (cl.cshifts[j].destcolor[1]-g) * a2; - b += (cl.cshifts[j].destcolor[2]-b) * a2; - a = 1 - (1 - a) * (1 - a2); // correct alpha multiply... took a while to find it on the web - } - // saturate color (to avoid blending in black) - if (a) - { - a2 = 1 / a; - r *= a2; - g *= a2; - b *= a2; - } - - r_refdef.viewblend[0] = bound(0, r * (1.0/255.0), 1); - r_refdef.viewblend[1] = bound(0, g * (1.0/255.0), 1); - r_refdef.viewblend[2] = bound(0, b * (1.0/255.0), 1); - r_refdef.viewblend[3] = bound(0, a , 1); -} - /* ============================================================================== @@ -449,20 +291,7 @@ void V_UpdateBlends (void) ============================================================================== */ -/* -============== -V_AddIdle - -Idle swaying -============== -*/ -static void V_AddIdle (float idle) -{ - r_refdef.viewangles[ROLL] += idle * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value; - r_refdef.viewangles[PITCH] += idle * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value; - r_refdef.viewangles[YAW] += idle * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value; -} - +extern matrix4x4_t viewmodelmatrix; /* ================== @@ -472,92 +301,179 @@ V_CalcRefdef */ void V_CalcRefdef (void) { - entity_t *ent, *view; - vec3_t forward; - vec3_t angles; - float bob; - float side; - - if (cls.state != ca_connected || !cl.worldmodel) - return; - - // ent is the player model (visible when out of body) - ent = &cl_entities[cl.viewentity]; - // view is the weapon model (only visible from inside body) - view = &cl.viewent; - - V_DriftPitch (); - - VectorCopy (cl.viewentorigin, r_refdef.vieworg); - if (!intimerefresh) - VectorCopy (cl.viewangles, r_refdef.viewangles); - - if (cl.intermission) - { - view->render.model = NULL; - VectorCopy (ent->render.angles, r_refdef.viewangles); - V_AddIdle (1); - } - else if (chase_active.value) + entity_t *ent; + if (cls.state == ca_connected && cls.signon == SIGNONS) { - r_refdef.vieworg[2] += cl.viewheight; - Chase_Update (); - V_AddIdle (v_idlescale.value); + // ent is the player model (visible when out of body) + ent = &cl_entities[cl.viewentity]; + if (cl.intermission) + { + // entity is a fixed camera + VectorCopy(ent->render.origin, r_refdef.vieworg); + VectorCopy(ent->render.angles, r_refdef.viewangles); + } + else if (chase_active.value) + { + // observing entity from third person + VectorCopy(ent->render.origin, r_refdef.vieworg); + VectorCopy(cl.viewangles, r_refdef.viewangles); + Chase_Update(); + } + else + { + // first person view from entity + VectorCopy(ent->render.origin, r_refdef.vieworg); + VectorCopy(cl.viewangles, r_refdef.viewangles); + // angles + if (cl.stats[STAT_HEALTH] <= 0) + r_refdef.viewangles[ROLL] = 80; // dead view angle + VectorAdd(r_refdef.viewangles, cl.punchangle, r_refdef.viewangles); + r_refdef.viewangles[ROLL] += V_CalcRoll(cl.viewangles, cl.velocity); + 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 -= cl.frametime; + } + if (v_idlescale.value) + { + 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; + } + // origin + VectorAdd(r_refdef.vieworg, cl.punchvector, r_refdef.vieworg); + r_refdef.vieworg[2] += cl.viewheight; + if (cl.stats[STAT_HEALTH] > 0 && cl_bob.value && cl_bobcycle.value) + { + double bob, cycle; + // LordHavoc: this code is *weird*, but not replacable (I think it + // should be done in QC on the server, but oh well, quake is quake) + // LordHavoc: figured out bobup: the time at which the sin is at 180 + // degrees (which allows lengthening or squishing the peak or valley) + cycle = cl.time / cl_bobcycle.value; + cycle -= (int) cycle; + if (cycle < cl_bobup.value) + cycle = sin(M_PI * cycle / cl_bobup.value); + else + cycle = sin(M_PI + M_PI * (cycle-cl_bobup.value)/(1.0 - cl_bobup.value)); + // bob is proportional to velocity in the xy plane + // (don't count Z, or jumping messes it up) + bob = sqrt(cl.velocity[0]*cl.velocity[0] + cl.velocity[1]*cl.velocity[1]) * cl_bob.value; + bob = bob*0.3 + bob*0.7*cycle; + r_refdef.vieworg[2] += bound(-7, bob, 4); + } + } + // calculate a viewmodel matrix for use in view-attached entities + Matrix4x4_CreateFromQuakeEntity(&viewmodelmatrix, r_refdef.vieworg[0], r_refdef.vieworg[1], r_refdef.vieworg[2], r_refdef.viewangles[0] + v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value, r_refdef.viewangles[1] - v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value, r_refdef.viewangles[2] - v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value, 0.3); } else + Matrix4x4_CreateIdentity(&viewmodelmatrix); +} + +void V_FadeViewFlashs(void) +{ + // drop the damage value + cl.cshifts[CSHIFT_DAMAGE].percent -= (cl.time - cl.oldtime)*150; + if (cl.cshifts[CSHIFT_DAMAGE].percent <= 0) + cl.cshifts[CSHIFT_DAMAGE].percent = 0; + // drop the bonus value + cl.cshifts[CSHIFT_BONUS].percent -= (cl.time - cl.oldtime)*100; + if (cl.cshifts[CSHIFT_BONUS].percent <= 0) + cl.cshifts[CSHIFT_BONUS].percent = 0; +} + +void V_CalcViewBlend(void) +{ + float a2; + int j; + r_refdef.viewblend[0] = 0; + r_refdef.viewblend[1] = 0; + r_refdef.viewblend[2] = 0; + r_refdef.viewblend[3] = 0; + if (cls.state == ca_connected && cls.signon == SIGNONS) { - side = V_CalcRoll (cl_entities[cl.viewentity].render.angles, cl.velocity); - r_refdef.viewangles[ROLL] += side; + // set contents color + switch (CL_PointContents(r_refdef.vieworg)) + { + case CONTENTS_EMPTY: + case CONTENTS_SOLID: + cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = v_cshift.destcolor[0]; + cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = v_cshift.destcolor[1]; + cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = v_cshift.destcolor[2]; + cl.cshifts[CSHIFT_CONTENTS].percent = v_cshift.percent; + break; + case CONTENTS_LAVA: + cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 255; + cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 80; + cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 0; + cl.cshifts[CSHIFT_CONTENTS].percent = 150 >> 1; + break; + case CONTENTS_SLIME: + cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 0; + cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 25; + cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 5; + cl.cshifts[CSHIFT_CONTENTS].percent = 150 >> 1; + break; + default: + cl.cshifts[CSHIFT_CONTENTS].destcolor[0] = 130; + cl.cshifts[CSHIFT_CONTENTS].destcolor[1] = 80; + cl.cshifts[CSHIFT_CONTENTS].destcolor[2] = 50; + cl.cshifts[CSHIFT_CONTENTS].percent = 128 >> 1; + } - if (v_dmg_time > 0) + if (cl.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.items & IT_SUIT) { - 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 -= cl.frametime; + 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.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.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; - if (cl.stats[STAT_HEALTH] <= 0) - r_refdef.viewangles[ROLL] = 80; // dead view angle - - V_AddIdle (v_idlescale.value); - - // offsets - angles[PITCH] = -ent->render.angles[PITCH]; // because entity pitches are actually backward - angles[YAW] = ent->render.angles[YAW]; - angles[ROLL] = ent->render.angles[ROLL]; - - AngleVectors (angles, forward, NULL, NULL); - - bob = V_CalcBob (); - - r_refdef.vieworg[2] += cl.viewheight + bob; - - // set up gun - view->state_current.modelindex = cl.stats[STAT_WEAPON]; - view->state_current.frame = cl.stats[STAT_WEAPONFRAME]; - VectorCopy(r_refdef.vieworg, view->render.origin); - //view->render.origin[0] = ent->render.origin[0] + bob * 0.4 * forward[0]; - //view->render.origin[1] = ent->render.origin[1] + bob * 0.4 * forward[1]; - //view->render.origin[2] = ent->render.origin[2] + bob * 0.4 * forward[2] + cl.viewheight + bob; - view->render.angles[PITCH] = -r_refdef.viewangles[PITCH] - v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value; - view->render.angles[YAW] = r_refdef.viewangles[YAW] - v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value; - view->render.angles[ROLL] = r_refdef.viewangles[ROLL] - v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value; - // FIXME: this setup code is somewhat evil (CL_LerpUpdate should be private?) - CL_LerpUpdate(view); - view->render.colormap = -1; // no special coloring - view->render.alpha = ent->render.alpha; // LordHavoc: if the player is transparent, so is the gun - view->render.effects = ent->render.effects; - view->render.scale = 1.0 / 3.0; - - // LordHavoc: origin view kick added - if (!intimerefresh) + // LordHavoc: fixed V_CalcBlend + for (j = 0;j < NUM_CSHIFTS;j++) { - VectorAdd(r_refdef.viewangles, cl.punchangle, r_refdef.viewangles); - VectorAdd(r_refdef.vieworg, cl.punchvector, r_refdef.vieworg); + a2 = bound(0.0f, cl.cshifts[j].percent * (1.0f / 255.0f), 1.0f); + if (a2 > 0) + { + VectorLerp(r_refdef.viewblend, a2, cl.cshifts[j].destcolor, r_refdef.viewblend); + r_refdef.viewblend[3] = 1 - (1 - r_refdef.viewblend[3]) * (1 - a2); // correct alpha multiply... took a while to find it on the web + } + } + // saturate color (to avoid blending in black) + if (r_refdef.viewblend[3]) + { + a2 = 1 / r_refdef.viewblend[3]; + VectorScale(r_refdef.viewblend, a2, r_refdef.viewblend); } - // copy to refdef - r_refdef.viewent = view->render; + r_refdef.viewblend[0] = bound(0.0f, r_refdef.viewblend[0] * (1.0f/255.0f), 1.0f); + r_refdef.viewblend[1] = bound(0.0f, r_refdef.viewblend[1] * (1.0f/255.0f), 1.0f); + r_refdef.viewblend[2] = bound(0.0f, r_refdef.viewblend[2] * (1.0f/255.0f), 1.0f); + r_refdef.viewblend[3] = bound(0.0f, r_refdef.viewblend[3] , 1.0f); } }