From bf7ed6258befe2504a81c5506cc480fa50472717 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 1 Jan 2010 11:00:58 +0000 Subject: [PATCH] - fixed: The node builder did not check if all segs could be split properly. Also removed some fudging that tried to work around this case but produced a broken BSP tree on other maps. SVN r2071 (trunk) --- docs/rh-log.txt | 11 ++++++---- src/nodebuild.cpp | 38 +++++++++++++++++++++++++++++++++-- src/p_setup.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++- src/r_bsp.cpp | 1 + 4 files changed, 94 insertions(+), 7 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 4af0837cd..e93b2a877 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,10 @@ +January 1, 2010 (Changes by Graf Zahl) +- fixed: The node builder did not check if all segs could be split properly. + Also removed some fudging that tried to work around this case but produced + a broken BSP tree on other maps. +- Added Blzut3's Solaris patch. +- Fixed: Heretic's Weredragon (Beast) should not have a melee state. + January 1, 2010 (SBARINFO update) - Reorganized the SBarInfo code. - Added interpolate() flag to drawnumber, drawbar, and drawgem. The old @@ -6,10 +13,6 @@ January 1, 2010 (SBARINFO update) - As an extension to the previous you can now use comparison operators on inventory items and armortype in drawswitchableimage. -January 1, 2010 (Changes by Graf Zahl) -- Added Blzut3's Solaris patch. -- Fixed: Heretic's Weredragon (Beast) should not have a melee state. - December 31, 2009 (Changes by Graf Zahl) - fixed: FastProjectile was missing all sky checks when the projectile's move was blocked. diff --git a/src/nodebuild.cpp b/src/nodebuild.cpp index a988ba6e8..3c87fb6e5 100644 --- a/src/nodebuild.cpp +++ b/src/nodebuild.cpp @@ -114,6 +114,17 @@ int FNodeBuilder::CreateNode (DWORD set, fixed_t bbox[4]) DWORD set1, set2; SplitSegs (set, node, splitseg, set1, set2); + + // Check if the set could be split. It may happen that all segs end up on the same side + // in which case we need to create a subsector from such a set. + if (set1 == DWORD_MAX) + { + return 0x80000000 | CreateSubsector (set2, bbox); + } + else if (set2 == DWORD_MAX) + { + return 0x80000000 | CreateSubsector (set1, bbox); + } 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)); @@ -490,7 +501,9 @@ int FNodeBuilder::SelectSplitter (DWORD set, node_t &node, DWORD &splitseg, int int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit) { - int score = 0; + int score = 1000000; // a high base so that segs that come too close to a splitter + // still can be weighed extremely negatively but preventing + // them from creating a negative score. int segsInSet = 0; int counts[2] = { 0, 0 }; int realSegs[2] = { 0, 0 }; @@ -767,6 +780,27 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou newvert.y += fixed_t(frac * double(Vertices[seg->v2].y - newvert.y)); vertnum = VertexMap->SelectVertexClose (newvert); + if (vertnum == seg->v1 || vertnum == seg->v2) + { + // Check if the resulting split vertex matches one of the line's ends. + // In this case this seg must not be split + if ((vertnum == seg->v1 && sidev2 == -1) || (vertnum == seg->v2 && sidev1 == -1)) + { + side = 0; + sidev1 = 0; + seg->next = outset0; + outset0 = set; + } + else + { + side = 1; + sidev2 = 0; + seg->next = outset1; + outset1 = set; + } + break; + } + seg2 = SplitSeg (set, vertnum, sidev1); Segs[seg2].next = outset0; @@ -841,7 +875,7 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou set = next; } FixSplitSharers (node); - if (GLNodes) + if (GLNodes && outset0 != DWORD_MAX && outset1 != DWORD_MAX) { AddMinisegs (node, splitseg, outset0, outset1); } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index ab467a77e..6b714cf44 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -2712,6 +2712,7 @@ static void P_GroupLines (bool buildmap) FBoundingBox bbox; bool flaggedNoFronts = false; unsigned int ii, jj; + TArray nosector; for (i = 0; i < (int)countof(times); ++i) { @@ -2722,7 +2723,13 @@ static void P_GroupLines (bool buildmap) times[0].Clock(); for (i = 0; i < numsubsectors; i++) { - subsectors[i].sector = segs[subsectors[i].firstline].sidedef->sector; + side_t *side = segs[subsectors[i].firstline].sidedef; + if (side != NULL) subsectors[i].sector = side->sector; + else + { + subsectors[i].sector = NULL; + nosector.Push(i); + } subsectors[i].validcount = validcount; double accumx = 0.0, accumy = 0.0; @@ -2737,6 +2744,48 @@ static void P_GroupLines (bool buildmap) subsectors[i].CenterX = fixed_t(accumx * 0.5 / subsectors[i].numlines); subsectors[i].CenterY = fixed_t(accumy * 0.5 / subsectors[i].numlines); } + for(unsigned i=0;inumlines; j++) + { + seg_t *seg = &segs[sub->firstline + j]; + if (seg->frontsector != NULL) + { + sub->sector = seg->frontsector; + break; + } + if (seg->PartnerSeg != NULL && seg->PartnerSeg->backsector != NULL) + { + sub->sector = seg->PartnerSeg->backsector; + break; + } + } + // we still haven't found a matching sector. Check the back sides of this subsector's segs next + if (sub->sector == NULL) + { + for(unsigned j=0;jnumlines; j++) + { + seg_t *seg = &segs[sub->firstline + j]; + if (seg->backsector != NULL) + { + sub->sector = seg->backsector; + break; + } + if (seg->PartnerSeg != NULL && seg->PartnerSeg->frontsector != NULL) + { + sub->sector = seg->PartnerSeg->frontsector; + break; + } + } + } + if (sub->sector == NULL) + { + sub->sector = §ors[0]; // prevent crashes. This hopefully does not matter because + // any subsector going through here is malformed. + Printf("Unable to assign a sector to subsector %d\n", subsectors[i].firstline); + } + } times[0].Unclock(); // count number of lines in each sector diff --git a/src/r_bsp.cpp b/src/r_bsp.cpp index a1f6f6098..a0aa40e8d 100644 --- a/src/r_bsp.cpp +++ b/src/r_bsp.cpp @@ -1026,6 +1026,7 @@ void R_Subsector (subsector_t *sub) #endif frontsector = sub->sector; + if (sub->sector == NULL) return; frontsector->MoreFlags |= SECF_DRAWN; count = sub->numlines; line = &segs[sub->firstline];