diff --git a/src/gl/data/gl_data.h b/src/gl/data/gl_data.h index 1e93f9a280..3e43408dd4 100644 --- a/src/gl/data/gl_data.h +++ b/src/gl/data/gl_data.h @@ -59,7 +59,8 @@ struct FGLLinePortal // defines the complete span of this portal vertex_t *v1, *v2; // vertices, from v1 to v2 DVector2 delta; // precalculated v2 - v1 for side checking - FLinePortal *reference; // one of the associated line portals, for retrieving translation info etc. + TArray lines; + int validcount = 0; }; extern TArray portals; diff --git a/src/gl/data/gl_portaldata.cpp b/src/gl/data/gl_portaldata.cpp index 0262f964b7..2635c9a2e5 100644 --- a/src/gl/data/gl_portaldata.cpp +++ b/src/gl/data/gl_portaldata.cpp @@ -443,7 +443,12 @@ void gl_InitPortals() tempindex[i] = glLinePortals.Size(); line_t *pSrcLine = linePortals[i].mOrigin; line_t *pLine = linePortals[i].mDestination; - FGLLinePortal glport = { pLine->v1, pLine->v2, {0, 0}, &linePortals[i] }; + FGLLinePortal glport; + + glport.v1 = pLine->v1; + glport.v2 = pLine->v2; + glport.delta = { 0, 0 }; + glport.lines.Push(&linePortals[i]); glLinePortals.Push(glport); // We cannot do this grouping for non-linked portals because they can be changed at run time. @@ -474,6 +479,7 @@ void gl_InitPortals() tempindex[j] = tempindex[i]; if (pLine->v1 == pLine2->v2) glLinePortals[tempindex[i]].v1 = pLine2->v1; else glLinePortals[tempindex[i]].v2 = pLine2->v2; + glLinePortals[tempindex[i]].lines.Push(&linePortals[j]); } } } diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index be25409e28..e4603cd1ec 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -102,7 +102,7 @@ UniqueList UniqueHorizons; UniqueList UniquePlaneMirrors; UniqueList UniqueLineToLines; - +void gl_RenderActorsInPortal(FGLLinePortal *glport); //========================================================================== // @@ -1003,7 +1003,7 @@ void GLLineToLinePortal::DrawContents() GLRenderer->mClipPortal = this; - line_t *origin = glport->reference->mOrigin; + line_t *origin = glport->lines[0]->mOrigin; P_TranslatePortalXY(origin, ViewPos.X, ViewPos.Y); P_TranslatePortalAngle(origin, ViewAngle); P_TranslatePortalZ(origin, ViewPos.Z); @@ -1038,17 +1038,22 @@ void GLLineToLinePortal::DrawContents() currentmapsection[mapsection >> 3] |= 1 << (mapsection & 7); } - GLRenderer->mViewActor = NULL; + GLRenderer->mViewActor = nullptr; GLRenderer->SetupView(ViewPos.X, ViewPos.Y, ViewPos.Z, ViewAngle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); ClearClipper(); - gl_RenderState.SetClipLine(glport->reference->mDestination); + gl_RenderState.SetClipLine(glport->lines[0]->mDestination); gl_RenderState.EnableClipLine(true); GLRenderer->DrawScene(); gl_RenderState.EnableClipLine(false); RestoreMapSection(); } +void GLLineToLinePortal::RenderAttached() +{ + gl_RenderActorsInPortal(glport); +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h index 2962a4be1d..c8afee2a63 100644 --- a/src/gl/scene/gl_portal.h +++ b/src/gl/scene/gl_portal.h @@ -169,6 +169,7 @@ public: virtual int ClipSubsector(subsector_t *sub) { return PClip_Inside; } virtual int ClipPoint(const DVector2 &pos) { return PClip_Inside; } virtual line_t *ClipLine() { return NULL; } + virtual void RenderAttached() {} static void BeginScene(); static void StartFrame(); @@ -194,10 +195,10 @@ struct GLLinePortal : public GLPortal GLLinePortal(FGLLinePortal *line) { - if (line->reference->mType != PORTT_LINKED) + if (line->lines[0]->mType != PORTT_LINKED) { // For non-linked portals we must check the actual linedef. - line_t *lline = line->reference->mDestination; + line_t *lline = line->lines[0]->mDestination; v1 = lline->v1; v2 = lline->v2; } @@ -258,6 +259,7 @@ protected: virtual void * GetSource() const { return glport; } virtual const char *GetName(); virtual line_t *ClipLine() { return line(); } + virtual void RenderAttached(); public: diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 1b6b8e87f9..23c7a6318b 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -308,6 +308,7 @@ void FGLRenderer::CreateScene() R_SetView(); validcount++; // used for processing sidedefs only once by the renderer. gl_RenderBSPNode (nodes + numnodes - 1); + if (GLRenderer->mCurrentPortal != NULL) GLRenderer->mCurrentPortal->RenderAttached(); Bsp.Unclock(); // And now the crappy hacks that have to be done to avoid rendering anomalies: diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 63a4f9c8cb..8e36c766e4 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -521,7 +521,7 @@ void GLSprite::PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingp // //========================================================================== -void GLSprite::Process(AActor* thing, sector_t * sector, bool thruportal) +void GLSprite::Process(AActor* thing, sector_t * sector, int thruportal) { sector_t rs; sector_t * rendersector; @@ -552,7 +552,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, bool thruportal) // [RH] Interpolate the sprite's position to make it look smooth DVector3 thingpos = thing->InterpolatedPosition(r_TicFracF); - if (thruportal) thingpos += Displacements.getOffset(thing->Sector->PortalGroup, sector->PortalGroup); + if (thruportal == 1) thingpos += Displacements.getOffset(thing->Sector->PortalGroup, sector->PortalGroup); // 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) @@ -581,7 +581,7 @@ void GLSprite::Process(AActor* thing, sector_t * sector, bool thruportal) thing->flags7 |= MF7_FLYCHEAT; // do this only once for the very first frame, but not if it gets into range again. } - if (GLRenderer->mClipPortal) + if (thruportal != 2 && GLRenderer->mClipPortal) { int clipres = GLRenderer->mClipPortal->ClipPoint(thingpos); if (clipres == GLPortal::PClip_InFront) return; @@ -601,7 +601,6 @@ void GLSprite::Process(AActor* thing, sector_t * sector, bool thruportal) topclip = rendersector->PortalBlocksMovement(sector_t::ceiling) ? LARGE_VALUE : rendersector->GetPortalPlaneZ(sector_t::ceiling); bottomclip = rendersector->PortalBlocksMovement(sector_t::floor) ? -LARGE_VALUE : rendersector->GetPortalPlaneZ(sector_t::floor); - x = thingpos.X; z = thingpos.Z - thing->Floorclip; y = thingpos.Y; @@ -1019,5 +1018,56 @@ void GLSprite::ProcessParticle (particle_t *particle, sector_t *sector)//, int s rendered_sprites++; } +//========================================================================== +// +// +// +//========================================================================== +void gl_RenderActorsInPortal(FGLLinePortal *glport) +{ + TMap processcheck; + if (glport->validcount == validcount) return; // only process once per frame + glport->validcount = validcount; + for (auto port : glport->lines) + { + line_t *line = port->mOrigin; + if (line->isLinePortal()) // only crossable ones + { + FLinePortal *port2 = port->mDestination->getPortal(); + // process only if the other side links back to this one. + if (port2 != nullptr && port->mDestination == port2->mOrigin && port->mOrigin == port2->mDestination) + { + for (portnode_t *node = port->render_thinglist; node != nullptr; node = node->m_snext) + { + AActor *th = node->m_thing; + + // process each actor only once per portal. + bool *check = processcheck.CheckKey(th); + if (check && *check) continue; + processcheck[th] = true; + + DAngle savedangle = th->Angles.Yaw; + DVector3 savedpos = th->Pos(); + DVector3 newpos = savedpos; + sector_t fakesector; + + P_TranslatePortalXY(line, newpos.X, newpos.Y); + P_TranslatePortalZ(line, newpos.Z); + P_TranslatePortalAngle(line, th->Angles.Yaw); + th->SetXYZ(newpos); + th->Prev += newpos - savedpos; + + GLSprite spr; + th->fillcolor = 0xff0000ff; + spr.Process(th, gl_FakeFlat(th->Sector, &fakesector, false), 2); + th->fillcolor = 0xffffffff; + th->Angles.Yaw = savedangle; + th->SetXYZ(savedpos); + th->Prev -= newpos - savedpos; + } + } + } + } +} \ No newline at end of file diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index c3b7f5de2b..7872a37cb0 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -359,7 +359,7 @@ public: void Draw(int pass); void PutSprite(bool translucent); - void Process(AActor* thing,sector_t * sector, bool thruportal = false); + void Process(AActor* thing,sector_t * sector, int thruportal = false); void ProcessParticle (particle_t *particle, sector_t *sector);//, int shade, int fakeside) void SetThingColor(PalEntry);