- 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.


SVN r153 (trunk)
This commit is contained in:
Randy Heit 2006-05-29 03:27:32 +00:00
parent fb31db860d
commit 12b066ef2e
6 changed files with 276 additions and 120 deletions

View file

@ -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.

View file

@ -39,6 +39,7 @@
*/
#include <string.h>
#include <float.h>
#include "nodebuild.h"
#include "templates.h"
@ -145,18 +146,31 @@ int FNodeBuilder::CloseSubsector (TArray<seg_t> &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<seg_t> &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)
{

View file

@ -376,7 +376,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Creating parse.c from parse.y"
CommandLine="..\lemon\lemon.exe -m -s &quot;$(InputFileName)&quot;"
CommandLine="..\lemon\lemon.exe -s &quot;$(InputFileName)&quot;&#x0D;&#x0A;"
Outputs="$(InputDir)parse.c"
/>
</FileConfiguration>
@ -386,7 +386,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Creating parse.c from parse.y"
CommandLine="..\lemon\lemon.exe -m -s &quot;$(InputFileName)&quot;"
CommandLine="..\lemon\lemon.exe -s &quot;$(InputFileName)&quot;&#x0D;&#x0A;"
Outputs="$(InputDir)parse.c"
/>
</FileConfiguration>
@ -396,7 +396,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Creating parse.c from parse.y"
CommandLine="..\lemon\lemon.exe -s &quot;$(InputFileName)&quot;"
CommandLine="..\lemon\lemon.exe -s &quot;$(InputFileName)&quot;&#x0D;&#x0A;"
Outputs="$(InputDir)parse.c"
/>
</FileConfiguration>
@ -406,7 +406,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Creating parse.c from parse.y"
CommandLine="..\lemon\lemon.exe -m -s &quot;$(InputFileName)&quot;"
CommandLine="..\lemon\lemon.exe -s &quot;$(InputFileName)&quot;&#x0D;&#x0A;"
Outputs="$(InputDir)parse.c"
/>
</FileConfiguration>

View file

@ -7,11 +7,11 @@
#ifndef NDEBUG
#include <string.h>
#endif
#line 1 "..\\dehsupp\\parse.y"
#line 1 "parse.y"
#include <malloc.h>
#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;

View file

@ -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))
{

View file

@ -881,13 +881,14 @@ yydestruct (yymsg, yytype, yyvaluep)
if (!yymsg)
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
/*
switch (yytype)
{
default:
break;
}
*/
}