From 09730bff73a241dc388e1d60ba1a5803b941de1b Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 29 Apr 2016 20:35:37 -0500 Subject: [PATCH 1/8] Fix incorrect texture mapping vectors for slopes --- src/r_plane.cpp | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 2fb90fa6f..d749319e3 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -1624,7 +1624,7 @@ void R_DrawTiltedPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t double lxscale, lyscale; double xscale, yscale; FVector3 p, m, n; - DAngle ang; + double ang, planeang, cosine, sine; double zeroheight; if (alpha <= 0) @@ -1640,37 +1640,44 @@ void R_DrawTiltedPlane (visplane_t *pl, double _xscale, double _yscale, fixed_t pviewx = xs_ToFixed(32 - ds_xbits, pl->xform.xOffs * pl->xform.xScale); pviewy = xs_ToFixed(32 - ds_ybits, pl->xform.yOffs * pl->xform.yScale); + planeang = (pl->xform.Angle + pl->xform.baseAngle).Radians(); // p is the texture origin in view space // Don't add in the offsets at this stage, because doing so can result in // errors if the flat is rotated. - ang = DAngle(270.) - ViewAngle; - p[0] = ViewPos.X * ang.Cos() - ViewPos.Y * ang.Sin(); - p[2] = ViewPos.X * ang.Sin() + ViewPos.Y * ang.Cos(); + ang = M_PI*3/2 - ViewAngle.Radians(); + cosine = cos(ang), sine = sin(ang); + p[0] = ViewPos.X * cosine - ViewPos.Y * sine; + p[2] = ViewPos.X * sine + ViewPos.Y * cosine; p[1] = pl->height.ZatPoint(0.0, 0.0) - ViewPos.Z; // m is the v direction vector in view space - ang = DAngle(180.) - ViewAngle; - m[0] = yscale * cos(ang.Radians()); - m[2] = yscale * sin(ang.Radians()); + ang = ang - M_PI / 2 - planeang; + cosine = cos(ang), sine = sin(ang); + m[0] = yscale * cosine; + m[2] = yscale * sine; // m[1] = pl->height.ZatPointF (0, iyscale) - pl->height.ZatPointF (0,0)); // VectorScale2 (m, 64.f/VectorLength(m)); // n is the u direction vector in view space - ang += 90; - n[0] = -xscale * cos(ang.Radians()); - n[2] = -xscale * sin(ang.Radians()); +#if 0 + //let's use the sin/cosine we already know instead of computing new ones + ang += M_PI/2 + n[0] = -xscale * cos(ang); + n[2] = -xscale * sin(ang); +#else + n[0] = xscale * sine; + n[2] = -xscale * cosine; +#endif // n[1] = pl->height.ZatPointF (ixscale, 0) - pl->height.ZatPointF (0,0)); // VectorScale2 (n, 64.f/VectorLength(n)); // This code keeps the texture coordinates constant across the x,y plane no matter // how much you slope the surface. Use the commented-out code above instead to keep // the textures a constant size across the surface's plane instead. - ang = pl->xform.Angle + pl->xform.baseAngle; - double cosine = cos(ang.Radians()), sine = sin(ang.Radians()); + cosine = cos(planeang), sine = sin(planeang); m[1] = pl->height.ZatPoint(ViewPos.X + yscale * sine, ViewPos.Y + yscale * cosine) - zeroheight; - ang += 90; - n[1] = pl->height.ZatPoint(ViewPos.X + xscale * sine, ViewPos.Y + xscale * cosine) - zeroheight; + n[1] = pl->height.ZatPoint(ViewPos.X - xscale * cosine, ViewPos.Y + xscale * sine) - zeroheight; plane_su = p ^ m; plane_sv = p ^ n; From a95c6b9644b14f7d3e1cbd4a22b36dd02f5f2b01 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Fri, 29 Apr 2016 21:54:29 -0500 Subject: [PATCH 2/8] Draw upper/lower textures on two-sided portal lines --- src/r_bsp.cpp | 12 ++++++++---- src/r_segs.cpp | 19 ++++++++++++++----- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/r_bsp.cpp b/src/r_bsp.cpp index 88c907e2b..2660fce6e 100644 --- a/src/r_bsp.cpp +++ b/src/r_bsp.cpp @@ -575,7 +575,6 @@ void R_AddLine (seg_t *line) return; vertex_t *v1, *v2; - v1 = line->linedef->v1; v2 = line->linedef->v2; @@ -605,7 +604,7 @@ void R_AddLine (seg_t *line) rw_havehigh = rw_havelow = false; // Single sided line? - if (backsector == NULL || (line->linedef->isVisualPortal() && line->sidedef == line->linedef->sidedef[0])) + if (backsector == NULL) { solid = true; } @@ -636,9 +635,14 @@ void R_AddLine (seg_t *line) WallMost (walllower, backsector->floorplane, &WallC); } + // Portal + if (line->linedef->isVisualPortal() && line->sidedef == line->linedef->sidedef[0]) + { + solid = true; + } // Closed door. - if ((rw_backcz1 <= rw_frontfz1 && rw_backcz2 <= rw_frontfz2) || - (rw_backfz1 >= rw_frontcz1 && rw_backfz2 >= rw_frontcz2)) + else if ((rw_backcz1 <= rw_frontfz1 && rw_backcz2 <= rw_frontfz2) || + (rw_backfz1 >= rw_frontcz1 && rw_backfz2 >= rw_frontcz2)) { solid = true; } diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 4c91a1314..69d517b17 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -2016,9 +2016,9 @@ void R_NewWall (bool needlights) midtexture = toptexture = bottomtexture = 0; if (sidedef == linedef->sidedef[0] && - (linedef->isVisualPortal() || (linedef->special == Line_Mirror && r_drawmirrors))) // [ZZ] compatibility with r_drawmirrors cvar that existed way before portals + (linedef->special == Line_Mirror && r_drawmirrors)) // [ZZ] compatibility with r_drawmirrors cvar that existed way before portals { - markfloor = markceiling = true; // act like an one-sided wall here (todo: check how does this work with transparency) + markfloor = markceiling = true; // act like a one-sided wall here (todo: check how does this work with transparency) rw_markportal = true; } else if (backsector == NULL) @@ -2027,7 +2027,11 @@ void R_NewWall (bool needlights) // a single sided line is terminal, so it must mark ends markfloor = markceiling = true; // [RH] Horizon lines do not need to be textured - if (linedef->special != Line_Horizon) + if (linedef->isVisualPortal()) + { + rw_markportal = true; + } + else if (linedef->special != Line_Horizon) { midtexture = TexMan(sidedef->GetTexture(side_t::mid), true); rw_offset_mid = FLOAT2FIXED(sidedef->GetTextureXOffset(side_t::mid)); @@ -2102,8 +2106,12 @@ void R_NewWall (bool needlights) rw_frontlowertop = backsector->GetPlaneTexZ(sector_t::ceiling); } - if ((rw_backcz1 <= rw_frontfz1 && rw_backcz2 <= rw_frontfz2) || - (rw_backfz1 >= rw_frontcz1 && rw_backfz2 >= rw_frontcz2)) + if (linedef->isVisualPortal()) + { + markceiling = markfloor = true; + } + else if ((rw_backcz1 <= rw_frontfz1 && rw_backcz2 <= rw_frontfz2) || + (rw_backfz1 >= rw_frontcz1 && rw_backfz2 >= rw_frontcz2)) { // closed door markceiling = markfloor = true; @@ -2260,6 +2268,7 @@ void R_NewWall (bool needlights) rw_bottomtexturemid += rowoffset; } } + rw_markportal = linedef->isVisualPortal(); } // if a floor / ceiling plane is on the wrong side of the view plane, From c3759646e7f1d78fe1389a8e9e48f6cabc60e0d9 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Apr 2016 12:36:55 +0200 Subject: [PATCH 3/8] - merged FWarpTexture and FWarp2Texture, making the choice of effect a parameter of the WarpBuffer function. Ideally the warping shouldn't be a property of the texture class itself but an effect processor that can get added to a texture. Unfortunately the current setup will not allow this, requiring some significant refactoring of texture access first. --- src/textures/animations.cpp | 6 +-- src/textures/textures.h | 12 +---- src/textures/warpbuffer.h | 100 ++++++++++++++++++----------------- src/textures/warptexture.cpp | 32 ++--------- 4 files changed, 57 insertions(+), 93 deletions(-) diff --git a/src/textures/animations.cpp b/src/textures/animations.cpp index a9a2433a3..76ad48443 100644 --- a/src/textures/animations.cpp +++ b/src/textures/animations.cpp @@ -219,7 +219,7 @@ void FTextureManager::InitAnimated (void) // SMMU-style swirly hack? Don't apply on already-warping texture if (animspeed > 65535 && tex1 != NULL && !tex1->bWarped) { - FTexture *warper = new FWarp2Texture (tex1); + FTexture *warper = new FWarpTexture (tex1, 2); ReplaceTexture (pic1, warper, false); } // These tests were not really relevant for swirling textures, or even potentially @@ -617,9 +617,7 @@ void FTextureManager::ParseWarp(FScanner &sc) // don't warp a texture more than once if (!warper->bWarped) { - if (type2) warper = new FWarp2Texture (warper); - else warper = new FWarpTexture (warper); - + warper = new FWarpTexture (warper, type2? 2:1); ReplaceTexture (picnum, warper, false); } diff --git a/src/textures/textures.h b/src/textures/textures.h index 23b66972d..55ad583ff 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -469,7 +469,7 @@ public: class FWarpTexture : public FTexture { public: - FWarpTexture (FTexture *source); + FWarpTexture (FTexture *source, int warptype); ~FWarpTexture (); virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0, FCopyInfo *inf = NULL); @@ -496,16 +496,6 @@ protected: void SetupMultipliers (int width, int height); // [mxd] }; -// [GRB] Eternity-like warping -class FWarp2Texture : public FWarpTexture -{ -public: - FWarp2Texture (FTexture *source); - -protected: - void MakeTexture (DWORD time); -}; - // A texture that can be drawn to. class DSimpleCanvas; class AActor; diff --git a/src/textures/warpbuffer.h b/src/textures/warpbuffer.h index 0110742f1..2516a838a 100644 --- a/src/textures/warpbuffer.h +++ b/src/textures/warpbuffer.h @@ -1,61 +1,63 @@ template -void WarpBufferType1(TYPE *Pixels, const TYPE *source, int width, int height, int xmul, int ymul, unsigned time, float Speed) -{ - TYPE *buffer = (TYPE *)alloca(sizeof(TYPE) * MAX(width, height)); - int ymask = height - 1; - int x, y; - - // [mxd] Rewrote to fix animation for NPo2 textures - unsigned timebase = unsigned(time * Speed * 32 / 28); - for (y = height - 1; y >= 0; y--) - { - int xf = (TexMan.sintable[((timebase + y*ymul) >> 2)&TexMan.SINMASK] >> 11) % width; - if (xf < 0) xf += width; - int xt = xf; - const TYPE *sourcep = source + y; - TYPE *dest = Pixels + y; - for (xt = width; xt; xt--, xf = (xf + 1) % width, dest += height) - *dest = sourcep[xf + ymask * xf]; - } - timebase = unsigned(time * Speed * 23 / 28); - for (x = width - 1; x >= 0; x--) - { - int yf = (TexMan.sintable[((time + (x + 17)*xmul) >> 2)&TexMan.SINMASK] >> 11) % height; - if (yf < 0) yf += height; - int yt = yf; - const TYPE *sourcep = Pixels + (x + ymask * x); - TYPE *dest = buffer; - for (yt = height; yt; yt--, yf = (yf + 1) % height) - *dest++ = sourcep[yf]; - memcpy(Pixels + (x + ymask*x), buffer, height * sizeof(TYPE)); - } -} - - -template -void WarpBufferType2(TYPE *Pixels, const TYPE *source, int width, int height, int xmul, int ymul, unsigned time, float Speed) +void WarpBuffer(TYPE *Pixels, const TYPE *source, int width, int height, int xmul, int ymul, unsigned time, float Speed, int warptype) { int ymask = height - 1; int x, y; - unsigned timebase = unsigned(time * Speed * 40 / 28); - // [mxd] Rewrote to fix animation for NPo2 textures - for (x = 0; x < width; x++) + if (warptype == 1) { - TYPE *dest = Pixels + (x + ymask * x); - for (y = 0; y < height; y++) + TYPE *buffer = (TYPE *)alloca(sizeof(TYPE) * MAX(width, height)); + // [mxd] Rewrote to fix animation for NPo2 textures + unsigned timebase = unsigned(time * Speed * 32 / 28); + for (y = height - 1; y >= 0; y--) { - int xt = (x + 128 - + ((TexMan.sintable[((y*ymul + timebase * 5 + 900) >> 2) & TexMan.SINMASK]) >> 13) - + ((TexMan.sintable[((x*xmul + timebase * 4 + 300) >> 2) & TexMan.SINMASK]) >> 13)) % width; - - int yt = (y + 128 - + ((TexMan.sintable[((y*ymul + timebase * 3 + 700) >> 2) & TexMan.SINMASK]) >> 13) - + ((TexMan.sintable[((x*xmul + timebase * 4 + 1200) >> 2) & TexMan.SINMASK]) >> 13)) % height; - - *dest++ = source[(xt + ymask * xt) + yt]; + int xf = (TexMan.sintable[((timebase + y*ymul) >> 2)&TexMan.SINMASK] >> 11) % width; + if (xf < 0) xf += width; + int xt = xf; + const TYPE *sourcep = source + y; + TYPE *dest = Pixels + y; + for (xt = width; xt; xt--, xf = (xf + 1) % width, dest += height) + *dest = sourcep[xf + ymask * xf]; + } + timebase = unsigned(time * Speed * 23 / 28); + for (x = width - 1; x >= 0; x--) + { + int yf = (TexMan.sintable[((time + (x + 17)*xmul) >> 2)&TexMan.SINMASK] >> 11) % height; + if (yf < 0) yf += height; + int yt = yf; + const TYPE *sourcep = Pixels + (x + ymask * x); + TYPE *dest = buffer; + for (yt = height; yt; yt--, yf = (yf + 1) % height) + *dest++ = sourcep[yf]; + memcpy(Pixels + (x + ymask*x), buffer, height * sizeof(TYPE)); } } + else if (warptype == 2) + { + unsigned timebase = unsigned(time * Speed * 40 / 28); + // [mxd] Rewrote to fix animation for NPo2 textures + for (x = 0; x < width; x++) + { + TYPE *dest = Pixels + (x + ymask * x); + for (y = 0; y < height; y++) + { + int xt = (x + 128 + + ((TexMan.sintable[((y*ymul + timebase * 5 + 900) >> 2) & TexMan.SINMASK]) >> 13) + + ((TexMan.sintable[((x*xmul + timebase * 4 + 300) >> 2) & TexMan.SINMASK]) >> 13)) % width; + + int yt = (y + 128 + + ((TexMan.sintable[((y*ymul + timebase * 3 + 700) >> 2) & TexMan.SINMASK]) >> 13) + + ((TexMan.sintable[((x*xmul + timebase * 4 + 1200) >> 2) & TexMan.SINMASK]) >> 13)) % height; + + *dest++ = source[(xt + ymask * xt) + yt]; + } + } + } + else + { + // should never happen, just in case... + memcpy(Pixels, source, width*height * sizeof(TYPE)); + } } diff --git a/src/textures/warptexture.cpp b/src/textures/warptexture.cpp index 54d697c22..2d9663dbc 100644 --- a/src/textures/warptexture.cpp +++ b/src/textures/warptexture.cpp @@ -41,12 +41,12 @@ #include "warpbuffer.h" -FWarpTexture::FWarpTexture (FTexture *source) +FWarpTexture::FWarpTexture (FTexture *source, int warptype) : GenTime (0), SourcePic (source), Pixels (0), Spans (0), Speed (1.f) { CopyInfo(source); SetupMultipliers(128, 128); // [mxd] - bWarped = 1; + bWarped = warptype; } FWarpTexture::~FWarpTexture () @@ -137,7 +137,7 @@ void FWarpTexture::MakeTexture(DWORD time) } GenTime = time; - WarpBufferType1(Pixels, otherpix, Width, Height, WidthOffsetMultiplier, HeightOffsetMultiplier, time, Speed); + WarpBuffer(Pixels, otherpix, Width, Height, WidthOffsetMultiplier, HeightOffsetMultiplier, time, Speed, bWarped); } // [mxd] Non power of 2 textures need different offset multipliers, otherwise warp animation won't sync across texture @@ -162,32 +162,6 @@ int FWarpTexture::NextPo2 (int v) return ++v; } -// [GRB] Eternity-like warping -FWarp2Texture::FWarp2Texture (FTexture *source) -: FWarpTexture (source) -{ - SetupMultipliers(256, 128); // [mxd] - bWarped = 2; -} - -void FWarp2Texture::MakeTexture (DWORD time) -{ - const BYTE *otherpix = SourcePic->GetPixels (); - - if (Pixels == NULL) - { - Pixels = new BYTE[Width * Height]; - } - if (Spans != NULL) - { - FreeSpans (Spans); - Spans = NULL; - } - - GenTime = time; - WarpBufferType2(Pixels, otherpix, Width, Height, WidthOffsetMultiplier, HeightOffsetMultiplier, time, Speed); -} - //========================================================================== // // FMultiPatchTexture :: TexPart :: TexPart From 2161ad2c4b74887d5b9c686c4f6cb1cf6f4ba903 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Apr 2016 12:48:51 +0200 Subject: [PATCH 4/8] - fixed: P_GetMapColorForKey did not check for keys that worked as an alias defined through their species. --- src/g_shared/a_keys.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_shared/a_keys.cpp b/src/g_shared/a_keys.cpp index 9e146b942..1164135bc 100644 --- a/src/g_shared/a_keys.cpp +++ b/src/g_shared/a_keys.cpp @@ -22,7 +22,7 @@ struct OneKey if (owner->IsKindOf(RUNTIME_CLASS(AKey))) { // P_GetMapColorForKey() checks the key directly - return owner->IsA(key); + return owner->IsA(key) || owner->GetSpecies() == key->TypeName; } else { From 86b647ed41f1ad0095b48142a5ae3c01a29d7f1f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Apr 2016 13:03:08 +0200 Subject: [PATCH 5/8] - added map name display to IDMYPOS. --- src/g_shared/shared_hud.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index 36ffdd5b5..4bfe85271 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -839,18 +839,26 @@ static void DrawCoordinates(player_t * CPlayer) int xpos = vwidth - SmallFont->StringWidth("X: -00000")-6; int ypos = 18; + screen->DrawText(SmallFont, hudcolor_titl, vwidth - 6 - SmallFont->StringWidth(level.MapName), ypos, level.MapName, + DTA_KeepRatio, true, + DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); + + screen->DrawText(SmallFont, hudcolor_titl, vwidth - 6 - SmallFont->StringWidth(level.LevelName), ypos + h, level.LevelName, + DTA_KeepRatio, true, + DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); + mysnprintf(coordstr, countof(coordstr), "X: %d", int(pos.X)); - screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos, coordstr, + screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+2*h, coordstr, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); mysnprintf(coordstr, countof(coordstr), "Y: %d", int(pos.Y)); - screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+h, coordstr, + screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+3*h, coordstr, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); mysnprintf(coordstr, countof(coordstr), "Z: %d", int(pos.Z)); - screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+2*h, coordstr, + screen->DrawText(SmallFont, hudcolor_xyco, xpos, ypos+4*h, coordstr, DTA_KeepRatio, true, DTA_VirtualWidth, vwidth, DTA_VirtualHeight, vheight, TAG_DONE); } From f387199442d580fe5da4f2fff94752679692aaec Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 30 Apr 2016 14:33:15 +0200 Subject: [PATCH 6/8] - extended the voxeldef parser to allow negative numbers where appropriate. --- src/r_data/voxels.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/r_data/voxels.cpp b/src/r_data/voxels.cpp index 8ca6d4f5f..7c7876243 100644 --- a/src/r_data/voxels.cpp +++ b/src/r_data/voxels.cpp @@ -501,25 +501,33 @@ static void VOX_ReadOptions(FScanner &sc, VoxelOptions &opts) } else if (sc.Compare("spin")) { + int mul = 1; sc.MustGetToken('='); + if (sc.CheckToken('-')) mul = -1; sc.MustGetToken(TK_IntConst); - opts.DroppedSpin = opts.PlacedSpin = sc.Number; + opts.DroppedSpin = opts.PlacedSpin = sc.Number*mul; } else if (sc.Compare("placedspin")) { + int mul = 1; sc.MustGetToken('='); + if (sc.CheckToken('-')) mul = -1; sc.MustGetToken(TK_IntConst); - opts.PlacedSpin = sc.Number; + opts.PlacedSpin = sc.Number*mul; } else if (sc.Compare("droppedspin")) { + int mul = 1; sc.MustGetToken('='); + if (sc.CheckToken('-')) mul = -1; sc.MustGetToken(TK_IntConst); - opts.DroppedSpin = sc.Number; + opts.DroppedSpin = sc.Number*mul; } else if (sc.Compare("angleoffset")) { + int mul = 1; sc.MustGetToken('='); + if (sc.CheckToken('-')) mul = -1; sc.MustGetAnyToken(); if (sc.TokenType == TK_IntConst) { @@ -529,7 +537,7 @@ static void VOX_ReadOptions(FScanner &sc, VoxelOptions &opts) { sc.TokenMustBe(TK_FloatConst); } - opts.AngleOffset = sc.Float + 90.; + opts.AngleOffset = mul * sc.Float + 90.; } else if (sc.Compare("overridepalette")) { From 265783e1f602824e36ba184965136e4b6cfdaec9 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 30 Apr 2016 21:28:41 -0500 Subject: [PATCH 7/8] Use doubles for intermediates in the nodebuilder's FindMapBounds() --- src/nodebuild_utility.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/nodebuild_utility.cpp b/src/nodebuild_utility.cpp index dcf5b7036..f25d747db 100644 --- a/src/nodebuild_utility.cpp +++ b/src/nodebuild_utility.cpp @@ -609,25 +609,25 @@ void FNodeBuilder::AddSegToBBox (fixed_t bbox[4], const FPrivSeg *seg) if (v2->y > bbox[BOXTOP]) bbox[BOXTOP] = v2->y; } -void FNodeBuilder::FLevel::FindMapBounds () +void FNodeBuilder::FLevel::FindMapBounds() { - fixed_t minx, maxx, miny, maxy; + double minx, maxx, miny, maxy; - minx = maxx = Vertices[0].fixX(); - miny = maxy = Vertices[0].fixY(); + minx = maxx = Vertices[0].fX(); + miny = maxy = Vertices[0].fY(); for (int i = 1; i < NumVertices; ++i) { - if (Vertices[i].fixX() < minx) minx = Vertices[i].fixX(); - else if (Vertices[i].fixX() > maxx) maxx = Vertices[i].fixX(); - if (Vertices[i].fixY() < miny) miny = Vertices[i].fixY(); - else if (Vertices[i].fixY() > maxy) maxy = Vertices[i].fixY(); + if (Vertices[i].fX() < minx) minx = Vertices[i].fX(); + else if (Vertices[i].fX() > maxx) maxx = Vertices[i].fX(); + if (Vertices[i].fY() < miny) miny = Vertices[i].fY(); + else if (Vertices[i].fY() > maxy) maxy = Vertices[i].fY(); } - MinX = minx; - MinY = miny; - MaxX = maxx; - MaxY = maxy; + MinX = FLOAT2FIXED(minx); + MinY = FLOAT2FIXED(miny); + MaxX = FLOAT2FIXED(maxx); + MaxY = FLOAT2FIXED(maxy); } FNodeBuilder::IVertexMap::~IVertexMap() From 7d03ed4dc76a9fa71f5ab63a1b48b6e7a30ded0b Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 30 Apr 2016 22:37:02 -0500 Subject: [PATCH 8/8] Use floating point node bounding boxes --- src/nodebuild.cpp | 12 ++++++------ src/nodebuild_extract.cpp | 14 ++++++++++++++ src/p_glnodes.cpp | 6 +++--- src/p_setup.cpp | 4 ++-- src/po_man.cpp | 14 +++++++------- src/r_bsp.cpp | 18 +++++++++--------- src/r_defs.h | 6 +++++- 7 files changed, 46 insertions(+), 28 deletions(-) diff --git a/src/nodebuild.cpp b/src/nodebuild.cpp index d1a8737ec..2d81d2ab2 100644 --- a/src/nodebuild.cpp +++ b/src/nodebuild.cpp @@ -156,12 +156,12 @@ int FNodeBuilder::CreateNode (DWORD set, unsigned int count, fixed_t bbox[4]) D(PrintSet (1, set1)); D(Printf (PRINT_LOG, "(%d,%d) delta (%d,%d) from seg %d\n", node.x>>16, node.y>>16, node.dx>>16, node.dy>>16, splitseg)); D(PrintSet (2, set2)); - node.intchildren[0] = CreateNode (set1, count1, node.bbox[0]); - node.intchildren[1] = CreateNode (set2, count2, node.bbox[1]); - bbox[BOXTOP] = MAX (node.bbox[0][BOXTOP], node.bbox[1][BOXTOP]); - bbox[BOXBOTTOM] = MIN (node.bbox[0][BOXBOTTOM], node.bbox[1][BOXBOTTOM]); - bbox[BOXLEFT] = MIN (node.bbox[0][BOXLEFT], node.bbox[1][BOXLEFT]); - bbox[BOXRIGHT] = MAX (node.bbox[0][BOXRIGHT], node.bbox[1][BOXRIGHT]); + node.intchildren[0] = CreateNode (set1, count1, node.nb_bbox[0]); + node.intchildren[1] = CreateNode (set2, count2, node.nb_bbox[1]); + bbox[BOXTOP] = MAX (node.nb_bbox[0][BOXTOP], node.nb_bbox[1][BOXTOP]); + bbox[BOXBOTTOM] = MIN (node.nb_bbox[0][BOXBOTTOM], node.nb_bbox[1][BOXBOTTOM]); + bbox[BOXLEFT] = MIN (node.nb_bbox[0][BOXLEFT], node.nb_bbox[1][BOXLEFT]); + bbox[BOXRIGHT] = MAX (node.nb_bbox[0][BOXRIGHT], node.nb_bbox[1][BOXRIGHT]); return (int)Nodes.Push (node); } else diff --git a/src/nodebuild_extract.cpp b/src/nodebuild_extract.cpp index 425c656e3..c3f63c820 100644 --- a/src/nodebuild_extract.cpp +++ b/src/nodebuild_extract.cpp @@ -94,6 +94,13 @@ void FNodeBuilder::Extract (node_t *&outNodes, int &nodeCount, outNodes[i].children[j] = outNodes + outNodes[i].intchildren[j]; } } + for (int j = 0; j < 2; ++j) + { + for (int k = 0; k < 4; ++k) + { + outNodes[i].bbox[j][k] = FIXED2FLOAT(outNodes[i].nb_bbox[j][k]); + } + } } if (GLNodes) @@ -194,6 +201,13 @@ void FNodeBuilder::ExtractMini (FMiniBSP *bsp) bsp->Nodes[i].children[j] = &bsp->Nodes[bsp->Nodes[i].intchildren[j]]; } } + for (int j = 0; j < 2; ++j) + { + for (int k = 0; k < 4; ++k) + { + bsp->Nodes[i].bbox[j][k] = FIXED2FLOAT(bsp->Nodes[i].nb_bbox[j][k]); + } + } } if (GLNodes) diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 739990692..0fe4cd9c0 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -589,7 +589,7 @@ static bool LoadNodes (FileReader * lump) } for (k = 0; k < 4; k++) { - no->bbox[j][k] = LittleShort(mn->bbox[j][k])<bbox[j][k] = (float)LittleShort(mn->bbox[j][k]); } } } @@ -649,7 +649,7 @@ static bool LoadNodes (FileReader * lump) } for (k = 0; k < 4; k++) { - no->bbox[j][k] = LittleShort(mn->bbox[j][k])<bbox[j][k] = (float)LittleShort(mn->bbox[j][k]); } } } @@ -1135,7 +1135,7 @@ static void CreateCachedNodes(MapData *map) { for (int k = 0; k < 4; ++k) { - WriteWord(ZNodes, nodes[i].bbox[j][k] >> FRACBITS); + WriteWord(ZNodes, (short)nodes[i].bbox[j][k]); } } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index ebd38ba9a..762f4b794 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1096,7 +1096,7 @@ void LoadZNodes(FileReaderBase &data, int glnodes) { SWORD coord; data >> coord; - nodes[i].bbox[j][k] = coord << FRACBITS; + nodes[i].bbox[j][k] = coord; } } for (int m = 0; m < 2; ++m) @@ -1640,7 +1640,7 @@ void P_LoadNodes (MapData * map) } for (k = 0; k < 4; k++) { - no->bbox[j][k] = LittleShort(mn->bbox[j][k])<bbox[j][k] = (float)LittleShort(mn->bbox[j][k]); } } } diff --git a/src/po_man.cpp b/src/po_man.cpp index 1f9c6dbfd..7b5e187a8 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -1919,7 +1919,7 @@ static double PartitionDistance(FPolyVertex *vt, node_t *node) // //========================================================================== -static void AddToBBox(fixed_t child[4], fixed_t parent[4]) +static void AddToBBox(float child[4], float parent[4]) { if (child[BOXTOP] > parent[BOXTOP]) { @@ -1945,10 +1945,10 @@ static void AddToBBox(fixed_t child[4], fixed_t parent[4]) // //========================================================================== -static void AddToBBox(FPolyVertex *v, fixed_t bbox[4]) +static void AddToBBox(FPolyVertex *v, float bbox[4]) { - fixed_t x = FLOAT2FIXED(v->pos.X); - fixed_t y = FLOAT2FIXED(v->pos.Y); + float x = float(v->pos.X); + float y = float(v->pos.Y); if (x < bbox[BOXLEFT]) { bbox[BOXLEFT] = x; @@ -1973,7 +1973,7 @@ static void AddToBBox(FPolyVertex *v, fixed_t bbox[4]) // //========================================================================== -static void SplitPoly(FPolyNode *pnode, void *node, fixed_t bbox[4]) +static void SplitPoly(FPolyNode *pnode, void *node, float bbox[4]) { static TArray lists[2]; static const double POLY_EPSILON = 0.3125; @@ -2110,7 +2110,7 @@ static void SplitPoly(FPolyNode *pnode, void *node, fixed_t bbox[4]) // calculate bounding box for this polynode assert(pnode->segs.Size() != 0); - fixed_t subbbox[4] = { FIXED_MIN, FIXED_MAX, FIXED_MAX, FIXED_MIN }; + float subbbox[4] = { FLT_MIN, FLT_MAX, FLT_MAX, FLT_MIN }; for (unsigned i = 0; i < pnode->segs.Size(); ++i) { @@ -2134,7 +2134,7 @@ void FPolyObj::CreateSubsectorLinks() // Even though we don't care about it, we need to initialize this // bounding box to something so that Valgrind won't complain about it // when SplitPoly modifies it. - fixed_t dummybbox[4] = { 0 }; + float dummybbox[4] = { 0 }; node->poly = this; node->segs.Resize(Sidedefs.Size()); diff --git a/src/r_bsp.cpp b/src/r_bsp.cpp index 2660fce6e..f41e99a74 100644 --- a/src/r_bsp.cpp +++ b/src/r_bsp.cpp @@ -877,7 +877,7 @@ extern "C" const int checkcoord[12][4] = }; -static bool R_CheckBBox (fixed_t *bspcoord) // killough 1/28/98: static +static bool R_CheckBBox (float *bspcoord) // killough 1/28/98: static { int boxx; int boxy; @@ -891,16 +891,16 @@ static bool R_CheckBBox (fixed_t *bspcoord) // killough 1/28/98: static // Find the corners of the box // that define the edges from current viewpoint. - if (ViewPos.X <= FIXED2DBL(bspcoord[BOXLEFT])) + if (ViewPos.X <= bspcoord[BOXLEFT]) boxx = 0; - else if (ViewPos.X < FIXED2DBL(bspcoord[BOXRIGHT])) + else if (ViewPos.X < bspcoord[BOXRIGHT]) boxx = 1; else boxx = 2; - if (ViewPos.Y >= FIXED2DBL(bspcoord[BOXTOP])) + if (ViewPos.Y >= bspcoord[BOXTOP]) boxy = 0; - else if (ViewPos.Y > FIXED2DBL(bspcoord[BOXBOTTOM])) + else if (ViewPos.Y > bspcoord[BOXBOTTOM]) boxy = 1; else boxy = 2; @@ -909,10 +909,10 @@ static bool R_CheckBBox (fixed_t *bspcoord) // killough 1/28/98: static if (boxpos == 5) return true; - x1 = FIXED2DBL(bspcoord[checkcoord[boxpos][0]]) - ViewPos.X; - y1 = FIXED2DBL(bspcoord[checkcoord[boxpos][1]]) - ViewPos.Y; - x2 = FIXED2DBL(bspcoord[checkcoord[boxpos][2]]) - ViewPos.X; - y2 = FIXED2DBL(bspcoord[checkcoord[boxpos][3]]) - ViewPos.Y; + x1 = bspcoord[checkcoord[boxpos][0]] - ViewPos.X; + y1 = bspcoord[checkcoord[boxpos][1]] - ViewPos.Y; + x2 = bspcoord[checkcoord[boxpos][2]] - ViewPos.X; + y2 = bspcoord[checkcoord[boxpos][3]] - ViewPos.Y; // check clip list for an open space diff --git a/src/r_defs.h b/src/r_defs.h index 371b9918e..f27ac2716 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -1364,7 +1364,11 @@ struct node_t fixed_t y; fixed_t dx; fixed_t dy; - fixed_t bbox[2][4]; // Bounding box for each child. + union + { + float bbox[2][4]; // Bounding box for each child. + fixed_t nb_bbox[2][4]; // Used by nodebuilder. + }; float len; union {