home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
D!Zone (Collector's Edition)
/
D_ZONE_CD.ISO
/
programs
/
editors
/
bsp12x
/
makenode.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-06
|
14KB
|
447 lines
/*- MAKENODE.C --------------------------------------------------------------*
Recursively create nodes and return the pointers.
*---------------------------------------------------------------------------*/
struct Node *CreateNode(struct Seg *ts)
{
struct Node *tn;
struct Seg *rights = NULL;
struct Seg *lefts = NULL;
tn = GetMemory( sizeof( struct Node)); /* Create a node*/
DivideSegs(ts,&rights,&lefts); /* Divide node in two*/
num_nodes++;
tn->x = node_x; /* store node line info*/
tn->y = node_y;
tn->dx = node_dx;
tn->dy = node_dy;
FindLimits(lefts); /* Find limits of vertices */
tn->maxy2 = lmaxy;
tn->miny2 = lminy;
tn->minx2 = lminx;
tn->maxx2 = lmaxx;
if(IsItConvex(lefts)) /* Check lefthand side*/
{
tn->nextl = CreateNode(lefts); /* still segs remaining*/
tn->chleft = 0;
}
else
{
tn->nextl = NULL;
tn->chleft = CreateSSector(lefts) | 0x8000;
}
FindLimits(rights); /* Find limits of vertices*/
tn->maxy1 = lmaxy;
tn->miny1 = lminy;
tn->minx1 = lminx;
tn->maxx1 = lmaxx;
if(IsItConvex(rights)) /* Check righthand side*/
{
tn->nextr = CreateNode(rights); /* still segs remaining*/
tn->chright = 0;
}
else
{
tn->nextr = NULL;
tn->chright = CreateSSector(rights) | 0x8000;
}
return tn;
}
/*---------------------------------------------------------------------------*
Split a list of segs (ts) into two using the method described at bottom of
file, this was taken from OBJECTS.C in the DEU5beta source.
This is done by scanning all of the segs and finding the one that does
the least splitting and has the least difference in numbers of segs on either
side.
If the ones on the left side make a SSector, then create another SSector
else put the segs into lefts list.
If the ones on the right side make a SSector, then create another SSector
else put the segs into rights list.
*---------------------------------------------------------------------------*/
void DivideSegs(struct Seg *ts,struct Seg **rs,struct Seg **ls)
{
struct Seg *rights,*lefts;
struct Seg *tmps,*best,*news,*prev;
struct Seg *add_to_rs,*add_to_ls;
struct Seg *new_best,*new_rs,*new_ls;
struct Seg *strights,*stlefts;
int num_secs_r,num_secs_l,last_sec_r,last_sec_l;
int num,least_splits,least;
int fv,tv,num_new = 0;
int bangle,cangle,cangle2,cfv,ctv,dx,dy;
short int x,y,val;
FindLimits(ts); /* Find limits of this set of Segs*/
sp.halfsx = (lmaxx - lminx) / 2; /* Find half width of Node*/
sp.halfsy = (lmaxy - lminy) / 2;
sp.halfx = lminx + sp.halfsx; /* Find middle of Node*/
sp.halfy = lminy + sp.halfsy;
best = PickNode(ts); /* Pick best node to use.*/
if(best == NULL) ProgError("Couldn't pick nodeline!");
node_x = vertices[best->start].x;
node_y = vertices[best->start].y;
node_dx = vertices[best->end].x-vertices[best->start].x;
node_dy = vertices[best->end].y-vertices[best->start].y;
/* When we get to here, best is a pointer to the partition seg.
Using this partition line, we must split any lines that are intersected
into a left and right half, flagging them to be put their respective sides
Ok, now we have the best line to use as a partitioning line, we must
split all of the segs into two lists (rightside & leftside). */
rights = NULL; /* Start off with empty*/
lefts = NULL; /* lists.*/
strights = NULL; /* Start off with empty*/
stlefts = NULL; /* lists.*/
psx = vertices[best->start].x; /* Partition line coords*/
psy = vertices[best->start].y;
pex = vertices[best->end].x;
pey = vertices[best->end].y;
pdx = psx - pex; /* Partition line DX,DY*/
pdy = psy - pey;
for(tmps=ts;tmps;tmps=tmps->next)
{
progress(); /* Something for the user to look at.*/
add_to_rs = NULL;
add_to_ls = NULL;
if(tmps != best)
{
lsx = vertices[tmps->start].x; /* Calculate this here, cos it doesn't*/
lsy = vertices[tmps->start].y; /* change for all the interations of*/
lex = vertices[tmps->end].x; /* the inner loop!*/
ley = vertices[tmps->end].y;
val = DoLinesIntersect();
if((val&2 && val&64) || (val&4 && val&32)) /* If intersecting !!*/
{
ComputeIntersection(&x,&y);
/* printf("Splitting Linedef %d at %d,%d\n",tmps->linedef,x,y);*/
vertices = ResizeMemory(vertices, sizeof(struct Vertex) * (num_verts+1));
vertices[num_verts].x = x;
vertices[num_verts].y = y;
news = GetMemory(sizeof( struct Seg));
news->next = tmps->next;
tmps->next = news;
news->start = num_verts;
news->end = tmps->end;
tmps->end = num_verts;
news->linedef = tmps->linedef;
news->angle = tmps->angle;
news->flip = tmps->flip;
news->dist = SplitDist(news);
/* printf("splitting dist = %d\n",news->dist);*/
/* printf("splitting vertices = %d,%d,%d,%d\n",tmps->start,tmps->end,news->start,news->end);*/
if(val&32) add_to_ls = tmps;
if(val&64) add_to_rs = tmps;
if(val&2) add_to_ls = news;
if(val&4) add_to_rs = news;
tmps = news;
num_verts++;
num_new++;
}
else
{ /* Not split, which side ?*/
if(val&34) add_to_ls = tmps;
if(val&68) add_to_rs = tmps;
if(val&1 && val&16) /* On same line*/
{
if(tmps->flip == best->flip) add_to_rs = tmps;
if(tmps->flip != best->flip) add_to_ls = tmps;
}
}
}
else add_to_rs = tmps; /* This is the partition line*/
/* printf("Val = %X\n",val);*/
if(add_to_rs) /* CHECK IF SHOULD ADD RIGHT ONE */
{
new_rs = GetMemory(sizeof(struct Seg));
if(add_to_rs == best) new_best = new_rs;
new_rs->start = add_to_rs->start;
new_rs->end = add_to_rs->end;
new_rs->linedef = add_to_rs->linedef;
new_rs->angle = add_to_rs->angle;
new_rs->flip = add_to_rs->flip;
new_rs->dist = add_to_rs->dist;
new_rs->next = NULL;
if(!rights) strights = rights = new_rs;
else
{
rights->next = new_rs;
rights = new_rs;
}
}
if(add_to_ls) /* CHECK IF SHOULD ADD LEFT ONE */
{
new_ls = GetMemory(sizeof(struct Seg));
if(add_to_ls == best) new_best = new_ls;
new_ls->start = add_to_ls->start;
new_ls->end = add_to_ls->end;
new_ls->linedef = add_to_ls->linedef;
new_ls->angle = add_to_ls->angle;
new_ls->flip = add_to_ls->flip;
new_ls->dist = add_to_ls->dist;
new_ls->next = NULL;
if(!lefts) stlefts = lefts = new_ls;
else
{
lefts->next = new_ls;
lefts = new_ls;
}
}
}
if(strights == NULL)
{
/* printf("No right side, moving partition into right side\n");*/
strights = rights = new_best;
prev = NULL;
for(tmps=stlefts;tmps;tmps=tmps->next)
{
if(tmps == new_best)
{
if(prev != NULL) prev->next=tmps->next;
else stlefts=tmps->next;
}
prev=tmps;
}
prev->next = NULL;
}
if(stlefts == NULL)
{
/* printf("No left side, moving partition into left side\n");*/
stlefts = lefts = new_best;
prev = NULL;
for(tmps=strights;tmps;tmps=tmps->next)
{
if(tmps == new_best)
{
if(prev != NULL) prev->next=tmps->next;
else strights=tmps->next;
}
prev=tmps;
}
stlefts->next = NULL;
prev->next = NULL; /* Make sure end of list = NULL*/
}
if(rights->next != NULL) rights->next = NULL;
if(lefts->next != NULL) lefts->next = NULL;
for(tmps=ts;tmps;tmps=best)
{
best=tmps->next;
free(tmps);
}
/* printf("Made %d new Vertices and Segs\n",num_new);*/
*rs = strights ; *ls = stlefts;
}
/*--------------------------------------------------------------------------*/
int IsItConvex( struct Seg *ts)
{
struct Seg *line,*check;
int sector,val;
if (ts->flip) sector = sidedefs[linedefs[ ts->linedef].sidedef2].sector;
else sector = sidedefs[linedefs[ts->linedef].sidedef1].sector;
for (line = ts->next; line; line = line->next)
{
if (line->fl