diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index cf9689a97..f260e0bdc 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -833,13 +833,11 @@ static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIEL // // HWR_SplitWall +// SoM: split up and light walls according to the lightlist. +// This may also include leaving out parts of the wall that can't be seen // static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor, FBITFIELD polyflags) { - /* SoM: split up and light walls according to the - lightlist. This may also include leaving out parts - of the wall that can't be seen */ - float realtop, realbot, top, bot; float pegt, pegb, pegmul; float height = 0.0f, bheight = 0.0f; @@ -848,38 +846,51 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, float endpegt, endpegb, endpegmul; float endheight = 0.0f, endbheight = 0.0f; - // compiler complains when P_GetSlopeZAt is used in FLOAT_TO_FIXED directly - // use this as a temp var to store P_GetSlopeZAt's return value each time - fixed_t temp; + float diff; - fixed_t v1x = FLOAT_TO_FIXED(wallVerts[0].x); - fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].z); // not a typo - fixed_t v2x = FLOAT_TO_FIXED(wallVerts[1].x); - fixed_t v2y = FLOAT_TO_FIXED(wallVerts[1].z); // not a typo + fixed_t v1x = FloatToFixed(wallVerts[0].x); + fixed_t v1y = FloatToFixed(wallVerts[0].z); + fixed_t v2x = FloatToFixed(wallVerts[1].x); + fixed_t v2y = FloatToFixed(wallVerts[1].z); - INT32 solid, i; - lightlist_t * list = sector->lightlist; const UINT8 alpha = Surf->PolyColor.s.alpha; FUINT lightnum = sector->lightlevel; extracolormap_t *colormap = NULL; realtop = top = wallVerts[3].y; realbot = bot = wallVerts[0].y; + diff = top - bot; + pegt = wallVerts[3].t; pegb = wallVerts[0].t; - pegmul = (pegb - pegt) / (top - bot); + + // Lactozilla: If both heights of a side lay on the same position, then this wall is a triangle. + // To avoid division by zero, which would result in a NaN, we check if the vertical difference + // between the two vertices is not zero. + if (fpclassify(diff) == FP_ZERO) + pegmul = 0.0; + else + pegmul = (pegb - pegt) / diff; endrealtop = endtop = wallVerts[2].y; endrealbot = endbot = wallVerts[1].y; + diff = endtop - endbot; + endpegt = wallVerts[2].t; endpegb = wallVerts[1].t; - endpegmul = (endpegb - endpegt) / (endtop - endbot); - for (i = 0; i < sector->numlights; i++) + if (fpclassify(diff) == FP_ZERO) + endpegmul = 0.0; + else + endpegmul = (endpegb - endpegt) / diff; + + for (INT32 i = 0; i < sector->numlights; i++) { if (endtop < endrealbot && top < realbot) return; + lightlist_t *list = sector->lightlist; + if (!(list[i].flags & FOF_NOSHADE)) { if (pfloor && (pfloor->fofflags & FOF_FOG)) @@ -894,7 +905,7 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, } } - solid = false; + boolean solid = false; if ((sector->lightlist[i].flags & FOF_CUTSOLIDS) && !(cutflag & FOF_EXTRA)) solid = true; @@ -911,16 +922,13 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, else solid = false; - temp = P_GetLightZAt(&list[i], v1x, v1y); - height = FIXED_TO_FLOAT(temp); - temp = P_GetLightZAt(&list[i], v2x, v2y); - endheight = FIXED_TO_FLOAT(temp); + height = FixedToFloat(P_GetLightZAt(&list[i], v1x, v1y)); + endheight = FixedToFloat(P_GetLightZAt(&list[i], v2x, v2y)); + if (solid) { - temp = P_GetFFloorBottomZAt(list[i].caster, v1x, v1y); - bheight = FIXED_TO_FLOAT(temp); - temp = P_GetFFloorBottomZAt(list[i].caster, v2x, v2y); - endbheight = FIXED_TO_FLOAT(temp); + bheight = FixedToFloat(P_GetFFloorBottomZAt(list[i].caster, v1x, v1y)); + endbheight = FixedToFloat(P_GetFFloorBottomZAt(list[i].caster, v2x, v2y)); } if (endheight >= endtop && height >= top) @@ -933,10 +941,8 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, if (i + 1 < sector->numlights) { - temp = P_GetLightZAt(&list[i+1], v1x, v1y); - bheight = FIXED_TO_FLOAT(temp); - temp = P_GetLightZAt(&list[i+1], v2x, v2y); - endbheight = FIXED_TO_FLOAT(temp); + bheight = FixedToFloat(P_GetLightZAt(&list[i+1], v1x, v1y)); + endbheight = FixedToFloat(P_GetLightZAt(&list[i+1], v2x, v2y)); } else { @@ -944,19 +950,20 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, endbheight = endrealbot; } - if (endbheight >= endtop && bheight >= top) + if (endbheight > endtop) + endbot = endtop; + + if (bheight >= top) continue; - //Found a break; + // Found a break + // The heights are clamped to ensure the polygon doesn't cross itself. bot = bheight; if (bot < realbot) bot = realbot; - endbot = endbheight; - - if (endbot < endrealbot) - endbot = endrealbot; + endbot = min(max(endbheight, endrealbot), endtop); Surf->PolyColor.s.alpha = alpha; @@ -1025,6 +1032,42 @@ static void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf) // PF_Occlude is set in HWR_ProjectWall to draw into the depth buffer } +// Returns true if the midtexture is visible, and false if... it isn't... +static boolean HWR_BlendMidtextureSurface(FSurfaceInfo *pSurf) +{ + FUINT blendmode = PF_Masked; + + pSurf->PolyColor.s.alpha = 0xFF; + + if (!gl_curline->polyseg) + { + if (gl_linedef->blendmode && gl_linedef->blendmode != AST_FOG) + { + if (gl_linedef->alpha >= 0 && gl_linedef->alpha < FRACUNIT) + blendmode = HWR_SurfaceBlend(gl_linedef->blendmode, R_GetLinedefTransTable(gl_linedef->alpha), pSurf); + else + blendmode = HWR_GetBlendModeFlag(gl_linedef->blendmode); + } + else if (gl_linedef->alpha >= 0 && gl_linedef->alpha < FRACUNIT) + blendmode = HWR_TranstableToAlpha(R_GetLinedefTransTable(gl_linedef->alpha), pSurf); + } + else if (gl_curline->polyseg->translucency > 0) + { + // Polyobject translucency is done differently + if (gl_curline->polyseg->translucency >= NUMTRANSMAPS) // wall not drawn + return false; + else + blendmode = HWR_TranstableToAlpha(gl_curline->polyseg->translucency, pSurf); + } + + if (blendmode != PF_Masked && pSurf->PolyColor.s.alpha == 0x00) + return false; + + pSurf->PolyFlags = blendmode; + + return true; +} + // // HWR_ProcessSeg // A portion or all of a wall segment will be drawn, from startfrac to endfrac, @@ -1043,16 +1086,9 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom fixed_t worldhighslope = 0, worldlowslope = 0; fixed_t v1x, v1y, v2x, v2y; - GLMapTexture_t *grTex = NULL; - float cliplow = 0.0f, cliphigh = 0.0f; - INT32 gl_midtexture; fixed_t h, l; // 3D sides and 2s middle textures fixed_t hS, lS; - FUINT lightnum = 255; - extracolormap_t *colormap; - FSurfaceInfo Surf; - boolean tripwire; gl_sidedef = gl_curline->sidedef; @@ -1104,11 +1140,15 @@ 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; - cliplow = (float)texturehpeg; - cliphigh = (float)(texturehpeg + (gl_curline->flength*FRACUNIT)); - } + fixed_t texturehpeg = gl_sidedef->textureoffset + gl_curline->offset; + float cliplow = (float)texturehpeg; + float cliphigh = (float)(texturehpeg + (gl_curline->flength*FRACUNIT)); + + FUINT lightnum = 255; + extracolormap_t *colormap = gl_frontsector->extra_colormap; + + FSurfaceInfo Surf; + Surf.PolyColor.s.alpha = 255; tripwire = P_IsLineTripWire(gl_linedef); @@ -1117,15 +1157,16 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom lightnum = HWR_CalcWallLight(gl_frontsector->lightlevel, gl_curline); } - colormap = gl_frontsector->extra_colormap; - - if (gl_frontsector) - Surf.PolyColor.s.alpha = 255; + INT32 gl_midtexture = R_GetTextureNum(gl_sidedef->midtexture); + GLMapTexture_t *grTex = NULL; + // two sided line if (gl_backsector) { INT32 gl_toptexture = 0, gl_bottomtexture = 0; - // two sided line + + fixed_t texturevpeg; + boolean bothceilingssky = false; // turned on if both back and front ceilings are sky boolean bothfloorssky = false; // likewise, but for floors @@ -1241,51 +1282,47 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // check TOP TEXTURE if ((worldhighslope < worldtopslope || worldhigh < worldtop) && gl_toptexture) { + // PEGGING + if (gl_linedef->flags & ML_DONTPEGTOP) + texturevpeg = 0; + else if (gl_linedef->flags & ML_SKEWTD) + texturevpeg = worldhigh + textureheight[gl_toptexture] - worldtop; + else + texturevpeg = gl_backsector->ceilingheight + textureheight[gl_toptexture] - gl_frontsector->ceilingheight; + + texturevpeg += gl_sidedef->rowoffset; + + // 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 %= textureheight[gl_toptexture]; + + grTex = HWR_GetTexture(gl_toptexture); + + wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; + wallVerts[0].t = wallVerts[1].t = (texturevpeg + gl_frontsector->ceilingheight - gl_backsector->ceilingheight) * grTex->scaleY; + wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + + // Adjust t value for sloped walls + if (!(gl_linedef->flags & ML_SKEWTD)) { - fixed_t texturevpegtop; // top - - grTex = HWR_GetTexture(gl_toptexture); - - // PEGGING - if (gl_linedef->flags & ML_DONTPEGTOP) - texturevpegtop = 0; - else if (gl_linedef->flags & ML_SKEWTD) - texturevpegtop = worldhigh + textureheight[gl_sidedef->toptexture] - worldtop; - else - texturevpegtop = gl_backsector->ceilingheight + textureheight[gl_sidedef->toptexture] - gl_frontsector->ceilingheight; - - texturevpegtop += gl_sidedef->rowoffset; - - // 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 - texturevpegtop %= (textures[gl_toptexture]->height)<scaleY; - wallVerts[0].t = wallVerts[1].t = (texturevpegtop + gl_frontsector->ceilingheight - gl_backsector->ceilingheight) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; - - // Adjust t value for sloped walls - if (!(gl_linedef->flags & ML_SKEWTD)) - { - // Unskewed - wallVerts[3].t -= (worldtop - gl_frontsector->ceilingheight) * grTex->scaleY; - wallVerts[2].t -= (worldtopslope - gl_frontsector->ceilingheight) * grTex->scaleY; - wallVerts[0].t -= (worldhigh - gl_backsector->ceilingheight) * grTex->scaleY; - wallVerts[1].t -= (worldhighslope - gl_backsector->ceilingheight) * grTex->scaleY; - } - else if (gl_linedef->flags & ML_DONTPEGTOP) - { - // Skewed by top - wallVerts[0].t = (texturevpegtop + worldtop - worldhigh) * grTex->scaleY; - wallVerts[1].t = (texturevpegtop + worldtopslope - worldhighslope) * grTex->scaleY; - } - else - { - // Skewed by bottom - wallVerts[0].t = wallVerts[1].t = (texturevpegtop + worldtop - worldhigh) * grTex->scaleY; - wallVerts[3].t = wallVerts[0].t - (worldtop - worldhigh) * grTex->scaleY; - wallVerts[2].t = wallVerts[1].t - (worldtopslope - worldhighslope) * grTex->scaleY; - } + // Unskewed + wallVerts[3].t -= (worldtop - gl_frontsector->ceilingheight) * grTex->scaleY; + wallVerts[2].t -= (worldtopslope - gl_frontsector->ceilingheight) * grTex->scaleY; + wallVerts[0].t -= (worldhigh - gl_backsector->ceilingheight) * grTex->scaleY; + wallVerts[1].t -= (worldhighslope - gl_backsector->ceilingheight) * grTex->scaleY; + } + else if (gl_linedef->flags & ML_DONTPEGTOP) + { + // Skewed by top + wallVerts[0].t = (texturevpeg + worldtop - worldhigh) * grTex->scaleY; + wallVerts[1].t = (texturevpeg + worldtopslope - worldhighslope) * grTex->scaleY; + } + else + { + // Skewed by bottom + wallVerts[0].t = wallVerts[1].t = (texturevpeg + worldtop - worldhigh) * grTex->scaleY; + wallVerts[3].t = wallVerts[0].t - (worldtop - worldhigh) * grTex->scaleY; + wallVerts[2].t = wallVerts[1].t - (worldtopslope - worldhighslope) * grTex->scaleY; } // set top/bottom coords @@ -1294,71 +1331,62 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope); wallVerts[1].y = FIXED_TO_FLOAT(worldhighslope); - { - FBITFIELD polyflags = PF_Masked; + FBITFIELD polyflags = PF_Masked; - if (grTex->mipmap.flags & TF_TRANSPARENT) - polyflags = PF_Environment; + if (grTex->mipmap.flags & TF_TRANSPARENT) + polyflags = PF_Environment; - if (gl_frontsector->numlights) - HWR_SplitWall(gl_frontsector, wallVerts, gl_toptexture, &Surf, FOF_CUTLEVEL, NULL, polyflags); - else if (grTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, &Surf, gl_toptexture, polyflags, false, lightnum, colormap); - else - HWR_ProjectWall(wallVerts, &Surf, polyflags, lightnum, colormap); - } + if (gl_frontsector->numlights) + HWR_SplitWall(gl_frontsector, wallVerts, gl_toptexture, &Surf, FOF_CUTLEVEL, NULL, polyflags); + else if (grTex->mipmap.flags & TF_TRANSPARENT) + HWR_AddTransparentWall(wallVerts, &Surf, gl_toptexture, polyflags, false, lightnum, colormap); + else + HWR_ProjectWall(wallVerts, &Surf, polyflags, lightnum, colormap); } // check BOTTOM TEXTURE - if (( - worldlowslope > worldbottomslope || - worldlow > worldbottom) && gl_bottomtexture) //only if VISIBLE!!! + if ((worldlowslope > worldbottomslope || worldlow > worldbottom) && gl_bottomtexture) { + // PEGGING + if (!(gl_linedef->flags & ML_DONTPEGBOTTOM)) + texturevpeg = 0; + else if (gl_linedef->flags & ML_SKEWTD) + texturevpeg = worldbottom - worldlow; + else + texturevpeg = gl_frontsector->floorheight - gl_backsector->floorheight; + + texturevpeg += gl_sidedef->rowoffset; + + // 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 %= textureheight[gl_bottomtexture]; + + grTex = HWR_GetTexture(gl_bottomtexture); + + wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; + wallVerts[0].t = wallVerts[1].t = (texturevpeg + gl_backsector->floorheight - gl_frontsector->floorheight) * grTex->scaleY; + wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + + // Adjust t value for sloped walls + if (!(gl_linedef->flags & ML_SKEWTD)) { - fixed_t texturevpegbottom = 0; // bottom - - grTex = HWR_GetTexture(gl_bottomtexture); - - // PEGGING - if (!(gl_linedef->flags & ML_DONTPEGBOTTOM)) - texturevpegbottom = 0; - else if (gl_linedef->flags & ML_SKEWTD) - texturevpegbottom = worldbottom - worldlow; - else - texturevpegbottom = gl_frontsector->floorheight - gl_backsector->floorheight; - - texturevpegbottom += gl_sidedef->rowoffset; - - // 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 - texturevpegbottom %= (textures[gl_bottomtexture]->height)<scaleY; - wallVerts[0].t = wallVerts[1].t = (texturevpegbottom + gl_backsector->floorheight - gl_frontsector->floorheight) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; - - // Adjust t value for sloped walls - if (!(gl_linedef->flags & ML_SKEWTD)) - { - // Unskewed - wallVerts[0].t -= (worldbottom - gl_frontsector->floorheight) * grTex->scaleY; - wallVerts[1].t -= (worldbottomslope - gl_frontsector->floorheight) * grTex->scaleY; - wallVerts[3].t -= (worldlow - gl_backsector->floorheight) * grTex->scaleY; - wallVerts[2].t -= (worldlowslope - gl_backsector->floorheight) * grTex->scaleY; - } - else if (gl_linedef->flags & ML_DONTPEGBOTTOM) - { - // Skewed by bottom - wallVerts[0].t = wallVerts[1].t = (texturevpegbottom + worldlow - worldbottom) * grTex->scaleY; - //wallVerts[3].t = wallVerts[0].t - (worldlow - worldbottom) * grTex->scaleY; // no need, [3] is already this - wallVerts[2].t = wallVerts[1].t - (worldlowslope - worldbottomslope) * grTex->scaleY; - } - else - { - // Skewed by top - wallVerts[0].t = (texturevpegbottom + worldlow - worldbottom) * grTex->scaleY; - wallVerts[1].t = (texturevpegbottom + worldlowslope - worldbottomslope) * grTex->scaleY; - } + // Unskewed + wallVerts[0].t -= (worldbottom - gl_frontsector->floorheight) * grTex->scaleY; + wallVerts[1].t -= (worldbottomslope - gl_frontsector->floorheight) * grTex->scaleY; + wallVerts[3].t -= (worldlow - gl_backsector->floorheight) * grTex->scaleY; + wallVerts[2].t -= (worldlowslope - gl_backsector->floorheight) * grTex->scaleY; + } + else if (gl_linedef->flags & ML_DONTPEGBOTTOM) + { + // Skewed by bottom + wallVerts[0].t = wallVerts[1].t = (texturevpeg + worldlow - worldbottom) * grTex->scaleY; + wallVerts[2].t = wallVerts[1].t - (worldlowslope - worldbottomslope) * grTex->scaleY; + } + else + { + // Skewed by top + wallVerts[0].t = (texturevpeg + worldlow - worldbottom) * grTex->scaleY; + wallVerts[1].t = (texturevpeg + worldlowslope - worldbottomslope) * grTex->scaleY; } // set top/bottom coords @@ -1367,29 +1395,23 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope); wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope); - { - FBITFIELD polyflags = PF_Masked; + FBITFIELD polyflags = PF_Masked; - if (grTex->mipmap.flags & TF_TRANSPARENT) - polyflags = PF_Environment; + if (grTex->mipmap.flags & TF_TRANSPARENT) + polyflags = PF_Environment; - if (gl_frontsector->numlights) - HWR_SplitWall(gl_frontsector, wallVerts, gl_bottomtexture, &Surf, FOF_CUTLEVEL, NULL, polyflags); - else if (grTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, &Surf, gl_bottomtexture, polyflags, false, lightnum, colormap); - else - HWR_ProjectWall(wallVerts, &Surf, polyflags, lightnum, colormap); - } + if (gl_frontsector->numlights) + HWR_SplitWall(gl_frontsector, wallVerts, gl_bottomtexture, &Surf, FOF_CUTLEVEL, NULL, polyflags); + else if (grTex->mipmap.flags & TF_TRANSPARENT) + HWR_AddTransparentWall(wallVerts, &Surf, gl_bottomtexture, polyflags, false, lightnum, colormap); + else + HWR_ProjectWall(wallVerts, &Surf, polyflags, lightnum, colormap); } - gl_midtexture = R_GetTextureNum(gl_sidedef->midtexture); - - if (gl_midtexture) + // Render midtexture if there's one. Determine if it's visible first, though + if (gl_midtexture && HWR_BlendMidtextureSurface(&Surf)) { - FBITFIELD blendmode; sector_t *front, *back; - fixed_t popentop, popenbottom, polytop, polybottom, lowcut, highcut; - fixed_t texturevpeg = 0; INT32 repeats; if (gl_linedef->frontsector->heightsec != -1) @@ -1418,57 +1440,73 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom else low = back->floorheight; - repeats = (high - low)/textureheight[gl_sidedef->midtexture]; - if ((high-low)%textureheight[gl_sidedef->midtexture]) + repeats = (high - low) / textureheight[gl_midtexture]; + if ((high - low) % textureheight[gl_midtexture]) repeats++; // tile an extra time to fill the gap -- Monster Iestyn } else repeats = 1; - // SoM: a little note: This code re-arranging will - // fix the bug in Nimrod map02. popentop and popenbottom + // 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 = back->ceilingheight; - popenbottom = back->floorheight; + 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 = textureheight[gl_midtexture] * repeats; + + // Texture is not skewed if (gl_linedef->flags & ML_NOSKEW) { - if (gl_linedef->flags & ML_MIDPEG) + if (gl_linedef->flags & ML_MIDPEG) // Peg it to the floor { polybottom = max(front->floorheight, back->floorheight) + gl_sidedef->rowoffset; - polytop = polybottom + textureheight[gl_midtexture]*repeats; + polytop = polybottom + midtexheight; } - else + else // Peg it to the ceiling { polytop = min(front->ceilingheight, back->ceilingheight) + gl_sidedef->rowoffset; - polybottom = polytop - textureheight[gl_midtexture]*repeats; + polybottom = polytop - midtexheight; } + + // The right side's coordinates are the the same as the left side + polytopslope = polytop; + polybottomslope = polybottom; } - else if (gl_linedef->flags & ML_MIDPEG) + else if (gl_linedef->flags & ML_MIDPEG) // Skew the texture, but peg it to the floor { polybottom = popenbottom + gl_sidedef->rowoffset; - polytop = polybottom + textureheight[gl_midtexture]*repeats; + polytop = polybottom + midtexheight; + polybottomslope = popenbottomslope + gl_sidedef->rowoffset; + polytopslope = polybottomslope + midtexheight; } - else + else // Skew it according to the ceiling's slope { polytop = popentop + gl_sidedef->rowoffset; - polybottom = polytop - textureheight[gl_midtexture]*repeats; + polybottom = polytop - midtexheight; + polytopslope = popentopslope + gl_sidedef->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 @@ -1476,40 +1514,63 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { 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) { - // PEGGING - if (gl_linedef->flags & ML_MIDPEG) - texturevpeg = textureheight[gl_sidedef->midtexture]*repeats - h + polybottom; - else - texturevpeg = polytop - h; - - grTex = HWR_GetTexture(gl_midtexture); - - wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; - wallVerts[0].t = wallVerts[1].t = (h - l + texturevpeg) * grTex->scaleY; - wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + texturevpeg = midtexheight - h + polybottom; + texturevpegslope = midtexheight - hS + polybottomslope; } + else + { + texturevpeg = polytop - h; + texturevpegslope = polytopslope - hS; + } + + grTex = HWR_GetTexture(gl_midtexture); + + // Left side + wallVerts[3].t = texturevpeg * grTex->scaleY; + wallVerts[0].t = (h - l + texturevpeg) * grTex->scaleY; + wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; + + // Right side + wallVerts[2].t = texturevpegslope * grTex->scaleY; + wallVerts[1].t = (hS - lS + texturevpegslope) * grTex->scaleY; + wallVerts[2].s = wallVerts[1].s = cliphigh * 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[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h); - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l); + 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); - // Correct to account for slopes + // TODO: Actually use the surface's flags so that I don't have to do this + FUINT blendmode = Surf.PolyFlags; + + if (udmf) // lug: idk if we should even keep this? seems like it doesent do anything since udmf maps still had issues which this did not fix { + // Correct to account for slopes fixed_t midtextureslant; if (gl_linedef->flags & ML_NOSKEW) @@ -1603,26 +1664,22 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { if (!gl_curline->polyseg) // Don't do it for polyobjects { - if (gl_frontsector->ceilingpic == skyflatnum) + if (gl_frontsector->ceilingpic == skyflatnum + && gl_backsector->ceilingpic != skyflatnum) // don't cull if back sector is also sky { - if (gl_backsector->ceilingpic != skyflatnum) // don't cull if back sector is also sky - { - wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(INT32_MAX); // draw to top of map space - wallVerts[0].y = FIXED_TO_FLOAT(worldtop); - wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); - HWR_DrawSkyWall(wallVerts, &Surf); - } + wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(INT32_MAX); // draw to top of map space + wallVerts[0].y = FIXED_TO_FLOAT(worldtop); + wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); + HWR_DrawSkyWall(wallVerts, &Surf); } - if (gl_frontsector->floorpic == skyflatnum) + if (gl_frontsector->floorpic == skyflatnum + && gl_backsector->floorpic != skyflatnum) // same thing here { - if (gl_backsector->floorpic != skyflatnum) // don't cull if back sector is also sky - { - wallVerts[3].y = FIXED_TO_FLOAT(worldbottom); - wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope); - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); // draw to bottom of map space - HWR_DrawSkyWall(wallVerts, &Surf); - } + wallVerts[3].y = FIXED_TO_FLOAT(worldbottom); + wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope); + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); // draw to bottom of map space + HWR_DrawSkyWall(wallVerts, &Surf); } } } @@ -1630,40 +1687,38 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom else { // Single sided line... Deal only with the middletexture (if one exists) - gl_midtexture = R_GetTextureNum(gl_sidedef->midtexture); - if (gl_midtexture && gl_linedef->special != 41) // (Ignore horizon line for OGL) + if (gl_midtexture && gl_linedef->special != HORIZONSPECIAL) // (Ignore horizon line for OGL) { - { - fixed_t texturevpeg; - // PEGGING - if ((gl_linedef->flags & (ML_DONTPEGBOTTOM|ML_NOSKEW)) == (ML_DONTPEGBOTTOM|ML_NOSKEW)) - texturevpeg = gl_frontsector->floorheight + textureheight[gl_sidedef->midtexture] - gl_frontsector->ceilingheight + gl_sidedef->rowoffset; - else if (gl_linedef->flags & ML_DONTPEGBOTTOM) - texturevpeg = worldbottom + textureheight[gl_sidedef->midtexture] - worldtop + gl_sidedef->rowoffset; - else - // top of texture at top - texturevpeg = gl_sidedef->rowoffset; + fixed_t texturevpeg; - grTex = HWR_GetTexture(gl_midtexture); + // PEGGING + if ((gl_linedef->flags & (ML_DONTPEGBOTTOM|ML_NOSKEW)) == (ML_DONTPEGBOTTOM|ML_NOSKEW)) + texturevpeg = gl_frontsector->floorheight + textureheight[gl_sidedef->midtexture] - gl_frontsector->ceilingheight + gl_sidedef->rowoffset; + else if (gl_linedef->flags & ML_DONTPEGBOTTOM) + texturevpeg = worldbottom + textureheight[gl_sidedef->midtexture] - worldtop + gl_sidedef->rowoffset; + else + // top of texture at top + texturevpeg = gl_sidedef->rowoffset; - 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 * grTex->scaleX; - wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + grTex = HWR_GetTexture(gl_midtexture); - // Texture correction for slopes - if (gl_linedef->flags & ML_NOSKEW) { - wallVerts[3].t += (gl_frontsector->ceilingheight - worldtop) * grTex->scaleY; - wallVerts[2].t += (gl_frontsector->ceilingheight - worldtopslope) * grTex->scaleY; - wallVerts[0].t += (gl_frontsector->floorheight - worldbottom) * grTex->scaleY; - wallVerts[1].t += (gl_frontsector->floorheight - worldbottomslope) * grTex->scaleY; - } else if (gl_linedef->flags & ML_DONTPEGBOTTOM) { - wallVerts[3].t = wallVerts[0].t + (worldbottom-worldtop) * grTex->scaleY; - wallVerts[2].t = wallVerts[1].t + (worldbottomslope-worldtopslope) * grTex->scaleY; - } else { - wallVerts[0].t = wallVerts[3].t - (worldbottom-worldtop) * grTex->scaleY; - wallVerts[1].t = wallVerts[2].t - (worldbottomslope-worldtopslope) * grTex->scaleY; - } + 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 * grTex->scaleX; + wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; + + // Texture correction for slopes + if (gl_linedef->flags & ML_NOSKEW) { + wallVerts[3].t += (gl_frontsector->ceilingheight - worldtop) * grTex->scaleY; + wallVerts[2].t += (gl_frontsector->ceilingheight - worldtopslope) * grTex->scaleY; + wallVerts[0].t += (gl_frontsector->floorheight - worldbottom) * grTex->scaleY; + wallVerts[1].t += (gl_frontsector->floorheight - worldbottomslope) * grTex->scaleY; + } else if (gl_linedef->flags & ML_DONTPEGBOTTOM) { + wallVerts[3].t = wallVerts[0].t + (worldbottom-worldtop) * grTex->scaleY; + wallVerts[2].t = wallVerts[1].t + (worldbottomslope-worldtopslope) * grTex->scaleY; + } else { + wallVerts[0].t = wallVerts[3].t - (worldbottom-worldtop) * grTex->scaleY; + wallVerts[1].t = wallVerts[2].t - (worldbottomslope-worldtopslope) * grTex->scaleY; } //Set textures properly on single sided walls that are sloped @@ -1726,7 +1781,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom //Hurdler: 3d-floors test - if (gl_frontsector && gl_backsector && !Tag_Compare(&gl_frontsector->tags, &gl_backsector->tags) && (gl_backsector->ffloors || gl_frontsector->ffloors)) + if (gl_backsector && !Tag_Compare(&gl_frontsector->tags, &gl_backsector->tags) && (gl_backsector->ffloors || gl_frontsector->ffloors)) { ffloor_t * rover; fixed_t highcut = 0, lowcut = 0; diff --git a/src/r_main.c b/src/r_main.c index 05fec4c6f..8cc2b2009 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -261,7 +261,7 @@ INT32 R_PointOnSideUDMF(fixed_t x, fixed_t y, const node_t *node) // Try to quickly decide by looking at sign bits. INT32 mask = (node->dy ^ node->dx ^ dx ^ dy) >> 31; return (mask & ((node->dy ^ dx) < 0)) | // (left is negative) - (~mask & (FixedMul(dy, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, dx))); + (~mask & (FixedMul(dy, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, dx))); } INT32 R_PointOnSideKart(fixed_t x, fixed_t y, const node_t *restrict node) @@ -279,7 +279,7 @@ INT32 R_PointOnSideKart(fixed_t x, fixed_t y, const node_t *restrict node) // also use a mask to avoid branch prediction INT32 mask = (node->dy ^ node->dx ^ x ^ y) >> 31; return (mask & ((node->dy ^ x) < 0)) | // (left is negative) - (~mask & (FixedMul(y, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, x))); + (~mask & (FixedMul(y, node->dx>>FRACBITS) >= FixedMul(node->dy>>FRACBITS, x))); } // killough 5/2/98: reformatted @@ -305,24 +305,6 @@ INT32 R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line) return FixedMul(dy, ldx>>FRACBITS) >= FixedMul(ldy>>FRACBITS, dx); } -// -// R_PointToAngle -// To get a global angle from cartesian coordinates, -// the coordinates are flipped until they are in -// the first octant of the coordinate system, then -// the y (<=x) is scaled and divided by x to get a -// tangent (slope) value which is looked up in the -// tantoangle[] table. The +1 size of tantoangle[] -// is to handle the case when x==y without additional -// checking. -// -// killough 5/2/98: reformatted, cleaned up - -angle_t R_PointToAngle(fixed_t x, fixed_t y) -{ - return R_PointToAngle2(viewx, viewy, x, y); -} - // Similar to R_PointToAngle, but requires an additional player_t argument. // If this player is a local displayplayer, this will base off the calculations off of their camera instead, otherwise use viewx/viewy as usual. // Yes this is kinda ghetto. @@ -385,40 +367,6 @@ angle_t R_PointToAngle2(fixed_t pviewx, fixed_t pviewy, fixed_t x, fixed_t y) 0; } -fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1) -{ - return FixedHypot(px1 - px2, py1 - py2); -} - -// Little extra utility. Works in the same way as R_PointToAngle2 -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) -{ - INT64 dx = x1-x2; - INT64 dy = y1-y2; - if (dx < INT32_MIN || dx > INT32_MAX || dy < INT32_MIN || dy > INT32_MAX) - { - x1 = (int)(dx / 2 + x2); - y1 = (int)(dy / 2 + y2); - } - 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; -} - // // R_ScaleFromGlobalAngle // Returns the texture mapping scale for the current line (horizontal span) diff --git a/src/r_main.h b/src/r_main.h index 2f0d87799..bdea280ab 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -75,13 +75,12 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; INT32 R_PointOnSideUDMF(fixed_t x, fixed_t y, const node_t *node); INT32 R_PointOnSideKart(fixed_t x, fixed_t y, const node_t *node); INT32 R_PointOnSegSide(fixed_t x, fixed_t y, const seg_t *line); -angle_t R_PointToAngle(fixed_t x, fixed_t y); +#define R_PointToAngle(x, y) R_PointToAngle2(viewx, viewy, x, y) angle_t R_PointToAnglePlayer(player_t *player, 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); +#define R_PointToDist(x, y) R_PointToDist2(viewx, viewy, x, y) +#define R_PointToDist2(px2, py2, px1, py1) FixedHypot((px1) - (px2), (py1) - (py2)) fixed_t R_ScaleFromGlobalAngle(angle_t visangle); subsector_t *R_PointInSubsector(fixed_t x, fixed_t y);