From acf66d9f8fe5a3fd622aba186de6d5d7798d9ab9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 7 Jan 2017 01:07:35 +0100 Subject: [PATCH 1/4] - fixed some edge cases with visible player sprites through non-static line portals. This required reinstating some code which I thought was no longer needed. --- src/actor.h | 1 + src/gl/scene/gl_portal.cpp | 25 +++++++++++++++++++++++-- src/gl/scene/gl_portal.h | 1 + src/gl/scene/gl_sprite.cpp | 17 +++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/actor.h b/src/actor.h index ffe3cc1a4..439ae2644 100644 --- a/src/actor.h +++ b/src/actor.h @@ -418,6 +418,7 @@ enum ActorRenderFlag RF_FLATSPRITE = 0x2000, // Flat sprite RF_VOXELSPRITE = 0x3000, // Voxel object RF_INVISIBLE = 0x8000, // Don't bother drawing this actor + RF_MAYBEINVISIBLE = 0x10000, RF_ROLLSPRITE = 0x40000, //[marrub]roll the sprite billboard RF_DONTFLIP = 0x80000, // Don't flip it when viewed from behind. RF_ROLLCENTER = 0x00100000, // Rotate from the center of sprite instead of offsets diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index e1fed484a..4cf8b9e7b 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -288,7 +288,9 @@ bool GLPortal::Start(bool usestencil, bool doquery) savedAngle = ViewAngle; savedviewactor=GLRenderer->mViewActor; savedviewarea=in_area; - savedvisibility = camera ? camera->renderflags & RF_INVISIBLE : ActorRenderFlags::FromInt(0); + savedviewpath[0] = ViewPath[0]; + savedviewpath[1] = ViewPath[1]; + savedvisibility = camera ? camera->renderflags & RF_MAYBEINVISIBLE : ActorRenderFlags::FromInt(0); PrevPortal = GLRenderer->mCurrentPortal; @@ -350,13 +352,15 @@ void GLPortal::End(bool usestencil) if (needdepth) FDrawInfo::EndDrawInfo(); // Restore the old view + ViewPath[0] = savedviewpath[0]; + ViewPath[1] = savedviewpath[1]; ViewPos = savedViewPos; r_showviewer = savedshowviewer; ViewActorPos = savedViewActorPos; ViewAngle = savedAngle; GLRenderer->mViewActor=savedviewactor; in_area=savedviewarea; - if (camera != nullptr) camera->renderflags = (camera->renderflags & ~RF_INVISIBLE) | savedvisibility; + if (camera != nullptr) camera->renderflags = (camera->renderflags & ~RF_MAYBEINVISIBLE) | savedvisibility; GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag & 1), !!(PlaneMirrorFlag & 1)); { @@ -1011,6 +1015,23 @@ void GLLineToLinePortal::DrawContents() P_TranslatePortalXY(origin, ViewActorPos.X, ViewActorPos.Y); P_TranslatePortalAngle(origin, ViewAngle); P_TranslatePortalZ(origin, ViewPos.Z); + P_TranslatePortalXY(origin, ViewPath[0].X, ViewPath[0].Y); + P_TranslatePortalXY(origin, ViewPath[1].X, ViewPath[1].Y); + if (!r_showviewer && camera != nullptr && P_PointOnLineSidePrecise(ViewPath[0], glport->lines[0]->mDestination) != P_PointOnLineSidePrecise(ViewPath[1], glport->lines[0]->mDestination)) + { + double distp = (ViewPath[0] - ViewPath[1]).Length(); + if (distp > EQUAL_EPSILON) + { + double dist1 = (ViewPos - ViewPath[0]).Length(); + double dist2 = (ViewPos - ViewPath[1]).Length(); + + if (dist1 + dist2 < distp + 1) + { + camera->renderflags |= RF_MAYBEINVISIBLE; + } + } + } + SaveMapSection(); diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h index 80f810cb5..8a40ec2e2 100644 --- a/src/gl/scene/gl_portal.h +++ b/src/gl/scene/gl_portal.h @@ -101,6 +101,7 @@ public: private: void DrawPortalStencil(); + DVector3 savedviewpath[2]; DVector3 savedViewPos; DVector3 savedViewActorPos; DAngle savedAngle; diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 7ed4199a1..4eda8aac1 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -677,6 +677,11 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) if (thruportal == 1) thingorigin += Displacements.getOffset(thing->Sector->PortalGroup, sector->PortalGroup); if (fabs(thingorigin.X - ViewActorPos.X) < 2 && fabs(thingorigin.Y - ViewActorPos.Y) < 2) return; } + // Thing is invisible if close to the camera. + if (thing->renderflags & RF_MAYBEINVISIBLE) + { + if (fabs(thingpos.X - ViewPos.X) < 32 && fabs(thingpos.Y - ViewPos.Y) < 32) return; + } // Too close to the camera. This doesn't look good if it is a sprite. if (fabs(thingpos.X - ViewPos.X) < 2 && fabs(thingpos.Y - ViewPos.Y) < 2) @@ -693,6 +698,10 @@ void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) } } } + if (thing == camera) + { + int a = 0; + } // don't draw first frame of a player missile if (thing->flags&MF_MISSILE) @@ -1203,6 +1212,14 @@ void gl_RenderActorsInPortal(FGLLinePortal *glport) DVector3 newpos = savedpos; sector_t fakesector; + if (!r_showviewer && th == camera) + { + if (fabs(savedpos.X - ViewActorPos.X) < 2 && fabs(savedpos.Y - ViewActorPos.Y) < 2) + { + continue; + } + } + P_TranslatePortalXY(line, newpos.X, newpos.Y); P_TranslatePortalZ(line, newpos.Z); P_TranslatePortalAngle(line, th->Angles.Yaw); From 42b1432b645e1a27810158fba4bd068f4787aa47 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 7 Jan 2017 11:36:57 +0100 Subject: [PATCH 2/4] - fixed: initialization of local vector variables did not properly allocate registers if the initializer was a subelement of another local vector variable. --- src/scripting/codegeneration/codegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 7a6997746..d5dbbdbfa 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -10154,7 +10154,7 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build) } emitval.Free(build); } - else if (Init->ExprType != EFX_LocalVariable) + else if (!emitval.Fixed) { // take over the register that got allocated while emitting the Init expression. RegNum = emitval.RegNum; From 581cd27818954089f90cb5c329ff73bae29843c3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 7 Jan 2017 13:13:16 +0100 Subject: [PATCH 3/4] - floatified the translucency values in particle_t to elimintate the gross inaccuracies with fadeout time. - widened ttl variable in particle_t to short to allow longer living particles than 6 seconds. - reordered fields in particle_t to reduce struct size a bit. --- src/gl/scene/gl_sprite.cpp | 4 ++-- src/p_effect.cpp | 27 +++++++++++++-------------- src/p_effect.h | 10 +++++----- src/r_things.cpp | 2 +- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 4eda8aac1..75d15543e 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -1060,7 +1060,7 @@ void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int s player_t *player=&players[consoleplayer]; - if (particle->trans==0) return; + if (particle->alpha==0) return; lightlevel = gl_ClampLight(sector->GetTexture(sector_t::ceiling) == skyflatnum ? sector->GetCeilingLight() : sector->GetFloorLight()); @@ -1100,7 +1100,7 @@ void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int s Colormap.ClearColor(); } - trans=particle->trans/255.0f; + trans=particle->alpha; RenderStyle = STYLE_Translucent; OverrideShader = 0; diff --git a/src/p_effect.cpp b/src/p_effect.cpp index 827a457ee..eb872edc1 100644 --- a/src/p_effect.cpp +++ b/src/p_effect.cpp @@ -62,7 +62,7 @@ CVAR (Bool, r_particles, true, 0); FRandom pr_railtrail("RailTrail"); -#define FADEFROMTTL(a) (255/(a)) +#define FADEFROMTTL(a) (1.f/(a)) // [RH] particle globals WORD NumParticles; @@ -269,11 +269,10 @@ void P_ThinkParticles () continue; } - BYTE oldtrans; - oldtrans = particle->trans; - particle->trans -= particle->fade; + auto oldtrans = particle->alpha; + particle->alpha -= particle->fadestep; particle->size += particle->sizestep; - if (oldtrans < particle->trans || --particle->ttl <= 0 || (particle->size <= 0)) + if (oldtrans < particle->alpha || --particle->ttl <= 0 || (particle->size <= 0)) { // The particle has expired, so free it memset (particle, 0, sizeof(particle_t)); if (prev) @@ -331,9 +330,9 @@ void P_SpawnParticle(const DVector3 &pos, const DVector3 &vel, const DVector3 &a particle->Vel = vel; particle->Acc = accel; particle->color = ParticleColor(color); - particle->trans = BYTE(startalpha*255); - if (fadestep < 0) particle->fade = FADEFROMTTL(lifetime); - else particle->fade = int(fadestep * 255); + particle->alpha = float(startalpha); + if (fadestep < 0) particle->fadestep = FADEFROMTTL(lifetime); + else particle->fadestep = float(fadestep); particle->ttl = lifetime; particle->bright = !!(flags & PS_FULLBRIGHT); particle->size = size; @@ -392,9 +391,9 @@ particle_t *JitterParticle (int ttl, double drift) for (i = 3; i; i--) particle->Acc[i] = ((1./16384) * (M_Random () - 128) * drift); - particle->trans = 255; // fully opaque + particle->alpha = 1.f; // fully opaque particle->ttl = ttl; - particle->fade = FADEFROMTTL(ttl); + particle->fadestep = FADEFROMTTL(ttl); } return particle; } @@ -622,8 +621,8 @@ void P_DrawSplash2 (int count, const DVector3 &pos, DAngle angle, int updown, in break; p->ttl = 12; - p->fade = FADEFROMTTL(12); - p->trans = 255; + p->fadestep = FADEFROMTTL(12); + p->alpha = 1.f; p->size = 4; p->color = M_Random() & 0x80 ? color1 : color2; p->Vel.Z = M_Random() * zvel; @@ -763,9 +762,9 @@ void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, int spiralduration = (duration == 0) ? 35 : duration; - p->trans = 255; + p->alpha = 1.f; p->ttl = duration; - p->fade = FADEFROMTTL(spiralduration); + p->fadestep = FADEFROMTTL(spiralduration); p->size = 3; p->bright = fullbright; diff --git a/src/p_effect.h b/src/p_effect.h index 614702a49..4e8e73d09 100644 --- a/src/p_effect.h +++ b/src/p_effect.h @@ -57,17 +57,17 @@ struct particle_t DVector3 Pos; DVector3 Vel; DVector3 Acc; - BYTE ttl; - BYTE trans; double size; double sizestep; + subsector_t * subsector; + short ttl; BYTE bright; - BYTE fade; + bool notimefreeze; + float fadestep; + float alpha; int color; WORD tnext; WORD snext; - subsector_t * subsector; - bool notimefreeze; }; extern particle_t *Particles; diff --git a/src/r_things.cpp b/src/r_things.cpp index ce356808e..51b8221ec 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2593,7 +2593,7 @@ void R_ProjectParticle (particle_t *particle, const sector_t *sector, int shade, vis->startfrac = 255 & (particle->color >>24); vis->pic = NULL; vis->bIsVoxel = false; - vis->renderflags = particle->trans; + vis->renderflags = short(particle->alpha * 255); vis->FakeFlatStat = fakeside; vis->floorclip = 0; vis->ColormapNum = 0; From d381fb5e3ff29803490fc8642abac274c3ec23b6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 7 Jan 2017 14:29:04 +0100 Subject: [PATCH 4/4] - fixed: A_SetInventory must check for voodoo dolls and delegate the action to the real player because it will always break the real player's inventory if done so. --- src/p_actionfunctions.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 5bf5bf450..f4b2f8103 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -2500,6 +2500,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetInventory) ACTION_RETURN_BOOL(false); } + // Do not run this function on voodoo dolls because the way they transfer the inventory to the player will not work with the code below. + if (mobj->player != nullptr) + { + mobj = mobj->player->mo; + } + AInventory *item = mobj->FindInventory(itemtype); if (item != nullptr)