diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 2df9deed1..d635715ff 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,11 @@ +May 28, 2006 +- Fixed: When building GL nodes for Deathkings MAP42, one polyobject had one + of its segs thrown away, so the map could not start. This was because the + nodebuilder assumed all subsectors would be 2D and could not handle the + case where a degenerate 1D subsector is created. In this case, that happens + because that map has three polyobjects in the middle of the void, so the only + way to assign them to a subsector is to use a 1D subsector. + May 28, 2006 (Changes by Graf Zahl) - Fixed: Monsters couldn't hurt other monsters of the same species if they were supposed to hate them. diff --git a/src/nodebuild_extract.cpp b/src/nodebuild_extract.cpp index 09d50a28e..3492965fb 100644 --- a/src/nodebuild_extract.cpp +++ b/src/nodebuild_extract.cpp @@ -39,6 +39,7 @@ */ #include +#include #include "nodebuild.h" #include "templates.h" @@ -145,18 +146,31 @@ int FNodeBuilder::CloseSubsector (TArray &segs, int subsector, vertex_t * fixed_t midx, midy; int firstVert; DWORD first, max, count, i, j; + bool diffplanes; + int firstplane; first = Subsectors[subsector].firstline; max = first + Subsectors[subsector].numlines; count = 0; accumx = accumy = 0.0; + diffplanes = false; + firstplane = Segs[SegList[first].SegNum].planenum; + // Calculate the midpoint of the subsector and also check for degenerate subsectors. + // A subsector is degenerate if it exists in only one dimension, which can be + // detected when all the segs lie in the same plane. This can happen if you have + // outward-facing lines in the void that don't point toward any sector. (Some of the + // polyobjects in Hexen are constructed like this.) for (i = first; i < max; ++i) { seg = &Segs[SegList[i].SegNum]; accumx += double(Vertices[seg->v1].x) + double(Vertices[seg->v2].x); accumy += double(Vertices[seg->v1].y) + double(Vertices[seg->v2].y); + if (firstplane != seg->planenum) + { + diffplanes = true; + } } midx = fixed_t(accumx / (max - first) / 2); @@ -169,54 +183,188 @@ int FNodeBuilder::CloseSubsector (TArray &segs, int subsector, vertex_t * prev = seg; firstVert = seg->v1; - for (i = first + 1; i < max; ++i) - { - angle_t bestdiff = ANGLE_MAX; - FPrivSeg *bestseg = NULL; - DWORD bestj = DWORD_MAX; - j = first; - do + if (diffplanes) + { // A well-behaved subsector. Output the segs sorted by the angle formed by connecting + // the subsector's center to their first vertex. + + for (i = first + 1; i < max; ++i) { - seg = &Segs[SegList[j].SegNum]; - angle_t ang = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy); - angle_t diff = prevAngle - ang; - if (seg->v1 == prev->v2) + angle_t bestdiff = ANGLE_MAX; + FPrivSeg *bestseg = NULL; + DWORD bestj = DWORD_MAX; + j = first; + do { - bestdiff = diff; - bestseg = seg; - bestj = j; + seg = &Segs[SegList[j].SegNum]; + angle_t ang = PointToAngle (Vertices[seg->v1].x - midx, Vertices[seg->v1].y - midy); + angle_t diff = prevAngle - ang; + if (seg->v1 == prev->v2) + { + bestdiff = diff; + bestseg = seg; + bestj = j; + break; + } + if (diff < bestdiff && diff > 0) + { + bestdiff = diff; + bestseg = seg; + bestj = j; + } + } + while (++j < max); + // Is a NULL bestseg actually okay? + if (bestseg != NULL) + { + seg = bestseg; + } + if (prev->v2 != seg->v1) + { + // Add a new miniseg to connect the two segs + PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[seg->v1]); + count++; + } + + prevAngle -= bestdiff; + seg->storedseg = PushGLSeg (segs, seg, outVerts); + count++; + prev = seg; + if (seg->v2 == firstVert) + { + prev = seg; break; } - if (diff < bestdiff && diff > 0) - { - bestdiff = diff; - bestseg = seg; - bestj = j; - } - } - while (++j < max); - // Is a NULL bestseg actually okay? - if (bestseg != NULL) - { - seg = bestseg; - } - if (prev->v2 != seg->v1) - { - // Add a new miniseg to connect the two segs - PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[seg->v1]); - count++; - } - - prevAngle -= bestdiff; - seg->storedseg = PushGLSeg (segs, seg, outVerts); - count++; - prev = seg; - if (seg->v2 == firstVert) - { - prev = seg; - break; } } + else + { // A degenerate subsector. These are handled in three stages: + // Stage 1. Proceed in the same direction as the start seg until we + // hit the seg furthest from it. + // Stage 2. Reverse direction and proceed until we hit the seg + // furthest from the start seg. + // Stage 3. Reverse direction again and insert segs until we get + // to the start seg. + // A dot product serves to determine distance from the start seg. + + seg = &Segs[SegList[first].SegNum]; + double x1 = Vertices[seg->v1].x; + double y1 = Vertices[seg->v1].y; + double dx = Vertices[seg->v2].x - x1, dx2; + double dy = Vertices[seg->v2].y - y1, dy2; + double lastdot = 0, dot; + bool firstside = seg->planefront; + + // Stage 1. Go forward. + for (i = first + 1; i < max; ++i) + { + double bestdot = DBL_MAX; + FPrivSeg *bestseg = NULL; + for (j = first + 1; j < max; ++j) + { + seg = &Segs[SegList[j].SegNum]; + if (seg->planefront != firstside) + { + continue; + } + dx2 = Vertices[seg->v1].x - x1; + dy2 = Vertices[seg->v1].y - y1; + dot = dx*dx2 + dy*dy2; + + if (dot < bestdot && dot > lastdot) + { + bestdot = dot; + bestseg = seg; + } + } + if (bestseg != NULL) + { + if (prev->v2 != bestseg->v1) + { + PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[bestseg->v1]); + count++; + } + seg->storedseg = PushGLSeg (segs, bestseg, outVerts); + count++; + prev = bestseg; + lastdot = bestdot; + } + } + + // Stage 2. Go backward. + lastdot = DBL_MAX; + for (i = first + 1; i < max; ++i) + { + double bestdot = -DBL_MAX; + FPrivSeg *bestseg = NULL; + for (j = first + 1; j < max; ++j) + { + seg = &Segs[SegList[j].SegNum]; + if (seg->planefront == firstside) + { + continue; + } + dx2 = Vertices[seg->v1].x - x1; + dy2 = Vertices[seg->v1].y - y1; + dot = dx*dx2 + dy*dy2; + + if (dot > bestdot && dot < lastdot) + { + bestdot = dot; + bestseg = seg; + } + } + if (bestseg != NULL) + { + if (prev->v2 != bestseg->v1) + { + PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[bestseg->v1]); + count++; + } + seg->storedseg = PushGLSeg (segs, bestseg, outVerts); + count++; + prev = bestseg; + lastdot = bestdot; + } + } + + // Stage 3. Go forward again. + lastdot = -DBL_MAX; + for (i = first + 1; i < max; ++i) + { + double bestdot = 0; + FPrivSeg *bestseg = NULL; + for (j = first + 1; j < max; ++j) + { + seg = &Segs[SegList[j].SegNum]; + if (seg->planefront != firstside) + { + continue; + } + dx2 = Vertices[seg->v1].x - x1; + dy2 = Vertices[seg->v1].y - y1; + dot = dx*dx2 + dy*dy2; + + if (dot < bestdot && dot > lastdot) + { + bestdot = dot; + bestseg = seg; + } + } + if (bestseg != NULL) + { + if (prev->v2 != bestseg->v1) + { + PushConnectingGLSeg (subsector, segs, &outVerts[prev->v2], &outVerts[bestseg->v1]); + count++; + } + seg->storedseg = PushGLSeg (segs, bestseg, outVerts); + count++; + prev = bestseg; + lastdot = bestdot; + } + } + } + if (prev->v2 != firstVert) { diff --git a/tools/dehsupp/dehsupp.vcproj b/tools/dehsupp/dehsupp.vcproj index 83c807341..e43f21705 100644 --- a/tools/dehsupp/dehsupp.vcproj +++ b/tools/dehsupp/dehsupp.vcproj @@ -376,7 +376,7 @@ @@ -386,7 +386,7 @@ @@ -396,7 +396,7 @@ @@ -406,7 +406,7 @@ diff --git a/tools/dehsupp/parse.c b/tools/dehsupp/parse.c index 82b917e58..61fb66ef8 100644 --- a/tools/dehsupp/parse.c +++ b/tools/dehsupp/parse.c @@ -7,11 +7,11 @@ #ifndef NDEBUG #include #endif -#line 1 "..\\dehsupp\\parse.y" +#line 1 "parse.y" #include #include "dehsupp.h" -#line 16 "..\\dehsupp\\parse.c" +#line 16 "parse.c" /* Next is all token values, in a form suitable for use by makeheaders. ** This section will be null unless lemon is run with the -m switch. */ @@ -486,9 +486,9 @@ static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ case 32: case 33: case 34: -#line 8 "..\\dehsupp\\parse.y" +#line 8 "parse.y" { if ((yypminor->yy0).string) free((yypminor->yy0).string); } -#line 493 "..\\dehsupp\\parse.c" +#line 493 "parse.c" break; default: break; /* If no destructor action specified: do nothing */ } @@ -788,205 +788,205 @@ static void yy_reduce( ** break; */ case 14: -#line 37 "..\\dehsupp\\parse.y" +#line 37 "parse.y" { printf ("\n"); yy_destructor(10,&yymsp[-3].minor); yy_destructor(11,&yymsp[-2].minor); yy_destructor(12,&yymsp[0].minor); } -#line 800 "..\\dehsupp\\parse.c" +#line 800 "parse.c" break; case 18: -#line 45 "..\\dehsupp\\parse.y" +#line 45 "parse.y" { printf ("%s", yymsp[0].minor.yy0.string); } -#line 805 "..\\dehsupp\\parse.c" +#line 805 "parse.c" break; case 19: -#line 46 "..\\dehsupp\\parse.y" +#line 46 "parse.y" { printf ("%d", yymsp[0].minor.yy62); } -#line 810 "..\\dehsupp\\parse.c" +#line 810 "parse.c" break; case 20: -#line 47 "..\\dehsupp\\parse.y" +#line 47 "parse.y" { printf ("\n"); yy_destructor(15,&yymsp[0].minor); } -#line 816 "..\\dehsupp\\parse.c" +#line 816 "parse.c" break; case 21: -#line 50 "..\\dehsupp\\parse.y" +#line 50 "parse.y" { yygotominor.yy62 = yymsp[0].minor.yy0.val; } -#line 821 "..\\dehsupp\\parse.c" +#line 821 "parse.c" break; case 22: -#line 51 "..\\dehsupp\\parse.y" +#line 51 "parse.y" { yygotominor.yy62 = yymsp[-2].minor.yy62 + yymsp[0].minor.yy62; yy_destructor(5,&yymsp[-1].minor); } -#line 827 "..\\dehsupp\\parse.c" +#line 827 "parse.c" break; case 23: -#line 52 "..\\dehsupp\\parse.y" +#line 52 "parse.y" { yygotominor.yy62 = yymsp[-2].minor.yy62 - yymsp[0].minor.yy62; yy_destructor(4,&yymsp[-1].minor); } -#line 833 "..\\dehsupp\\parse.c" +#line 833 "parse.c" break; case 24: -#line 53 "..\\dehsupp\\parse.y" +#line 53 "parse.y" { yygotominor.yy62 = yymsp[-2].minor.yy62 * yymsp[0].minor.yy62; yy_destructor(6,&yymsp[-1].minor); } -#line 839 "..\\dehsupp\\parse.c" +#line 839 "parse.c" break; case 25: -#line 54 "..\\dehsupp\\parse.y" +#line 54 "parse.y" { yygotominor.yy62 = yymsp[-2].minor.yy62 / yymsp[0].minor.yy62; yy_destructor(7,&yymsp[-1].minor); } -#line 845 "..\\dehsupp\\parse.c" +#line 845 "parse.c" break; case 26: -#line 55 "..\\dehsupp\\parse.y" +#line 55 "parse.y" { yygotominor.yy62 = yymsp[-2].minor.yy62 | yymsp[0].minor.yy62; yy_destructor(1,&yymsp[-1].minor); } -#line 851 "..\\dehsupp\\parse.c" +#line 851 "parse.c" break; case 27: -#line 56 "..\\dehsupp\\parse.y" +#line 56 "parse.y" { yygotominor.yy62 = yymsp[-2].minor.yy62 & yymsp[0].minor.yy62; yy_destructor(3,&yymsp[-1].minor); } -#line 857 "..\\dehsupp\\parse.c" +#line 857 "parse.c" break; case 28: -#line 57 "..\\dehsupp\\parse.y" +#line 57 "parse.y" { yygotominor.yy62 = yymsp[-2].minor.yy62 ^ yymsp[0].minor.yy62; yy_destructor(2,&yymsp[-1].minor); } -#line 863 "..\\dehsupp\\parse.c" +#line 863 "parse.c" break; case 29: -#line 58 "..\\dehsupp\\parse.y" +#line 58 "parse.y" { yygotominor.yy62 = -yymsp[0].minor.yy62; yy_destructor(4,&yymsp[-1].minor); } -#line 869 "..\\dehsupp\\parse.c" +#line 869 "parse.c" break; case 30: -#line 59 "..\\dehsupp\\parse.y" +#line 59 "parse.y" { yygotominor.yy62 = yymsp[-1].minor.yy62; yy_destructor(11,&yymsp[-2].minor); yy_destructor(12,&yymsp[0].minor); } -#line 876 "..\\dehsupp\\parse.c" +#line 876 "parse.c" break; case 33: -#line 65 "..\\dehsupp\\parse.y" +#line 65 "parse.y" { AddAction (yymsp[0].minor.yy0.string); } -#line 881 "..\\dehsupp\\parse.c" +#line 881 "parse.c" break; case 34: -#line 66 "..\\dehsupp\\parse.y" +#line 66 "parse.y" { AddAction (yymsp[0].minor.yy0.string); yy_destructor(13,&yymsp[-1].minor); } -#line 887 "..\\dehsupp\\parse.c" +#line 887 "parse.c" break; case 37: -#line 72 "..\\dehsupp\\parse.y" +#line 72 "parse.y" { AddHeight (yymsp[0].minor.yy62); } -#line 892 "..\\dehsupp\\parse.c" +#line 892 "parse.c" break; case 38: -#line 73 "..\\dehsupp\\parse.y" +#line 73 "parse.y" { AddHeight (yymsp[0].minor.yy62); yy_destructor(13,&yymsp[-1].minor); } -#line 898 "..\\dehsupp\\parse.c" +#line 898 "parse.c" break; case 41: -#line 79 "..\\dehsupp\\parse.y" +#line 79 "parse.y" { AddActionMap (yymsp[0].minor.yy0.string); } -#line 903 "..\\dehsupp\\parse.c" +#line 903 "parse.c" break; case 42: -#line 80 "..\\dehsupp\\parse.y" +#line 80 "parse.y" { AddActionMap (yymsp[0].minor.yy0.string); yy_destructor(13,&yymsp[-1].minor); } -#line 909 "..\\dehsupp\\parse.c" +#line 909 "parse.c" break; case 45: -#line 86 "..\\dehsupp\\parse.y" +#line 86 "parse.y" { AddCodeP (yymsp[0].minor.yy62); } -#line 914 "..\\dehsupp\\parse.c" +#line 914 "parse.c" break; case 46: -#line 87 "..\\dehsupp\\parse.y" +#line 87 "parse.y" { AddCodeP (yymsp[0].minor.yy62); yy_destructor(13,&yymsp[-1].minor); } -#line 920 "..\\dehsupp\\parse.c" +#line 920 "parse.c" break; case 49: -#line 93 "..\\dehsupp\\parse.y" +#line 93 "parse.y" { AddSpriteName (yymsp[0].minor.yy0.string); } -#line 925 "..\\dehsupp\\parse.c" +#line 925 "parse.c" break; case 50: -#line 94 "..\\dehsupp\\parse.y" +#line 94 "parse.y" { AddSpriteName (yymsp[0].minor.yy0.string); yy_destructor(13,&yymsp[-1].minor); } -#line 931 "..\\dehsupp\\parse.c" +#line 931 "parse.c" break; case 55: -#line 103 "..\\dehsupp\\parse.y" +#line 103 "parse.y" { AddStateMap (yymsp[-4].minor.yy0.string, yymsp[-2].minor.yy62, yymsp[0].minor.yy62); yy_destructor(13,&yymsp[-3].minor); yy_destructor(13,&yymsp[-1].minor); } -#line 938 "..\\dehsupp\\parse.c" +#line 938 "parse.c" break; case 56: -#line 106 "..\\dehsupp\\parse.y" +#line 106 "parse.y" { yygotominor.yy62 = 0; yy_destructor(28,&yymsp[0].minor); } -#line 944 "..\\dehsupp\\parse.c" +#line 944 "parse.c" break; case 57: -#line 107 "..\\dehsupp\\parse.y" +#line 107 "parse.y" { yygotominor.yy62 = 1; yy_destructor(29,&yymsp[0].minor); } -#line 950 "..\\dehsupp\\parse.c" +#line 950 "parse.c" break; case 58: -#line 108 "..\\dehsupp\\parse.y" +#line 108 "parse.y" { yygotominor.yy62 = 2; yy_destructor(30,&yymsp[0].minor); } -#line 956 "..\\dehsupp\\parse.c" +#line 956 "parse.c" break; case 61: -#line 114 "..\\dehsupp\\parse.y" +#line 114 "parse.y" { AddSoundMap (yymsp[0].minor.yy0.string); } -#line 961 "..\\dehsupp\\parse.c" +#line 961 "parse.c" break; case 62: -#line 115 "..\\dehsupp\\parse.y" +#line 115 "parse.y" { AddSoundMap (yymsp[0].minor.yy0.string); yy_destructor(13,&yymsp[-1].minor); } -#line 967 "..\\dehsupp\\parse.c" +#line 967 "parse.c" break; case 65: -#line 121 "..\\dehsupp\\parse.y" +#line 121 "parse.y" { AddInfoName (yymsp[0].minor.yy0.string); } -#line 972 "..\\dehsupp\\parse.c" +#line 972 "parse.c" break; case 66: -#line 122 "..\\dehsupp\\parse.y" +#line 122 "parse.y" { AddInfoName (yymsp[0].minor.yy0.string); yy_destructor(13,&yymsp[-1].minor); } -#line 978 "..\\dehsupp\\parse.c" +#line 978 "parse.c" break; case 71: -#line 131 "..\\dehsupp\\parse.y" +#line 131 "parse.y" { AddThingBits (yymsp[0].minor.yy0.string, yymsp[-4].minor.yy62, yymsp[-2].minor.yy62); yy_destructor(13,&yymsp[-3].minor); yy_destructor(13,&yymsp[-1].minor); } -#line 985 "..\\dehsupp\\parse.c" +#line 985 "parse.c" break; case 76: -#line 140 "..\\dehsupp\\parse.y" +#line 140 "parse.y" { AddRenderStyle (yymsp[0].minor.yy0.string, yymsp[-2].minor.yy62); yy_destructor(13,&yymsp[-1].minor); } -#line 991 "..\\dehsupp\\parse.c" +#line 991 "parse.c" break; }; yygoto = yyRuleInfo[yyruleno].lhs; diff --git a/tools/re2c/code.cc b/tools/re2c/code.cc index 227682745..a256a3697 100644 --- a/tools/re2c/code.cc +++ b/tools/re2c/code.cc @@ -962,7 +962,6 @@ void Go::genGoto(std::ostream &o, uint ind, const State *from, const State *next if (to && to->isBase) { const BitMap *b = BitMap::find(to); - const char * sYych; if (b && matches(b->go, b->on, this, to)) { diff --git a/tools/re2c/parser.cc b/tools/re2c/parser.cc index 2b9cacc21..a8f7f474a 100644 --- a/tools/re2c/parser.cc +++ b/tools/re2c/parser.cc @@ -881,13 +881,14 @@ yydestruct (yymsg, yytype, yyvaluep) if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - +/* switch (yytype) { default: break; } +*/ }