diff --git a/src/hardware/hw_clip.c b/src/hardware/hw_clip.c index 4bdc753ec..a63527083 100644 --- a/src/hardware/hw_clip.c +++ b/src/hardware/hw_clip.c @@ -72,6 +72,7 @@ #include "../v_video.h" #include "hw_clip.h" #include "hw_glob.h" +#include "../r_main.h" #include "../r_state.h" #include "../tables.h" #include "r_opengl/r_opengl.h" @@ -328,7 +329,7 @@ angle_t gld_FrustumAngle(void) // NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function - float render_fov = FIXED_TO_FLOAT(cv_grfov.value); + float render_fov = FIXED_TO_FLOAT(cv_fov.value); float render_fovratio = (float)BASEVIDWIDTH / (float)BASEVIDHEIGHT; // SRB2CBTODO: NEWCLIPTODO: Is this right? float render_multiplier = 64.0f / render_fovratio / RMUL; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 3da803ef6..74be53db5 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5530,6 +5530,7 @@ static void HWR_ProjectSprite(mobj_t *thing) spritedef_t *sprdef; spriteframe_t *sprframe; spriteinfo_t *sprinfo; + md2_t *md2; size_t lumpoff; unsigned rot; UINT16 flip; @@ -5561,8 +5562,21 @@ static void HWR_ProjectSprite(mobj_t *thing) tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin); // thing is behind view plane? - if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmodels.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear - return; + if (tz < ZCLIP_PLANE && !papersprite) + { + if (cv_grmodels.value) //Yellow: Only MD2's dont disappear + { + if (thing->skin && thing->sprite == SPR_PLAY) + md2 = &md2_playermodels[( (skin_t *)thing->skin - skins )]; + else + md2 = &md2_models[thing->sprite]; + + if (md2->notfound || md2->scale < 0.0f) + return; + } + else + return; + } // The above can stay as it works for cutting sprites that are too close tr_x = FIXED_TO_FLOAT(thing->x); @@ -5930,7 +5944,7 @@ static void HWR_DrawSkyBackground(player_t *player) if (cv_grskydome.value) { FTransform dometransform; - const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); + const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd); postimg_t *type; if (splitscreen && player == &players[secondarydisplayplayer]) @@ -6108,7 +6122,7 @@ void HWR_SetViewSize(void) // ========================================================================== void HWR_RenderSkyboxView(INT32 viewnumber, player_t *player) { - const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); + const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd); postimg_t *type; if (splitscreen && player == &players[secondarydisplayplayer]) @@ -6234,7 +6248,7 @@ if (0) viewangle = localaiming2; // Handle stuff when you are looking farther up or down. - if ((aimingangle || cv_grfov.value+player->fovadd > 90*FRACUNIT)) + if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) { dup_viewangle += ANGLE_90; HWR_ClearClipSegs(); @@ -6312,7 +6326,7 @@ if (0) // ========================================================================== void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) { - const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd); + const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd); postimg_t *type; const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on @@ -6454,7 +6468,7 @@ if (0) viewangle = localaiming2; // Handle stuff when you are looking farther up or down. - if ((aimingangle || cv_grfov.value+player->fovadd > 90*FRACUNIT)) + if ((aimingangle || cv_fov.value+player->fovadd > 90*FRACUNIT)) { dup_viewangle += ANGLE_90; HWR_ClearClipSegs(); @@ -6583,9 +6597,7 @@ static void CV_grmodellighting_OnChange(void); static void CV_grfiltermode_OnChange(void); static void CV_granisotropic_OnChange(void); static void CV_grfogdensity_OnChange(void); -static void CV_grfov_OnChange(void); -static CV_PossibleValue_t grfov_cons_t[] = {{0, "MIN"}, {179*FRACUNIT, "MAX"}, {0, NULL}}; static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"}, {HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"}, {HWD_SET_TEXTUREFILTER_MIXED1, "Linear_Nearest"}, @@ -6594,7 +6606,7 @@ static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSA {0, NULL}}; CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}}; -consvar_t cv_grfovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_fovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfog = {"gr_fog", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfogcolor = {"gr_fogcolor", "AAAAAA", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grsoftwarefog = {"gr_softwarefog", "Off", CV_SAVE, grsoftwarefog_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -6615,7 +6627,6 @@ consvar_t cv_grskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, consvar_t cv_grfakecontrast = {"gr_fakecontrast", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grrounddown = {"gr_rounddown", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfov = {"gr_fov", "90", CV_FLOAT|CV_CALL, grfov_cons_t, CV_grfov_OnChange, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_grfogdensity = {"gr_fogdensity", "150", CV_CALL|CV_NOINIT, CV_Unsigned, CV_grfogdensity_OnChange, 0, NULL, NULL, 0, 0, NULL}; @@ -6651,17 +6662,10 @@ static void CV_granisotropic_OnChange(void) HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value); } -static void CV_grfov_OnChange(void) -{ - if ((netgame || multiplayer) && !cv_debug && cv_grfov.value != 90*FRACUNIT) - CV_Set(&cv_grfov, cv_grfov.defaultvalue); -} - //added by Hurdler: console varibale that are saved void HWR_AddCommands(void) { - CV_RegisterVar(&cv_grfovchange); - CV_RegisterVar(&cv_grfov); + CV_RegisterVar(&cv_fovchange); CV_RegisterVar(&cv_grfogdensity); CV_RegisterVar(&cv_grfogcolor); diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index 20ff3ad9f..ec5362194 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -84,7 +84,6 @@ extern consvar_t cv_grstaticlighting; extern consvar_t cv_grcoronas; extern consvar_t cv_grcoronasize; #endif -extern consvar_t cv_grfov; extern consvar_t cv_grmodels; extern consvar_t cv_grmodelinterpolation; extern consvar_t cv_grmodellighting; @@ -95,7 +94,7 @@ extern consvar_t cv_grsoftwarefog; extern consvar_t cv_grfiltermode; extern consvar_t cv_granisotropicmode; extern consvar_t cv_grcorrecttricks; -extern consvar_t cv_grfovchange; +extern consvar_t cv_fovchange; extern consvar_t cv_grsolvetjoin; extern consvar_t cv_grspritebillboarding; extern consvar_t cv_grskydome; diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index 327dbd3df..becce9fa3 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -2222,11 +2222,11 @@ EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, EXPORT void HWRAPI(SetTransform) (FTransform *stransform) { static boolean special_splitscreen; + float used_fov; pglLoadIdentity(); if (stransform) { - boolean fovx90; - + used_fov = stransform->fovxangle; #ifdef USE_FTRANSFORM_MIRROR // mirroring from Kart if (stransform->mirror) @@ -2242,32 +2242,28 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) pglRotatef(stransform->angley+270.0f, 0.0f, 1.0f, 0.0f); pglTranslatef(-stransform->x, -stransform->z, -stransform->y); - pglMatrixMode(GL_PROJECTION); - pglLoadIdentity(); - fovx90 = stransform->fovxangle > 0.0f && fabsf(stransform->fovxangle - 90.0f) < 0.5f; - special_splitscreen = (stransform->splitscreen && fovx90); - if (special_splitscreen) - GLPerspective(53.13f, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5) - else - GLPerspective(stransform->fovxangle, ASPECT_RATIO); - pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) - pglMatrixMode(GL_MODELVIEW); + special_splitscreen = stransform->splitscreen; } else { + used_fov = fov; pglScalef(1.0f, 1.0f, -1.0f); - - pglMatrixMode(GL_PROJECTION); - pglLoadIdentity(); - if (special_splitscreen) - GLPerspective(53.13f, 2*ASPECT_RATIO); // 53.13 = 2*atan(0.5) - else - //Hurdler: is "fov" correct? - GLPerspective(fov, ASPECT_RATIO); - pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) - pglMatrixMode(GL_MODELVIEW); } + pglMatrixMode(GL_PROJECTION); + pglLoadIdentity(); + + if (special_splitscreen) + { + used_fov = atan(tan(used_fov*M_PI/360)*0.8)*360/M_PI; + GLPerspective(used_fov, 2*ASPECT_RATIO); + } + else + GLPerspective(used_fov, ASPECT_RATIO); + + pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) + pglMatrixMode(GL_MODELVIEW); + pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) } diff --git a/src/m_menu.c b/src/m_menu.c index f2287177f..d9ea6bae1 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1397,7 +1397,7 @@ static menuitem_t OP_OpenGLOptionsMenu[] = {IT_STRING|IT_CVAR, NULL, "Model lighting", &cv_grmodellighting, 32}, {IT_HEADER, NULL, "General", NULL, 51}, - {IT_STRING|IT_CVAR, NULL, "Field of view", &cv_grfov, 63}, + {IT_STRING|IT_CVAR, NULL, "Field of view", &cv_fov, 63}, {IT_STRING|IT_CVAR, NULL, "Quality", &cv_scr_depth, 73}, {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 83}, {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode,93}, diff --git a/src/p_user.c b/src/p_user.c index 2bd856481..97d734a9e 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8672,7 +8672,7 @@ static void P_MovePlayer(player_t *player) } #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none && cv_grfovchange.value) + if (rendermode != render_soft && rendermode != render_none && cv_fovchange.value) { fixed_t speed; const fixed_t runnyspeed = 20*FRACUNIT; @@ -10105,13 +10105,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall { dist = camdist; - // x1.5 dist for splitscreen - if (splitscreen) - { - dist = FixedMul(dist, 3*FRACUNIT/2); - camheight = FixedMul(camheight, 3*FRACUNIT/2); - } - if (sign) // signpost camera has specific placement { camheight = mo->scale << 7; @@ -10511,13 +10504,17 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (!(multiplayer || netgame) && !splitscreen) { fixed_t vx = thiscam->x, vy = thiscam->y; + fixed_t vz = thiscam->z + thiscam->height / 2; if (player->awayviewtics && player->awayviewmobj != NULL && !P_MobjWasRemoved(player->awayviewmobj)) // Camera must obviously exist { vx = player->awayviewmobj->x; vy = player->awayviewmobj->y; + vz = player->awayviewmobj->z + player->awayviewmobj->height / 2; } - if (P_AproxDistance(vx - mo->x, vy - mo->y) < FixedMul(48*FRACUNIT, mo->scale)) + /* check z distance too for orbital camera */ + if (P_AproxDistance(P_AproxDistance(vx - mo->x, vy - mo->y), + vz - ( mo->z + mo->height / 2 )) < FixedMul(48*FRACUNIT, mo->scale)) mo->flags2 |= MF2_SHADOW; else mo->flags2 &= ~MF2_SHADOW; diff --git a/src/r_main.c b/src/r_main.c index a2674b543..3c6aaf6a6 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -59,6 +59,7 @@ INT32 centerx, centery; fixed_t centerxfrac, centeryfrac; fixed_t projection; fixed_t projectiony; // aspect ratio +fixed_t fovtan; // field of view // just for profiling purposes size_t framecount; @@ -108,10 +109,12 @@ static CV_PossibleValue_t drawdist_precip_cons_t[] = { {1024, "1024"}, {1536, "1536"}, {2048, "2048"}, {0, "None"}, {0, NULL}}; +static CV_PossibleValue_t fov_cons_t[] = {{60*FRACUNIT, "MIN"}, {179*FRACUNIT, "MAX"}, {0, NULL}}; static CV_PossibleValue_t translucenthud_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; static CV_PossibleValue_t maxportals_cons_t[] = {{0, "MIN"}, {12, "MAX"}, {0, NULL}}; // lmao rendering 32 portals, you're a card static CV_PossibleValue_t homremoval_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Flash"}, {0, NULL}}; +static void Fov_OnChange(void); static void ChaseCam_OnChange(void); static void ChaseCam2_OnChange(void); static void FlipCam_OnChange(void); @@ -141,6 +144,7 @@ consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, consvar_t cv_drawdist_nights = {"drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; //consvar_t cv_precipdensity = {"precipdensity", "Moderate", CV_SAVE, precipdensity_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL}; // Okay, whoever said homremoval causes a performance hit should be shot. consvar_t cv_homremoval = {"homremoval", "No", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -184,6 +188,14 @@ void SplitScreen_OnChange(void) } } } +static void Fov_OnChange(void) +{ + // Shouldn't be needed with render parity? + //if ((netgame || multiplayer) && !cv_debug && cv_fov.value != 90*FRACUNIT) + // CV_Set(&cv_fov, cv_fov.defaultvalue); + + R_SetViewSize(); +} static void ChaseCam_OnChange(void) { @@ -448,8 +460,8 @@ static void R_InitTextureMapping(void) // // Calc focallength // so FIELDOFVIEW angles covers SCREENWIDTH. - focallength = FixedDiv(centerxfrac, - FINETANGENT(FINEANGLES/4+/*cv_fov.value*/ FIELDOFVIEW/2)); + focallength = FixedDiv(projection, + FINETANGENT(FINEANGLES/4+FIELDOFVIEW/2)); #ifdef ESLOPE focallengthf = FIXED_TO_FLOAT(focallength); @@ -457,9 +469,9 @@ static void R_InitTextureMapping(void) for (i = 0; i < FINEANGLES/2; i++) { - if (FINETANGENT(i) > FRACUNIT*2) + if (FINETANGENT(i) > fovtan*2) t = -1; - else if (FINETANGENT(i) < -FRACUNIT*2) + else if (FINETANGENT(i) < -fovtan*2) t = viewwidth+1; else { @@ -563,6 +575,7 @@ void R_ExecuteSetViewSize(void) INT32 j; INT32 level; INT32 startmapl; + angle_t fov; setsizeneeded = false; @@ -585,9 +598,12 @@ void R_ExecuteSetViewSize(void) centerxfrac = centerx<> ANGLETOFINESHIFT); + if (splitscreen == 1) // Splitscreen FOV should be adjusted to maintain expected vertical view + fovtan = 17*fovtan/10; + + projection = projectiony = FixedDiv(centerxfrac, fovtan); R_InitViewBuffer(scaledviewwidth, viewheight); @@ -613,7 +629,7 @@ void R_ExecuteSetViewSize(void) for (i = 0; i < j; i++) { dy = ((i - viewheight*8)<>ANGLETOFINESHIFT)) & FINEMASK)*160)>>FRACBITS) +#define AIMINGTODY(a) FixedDiv((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160)>>FRACBITS, fovtan) // recalc necessary stuff for mouseaiming // slopes are already calculated for the full possible view (which is 4*viewheight). @@ -1203,6 +1219,7 @@ void R_RegisterEngineStuff(void) CV_RegisterVar(&cv_drawdist); CV_RegisterVar(&cv_drawdist_nights); CV_RegisterVar(&cv_drawdist_precip); + CV_RegisterVar(&cv_fov); CV_RegisterVar(&cv_chasecam); CV_RegisterVar(&cv_chasecam2); diff --git a/src/r_main.h b/src/r_main.h index 143cc1de0..998bb50ef 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -84,6 +84,7 @@ extern conscar_t cv_shadowoffs; #endif //#ifdef GLBADSHADOWS extern consvar_t cv_translucency; extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip; +extern consvar_t cv_fov; extern consvar_t cv_skybox; extern consvar_t cv_tailspickup; diff --git a/src/r_things.c b/src/r_things.c index d80d74d78..dd96e4f16 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -756,9 +756,7 @@ void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) static void R_DrawVisSprite(vissprite_t *vis) { column_t *column; -#ifdef RANGECHECK INT32 texturecolumn; -#endif fixed_t frac; patch_t *patch = vis->patch; fixed_t this_scale = vis->mobj->scale; @@ -906,28 +904,51 @@ static void R_DrawVisSprite(vissprite_t *vis) if (vis->x2 >= vid.width) vis->x2 = vid.width-1; - for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) + // Split drawing loops for paper and non-paper to reduce conditional checks per sprite + if (vis->scalestep) { -#ifdef RANGECHECK + // Papersprite drawing loop - texturecolumn = frac>>FRACBITS; - - if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) - I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); -#else - column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS])); -#endif - if (vis->scalestep) + for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, spryscale += vis->scalestep) { + angle_t angle = ((vis->centerangle + xtoviewangle[dc_x]) >> ANGLETOFINESHIFT) & 0xFFF; + texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / this_scale; + + if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + continue; + + if (vis->xiscale < 0) // Flipped sprite + texturecolumn = SHORT(patch->width) - 1 - texturecolumn; + sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); dc_iscale = (0xffffffffu / (unsigned)spryscale); + + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); + + if (vis->cut & SC_VFLIP) + R_DrawFlippedMaskedColumn(column, patch->height); + else + R_DrawMaskedColumn(column); + } + } + else + { + // Non-paper drawing loop + for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale) + { +#ifdef RANGECHECK + texturecolumn = frac>>FRACBITS; + if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); +#else + column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS])); +#endif + if (vis->cut & SC_VFLIP) + R_DrawFlippedMaskedColumn(column, patch->height); + else + R_DrawMaskedColumn(column); } - if (vis->cut & SC_VFLIP) - R_DrawFlippedMaskedColumn(column, patch->height); - else - R_DrawMaskedColumn(column); - spryscale += vis->scalestep; } colfunc = colfuncs[BASEDRAWFUNC]; @@ -1086,8 +1107,6 @@ static void R_SplitSprite(vissprite_t *sprite) } } -//#define PROPERPAPER // This was reverted less than 7 hours before 2.2's release because of very strange, frequent crashes. - // // R_ProjectSprite // Generates a vissprite for a thing @@ -1124,7 +1143,9 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t iscale; fixed_t scalestep; fixed_t offset, offset2; + boolean papersprite = !!(thing->frame & FF_PAPERSPRITE); + fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0; INT32 dispoffset = thing->info->dispoffset; @@ -1142,10 +1163,6 @@ static void R_ProjectSprite(mobj_t *thing) INT32 rollangle = 0; #endif -#ifndef PROPERPAPER - fixed_t ang_scale = FRACUNIT; -#endif - // transform the origin point tr_x = thing->x - viewx; tr_y = thing->y - viewy; @@ -1156,7 +1173,7 @@ static void R_ProjectSprite(mobj_t *thing) tz = gxt-gyt; // thing is behind view plane? - if (!(papersprite) && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later + if (!papersprite && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later return; gxt = -FixedMul(tr_x, viewsin); @@ -1164,7 +1181,7 @@ static void R_ProjectSprite(mobj_t *thing) tx = -(gyt + gxt); // too far off the side? - if (abs(tx) > tz<<2) + if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later return; // aspect ratio stuff @@ -1228,13 +1245,7 @@ static void R_ProjectSprite(mobj_t *thing) #endif if (sprframe->rotate != SRF_SINGLE || papersprite) - { ang = R_PointToAngle (thing->x, thing->y) - (thing->player ? thing->player->drawangle : thing->angle); -#ifndef PROPERPAPER - if (papersprite) - ang_scale = abs(FINESINE(ang>>ANGLETOFINESHIFT)); -#endif - } if (sprframe->rotate == SRF_SINGLE) { @@ -1300,31 +1311,11 @@ static void R_ProjectSprite(mobj_t *thing) else offset = -spr_offset; offset = FixedMul(offset, this_scale); -#ifndef PROPERPAPER - tx += FixedMul(offset, ang_scale); - x1 = (centerxfrac + FixedMul (tx,xscale)) >>FRACBITS; - - // off the right side? - if (x1 > viewwidth) - return; -#endif offset2 = FixedMul(spr_width, this_scale); -#ifndef PROPERPAPER - tx += FixedMul(offset2, ang_scale); - x2 = ((centerxfrac + FixedMul (tx,xscale)) >> FRACBITS) - (papersprite ? 2 : 1); - - // off the left side - if (x2 < 0) - return; -#endif if (papersprite) { - fixed_t -#ifdef PROPERPAPER - xscale2, -#endif - yscale2, cosmul, sinmul, tz2; + fixed_t xscale2, yscale2, cosmul, sinmul, tx2, tz2; INT32 range; if (ang >= ANGLE_180) @@ -1342,19 +1333,23 @@ static void R_ProjectSprite(mobj_t *thing) gyt = -FixedMul(tr_y, viewsin); tz = gxt-gyt; yscale = FixedDiv(projectiony, tz); - if (yscale < 64) return; // Fix some funky visuals + //if (yscale < 64) return; // Fix some funky visuals -#ifdef PROPERPAPER gxt = -FixedMul(tr_x, viewsin); gyt = FixedMul(tr_y, viewcos); tx = -(gyt + gxt); xscale = FixedDiv(projection, tz); x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; - // off the right side? - if (x1 > viewwidth) - return; -#endif + // Get paperoffset (offset) and paperoffset (distance) + paperoffset = -FixedMul(tr_x, cosmul) - FixedMul(tr_y, sinmul); + paperdistance = -FixedMul(tr_x, sinmul) + FixedMul(tr_y, cosmul); + if (paperdistance < 0) + { + paperoffset = -paperoffset; + paperdistance = -paperdistance; + } + centerangle = viewangle - thing->angle; tr_x += FixedMul(offset2, cosmul); tr_y += FixedMul(offset2, sinmul); @@ -1362,38 +1357,52 @@ static void R_ProjectSprite(mobj_t *thing) gyt = -FixedMul(tr_y, viewsin); tz2 = gxt-gyt; yscale2 = FixedDiv(projectiony, tz2); - if (yscale2 < 64) return; // ditto + //if (yscale2 < 64) return; // ditto -#ifdef PROPERPAPER gxt = -FixedMul(tr_x, viewsin); gyt = FixedMul(tr_y, viewcos); - tx = -(gyt + gxt); + tx2 = -(gyt + gxt); xscale2 = FixedDiv(projection, tz2); - x2 = (centerxfrac + FixedMul(tx,xscale2))>>FRACBITS; x2--; + x2 = ((centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS); + + if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier + return; + + // Needs partially clipped + if (tz < FixedMul(MINZ, this_scale)) + { + fixed_t div = FixedDiv(tz2-tz, FixedMul(MINZ, this_scale)-tz); + tx += FixedDiv(tx2-tx, div); + tz = FixedMul(MINZ, this_scale); + yscale = FixedDiv(projectiony, tz); + xscale = FixedDiv(projection, tz); + x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; + } + else if (tz2 < FixedMul(MINZ, this_scale)) + { + fixed_t div = FixedDiv(tz-tz2, FixedMul(MINZ, this_scale)-tz2); + tx2 += FixedDiv(tx-tx2, div); + tz2 = FixedMul(MINZ, this_scale); + yscale2 = FixedDiv(projectiony, tz2); + xscale2 = FixedDiv(projection, tz2); + x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS; + } + + // off the right side? + if (x1 > viewwidth) + return; // off the left side if (x2 < 0) return; -#endif - - if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier - return; if ((range = x2 - x1) <= 0) return; -#ifdef PROPERPAPER range++; // fencepost problem -#endif - scalestep = (yscale2 - yscale)/range; - xscale = -#ifdef PROPERPAPER - FixedDiv(range<>FRACBITS; @@ -1417,7 +1425,6 @@ static void R_ProjectSprite(mobj_t *thing) // off the left side if (x2 < 0) return; -#endif } if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) // toast 16/09/16 (SYMMETRY) @@ -1538,6 +1545,9 @@ static void R_ProjectSprite(mobj_t *thing) vis->pzt = vis->pz + vis->thingheight; vis->texturemid = vis->gzt - viewz; vis->scalestep = scalestep; + vis->paperoffset = paperoffset; + vis->paperdistance = paperdistance; + vis->centerangle = centerangle; vis->mobj = thing; // Easy access! Tails 06-07-2002 diff --git a/src/r_things.h b/src/r_things.h index b4ef66a62..d6af0fefa 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -177,8 +177,11 @@ typedef struct vissprite_s fixed_t startfrac; // horizontal position of x1 fixed_t scale, sortscale; // sortscale only differs from scale for paper sprites and MF2_LINKDRAW fixed_t scalestep; // only for paper sprites, 0 otherwise + fixed_t paperoffset, paperdistance; // for paper sprites, offset/dist relative to the angle fixed_t xiscale; // negative if flipped + angle_t centerangle; // for paper sprites + fixed_t texturemid; patch_t *patch;