From 98ba396dbcb45d7c056e8f6f765768df86a7604f Mon Sep 17 00:00:00 2001 From: Lactozilla Date: Fri, 16 Feb 2024 17:28:55 -0300 Subject: [PATCH] Fix issues related to texture scaling --- src/hardware/hw_main.c | 562 +++++++++++++++++++++++------------------ src/p_setup.c | 2 - src/r_defs.h | 6 +- src/r_main.c | 55 +--- src/r_main.h | 5 +- src/r_segs.c | 308 +++++++++++++--------- src/r_things.c | 34 ++- src/r_things.h | 1 + src/tables.h | 2 +- 9 files changed, 541 insertions(+), 434 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 9c1a95c93..8c4651c04 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1034,6 +1034,191 @@ static boolean HWR_BlendMidtextureSurface(FSurfaceInfo *pSurf) return true; } +static void HWR_RenderMidtexture(INT32 gl_midtexture, float cliplow, float cliphigh, fixed_t worldtop, fixed_t worldbottom, fixed_t worldhigh, fixed_t worldlow, fixed_t worldtopslope, fixed_t worldbottomslope, fixed_t worldhighslope, fixed_t worldlowslope, UINT32 lightnum, FOutVector *inWallVerts) +{ + FOutVector wallVerts[4]; + + FSurfaceInfo Surf; + Surf.PolyColor.s.alpha = 255; + + // Determine if it's visible + if (!HWR_BlendMidtextureSurface(&Surf)) + return; + + fixed_t texheight = FixedDiv(textureheight[gl_midtexture], abs(gl_sidedef->scaley_mid)); + INT32 repeats; + + if (gl_sidedef->repeatcnt) + repeats = 1 + gl_sidedef->repeatcnt; + else if (gl_linedef->flags & ML_WRAPMIDTEX) + { + fixed_t high, low; + + if (gl_frontsector->ceilingheight > gl_backsector->ceilingheight) + high = gl_backsector->ceilingheight; + else + high = gl_frontsector->ceilingheight; + + if (gl_frontsector->floorheight > gl_backsector->floorheight) + low = gl_frontsector->floorheight; + else + low = gl_backsector->floorheight; + + repeats = (high - low) / texheight; + if ((high - low) % texheight) + repeats++; // tile an extra time to fill the gap -- Monster Iestyn + } + else + repeats = 1; + + GLMapTexture_t *grTex = HWR_GetTexture(gl_midtexture); + float xscale = FixedToFloat(gl_sidedef->scalex_mid); + float yscale = FixedToFloat(gl_sidedef->scaley_mid); + + // SoM: a little note: popentop and popenbottom + // record the limits the texture can be displayed in. + // polytop and polybottom, are the ideal (i.e. unclipped) + // heights of the polygon, and h & l, are the final (clipped) + // poly coords. + fixed_t popentop, popenbottom, polytop, polybottom, lowcut, highcut; + fixed_t popentopslope, popenbottomslope, polytopslope, polybottomslope, lowcutslope, highcutslope; + + // NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to, + // you must use the linedef's backsector to be correct + // From CB + if (gl_curline->polyseg) + { + // Change this when polyobjects support slopes + popentop = popentopslope = gl_curline->backsector->ceilingheight; + popenbottom = popenbottomslope = gl_curline->backsector->floorheight; + } + else + { + popentop = min(worldtop, worldhigh); + popenbottom = max(worldbottom, worldlow); + popentopslope = min(worldtopslope, worldhighslope); + popenbottomslope = max(worldbottomslope, worldlowslope); + } + + // Find the wall's coordinates + fixed_t midtexheight = texheight * repeats; + + fixed_t rowoffset = FixedDiv(gl_sidedef->rowoffset + gl_sidedef->offsety_mid, abs(gl_sidedef->scaley_mid)); + + // Texture is not skewed + if (gl_linedef->flags & ML_NOSKEW) + { + // Peg it to the floor + if (gl_linedef->flags & ML_MIDPEG) + { + polybottom = max(gl_frontsector->floorheight, gl_backsector->floorheight) + rowoffset; + polytop = polybottom + midtexheight; + } + // Peg it to the ceiling + else + { + polytop = min(gl_frontsector->ceilingheight, gl_backsector->ceilingheight) + rowoffset; + polybottom = polytop - midtexheight; + } + + // The right side's coordinates are the the same as the left side + polytopslope = polytop; + polybottomslope = polybottom; + } + // Skew the texture, but peg it to the floor + else if (gl_linedef->flags & ML_MIDPEG) + { + polybottom = popenbottom + rowoffset; + polytop = polybottom + midtexheight; + polybottomslope = popenbottomslope + rowoffset; + polytopslope = polybottomslope + midtexheight; + } + // Skew it according to the ceiling's slope + else + { + polytop = popentop + rowoffset; + polybottom = polytop - midtexheight; + polytopslope = popentopslope + rowoffset; + polybottomslope = polytopslope - midtexheight; + } + + // The cut-off values of a linedef can always be constant, since every line has an absoulute front and or back sector + if (gl_curline->polyseg) + { + lowcut = polybottom; + highcut = polytop; + lowcutslope = polybottomslope; + highcutslope = polytopslope; + } + else + { + lowcut = popenbottom; + highcut = popentop; + lowcutslope = popenbottomslope; + highcutslope = popentopslope; + } + + fixed_t h = min(highcut, polytop); + fixed_t l = max(polybottom, lowcut); + fixed_t hS = min(highcutslope, polytopslope); + fixed_t lS = max(polybottomslope, lowcutslope); + + // PEGGING + fixed_t texturevpeg, texturevpegslope; + + if (gl_linedef->flags & ML_MIDPEG) + { + texturevpeg = midtexheight - h + polybottom; + texturevpegslope = midtexheight - hS + polybottomslope; + } + else + { + texturevpeg = polytop - h; + texturevpegslope = polytopslope - hS; + } + + memcpy(wallVerts, inWallVerts, sizeof(wallVerts)); + + // Left side + wallVerts[3].t = texturevpeg * yscale * grTex->scaleY; + wallVerts[0].t = (h - l + texturevpeg) * yscale * grTex->scaleY; + wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->textureoffset + gl_sidedef->offsetx_mid) * grTex->scaleX; + + // Right side + wallVerts[2].t = texturevpegslope * yscale * grTex->scaleY; + wallVerts[1].t = (hS - lS + texturevpegslope) * yscale * grTex->scaleY; + wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->textureoffset + gl_sidedef->offsetx_mid) * grTex->scaleX; + + // set top/bottom coords + // Take the texture peg into account, rather than changing the offsets past + // where the polygon might not be. + wallVerts[3].y = FIXED_TO_FLOAT(h); + wallVerts[0].y = FIXED_TO_FLOAT(l); + wallVerts[2].y = FIXED_TO_FLOAT(hS); + wallVerts[1].y = FIXED_TO_FLOAT(lS); + + // TODO: Actually use the surface's flags so that I don't have to do this + FUINT blendmode = Surf.PolyFlags; + + // Render midtextures on two-sided lines with a z-buffer offset. + // This will cause the midtexture appear on top, if a FOF overlaps with it. + blendmode |= PF_Decal; + + extracolormap_t *colormap = gl_frontsector->extra_colormap; + + if (gl_frontsector->numlights) + { + if (!(blendmode & PF_Masked)) + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_TRANSLUCENT, NULL, blendmode); + else + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_CUTLEVEL, NULL, blendmode); + } + else if (!(blendmode & PF_Masked)) + HWR_AddTransparentWall(wallVerts, &Surf, gl_midtexture, blendmode, false, lightnum, colormap); + else + HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); +} + // // HWR_ProcessSeg // A portion or all of a wall segment will be drawn, from startfrac to endfrac, @@ -1105,9 +1290,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].z = wallVerts[1].z = ve.y; // x offset the texture - fixed_t texturehpeg = gl_sidedef->textureoffset + gl_curline->offset; - float cliplow = (float)texturehpeg; - float cliphigh = (float)(texturehpeg + (gl_curline->flength*FRACUNIT)); + float cliplow = (float)gl_curline->offset; + float cliphigh = cliplow + (gl_curline->flength * FRACUNIT); FUINT lightnum = HWR_CalcWallLight(gl_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); extracolormap_t *colormap = gl_frontsector->extra_colormap; @@ -1122,6 +1306,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (gl_backsector) { INT32 gl_toptexture = 0, gl_bottomtexture = 0; + fixed_t texturevpeg; SLOPEPARAMS(gl_backsector->c_slope, worldhigh, worldhighslope, gl_backsector->ceilingheight) @@ -1151,30 +1336,46 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if ((worldhighslope < worldtopslope || worldhigh < worldtop) && gl_toptexture) { grTex = HWR_GetTexture(gl_toptexture); - xscale = FixedToFloat(gl_sidedef->scalex_top); - yscale = FixedToFloat(gl_sidedef->scaley_top); + xscale = FixedToFloat(abs(gl_sidedef->scalex_top)); + yscale = FixedToFloat(abs(gl_sidedef->scaley_top)); - fixed_t texheight = FixedDiv(textureheight[gl_toptexture], gl_sidedef->scaley_top); + fixed_t offsetx_top = gl_sidedef->textureoffset + gl_sidedef->offsetx_top; + + float left = cliplow * xscale; + float right = cliphigh * xscale; + if (gl_sidedef->scalex_top < 0) + { + left = -left; + right = -right; + offsetx_top = -offsetx_top; + } + + fixed_t texheight = textureheight[gl_toptexture]; + fixed_t texheightscaled = FixedDiv(texheight, abs(gl_sidedef->scaley_top)); // PEGGING + // FIXME: This is probably not correct? if (gl_linedef->flags & ML_DONTPEGTOP) texturevpeg = 0; else if (gl_linedef->flags & ML_SKEWTD) texturevpeg = worldhigh + texheight - worldtop; else - texturevpeg = gl_backsector->ceilingheight + texheight - gl_frontsector->ceilingheight; + texturevpeg = gl_backsector->ceilingheight + texheightscaled - gl_frontsector->ceilingheight; texturevpeg *= yscale; - texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_top; + if (gl_sidedef->scaley_top < 0) + texturevpeg -= gl_sidedef->rowoffset + gl_sidedef->offsety_top; + else + texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_top; // This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway - texturevpeg %= texheight; + texturevpeg %= texheightscaled; wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + (gl_frontsector->ceilingheight - gl_backsector->ceilingheight) * yscale) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_top) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_top) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (left + offsetx_top) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (right + offsetx_top) * grTex->scaleX; // Adjust t value for sloped walls if (!(gl_linedef->flags & ML_SKEWTD)) @@ -1199,6 +1400,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].t = wallVerts[1].t - (worldtopslope - worldhighslope) * yscale * grTex->scaleY; } + if (gl_sidedef->scaley_top < 0) + { + wallVerts[0].t = -wallVerts[0].t; + wallVerts[1].t = -wallVerts[1].t; + wallVerts[2].t = -wallVerts[2].t; + wallVerts[3].t = -wallVerts[3].t; + } + // set top/bottom coords wallVerts[3].y = FIXED_TO_FLOAT(worldtop); wallVerts[0].y = FIXED_TO_FLOAT(worldhigh); @@ -1217,8 +1426,19 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if ((worldlowslope > worldbottomslope || worldlow > worldbottom) && gl_bottomtexture) { grTex = HWR_GetTexture(gl_bottomtexture); - xscale = FixedToFloat(gl_sidedef->scalex_bottom); - yscale = FixedToFloat(gl_sidedef->scaley_bottom); + xscale = FixedToFloat(abs(gl_sidedef->scalex_bottom)); + yscale = FixedToFloat(abs(gl_sidedef->scaley_bottom)); + + fixed_t offsetx_bottom = gl_sidedef->textureoffset + gl_sidedef->offsetx_bottom; + + float left = cliplow * xscale; + float right = cliphigh * xscale; + if (gl_sidedef->scalex_bottom < 0) + { + left = -left; + right = -right; + offsetx_bottom = -offsetx_bottom; + } // PEGGING if (!(gl_linedef->flags & ML_DONTPEGBOTTOM)) @@ -1230,15 +1450,18 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom texturevpeg *= yscale; - texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_bottom; + if (gl_sidedef->scaley_bottom < 0) + texturevpeg -= gl_sidedef->rowoffset + gl_sidedef->offsety_bottom; + else + texturevpeg += gl_sidedef->rowoffset + gl_sidedef->offsety_bottom; // This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway - texturevpeg %= FixedDiv(textureheight[gl_bottomtexture], gl_sidedef->scaley_bottom); + texturevpeg %= FixedDiv(textureheight[gl_bottomtexture], abs(gl_sidedef->scaley_bottom)); wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + (gl_backsector->floorheight - gl_frontsector->floorheight) * yscale) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_bottom) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_bottom) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = (left + offsetx_bottom) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = (right + offsetx_bottom) * grTex->scaleX; // Adjust t value for sloped walls if (!(gl_linedef->flags & ML_SKEWTD)) @@ -1262,6 +1485,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[1].t = (texturevpeg + (worldlowslope - worldbottomslope) * yscale) * grTex->scaleY; } + if (gl_sidedef->scaley_bottom < 0) + { + wallVerts[0].t = -wallVerts[0].t; + wallVerts[1].t = -wallVerts[1].t; + wallVerts[2].t = -wallVerts[2].t; + wallVerts[3].t = -wallVerts[3].t; + } + // set top/bottom coords wallVerts[3].y = FIXED_TO_FLOAT(worldlow); wallVerts[0].y = FIXED_TO_FLOAT(worldbottom); @@ -1276,196 +1507,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); } - // Render midtexture if there's one. Determine if it's visible first, though - if (gl_midtexture && HWR_BlendMidtextureSurface(&Surf)) - { - sector_t *front, *back; - fixed_t texheight = FixedDiv(textureheight[gl_midtexture], gl_sidedef->scaley_mid); - INT32 repeats; + // Render midtexture if there's one + if (gl_midtexture) + HWR_RenderMidtexture(gl_midtexture, cliplow, cliphigh, worldtop, worldbottom, worldhigh, worldlow, worldtopslope, worldbottomslope, worldhighslope, worldlowslope, lightnum, wallVerts); - if (gl_linedef->frontsector->heightsec != -1) - front = §ors[gl_linedef->frontsector->heightsec]; - else - front = gl_linedef->frontsector; - - if (gl_linedef->backsector->heightsec != -1) - back = §ors[gl_linedef->backsector->heightsec]; - else - back = gl_linedef->backsector; - - if (gl_sidedef->repeatcnt) - repeats = 1 + gl_sidedef->repeatcnt; - else if (gl_linedef->flags & ML_WRAPMIDTEX) - { - fixed_t high, low; - - if (front->ceilingheight > back->ceilingheight) - high = back->ceilingheight; - else - high = front->ceilingheight; - - if (front->floorheight > back->floorheight) - low = front->floorheight; - else - low = back->floorheight; - - repeats = (high - low) / texheight; - if ((high - low) % texheight) - repeats++; // tile an extra time to fill the gap -- Monster Iestyn - } - else - repeats = 1; - - grTex = HWR_GetTexture(gl_midtexture); - xscale = FixedToFloat(gl_sidedef->scalex_mid); - yscale = FixedToFloat(gl_sidedef->scaley_mid); - - // SoM: a little note: popentop and popenbottom - // record the limits the texture can be displayed in. - // polytop and polybottom, are the ideal (i.e. unclipped) - // heights of the polygon, and h & l, are the final (clipped) - // poly coords. - fixed_t popentop, popenbottom, polytop, polybottom, lowcut, highcut; - fixed_t popentopslope, popenbottomslope, polytopslope, polybottomslope, lowcutslope, highcutslope; - - // NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to, - // you must use the linedef's backsector to be correct - // From CB - if (gl_curline->polyseg) - { - popentop = popentopslope = back->ceilingheight; - popenbottom = popenbottomslope = back->floorheight; - } - else - { - popentop = min(worldtop, worldhigh); - popenbottom = max(worldbottom, worldlow); - popentopslope = min(worldtopslope, worldhighslope); - popenbottomslope = max(worldbottomslope, worldlowslope); - } - - // Find the wall's coordinates - fixed_t midtexheight = texheight * repeats; - - fixed_t rowoffset = FixedDiv(gl_sidedef->rowoffset + gl_sidedef->offsety_mid, gl_sidedef->scaley_mid); - - // Texture is not skewed - if (gl_linedef->flags & ML_NOSKEW) - { - // Peg it to the floor - if (gl_linedef->flags & ML_MIDPEG) - { - polybottom = max(front->floorheight, back->floorheight) + rowoffset; - polytop = polybottom + midtexheight; - } - // Peg it to the ceiling - else - { - polytop = min(front->ceilingheight, back->ceilingheight) + rowoffset; - polybottom = polytop - midtexheight; - } - - // The right side's coordinates are the the same as the left side - polytopslope = polytop; - polybottomslope = polybottom; - } - // Skew the texture, but peg it to the floor - else if (gl_linedef->flags & ML_MIDPEG) - { - polybottom = popenbottom + rowoffset; - polytop = polybottom + midtexheight; - polybottomslope = popenbottomslope + rowoffset; - polytopslope = polybottomslope + midtexheight; - } - // Skew it according to the ceiling's slope - else - { - polytop = popentop + rowoffset; - polybottom = polytop - midtexheight; - polytopslope = popentopslope + rowoffset; - polybottomslope = polytopslope - midtexheight; - } - - // CB - // NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to, - // you must use the linedef's backsector to be correct - if (gl_curline->polyseg) - { - lowcut = polybottom; - highcut = polytop; - lowcutslope = polybottomslope; - highcutslope = polytopslope; - } - else - { - // The cut-off values of a linedef can always be constant, since every line has an absoulute front and or back sector - lowcut = popenbottom; - highcut = popentop; - lowcutslope = popenbottomslope; - highcutslope = popentopslope; - } - - h = min(highcut, polytop); - l = max(polybottom, lowcut); - hS = min(highcutslope, polytopslope); - lS = max(polybottomslope, lowcutslope); - - // PEGGING - fixed_t texturevpegslope; - - if (gl_linedef->flags & ML_MIDPEG) - { - texturevpeg = midtexheight - h + polybottom; - texturevpegslope = midtexheight - hS + polybottomslope; - } - else - { - texturevpeg = polytop - h; - texturevpegslope = polytopslope - hS; - } - - // Left side - wallVerts[3].t = texturevpeg * yscale * grTex->scaleY; - wallVerts[0].t = (h - l + texturevpeg) * yscale * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX; - - // Right side - wallVerts[2].t = texturevpegslope * yscale * grTex->scaleY; - wallVerts[1].t = (hS - lS + texturevpegslope) * yscale * grTex->scaleY; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX; - - // set top/bottom coords - // Take the texture peg into account, rather than changing the offsets past - // where the polygon might not be. - wallVerts[3].y = FIXED_TO_FLOAT(h); - wallVerts[0].y = FIXED_TO_FLOAT(l); - wallVerts[2].y = FIXED_TO_FLOAT(hS); - wallVerts[1].y = FIXED_TO_FLOAT(lS); - - // TODO: Actually use the surface's flags so that I don't have to do this - FUINT blendmode = Surf.PolyFlags; - - // Render midtextures on two-sided lines with a z-buffer offset. - // This will cause the midtexture appear on top, if a FOF overlaps with it. - blendmode |= PF_Decal; - - if (gl_frontsector->numlights) - { - if (!(blendmode & PF_Masked)) - HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_TRANSLUCENT, NULL, blendmode); - else - HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FOF_CUTLEVEL, NULL, blendmode); - } - else if (!(blendmode & PF_Masked)) - HWR_AddTransparentWall(wallVerts, &Surf, gl_midtexture, blendmode, false, lightnum, colormap); - else - HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); - } - - // Sky culling - // No longer so much a mess as before! if (!gl_curline->polyseg) // Don't do it for polyobjects { + // Sky culling + // No longer so much a mess as before! if (gl_frontsector->ceilingpic == skyflatnum && gl_backsector->ceilingpic != skyflatnum) // don't cull if back sector is also sky { @@ -1509,8 +1558,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (texturevpeg + gl_frontsector->ceilingheight - gl_frontsector->floorheight) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->offsetx_mid) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + gl_sidedef->textureoffset + gl_sidedef->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + gl_sidedef->textureoffset + gl_sidedef->offsetx_mid) * grTex->scaleX; // Texture correction for slopes if (gl_linedef->flags & ML_NOSKEW) { @@ -1573,8 +1622,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // Used for height comparisons and etc across FOFs and slopes fixed_t high1, highslope1, low1, lowslope1; + fixed_t texturehpeg = gl_sidedef->textureoffset + gl_sidedef->offsetx_mid; + INT32 texnum; - line_t * newline = NULL; // Multi-Property FOF lowcut = max(worldbottom, worldlow); highcut = min(worldtop, worldhigh); @@ -1608,16 +1658,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) continue; - side_t *side = &sides[rover->master->sidenum[0]]; + side_t *side = R_GetFFloorSide(gl_curline, rover); boolean do_texture_skew; boolean dont_peg_bottom; if (rover->master->flags & ML_TFERLINE) { - size_t linenum = gl_curline->linedef-gl_backsector->lines[0]; - newline = rover->master->frontsector->lines[0] + linenum; - side = &sides[newline->sidenum[0]]; + line_t *newline = R_GetFFloorLine(gl_curline, rover); do_texture_skew = newline->flags & ML_SKEWTD; dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM; } @@ -1695,14 +1743,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } } - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + side->offsetx_mid) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + side->offsetx_mid) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + texturehpeg + side->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + texturehpeg + side->offsetx_mid) * grTex->scaleX; } + FBITFIELD blendmode; + if (rover->fofflags & FOF_FOG) { - FBITFIELD blendmode; - blendmode = PF_Fog|PF_NoTexture; lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); @@ -1717,7 +1765,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } else { - FBITFIELD blendmode = PF_Masked; + blendmode = PF_Masked; if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) { @@ -1765,13 +1813,21 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) continue; - side_t *side = &sides[rover->master->sidenum[0]]; + side_t *side = R_GetFFloorSide(gl_curline, rover); + + boolean do_texture_skew; + boolean dont_peg_bottom; if (rover->master->flags & ML_TFERLINE) { - size_t linenum = gl_curline->linedef-gl_backsector->lines[0]; - newline = rover->master->frontsector->lines[0] + linenum; - side = &sides[newline->sidenum[0]]; + line_t *newline = R_GetFFloorLine(gl_curline, rover); + do_texture_skew = newline->flags & ML_SKEWTD; + dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM; + } + else + { + do_texture_skew = rover->master->flags & ML_SKEWTD; + dont_peg_bottom = gl_curline->linedef->flags & ML_DONTPEGBOTTOM; } texnum = R_GetTextureNum(side->midtexture); @@ -1808,23 +1864,49 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } else { + // Wow, how was this missing from OpenGL for so long? + // ...Oh well, anyway, Lower Unpegged now changes pegging of FOFs like in software + // -- Monster Iestyn 26/06/18 + fixed_t texturevpeg = side->rowoffset + side->offsety_mid; + grTex = HWR_GetTexture(texnum); xscale = FixedToFloat(side->scalex_mid); yscale = FixedToFloat(side->scaley_mid); - fixed_t diff = (*rover->topheight - h) * yscale; + if (!do_texture_skew) // no skewing + { + if (dont_peg_bottom) + texturevpeg -= (*rover->topheight - *rover->bottomheight) * yscale; - wallVerts[3].t = wallVerts[2].t = (diff + side->rowoffset + side->offsety_mid) * grTex->scaleY; - wallVerts[0].t = wallVerts[1].t = (((h - l) * yscale) + (diff + side->rowoffset + side->offsety_mid)) * grTex->scaleY; + wallVerts[3].t = (((*rover->topheight - h) * yscale) + texturevpeg) * grTex->scaleY; + wallVerts[2].t = (((*rover->topheight - hS) * yscale) + texturevpeg) * grTex->scaleY; + wallVerts[0].t = (((*rover->topheight - l) * yscale) + texturevpeg) * grTex->scaleY; + wallVerts[1].t = (((*rover->topheight - lS) * yscale) + texturevpeg) * grTex->scaleY; + } + else + { + if (!dont_peg_bottom) // skew by top + { + wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; + wallVerts[0].t = (((h - l) * yscale) + texturevpeg) * grTex->scaleY; + wallVerts[1].t = (((hS - lS) * yscale) + texturevpeg) * grTex->scaleY; + } + else // skew by bottom + { + wallVerts[0].t = wallVerts[1].t = texturevpeg * grTex->scaleY; + wallVerts[3].t = wallVerts[0].t - ((h - l) * yscale) * grTex->scaleY; + wallVerts[2].t = wallVerts[1].t - ((hS - lS) * yscale) * grTex->scaleY; + } + } - wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + side->offsetx_mid) * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + side->offsetx_mid) * grTex->scaleX; + wallVerts[0].s = wallVerts[3].s = ((cliplow * xscale) + texturehpeg + side->offsetx_mid) * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = ((cliphigh * xscale) + texturehpeg + side->offsetx_mid) * grTex->scaleX; } + FBITFIELD blendmode; + if (rover->fofflags & FOF_FOG) { - FBITFIELD blendmode; - blendmode = PF_Fog|PF_NoTexture; lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); @@ -1839,7 +1921,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } else { - FBITFIELD blendmode = PF_Masked; + blendmode = PF_Masked; if ((rover->fofflags & FOF_TRANSLUCENT && !(rover->fofflags & FOF_SPLAT)) || rover->blend) { @@ -2656,36 +2738,14 @@ static boolean HWR_CheckBBox(fixed_t *bspcoord) static inline void HWR_AddPolyObjectSegs(void) { size_t i, j; - seg_t *gl_fakeline = Z_Calloc(sizeof(seg_t), PU_STATIC, NULL); - polyvertex_t *pv1 = Z_Calloc(sizeof(polyvertex_t), PU_STATIC, NULL); - polyvertex_t *pv2 = Z_Calloc(sizeof(polyvertex_t), PU_STATIC, NULL); // Sort through all the polyobjects for (i = 0; i < numpolys; ++i) { // Render the polyobject's lines for (j = 0; j < po_ptrs[i]->segCount; ++j) - { - // Copy the info of a polyobject's seg, then convert it to OpenGL floating point - M_Memcpy(gl_fakeline, po_ptrs[i]->segs[j], sizeof(seg_t)); - - // Now convert the line to float and add it to be rendered - pv1->x = FIXED_TO_FLOAT(gl_fakeline->v1->x); - pv1->y = FIXED_TO_FLOAT(gl_fakeline->v1->y); - pv2->x = FIXED_TO_FLOAT(gl_fakeline->v2->x); - pv2->y = FIXED_TO_FLOAT(gl_fakeline->v2->y); - - gl_fakeline->pv1 = pv1; - gl_fakeline->pv2 = pv2; - - HWR_AddLine(gl_fakeline); - } + HWR_AddLine(po_ptrs[i]->segs[j]); } - - // Free temporary data no longer needed - Z_Free(pv2); - Z_Free(pv1); - Z_Free(gl_fakeline); } static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, diff --git a/src/p_setup.c b/src/p_setup.c index 1d985beb4..3bde51c3b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3290,8 +3290,6 @@ static void P_InitializeSeg(seg_t *seg) seg->lightmaps = NULL; // list of static lightmap for this seg #endif - seg->numlights = 0; - seg->rlights = NULL; seg->polyseg = NULL; seg->dontrenderme = false; } diff --git a/src/r_defs.h b/src/r_defs.h index d556b540f..899d6ad73 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -742,9 +742,6 @@ typedef struct seg_s lightmap_t *lightmaps; // for static lightmap #endif - // Why slow things down by calculating lightlists for every thick side? - size_t numlights; - r_lightlist_t *rlights; polyobj_t *polyseg; boolean dontrenderme; boolean glseg; @@ -828,6 +825,7 @@ typedef struct drawseg_s INT16 *sprtopclip; INT16 *sprbottomclip; fixed_t *maskedtexturecol; + fixed_t *maskedtextureheight; // For handling sloped midtextures fixed_t *invscale; struct visplane_s *ffloorplanes[MAXFFLOORS]; @@ -839,8 +837,6 @@ typedef struct drawseg_s UINT8 portalpass; // if > 0 and <= portalrender, do not affect sprite clipping - fixed_t maskedtextureheight[MAXVIDWIDTH]; // For handling sloped midtextures - vertex_t leftpos, rightpos; // Used for rendering FOF walls with slopes } drawseg_t; diff --git a/src/r_main.c b/src/r_main.c index aaab234ad..c920031a0 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -318,7 +318,6 @@ angle_t R_PointToAngle(fixed_t x, fixed_t y) } // This version uses 64-bit variables to avoid overflows with large values. -// Currently used only by OpenGL rendering. angle_t R_PointToAngle64(INT64 x, INT64 y) { return (y -= viewy, (x -= viewx) || y) ? @@ -384,56 +383,26 @@ fixed_t R_PointToDist(fixed_t x, fixed_t y) return R_PointToDist2(viewx, viewy, x, y); } -angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1) +line_t *R_GetFFloorLine(const seg_t *seg, const ffloor_t *pfloor) { - INT64 dx = x1-x2; - INT64 dy = y1-y2; - if (dx < INT32_MIN || dx > INT32_MAX || dy < INT32_MIN || dy > INT32_MAX) + if (pfloor->master->flags & ML_TFERLINE) { - x1 = (int)(dx / 2 + x2); - y1 = (int)(dy / 2 + y2); + size_t linenum = seg->linedef - pfloor->target->lines[0]; + return pfloor->master->frontsector->lines[0] + linenum; } - return (y1 -= y2, (x1 -= x2) || y1) ? - x1 >= 0 ? - y1 >= 0 ? - (x1 > y1) ? tantoangle[SlopeDivEx(y1,x1)] : // octant 0 - ANGLE_90-tantoangle[SlopeDivEx(x1,y1)] : // octant 1 - x1 > (y1 = -y1) ? 0-tantoangle[SlopeDivEx(y1,x1)] : // octant 8 - ANGLE_270+tantoangle[SlopeDivEx(x1,y1)] : // octant 7 - y1 >= 0 ? (x1 = -x1) > y1 ? ANGLE_180-tantoangle[SlopeDivEx(y1,x1)] : // octant 3 - ANGLE_90 + tantoangle[SlopeDivEx(x1,y1)] : // octant 2 - (x1 = -x1) > (y1 = -y1) ? ANGLE_180+tantoangle[SlopeDivEx(y1,x1)] : // octant 4 - ANGLE_270-tantoangle[SlopeDivEx(x1,y1)] : // octant 5 - 0; + else + return pfloor->master; } -// -// R_ScaleFromGlobalAngle -// Returns the texture mapping scale for the current line (horizontal span) -// at the given angle. -// rw_distance must be calculated first. -// -// killough 5/2/98: reformatted, cleaned up -// -// note: THIS IS USED ONLY FOR WALLS! -fixed_t R_ScaleFromGlobalAngle(angle_t visangle) +side_t *R_GetFFloorSide(const seg_t *seg, const ffloor_t *pfloor) { - angle_t anglea = ANGLE_90 + (visangle-viewangle); - angle_t angleb = ANGLE_90 + (visangle-rw_normalangle); - fixed_t den = FixedMul(rw_distance, FINESINE(anglea>>ANGLETOFINESHIFT)); - // proff 11/06/98: Changed for high-res - fixed_t num = FixedMul(projectiony, FINESINE(angleb>>ANGLETOFINESHIFT)); - - if (den > num>>16) + if (pfloor->master->flags & ML_TFERLINE) { - num = FixedDiv(num, den); - if (num > 64*FRACUNIT) - return 64*FRACUNIT; - if (num < 256) - return 256; - return num; + line_t *newline = R_GetFFloorLine(seg, pfloor); + return &sides[newline->sidenum[0]]; } - return 64*FRACUNIT; + else + return &sides[pfloor->master->sidenum[0]]; } // diff --git a/src/r_main.h b/src/r_main.h index c7dc06c90..da2189328 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -77,17 +77,18 @@ INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line); angle_t R_PointToAngle(fixed_t x, fixed_t y); angle_t R_PointToAngle64(INT64 x, INT64 y); angle_t R_PointToAngle2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1); -angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1); fixed_t R_PointToDist(fixed_t x, fixed_t y); fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1); -fixed_t R_ScaleFromGlobalAngle(angle_t visangle); boolean R_IsPointInSector(sector_t *sector, fixed_t x, fixed_t y); subsector_t *R_PointInSubsector(fixed_t x, fixed_t y); subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y); boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph); +line_t *R_GetFFloorLine(const seg_t *seg, const ffloor_t *pfloor); +side_t *R_GetFFloorSide(const seg_t *seg, const ffloor_t *pfloor); + // Render stats extern precise_t ps_prevframetime;// time when previous frame was rendered diff --git a/src/r_segs.c b/src/r_segs.c index 267c1d47d..b5d4a6dae 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -16,15 +16,10 @@ #include "r_sky.h" #include "r_portal.h" -#include "r_splats.h" #include "w_wad.h" #include "z_zone.h" -#include "netcode/d_netcmd.h" -#include "m_misc.h" -#include "p_local.h" // Camera... #include "p_slopes.h" -#include "console.h" // con_clipviewtop #include "taglist.h" // OPTIMIZE: closed two sided lines as single sided @@ -79,6 +74,8 @@ static fixed_t *maskedtextureheight = NULL; static fixed_t *thicksidecol = NULL; static fixed_t *invscale = NULL; +static boolean texcoltables; + //SoM: 3/23/2000: Use boom opening limit removal static size_t numopenings; static INT16 *openings, *lastopening; @@ -92,10 +89,6 @@ void R_ClearSegTables(void) curtexturecolumntable = texturecolumntable; } -// ========================================================================== -// R_RenderMaskedSegRange -// ========================================================================== - transnum_t R_GetLinedefTransTable(fixed_t alpha) { return (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1); @@ -115,8 +108,13 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) INT32 times, repeats; INT64 overflow_test; INT32 range; + UINT8 vertflip; unsigned lengthcol; + fixed_t wall_scaley; + fixed_t scalestep; + fixed_t scale1; + // Calculate light table. // Use different light tables // for horizontal / vertical / diagonal. Diagonal? @@ -164,9 +162,17 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) colfunc = colfuncs[COLDRAWFUNC_FUZZY]; } - fixed_t wall_scaley = sidedef->scaley_mid; - fixed_t scalestep = FixedDiv(ds->scalestep, wall_scaley); - fixed_t scale1 = FixedDiv(ds->scale1, wall_scaley); + vertflip = textures[texnum]->flip & 2; + + wall_scaley = sidedef->scaley_mid; + if (wall_scaley < 0) + { + wall_scaley = -wall_scaley; + vertflip = !vertflip; + } + + scalestep = FixedDiv(ds->scalestep, wall_scaley); + scale1 = FixedDiv(ds->scale1, wall_scaley); range = max(ds->x2-ds->x1, 1); rw_scalestep = scalestep; @@ -175,7 +181,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // Texture must be cached R_CheckTextureCache(texnum); - if (textures[texnum]->flip & 2) // vertically flipped? + if (vertflip) // vertically flipped? colfunc_2s = R_DrawFlippedMaskedColumn; else colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture @@ -469,6 +475,11 @@ static boolean R_IsFFloorTranslucent(visffloor_t *pfloor) return false; } +static fixed_t R_GetSlopeTextureSlide(pslope_t *slope, angle_t lineangle) +{ + return FixedMul(slope->zdelta, FINECOSINE((lineangle-slope->xydirection)>>ANGLETOFINESHIFT)); +} + // // R_RenderThickSideRange // Renders all the thick sides in the given range. @@ -484,8 +495,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) sector_t tempsec; INT32 templight; INT32 i, p; - fixed_t bottombounds = viewheight << FRACBITS; - fixed_t topbounds = (con_clipviewtop - 1) << FRACBITS; fixed_t offsetvalue; lightlist_t *light; r_lightlist_t *rlight; @@ -495,12 +504,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) INT64 top_frac, top_step, bottom_frac, bottom_step; // skew FOF walls with slopes? fixed_t ffloortextureslide = 0; - INT32 oldx = -1; + fixed_t oldtexturecolumn = -1; fixed_t left_top, left_bottom; // needed here for slope skewing pslope_t *skewslope = NULL; boolean do_texture_skew; boolean dont_peg_bottom; + fixed_t wall_offsetx; fixed_t wall_scalex, wall_scaley; + UINT8 vertflip; unsigned lengthcol; void (*colfunc_2s) (column_t *, unsigned); @@ -513,15 +524,13 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) curline = ds->curline; backsector = pfloor->target; frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; - sidedef = &sides[pfloor->master->sidenum[0]]; + sidedef = R_GetFFloorSide(curline, pfloor); colfunc = colfuncs[BASEDRAWFUNC]; if (pfloor->master->flags & ML_TFERLINE) { - size_t linenum = curline->linedef-backsector->lines[0]; - line_t *newline = pfloor->master->frontsector->lines[0] + linenum; - sidedef = &sides[newline->sidenum[0]]; + line_t *newline = R_GetFFloorLine(curline, pfloor); do_texture_skew = newline->flags & ML_SKEWTD; dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM; } @@ -532,6 +541,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) } texnum = R_GetTextureNum(sidedef->midtexture); + vertflip = textures[texnum]->flip & 2; if (pfloor->fofflags & FOF_TRANSLUCENT) { @@ -685,18 +695,25 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) wall_scalex = FixedDiv(FRACUNIT, sidedef->scalex_mid); wall_scaley = sidedef->scaley_mid; + if (wall_scaley < 0) + { + wall_scaley = -wall_scaley; + vertflip = !vertflip; + } thicksidecol = ffloortexturecolumn; + wall_offsetx = ds->offsetx + sidedef->offsetx_mid; + if (wall_scalex == FRACUNIT) { for (INT32 x = x1; x <= x2; x++) - thicksidecol[x] = ds->thicksidecol[x] + ds->offsetx; + thicksidecol[x] = ds->thicksidecol[x]; } else { for (INT32 x = x1; x <= x2; x++) - thicksidecol[x] = FixedDiv(ds->thicksidecol[x], wall_scalex) + ds->offsetx; + thicksidecol[x] = FixedDiv(ds->thicksidecol[x], wall_scalex); } mfloorclip = ds->sprbottomclip; @@ -731,7 +748,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (skewslope) { angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); - ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT)); + ffloortextureslide = FixedMul(R_GetSlopeTextureSlide(skewslope, lineangle), wall_scaley); } dc_texturemid += offsetvalue; @@ -739,7 +756,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // Texture must be cached R_CheckTextureCache(texnum); - if (textures[texnum]->flip & 2) // vertically flipped? + if (vertflip) // vertically flipped? colfunc_2s = R_DrawRepeatFlippedMaskedColumn; else colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture @@ -773,9 +790,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) // skew FOF walls if (ffloortextureslide) { - if (oldx != -1) - dc_texturemid += FixedMul(ffloortextureslide, thicksidecol[oldx]-thicksidecol[dc_x]); - oldx = dc_x; + if (oldtexturecolumn != -1) + dc_texturemid += FixedMul(ffloortextureslide, oldtexturecolumn-ds->thicksidecol[dc_x]); + oldtexturecolumn = ds->thicksidecol[dc_x]; } // Calculate bounds @@ -791,7 +808,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) bottom_frac += bottom_step; // SoM: If column is out of range, why bother with it?? - if (windowbottom < topbounds || windowtop > bottombounds) + if (windowbottom < 0 || windowtop > (viewheight << FRACBITS)) { if (dc_numlights) { @@ -810,7 +827,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc_iscale = FixedMul(0xffffffffu / (unsigned)spryscale, wall_scaley); // Get data for the column - col = R_GetColumn(texnum, (thicksidecol[dc_x] >> FRACBITS)); + col = R_GetColumn(texnum, ((thicksidecol[dc_x] + wall_offsetx) >> FRACBITS)); // SoM: New code does not rely on R_DrawColumnShadowed_8 which // will (hopefully) put less strain on the stack. @@ -984,36 +1001,64 @@ static boolean R_FFloorCanClip(visffloor_t *pfloor) #define HEIGHTBITS 12 #define HEIGHTUNIT (1<colormap + (xwalllights[pindex] - colormaps); else dc_lightlist[i].rcolormap = xwalllights[pindex]; - - colfunc = colfuncs[COLDRAWFUNC_SHADOWED]; } } @@ -1252,24 +1295,9 @@ static void R_RenderSegLoop (void) dc_yl = yl; dc_yh = yh; dc_texturemid = rw_midtexturemid; - dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_midtexturescaley); - dc_source = R_GetColumn(midtexture, offset >> FRACBITS)->pixels; dc_texheight = textureheight[midtexture]>>FRACBITS; - - //profile stuff --------------------------------------------------------- -#ifdef TIMING - ProfZeroTimer(); -#endif - colfunc(); -#ifdef TIMING - RDMSR(0x10,&mycount); - mytotal += mycount; //64bit add - - if (nombre--==0) - I_Error("R_DrawColumn CPU Spy reports: 0x%d %d\n", *((INT32 *)&mytotal+1), - (INT32)mytotal); -#endif - //profile stuff --------------------------------------------------------- + dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, midscaley); + drawmiddle(R_GetColumn(midtexture, offset >> FRACBITS)->pixels, dc_texheight); // dont draw anything more for this column, since // a midtexture blocks the view @@ -1321,10 +1349,9 @@ static void R_RenderSegLoop (void) dc_yl = yl; dc_yh = mid; dc_texturemid = rw_toptexturemid; - dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_toptexturescaley); - dc_source = R_GetColumn(toptexture, offset >> FRACBITS)->pixels; dc_texheight = textureheight[toptexture]>>FRACBITS; - colfunc(); + dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, topscaley); + drawtop(R_GetColumn(toptexture, offset >> FRACBITS)->pixels, dc_texheight); ceilingclip[rw_x] = (INT16)mid; } else if (!rw_ceilingmarked) // entirely off top of screen @@ -1334,8 +1361,8 @@ static void R_RenderSegLoop (void) ceilingclip[rw_x] = topclip; if (oldtexturecolumn_top != -1) - rw_toptexturemid += FixedMul(rw_toptextureslide, oldtexturecolumn_top-toptexturecolumn); - oldtexturecolumn_top = toptexturecolumn; + rw_toptexturemid += FixedMul(rw_toptextureslide, oldtexturecolumn_top-textureoffset); + oldtexturecolumn_top = textureoffset; } else if (markceiling && (!rw_ceilingmarked)) // no top wall ceilingclip[rw_x] = topclip; @@ -1369,10 +1396,9 @@ static void R_RenderSegLoop (void) dc_yl = mid; dc_yh = yh; dc_texturemid = rw_bottomtexturemid; - dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, rw_bottomtexturescaley); - dc_source = R_GetColumn(bottomtexture, offset >> FRACBITS)->pixels; dc_texheight = textureheight[bottomtexture]>>FRACBITS; - colfunc(); + dc_iscale = FixedMul(0xffffffffu / (unsigned)rw_scale, bottomscaley); + drawbottom(R_GetColumn(bottomtexture, offset >> FRACBITS)->pixels, dc_texheight); floorclip[rw_x] = (INT16)mid; } else if (!rw_floormarked) // entirely off bottom of screen @@ -1382,8 +1408,8 @@ static void R_RenderSegLoop (void) floorclip[rw_x] = bottomclip; if (oldtexturecolumn_bottom != -1) - rw_bottomtexturemid += FixedMul(rw_bottomtextureslide, oldtexturecolumn_bottom-bottomtexturecolumn); - oldtexturecolumn_bottom = bottomtexturecolumn; + rw_bottomtexturemid += FixedMul(rw_bottomtextureslide, oldtexturecolumn_bottom-textureoffset); + oldtexturecolumn_bottom = textureoffset; } else if (markfloor && (!rw_floormarked)) // no bottom wall floorclip[rw_x] = bottomclip; @@ -1407,11 +1433,14 @@ static void R_RenderSegLoop (void) { if (oldtexturecolumn != -1) { - rw_midtexturemid += FixedMul(rw_midtextureslide, oldtexturecolumn-texturecolumn); - rw_midtextureback += FixedMul(rw_midtexturebackslide, oldtexturecolumn-texturecolumn); + INT32 diff = oldtexturecolumn-textureoffset; + if (rw_invmidtexturescalex < 0) + diff = -diff; + rw_midtexturemid += FixedMul(rw_midtextureslide, diff); + rw_midtextureback += FixedMul(rw_midtexturebackslide, diff); } - oldtexturecolumn = texturecolumn; + oldtexturecolumn = textureoffset; } if (invscale) @@ -1505,7 +1534,7 @@ static void R_AllocClippingTables(size_t range) static void R_AllocTextureColumnTables(size_t range) { size_t pos = curtexturecolumntable - texturecolumntable; - size_t need = range * 3; + size_t need = range * 4; if (pos + need < texturecolumntablesize) return; @@ -1526,15 +1555,48 @@ static void R_AllocTextureColumnTables(size_t range) for (drawseg_t *ds = drawsegs; ds < ds_p; ds++) { // Check if it's in range of the tables - if (ds->maskedtexturecol + ds->x1 >= oldtable && ds->maskedtexturecol + ds->x1 <= oldlast) - ds->maskedtexturecol = (ds->maskedtexturecol - oldtable) + texturecolumntable; - if (ds->thicksidecol + ds->x1 >= oldtable && ds->thicksidecol + ds->x1 <= oldlast) - ds->thicksidecol = (ds->thicksidecol - oldtable) + texturecolumntable; - if (ds->invscale + ds->x1 >= oldtable && ds->invscale + ds->x1 <= oldlast) - ds->invscale = (ds->invscale - oldtable) + texturecolumntable; +#define CHECK(which) \ + if (which + ds->x1 >= oldtable && which + ds->x1 <= oldlast) \ + which = (which - oldtable) + texturecolumntable + + CHECK(ds->maskedtexturecol); + CHECK(ds->maskedtextureheight); + CHECK(ds->thicksidecol); + CHECK(ds->invscale); + +#undef CHECK } } +// +// R_ScaleFromGlobalAngle +// Returns the texture mapping scale for the current line (horizontal span) +// at the given angle. +// rw_distance must be calculated first. +// +// killough 5/2/98: reformatted, cleaned up +// +// note: THIS IS USED ONLY FOR WALLS! +static fixed_t R_ScaleFromGlobalAngle(angle_t visangle) +{ + angle_t anglea = ANGLE_90 + (visangle-viewangle); + angle_t angleb = ANGLE_90 + (visangle-rw_normalangle); + fixed_t den = FixedMul(rw_distance, FINESINE(anglea>>ANGLETOFINESHIFT)); + // proff 11/06/98: Changed for high-res + fixed_t num = FixedMul(projectiony, FINESINE(angleb>>ANGLETOFINESHIFT)); + + if (den > num>>16) + { + num = FixedDiv(num, den); + if (num > 64*FRACUNIT) + return 64*FRACUNIT; + if (num < 256) + return 256; + return num; + } + return 64*FRACUNIT; +} + // // R_StoreWallRange // A wall segment will be drawn @@ -1706,11 +1768,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) midtexture = toptexture = bottomtexture = maskedtexture = 0; ds_p->maskedtexturecol = NULL; + ds_p->maskedtextureheight = NULL; ds_p->numthicksides = numthicksides = 0; ds_p->thicksidecol = NULL; ds_p->invscale = NULL; ds_p->tsilheight = 0; + texcoltables = false; + numbackffloors = 0; for (i = 0; i < MAXFFLOORS; i++) @@ -1736,16 +1801,19 @@ void R_StoreWallRange(INT32 start, INT32 stop) angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); if (frontsector->f_slope) - floorfrontslide = FixedMul(frontsector->f_slope->zdelta, FINECOSINE((lineangle-frontsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); + floorfrontslide = R_GetSlopeTextureSlide(frontsector->f_slope, lineangle); if (frontsector->c_slope) - ceilingfrontslide = FixedMul(frontsector->c_slope->zdelta, FINECOSINE((lineangle-frontsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); + ceilingfrontslide = R_GetSlopeTextureSlide(frontsector->c_slope, lineangle); - if (backsector && backsector->f_slope) - floorbackslide = FixedMul(backsector->f_slope->zdelta, FINECOSINE((lineangle-backsector->f_slope->xydirection)>>ANGLETOFINESHIFT)); + if (backsector) + { + if (backsector->f_slope) + floorbackslide = R_GetSlopeTextureSlide(backsector->f_slope, lineangle); - if (backsector && backsector->c_slope) - ceilingbackslide = FixedMul(backsector->c_slope->zdelta, FINECOSINE((lineangle-backsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); + if (backsector->c_slope) + ceilingbackslide = R_GetSlopeTextureSlide(backsector->c_slope, lineangle); + } } rw_midtexturescalex = sidedef->scalex_mid; @@ -1761,26 +1829,27 @@ void R_StoreWallRange(INT32 start, INT32 stop) fixed_t rowoffset = sidedef->rowoffset + sidedef->offsety_mid; fixed_t texheight = textureheight[midtexture]; + fixed_t scaley = abs(rw_midtexturescaley); if (rw_midtexturescaley > 0) { if (linedef->flags & ML_NOSKEW) { if (linedef->flags & ML_DONTPEGBOTTOM) - rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, rw_midtexturescaley) + texheight; + rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, scaley) + texheight; else - rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, rw_midtexturescaley); + rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, scaley); } else if (linedef->flags & ML_DONTPEGBOTTOM) { - rw_midtexturemid = FixedMul(worldbottom, rw_midtexturescaley) + texheight; - rw_midtextureslide = floorfrontslide; + rw_midtexturemid = FixedMul(worldbottom, scaley) + texheight; + rw_midtextureslide = FixedMul(floorfrontslide, scaley); } else { // top of texture at top - rw_midtexturemid = FixedMul(worldtop, rw_midtexturescaley); - rw_midtextureslide = ceilingfrontslide; + rw_midtexturemid = FixedMul(worldtop, scaley); + rw_midtextureslide = FixedMul(ceilingfrontslide, scaley); } } else @@ -1791,20 +1860,20 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (linedef->flags & ML_NOSKEW) { if (linedef->flags & ML_DONTPEGBOTTOM) - rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, rw_midtexturescaley); + rw_midtexturemid = FixedMul(frontsector->floorheight - viewz, scaley); else - rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, rw_midtexturescaley) + texheight; + rw_midtexturemid = FixedMul(frontsector->ceilingheight - viewz, scaley) + texheight; } else if (linedef->flags & ML_DONTPEGBOTTOM) { - rw_midtexturemid = FixedMul(worldbottom, rw_midtexturescaley); - rw_midtextureslide = floorfrontslide; + rw_midtexturemid = FixedMul(worldbottom, scaley); + rw_midtextureslide = FixedMul(floorfrontslide, scaley); } else { // top of texture at top - rw_midtexturemid = FixedMul(worldtop, rw_midtexturescaley) + texheight; - rw_midtextureslide = ceilingfrontslide; + rw_midtexturemid = FixedMul(worldtop, scaley) + texheight; + rw_midtextureslide = FixedMul(ceilingfrontslide, scaley); } } @@ -2013,15 +2082,16 @@ void R_StoreWallRange(INT32 start, INT32 stop) { // top of texture at top rw_toptexturemid = worldtop; - rw_toptextureslide = ceilingfrontslide; + rw_toptextureslide = FixedMul(ceilingfrontslide, abs(rw_toptexturescaley)); } else { rw_toptexturemid = worldhigh + texheight; - rw_toptextureslide = ceilingbackslide; + rw_toptextureslide = FixedMul(ceilingbackslide, abs(rw_toptexturescaley)); } - rw_toptexturemid = FixedMul(rw_toptexturemid, rw_toptexturescaley); + rw_toptexturemid = FixedMul(rw_toptexturemid, abs(rw_toptexturescaley)); + rw_toptexturemid += toprowoffset; } // check BOTTOM TEXTURE @@ -2052,24 +2122,24 @@ void R_StoreWallRange(INT32 start, INT32 stop) // bottom of texture at bottom // top of texture at top rw_bottomtexturemid = worldbottom; - rw_bottomtextureslide = floorfrontslide; + rw_bottomtextureslide = FixedMul(floorfrontslide, abs(rw_bottomtexturescaley)); } else { // top of texture at top rw_bottomtexturemid = worldlow; - rw_bottomtextureslide = floorbackslide; + rw_bottomtextureslide = FixedMul(floorbackslide, abs(rw_bottomtexturescaley)); } - rw_bottomtexturemid = FixedMul(rw_bottomtexturemid, rw_bottomtexturescaley); + rw_bottomtexturemid = FixedMul(rw_bottomtexturemid, abs(rw_bottomtexturescaley)); + rw_bottomtexturemid += botrowoffset; } - rw_toptexturemid += toprowoffset; - rw_bottomtexturemid += botrowoffset; - // allocate space for masked texture tables R_AllocTextureColumnTables(rw_stopx - start); + texcoltables = true; + if (frontsector && backsector && !Tag_Compare(&frontsector->tags, &backsector->tags) && (backsector->ffloors || frontsector->ffloors)) { ffloor_t *rover; @@ -2268,7 +2338,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) ds_p->maskedtexturecol = maskedtexturecol = curtexturecolumntable - rw_x; curtexturecolumntable += rw_stopx - rw_x; - maskedtextureheight = ds_p->maskedtextureheight; // note to red, this == &(ds_p->maskedtextureheight[0]) + ds_p->maskedtextureheight = maskedtextureheight = curtexturecolumntable - rw_x; + curtexturecolumntable += rw_stopx - rw_x; maskedtexture = true; @@ -2310,13 +2381,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) } } - rw_midtexturemid = FixedMul(rw_midtexturemid, rw_midtexturescaley); - rw_midtextureback = FixedMul(rw_midtextureback, rw_midtexturescaley); + rw_midtexturemid = FixedMul(rw_midtexturemid, abs(rw_midtexturescaley)); + rw_midtextureback = FixedMul(rw_midtextureback, abs(rw_midtexturescaley)); + + rw_midtextureslide = FixedMul(rw_midtextureslide, abs(rw_midtexturescaley)); + rw_midtexturebackslide = FixedMul(rw_midtexturebackslide, abs(rw_midtexturescaley)); rw_midtexturemid += sidedef->rowoffset + sidedef->offsety_mid; rw_midtextureback += sidedef->rowoffset + sidedef->offsety_mid; - - maskedtexture = true; } } @@ -2440,7 +2512,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (frontsector->numlights) { dc_numlights = frontsector->numlights; - if (dc_numlights >= dc_maxlights) + if (dc_numlights > dc_maxlights) { dc_maxlights = dc_numlights; dc_lightlist = Z_Realloc(dc_lightlist, sizeof (*dc_lightlist) * dc_maxlights, PU_STATIC, NULL); diff --git a/src/r_things.c b/src/r_things.c index d6ef72b9d..2d1e27a59 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -658,12 +658,31 @@ void R_DrawMaskedColumn(column_t *column, unsigned lengthcol) static UINT8 *flippedcol = NULL; static size_t flippedcolsize = 0; +void R_DrawFlippedPost(UINT8 *source, unsigned length, void (*drawcolfunc)(void)) +{ + if (!length) + return; + + if (!flippedcolsize || length > flippedcolsize) + { + flippedcolsize = length; + flippedcol = Z_Realloc(flippedcol, length, PU_STATIC, NULL); + } + + dc_source = flippedcol; + + for (UINT8 *s = (UINT8 *)source, *d = flippedcol+length-1; d >= flippedcol; s++) + *d-- = *s; + + drawcolfunc(); +} + void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol) { INT32 topscreen; INT32 bottomscreen; fixed_t basetexturemid = dc_texturemid; - UINT8 *d,*s; + INT32 topdelta; for (unsigned i = 0; i < column->num_posts; i++) { @@ -671,7 +690,7 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol) if (!post->length) continue; - INT32 topdelta = lengthcol-post->length-post->topdelta; + topdelta = lengthcol-post->length-post->topdelta; topscreen = sprtopscreen + spryscale*topdelta; bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*post->length : sprbotscreen + spryscale*post->length; @@ -698,18 +717,9 @@ void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol) if (dc_yl <= dc_yh && dc_yh > 0) { - if (post->length > flippedcolsize) - { - flippedcolsize = post->length; - flippedcol = Z_Realloc(flippedcol, flippedcolsize, PU_STATIC, NULL); - } - - for (s = column->pixels+post->data_offset+post->length, d = flippedcol; d < flippedcol+post->length; --s) - *d++ = *s; - dc_source = flippedcol; dc_texturemid = basetexturemid - (topdelta<pixels + post->data_offset, post->length, colfunc); } } diff --git a/src/r_things.h b/src/r_things.h index 043b454b0..f68d75a83 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -48,6 +48,7 @@ extern fixed_t windowbottom; void R_DrawMaskedColumn(column_t *column, unsigned lengthcol); void R_DrawFlippedMaskedColumn(column_t *column, unsigned lengthcol); +void R_DrawFlippedPost(UINT8 *source, unsigned length, void (*drawcolfunc)(void)); // ---------------- // SPRITE RENDERING diff --git a/src/tables.h b/src/tables.h index 2736f03e8..65d7f7243 100644 --- a/src/tables.h +++ b/src/tables.h @@ -81,7 +81,7 @@ extern angle_t tantoangle[SLOPERANGE+1]; // Utility function, called by R_PointToAngle. FUNCMATH unsigned SlopeDiv(unsigned num, unsigned den); -// Only called by R_PointToAngleEx +// Only called by R_PointToAngle64 UINT64 SlopeDivEx(unsigned int num, unsigned int den); // 360 - angle_t(ANGLE_45) = ANGLE_315