Support polyobject planes in software renderer

Backported from private trunk (it's all my work so shoosh) so other people can check out how it's done (and maybe provide some additional bugfixes? hint hint?)
This commit is contained in:
RedEnchilada 2014-10-31 23:34:07 -05:00
parent 5b07cf8ff0
commit 2df51dc151
6 changed files with 161 additions and 23 deletions

View file

@ -453,7 +453,7 @@ extern const char *compdate, *comptime, *comprevision;
//#define CHAOSISNOTDEADYET
/// Polyobject fake flat code
//#define POLYOBJECTS_PLANES
#define POLYOBJECTS_PLANES
/// Blue spheres for future use.
/// \todo Remove this define.

View file

@ -683,6 +683,33 @@ void R_SortPolyObjects(subsector_t *sub)
}
}
//
// R_PolysegCompare
//
// Callback for qsort to sort the segs of a polyobject. Returns such that the
// closer one is sorted first. I sure hope this doesn't break anything. -Red
//
static int R_PolysegCompare(const void *p1, const void *p2)
{
const seg_t *seg1 = *(const seg_t * const *)p1;
const seg_t *seg2 = *(const seg_t * const *)p2;
fixed_t dist1, dist2;
// TODO might be a better way to get distance?
#define vxdist(v) FixedMul(R_PointToDist(v->x, v->y), FINECOSINE((R_PointToAngle(v->x, v->y)-viewangle)>>ANGLETOFINESHIFT))+0xFFFFFFF
dist1 = min(vxdist(seg1->v1), vxdist(seg1->v2));
dist2 = min(vxdist(seg2->v1), vxdist(seg2->v2));
if (dist1 == dist2) { // Segs connect toward the front, so use the back verts to determine order!
dist1 = max(vxdist(seg1->v1), vxdist(seg1->v2));
dist2 = max(vxdist(seg2->v1), vxdist(seg2->v2));
}
#undef vxdist
return dist1-dist2;
}
//
// R_AddPolyObjects
//
@ -709,6 +736,7 @@ static void R_AddPolyObjects(subsector_t *sub)
// render polyobjects
for (i = 0; i < numpolys; ++i)
{
qsort(po_ptrs[i]->segs, po_ptrs[i]->segCount, sizeof(seg_t *), R_PolysegCompare);
for (j = 0; j < po_ptrs[i]->segCount; ++j)
R_AddLine(po_ptrs[i]->segs[j]);
}
@ -909,15 +937,28 @@ static void R_Subsector(size_t num)
&& polysec->floorheight >= frontsector->floorheight
&& (viewz < polysec->floorheight))
{
fixed_t xoff, yoff;
xoff = polysec->floor_xoffs;
yoff = polysec->floor_yoffs;
if (po->angle != 0) {
angle_t fineshift = po->angle >> ANGLETOFINESHIFT;
xoff -= FixedMul(FINECOSINE(fineshift), po->centerPt.x)+FixedMul(FINESINE(fineshift), po->centerPt.y);
yoff -= FixedMul(FINESINE(fineshift), po->centerPt.x)-FixedMul(FINECOSINE(fineshift), po->centerPt.y);
} else {
xoff -= po->centerPt.x;
yoff += po->centerPt.y;
}
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight);
light = 0;
ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic,
polysec->lightlevel, polysec->floor_xoffs,
polysec->floor_yoffs,
polysec->floorpic_angle,
polysec->lightlevel, xoff, yoff,
polysec->floorpic_angle-po->angle,
NULL,
NULL);
ffloor[numffloors].plane->polyobj = true;
ffloor[numffloors].plane->polyobj = po;
ffloor[numffloors].height = polysec->floorheight;
ffloor[numffloors].polyobj = po;
@ -934,12 +975,27 @@ static void R_Subsector(size_t num)
&& polysec->ceilingheight <= frontsector->ceilingheight
&& (viewz > polysec->ceilingheight))
{
fixed_t xoff, yoff;
xoff = polysec->ceiling_xoffs;
yoff = polysec->ceiling_yoffs;
if (po->angle != 0) {
angle_t fineshift = po->angle >> ANGLETOFINESHIFT;
xoff -= FixedMul(FINECOSINE(fineshift), po->centerPt.x)+FixedMul(FINESINE(fineshift), po->centerPt.y);
yoff -= FixedMul(FINESINE(fineshift), po->centerPt.x)-FixedMul(FINECOSINE(fineshift), po->centerPt.y);
} else {
xoff -= po->centerPt.x;
yoff += po->centerPt.y;
}
light = R_GetPlaneLight(frontsector, polysec->ceilingheight, viewz < polysec->ceilingheight);
light = 0;
ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic,
polysec->lightlevel, polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle,
polysec->lightlevel, xoff, yoff, polysec->ceilingpic_angle-po->angle,
NULL, NULL);
ffloor[numffloors].plane->polyobj = true;
ffloor[numffloors].plane->polyobj = po;
ffloor[numffloors].polyobj = po;
ffloor[numffloors].height = polysec->ceilingheight;
// ffloor[numffloors].ffloor = rover;

View file

@ -409,6 +409,10 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
for (check = visplanes[hash]; check; check = check->next)
{
#ifdef POLYOBJECTS_PLANES
if (check->polyobj && pfloor)
continue;
#endif
if (height == check->height && picnum == check->picnum
&& lightlevel == check->lightlevel
&& xoff == check->xoffs && yoff == check->yoffs
@ -434,6 +438,9 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
check->viewz = viewz;
check->viewangle = viewangle + plangle;
check->plangle = plangle;
#ifdef POLYOBJECTS_PLANES
check->polyobj = NULL;
#endif
memset(check->top, 0xff, sizeof (check->top));
memset(check->bottom, 0x00, sizeof (check->bottom));
@ -666,6 +673,42 @@ void R_DrawSinglePlane(visplane_t *pl)
itswater = false;
#endif
spanfunc = basespanfunc;
#ifdef POLYOBJECTS_PLANES
if (pl->polyobj && pl->polyobj->translucency != 0) {
spanfunc = R_DrawTranslucentSpan_8;
// Hacked up support for alpha value in software mode Tails 09-24-2002 (sidenote: ported to polys 10-15-2014, there was no time travel involved -Red)
if (pl->polyobj->translucency >= 10)
return; // Don't even draw it
else if (pl->polyobj->translucency == 9)
ds_transmap = ((tr_trans90)<<FF_TRANSSHIFT) - 0x10000 + transtables;
else if (pl->polyobj->translucency == 8)
ds_transmap = ((tr_trans80)<<FF_TRANSSHIFT) - 0x10000 + transtables;
else if (pl->polyobj->translucency == 7)
ds_transmap = ((tr_trans70)<<FF_TRANSSHIFT) - 0x10000 + transtables;
else if (pl->polyobj->translucency == 6)
ds_transmap = ((tr_trans60)<<FF_TRANSSHIFT) - 0x10000 + transtables;
else if (pl->polyobj->translucency == 5)
ds_transmap = ((tr_trans50)<<FF_TRANSSHIFT) - 0x10000 + transtables;
else if (pl->polyobj->translucency == 4)
ds_transmap = ((tr_trans40)<<FF_TRANSSHIFT) - 0x10000 + transtables;
else if (pl->polyobj->translucency == 3)
ds_transmap = ((tr_trans30)<<FF_TRANSSHIFT) - 0x10000 + transtables;
else if (pl->polyobj->translucency == 2)
ds_transmap = ((tr_trans20)<<FF_TRANSSHIFT) - 0x10000 + transtables;
else if (pl->polyobj->translucency == 1)
ds_transmap = ((tr_trans10)<<FF_TRANSSHIFT) - 0x10000 + transtables;
else // Opaque, but allow transparent flat pixels
spanfunc = splatfunc;
if (pl->extra_colormap && pl->extra_colormap->fog)
light = (pl->lightlevel >> LIGHTSEGSHIFT);
else
light = LIGHTLEVELS-1;
} else
#endif
if (pl->ffloor)
{
// Don't draw planes that shouldn't be drawn.

View file

@ -59,7 +59,7 @@ typedef struct visplane_s
struct ffloor_s *ffloor;
#ifdef POLYOBJECTS_PLANES
boolean polyobj;
polyobj_t *polyobj;
#endif
} visplane_t;

View file

@ -589,7 +589,8 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
// draw the texture
col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3);
#ifdef POLYOBJECTS_PLANES
//#ifdef POLYOBJECTS_PLANES
#if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red
if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES))
{
fixed_t my_topscreen;
@ -611,7 +612,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
for (i = 0; i < numffloors; i++)
{
if (!ffloor[i].polyobj)
if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg)
continue;
if (ffloor[i].height < viewz)
@ -1120,8 +1121,16 @@ static void R_RenderSegLoop (void)
for (i = 0; i < numffloors; i++)
{
#ifdef POLYOBJECTS_PLANES
if (curline->polyseg && !ffloor[i].polyobj)
continue;
//if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg))
//continue; // Causes issues with FOF planes in The Wall -Red
// FIXME hack to fix planes disappearing when a seg goes behind the camera. This NEEDS to be changed to be done properly. -Red
if (curline->polyseg) {
if (ffloor[i].plane->minx > rw_x)
ffloor[i].plane->minx = rw_x;
else if (ffloor[i].plane->maxx < rw_x)
ffloor[i].plane->maxx = rw_x;
}
#endif
if (ffloor[i].height < viewz)
@ -1135,6 +1144,13 @@ static void R_RenderSegLoop (void)
if (bottom_w > bottom)
bottom_w = bottom;
#ifdef POLYOBJECTS_PLANES
// Polyobject-specific hack to fix plane leaking -Red
if (curline->polyseg && ffloor[i].polyobj && ffloor[i].polyobj == curline->polyseg && top_w >= bottom_w) {
ffloor[i].plane->top[rw_x] = ffloor[i].plane->bottom[rw_x] = 0xFFFF;
} else
#endif
if (top_w <= bottom_w)
{
ffloor[i].plane->top[rw_x] = (INT16)top_w;
@ -1152,6 +1168,13 @@ static void R_RenderSegLoop (void)
if (bottom_w > bottom)
bottom_w = bottom;
#ifdef POLYOBJECTS_PLANES
// Polyobject-specific hack to fix plane leaking -Red
if (curline->polyseg && ffloor[i].polyobj && ffloor[i].polyobj == curline->polyseg && top_w >= bottom_w) {
ffloor[i].plane->top[rw_x] = ffloor[i].plane->bottom[rw_x] = 0xFFFF;
} else
#endif
if (top_w <= bottom_w)
{
ffloor[i].plane->top[rw_x] = (INT16)top_w;
@ -1327,9 +1350,9 @@ static void R_RenderSegLoop (void)
for (i = 0; i < numffloors; i++)
{
#ifdef POLYOBJECTS_PLANES
if (curline->polyseg && !ffloor[i].polyobj)
continue;
#if 0 //#ifdef POLYOBJECTS_PLANES
if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg))
continue; // Causes issues with FOF planes in The Wall -Red
#endif
ffloor[i].f_frac += ffloor[i].f_step;
@ -1339,9 +1362,9 @@ static void R_RenderSegLoop (void)
{
INT32 y_w;
#ifdef POLYOBJECTS_PLANES
if (curline->polyseg && !ffloor[i].polyobj)
continue;
#if 0 //#ifdef POLYOBJECTS_PLANES
if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg))
continue; // Causes issues with FOF planes in The Wall -Red
#endif
y_w = ffloor[i].b_frac >> HEIGHTBITS;
@ -1488,9 +1511,9 @@ void R_StoreWallRange(INT32 start, INT32 stop)
{
for (i = 0; i < numffloors; i++)
{
#ifdef POLYOBJECTS_PLANES
if (ds_p->curline->polyseg && !ffloor[i].polyobj)
continue;
#if 0 //#ifdef POLYOBJECTS_PLANES
if (ds_p->curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != ds_p->curline->polyseg))
continue; // Causes issues with FOF planes in The Wall -Red
#endif
ffloor[i].f_pos = ffloor[i].height - viewz;
}
@ -1989,8 +2012,10 @@ void R_StoreWallRange(INT32 start, INT32 stop)
{
for (i = 0; i < numffloors; i++)
{
// if (curline->polyseg && !ffloor[i].polyobj)
// continue;
#if 0 //#ifdef POLYOBJECTS_PLANES
if (curline->polyseg && (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg))
continue; // Causes issues with FOF planes in The Wall -Red
#endif
ffloor[i].f_pos >>= 4;
ffloor[i].f_step = FixedMul(-rw_scalestep, ffloor[i].f_pos);

View file

@ -1830,6 +1830,20 @@ static void R_CreateDrawNodes(void)
}
else if (r2->seg)
{
#ifdef POLYOBJECTS_PLANES
if (r2->seg->curline->polyseg && rover->mobj && P_MobjInsidePolyobj(r2->seg->curline->polyseg, rover->mobj)) {
// Determine if we need to sort in front of the polyobj, based on the planes. This fixes the issue where
// polyobject planes render above the object standing on them. (A bit hacky... but it works.) -Red
mobj_t *mo = rover->mobj;
sector_t *po = r2->seg->curline->backsector;
if (po->ceilingheight < viewz && mo->z+mo->height > po->ceilingheight)
continue;
if (po->floorheight > viewz && mo->z < po->floorheight)
continue;
}
#endif
if (rover->x1 > r2->seg->x2 || rover->x2 < r2->seg->x1)
continue;