diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 621ec723..f87af074 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -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,78 +1697,81 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } // Isn't this just the most lovely mess - if (gr_frontsector->ceilingpic == skyflatnum || gr_backsector->ceilingpic == skyflatnum) + if (!gr_curline->polyseg) // Don't do it for polyobjects { - fixed_t depthwallheight; - - if (!gr_sidedef->toptexture || (gr_frontsector->ceilingpic == skyflatnum && gr_backsector->ceilingpic == skyflatnum)) // when both sectors are sky, the top texture isn't drawn - depthwallheight = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; - else - depthwallheight = gr_frontsector->ceilingheight > gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; - - if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier + if (gr_frontsector->ceilingpic == skyflatnum || gr_backsector->ceilingpic == skyflatnum) { - if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier + fixed_t depthwallheight; + + if (!gr_sidedef->toptexture || (gr_frontsector->ceilingpic == skyflatnum && gr_backsector->ceilingpic == skyflatnum)) // when both sectors are sky, the top texture isn't drawn + depthwallheight = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; + else + depthwallheight = gr_frontsector->ceilingheight > gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; + + if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier { - if (!gr_sidedef->bottomtexture) // Only extend further down if there's no texture - HWR_DrawSkyWall(wallVerts, &Surf, worldbottom < worldlow ? worldbottom : worldlow, INT32_MAX); - else - HWR_DrawSkyWall(wallVerts, &Surf, worldbottom > worldlow ? worldbottom : worldlow, INT32_MAX); + if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier + { + if (!gr_sidedef->bottomtexture) // Only extend further down if there's no texture + HWR_DrawSkyWall(wallVerts, &Surf, worldbottom < worldlow ? worldbottom : worldlow, INT32_MAX); + else + HWR_DrawSkyWall(wallVerts, &Surf, worldbottom > worldlow ? worldbottom : worldlow, INT32_MAX); + } + // behind sector is not a thok barrier + else if (gr_backsector->ceilingheight <= gr_frontsector->ceilingheight) // behind sector ceiling is lower or equal to current sector + HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); + // gr_front/backsector heights need to be used here because of the worldtop being set to worldhigh earlier on } - // behind sector is not a thok barrier - else if (gr_backsector->ceilingheight <= gr_frontsector->ceilingheight) // behind sector ceiling is lower or equal to current sector - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - // gr_front/backsector heights need to be used here because of the worldtop being set to worldhigh earlier on - } - else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not - { - if (gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier ceiling height is equal to or greater than current sector ceiling height - || gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier ceiling height is equal to or less than current sector floor height - || gr_backsector->ceilingpic != skyflatnum) // thok barrier is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - } - else // neither sectors are thok barriers - { - if ((gr_backsector->ceilingheight < gr_frontsector->ceilingheight && !gr_sidedef->toptexture) // no top texture and sector behind is lower - || gr_backsector->ceilingpic != skyflatnum) // behind sector is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); - } - } - // And now for sky floors! - if (gr_frontsector->floorpic == skyflatnum || gr_backsector->floorpic == skyflatnum) - { - fixed_t depthwallheight; - - if (!gr_sidedef->bottomtexture) - depthwallheight = worldbottom > worldlow ? worldbottom : worldlow; - else - depthwallheight = worldbottom < worldlow ? worldbottom : worldlow; - - if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier - { - if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier + else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not { - if (!gr_sidedef->toptexture) // Only extend up if there's no texture - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop > worldhigh ? worldtop : worldhigh); - else - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop < worldhigh ? worldtop : worldhigh); + if (gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier ceiling height is equal to or greater than current sector ceiling height + || gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier ceiling height is equal to or less than current sector floor height + || gr_backsector->ceilingpic != skyflatnum) // thok barrier is not a sky + HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); + } + else // neither sectors are thok barriers + { + if ((gr_backsector->ceilingheight < gr_frontsector->ceilingheight && !gr_sidedef->toptexture) // no top texture and sector behind is lower + || gr_backsector->ceilingpic != skyflatnum) // behind sector is not a sky + HWR_DrawSkyWall(wallVerts, &Surf, depthwallheight, INT32_MAX); } - // behind sector is not a thok barrier - else if (gr_backsector->floorheight >= gr_frontsector->floorheight) // behind sector floor is greater or equal to current sector - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); } - else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not + // And now for sky floors! + if (gr_frontsector->floorpic == skyflatnum || gr_backsector->floorpic == skyflatnum) { - if (gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier floor height is equal to or less than current sector floor height - || gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier floor height is equal to or greater than current sector ceiling height - || gr_backsector->floorpic != skyflatnum) // thok barrier is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); - } - else // neither sectors are thok barriers - { - if ((gr_backsector->floorheight > gr_frontsector->floorheight && !gr_sidedef->bottomtexture) // no bottom texture and sector behind is higher - || gr_backsector->floorpic != skyflatnum) // behind sector is not a sky - HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); + fixed_t depthwallheight; + + if (!gr_sidedef->bottomtexture) + depthwallheight = worldbottom > worldlow ? worldbottom : worldlow; + else + depthwallheight = worldbottom < worldlow ? worldbottom : worldlow; + + if (gr_frontsector->ceilingheight-gr_frontsector->floorheight <= 0) // current sector is a thok barrier + { + if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is also a thok barrier + { + if (!gr_sidedef->toptexture) // Only extend up if there's no texture + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop > worldhigh ? worldtop : worldhigh); + else + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, worldtop < worldhigh ? worldtop : worldhigh); + } + // behind sector is not a thok barrier + else if (gr_backsector->floorheight >= gr_frontsector->floorheight) // behind sector floor is greater or equal to current sector + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); + } + else if (gr_backsector->ceilingheight-gr_backsector->floorheight <= 0) // behind sector is a thok barrier, current sector is not + { + if (gr_backsector->floorheight <= gr_frontsector->floorheight // thok barrier floor height is equal to or less than current sector floor height + || gr_backsector->ceilingheight >= gr_frontsector->ceilingheight // thok barrier floor height is equal to or greater than current sector ceiling height + || gr_backsector->floorpic != skyflatnum) // thok barrier is not a sky + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); + } + else // neither sectors are thok barriers + { + if ((gr_backsector->floorheight > gr_frontsector->floorheight && !gr_sidedef->bottomtexture) // no bottom texture and sector behind is higher + || gr_backsector->floorpic != skyflatnum) // behind sector is not a sky + HWR_DrawSkyWall(wallVerts, &Surf, INT32_MIN, depthwallheight); + } } } } @@ -1809,10 +1814,13 @@ static void HWR_StoreWallRange(double startfrac, double endfrac) } } - 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); + 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); + } } @@ -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(); - // Draw polyobject planes - //HWR_AddPolyObjectPlanes(); +#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(); + } +#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)