diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index 8b7bd010ac..5cb35f20c1 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -95,6 +95,7 @@ bool GLPortal::inskybox; UniqueList UniqueSkies; UniqueList UniqueHorizons; UniqueList UniquePlaneMirrors; +UniqueList UniqueLineToLines; @@ -109,6 +110,7 @@ void GLPortal::BeginScene() UniqueSkies.Clear(); UniqueHorizons.Clear(); UniquePlaneMirrors.Clear(); + UniqueLineToLines.Clear(); } //========================================================================== @@ -216,7 +218,7 @@ bool GLPortal::Start(bool usestencil, bool doquery) else if (gl_noquery) doquery = false; // If occlusion query is supported let's use it to avoid rendering portals that aren't visible - if (!QueryObject) glGenQueries(1, &QueryObject); + if (!QueryObject && doquery) glGenQueries(1, &QueryObject); if (QueryObject) { glBeginQuery(GL_SAMPLES_PASSED, QueryObject); @@ -244,15 +246,18 @@ bool GLPortal::Start(bool usestencil, bool doquery) GLuint sampleCount; - glGetQueryObjectuiv(QueryObject, GL_QUERY_RESULT, &sampleCount); - - if (sampleCount == 0) // not visible + if (QueryObject) { - // restore default stencil op. - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - glStencilFunc(GL_EQUAL, recursion, ~0); // draw sky into stencil - PortalAll.Unclock(); - return false; + glGetQueryObjectuiv(QueryObject, GL_QUERY_RESULT, &sampleCount); + + if (sampleCount == 0) // not visible + { + // restore default stencil op. + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glStencilFunc(GL_EQUAL, recursion, ~0); // draw sky into stencil + PortalAll.Unclock(); + return false; + } } FDrawInfo::StartDrawInfo(); } @@ -969,6 +974,86 @@ int GLMirrorPortal::ClipPoint(fixed_t x, fixed_t y) } +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// +// +// Line to line Portal +// +// +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// +// +// +//----------------------------------------------------------------------------- +void GLLineToLinePortal::DrawContents() +{ + // TODO: Handle recursion more intelligently + if (renderdepth>r_mirror_recursions) + { + ClearScreen(); + return; + } + + GLRenderer->mCurrentPortal = this; + + viewx += l2l->xDisplacement; + viewy += l2l->yDisplacement; + SaveMapSection(); + + for (unsigned i = 0; i < lines.Size(); i++) + { + ASkyViewpoint *pt = lines[i].seg->linedef->skybox; + int mapsection = lines[i].seg->Subsector->mapsection; + currentmapsection[mapsection >> 3] |= 1 << (mapsection & 7); + } + + GLRenderer->mViewActor = NULL; + validcount++; + GLRenderer->SetupView(viewx, viewy, viewz, viewangle, !!(MirrorFlag&1), !!(PlaneMirrorFlag&1)); + + ClearClipper(); + GLRenderer->DrawScene(); + RestoreMapSection(); +} + + +int GLLineToLinePortal::ClipSeg(seg_t *seg) +{ + line_t *masterline = lines[0].seg->linedef->getPortalDestination(); + // this seg is completely behind the portal + if (P_PointOnLineSide(seg->v1->x, seg->v1->y, masterline) && + P_PointOnLineSide(seg->v2->x, seg->v2->y, masterline)) + { + return PClip_InFront; + } + return PClip_Inside; +} + +int GLLineToLinePortal::ClipSubsector(subsector_t *sub) +{ + line_t *masterline = lines[0].seg->linedef->getPortalDestination(); + + for(unsigned int i=0;inumlines;i++) + { + if (P_PointOnLineSide(sub->firstline[i].v1->x, sub->firstline[i].v1->y, masterline) == 0) return PClip_Inside; + } + return PClip_InFront; +} + +int GLLineToLinePortal::ClipPoint(fixed_t x, fixed_t y) +{ + line_t *masterline = lines[0].seg->linedef->getPortalDestination(); + if (P_PointOnLineSide(x, y, masterline)) + { + return PClip_InFront; + } + return PClip_Inside; +} + //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // @@ -1165,6 +1250,7 @@ const char *GLSkyboxPortal::GetName() { return "Skybox"; } const char *GLSectorStackPortal::GetName() { return "Sectorstack"; } const char *GLPlaneMirrorPortal::GetName() { return "Planemirror"; } const char *GLMirrorPortal::GetName() { return "Mirror"; } +const char *GLLineToLinePortal::GetName() { return "LineToLine"; } const char *GLHorizonPortal::GetName() { return "Horizon"; } const char *GLEEHorizonPortal::GetName() { return "EEHorizon"; } diff --git a/src/gl/scene/gl_portal.h b/src/gl/scene/gl_portal.h index c7c07986be..279c2e7154 100644 --- a/src/gl/scene/gl_portal.h +++ b/src/gl/scene/gl_portal.h @@ -51,6 +51,17 @@ struct GLHorizonInfo FColormap colormap; }; +struct GLLineToLineInfo +{ + fixed_t xDisplacement; + fixed_t yDisplacement; + fixed_t turnangle; + fixed_t angle; + fixed_t x0; + fixed_t y0; + void init(line_t *line); +}; + struct GLSkyInfo { float x_offset[2]; @@ -76,6 +87,7 @@ struct GLSkyInfo extern UniqueList UniqueSkies; extern UniqueList UniqueHorizons; extern UniqueList UniquePlaneMirrors; +extern UniqueList UniqueLineToLines; struct GLEEHorizonPortal; class GLPortal @@ -195,6 +207,28 @@ public: }; +struct GLLineToLinePortal : public GLPortal +{ + GLLineToLineInfo *l2l; +protected: + virtual void DrawContents(); + virtual void * GetSource() const { return l2l; } + virtual const char *GetName(); + +public: + + GLLineToLinePortal(GLLineToLineInfo *ll) + { + l2l=ll; + } + + virtual bool NeedCap() { return false; } + virtual int ClipSeg(seg_t *seg); + virtual int ClipSubsector(subsector_t *sub); + virtual int ClipPoint(fixed_t x, fixed_t y); +}; + + struct GLSkyboxPortal : public GLPortal { AActor * origin; diff --git a/src/gl/scene/gl_sky.cpp b/src/gl/scene/gl_sky.cpp index c020ab2768..10ed2ffa15 100644 --- a/src/gl/scene/gl_sky.cpp +++ b/src/gl/scene/gl_sky.cpp @@ -129,6 +129,23 @@ void GLSkyInfo::init(int sky1, PalEntry FadeColor) } + +void GLLineToLineInfo::init(line_t *line) +{ +/* + static const divline_t divlx = { 0, 0, 128 * FRACUNIT, 0 }; + static const divline_t divly = { 0, 0, 0, 128 * FRACUNIT }; + xDisplacement = line->skybox->scaleX; + yDisplacement = line->skybox->scaleY; + angle = R_PointToAnglePrecise(line->v1->x, line->v1->y, line->v2->x, line->v2->y); + + divline_t divl; + P_MakeDivline(line, &divl); + x0 = P_InterceptVector(&divlx, &divl); + y0 = P_InterceptVector(&divly, &divl); +*/ +} + //========================================================================== // // Calculate sky texture for ceiling or floor @@ -188,23 +205,30 @@ void GLWall::SkyPlane(sector_t *sector, int plane, bool allowreflect) // //========================================================================== -void GLWall::SkyLine(line_t *line) +void GLWall::SkyLine(sector_t *fs, line_t *line) { ASkyViewpoint * skyboxx = line->skybox; GLSkyInfo skyinfo; + GLLineToLineInfo llinfo; int ptype; // JUSTHIT is used as an indicator that a skybox is in use. // This is to avoid recursion - if (!gl_noskyboxes && skyboxx && GLRenderer->mViewActor != skyboxx && !(skyboxx->flags&MF_JUSTHIT)) + if (line->isVisualPortal()) + { + ptype = PORTALTYPE_LINETOLINE; + llinfo.init(line); + l2l = UniqueLineToLines.Get(&llinfo); + } + else if (!gl_noskyboxes && skyboxx && GLRenderer->mViewActor != skyboxx && !(skyboxx->flags&MF_JUSTHIT)) { ptype = PORTALTYPE_SKYBOX; skybox = skyboxx; } else { - skyinfo.init(line->frontsector->sky, Colormap.FadeColor); + skyinfo.init(fs->sky, Colormap.FadeColor); ptype = PORTALTYPE_SKY; sky = UniqueSkies.Get(&skyinfo); } @@ -231,7 +255,7 @@ void GLWall::SkyNormal(sector_t * fs,vertex_t * v1,vertex_t * v2) ztop[1] = zceil[1]; zbottom[0] = zfloor[0]; zbottom[1] = zfloor[1]; - SkyLine(seg->linedef); + SkyLine(fs, seg->linedef); } ztop[0]=zfloor[0]; diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h index 1aa9023723..1dc060e660 100644 --- a/src/gl/scene/gl_wall.h +++ b/src/gl/scene/gl_wall.h @@ -21,6 +21,7 @@ struct GLSkyInfo; struct FTexCoordInfo; struct FPortal; struct FFlatVertex; +struct GLLineToLineInfo; enum WallTypes @@ -46,6 +47,7 @@ enum PortalTypes PORTALTYPE_SECTORSTACK, PORTALTYPE_PLANEMIRROR, PORTALTYPE_MIRROR, + PORTALTYPE_LINETOLINE, }; struct GLSeg @@ -147,6 +149,7 @@ public: GLHorizonInfo * horizon; // for horizon information FPortal * portal; // stacked sector portals secplane_t * planemirror; // for plane mirrors + GLLineToLineInfo *l2l; // line-to-line portals }; @@ -178,7 +181,7 @@ private: void FloodPlane(int pass); void SkyPlane(sector_t *sector, int plane, bool allowmirror); - void SkyLine(line_t *line); + void SkyLine(sector_t *sec, line_t *line); void SkyNormal(sector_t * fs,vertex_t * v1,vertex_t * v2); void SkyTop(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2); void SkyBottom(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex_t * v2); diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp index b7243dcf82..92628f879a 100644 --- a/src/gl/scene/gl_walls.cpp +++ b/src/gl/scene/gl_walls.cpp @@ -209,6 +209,12 @@ void GLWall::PutPortal(int ptype) } break; + case PORTALTYPE_LINETOLINE: + portal=GLPortal::FindPortal(l2l); + if (!portal) portal=new GLLineToLinePortal(l2l); + portal->AddLine(this); + break; + case PORTALTYPE_SKY: portal=GLPortal::FindPortal(sky); if (!portal) portal=new GLSkyPortal(sky); @@ -1582,7 +1588,16 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector) fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2); } - if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size()) + if (seg->linedef->isVisualPortal() && seg->sidedef == seg->linedef->sidedef[0]) + { + ztop[0] = FIXED2FLOAT(bch1); + ztop[1] = FIXED2FLOAT(bch2); + zbottom[0] = FIXED2FLOAT(bfh1); + zbottom[1] = FIXED2FLOAT(bfh2); + + //SkyLine(frontsector, seg->linedef); + } + else if (backsector->e->XFloor.ffloors.Size() || frontsector->e->XFloor.ffloors.Size()) { DoFFloorBlocks(seg, frontsector, backsector, fch1, fch2, ffh1, ffh2, bch1, bch2, bfh1, bfh2); }