From fa3e5e34a8f7850b78a28ff3689f109638b3c584 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 12 Nov 2019 02:22:30 +0100 Subject: [PATCH] Move all ProjectedWallTexcoords calculations to that class --- src/rendering/swrenderer/line/r_line.cpp | 226 +------------- src/rendering/swrenderer/line/r_line.h | 6 - .../swrenderer/line/r_renderdrawsegment.cpp | 76 +---- src/rendering/swrenderer/line/r_wallsetup.cpp | 279 ++++++++++++++++++ src/rendering/swrenderer/line/r_wallsetup.h | 11 + 5 files changed, 307 insertions(+), 291 deletions(-) diff --git a/src/rendering/swrenderer/line/r_line.cpp b/src/rendering/swrenderer/line/r_line.cpp index 9c793d5c1..aa4f9a509 100644 --- a/src/rendering/swrenderer/line/r_line.cpp +++ b/src/rendering/swrenderer/line/r_line.cpp @@ -301,7 +301,6 @@ namespace swrenderer SetWallVariables(); } - line_t *linedef = mLineSegment->linedef; side_t *sidedef = mLineSegment->sidedef; RenderPortal *renderportal = Thread->Portal.get(); @@ -419,43 +418,7 @@ namespace swrenderer if (pic) { draw_segment->SetHas3DFloorMidTexture(); - - double yscale = GetYScale(sidedef, pic, side_t::mid); - double cameraZ = Thread->Viewport->viewpoint.Pos.Z; - - double texZFloor = MAX(mFrontSector->GetPlaneTexZ(sector_t::floor), mBackSector->GetPlaneTexZ(sector_t::floor)); - double texZCeiling = MIN(mFrontSector->GetPlaneTexZ(sector_t::ceiling), mBackSector->GetPlaneTexZ(sector_t::ceiling)); - - double TextureMid; - if (yscale >= 0) - { // normal orientation - if (linedef->flags & ML_DONTPEGBOTTOM) - { // bottom of texture at bottom - TextureMid = (texZFloor - cameraZ) * yscale + pic->GetHeight(); - } - else - { // top of texture at top - TextureMid = (texZCeiling - cameraZ) * yscale; - } - } - else - { // upside down - if (linedef->flags & ML_DONTPEGBOTTOM) - { // top of texture at bottom - TextureMid = (texZFloor - cameraZ) * yscale; - } - else - { // bottom of texture at top - TextureMid = (texZCeiling - cameraZ) * yscale + pic->GetHeight(); - } - } - - TextureMid += GetRowOffset(linedef, sidedef, pic, side_t::mid); - - draw_segment->texcoords.Project(Thread->Viewport.get(), sidedef->TexelLength * GetXScale(sidedef, pic, side_t::mid), WallC.sx1, WallC.sx2, WallT); - draw_segment->texcoords.xoffset = GetXOffset(sidedef, pic, side_t::mid); - draw_segment->texcoords.yscale = yscale; - draw_segment->texcoords.texturemid = TextureMid; + draw_segment->texcoords.ProjectTranslucent(Thread->Viewport.get(), mFrontSector, mBackSector, mLineSegment, WallC.sx1, WallC.sx2, WallT, pic); } } @@ -959,43 +922,8 @@ namespace swrenderer if (!mTopTexture) return; if (!viewactive) return; - side_t* sidedef = mLineSegment->sidedef; - line_t* linedef = mLineSegment->linedef; - - double yscale = GetYScale(sidedef, mTopTexture, side_t::top); - double cameraZ = Thread->Viewport->viewpoint.Pos.Z; - - double TextureMid; - if (yscale >= 0) - { // normal orientation - if (linedef->flags & ML_DONTPEGTOP) - { // top of texture at top - TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale; - } - else - { // bottom of texture at bottom - TextureMid = (mBackSector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale + mTopTexture->GetHeight(); - } - } - else - { // upside down - if (linedef->flags & ML_DONTPEGTOP) - { // bottom of texture at top - TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale + mTopTexture->GetHeight(); - } - else - { // top of texture at bottom - TextureMid = (mBackSector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale; - } - } - - TextureMid += GetRowOffset(linedef, sidedef, mTopTexture, side_t::top); - ProjectedWallTexcoords texcoords; - texcoords.Project(Thread->Viewport.get(), mLineSegment->sidedef->TexelLength * GetXScale(sidedef, mTopTexture, side_t::top), WallC.sx1, WallC.sx2, WallT); - texcoords.xoffset = GetXOffset(sidedef, mTopTexture, side_t::top); - texcoords.yscale = yscale; - texcoords.texturemid = TextureMid; + texcoords.ProjectTop(Thread->Viewport.get(), mFrontSector, mBackSector, mLineSegment, WallC.sx1, WallC.sx2, WallT, mTopTexture); RenderWallPart renderWallpart(Thread); renderWallpart.Render(mFrontSector, mLineSegment, WallC, mTopTexture, x1, x2, walltop.ScreenY, wallupper.ScreenY, texcoords, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mBackCeilingZ1, mBackCeilingZ2), false, false, OPAQUE, mLight, GetLightList()); @@ -1006,43 +934,8 @@ namespace swrenderer if (!mMiddleTexture) return; if (!viewactive) return; - side_t* sidedef = mLineSegment->sidedef; - line_t* linedef = mLineSegment->linedef; - - double yscale = GetYScale(sidedef, mMiddleTexture, side_t::mid); - double cameraZ = Thread->Viewport->viewpoint.Pos.Z; - - double TextureMid; - if (yscale >= 0) - { // normal orientation - if (linedef->flags & ML_DONTPEGBOTTOM) - { // bottom of texture at bottom - TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale + mMiddleTexture->GetHeight(); - } - else - { // top of texture at top - TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale; - } - } - else - { // upside down - if (linedef->flags & ML_DONTPEGBOTTOM) - { // top of texture at bottom - TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale; - } - else - { // bottom of texture at top - TextureMid = (mFrontSector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale + mMiddleTexture->GetHeight(); - } - } - - TextureMid += GetRowOffset(linedef, sidedef, mMiddleTexture, side_t::mid); - ProjectedWallTexcoords texcoords; - texcoords.Project(Thread->Viewport.get(), mLineSegment->sidedef->TexelLength * GetXScale(sidedef, mMiddleTexture, side_t::mid), WallC.sx1, WallC.sx2, WallT); - texcoords.xoffset = GetXOffset(sidedef, mMiddleTexture, side_t::mid); - texcoords.yscale = yscale; - texcoords.texturemid = TextureMid; + texcoords.ProjectMid(Thread->Viewport.get(), mFrontSector, mLineSegment, WallC.sx1, WallC.sx2, WallT, mMiddleTexture); RenderWallPart renderWallpart(Thread); renderWallpart.Render(mFrontSector, mLineSegment, WallC, mMiddleTexture, x1, x2, walltop.ScreenY, wallbottom.ScreenY, texcoords, MAX(mFrontCeilingZ1, mFrontCeilingZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, mLight, GetLightList()); @@ -1054,124 +947,13 @@ namespace swrenderer if (!mBottomTexture) return; if (!viewactive) return; - side_t* sidedef = mLineSegment->sidedef; - line_t* linedef = mLineSegment->linedef; - - double frontlowertop = mFrontSector->GetPlaneTexZ(sector_t::ceiling); - if (mFrontSector->GetTexture(sector_t::ceiling) == skyflatnum && mBackSector->GetTexture(sector_t::ceiling) == skyflatnum) - { - // Putting sky ceilings on the front and back of a line alters the way unpegged - // positioning works. - frontlowertop = mBackSector->GetPlaneTexZ(sector_t::ceiling); - } - - double yscale = GetYScale(sidedef, mBottomTexture, side_t::bottom); - double cameraZ = Thread->Viewport->viewpoint.Pos.Z; - - double TextureMid; - if (yscale >= 0) - { // normal orientation - if (linedef->flags & ML_DONTPEGBOTTOM) - { // bottom of texture at bottom - TextureMid = (frontlowertop - cameraZ) * yscale; - } - else - { // top of texture at top - TextureMid = (mBackSector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale; - } - } - else - { // upside down - if (linedef->flags & ML_DONTPEGBOTTOM) - { // top of texture at bottom - TextureMid = (frontlowertop - cameraZ) * yscale; - } - else - { // bottom of texture at top - TextureMid = (mBackSector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale + mBottomTexture->GetHeight(); - } - } - - TextureMid += GetRowOffset(linedef, sidedef, mBottomTexture, side_t::bottom); - ProjectedWallTexcoords texcoords; - texcoords.Project(Thread->Viewport.get(), mLineSegment->sidedef->TexelLength * GetXScale(sidedef, mBottomTexture, side_t::bottom), WallC.sx1, WallC.sx2, WallT); - texcoords.xoffset = GetXOffset(sidedef, mBottomTexture, side_t::bottom); - texcoords.yscale = yscale; - texcoords.texturemid = TextureMid; + texcoords.ProjectBottom(Thread->Viewport.get(), mFrontSector, mBackSector, mLineSegment, WallC.sx1, WallC.sx2, WallT, mBottomTexture); RenderWallPart renderWallpart(Thread); renderWallpart.Render(mFrontSector, mLineSegment, WallC, mBottomTexture, x1, x2, walllower.ScreenY, wallbottom.ScreenY, texcoords, MAX(mBackFloorZ1, mBackFloorZ2), MIN(mFrontFloorZ1, mFrontFloorZ2), false, false, OPAQUE, mLight, GetLightList()); } - double SWRenderLine::GetRowOffset(line_t* linedef, side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart) - { - double yrepeat = GetYScale(sidedef, tex, texpart); - double rowoffset = sidedef->GetTextureYOffset(texpart); - if (yrepeat >= 0) - { - // check if top of texture at top: - bool top_at_top = - (texpart == side_t::top && (linedef->flags & ML_DONTPEGTOP)) || - (texpart != side_t::top && !(linedef->flags & ML_DONTPEGBOTTOM)); - - if (rowoffset < 0 && top_at_top) - { - rowoffset += tex->GetHeight(); - } - } - else - { - rowoffset = -rowoffset; - } - - if (tex->useWorldPanning(mLineSegment->GetLevel())) - { - return rowoffset * yrepeat; - } - else - { - // rowoffset is added outside the multiply so that it positions the texture - // by texels instead of world units. - return rowoffset; - } - } - - fixed_t SWRenderLine::GetXOffset(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart) - { - fixed_t TextureOffsetU = FLOAT2FIXED(sidedef->GetTextureXOffset(texpart)); - double xscale = GetXScale(sidedef, tex, texpart); - - fixed_t xoffset; - if (tex->useWorldPanning(mLineSegment->GetLevel())) - { - xoffset = xs_RoundToInt(TextureOffsetU * xscale); - } - else - { - xoffset = TextureOffsetU; - } - - if (xscale < 0) - { - xoffset = -xoffset; - } - - return xoffset; - } - - double SWRenderLine::GetXScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart) - { - double TextureScaleU = sidedef->GetTextureXScale(texpart); - return tex->GetScale().X * TextureScaleU; - } - - double SWRenderLine::GetYScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart) - { - double TextureScaleV = sidedef->GetTextureYScale(texpart); - return tex->GetScale().Y * TextureScaleV; - } - FLightNode *SWRenderLine::GetLightList() { CameraLight *cameraLight = CameraLight::Instance(); diff --git a/src/rendering/swrenderer/line/r_line.h b/src/rendering/swrenderer/line/r_line.h index c84bfa112..2944a550f 100644 --- a/src/rendering/swrenderer/line/r_line.h +++ b/src/rendering/swrenderer/line/r_line.h @@ -74,12 +74,6 @@ namespace swrenderer void RenderMiddleTexture(int x1, int x2); void RenderBottomTexture(int x1, int x2); - fixed_t GetXOffset(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart); - double GetXScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart); - double GetYScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart); - - double GetRowOffset(line_t* linedef, side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart); - FLightNode *GetLightList(); bool IsFogBoundary(sector_t *front, sector_t *back) const; diff --git a/src/rendering/swrenderer/line/r_renderdrawsegment.cpp b/src/rendering/swrenderer/line/r_renderdrawsegment.cpp index 81d5ff4c7..556e1a520 100644 --- a/src/rendering/swrenderer/line/r_renderdrawsegment.cpp +++ b/src/rendering/swrenderer/line/r_renderdrawsegment.cpp @@ -149,15 +149,16 @@ namespace swrenderer { // Texture does not wrap vertically. // find positioning - double texheight = tex->GetScaledHeightDouble(); - double texheightscale = fabs(curline->sidedef->GetTextureYScale(side_t::mid)); - if (texheightscale != 1) - { - texheight = texheight / texheightscale; - } - - bool sprflipvert = ds->texcoords.yscale < 0; - double textop = ds->texcoords.texturemid / ds->texcoords.yscale; + double texheight = tex->GetScaledHeightDouble() / fabs(curline->sidedef->GetTextureYScale(side_t::mid)); + double texturemid; + if (curline->linedef->flags & ML_DONTPEGBOTTOM) + texturemid = MAX(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor)) + texheight; + else + texturemid = MIN(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling)); + double rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid); + if (tex->useWorldPanning(curline->GetLevel())) + rowoffset /= fabs(ds->texcoords.yscale); + double textop = texturemid + rowoffset - Thread->Viewport->viewpoint.Pos.Z; // [RH] Don't bother drawing segs that are completely offscreen if (viewport->globaldclip * ds->WallC.sz1 < -textop && viewport->globaldclip * ds->WallC.sz2 < -textop) @@ -290,10 +291,6 @@ namespace swrenderer void RenderDrawSegment::Render3DFloorWall(DrawSegment *ds, int x1, int x2, F3DFloor *rover, double clipTop, double clipBottom, FSoftwareTexture *rw_pic) { - int i; - double xscale; - double yscale; - fixed_t Alpha = Scale(rover->alpha, OPAQUE, 255); if (Alpha <= 0) return; @@ -303,70 +300,23 @@ namespace swrenderer const short *mfloorclip = ds->sprbottomclip - ds->x1; const short *mceilingclip = ds->sprtopclip - ds->x1; - // find positioning - side_t *scaledside; - side_t::ETexpart scaledpart; - if (rover->flags & FF_UPPERTEXTURE) - { - scaledside = curline->sidedef; - scaledpart = side_t::top; - } - else if (rover->flags & FF_LOWERTEXTURE) - { - scaledside = curline->sidedef; - scaledpart = side_t::bottom; - } - else - { - scaledside = rover->master->sidedef[0]; - scaledpart = side_t::mid; - } - xscale = rw_pic->GetScale().X * scaledside->GetTextureXScale(scaledpart); - yscale = rw_pic->GetScale().Y * scaledside->GetTextureYScale(scaledpart); - - double rowoffset = curline->sidedef->GetTextureYOffset(side_t::mid) + rover->master->sidedef[0]->GetTextureYOffset(side_t::mid); - double planez = rover->model->GetPlaneTexZ(sector_t::ceiling); - fixed_t rw_offset = FLOAT2FIXED(curline->sidedef->GetTextureXOffset(side_t::mid) + rover->master->sidedef[0]->GetTextureXOffset(side_t::mid)); - if (rowoffset < 0) - { - rowoffset += rw_pic->GetHeight(); - } - double texturemid = (planez - Thread->Viewport->viewpoint.Pos.Z) * yscale; - if (rw_pic->useWorldPanning(curline->GetLevel())) - { - // rowoffset is added before the multiply so that the masked texture will - // still be positioned in world units rather than texels. - - texturemid = texturemid + rowoffset * yscale; - rw_offset = xs_RoundToInt(rw_offset * xscale); - } - else - { - // rowoffset is added outside the multiply so that it positions the texture - // by texels instead of world units. - texturemid += rowoffset; - } - Clip3DFloors *clip3d = Thread->Clip3D.get(); wallupper.Project(Thread->Viewport.get(), clipTop - Thread->Viewport->viewpoint.Pos.Z, &ds->WallC); walllower.Project(Thread->Viewport.get(), clipBottom - Thread->Viewport->viewpoint.Pos.Z, &ds->WallC); - for (i = x1; i < x2; i++) + for (int i = x1; i < x2; i++) { if (wallupper.ScreenY[i] < mceilingclip[i]) wallupper.ScreenY[i] = mceilingclip[i]; } - for (i = x1; i < x2; i++) + for (int i = x1; i < x2; i++) { if (walllower.ScreenY[i] > mfloorclip[i]) walllower.ScreenY[i] = mfloorclip[i]; } ProjectedWallTexcoords walltexcoords; - walltexcoords.Project(Thread->Viewport.get(), curline->sidedef->TexelLength*xscale, ds->WallC.sx1, ds->WallC.sx2, ds->tmapvals); - walltexcoords.texturemid = texturemid; - walltexcoords.yscale = yscale; - walltexcoords.xoffset = rw_offset; + walltexcoords.Project3DFloor(Thread->Viewport.get(), rover, curline, ds->WallC.sx1, ds->WallC.sx2, ds->tmapvals, rw_pic); double top, bot; GetMaskedWallTopBottom(ds, top, bot); diff --git a/src/rendering/swrenderer/line/r_wallsetup.cpp b/src/rendering/swrenderer/line/r_wallsetup.cpp index 50c7be7c3..1fa28c7aa 100644 --- a/src/rendering/swrenderer/line/r_wallsetup.cpp +++ b/src/rendering/swrenderer/line/r_wallsetup.cpp @@ -221,6 +221,217 @@ namespace swrenderer ///////////////////////////////////////////////////////////////////////// + void ProjectedWallTexcoords::ProjectTop(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic) + { + side_t* sidedef = lineseg->sidedef; + line_t* linedef = lineseg->linedef; + + yscale = GetYScale(sidedef, pic, side_t::top); + double cameraZ = viewport->viewpoint.Pos.Z; + + if (yscale >= 0) + { // normal orientation + if (linedef->flags & ML_DONTPEGTOP) + { // top of texture at top + texturemid = (frontsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale; + } + else + { // bottom of texture at bottom + texturemid = (backsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale + pic->GetHeight(); + } + } + else + { // upside down + if (linedef->flags & ML_DONTPEGTOP) + { // bottom of texture at top + texturemid = (frontsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale + pic->GetHeight(); + } + else + { // top of texture at bottom + texturemid = (backsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale; + } + } + + texturemid += GetRowOffset(lineseg, pic, side_t::top); + + Project(viewport, sidedef->TexelLength * GetXScale(sidedef, pic, side_t::top), x1, x2, WallT); + xoffset = GetXOffset(lineseg, pic, side_t::top); + } + + void ProjectedWallTexcoords::ProjectMid(RenderViewport* viewport, sector_t* frontsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic) + { + side_t* sidedef = lineseg->sidedef; + line_t* linedef = lineseg->linedef; + + yscale = GetYScale(sidedef, pic, side_t::mid); + double cameraZ = viewport->viewpoint.Pos.Z; + + if (yscale >= 0) + { // normal orientation + if (linedef->flags & ML_DONTPEGBOTTOM) + { // bottom of texture at bottom + texturemid = (frontsector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale + pic->GetHeight(); + } + else + { // top of texture at top + texturemid = (frontsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale; + } + } + else + { // upside down + if (linedef->flags & ML_DONTPEGBOTTOM) + { // top of texture at bottom + texturemid = (frontsector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale; + } + else + { // bottom of texture at top + texturemid = (frontsector->GetPlaneTexZ(sector_t::ceiling) - cameraZ) * yscale + pic->GetHeight(); + } + } + + texturemid += GetRowOffset(lineseg, pic, side_t::mid); + + Project(viewport, sidedef->TexelLength * GetXScale(sidedef, pic, side_t::mid), x1, x2, WallT); + xoffset = GetXOffset(lineseg, pic, side_t::mid); + } + + void ProjectedWallTexcoords::ProjectBottom(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic) + { + side_t* sidedef = lineseg->sidedef; + line_t* linedef = lineseg->linedef; + + double frontlowertop = frontsector->GetPlaneTexZ(sector_t::ceiling); + if (frontsector->GetTexture(sector_t::ceiling) == skyflatnum && backsector->GetTexture(sector_t::ceiling) == skyflatnum) + { + // Putting sky ceilings on the front and back of a line alters the way unpegged + // positioning works. + frontlowertop = backsector->GetPlaneTexZ(sector_t::ceiling); + } + + yscale = GetYScale(sidedef, pic, side_t::bottom); + double cameraZ = viewport->viewpoint.Pos.Z; + + if (yscale >= 0) + { // normal orientation + if (linedef->flags & ML_DONTPEGBOTTOM) + { // bottom of texture at bottom + texturemid = (frontlowertop - cameraZ) * yscale; + } + else + { // top of texture at top + texturemid = (backsector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale; + } + } + else + { // upside down + if (linedef->flags & ML_DONTPEGBOTTOM) + { // top of texture at bottom + texturemid = (frontlowertop - cameraZ) * yscale; + } + else + { // bottom of texture at top + texturemid = (backsector->GetPlaneTexZ(sector_t::floor) - cameraZ) * yscale + pic->GetHeight(); + } + } + + texturemid += GetRowOffset(lineseg, pic, side_t::bottom); + + Project(viewport, sidedef->TexelLength * GetXScale(sidedef, pic, side_t::bottom), x1, x2, WallT); + xoffset = GetXOffset(lineseg, pic, side_t::bottom); + } + + void ProjectedWallTexcoords::ProjectTranslucent(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic) + { + line_t* linedef = lineseg->linedef; + side_t* sidedef = lineseg->sidedef; + + yscale = GetYScale(sidedef, pic, side_t::mid); + double cameraZ = viewport->viewpoint.Pos.Z; + + double texZFloor = MAX(frontsector->GetPlaneTexZ(sector_t::floor), backsector->GetPlaneTexZ(sector_t::floor)); + double texZCeiling = MIN(frontsector->GetPlaneTexZ(sector_t::ceiling), backsector->GetPlaneTexZ(sector_t::ceiling)); + + if (yscale >= 0) + { // normal orientation + if (linedef->flags & ML_DONTPEGBOTTOM) + { // bottom of texture at bottom + texturemid = (texZFloor - cameraZ) * yscale + pic->GetHeight(); + } + else + { // top of texture at top + texturemid = (texZCeiling - cameraZ) * yscale; + } + } + else + { // upside down + if (linedef->flags & ML_DONTPEGBOTTOM) + { // top of texture at bottom + texturemid = (texZFloor - cameraZ) * yscale; + } + else + { // bottom of texture at top + texturemid = (texZCeiling - cameraZ) * yscale + pic->GetHeight(); + } + } + + texturemid += GetRowOffset(lineseg, pic, side_t::mid); + + Project(viewport, sidedef->TexelLength * GetXScale(sidedef, pic, side_t::mid), x1, x2, WallT); + xoffset = GetXOffset(lineseg, pic, side_t::mid); + } + + void ProjectedWallTexcoords::Project3DFloor(RenderViewport* viewport, F3DFloor* rover, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic) + { + // find positioning + side_t* scaledside; + side_t::ETexpart scaledpart; + if (rover->flags & FF_UPPERTEXTURE) + { + scaledside = lineseg->sidedef; + scaledpart = side_t::top; + } + else if (rover->flags & FF_LOWERTEXTURE) + { + scaledside = lineseg->sidedef; + scaledpart = side_t::bottom; + } + else + { + scaledside = rover->master->sidedef[0]; + scaledpart = side_t::mid; + } + + double xscale = pic->GetScale().X * scaledside->GetTextureXScale(scaledpart); + yscale = pic->GetScale().Y * scaledside->GetTextureYScale(scaledpart); + + double rowoffset = lineseg->sidedef->GetTextureYOffset(side_t::mid) + rover->master->sidedef[0]->GetTextureYOffset(side_t::mid); + double planez = rover->model->GetPlaneTexZ(sector_t::ceiling); + + xoffset = FLOAT2FIXED(lineseg->sidedef->GetTextureXOffset(side_t::mid) + rover->master->sidedef[0]->GetTextureXOffset(side_t::mid)); + if (rowoffset < 0) + { + rowoffset += pic->GetHeight(); + } + + texturemid = (planez - viewport->viewpoint.Pos.Z) * yscale; + if (pic->useWorldPanning(lineseg->GetLevel())) + { + // rowoffset is added before the multiply so that the masked texture will + // still be positioned in world units rather than texels. + + texturemid = texturemid + rowoffset * yscale; + xoffset = xs_RoundToInt(xoffset * xscale); + } + else + { + // rowoffset is added outside the multiply so that it positions the texture + // by texels instead of world units. + texturemid += rowoffset; + } + + Project(viewport, lineseg->sidedef->TexelLength * xscale, x1, x2, WallT); + } + void ProjectedWallTexcoords::Project(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT, bool flipx) { this->walxrepeat = walxrepeat; @@ -273,6 +484,74 @@ namespace swrenderer return value + xoffset; } + double ProjectedWallTexcoords::GetRowOffset(seg_t* lineseg, FSoftwareTexture* tex, side_t::ETexpart texpart) + { + double yrepeat = GetYScale(lineseg->sidedef, tex, texpart); + double rowoffset = lineseg->sidedef->GetTextureYOffset(texpart); + if (yrepeat >= 0) + { + // check if top of texture at top: + bool top_at_top = + (texpart == side_t::top && (lineseg->linedef->flags & ML_DONTPEGTOP)) || + (texpart != side_t::top && !(lineseg->linedef->flags & ML_DONTPEGBOTTOM)); + + if (rowoffset < 0 && top_at_top) + { + rowoffset += tex->GetHeight(); + } + } + else + { + rowoffset = -rowoffset; + } + + if (tex->useWorldPanning(lineseg->GetLevel())) + { + return rowoffset * yrepeat; + } + else + { + // rowoffset is added outside the multiply so that it positions the texture + // by texels instead of world units. + return rowoffset; + } + } + + fixed_t ProjectedWallTexcoords::GetXOffset(seg_t* lineseg, FSoftwareTexture* tex, side_t::ETexpart texpart) + { + fixed_t TextureOffsetU = FLOAT2FIXED(lineseg->sidedef->GetTextureXOffset(texpart)); + double xscale = GetXScale(lineseg->sidedef, tex, texpart); + + fixed_t xoffset; + if (tex->useWorldPanning(lineseg->GetLevel())) + { + xoffset = xs_RoundToInt(TextureOffsetU * xscale); + } + else + { + xoffset = TextureOffsetU; + } + + if (xscale < 0) + { + xoffset = -xoffset; + } + + return xoffset; + } + + double ProjectedWallTexcoords::GetXScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart) + { + double TextureScaleU = sidedef->GetTextureXScale(texpart); + return tex->GetScale().X * TextureScaleU; + } + + double ProjectedWallTexcoords::GetYScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart) + { + double TextureScaleV = sidedef->GetTextureYScale(texpart); + return tex->GetScale().Y * TextureScaleV; + } + ///////////////////////////////////////////////////////////////////////// void ProjectedWallLight::SetLightLeft(RenderThread *thread, const FWallCoords &wallc) diff --git a/src/rendering/swrenderer/line/r_wallsetup.h b/src/rendering/swrenderer/line/r_wallsetup.h index 3f43c137a..1b07d9067 100644 --- a/src/rendering/swrenderer/line/r_wallsetup.h +++ b/src/rendering/swrenderer/line/r_wallsetup.h @@ -61,6 +61,12 @@ namespace swrenderer class ProjectedWallTexcoords { public: + void ProjectTop(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic); + void ProjectMid(RenderViewport* viewport, sector_t* frontsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic); + void ProjectBottom(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic); + void ProjectTranslucent(RenderViewport* viewport, sector_t* frontsector, sector_t* backsector, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic); + void Project3DFloor(RenderViewport* viewport, F3DFloor* rover, seg_t* lineseg, int x1, int x2, const FWallTmapVals& WallT, FSoftwareTexture* pic); + void Project(RenderViewport *viewport, double walxrepeat, int x1, int x2, const FWallTmapVals &WallT, bool flipx = false); float VStep(int x) const; @@ -73,6 +79,11 @@ namespace swrenderer explicit operator bool() const { return valid; } private: + static fixed_t GetXOffset(seg_t* lineseg, FSoftwareTexture* tex, side_t::ETexpart texpart); + static double GetRowOffset(seg_t* lineseg, FSoftwareTexture* tex, side_t::ETexpart texpart); + static double GetXScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart); + static double GetYScale(side_t* sidedef, FSoftwareTexture* tex, side_t::ETexpart texpart); + bool valid = false; double CenterX; double WallTMapScale2;