OpenGL: Polyobject Planes

This commit is contained in:
Sryder13 2014-10-27 20:57:45 +00:00
parent 1ab29ba96a
commit 0c0ede6f18

View file

@ -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,6 +1697,8 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
}
// Isn't this just the most lovely mess
if (!gr_curline->polyseg) // Don't do it for polyobjects
{
if (gr_frontsector->ceilingpic == skyflatnum || gr_backsector->ceilingpic == skyflatnum)
{
fixed_t depthwallheight;
@ -1770,6 +1774,7 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
}
}
}
}
else
{
// Single sided line... Deal only with the middletexture (if one exists)
@ -1809,11 +1814,14 @@ static void HWR_StoreWallRange(double startfrac, double endfrac)
}
}
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);
}
}
//Hurdler: 3d-floors test
@ -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();
#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();
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)