This commit is contained in:
Rachael Alexanderson 2018-06-05 16:49:28 -04:00
commit 61c11e513b
20 changed files with 901 additions and 181 deletions

View file

@ -401,6 +401,7 @@ enum ActorFlag8
{
MF8_FRIGHTENING = 0x00000001, // for those moments when halloween just won't do
MF8_INSCROLLSEC = 0x00000002, // actor is partially inside a scrolling sector
MF8_BLOCKASPLAYER = 0x00000004, // actor is blocked by player-blocking lines even if not a player
};
// --- mobj.renderflags ---

View file

@ -210,44 +210,47 @@ void FDrawInfo::DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool
auto vcount = flat->sector->ibocount;
gl_RenderState.Apply();
auto iboindex = flat->iboindex;
if (gl.legacyMode)
{
processlights = false;
goto legacy;
iboindex = -1;
}
if (vcount > 0 && !gl_RenderState.GetClipLineShouldBeActive())
if (iboindex >= 0)
{
if (processlights) SetupSectorLights(flat, GLPASS_ALL, &dli);
drawcalls.Clock();
glDrawElements(GL_TRIANGLES, vcount, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + flat->iboindex);
drawcalls.Unclock();
flatvertices += vcount;
flatprimitives++;
}
else if (flat->iboindex >= 0)
{
int index = flat->iboindex;
for (int i=0; i<flat->sector->subsectorcount; i++)
if (vcount > 0 && !gl_RenderState.GetClipLineShouldBeActive())
{
subsector_t * sub = flat->sector->subsectors[i];
if (sub->numlines <= 2) continue;
if (ss_renderflags[sub->Index()]& flat->renderflags || istrans)
if (processlights) SetupSectorLights(flat, GLPASS_ALL, &dli);
drawcalls.Clock();
glDrawElements(GL_TRIANGLES, vcount, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + iboindex);
drawcalls.Unclock();
flatvertices += vcount;
flatprimitives++;
}
else
{
int index = iboindex;
for (int i = 0; i < flat->sector->subsectorcount; i++)
{
if (processlights) SetupSubsectorLights(flat, GLPASS_ALL, sub, &dli);
drawcalls.Clock();
glDrawElements(GL_TRIANGLES, (sub->numlines - 2) * 3, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + index);
drawcalls.Unclock();
flatvertices += sub->numlines;
flatprimitives++;
subsector_t * sub = flat->sector->subsectors[i];
if (sub->numlines <= 2) continue;
if (ss_renderflags[sub->Index()] & flat->renderflags || istrans)
{
if (processlights) SetupSubsectorLights(flat, GLPASS_ALL, sub, &dli);
drawcalls.Clock();
glDrawElements(GL_TRIANGLES, (sub->numlines - 2) * 3, GL_UNSIGNED_INT, GLRenderer->mVBO->GetIndexPointer() + index);
drawcalls.Unclock();
flatvertices += sub->numlines;
flatprimitives++;
}
index += (sub->numlines - 2) * 3;
}
index += (sub->numlines - 2) * 3;
}
}
else
{
legacy:
// Draw the subsectors belonging to this sector
for (int i=0; i<flat->sector->subsectorcount; i++)
{

View file

@ -46,6 +46,7 @@ struct FMemArena::Block
Block *NextBlock;
void *Limit; // End of this block
void *Avail; // Start of free space in this block
void *alignme; // align to 16 bytes.
void Reset();
void *Alloc(size_t size);
@ -94,7 +95,7 @@ FMemArena::~FMemArena()
//
//==========================================================================
void *FMemArena::Alloc(size_t size)
void *FMemArena::iAlloc(size_t size)
{
Block *block;
@ -110,6 +111,11 @@ void *FMemArena::Alloc(size_t size)
return block->Alloc(size);
}
void *FMemArena::Alloc(size_t size)
{
return iAlloc((size + 15) & ~15);
}
//==========================================================================
//
// FMemArena :: FreeAll
@ -316,7 +322,7 @@ FString *FSharedStringArena::Alloc(const FString &source)
strnode = FindString(source, source.Len(), hash);
if (strnode == NULL)
{
strnode = (Node *)FMemArena::Alloc(sizeof(Node));
strnode = (Node *)iAlloc(sizeof(Node));
::new(&strnode->String) FString(source);
strnode->Hash = hash;
hash %= countof(Buckets);
@ -351,7 +357,7 @@ FString *FSharedStringArena::Alloc(const char *source, size_t strlen)
strnode = FindString(source, strlen, hash);
if (strnode == NULL)
{
strnode = (Node *)FMemArena::Alloc(sizeof(Node));
strnode = (Node *)iAlloc(sizeof(Node));
::new(&strnode->String) FString(source, strlen);
strnode->Hash = hash;
hash %= countof(Buckets);

View file

@ -54,6 +54,7 @@ protected:
Block *AddBlock(size_t size);
void FreeBlockChain(Block *&top);
void *iAlloc(size_t size);
Block *TopBlock;
Block *FreeBlocks;

View file

@ -714,7 +714,9 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags)
tics = 1;
}
}
else
// The following condition is needed to avoid crash when player class has no death states
// Instance of player pawn will be garbage collected on reloading of level
else if (player == nullptr)
{
Destroy();
}

View file

@ -930,7 +930,10 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
bool NotBlocked = ((tm.thing->flags3 & MF3_NOBLOCKMONST)
|| ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY)));
if (!(Projectile) || (ld->flags & (ML_BLOCKEVERYTHING | ML_BLOCKPROJECTILE)))
uint32_t ProjectileBlocking = ML_BLOCKEVERYTHING | ML_BLOCKPROJECTILE;
if ( tm.thing->flags8 & MF8_BLOCKASPLAYER ) ProjectileBlocking |= ML_BLOCK_PLAYERS | ML_BLOCKING;
if (!(Projectile) || (ld->flags & ProjectileBlocking) )
{
if (ld->flags & ML_RAILING)
{
@ -938,7 +941,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
}
else if ((ld->flags & (ML_BLOCKING | ML_BLOCKEVERYTHING)) || // explicitly blocking everything
(!(NotBlocked) && (ld->flags & ML_BLOCKMONSTERS)) || // block monsters only
(tm.thing->player != NULL && (ld->flags & ML_BLOCK_PLAYERS)) || // block players
(((tm.thing->player != NULL) || (tm.thing->flags8 & MF8_BLOCKASPLAYER)) && (ld->flags & ML_BLOCK_PLAYERS)) || // block players
((Projectile) && (ld->flags & ML_BLOCKPROJECTILE)) || // block projectiles
((tm.thing->flags & MF_FLOAT) && (ld->flags & ML_BLOCK_FLOATERS))) // block floaters
{
@ -3100,7 +3103,7 @@ void FSlide::SlideTraverse(const DVector2 &start, const DVector2 &end)
{
goto isblocking;
}
if (li->flags & ML_BLOCK_PLAYERS && slidemo->player != NULL)
if (li->flags & ML_BLOCK_PLAYERS && ((slidemo->player != NULL) || (slidemo->flags8 & MF8_BLOCKASPLAYER)))
{
goto isblocking;
}
@ -4195,11 +4198,38 @@ struct aim_t
thingtoppitch = -VecToAngle(dist, th->Top() - shootz);
if (thingtoppitch > bottompitch)
continue; // shot over the thing
{
// Check for a hit from above
if (shootz > th->Top())
{
double exitfrac = ExitPoint(th);
if (exitfrac > 0.)
{
double exitdist = attackrange * exitfrac;
thingtoppitch = -VecToAngle(exitdist, th->Top() - shootz);
if (thingtoppitch > bottompitch) continue;
}
else continue; // shot over the thing
}
else continue; // shot over the thing
}
thingbottompitch = -VecToAngle(dist, th->Z() - shootz);
if (thingbottompitch < toppitch)
{
// Check for a hit from below
if (shootz < th->Z())
{
double exitfrac = ExitPoint(th);
if (exitfrac > 0.)
{
double exitdist = attackrange * exitfrac;
thingbottompitch = -VecToAngle(exitdist, th->Z() - shootz);
if (thingbottompitch < toppitch) continue;
}
else continue; // shot over the thing
}
continue; // shot under the thing
if (crossedffloors)

View file

@ -589,7 +589,15 @@ void P_GiveSecret(AActor *actor, bool printmessage, bool playsound, int sectornu
{
actor->player->secretcount++;
}
if (cl_showsecretmessage && actor->CheckLocalView(consoleplayer))
int retval = 1;
IFVIRTUALPTR(actor, AActor, OnGiveSecret)
{
VMValue params[] = { actor, printmessage, playsound };
VMReturn ret;
ret.IntAt(&retval);
VMCall(func, params, countof(params), &ret, 1);
}
if (retval && cl_showsecretmessage && actor->CheckLocalView(consoleplayer))
{
if (printmessage)
{
@ -616,6 +624,7 @@ DEFINE_ACTION_FUNCTION(AActor, GiveSecret)
return 0;
}
DEFINE_ACTION_FUNCTION(FLevelLocals, GiveSecret)
{
PARAM_PROLOGUE;

View file

@ -1157,7 +1157,7 @@ bool FPolyObj::CheckMobjBlocking (side_t *sd)
// [TN] Check wether this actor gets blocked by the line.
if (ld->backsector != NULL &&
!(ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING))
&& !(ld->flags & ML_BLOCK_PLAYERS && mobj->player)
&& !(ld->flags & ML_BLOCK_PLAYERS && (mobj->player || (mobj->flags8 & MF8_BLOCKASPLAYER)))
&& !(ld->flags & ML_BLOCKMONSTERS && mobj->flags3 & MF3_ISMONSTER)
&& !((mobj->flags & MF_FLOAT) && (ld->flags & ML_BLOCK_FLOATERS))
&& (!(ld->flags & ML_3DMIDTEX) ||

View file

@ -106,15 +106,24 @@ void PolyDrawArgs::SetLight(FSWColormap *base_colormap, uint32_t lightlevel, dou
mLight = clamp<uint32_t>(lightlevel, 0, 255);
mFixedLight = fixed;
mLightRed = base_colormap->Color.r * 256 / 255;
mLightGreen = base_colormap->Color.g * 256 / 255;
mLightBlue = base_colormap->Color.b * 256 / 255;
mLightAlpha = base_colormap->Color.a * 256 / 255;
mLightRed = base_colormap->Color.r;
mLightRed += mLightRed >> 7;
mLightGreen = base_colormap->Color.g;
mLightGreen += mLightGreen >> 7;
mLightBlue = base_colormap->Color.b;
mLightBlue += mLightBlue >> 7;
mLightAlpha = base_colormap->Color.a;
mLightAlpha += mLightAlpha >> 7;
mFadeRed = base_colormap->Fade.r;
mFadeRed += mFadeRed >> 7;
mFadeGreen = base_colormap->Fade.g;
mFadeGreen += mFadeGreen >> 7;
mFadeBlue = base_colormap->Fade.b;
mFadeBlue += mFadeBlue >> 7;
mFadeAlpha = base_colormap->Fade.a;
mDesaturate = MIN(abs(base_colormap->Desaturate), 255) * 255 / 256;
mFadeAlpha += mFadeAlpha >> 7;
mDesaturate = MIN(abs(base_colormap->Desaturate), 255);
mDesaturate += mDesaturate >> 7;
mSimpleShade = (base_colormap->Color.d == 0x00ffffff && base_colormap->Fade.d == 0x00000000 && base_colormap->Desaturate == 0);
mColormaps = base_colormap->Maps;
}

File diff suppressed because it is too large Load diff

View file

@ -757,8 +757,8 @@ static void CalcPosVel(int type, const AActor *actor, const sector_t *sector,
{
// listener must be reversely offset to calculate the proper sound origin.
CalcSectorSoundOrg(listenpos + disp, sector, channum, *pos);
pos->X += (float)disp.X;
pos->Z += (float)disp.Y;
pos->X -= (float)disp.X;
pos->Z -= (float)disp.Y;
}
else
{

View file

@ -316,6 +316,7 @@ static FFlagDef ActorFlagDefs[]=
DEFINE_FLAG(MF7, FORCEINFIGHTING, AActor, flags7),
DEFINE_FLAG(MF8, FRIGHTENING, AActor, flags8),
DEFINE_FLAG(MF8, BLOCKASPLAYER, AActor, flags8),
// Effect flags
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),

View file

@ -189,7 +189,12 @@ namespace swrenderer
{
auto viewport = Thread->Viewport.get();
drawerargs.dc_viewpos.X = (float)((x + 0.5 - viewport->CenterX) / viewport->CenterX * zcol);
int tx = x;
bool mirror = !!(Thread->Portal->MirrorFlags & RF_XFLIP);
if (mirror)
tx = viewwidth - tx - 1;
drawerargs.dc_viewpos.X = (float)((tx + 0.5 - viewport->CenterX) / viewport->CenterX * zcol);
drawerargs.dc_viewpos.Y = zcol;
drawerargs.dc_viewpos.Z = (float)((viewport->CenterY - y1 - 0.5) / viewport->InvZtoScale * zcol);
drawerargs.dc_viewpos_step.Z = (float)(-zcol / viewport->InvZtoScale);

View file

@ -205,13 +205,21 @@ namespace swrenderer
if (r_dynlights)
{
int tx = x1;
bool mirror = !!(Thread->Portal->MirrorFlags & RF_XFLIP);
if (mirror)
tx = viewwidth - tx - 1;
// Find row position in view space
float zspan = (float)(planeheight / (fabs(y + 0.5 - viewport->CenterY) / viewport->InvZtoScale));
drawerargs.dc_viewpos.X = (float)((x1 + 0.5 - viewport->CenterX) / viewport->CenterX * zspan);
drawerargs.dc_viewpos.X = (float)((tx + 0.5 - viewport->CenterX) / viewport->CenterX * zspan);
drawerargs.dc_viewpos.Y = zspan;
drawerargs.dc_viewpos.Z = (float)((viewport->CenterY - y - 0.5) / viewport->InvZtoScale * zspan);
drawerargs.dc_viewpos_step.X = (float)(zspan / viewport->CenterX);
if (mirror)
drawerargs.dc_viewpos_step.X = -drawerargs.dc_viewpos_step.X;
// Plane normal
drawerargs.dc_normal.X = 0.0f;
drawerargs.dc_normal.Y = 0.0f;

View file

@ -173,6 +173,7 @@ namespace swrenderer
Thread->Viewport->viewpoint.sector = port->mDestination;
assert(Thread->Viewport->viewpoint.sector != nullptr);
R_SetViewAngle(Thread->Viewport->viewpoint, Thread->Viewport->viewwindow);
Thread->Viewport->SetupPolyViewport(Thread);
Thread->OpaquePass->ClearSeenSprites();
Thread->Clip3D->ClearFakeFloors();
@ -239,6 +240,7 @@ namespace swrenderer
// Masked textures and planes need the view coordinates restored for proper positioning.
viewposStack.Pop(Thread->Viewport->viewpoint.Pos);
Thread->Viewport->SetupPolyViewport(Thread);
Thread->TranslucentPass->Render();
VisiblePlane *pl = nullptr; // quiet, GCC!
@ -259,6 +261,7 @@ namespace swrenderer
Thread->Viewport->viewpoint.extralight = savedextralight;
Thread->Viewport->viewpoint.Angles = savedangles;
R_SetViewAngle(Thread->Viewport->viewpoint, Thread->Viewport->viewwindow);
Thread->Viewport->SetupPolyViewport(Thread);
CurrentPortalInSkybox = false;
Thread->Clip3D->LeaveSkybox();
@ -426,6 +429,8 @@ namespace swrenderer
else MirrorFlags |= RF_XFLIP;
}
Thread->Viewport->SetupPolyViewport(Thread);
// some portals have height differences, account for this here
Thread->Clip3D->EnterSkybox(); // push 3D floor height map
CurrentPortalInSkybox = false; // first portal in a skybox should set this variable to false for proper clipping in skyboxes.
@ -478,6 +483,8 @@ namespace swrenderer
viewpoint.Pos = startpos;
viewpoint.Path[0] = savedpath[0];
viewpoint.Path[1] = savedpath[1];
viewport->SetupPolyViewport(Thread);
}
#if 0

View file

@ -159,6 +159,8 @@ namespace swrenderer
if (r_models)
MainThread()->Viewport->SetupPolyViewport(MainThread());
FRenderViewpoint origviewpoint = MainThread()->Viewport->viewpoint;
ActorRenderFlags savedflags = MainThread()->Viewport->viewpoint.camera->renderflags;
// Never draw the player unless in chasecam mode
if (!MainThread()->Viewport->viewpoint.showviewer)
@ -167,6 +169,12 @@ namespace swrenderer
}
RenderThreadSlices();
// Mirrors fail to restore the original viewpoint -- we need it for the HUD weapon to draw correctly.
MainThread()->Viewport->viewpoint = origviewpoint;
if (r_models)
MainThread()->Viewport->SetupPolyViewport(MainThread());
RenderPSprites();
MainThread()->Viewport->viewpoint.camera->renderflags = savedflags;

View file

@ -47,12 +47,22 @@ namespace swrenderer
if (tz < MINZ)
return;
// too far off the side?
double tx = tr_x * thread->Viewport->viewpoint.Sin - tr_y * thread->Viewport->viewpoint.Cos;
// Flip for mirrors
if (thread->Portal->MirrorFlags & RF_XFLIP)
{
tx = viewwidth - tx - 1;
}
// too far off the side?
if (fabs(tx / 64) > fabs(tz))
return;
RenderModel *vis = thread->FrameMemory->NewObject<RenderModel>(x, y, z, smf, actor, float(1 / tz));
vis->CurrentPortalUniq = thread->Portal->CurrentPortalUniq;
vis->WorldToClip = thread->Viewport->WorldToClip;
vis->MirrorWorldToClip = !!(thread->Portal->MirrorFlags & RF_XFLIP);
thread->SpriteList->Push(vis);
}
@ -64,7 +74,7 @@ namespace swrenderer
void RenderModel::Render(RenderThread *thread, short *cliptop, short *clipbottom, int minZ, int maxZ, Fake3DTranslucent clip3DFloor)
{
SWModelRenderer renderer(thread, clip3DFloor);
SWModelRenderer renderer(thread, clip3DFloor, &WorldToClip, MirrorWorldToClip);
renderer.RenderModel(x, y, z, smf, actor);
}
@ -72,13 +82,14 @@ namespace swrenderer
void RenderHUDModel(RenderThread *thread, DPSprite *psp, float ofsx, float ofsy)
{
SWModelRenderer renderer(thread, Fake3DTranslucent());
SWModelRenderer renderer(thread, Fake3DTranslucent(), &thread->Viewport->WorldToClip, false);
renderer.RenderHUDModel(psp, ofsx, ofsy);
}
/////////////////////////////////////////////////////////////////////////////
SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor) : Thread(thread), Clip3DFloor(clip3DFloor)
SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor, Mat4f *worldToClip, bool mirrorWorldToClip)
: Thread(thread), Clip3DFloor(clip3DFloor), WorldToClip(worldToClip), MirrorWorldToClip(mirrorWorldToClip)
{
}
@ -123,6 +134,7 @@ namespace swrenderer
if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal] || !!(smf->flags & MDL_DONTCULLBACKFACES))
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true);
PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, !(mirrored ^ MirrorWorldToClip));
}
void SWModelRenderer::EndDrawModel(AActor *actor, FSpriteModelFrame *smf)
@ -192,6 +204,7 @@ namespace swrenderer
if (actor->RenderStyle == LegacyRenderStyles[STYLE_Normal])
PolyTriangleDrawer::SetTwoSided(Thread->DrawQueue, true);
PolyTriangleDrawer::SetCullCCW(Thread->DrawQueue, !(mirrored ^ MirrorWorldToClip));
}
void SWModelRenderer::EndDrawHUDModel(AActor *actor)
@ -221,7 +234,7 @@ namespace swrenderer
swapYZ.Matrix[2 + 1 * 4] = 1.0f;
swapYZ.Matrix[3 + 3 * 4] = 1.0f;
PolyTriangleDrawer::SetTransform(Thread->DrawQueue, Thread->FrameMemory->NewObject<Mat4f>(Thread->Viewport->WorldToClip * swapYZ * ObjectToWorld));
PolyTriangleDrawer::SetTransform(Thread->DrawQueue, Thread->FrameMemory->NewObject<Mat4f>((*WorldToClip) * swapYZ * ObjectToWorld));
}
void SWModelRenderer::DrawArrays(int start, int count)

View file

@ -47,12 +47,14 @@ namespace swrenderer
float x, y, z;
FSpriteModelFrame *smf;
AActor *actor;
Mat4f WorldToClip;
bool MirrorWorldToClip;
};
class SWModelRenderer : public FModelRenderer
{
public:
SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor);
SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor, Mat4f *worldToClip, bool mirrorWorldToClip);
ModelRendererType GetType() const override { return SWModelRendererType; }
@ -81,6 +83,8 @@ namespace swrenderer
unsigned int *IndexBuffer = nullptr;
TriVertex *VertexBuffer = nullptr;
float InterpolationFactor = 0.0;
Mat4f *WorldToClip = nullptr;
bool MirrorWorldToClip = false;
};
class SWModelVertexBuffer : public IModelVertexBuffer

View file

@ -62,6 +62,10 @@ namespace swrenderer
void RenderViewport::SetupPolyViewport(RenderThread *thread)
{
WorldToView = SoftwareWorldToView(viewpoint);
if (thread->Portal->MirrorFlags & RF_XFLIP)
WorldToView = Mat4f::Scale(-1.0f, 1.0f, 1.0f) * WorldToView;
ViewToClip = SoftwareViewToClip();
WorldToClip = ViewToClip * WorldToView;
}

View file

@ -539,6 +539,9 @@ class Actor : Thinker native
{
return damage;
}
// called on getting a secret, return false to disable default "secret found" message/sound
virtual bool OnGiveSecret(bool printmsg, bool playsound) { return true; }
native virtual bool OkayToSwitchTarget(Actor other);
native static class<Actor> GetReplacement(class<Actor> cls);