static void VQH_CalcRefdef( qwplayer_state_t* qwViewMessage, hwplayer_state_t* hwViewMessage ) { static float oldz = 0; if ( !( GGameType & GAME_Hexen2 ) || !cl.h2_v.cameramode ) { VQH_DriftPitch( qwViewMessage, hwViewMessage ); if ( GGameType & GAME_Hexen2 ) { VH2_DriftRoll( hwViewMessage ); } } float bob = VQH_CalcBob(); // ent is the player model (visible when out of body) q1entity_t* q1ent; h2entity_t* h2ent; if ( GGameType & GAME_QuakeWorld ) { // refresh position from simulated origin VectorCopy( cl.qh_simorg, cl.refdef.vieworg ); } else if ( GGameType & GAME_Quake ) { q1ent = &clq1_entities[ cl.viewentity ]; // transform the view offset by the model's matrix to get the offset from // model origin for the view q1ent->state.angles[ YAW ] = cl.viewangles[ YAW ]; // the model should face // the view dir q1ent->state.angles[ PITCH ] = -cl.viewangles[ PITCH ]; // the model should face // the view dir // refresh position VectorCopy( q1ent->state.origin, cl.refdef.vieworg ); cl.refdef.vieworg[ 2 ] += cl.qh_viewheight; } else if ( GGameType & GAME_HexenWorld ) { // refresh position from simulated origin VectorCopy( cl.qh_simorg, cl.refdef.vieworg ); } else { h2ent = &h2cl_entities[ cl.viewentity ]; // transform the view offset by the model's matrix to get the offset from // model origin for the view h2ent->state.angles[ YAW ] = cl.viewangles[ YAW ]; // the model should face // the view dir h2ent->state.angles[ PITCH ] = -cl.viewangles[ PITCH ]; // the model should face // the view dir // refresh position VectorCopy( h2ent->state.origin, cl.refdef.vieworg ); cl.refdef.vieworg[ 2 ] += cl.qh_viewheight; } cl.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 cl.refdef.vieworg[ 0 ] += 1.0 / 16; cl.refdef.vieworg[ 1 ] += 1.0 / 16; cl.refdef.vieworg[ 2 ] += 1.0 / 16; vec3_t viewangles; if ( GGameType & ( GAME_QuakeWorld | GAME_HexenWorld ) ) { VectorCopy( cl.qh_simangles, viewangles ); } else { VectorCopy( cl.viewangles, viewangles ); } VQH_CalcViewRoll( viewangles ); VQH_AddIdle( viewangles ); vec3_t forward, right, up; if ( GGameType & GAME_QuakeWorld ) { if ( qwViewMessage->flags & QWPF_GIB ) { cl.refdef.vieworg[ 2 ] += 8; // gib view height } else if ( qwViewMessage->flags & QWPF_DEAD ) { cl.refdef.vieworg[ 2 ] -= 16; // corpse view height } else { cl.refdef.vieworg[ 2 ] += 22; // view height } if ( qwViewMessage->flags & QWPF_DEAD ) { // QWPF_GIB will also set QWPF_DEAD viewangles[ ROLL ] = 80; // dead view angle } // offsets AngleVectors( cl.qh_simangles, forward, right, up ); } else if ( GGameType & GAME_HexenWorld ) { if ( cl.qh_spectator ) { cl.refdef.vieworg[ 2 ] += 50; // view height } else { if ( hwViewMessage->flags & HWPF_CROUCH ) { cl.refdef.vieworg[ 2 ] += 24; // gib view height } else if ( hwViewMessage->flags & HWPF_DEAD ) { cl.refdef.vieworg[ 2 ] += 8; // corpse view height } else { cl.refdef.vieworg[ 2 ] += 50; // view height } if ( hwViewMessage->flags & HWPF_DEAD ) { // PF_GIB will also set HWPF_DEAD viewangles[ ROLL ] = 80; // dead view angle } } // offsets AngleVectors( cl.qh_simangles, forward, right, up ); } else if ( GGameType & GAME_Quake ) { // offsets vec3_t angles; angles[ PITCH ] = -q1ent->state.angles[ PITCH ]; // because entity pitches are actually backward angles[ YAW ] = q1ent->state.angles[ YAW ]; angles[ ROLL ] = q1ent->state.angles[ ROLL ]; AngleVectors( angles, forward, right, up ); VQH_BoundOffsets(); } else { // offsets vec3_t angles; angles[ PITCH ] = -h2ent->state.angles[ PITCH ]; // because entity pitches are actually backward angles[ YAW ] = h2ent->state.angles[ YAW ]; angles[ ROLL ] = h2ent->state.angles[ ROLL ]; AngleVectors( angles, forward, right, up ); VQH_BoundOffsets(); } // view is the weapon model (only visible from inside body) q1entity_t* q1view; h2entity_t* h2view; if ( GGameType & GAME_Quake ) { q1view = &cl.q1_viewent; // set up gun position if ( GGameType & GAME_QuakeWorld ) { VectorCopy( cl.qh_simangles, q1view->state.angles ); } else { VectorCopy( cl.viewangles, q1view->state.angles ); } VQH_CalcGunAngle( viewangles ); if ( GGameType & GAME_QuakeWorld ) { VectorCopy( cl.qh_simorg, q1view->state.origin ); q1view->state.origin[ 2 ] += 22; } else { VectorCopy( q1ent->state.origin, q1view->state.origin ); q1view->state.origin[ 2 ] += cl.qh_viewheight; } for ( int i = 0; i < 3; i++ ) { q1view->state.origin[ i ] += forward[ i ] * bob * 0.4; } q1view->state.origin[ 2 ] += bob; // fudge position around to keep amount of weapon visible // roughly equal with different FOV if ( scr_viewsize->value == 110 ) { q1view->state.origin[ 2 ] += 1; } else if ( scr_viewsize->value == 100 ) { q1view->state.origin[ 2 ] += 2; } else if ( scr_viewsize->value == 90 ) { q1view->state.origin[ 2 ] += 1; } else if ( scr_viewsize->value == 80 ) { q1view->state.origin[ 2 ] += 0.5; } if ( GGameType & GAME_QuakeWorld ) { if ( qwViewMessage->flags & ( QWPF_GIB | QWPF_DEAD ) ) { q1view->state.modelindex = 0; } else { q1view->state.modelindex = cl.qh_stats[ Q1STAT_WEAPON ]; } q1view->state.frame = qwViewMessage->weaponframe; } else { q1view->state.modelindex = cl.qh_stats[ Q1STAT_WEAPON ]; q1view->state.frame = cl.qh_stats[ Q1STAT_WEAPONFRAME ]; q1view->state.colormap = 0; } } else { h2view = &cl.h2_viewent; // set up gun position if ( GGameType & GAME_HexenWorld ) { VectorCopy( cl.qh_simangles, h2view->state.angles ); } else { VectorCopy( cl.viewangles, h2view->state.angles ); } VQH_CalcGunAngle( viewangles ); if ( GGameType & GAME_HexenWorld ) { VectorCopy( cl.refdef.vieworg, h2view->state.origin ); } else { VectorCopy( h2ent->state.origin, h2view->state.origin ); h2view->state.origin[ 2 ] += cl.qh_viewheight; } for ( int i = 0; i < 3; i++ ) { h2view->state.origin[ i ] += forward[ i ] * bob * 0.4; } if ( !( GGameType & GAME_HexenWorld ) ) { h2view->state.origin[ 2 ] += bob; } // fudge position around to keep amount of weapon visible // roughly equal with different FOV if ( scr_viewsize->value == 110 ) { h2view->state.origin[ 2 ] += 1; } else if ( scr_viewsize->value == 100 ) { h2view->state.origin[ 2 ] += 2; } else if ( scr_viewsize->value == 90 ) { h2view->state.origin[ 2 ] += 1; } else if ( scr_viewsize->value == 80 ) { h2view->state.origin[ 2 ] += 0.5; } if ( GGameType & GAME_HexenWorld ) { if ( hwViewMessage->flags & ( HWPF_DEAD ) ) { h2view->state.modelindex = 0; } else { h2view->state.modelindex = cl.qh_stats[ Q1STAT_WEAPON ]; } h2view->state.frame = hwViewMessage->weaponframe; // Place weapon in powered up mode if ( ( cl.hw_frames[ clc.netchan.incomingSequence & UPDATE_MASK_HW ].playerstate[ cl.playernum ].drawflags & H2MLS_MASKIN ) == H2MLS_POWERMODE ) { h2view->state.drawflags = ( h2view->state.drawflags & H2MLS_MASKOUT ) | H2MLS_POWERMODE; } else { h2view->state.drawflags = ( h2view->state.drawflags & H2MLS_MASKOUT ) | 0; } } else { h2view->state.modelindex = cl.qh_stats[ Q1STAT_WEAPON ]; h2view->state.frame = cl.qh_stats[ Q1STAT_WEAPONFRAME ]; // Place weapon in powered up mode if ( ( h2ent->state.drawflags & H2MLS_MASKIN ) == H2MLS_POWERMODE ) { h2view->state.drawflags = ( h2view->state.drawflags & H2MLS_MASKOUT ) | H2MLS_POWERMODE; } else { h2view->state.drawflags = ( h2view->state.drawflags & H2MLS_MASKOUT ) | 0; } } } // set up the refresh position if ( GGameType & ( GAME_QuakeWorld | GAME_HexenWorld ) ) { viewangles[ PITCH ] += cl.qh_punchangle; } else { VectorAdd( viewangles, cl.qh_punchangles, viewangles ); } AnglesToAxis( viewangles, cl.refdef.viewaxis ); bool onGround; float currentZ; if ( GGameType & GAME_QuakeWorld ) { onGround = qwViewMessage->onground != -1; currentZ = cl.qh_simorg[ 2 ]; } else if ( GGameType & GAME_Quake ) { onGround = cl.qh_onground; currentZ = q1ent->state.origin[ 2 ]; } else if ( GGameType & GAME_HexenWorld ) { onGround = hwViewMessage->onground != -1; currentZ = cl.qh_simorg[ 2 ]; } else { onGround = cl.qh_onground; currentZ = h2ent->state.origin[ 2 ]; } // smooth out stair step ups if ( onGround && currentZ - oldz > 0 ) { float steptime = cls.frametime * 0.001; oldz += steptime * 80; if ( oldz > currentZ ) { oldz = currentZ; } if ( currentZ - oldz > 12 ) { oldz = currentZ - 12; } cl.refdef.vieworg[ 2 ] += oldz - currentZ; if ( GGameType & GAME_Hexen2 ) { h2view->state.origin[ 2 ] += oldz - currentZ; } else { q1view->state.origin[ 2 ] += oldz - currentZ; } } else { oldz = currentZ; } if ( !( GGameType & ( GAME_QuakeWorld | GAME_HexenWorld ) ) && chase_active->value ) { Chase_Update(); } }
/* ================== V_CalcRefdef ================== */ void V_CalcRefdef(void) { entity_t *ent, *view; int i; vec3_t forward, right, up; vec3_t angles; float bob; static float oldz = 0; V_DriftPitch(); // 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; // transform the view offset by the model's matrix to get the offset from // model origin for the view ent->angles[YAW] = cl.viewangles[YAW]; // the model should face // the view dir ent->angles[PITCH] = -cl.viewangles[PITCH]; // the model should face // the view dir bob = V_CalcBob(); // refresh position VectorCopy(ent->origin, r_refdef.vieworg); r_refdef.vieworg[2] += cl.viewheight + 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/16 pixel, so add 1/32 in each axis r_refdef.vieworg[0] += 1.0 / 32; r_refdef.vieworg[1] += 1.0 / 32; r_refdef.vieworg[2] += 1.0 / 32; VectorCopy(cl.viewangles, r_refdef.viewangles); V_CalcViewRoll(); V_AddIdle(); // offsets angles[PITCH] = -ent->angles[PITCH]; // because entity pitches are // actually backward angles[YAW] = ent->angles[YAW]; angles[ROLL] = ent->angles[ROLL]; AngleVectors(angles, forward, right, up); for (i = 0; i < 3; i++) r_refdef.vieworg[i] += scr_ofsx.value * forward[i] + scr_ofsy.value * right[i] + scr_ofsz.value * up[i]; V_BoundOffsets(); // set up gun position VectorCopy(cl.viewangles, view->angles); CalcGunAngle(); VectorCopy(ent->origin, view->origin); view->origin[2] += cl.viewheight; 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; view->model = cl.model_precache[cl.stats[STAT_WEAPON]]; view->frame = cl.stats[STAT_WEAPONFRAME]; view->colormap = vid.colormap; // set up the refresh position VectorAdd(r_refdef.viewangles, cl.punchangle, r_refdef.viewangles); // smooth out stair step ups if (cl.onground && ent->origin[2] - oldz > 0) { float steptime; steptime = cl.time - cl.oldtime; if (steptime < 0) //FIXME I_Error ("steptime < 0"); steptime = 0; oldz += steptime * 80; if (oldz > ent->origin[2]) oldz = ent->origin[2]; if (ent->origin[2] - oldz > 12) oldz = ent->origin[2] - 12; r_refdef.vieworg[2] += oldz - ent->origin[2]; view->origin[2] += oldz - ent->origin[2]; } else oldz = ent->origin[2]; if (chase_active.value) Chase_Update(); }
static void V_CalcRefdef (void) { // view is the weapon model (visible only from inside body) entity_t *view = &cl.viewent; float bob; static float oldz = 0; int i; vec3_t forward, right, up; vec_t *origin = cl.simorg; vec_t *viewangles = cl.simangles; V_DriftPitch (); bob = V_CalcBob (); // refresh position VectorCopy (origin, r_data->refdef->vieworg); r_data->refdef->vieworg[2] += cl.viewheight + bob; // never let it sit exactly on a node line, because a water plane can // disappear when viewed with the eye exactly on it. // server protocol specifies to only 1/8 pixel, so add 1/16 in each axis r_data->refdef->vieworg[0] += 1.0 / 16; r_data->refdef->vieworg[1] += 1.0 / 16; r_data->refdef->vieworg[2] += 1.0 / 16; VectorCopy (viewangles, r_data->refdef->viewangles); V_CalcViewRoll (); V_AddIdle (); // offsets AngleVectors (viewangles, forward, right, up); // don't allow cheats in multiplayer // FIXME check for dead if (cl.maxclients == 1) { for (i = 0; i < 3; i++) { r_data->refdef->vieworg[i] += scr_ofsx->value * forward[i] + scr_ofsy->value * right[i] + scr_ofsz->value * up[i]; } } V_BoundOffsets (); // set up gun position VectorCopy (viewangles, view->angles); CalcGunAngle (); VectorCopy (origin, view->origin); view->origin[2] += cl.viewheight; 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 (hud_sbar->int_val == 0 && r_data->scr_viewsize->int_val >= 100) ; else if (r_data->scr_viewsize->int_val == 110) view->origin[2] += 1; else if (r_data->scr_viewsize->int_val == 100) view->origin[2] += 2; else if (r_data->scr_viewsize->int_val == 90) view->origin[2] += 1; else if (r_data->scr_viewsize->int_val == 80) view->origin[2] += 0.5; if (view_message->pls.flags & (PF_GIB | PF_DEAD)) view->model = NULL; else view->model = cl.model_precache[cl.stats[STAT_WEAPON]]; view->frame = view_message->pls.weaponframe; view->skin = 0; // set up the refresh position VectorAdd (r_data->refdef->viewangles, cl.punchangle, r_data->refdef->viewangles); // smooth out stair step ups if ((cl.onground != -1) && (origin[2] - oldz > 0)) { float steptime; steptime = host_frametime; oldz += steptime * 80; if (oldz > origin[2]) oldz = origin[2]; if (origin[2] - oldz > 12) oldz = origin[2] - 12; r_data->refdef->vieworg[2] += oldz - origin[2]; view->origin[2] += oldz - origin[2]; } else oldz = origin[2]; if (cl.chase && chase_active->int_val) Chase_Update (); CL_TransformEntity (view, view->angles, true); }