void V_AddViewWeapon (float bob) { vec3_t forward, right, up; centity_t *cent; int gunmodel = V_CurrentWeaponModel(); extern cvar_t scr_fov; cent = &cl.viewent; TP_ParseWeaponModel(cl.model_precache[gunmodel]); if (!cl_drawgun.value || (cl_drawgun.value == 2 && scr_fov.value > 90) || ((view_message.flags & (PF_GIB|PF_DEAD))) || cl.stats[STAT_ITEMS] & IT_INVISIBILITY || cl.stats[STAT_HEALTH] <= 0 || !Cam_DrawViewModel()) { cent->current.modelindex = 0; //no model return; } //angles cent->current.angles[YAW] = r_refdef.viewangles[YAW]; cent->current.angles[PITCH] = -r_refdef.viewangles[PITCH]; cent->current.angles[ROLL] = r_refdef.viewangles[ROLL]; //origin AngleVectors (r_refdef.viewangles, forward, right, up); VectorCopy (r_refdef.vieworg, cent->current.origin); VectorMA (cent->current.origin, bob * 0.4, forward, cent->current.origin); if (r_viewmodeloffset.string[0]) { float offset[3]; int size = sizeof(offset)/sizeof(offset[0]); ParseFloats(r_viewmodeloffset.string, offset, &size); VectorMA (cent->current.origin, offset[0], right, cent->current.origin); VectorMA (cent->current.origin, -offset[1], up, cent->current.origin); VectorMA (cent->current.origin, offset[2], forward, cent->current.origin); } // fudge position around to keep amount of weapon visible roughly equal with different FOV if (scr_viewsize.value == 110) cent->current.origin[2] += 1; else if (scr_viewsize.value == 100) cent->current.origin[2] += 2; else if (scr_viewsize.value == 90) cent->current.origin[2] += 1; else if (scr_viewsize.value == 80) cent->current.origin[2] += 0.5; if (cent->current.modelindex != gunmodel) { cl.viewent.frametime = -1; } else { if (cent->current.frame != view_message.weaponframe) { cent->frametime = cl.time; cent->oldframe = cent->current.frame; } } cent->current.modelindex = gunmodel; cent->current.frame = view_message.weaponframe; }
/* ================== V_AddViewWeapon ================== */ void V_AddViewWeapon (float bob) { vec3_t forward, up; entity_t ent; extern cvar_t scr_fov; // FIXME, move the statics to a structure like cl static int oldweapon, curframe, oldframe; static double start_lerp_time; if (!cl_drawgun.value || (cl_drawgun.value == 2 && scr_fov.value > 90) || view_message.flags & (PF_GIB|PF_DEAD) || !Cam_DrawViewModel()) return; memset (&ent, 0, sizeof(ent)); if ((unsigned int)cl.stats[STAT_WEAPON] >= MAX_MODELS) Host_Error ("STAT_WEAPON >= MAX_MODELS"); ent.model = cl.model_precache[cl.stats[STAT_WEAPON]]; if (!ent.model) return; ent.frame = view_message.weaponframe; ent.colormap = 0; ent.renderfx = RF_WEAPONMODEL; if (cl.stats[STAT_WEAPON] != oldweapon) { oldweapon = cl.stats[STAT_WEAPON]; curframe = -1; start_lerp_time = -1; } if (ent.frame != curframe) { oldframe = curframe; curframe = ent.frame; start_lerp_time = cl.time; } ent.oldframe = oldframe; ent.backlerp = 1 - (cl.time - start_lerp_time)*10; ent.backlerp = bound (0, ent.backlerp, 1); // if (r_lerpmuzzlehack.value && cl.modelinfos[cl.stats[STAT_WEAPON]] != mi_no_lerp_hack) // ent.renderfx |= RF_LIMITLERP; if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) ent.alpha = 128; ent.angles[YAW] = r_refdef2.viewangles[YAW]; ent.angles[PITCH] = -r_refdef2.viewangles[PITCH]; ent.angles[ROLL] = r_refdef2.viewangles[ROLL]; AngleVectors (r_refdef2.viewangles, forward, NULL, up); VectorCopy (r_refdef2.vieworg, ent.origin); if (cl_bobmodel.value) { // calculate for swinging gun model // the gun bobs when running on the ground, but doesn't bob when you're in the air. // Sajt: I tried to smooth out the transitions between bob and no bob, which works // for the most part, but for some reason when you go through a message trigger or // pick up an item or anything like that it will momentarily jolt the gun. vec3_t forward, right, up; static double lastongroundtime = 0; double xyspeed; float bspeed; float s, t; xyspeed = sqrt(cl.simvel[0] * cl.simvel[0] + cl.simvel[1] * cl.simvel[1]); s = cl.time * cl_bobmodel_speed.value; if (cl.onground) { lastongroundtime = cl.time; if (cl.time - cl.landtime < 0.2) { // just hit the ground, speed the bob back up over the next 0.2 seconds t = cl.time - cl.landtime; t = bound(0, t, 0.2); t *= 5; } else { t = 1; } } else { // recently left the ground, slow the bob down over the next 0.2 seconds t = cl.time - lastongroundtime; t = 0.2 - bound(0, t, 0.2); t *= 5; } bspeed = bound (0, xyspeed, 400) * 0.01f; AngleVectors (r_refdef2.viewangles, forward, right, up); bob = bspeed * cl_bobmodel_side.value * sin (s) * t; VectorMA (ent.origin, bob, right, ent.origin); bob = bspeed * cl_bobmodel_up.value * cos (s * 2) * t; VectorMA (ent.origin, bob, up, ent.origin); } // fudge position around to keep amount of weapon visible // roughly equal with different FOV if (scr_viewsize.value == 110) VectorMA (ent.origin, 1, up, ent.origin); else if (scr_viewsize.value == 100) VectorMA (ent.origin, 2, up, ent.origin); else if (scr_viewsize.value == 90) VectorMA (ent.origin, 1, up, ent.origin); else if (scr_viewsize.value == 80) VectorMA (ent.origin, 0.5, up, ent.origin); V_AddEntity (&ent); }
static void VQH_AddViewModel() { if ( !vqh_drawviewmodel->value ) { return; } if ( GGameType & GAME_QuakeWorld && !Cam_DrawViewModel() ) { return; } if ( GGameType & GAME_Quake && !( GGameType & GAME_QuakeWorld ) && cl.q1_items & Q1IT_INVISIBILITY ) { return; } if ( GGameType & GAME_QuakeWorld && cl.qh_stats[ QWSTAT_ITEMS ] & Q1IT_INVISIBILITY ) { return; } if ( GGameType & GAME_HexenWorld && cl.qh_spectator ) { return; } if ( GGameType & GAME_Quake && cl.qh_stats[ Q1STAT_HEALTH ] <= 0 ) { return; } if ( GGameType & GAME_Hexen2 && cl.h2_v.health <= 0 ) { return; } if ( GGameType & GAME_Quake && !cl.q1_viewent.state.modelindex ) { return; } if ( GGameType & GAME_Hexen2 && !cl.h2_viewent.state.modelindex ) { return; } if ( !( GGameType & ( GAME_QuakeWorld | GAME_HexenWorld ) ) && chase_active->value ) { return; } refEntity_t gun; Com_Memset( &gun, 0, sizeof ( gun ) ); gun.reType = RT_MODEL; gun.renderfx = RF_MINLIGHT | RF_FIRST_PERSON | RF_DEPTHHACK; if ( GGameType & GAME_Hexen2 ) { VectorCopy( cl.h2_viewent.state.origin, gun.origin ); gun.hModel = cl.model_draw[ cl.h2_viewent.state.modelindex ]; gun.frame = cl.h2_viewent.state.frame; gun.skinNum = cl.h2_viewent.state.skinnum; gun.syncBase = cl.h2_viewent.syncbase; CLH2_SetRefEntAxis( &gun, cl.h2_viewent.state.angles, oldvec3_origin, cl.h2_viewent.state.scale, cl.h2_viewent.state.abslight, cl.h2_viewent.state.drawflags ); CLH2_HandleCustomSkin( &gun ); } else { VectorCopy( cl.q1_viewent.state.origin, gun.origin ); gun.hModel = cl.model_draw[ cl.q1_viewent.state.modelindex ]; gun.frame = cl.q1_viewent.state.frame; gun.skinNum = cl.q1_viewent.state.skinnum; gun.syncBase = cl.q1_viewent.syncbase; CLQ1_SetRefEntAxis( &gun, cl.q1_viewent.state.angles ); } R_AddRefEntityToScene( &gun ); if ( GGameType & GAME_Hexen2 ) { CLH2_AddColourShadeRefEnt(&gun, cl.h2_viewent.state.colormap, cl.h2_viewent.state.drawflags ); } }
/* ============= R_DrawViewModel ============= */ void R_DrawViewModel (void) { float ambient[4], diffuse[4]; int j; int lnum; vec3_t dist; float add; dlight_t *dl; int ambientlight, shadelight; if (!r_drawviewmodel.value || !Cam_DrawViewModel()) return; if (envmap) return; if (!r_drawentities.value) return; if (cl.stats[STAT_ITEMS] & IT_INVISIBILITY) return; if (cl.stats[STAT_HEALTH] <= 0) return; currententity = &cl.viewent; if (!currententity->model) return; j = R_LightPoint (currententity->origin); if (j < 24) j = 24; // allways give some light on gun ambientlight = j; shadelight = j; // add dynamic lights for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++) { dl = &cl_dlights[lnum]; if (!dl->radius) continue; if (!dl->radius) continue; if (dl->die < cl.time) continue; VectorSubtract (currententity->origin, dl->origin, dist); add = dl->radius - Length(dist); if (add > 0) ambientlight += add; } ambient[0] = ambient[1] = ambient[2] = ambient[3] = (float)ambientlight / 128; diffuse[0] = diffuse[1] = diffuse[2] = diffuse[3] = (float)shadelight / 128; // hack the depth range to prevent view model from poking into walls glDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); R_DrawAliasModel (currententity); glDepthRange (gldepthmin, gldepthmax); }