diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c
index 621ec7237329971962c3708d0302e2f221a7d45f..f87af074185fbff39cca880130188052b47253a3 100644
--- a/src/hardware/hw_main.c
+++ b/src/hardware/hw_main.c
@@ -66,6 +66,8 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing);
 #ifdef SORTING
 void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight,
                              INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap);
+void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, fixed_t fixedheight,
+                             INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap);
 #else
 static void HWR_Add3DWater(lumpnum_t lumpnum, extrasubsector_t *xsub, fixed_t fixedheight,
                            INT32 lightlevel, INT32 alpha, sector_t *FOFSector);
@@ -1695,78 +1697,81 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 		}
 
 		// Isn't this just the most lovely mess
-		if (gr_frontsector->ceilingpic == skyflatnum || gr_backsector->ceilingpic == skyflatnum)
+		if (!gr_curline->polyseg) // Don't do it for polyobjects
 		{
-			fixed_t depthwallheight;
+			if (gr_frontsector->ceilingpic == skyflatnum || gr_backsector->ceilingpic == skyflatnum)
+			{
+				fixed_t depthwallheight;
 
-			if (!gr_sidedef->toptexture || (gr_frontsector->ceilingpic == skyflatnum && gr_backsector->ceilingpic == skyflatnum)) // when both sectors are sky, the top texture isn't drawn
-				depthwallheight = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight;
-			else
-				depthwallheight = gr_frontsector->ceilingheight > gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight;
+				if (!gr_sidedef->toptexture || (gr_frontsector->ceilingpic == skyflatnum && gr_backsector->ceilingpic == skyflatnum)) // when both sectors are sky, the top texture isn't drawn
+					depthwallheight = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight;
+				else
+					depthwallheight = gr_frontsector->ceilingheight > gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight;
 
-			if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier
-			{
-				if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier
+				if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier
 				{
-					if (!gr_sidedef->bottomtexture) // Only extend further down if there's no texture
-						HWR_DrawSkyWall(wallVerts, &Surf, worldbottom < worldlow ? worldbottom : worldlow, INT32_MAX);
-					else
-						HWR_DrawSkyWall(wallVerts, &Surf, worldbottom > worldlow ? worldbottom : worldlow, INT32_MAX);
+					if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier
+					{
+						if (!gr_sidedef->bottomtexture) // Only extend further down if there's no texture
+							HWR_DrawSkyWall(wallVerts, &Surf, worldbottom < worldlow ? worldbottom : worldlow, INT32_MAX);
+						else
+							HWR_DrawSkyWall(wallVerts, &Surf, worldbottom > worldlow ? worldbottom : worldlow, INT32_MAX);
+					}
+					// behind sector is not a thok barrier
+					else if (gr_backsector->ceilingheight <= gr_frontsector->ceilingheight) // behind sector ceiling is lower or equal to current sector
+						HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX);
+						// gr_front/backsector heights need to be used here because of the worldtop being set to worldhigh earlier on
+				}
+				else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not
+				{
+					if (gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier ceiling height is equal to or greater than current sector ceiling height
+						|| gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier ceiling height is equal to or less than current sector floor height
+						|| gr_backsector->ceilingpic != skyflatnum) // thok barrier is not a sky
+						HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX);
+				}
+				else // neither sectors are thok barriers
+				{
+					if ((gr_backsector->ceilingheight < gr_frontsector->ceilingheight && !gr_sidedef->toptexture) // no top texture and sector behind is lower
+						|| gr_backsector->ceilingpic != skyflatnum) // behind sector is not a sky
+						HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX);
 				}
-				// behind sector is not a thok barrier
-				else if (gr_backsector->ceilingheight <= gr_frontsector->ceilingheight) // behind sector ceiling is lower or equal to current sector
-					HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX);
-					// gr_front/backsector heights need to be used here because of the worldtop being set to worldhigh earlier on
-			}
-			else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not
-			{
-				if (gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier ceiling height is equal to or greater than current sector ceiling height
-					|| gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier ceiling height is equal to or less than current sector floor height
-					|| gr_backsector->ceilingpic != skyflatnum) // thok barrier is not a sky
-					HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX);
 			}
-			else // neither sectors are thok barriers
+			// And now for sky floors!
+			if (gr_frontsector->floorpic == skyflatnum || gr_backsector->floorpic == skyflatnum)
 			{
-				if ((gr_backsector->ceilingheight < gr_frontsector->ceilingheight && !gr_sidedef->toptexture) // no top texture and sector behind is lower
-					|| gr_backsector->ceilingpic != skyflatnum) // behind sector is not a sky
-					HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX);
-			}
-		}
-		// And now for sky floors!
-		if (gr_frontsector->floorpic == skyflatnum || gr_backsector->floorpic == skyflatnum)
-		{
-			fixed_t depthwallheight;
+				fixed_t depthwallheight;
 
-			if (!gr_sidedef->bottomtexture)
-				depthwallheight = worldbottom > worldlow ? worldbottom : worldlow;
-			else
-				depthwallheight = worldbottom < worldlow ? worldbottom : worldlow;
+				if (!gr_sidedef->bottomtexture)
+					depthwallheight = worldbottom > worldlow ? worldbottom : worldlow;
+				else
+					depthwallheight = worldbottom < worldlow ? worldbottom : worldlow;
 
-			if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier
-			{
-				if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier
+				if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier
 				{
-					if (!gr_sidedef->toptexture) // Only extend up if there's no texture
-						HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop > worldhigh ? worldtop : worldhigh);
-					else
-						HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop < worldhigh ? worldtop : worldhigh);
+					if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier
+					{
+						if (!gr_sidedef->toptexture) // Only extend up if there's no texture
+							HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop > worldhigh ? worldtop : worldhigh);
+						else
+							HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop < worldhigh ? worldtop : worldhigh);
+					}
+					// behind sector is not a thok barrier
+					else if (gr_backsector->floorheight >= gr_frontsector->floorheight) // behind sector floor is greater or equal to current sector
+						HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight);
+				}
+				else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not
+				{
+					if (gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier floor height is equal to or less than current sector floor height
+						|| gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier floor height is equal to or greater than current sector ceiling height
+						|| gr_backsector->floorpic != skyflatnum) // thok barrier is not a sky
+						HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight);
+				}
+				else // neither sectors are thok barriers
+				{
+					if ((gr_backsector->floorheight > gr_frontsector->floorheight && !gr_sidedef->bottomtexture) // no bottom texture and sector behind is higher
+						|| gr_backsector->floorpic != skyflatnum) // behind sector is not a sky
+						HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight);
 				}
-				// behind sector is not a thok barrier
-				else if (gr_backsector->floorheight >= gr_frontsector->floorheight) // behind sector floor is greater or equal to current sector
-					HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight);
-			}
-			else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not
-			{
-				if (gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier floor height is equal to or less than current sector floor height
-					|| gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier floor height is equal to or greater than current sector ceiling height
-					|| gr_backsector->floorpic != skyflatnum) // thok barrier is not a sky
-					HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight);
-			}
-			else // neither sectors are thok barriers
-			{
-				if ((gr_backsector->floorheight > gr_frontsector->floorheight && !gr_sidedef->bottomtexture) // no bottom texture and sector behind is higher
-					|| gr_backsector->floorpic != skyflatnum) // behind sector is not a sky
-					HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight);
 			}
 		}
 	}
@@ -1809,10 +1814,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
 			}
 		}
 
-		if (gr_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector
-			HWR_DrawSkyWall(wallVerts, &Surf, worldtop, INT32_MAX);
-		if (gr_frontsector->floorpic == skyflatnum)
-			HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldbottom);
+		if (!gr_curline->polyseg)
+		{
+			if (gr_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector
+				HWR_DrawSkyWall(wallVerts, &Surf, worldtop, INT32_MAX);
+			if (gr_frontsector->floorpic == skyflatnum)
+				HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldbottom);
+		}
 	}
 
 
@@ -2612,6 +2620,234 @@ static inline void HWR_AddPolyObjectSegs(void)
 	Z_Free(pv1);
 	Z_Free(gr_fakeline);
 }
+
+#ifdef POLYOBJECTS_PLANES
+static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, fixed_t fixedheight,
+									FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector,
+									UINT8 alpha, extracolormap_t *planecolormap)
+{
+	float           height; //constant y for all points on the convex flat polygon
+	FOutVector      *v3d;
+	INT32             i;
+	float           flatxref,flatyref;
+	float fflatsize;
+	INT32 flatflag;
+	size_t len;
+	float scrollx = 0.0f, scrolly = 0.0f;
+	angle_t angle = 0;
+	FSurfaceInfo    Surf;
+	fixed_t tempxsow, tempytow;
+	size_t nrPlaneVerts;
+
+	static FOutVector *planeVerts = NULL;
+	static UINT16 numAllocedPlaneVerts = 0;
+
+	nrPlaneVerts = polysector->numVertices;
+
+	height = FIXED_TO_FLOAT(fixedheight);
+
+	if (nrPlaneVerts < 3)   //not even a triangle ?
+		return;
+
+	if (nrPlaneVerts > UINT16_MAX) // FIXME: exceeds plVerts size
+	{
+		CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, UINT16_MAX);
+		return;
+	}
+
+	// Allocate plane-vertex buffer if we need to
+	if (!planeVerts || nrPlaneVerts > numAllocedPlaneVerts)
+	{
+		numAllocedPlaneVerts = (UINT16)nrPlaneVerts;
+		Z_Free(planeVerts);
+		Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts);
+	}
+
+	len = W_LumpLength(lumpnum);
+
+	switch (len)
+	{
+		case 4194304: // 2048x2048 lump
+			fflatsize = 2048.0f;
+			flatflag = 2047;
+			break;
+		case 1048576: // 1024x1024 lump
+			fflatsize = 1024.0f;
+			flatflag = 1023;
+			break;
+		case 262144:// 512x512 lump
+			fflatsize = 512.0f;
+			flatflag = 511;
+			break;
+		case 65536: // 256x256 lump
+			fflatsize = 256.0f;
+			flatflag = 255;
+			break;
+		case 16384: // 128x128 lump
+			fflatsize = 128.0f;
+			flatflag = 127;
+			break;
+		case 1024: // 32x32 lump
+			fflatsize = 32.0f;
+			flatflag = 31;
+			break;
+		default: // 64x64 lump
+			fflatsize = 64.0f;
+			flatflag = 63;
+			break;
+	}
+
+	// reference point for flat texture coord for each vertex around the polygon
+	flatxref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].x) & (~flatflag)) / fflatsize);
+	flatyref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].y) & (~flatflag)) / fflatsize);
+
+	// transform
+	v3d = planeVerts;
+
+	if (FOFsector != NULL)
+	{
+		if (fixedheight == FOFsector->floorheight) // it's a floor
+		{
+			scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize;
+			scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize;
+			angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT;
+		}
+		else // it's a ceiling
+		{
+			scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize;
+			scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize;
+			angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT;
+		}
+	}
+	else if (gr_frontsector)
+	{
+		if (fixedheight < dup_viewz) // it's a floor
+		{
+			scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize;
+			scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize;
+			angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT;
+		}
+		else // it's a ceiling
+		{
+			scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize;
+			scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize;
+			angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT;
+		}
+	}
+
+	if (angle) // Only needs to be done if there's an altered angle
+	{
+		// This needs to be done so that it scrolls in a different direction after rotation like software
+		tempxsow = FLOAT_TO_FIXED(scrollx);
+		tempytow = FLOAT_TO_FIXED(scrolly);
+		scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
+		scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
+
+		// This needs to be done so everything aligns after rotation
+		// It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does
+		tempxsow = FLOAT_TO_FIXED(flatxref);
+		tempytow = FLOAT_TO_FIXED(flatyref);
+		flatxref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
+		flatyref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));
+	}
+
+	for (i = 0; i < nrPlaneVerts; i++,v3d++)
+	{
+		// Hurdler: add scrolling texture on floor/ceiling
+		v3d->sow = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatsize) - flatxref + scrollx); // Go from the polysector's original vertex locations
+		v3d->tow = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatsize) + scrolly); // Means the flat is offset based on the original vertex locations
+
+		// Need to rotate before translate
+		if (angle) // Only needs to be done if there's an altered angle
+		{
+			tempxsow = FLOAT_TO_FIXED(v3d->sow);
+			tempytow = FLOAT_TO_FIXED(v3d->tow);
+			v3d->sow = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));
+			v3d->tow = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle))));
+		}
+
+		v3d->x = FIXED_TO_FLOAT(polysector->lines[i]->v1->x);
+		v3d->y = height;
+		v3d->z = FIXED_TO_FLOAT(polysector->lines[i]->v1->y);
+	}
+
+
+	if (planecolormap)
+		Surf.FlatColor.rgba = HWR_Lighting(lightlevel, planecolormap->rgba, planecolormap->fadergba, false, true);
+	else
+		Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, true);
+
+	if (blendmode & PF_Translucent)
+	{
+		Surf.FlatColor.s.alpha = (UINT8)alpha;
+		blendmode |= PF_Modulated|PF_Occlude|PF_Clip;
+	}
+	else
+		blendmode |= PF_Masked|PF_Modulated|PF_Clip;
+
+	HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode);
+}
+
+static void HWR_AddPolyObjectPlanes(void)
+{
+	size_t i;
+	sector_t *polyobjsector; 
+
+	// Polyobject Planes need their own function for drawing because they don't have extrasubsectors by themselves
+	// It should be okay because polyobjects should always be convex anyway
+
+	for (i  = 0; i < numpolys; i++)
+	{
+		polyobjsector = po_ptrs[i]->lines[0]->backsector; // the in-level polyobject sector
+
+		if (!(po_ptrs[i]->flags & POF_RENDERPLANES)) // Only render planes when you should
+			continue;
+
+		if (po_ptrs[i]->translucency >= NUMTRANSMAPS)
+			continue;
+
+		if (polyobjsector->floorheight <= gr_frontsector->ceilingheight
+			&& polyobjsector->floorheight >= gr_frontsector->floorheight
+			&& (viewz < polyobjsector->floorheight))
+		{
+			if (po_ptrs[i]->translucency > 0)
+			{
+				FSurfaceInfo Surf;
+				FBITFIELD blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf);
+				HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, po_ptrs[i], polyobjsector->floorheight,
+													polyobjsector->lightlevel, Surf.FlatColor.s.alpha, polyobjsector, blendmode, NULL);
+			}
+			else
+			{
+				HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum);
+				HWR_RenderPolyObjectPlane(po_ptrs[i], polyobjsector->floorheight, PF_Occlude,
+										polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum,
+										polyobjsector, 255, NULL);
+			}
+		}
+
+		if (polyobjsector->ceilingheight >= gr_frontsector->floorheight
+			&& polyobjsector->ceilingheight <= gr_frontsector->ceilingheight
+			&& (viewz > polyobjsector->ceilingheight))
+		{
+			if (po_ptrs[i]->translucency > 0)
+			{
+				FSurfaceInfo Surf;
+				FBITFIELD blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf);
+				HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, po_ptrs[i], polyobjsector->ceilingheight,
+													polyobjsector->lightlevel, Surf.FlatColor.s.alpha, polyobjsector, blendmode, NULL);
+			}
+			else
+			{
+				HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum);
+				HWR_RenderPolyObjectPlane(po_ptrs[i], polyobjsector->ceilingheight, PF_Occlude,
+										polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum,
+										polyobjsector, 255, NULL);
+			}
+		}
+	}
+}
+#endif
 #endif
 
 // -----------------+
@@ -2922,8 +3158,13 @@ static void HWR_Subsector(size_t num)
 		// Draw polyobject lines.
 		HWR_AddPolyObjectSegs();
 
-		// Draw polyobject planes
-		//HWR_AddPolyObjectPlanes();
+#ifdef POLYOBJECTS_PLANES
+		if (sub->validcount != validcount) // This validcount situation seems to let us know that the floors have already been drawn.
+		{
+			// Draw polyobject planes
+			HWR_AddPolyObjectPlanes();
+		}
+#endif
 	}
 #endif
 
@@ -3804,6 +4045,22 @@ typedef struct
 static size_t numplanes = 0; // a list of transparent floors to be drawn
 static planeinfo_t *planeinfo = NULL;
 
+typedef struct
+{
+	polyobj_t *polysector;
+	fixed_t fixedheight;
+	INT32 lightlevel;
+	lumpnum_t lumpnum;
+	INT32 alpha;
+	sector_t *FOFSector;
+	FBITFIELD blend;
+	extracolormap_t *planecolormap;
+	INT32 drawcount;
+} polyplaneinfo_t;
+
+static size_t numpolyplanes = 0; // a list of transparent poyobject floors to be drawn
+static polyplaneinfo_t *polyplaneinfo = NULL;
+
 #ifndef SORTING
 size_t numfloors = 0;
 #else
@@ -3813,6 +4070,7 @@ size_t numfloors = 0;
 typedef struct gr_drawnode_s
 {
 	planeinfo_t *plane;
+	polyplaneinfo_t *polyplane;
 	wallinfo_t *wall;
 	gr_vissprite_t *sprite;
 
@@ -3853,6 +4111,35 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub,
 	numplanes++;
 }
 
+// Adding this for now until I can create extrasubsector info for polyobjects
+// When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane
+void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector,
+	fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap)
+{
+	static size_t allocedpolyplanes = 0;
+
+	// Force realloc if buffer has been freed
+	if (!polyplaneinfo)
+		allocedpolyplanes = 0;
+
+	if (allocedpolyplanes < numpolyplanes + 1)
+	{
+		allocedpolyplanes += MAX_TRANSPARENTFLOOR;
+		Z_Realloc(polyplaneinfo, allocedpolyplanes * sizeof (*polyplaneinfo), PU_LEVEL, &polyplaneinfo);
+	}
+
+	polyplaneinfo[numpolyplanes].fixedheight = fixedheight;
+	polyplaneinfo[numpolyplanes].lightlevel = lightlevel;
+	polyplaneinfo[numpolyplanes].lumpnum = lumpnum;
+	polyplaneinfo[numpolyplanes].polysector = polysector;
+	polyplaneinfo[numpolyplanes].alpha = alpha;
+	polyplaneinfo[numpolyplanes].FOFSector = FOFSector;
+	polyplaneinfo[numpolyplanes].blend = blend;
+	polyplaneinfo[numpolyplanes].planecolormap = planecolormap;
+	polyplaneinfo[numpolyplanes].drawcount = drawcount++;
+	numpolyplanes++;
+}
+
 //
 // HWR_CreateDrawNodes
 // Creates and sorts a list of drawnodes for the scene being rendered.
@@ -3865,12 +4152,13 @@ static void HWR_CreateDrawNodes(void)
 	// Could this be optimized into _AddTransparentWall/_AddTransparentPlane?
 	// Hell yes! But sort algorithm must be modified to use a linked list.
 	gr_drawnode_t *sortnode = Z_Calloc((sizeof(planeinfo_t)*numplanes)
+									+ (sizeof(polyplaneinfo_t)*numpolyplanes)
 									+ (sizeof(wallinfo_t)*numwalls)
 									,PU_STATIC, NULL);
 	// todo:
 	// However, in reality we shouldn't be re-copying and shifting all this information
 	// that is already lying around. This should all be in some sort of linked list or lists.
-	size_t *sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numwalls), PU_STATIC, NULL);
+	size_t *sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numpolyplanes + numwalls), PU_STATIC, NULL);
 
 	// If true, swap the draw order.
 	boolean shift = false;
@@ -3881,6 +4169,12 @@ static void HWR_CreateDrawNodes(void)
 		sortindex[p] = p;
 	}
 
+	for (i = 0; i < numpolyplanes; i++, p++)
+	{
+		sortnode[p].polyplane = &polyplaneinfo[i];
+		sortindex[p] = p;
+	}
+
 	for (i = 0; i < numwalls; i++, p++)
 	{
 		sortnode[p].wall = &wallinfo[i];
@@ -3916,6 +4210,12 @@ static void HWR_CreateDrawNodes(void)
 					if (ABS(sortnode[sortindex[i]].plane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].plane->fixedheight - pviewz))
 						shift = true;
 				}
+				if (sortnode[sortindex[prev]].polyplane)
+				{
+					// Plane (i) is further away than polyplane (prev)
+					if (ABS(sortnode[sortindex[i]].plane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].polyplane->fixedheight - pviewz))
+						shift = true;
+				}
 				else if (sortnode[sortindex[prev]].wall)
 				{
 					// Plane (i) is further than wall (prev)
@@ -3923,6 +4223,28 @@ static void HWR_CreateDrawNodes(void)
 						shift = true;
 				}
 			}
+			else if (sortnode[sortindex[i]].polyplane)
+			{
+				// What are we comparing it with?
+				if (sortnode[sortindex[prev]].plane)
+				{
+					// Plane (i) is further away than plane (prev)
+					if (ABS(sortnode[sortindex[i]].polyplane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].plane->fixedheight - pviewz))
+						shift = true;
+				}
+				if (sortnode[sortindex[prev]].polyplane)
+				{
+					// Plane (i) is further away than polyplane (prev)
+					if (ABS(sortnode[sortindex[i]].polyplane->fixedheight - pviewz) > ABS(sortnode[sortindex[prev]].polyplane->fixedheight - pviewz))
+						shift = true;
+				}
+				else if (sortnode[sortindex[prev]].wall)
+				{
+					// Plane (i) is further than wall (prev)
+					if (sortnode[sortindex[i]].polyplane->drawcount > sortnode[sortindex[prev]].wall->drawcount)
+						shift = true;
+				}
+			}
 			else if (sortnode[sortindex[i]].wall)
 			{
 				// What are we comparing it with?
@@ -3932,6 +4254,12 @@ static void HWR_CreateDrawNodes(void)
 					if (sortnode[sortindex[i]].wall->drawcount > sortnode[sortindex[prev]].plane->drawcount)
 						shift = true;
 				}
+				if (sortnode[sortindex[prev]].polyplane)
+				{
+					// Wall (i) is further than polyplane(prev)
+					if (sortnode[sortindex[i]].wall->drawcount > sortnode[sortindex[prev]].polyplane->drawcount)
+						shift = true;
+				}
 				else if (sortnode[sortindex[prev]].wall)
 				{
 					// Wall (i) is further than wall (prev)
@@ -3968,6 +4296,16 @@ static void HWR_CreateDrawNodes(void)
 			HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel,
 				sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->fogplane, sortnode[sortindex[i]].plane->planecolormap);
 		}
+		else if (sortnode[sortindex[i]].polyplane)
+		{
+			// We aren't traversing the BSP tree, so make gr_frontsector null to avoid crashes.
+			gr_frontsector = NULL;
+
+			if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture))
+				HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum);
+			HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel,
+				sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap);
+		}
 		else if (sortnode[sortindex[i]].wall)
 		{
 			if (!(sortnode[sortindex[i]].wall->blend & PF_NoTexture))
@@ -3979,6 +4317,7 @@ static void HWR_CreateDrawNodes(void)
 
 	numwalls = 0;
 	numplanes = 0;
+	numpolyplanes = 0;
 
 	// No mem leaks, please.
 	Z_Free(sortnode);
@@ -4768,7 +5107,7 @@ if (0)
 #endif
 
 #ifdef SORTING
-	if (numplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything
+	if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything
 	{
 		HWR_CreateDrawNodes();
 	}
@@ -4998,12 +5337,12 @@ if (0)
 #endif
 
 #ifdef SORTING
-	if (numplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything
+	if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything
 	{
 		HWR_CreateDrawNodes();
 	}
 #else
-	if (numfloors || numwalls)
+	if (numfloors || numpolyplanes || numwalls)
 	{
 		HWD.pfnSetTransform(&atransform);
 		if (numfloors)