From 2df51dc151e143bfa8d2b67a889352ca50b2d392 Mon Sep 17 00:00:00 2001 From: RedEnchilada Date: Fri, 31 Oct 2014 23:34:07 -0500 Subject: [PATCH] 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?) --- src/doomdef.h | 2 +- src/r_bsp.c | 68 +++++++++++++++++++++++++++++++++++++++++++++----- src/r_plane.c | 43 +++++++++++++++++++++++++++++++ src/r_plane.h | 2 +- src/r_segs.c | 55 +++++++++++++++++++++++++++++----------- src/r_things.c | 14 +++++++++++ 6 files changed, 161 insertions(+), 23 deletions(-) diff --git a/src/doomdef.h b/src/doomdef.h index a978e047b..ad45f497b 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -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. diff --git a/src/r_bsp.c b/src/r_bsp.c index 5a90f1fca..cfd628b5c 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -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; diff --git a/src/r_plane.c b/src/r_plane.c index 7e1764fc5..5833bf6d5 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -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)<polyobj->translucency == 8) + ds_transmap = ((tr_trans80)<polyobj->translucency == 7) + ds_transmap = ((tr_trans70)<polyobj->translucency == 6) + ds_transmap = ((tr_trans60)<polyobj->translucency == 5) + ds_transmap = ((tr_trans50)<polyobj->translucency == 4) + ds_transmap = ((tr_trans40)<polyobj->translucency == 3) + ds_transmap = ((tr_trans30)<polyobj->translucency == 2) + ds_transmap = ((tr_trans20)<polyobj->translucency == 1) + ds_transmap = ((tr_trans10)<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. diff --git a/src/r_plane.h b/src/r_plane.h index 1f046588f..bd0df27c0 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -59,7 +59,7 @@ typedef struct visplane_s struct ffloor_s *ffloor; #ifdef POLYOBJECTS_PLANES - boolean polyobj; + polyobj_t *polyobj; #endif } visplane_t; diff --git a/src/r_segs.c b/src/r_segs.c index 1070bff7c..a3da0f3ca 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -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); diff --git a/src/r_things.c b/src/r_things.c index c0f33dafb..4fc785773 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -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;