Isometric Mode and Robin (#2618)
* Feature-complete isometric mode fork. * Dithered transparency condition tweaks. * Dithered transparency for non-corpse monsters only (and missiles). * SpectatorCamera vertical shift. * Including math.h in hw_sprites.cpp to keep visual studio happy (it couldn't find M_SQRT2 definition). * Defining MY_SQRT2 in hw_sprites.cpp to keep visual studio happy (it couldn't find M_SQRT2 definition). * Defining MY_SQRT2 in r_utility.cpp also to keep visual studio happy. * retrigger checks * Have correct sprite angle-frame face the camera with orthographic projection enabled. * Dithered Transparency now works properly on 3D floors. Moved that dither-trans flag setting code within hw_bsp.cpp to handle double-processing of linedefs. Added helper functions to FRenderViewpoint class 'bool IsOrtho()' and 'bool IsAllowedOoB()' to clean up checks everywhere in the code. * Fixed indents. Added bbox property to subsector struct and use it instead of BSP nodes and Clippers (creating a bbox around viewpoint and checking for overlap) in orthographic mode when no fog of war is active. Turns out to be much faster. Though you need really big maps (Winter's Fury MAP01) to see a difference in fps. * Non-linux checks don't like uint. Changed to unsigned int. * Small change of a float to camera.zs. Ignore for testing. Should make no difference. * Update actor.h to remain mergeable RF2_NOMIPMAP was introduced, so I had to displace RF_ISOMETRICSPRITES to next bit.
This commit is contained in:
parent
b044baf850
commit
95b264bdb6
33 changed files with 819 additions and 84 deletions
|
|
@ -65,6 +65,7 @@ extern TArray<spriteframe_t> SpriteFrames;
|
|||
extern uint32_t r_renderercaps;
|
||||
|
||||
const float LARGE_VALUE = 1e19f;
|
||||
const float MY_SQRT2 = 1.41421356237309504880; // sqrt(2)
|
||||
|
||||
EXTERN_CVAR(Bool, r_debug_disable_vis_filter)
|
||||
EXTERN_CVAR(Float, transsouls)
|
||||
|
|
@ -494,7 +495,7 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp)
|
|||
}
|
||||
else // traditional "Y" billboard mode
|
||||
{
|
||||
if (doRoll || !offset.isZero())
|
||||
if (doRoll || !offset.isZero() || (actor && (actor->renderflags2 & RF2_ISOMETRICSPRITES)))
|
||||
{
|
||||
mat.MakeIdentity();
|
||||
|
||||
|
|
@ -516,6 +517,16 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp)
|
|||
mat.Translate(-center.X, -center.Z, -center.Y);
|
||||
}
|
||||
|
||||
if (actor && (actor->renderflags2 & RF2_ISOMETRICSPRITES) && di->Viewpoint.IsOrtho())
|
||||
{
|
||||
float angleRad = (FAngle::fromDeg(270.) - HWAngles.Yaw).Radians();
|
||||
mat.Translate(center.X, center.Z, center.Y);
|
||||
mat.Translate(0.0, z2 - center.Z, 0.0);
|
||||
mat.Rotate(-sin(angleRad), 0, cos(angleRad), -actor->isotheta);
|
||||
mat.Translate(0.0, center.Z - z2, 0.0);
|
||||
mat.Translate(-center.X, -center.Z, -center.Y);
|
||||
}
|
||||
|
||||
v[0] = mat * FVector3(x1, z1, y1);
|
||||
v[1] = mat * FVector3(x2, z1, y2);
|
||||
v[2] = mat * FVector3(x1, z2, y1);
|
||||
|
|
@ -911,6 +922,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
{
|
||||
bool mirror = false;
|
||||
DAngle ang = (thingpos - vp.Pos).Angle();
|
||||
if (di->Viewpoint.IsOrtho()) ang = vp.Angles.Yaw;
|
||||
FTextureID patch;
|
||||
// [ZZ] add direct picnum override
|
||||
if (isPicnumOverride)
|
||||
|
|
@ -1004,7 +1016,25 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
if (thing->renderflags & RF_SPRITEFLIP) // [SP] Flip back
|
||||
thing->renderflags ^= RF_XFLIP;
|
||||
|
||||
r.Scale(sprscale.X, isSpriteShadow ? sprscale.Y * 0.15 : sprscale.Y);
|
||||
// If sprite is isometric, do both vertical scaling and partial rotation to face the camera to compensate for Y-billboarding.
|
||||
// Using just rotation (about z=0) might cause tall+slender (high aspect ratio) sprites to clip out of collision box
|
||||
// at the top and clip into whatever is behind them from the viewpoint's perspective. - [DVR]
|
||||
thing->isoscaleY = 1.0;
|
||||
thing->isotheta = vp.HWAngles.Pitch.Degrees();
|
||||
if (thing->renderflags2 & RF2_ISOMETRICSPRITES)
|
||||
{
|
||||
float floordist = thing->radius * vp.floordistfact;
|
||||
floordist -= 0.5 * r.width * vp.cotfloor;
|
||||
float sineisotheta = floordist / r.height;
|
||||
double scl = g_sqrt( 1.0 + sineisotheta * sineisotheta - 2.0 * vp.PitchSin * sineisotheta );
|
||||
if ((thing->radius > 0.0) && (scl > fabs(vp.PitchCos)))
|
||||
{
|
||||
thing->isoscaleY = scl / ( fabs(vp.PitchCos) > 0.01 ? fabs(vp.PitchCos) : 0.01 );
|
||||
thing->isotheta = 180.0 * asin( sineisotheta / thing->isoscaleY ) / M_PI;
|
||||
}
|
||||
}
|
||||
|
||||
r.Scale(sprscale.X, isSpriteShadow ? sprscale.Y * 0.15 * thing->isoscaleY : sprscale.Y * thing->isoscaleY);
|
||||
|
||||
if (thing->renderflags & (RF_ROLLSPRITE|RF_FLATSPRITE))
|
||||
{
|
||||
|
|
@ -1018,7 +1048,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
z1 = z - r.top;
|
||||
z2 = z1 - r.height;
|
||||
|
||||
float spriteheight = sprscale.Y * r.height;
|
||||
float spriteheight = sprscale.Y * r.height * thing->isoscaleY;
|
||||
|
||||
// Tests show that this doesn't look good for many decorations and corpses
|
||||
if (spriteheight > 0 && gl_spriteclip > 0 && (thing->renderflags & RF_SPRITETYPEMASK) == RF_FACESPRITE)
|
||||
|
|
@ -1037,6 +1067,13 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
x2 = x - viewvecY*rightfac;
|
||||
y1 = y + viewvecX*leftfac;
|
||||
y2 = y + viewvecX*rightfac;
|
||||
if (thing->renderflags2 & RF2_ISOMETRICSPRITES) // If sprites are drawn from an isometric perspective
|
||||
{
|
||||
x1 -= viewvecX * thing->radius * MY_SQRT2;
|
||||
x2 -= viewvecX * thing->radius * MY_SQRT2;
|
||||
y1 -= viewvecY * thing->radius * MY_SQRT2;
|
||||
y2 -= viewvecY * thing->radius * MY_SQRT2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RF_FLATSPRITE:
|
||||
|
|
@ -1077,6 +1114,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t
|
|||
}
|
||||
|
||||
depth = (float)((x - vp.Pos.X) * vp.TanCos + (y - vp.Pos.Y) * vp.TanSin);
|
||||
if(thing->renderflags2 & RF2_ISOMETRICSPRITES) depth = depth * vp.PitchCos - vp.PitchSin * z2; // Helps with stacking actors with small xy offsets
|
||||
if (isSpriteShadow) depth += 1.f/65536.f; // always sort shadows behind the sprite.
|
||||
|
||||
// light calculation
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue