diff --git a/src/doomdef.h b/src/doomdef.h index a978e047ba3ecad97cbebbbfd44cb57273b158f6..ad45f497b8a4d4d9376cd9cbcad31f5c8a78d3ab 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 5a90f1fca7e6c1266b16f98ac5e1ad4e106ce278..cfd628b5c5f53e419f7b1c416706da6077810e1a 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 7e1764fc549dfee930a2bc910209051e551e2ee6..5833bf6d50ea2a1234e8d2a24de9ee288ae02095 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)<<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. diff --git a/src/r_plane.h b/src/r_plane.h index 1f046588f3941748d6815484d02b4f5d4f1f19ee..bd0df27c08f1fcb6f195055f8ccb69983f80ffc3 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 1070bff7c01e896d288f2b1f5bc554b060e32c76..a3da0f3cab93e1aae888ae7324896a80b4519eff 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 c0f33dafb7af18dd6af78491301b1579c92e97ab..4fc785773d666770ba15063cca13e0038a34ad50 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;