Skip to content

Commit

Permalink
Support polyobject planes in software renderer
Browse files Browse the repository at this point in the history
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?)
  • Loading branch information
RedEnchilada committed Nov 1, 2014
1 parent 5b07cf8 commit 2df51dc
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/doomdef.h
Expand Up @@ -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.
Expand Down
68 changes: 62 additions & 6 deletions src/r_bsp.c
Expand Up @@ -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
//
Expand All @@ -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]);
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
43 changes: 43 additions & 0 deletions src/r_plane.c
Expand Up @@ -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
Expand All @@ -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));
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion src/r_plane.h
Expand Up @@ -59,7 +59,7 @@ typedef struct visplane_s

struct ffloor_s *ffloor;
#ifdef POLYOBJECTS_PLANES
boolean polyobj;
polyobj_t *polyobj;
#endif
} visplane_t;

Expand Down
55 changes: 40 additions & 15 deletions src/r_segs.c
Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down
14 changes: 14 additions & 0 deletions src/r_things.c
Expand Up @@ -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;

Expand Down

0 comments on commit 2df51dc

Please sign in to comment.