//************************************************************************** //** //** ## ## ## ## ## #### #### ### ### //** ## ## ## ## ## ## ## ## ## ## #### #### //** ## ## ## ## ## ## ## ## ## ## ## ## ## ## //** ## ## ######## ## ## ## ## ## ## ## ### ## //** ### ## ## ### ## ## ## ## ## ## //** # ## ## # #### #### ## ## //** //** $Id: r_things.cpp 4355 2010-12-24 01:29:15Z firebrand_kh $ //** //** Copyright (C) 1999-2006 Jānis Legzdiņš //** //** 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. //** //************************************************************************** //** //** Refresh of things, i.e. objects represented by sprites. //** //** Sprite rotation 0 is facing the viewer, rotation 1 is one angle turn //** CLOCKWISE around the axis. This is not the same as the angle, which //** increases counter clockwise (protractor). There was a lot of stuff //** grabbed wrong, so I changed it... //** //************************************************************************** // HEADER FILES ------------------------------------------------------------ #include "gamedefs.h" #include "r_local.h" #include "sv_local.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- enum { SPR_VP_PARALLEL_UPRIGHT, SPR_FACING_UPRIGHT, SPR_VP_PARALLEL, SPR_ORIENTED, SPR_VP_PARALLEL_ORIENTED, SPR_VP_PARALLEL_UPRIGHT_ORIENTED, }; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern VCvarI r_chasecam; // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ VCvarI r_draw_mobjs("r_draw_mobjs", "1", CVAR_Archive); VCvarI r_draw_psprites("r_draw_psprites", "1", CVAR_Archive); VCvarI r_models("r_models", "1", CVAR_Archive); VCvarI r_hide_models("r_hide_models", "0", CVAR_Archive); VCvarI r_view_models("r_view_models", "1", CVAR_Archive); VCvarI r_model_shadows("r_model_shadows", "1", CVAR_Archive); VCvarI r_model_light("r_model_light", "1", CVAR_Archive); VCvarI r_sort_sprites("r_sort_sprites", "0"); VCvarI r_fix_sprite_offsets("r_fix_sprite_offsets", "1", CVAR_Archive); VCvarI r_sprite_fix_delta("r_sprite_fix_delta", "-3", CVAR_Archive); VCvarI r_drawfuzz("r_drawfuzz", "1", CVAR_Archive); VCvarF transsouls("transsouls", "1.0", CVAR_Archive); VCvarI croshair("croshair", "0", CVAR_Archive); VCvarF croshair_alpha("croshair_alpha", "1", CVAR_Archive); // CODE -------------------------------------------------------------------- //========================================================================== // // VRenderLevelShared::DrawTranslucentPoly // //========================================================================== void VRenderLevelShared::DrawTranslucentPoly(surface_t* surf, TVec* sv, int count, int lump, float Alpha, bool Additive, int translation, bool type, vuint32 light, vuint32 Fade, const TVec& normal, float pdist, const TVec& saxis, const TVec& taxis, const TVec& texorg) { guard(VRenderLevelShared::DrawTranslucentPoly); int i; TVec mid(0, 0, 0); for (i = 0; i < count; i++) { mid += sv[i]; } mid /= count; float dist = fabs(DotProduct(mid - vieworg, viewforward)); // float dist = Length(mid - vieworg); int found = -1; float best_dist = -1; for (i = 0; i < MAX_TRANS_SPRITES; i++) { trans_sprite_t &spr = trans_sprites[i]; if (!spr.Alpha) { if (type) memcpy(spr.Verts, sv, sizeof(TVec) * 4); spr.dist = dist; spr.lump = lump; spr.normal = normal; spr.pdist = pdist; spr.saxis = saxis; spr.taxis = taxis; spr.texorg = texorg; spr.surf = surf; spr.Alpha = Alpha; spr.Additive = Additive; spr.translation = translation; spr.type = type; spr.light = light; spr.Fade = Fade; return; } if (spr.dist > best_dist) { found = i; best_dist = spr.dist; } } if (best_dist > dist) { // All slots are full, draw and replace a far away sprite trans_sprite_t &spr = trans_sprites[found]; if (spr.type == 2) { DrawEntityModel(spr.Ent, spr.light, spr.Fade, spr.Alpha, spr.Additive, spr.TimeFrac, RPASS_Normal); } else if (spr.type) { Drawer->DrawSpritePolygon(spr.Verts, GTextureManager[spr.lump], spr.Alpha, spr.Additive, GetTranslation(spr.translation), ColourMap, spr.light, spr.Fade, spr.normal, spr.pdist, spr.saxis, spr.taxis, spr.texorg); } else { check(spr.surf); Drawer->DrawMaskedPolygon(spr.surf, spr.Alpha, spr.Additive); } if (type) memcpy(spr.Verts, sv, sizeof(TVec) * 4); spr.dist = dist; spr.lump = lump; spr.normal = normal; spr.pdist = pdist; spr.saxis = saxis; spr.taxis = taxis; spr.texorg = texorg; spr.surf = surf; spr.Alpha = Alpha; spr.Additive = Additive; spr.translation = translation; spr.type = type; spr.light = light; spr.Fade = Fade; return; } // All slots are full and are nearer to current sprite so draw it if (type) { Drawer->DrawSpritePolygon(sv, GTextureManager[lump], Alpha, Additive, GetTranslation(translation), ColourMap, light, Fade, normal, pdist, saxis, taxis, texorg); } else { check(surf); Drawer->DrawMaskedPolygon(surf, Alpha, Additive); } unguard; } //========================================================================== // // VRenderLevelShared::RenderSprite // //========================================================================== void VRenderLevelShared::RenderSprite(VEntity* thing, vuint32 light, vuint32 Fade, float Alpha, bool Additive) { guard(VRenderLevelShared::RenderSprite); int spr_type = thing->SpriteType; TVec sprorigin = thing->Origin; sprorigin.z -= thing->FloorClip; TVec sprforward; TVec sprright; TVec sprup; float dot; TVec tvec; float sr; float cr; switch (spr_type) { case SPR_VP_PARALLEL_UPRIGHT: // Generate the sprite's axes, with sprup straight up in worldspace, // and sprright parallel to the viewplane. This will not work if the // view direction is very close to straight up or down, because the // cross product will be between two nearly parallel vectors and // starts to approach an undefined state, so we don't draw if the two // vectors are less than 1 degree apart dot = viewforward.z; // same as DotProduct(viewforward, sprup) // because sprup is 0, 0, 1 if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = 0.999848 return; sprup = TVec(0, 0, 1); // CrossProduct(sprup, viewforward) sprright = Normalise(TVec(viewforward.y, -viewforward.x, 0)); // CrossProduct(sprright, sprup) sprforward = TVec(-sprright.y, sprright.x, 0); break; case SPR_FACING_UPRIGHT: // Generate the sprite's axes, with sprup straight up in worldspace, // and sprright perpendicular to sprorigin. This will not work if the // view direction is very close to straight up or down, because the // cross product will be between two nearly parallel vectors and // starts to approach an undefined state, so we don't draw if the two // vectors are less than 1 degree apart tvec = Normalise(sprorigin - vieworg); dot = tvec.z; // same as DotProduct (tvec, sprup) because // sprup is 0, 0, 1 if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = 0.999848 return; sprup = TVec(0, 0, 1); // CrossProduct(sprup, -sprorigin) sprright = Normalise(TVec(tvec.y, -tvec.x, 0)); // CrossProduct(sprright, sprup) sprforward = TVec(-sprright.y, sprright.x, 0); break; case SPR_VP_PARALLEL: // Generate the sprite's axes, completely parallel to the viewplane. // There are no problem situations, because the sprite is always in // the same position relative to the viewer sprup = viewup; sprright = viewright; sprforward = viewforward; break; case SPR_ORIENTED: // Generate the sprite's axes, according to the sprite's world // orientation AngleVectors(thing->Angles, sprforward, sprright, sprup); break; case SPR_VP_PARALLEL_ORIENTED: // Generate the sprite's axes, parallel to the viewplane, but // rotated in that plane around the centre according to the sprite // entity's roll angle. So sprforward stays the same, but sprright // and sprup rotate sr = msin(thing->Angles.roll); cr = mcos(thing->Angles.roll); sprforward = viewforward; sprright = TVec(viewright.x * cr + viewup.x * sr, viewright.y * cr + viewup.y * sr, viewright.z * cr + viewup.z * sr); sprup = TVec(viewright.x * -sr + viewup.x * cr, viewright.y * -sr + viewup.y * cr, viewright.z * -sr + viewup.z * cr); break; case SPR_VP_PARALLEL_UPRIGHT_ORIENTED: // Generate the sprite's axes, with sprup straight up in worldspace, // and sprright parallel to the viewplane and then rotated in that // plane around the centre according to the sprite entity's roll // angle. So sprforward stays the same, but sprright and sprup rotate // This will not work if the view direction is very close to straight // up or down, because the cross product will be between two nearly // parallel vectors and starts to approach an undefined state, so we // don't draw if the two vectors are less than 1 degree apart dot = viewforward.z; // same as DotProduct(viewforward, sprup) // because sprup is 0, 0, 1 if ((dot > 0.999848) || (dot < -0.999848)) // cos(1 degree) = 0.999848 return; sr = msin(thing->Angles.roll); cr = mcos(thing->Angles.roll); // CrossProduct(TVec(0, 0, 1), viewforward) tvec = Normalise(TVec(viewforward.y, -viewforward.x, 0)); // CrossProduct(tvec, TVec(0, 0, 1)) sprforward = TVec(-tvec.y, tvec.x, 0); // Rotate sprright = TVec(tvec.x * cr, tvec.y * cr, tvec.z * cr + sr); sprup = TVec(tvec.x * -sr, tvec.y * -sr, tvec.z * -sr + cr); break; default: Sys_Error("RenderSprite: Bad sprite type %d", spr_type); } spritedef_t* sprdef; spriteframe_t* sprframe; VState* DispState = (thing->EntityFlags & VEntity::EF_UseDispState) ? thing->DispState : thing->State; int SpriteIndex = DispState->SpriteIndex; if (thing->FixedSpriteName != NAME_None) { SpriteIndex = VClass::FindSprite(thing->FixedSpriteName); } // decide which patch to use for sprite relative to player if ((unsigned)SpriteIndex >= MAX_SPRITE_MODELS) { #ifdef PARANOID GCon->Logf(NAME_Dev, "Invalid sprite number %d", SpriteIndex); #endif return; } sprdef = &sprites[SpriteIndex]; if ((DispState->Frame & VState::FF_FRAMEMASK) >= sprdef->numframes) { #ifdef PARANOID GCon->Logf(NAME_Dev, "Invalid sprite frame %d : %d", SpriteIndex, DispState->Frame); #endif return; } sprframe = &sprdef->spriteframes[DispState->Frame & VState::FF_FRAMEMASK]; int lump; bool flip; if (sprframe->rotate) { // choose a different rotation based on player view //FIXME must use sprforward here? float ang = matan(thing->Origin.y - vieworg.y, thing->Origin.x - vieworg.x); if (sprframe->lump[0] == sprframe->lump[1]) { ang = AngleMod(ang - thing->Angles.yaw + 180.0 + 45.0 / 2.0); } else { ang = AngleMod(ang - thing->Angles.yaw + 180.0 + 45.0 / 4.0); } vuint32 rot = (vuint32)(ang * 16 / 360.0) & 15; lump = sprframe->lump[rot]; flip = sprframe->flip[rot]; } else { // use single rotation for all views lump = sprframe->lump[0]; flip = sprframe->flip[0]; } if (lump <= 0) { #ifdef PARANOID GCon->Logf(NAME_Dev, "Sprite frame %d : %d, not present", SpriteIndex, DispState->Frame); #endif // Sprite lump is not present return; } VTexture* Tex = GTextureManager[lump]; int TexWidth = Tex->GetWidth(); int TexHeight = Tex->GetHeight(); int TexSOffset = Tex->SOffset; int TexTOffset = Tex->TOffset; TVec sv[4]; TVec start = -TexSOffset * sprright * thing->ScaleX; TVec end = (TexWidth - TexSOffset) * sprright * thing->ScaleX; if (r_fix_sprite_offsets && TexTOffset < TexHeight && 2 * TexTOffset + r_sprite_fix_delta >= TexHeight) { TexTOffset = TexHeight; } TVec topdelta = TexTOffset * sprup * thing->ScaleY; TVec botdelta = (TexTOffset - TexHeight) * sprup * thing->ScaleY; sv[0] = sprorigin + start + botdelta; sv[1] = sprorigin + start + topdelta; sv[2] = sprorigin + end + topdelta; sv[3] = sprorigin + end + botdelta; if (Alpha < 1.0 || Additive || r_sort_sprites) { DrawTranslucentPoly(NULL, sv, 4, lump, Alpha, Additive, thing->Translation, true, light, Fade, -sprforward, DotProduct( sprorigin, -sprforward), (flip ? -sprright : sprright) / thing->ScaleX, -sprup / thing->ScaleY, flip ? sv[2] : sv[1]); } else { Drawer->DrawSpritePolygon(sv, GTextureManager[lump], Alpha, Additive, GetTranslation(thing->Translation), ColourMap, light, Fade, -sprforward, DotProduct(sprorigin, -sprforward), (flip ? -sprright : sprright) / thing->ScaleX, -sprup / thing->ScaleY, flip ? sv[2] : sv[1]); } unguard; } //========================================================================== // // VRenderLevelShared::RenderTranslucentAliasModel // //========================================================================== void VRenderLevelShared::RenderTranslucentAliasModel(VEntity* mobj, vuint32 light, vuint32 Fade, float Alpha, bool Additive, float TimeFrac) { guard(VRenderLevelShared::RenderTranslucentAliasModel); int i; float dist = fabs(DotProduct(mobj->Origin - vieworg, viewforward)); int found = -1; float best_dist = -1; for (i = 0; i < MAX_TRANS_SPRITES; i++) { trans_sprite_t &spr = trans_sprites[i]; if (!spr.Alpha) { spr.Ent = mobj; spr.light = light; spr.Fade = Fade; spr.Alpha = Alpha; spr.Additive = Additive; spr.dist = dist; spr.type = 2; spr.TimeFrac = TimeFrac; return; } if (spr.dist > best_dist) { found = i; best_dist = spr.dist; } } if (best_dist > dist) { // All slots are full, draw and replace a far away sprite trans_sprite_t &spr = trans_sprites[found]; if (spr.type == 2) { DrawEntityModel(spr.Ent, spr.light, spr.Fade, spr.Alpha, spr.Additive, spr.TimeFrac, RPASS_Normal); } else if (spr.type) { Drawer->DrawSpritePolygon(spr.Verts, GTextureManager[spr.lump], spr.Alpha, spr.Additive, GetTranslation(spr.translation), ColourMap, spr.light, spr.Fade, spr.normal, spr.pdist, spr.saxis, spr.taxis, spr.texorg); } else { check(spr.surf); Drawer->DrawMaskedPolygon(spr.surf, spr.Alpha, spr.Additive); } spr.Ent = mobj; spr.light = light; spr.Fade = Fade; spr.Alpha = Alpha; spr.Additive = Additive; spr.dist = dist; spr.type = 2; spr.TimeFrac = TimeFrac; return; } DrawEntityModel(mobj, light, Fade, Alpha, Additive, TimeFrac, RPASS_Normal); unguard; } //========================================================================== // // VRenderLevelShared::RenderAliasModel // //========================================================================== bool VRenderLevelShared::RenderAliasModel(VEntity* mobj, vuint32 light, vuint32 Fade, float Alpha, bool Additive, ERenderPass Pass) { guard(VRenderLevelShared::RenderAliasModel); if (!r_models) { return false; } float TimeFrac = 0; if (mobj->State->Time > 0) { TimeFrac = 1.0 - (mobj->StateTime / mobj->State->Time); TimeFrac = MID(0.0, TimeFrac, 1.0); } // Draw it if (Alpha < 1.0 || Additive) { if (!CheckAliasModelFrame(mobj, TimeFrac)) { return false; } RenderTranslucentAliasModel(mobj, light, Fade, Alpha, Additive, TimeFrac); return true; } else { return DrawEntityModel(mobj, light, Fade, 1.0, false, TimeFrac, Pass); } unguard; } //========================================================================== // // VRenderLevelShared::RenderThing // //========================================================================== void VRenderLevelShared::RenderThing(VEntity* mobj, ERenderPass Pass) { guard(VRenderLevelShared::RenderThing); if (mobj == ViewEnt && (!r_chasecam || ViewEnt != cl->MO)) { // Don't draw camera actor. return; } if ((mobj->EntityFlags & VEntity::EF_NoSector) || (mobj->EntityFlags & VEntity::EF_Invisible)) { return; } if (!mobj->State) { return; } // Skip things in subsectors that are not visible. int SubIdx = mobj->SubSector - Level->Subsectors; if (!(BspVis[SubIdx >> 3] & (1 << (SubIdx & 7)))) { return; } int RendStyle = mobj->RenderStyle; float Alpha = mobj->Alpha; bool Additive = false; if (RendStyle == STYLE_SoulTrans) { RendStyle = STYLE_Translucent; Alpha = transsouls; } else if (RendStyle == STYLE_OptFuzzy) { RendStyle = r_drawfuzz ? STYLE_Fuzzy : STYLE_Translucent; } switch (RendStyle) { case STYLE_None: return; case STYLE_Normal: Alpha = 1.0; break; case STYLE_Fuzzy: Alpha = 0.1; break; case STYLE_Add: Additive = true; break; } Alpha = MID(0.0, Alpha, 1.0); if (!Alpha) { // Never make a vissprite when MF2_DONTDRAW is flagged. return; } // Setup lighting vuint32 light; if (RendStyle == STYLE_Fuzzy) { light = 0; } else if ((mobj->State->Frame & VState::FF_FULLBRIGHT) || (mobj->EntityFlags & (VEntity::EF_FullBright | VEntity::EF_Bright))) { light = 0xffffffff; } else { light = LightPoint(mobj->Origin); } vuint32 Fade = GetFade(SV_PointInRegion(mobj->Sector, mobj->Origin)); // Try to draw a model. If it's a script and it doesn't // specify model for this frame, draw sprite instead. if (!RenderAliasModel(mobj, light, Fade, Alpha, Additive, Pass)) { RenderSprite(mobj, light, Fade, Alpha, Additive); } unguard; } //========================================================================== // // VRenderLevelShared::RenderMobjs // //========================================================================== void VRenderLevelShared::RenderMobjs(ERenderPass Pass) { guard(VRenderLevelShared::RenderMobjs); if (!r_draw_mobjs) { return; } for (TThinkerIterator Ent(Level); Ent; ++Ent) { RenderThing(*Ent, Pass); } unguard; } //========================================================================== // // VRenderLevelShared::DrawTranslucentPolys // //========================================================================== void VRenderLevelShared::DrawTranslucentPolys() { guard(VRenderLevelShared::DrawTranslucentPolys); int i, found; do { found = -1; float best_dist = -1; for (i = 0; i < MAX_TRANS_SPRITES; i++) { trans_sprite_t &spr = trans_sprites[i]; if (!spr.Alpha) { continue; } if (spr.dist > best_dist) { found = i; best_dist = spr.dist; } } if (found != -1) { trans_sprite_t &spr = trans_sprites[found]; if (spr.type == 2) { DrawEntityModel(spr.Ent, spr.light, spr.Fade, spr.Alpha, spr.Additive, spr.TimeFrac, RPASS_Normal); } else if (spr.type) { Drawer->DrawSpritePolygon(spr.Verts, GTextureManager[spr.lump], spr.Alpha, spr.Additive, GetTranslation(spr.translation), ColourMap, spr.light, spr.Fade, spr.normal, spr.pdist, spr.saxis, spr.taxis, spr.texorg); } else { check(spr.surf); Drawer->DrawMaskedPolygon(spr.surf, spr.Alpha, spr.Additive); } spr.Alpha = 0; } } while (found != -1); unguard; } //========================================================================== // // VRenderLevelShared::RenderPSprite // //========================================================================== void VRenderLevelShared::RenderPSprite(VViewState* VSt, float PSP_DIST, vuint32 light, vuint32 Fade, float Alpha, bool Additive) { guard(VRenderLevelShared::RenderPSprite); spritedef_t* sprdef; spriteframe_t* sprframe; int lump; bool flip; // decide which patch to use if ((vuint32)VSt->State->SpriteIndex >= MAX_SPRITE_MODELS) { #ifdef PARANOID GCon->Logf("R_ProjectSprite: invalid sprite number %d", VSt->State->SpriteIndex); #endif return; } sprdef = &sprites[VSt->State->SpriteIndex]; if ((VSt->State->Frame & VState::FF_FRAMEMASK) >= sprdef->numframes) { #ifdef PARANOID GCon->Logf("R_ProjectSprite: invalid sprite frame %d : %d", VSt->State->SpriteIndex, VSt->State->Frame); #endif return; } sprframe = &sprdef->spriteframes[VSt->State->Frame & VState::FF_FRAMEMASK]; lump = sprframe->lump[0]; flip = sprframe->flip[0]; VTexture* Tex = GTextureManager[lump]; int TexWidth = Tex->GetWidth(); int TexHeight = Tex->GetHeight(); int TexSOffset = Tex->SOffset; int TexTOffset = Tex->TOffset; TVec dv[4]; float PSP_DISTI = 1.0 / PSP_DIST; TVec sprorigin = vieworg + PSP_DIST * viewforward; float sprx = 160.0 - VSt->SX + TexSOffset; float spry = 100.0 - VSt->SY + TexTOffset; spry -= cl->PSpriteSY; // 1 / 160 = 0.00625 TVec start = sprorigin - (sprx * PSP_DIST * 0.00625) * viewright; TVec end = start + (TexWidth * PSP_DIST * 0.00625) * viewright; // 1 / 160.0 * 120 / 100 = 0.0075 TVec topdelta = (spry * PSP_DIST * 0.0075) * viewup; TVec botdelta = topdelta - (TexHeight * PSP_DIST * 0.0075) * viewup; if (aspect_ratio > 1) { topdelta *= 100.0 / 120.0; botdelta *= 100.0 / 120.0; } dv[0] = start + botdelta; dv[1] = start + topdelta; dv[2] = end + topdelta; dv[3] = end + botdelta; TVec saxis; TVec taxis; TVec texorg; if (flip) { saxis = -(viewright * 160 * PSP_DISTI); texorg = dv[2]; } else { saxis = viewright * 160 * PSP_DISTI; texorg = dv[1]; } if (aspect_ratio == 0) { taxis = -(viewup * 160 * PSP_DISTI); } else if (aspect_ratio == 1) { taxis = -(viewup * 100 * 4 / 3 * PSP_DISTI); } else if (aspect_ratio == 2) { taxis = -(viewup * 100 * 16 / 9 * PSP_DISTI); } else if (aspect_ratio > 2) { taxis = -(viewup * 100 * 16 / 10 * PSP_DISTI); } Drawer->DrawSpritePolygon(dv, GTextureManager[lump], Alpha, Additive, 0, ColourMap, light, Fade, -viewforward, DotProduct(dv[0], -viewforward), saxis, taxis, texorg); unguard; } //========================================================================== // // VRenderLevelShared::RenderViewModel // //========================================================================== bool VRenderLevelShared::RenderViewModel(VViewState* VSt, vuint32 light, vuint32 Fade, float Alpha, bool Additive) { guard(VRenderLevelShared::RenderViewModel); if (!r_view_models) { return false; } TVec origin = vieworg + (VSt->SX - 1.0) * viewright / 8.0 - (VSt->SY - 32.0) * viewup / 6.0; float TimeFrac = 0; if (VSt->State->Time > 0) { TimeFrac = 1.0 - (VSt->StateTime / VSt->State->Time); TimeFrac = MID(0.0, TimeFrac, 1.0); } bool Interpolate; // Check if we want to interpolate model frames if (!r_interpolate_frames) { Interpolate = false; } else { Interpolate = true; } return DrawAliasModel(origin, cl->ViewAngles, 1.0, 1.0, VSt->State, VSt->State->NextState ? VSt->State->NextState : VSt->State, NULL, 0, light, Fade, Alpha, Additive, true, TimeFrac, Interpolate, RPASS_Normal); unguard; } //========================================================================== // // VRenderLevelShared::DrawPlayerSprites // //========================================================================== void VRenderLevelShared::DrawPlayerSprites() { guard(VRenderLevelShared::DrawPlayerSprites); if (!r_draw_psprites || r_chasecam) { return; } int RendStyle = STYLE_Normal; float Alpha = 1.0; bool Additive = false; cl->MO->eventGetViewEntRenderParams(Alpha, RendStyle); if (RendStyle == STYLE_SoulTrans) { RendStyle = STYLE_Translucent; Alpha = transsouls; } else if (RendStyle == STYLE_OptFuzzy) { RendStyle = r_drawfuzz ? STYLE_Fuzzy : STYLE_Translucent; } switch (RendStyle) { case STYLE_None: return; case STYLE_Normal: Alpha = 1.0; break; case STYLE_Fuzzy: Alpha = 0.1; break; case STYLE_Add: Additive = true; break; } Alpha = MID(0.0, Alpha, 1.0); // add all active psprites for (int i = 0; i < NUMPSPRITES; i++) { if (!cl->ViewStates[i].State) { continue; } vuint32 light; if (RendStyle == STYLE_Fuzzy) { light = 0; } else if (cl->ViewStates[i].State->Frame & VState::FF_FULLBRIGHT) { light = 0xffffffff; } else { light = LightPoint(vieworg); } vuint32 Fade = GetFade(SV_PointInRegion(r_viewleaf->sector, cl->ViewOrg)); if (!RenderViewModel(&cl->ViewStates[i], light, Fade, Alpha, Additive)) { RenderPSprite(&cl->ViewStates[i], 3 - i, light, Fade, Alpha, Additive); } } unguard; } //========================================================================== // // VRenderLevelShared::DrawCroshair // //========================================================================== void VRenderLevelShared::DrawCroshair() { guard(VRenderLevelShared::DrawCroshair); if (croshair) { if (croshair_alpha < 0.0) croshair_alpha = 0.0; if (croshair_alpha > 1.0) croshair_alpha = 1.0; int cy; if (screenblocks < 11) cy = (480 - sb_height) / 2; else cy = 240; int handle = GTextureManager.AddPatch(VName(va("CROSHAI%i", (int)croshair), VName::AddLower8), TEXTYPE_Pic); R_DrawPic(320, cy, handle, croshair_alpha); } unguard; } //========================================================================== // // R_DrawSpritePatch // //========================================================================== void R_DrawSpritePatch(int x, int y, int sprite, int frame, int rot, int TranslStart, int TranslEnd, int Colour) { guard(R_DrawSpritePatch); bool flip; int lump; spriteframe_t *sprframe = &sprites[sprite].spriteframes[frame & VState::FF_FRAMEMASK]; flip = sprframe->flip[rot]; lump = sprframe->lump[rot]; VTexture* Tex = GTextureManager[lump]; Tex->GetWidth(); float x1 = x - Tex->SOffset; float y1 = y - Tex->TOffset; float x2 = x1 + Tex->GetWidth(); float y2 = y1 + Tex->GetHeight(); x1 *= fScaleX; y1 *= fScaleY; x2 *= fScaleX; y2 *= fScaleY; Drawer->DrawSpriteLump(x1, y1, x2, y2, Tex, R_GetCachedTranslation( R_SetMenuPlayerTrans(TranslStart, TranslEnd, Colour), NULL), flip); unguard; }