From a0a530945d3399cbfbf75fdc2f4b2dce4947f468 Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@zdoom.fake>
Date: Thu, 14 Apr 2016 13:22:15 +0200
Subject: [PATCH] - added new sector type 90 which designates a sector that is
 being used as a cubemapped skybox, in case someone wants to make one of those
 without using an actual sky for this.

---
 src/gl/scene/gl_flats.cpp | 90 ++++++++++++++++++++++++++++++++++++---
 src/gl/scene/gl_sky.cpp   | 10 +----
 src/gl/scene/gl_wall.h    |  6 +++
 src/gl/scene/gl_walls.cpp | 36 ++++++++++++----
 4 files changed, 119 insertions(+), 23 deletions(-)

diff --git a/src/gl/scene/gl_flats.cpp b/src/gl/scene/gl_flats.cpp
index 6dd611cdd..2a5ef712e 100644
--- a/src/gl/scene/gl_flats.cpp
+++ b/src/gl/scene/gl_flats.cpp
@@ -178,8 +178,8 @@ void GLFlat::DrawSubsector(subsector_t * sub)
 	{
 		vertex_t *vt = sub->firstline[k].v1;
 		ptr->x = vt->fX();
-		ptr->y = vt->fY();
 		ptr->z = plane.plane.ZatPoint(vt) + dz;
+		ptr->y = vt->fY();
 		ptr->u = vt->fX() / 64.f;
 		ptr->v = -vt->fY() / 64.f;
 		ptr++;
@@ -252,7 +252,7 @@ void GLFlat::DrawSubsectors(int pass, bool processlights, bool istrans)
 		if (processlights) SetupSubsectorLights(GLPASS_ALL, sub, &dli);
 		DrawSubsector(sub);
 	}
-	else
+	else 
 	{
 		if (vboindex >= 0)
 		{
@@ -305,6 +305,76 @@ void GLFlat::DrawSubsectors(int pass, bool processlights, bool istrans)
 }
 
 
+//==========================================================================
+//
+// special handling for skyboxes which need texture clamping.
+// This will find the bounding rectangle of the sector and just
+// draw one single polygon filling that rectangle with a clamped
+// texture.
+//
+//==========================================================================
+
+void GLFlat::DrawSkyboxSector(int pass, bool processlights)
+{
+	FFlatVertex *ptr = GLRenderer->mVBO->GetBuffer();
+
+	float minx = FLT_MAX, miny = FLT_MAX;
+	float maxx = -FLT_MAX, maxy = -FLT_MAX;
+
+	for (int i = 0; i < sector->linecount; i++)
+	{
+		line_t *ln = sector->lines[i];
+		float x = ln->v1->fX();
+		float y = ln->v1->fY();
+		if (x < minx) minx = x;
+		if (y < miny) miny = y;
+		if (x > maxx) maxx = x;
+		if (y > maxy) maxy = y;
+		x = ln->v2->fX();
+		y = ln->v2->fY();
+		if (x < minx) minx = x;
+		if (y < miny) miny = y;
+		if (x > maxx) maxx = x;
+		if (y > maxy) maxy = y;
+	}
+
+	float z = plane.plane.ZatPoint(0., 0.) + dz;
+
+	ptr->x = minx;
+	ptr->z = z;
+	ptr->y = miny;
+	ptr->u = 0;
+	ptr->v = 1;
+	ptr++;
+
+	ptr->x = minx;
+	ptr->z = z;
+	ptr->y = maxy;
+	ptr->u = 0;
+	ptr->v = 0;
+	ptr++;
+
+	ptr->x = maxx;
+	ptr->z = z;
+	ptr->y = maxy;
+	ptr->u = 1;
+	ptr->v = 0;
+	ptr++;
+
+	ptr->x = maxx;
+	ptr->z = z;
+	ptr->y = miny;
+	ptr->u = 1;
+	ptr->v = 1;
+	ptr++;
+
+	GLRenderer->mVBO->RenderCurrent(ptr, GL_TRIANGLE_FAN);
+
+	flatvertices += 4;
+	flatprimitives++;
+}
+
+
 //==========================================================================
 //
 //
@@ -328,10 +398,18 @@ void GLFlat::Draw(int pass, bool trans)	// trans only has meaning for GLPASS_LIG
 	case GLPASS_ALL:
 		gl_SetColor(lightlevel, rel, Colormap,1.0f);
 		gl_SetFog(lightlevel, rel, &Colormap, false);
-		gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
-		gl_SetPlaneTextureRotation(&plane, gltexture);
-		DrawSubsectors(pass, (pass == GLPASS_ALL || dynlightindex > -1), false);
-		gl_RenderState.EnableTextureMatrix(false);
+		if (sector->special != GLSector_Skybox)
+		{
+			gl_RenderState.SetMaterial(gltexture, CLAMP_NONE, 0, -1, false);
+			gl_SetPlaneTextureRotation(&plane, gltexture);
+			DrawSubsectors(pass, (pass == GLPASS_ALL || dynlightindex > -1), false);
+			gl_RenderState.EnableTextureMatrix(false);
+		}
+		else
+		{
+			gl_RenderState.SetMaterial(gltexture, CLAMP_XY, 0, -1, false);
+			DrawSkyboxSector(pass, (pass == GLPASS_ALL || dynlightindex > -1));
+		}
 		break;
 
 	case GLPASS_LIGHTSONLY:
diff --git a/src/gl/scene/gl_sky.cpp b/src/gl/scene/gl_sky.cpp
index 2826236b2..6f6039c00 100644
--- a/src/gl/scene/gl_sky.cpp
+++ b/src/gl/scene/gl_sky.cpp
@@ -58,12 +58,6 @@
 CVAR(Bool,gl_noskyboxes, false, 0)
 extern int skyfog;
 
-enum
-{
-	NoSkyDraw = 89
-};
-
-
 //==========================================================================
 //
 //  Set up the skyinfo struct
@@ -254,7 +248,7 @@ void GLWall::SkyTop(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,vertex
 {
 	if (fs->GetTexture(sector_t::ceiling)==skyflatnum)
 	{
-		if (bs->special == NoSkyDraw) return;
+		if (bs->special == GLSector_NoSkyDraw) return;
 		if (bs->GetTexture(sector_t::ceiling)==skyflatnum) 
 		{
 			// if the back sector is closed the sky must be drawn!
@@ -344,7 +338,7 @@ void GLWall::SkyBottom(seg_t * seg,sector_t * fs,sector_t * bs,vertex_t * v1,ver
 {
 	if (fs->GetTexture(sector_t::floor)==skyflatnum)
 	{
-		if (bs->special == NoSkyDraw) return;
+		if (bs->special == GLSector_NoSkyDraw) return;
 		FTexture * tex = TexMan(seg->sidedef->GetTexture(side_t::bottom));
 		
 		// For lower skies the normal logic only applies to walls with no lower texture!
diff --git a/src/gl/scene/gl_wall.h b/src/gl/scene/gl_wall.h
index 8bd39b372..890ba980d 100644
--- a/src/gl/scene/gl_wall.h
+++ b/src/gl/scene/gl_wall.h
@@ -23,6 +23,11 @@ struct FPortal;
 struct FFlatVertex;
 struct FGLLinePortal;
 
+enum
+{
+	GLSector_NoSkyDraw = 89,
+	GLSector_Skybox = 90,
+};
 
 enum WallTypes
 {
@@ -290,6 +295,7 @@ public:
 	void SetupSubsectorLights(int pass, subsector_t * sub, int *dli = NULL);
 	void DrawSubsector(subsector_t * sub);
 	void DrawSubsectorLights(subsector_t * sub, int pass);
+	void DrawSkyboxSector(int pass, bool processlights);
 	void DrawSubsectors(int pass, bool processlights, bool istrans);
 	void ProcessLights(bool istrans);
 
diff --git a/src/gl/scene/gl_walls.cpp b/src/gl/scene/gl_walls.cpp
index 5d13a0720..8f91b59cd 100644
--- a/src/gl/scene/gl_walls.cpp
+++ b/src/gl/scene/gl_walls.cpp
@@ -583,7 +583,23 @@ void GLWall::CheckTexturePosition()
 	if ((uplft.v == 0.f && uprgt.v == 0.f && lolft.v <= 1.f && lorgt.v <= 1.f) ||
 		(uplft.v >= 0.f && uprgt.v >= 0.f && lolft.v == 1.f && lorgt.v == 1.f))
 	{
-		flags|=GLT_CLAMPY;
+		flags |= GLT_CLAMPY;
+	}
+
+	// Check if this is marked as a skybox and if so, do the same for x.
+	// This intentionally only tests the seg's frontsector.
+	if (seg->frontsector->special == GLSector_Skybox)
+	{
+		sub = (float)xs_FloorToInt(uplft.u);
+		uplft.u -= sub;
+		uprgt.u -= sub;
+		lolft.u -= sub;
+		lorgt.u -= sub;
+		if ((uplft.u == 0.f && lolft.u == 0.f && uprgt.u <= 1.f && lorgt.u <= 1.f) ||
+			(uplft.u >= 0.f && lolft.u >= 0.f && uprgt.u == 1.f && lorgt.u == 1.f))
+		{
+			flags |= GLT_CLAMPX;
+		}
 	}
 }
 
@@ -604,6 +620,7 @@ void GLWall::DoTexture(int _type,seg_t * seg, int peg,
 	GLSeg glsave=glseg;
 	float flh=ceilingrefheight-floorrefheight;
 	int texpos;
+	BYTE savedflags = flags;
 
 	switch (_type)
 	{
@@ -636,16 +653,17 @@ void GLWall::DoTexture(int _type,seg_t * seg, int peg,
 	}
 	else
 	{
-		CheckTexturePosition();
-		// Add this wall to the render list
-		sector_t * sec = sub? sub->sector : seg->frontsector;
 
+		CheckTexturePosition();
+
+		// Add this wall to the render list
+		sector_t * sec = sub ? sub->sector : seg->frontsector;
 		if (sec->e->XFloor.lightlist.Size()==0 || gl_fixedcolormap) PutWall(false);
 		else SplitWall(sec, false);
 	}
 
-	glseg=glsave;
-	flags&=~GLT_CLAMPY;
+	glseg = glsave;
+	flags = savedflags;
 }
 
 
@@ -837,11 +855,11 @@ void GLWall::DoMidTexture(seg_t * seg, bool drawfogboundary,
 		}
 		else
 		{
-			flags&=~GLT_CLAMPX;
+			flags &= ~GLT_CLAMPX;
 		}
 		if (!wrap)
 		{
-			flags|=GLT_CLAMPY;
+			flags |= GLT_CLAMPY;
 		}
 	}
 	if (mirrory)
@@ -1330,7 +1348,7 @@ void GLWall::Process(seg_t *seg, sector_t * frontsector, sector_t * backsector)
 	sector_t * segback;
 
 #ifdef _DEBUG
-	if (seg->linedef - lines == 904)
+	if (seg->linedef - lines < 4)
 	{
 		int a = 0;
 	}