home *** CD-ROM | disk | FTP | other *** search
- /* saveconnect.m */
-
- #ifdef _STEVE_FIX_
- #include <malloc.h>
- #endif
-
- #include "idbsp.h"
-
- typedef struct
- {
- int x,y;
- } bpoint_t;
-
- typedef struct
- {
- int xl, xh, yl, yh;
- } bbox_t;
-
- typedef struct
- {
- bpoint_t p1, p2;
- } bline_t;
-
- typedef struct
- {
- int numpoints;
- bbox_t bounds;
- bpoint_t *points;
- } bchain_t;
-
- typedef struct
- {
- int x,y;
- int dx,dy;
- } bdivline_t;
-
-
- /* [numsec][numsec] array */
- byte *connections;
-
- int numblines;
- bline_t *blines;
-
- int numsectors;
- bbox_t *secboxes;
-
- int numbchains;
- bchain_t *bchains;
-
- void ClearBBox (bbox_t *box)
- {
- box->xl = box->yl = INT_MAX;
- box->xh = box->yh = INT_MIN;
- }
-
- void AddToBBox (bbox_t *box, int x, int y)
- {
- if (x < box->xl)
- box->xl = x;
- if (x > box->xh)
- box->xh = x;
- if (y < box->yl)
- box->yl = y;
- if (y > box->yh)
- box->yh = y;
- }
-
-
- /*
- ==================
- =
- = BPointOnSide
- =
- = Returns side 0 (front), 1 (back), or -1 (colinear)
- ==================
- */
-
- int BPointOnSide (bpoint_t *pt, bdivline_t *l)
- {
- int dx,dy;
- int left, right;
-
- if (!l->dx)
- {
- if (pt->x < l->x)
- return l->dy > 0;
- return l->dy < 0;
- }
- if (!l->dy)
- {
- if (pt->y < l->y)
- return l->dx < 0;
- return l->dx > 0;
- }
-
-
- dx = pt->x - l->x;
- dy = pt->y - l->y;
-
- left = l->dy * dx;
- right = dy * l->dx;
-
- if (right < left)
- return 0; /* front side */
- return 1; /* back side */
- }
-
-
- void DrawBBox (bbox_t *box)
- {
- /*
- PSmoveto (box->xl,box->yl);
- PSlineto (box->xh,box->yl);
- PSlineto (box->xh,box->yh);
- PSlineto (box->xl,box->yh);
- PSlineto (box->xl,box->yl);
- PSstroke ();
- NXPing ();
- */
- }
-
- void DrawDivline (bdivline_t *li)
- {
- /*
- PSmoveto (li->x,li->y);
- PSrlineto (li->dx,li->dy);
- PSstroke ();
- NXPing ();
- */
- }
-
- void DrawBChain (bchain_t *ch)
- {
- /*
- int i;
-
- PSmoveto (ch->points->x,ch->points->y);
- for (i=1 ; i<ch->numpoints ; i++)
- PSlineto (ch->points[i].x,ch->points[i].y);
- PSstroke ();
- NXPing ();
- */
- }
-
-
- bdivline_t ends[2], sides[2];
- int end0out, end1out, side0out, side1out;
- bbox_t sweptarea;
-
-
- /*
- ====================
- =
- = DoesChainBlock
- =
- ====================
- */
-
- boolean DoesChainBlock (bchain_t *chain)
- {
- /*
-
- if a solid line can be walked from one side to the other without going out
- an end, the path is blocked
-
- */
-
- bpoint_t *pt;
- int side, startside;
- int p;
-
- /* don't check if bounds don't intersect */
-
- if (sweptarea.xl > chain->bounds.xh || sweptarea.xh < chain->bounds. xl ||
- sweptarea.yl > chain->bounds. yh || sweptarea.yh < chain->bounds. yl)
- return false;
-
- startside = -1; /* not started yet */
-
- for (p=0, pt=chain->points ; p<chain->numpoints ; p++, pt++)
- {
- /* find side for pt */
- #if 0
- if (p>0)
- {
- PSmoveto ((pt-1)->x, (pt-1)->y);
- PSlineto (pt->x,pt->y);
- PSstroke ();
- NXPing ();
- }
- #endif
-
- if (BPointOnSide (pt, &ends[0]) == end0out)
- {
- startside = -1; /* off end */
- continue;
- }
- if (BPointOnSide (pt, &ends[1]) == end1out)
- {
- startside = -1; /* off end */
- continue;
- }
- if (BPointOnSide (pt, &sides[0]) == side0out)
- side = 0;
- else if (BPointOnSide (pt, &sides[1]) == side1out)
- side = 1;
- else
- continue; /* in middle */
-
- /* point is on one side or the other */
- if (startside == -1 || startside == side)
- {
- startside = side;
- continue;
- }
-
- /* opposite of startside */
- return true; /* totally crossed area */
-
- }
-
- return false;
- }
-
- /*
- ====================
- =
- = BuildConnections
- =
- ====================
- */
-
- enum {si_north, si_east, si_south, si_west};
-
- void BuildConnections (void)
- {
- int blockcount, passcount;
- int i,j, k, s, bn;
- int x,y;
- bbox_t *bbox[2];
- int walls[4];
- bpoint_t points[2][2];
-
- /* look for obscured sectors */
- blockcount = passcount = 0;
- bbox[0] = secboxes;
- printf("\n");
- for (i=0 ; i<numsectors-1 ; i++, bbox[0]++)
- {
- printf("connection #%d of %d\r",i,numsectors-1);
- bbox[1] = bbox[0] + 1;
- if (bbox[0]->xh - bbox[0]->xl < 64 || bbox[0]->yh - bbox[0]->yl < 64)
- { /* don't bother with small sectors (stairs, doorways, etc) */
- continue;
- }
-
- for (j=i+1 ; j<numsectors ; j++, bbox[1]++)
- {
- if (bbox[1]->xh - bbox[1]->xl < 64 || bbox[1]->yh - bbox[1]->yl < 64)
- { /* don't bother with small sectors (stairs, doorways, etc) */
- continue;
- }
- if (bbox[1]->xl <= bbox[0]->xh && bbox[1]->xh >= bbox[0]->xl &&
- bbox[1]->yl <= bbox[0]->yh && bbox[1]->yh >= bbox[0]->yl)
- { /* touching sectors are never blocked */
- passcount++;
- continue;
- }
-
- sweptarea.xl = bbox[0]->xl < bbox[1]->xl ? bbox[0]->xl : bbox[1]->xl;
- sweptarea.xh = bbox[0]->xh > bbox[1]->xh ? bbox[0]->xh : bbox[1]->xh;
- sweptarea.yl = bbox[0]->yl < bbox[1]->yl ? bbox[0]->yl : bbox[1]->yl;
- sweptarea.yh = bbox[0]->yh > bbox[1]->yh ? bbox[0]->yh : bbox[1]->yh;
-
- /*
- calculate the swept area between the sectors
- */
- for (bn=0 ; bn<2 ; bn++)
- {
- memset (walls,0,sizeof(walls));
- if (bbox[bn]->xl <= bbox[!bn]->xl)
- walls[si_west] = 1;
- if (bbox[bn]->xh >= bbox[!bn]->xh)
- walls[si_east] = 1;
- if (bbox[bn]->yl <= bbox[!bn]->yl)
- walls[si_south] = 1;
- if (bbox[bn]->yh >= bbox[!bn]->yh)
- walls[si_north] = 1;
-
- for (s=0 ; s<5 ; s++)
- {
- switch (s&3)
- {
- case si_north:
- x = bbox[bn]->xl;
- y = bbox[bn]->yh;
- break;
- case si_east:
- x = bbox[bn]->xh;
- y = bbox[bn]->yh;
- break;
- case si_south:
- x = bbox[bn]->xh;
- y = bbox[bn]->yl;
- break;
- case si_west:
- x = bbox[bn]->xl;
- y = bbox[bn]->yl;
- break;
- }
- if (!walls[(s-1)&3] && walls[s&3])
- {
- points[bn][0].x = x;
- points[bn][0].y = y;
- }
- if (walls[(s-1)&3] && !walls[s&3])
- {
- points[bn][1].x = x;
- points[bn][1].y = y;
- }
- }
-
- ends[bn].x = points[bn][0].x;
- ends[bn].y = points[bn][0].y;
- ends[bn].dx = points[bn][1].x - points[bn][0].x;
- ends[bn].dy = points[bn][1].y - points[bn][0].y;
- }
-
- sides[0].x = points[0][0].x;
- sides[0].y = points[0][0].y;
- sides[0].dx = points[1][1].x - points[0][0].x;
- sides[0].dy = points[1][1].y - points[0][0].y;
-
- sides[1].x = points[0][1].x;
- sides[1].y = points[0][1].y;
- sides[1].dx = points[1][0].x - points[0][1].x;
- sides[1].dy = points[1][0].y - points[0][1].y;
-
- end0out = !BPointOnSide (&points[1][0], &ends[0]);
- end1out = !BPointOnSide (&points[0][0], &ends[1]);
- side0out = !BPointOnSide (&points[0][1], &sides[0]);
- side1out = !BPointOnSide (&points[0][0], &sides[1]);
-
- /*
- look for a line change that covers the swept area
- */
- for (k=0 ; k<numbchains ; k++)
- {
- if (!DoesChainBlock (&bchains[k]))
- continue;
- blockcount++;
- connections[i*numsectors+j] = connections[j*numsectors+i] = 1;
- /*
- if (draw)
- {
- EraseWindow ();
- DrawBBox (bbox[0]);
- DrawBBox (bbox[1]);
- DrawDivline (&ends[0]);
- DrawDivline (&ends[1]);
- DrawDivline (&sides[0]);
- DrawDivline (&sides[1]);
- DrawBChain (&bchains[k]);
- }
- */
- goto blocked;
- }
-
- /* nothing definately blocked the path */
- passcount++;
- blocked: ;
- }
- }
- printf ("passcount: %i\nblockcount: %i\n",passcount, blockcount);
- }
-
-
- /*
- ====================
- =
- = BuildBlockingChains
- =
- ====================
- */
-
- void BuildBlockingChains (void)
- {
- boolean *used;
- int i,j;
- bpoint_t *temppoints, *pt_p;
- bline_t *li1, *li2;
- /* id chains_i; */
- STORAGE *chains_i;
- bchain_t bch;
- int cx, cy;
-
- #ifdef _STEVE_FIX_
- used = malloc (numblines*sizeof (*used));
- memset (used,0,numblines*sizeof (*used));
- temppoints = malloc (numblines*sizeof (*temppoints));
- #else
- used = alloca (numblines*sizeof (*used));
- memset (used,0,numblines*sizeof (*used));
- temppoints = alloca (numblines*sizeof (*temppoints));
- #endif
-
- /*
- chains_i = [[Storage alloc]
- initCount: 0
- elementSize: sizeof(bchain_t)
- description: NULL];
- */
- chains_i = (STORAGE *)SafeMalloc(sizeof(STORAGE));
- chains_i->data = (bchain_t *)SafeMalloc(sizeof(bchain_t));
- chains_i->count = 0;
- chains_i->size = sizeof(bchain_t);
-
- printf("\n");
- li1 = blines;
- for (i=0 ; i<numblines ; i++, li1++)
- {
- printf("bline #%d of %d\r",i,numblines);
- if (used[i])
- continue;
- used[i] = true;
-
- /* start a new chain */
- pt_p = temppoints;
- pt_p->x = li1->p1.x;
- pt_p->y = li1->p1.y;
- pt_p++;
- pt_p->x = cx = li1->p2.x;
- pt_p->y = cy = li1->p2.y;
- pt_p++;
-
- ClearBBox (&bch.bounds);
- AddToBBox (&bch.bounds, li1->p1.x, li1->p1.y);
- AddToBBox (&bch.bounds, cx, cy);
-
- /* look for connected lines */
- do
- {
- li2 = li1+1;
- for (j=i+1 ; j<numblines ; j++,li2++)
- if (!used[j] && li2->p1.x == cx && li2->p1.y == cy)
- break;
-
- if (j==numblines)
- break; /* no more lines in chain */
-
- /* add to chain */
- used[j] = true;
- pt_p->x = cx = li2->p2.x;
- pt_p->y = cy = li2->p2.y;
- pt_p++;
- AddToBBox (&bch.bounds, cx, cy);
- } while (1);
-
- /* save the block chain */
- bch.numpoints = pt_p - temppoints;
- bch.points = (bpoint_t *)malloc (bch.numpoints*sizeof(*bch.points));
- memcpy (bch.points, temppoints, bch.numpoints*sizeof(*bch.points));
- /* [chains_i addElement: &bch]; */
- memcpy((bchain_t *)chains_i->data + chains_i->count, &bch, sizeof(bchain_t));
- chains_i->count += 1;
- chains_i->data = (bchain_t *)realloc(chains_i->data,
- sizeof(bchain_t) * (chains_i->count + 1));
- /*DrawBChain (&bch); */
- }
-
- /*
- numbchains = [chains_i count];
- bchains = [chains_i elementAt:0];
- */
- numbchains = chains_i->count;
- bchains = chains_i->data;
-
- #ifdef _STEVE_FIX_
- free(used);
- free(temppoints);
- #endif
- }
-
-
- /*
- ====================
- =
- = ProcessConnections
- =
- ====================
- */
-
- void ProcessConnections (void)
- {
- int i, s, wlcount, count;
- bbox_t *secbox;
- /* id lines; */
- STORAGE *lines;
- worldline_t *wl;
- mapvertex_t *vt;
- maplinedef_t *p;
- mapsidedef_t *sd;
- bline_t bline;
- int sec;
- int RonsLines=0;
-
- /*
- numsectors = [secstore_i count];
- wlcount = [linestore_i count];
- */
-
- numsectors = secstore_i->count;
- wlcount = linestore_i->count;
-
- connections = (unsigned char *)malloc (numsectors*numsectors+8); /* allow rounding to bytes */
- memset (connections, 0, numsectors*numsectors);
-
- secboxes = secbox = (bbox_t *)malloc (numsectors*sizeof(bbox_t));
- for (i=0 ; i<numsectors ; i++, secbox++)
- ClearBBox (secbox);
-
- /*
- calculate bounding boxes for all sectors
-
- count = [ldefstore_i count];
- p = [ldefstore_i elementAt:0];
- vt = [mapvertexstore_i elementAt:0];
- */
-
- count = ldefstore_i->count;
- p = ldefstore_i->data;
- vt = mapvertexstore_i->data;
- printf("\n");
- for (i=0 ; i<count ; i++, p++)
- {
- printf("BBox #%d of %d\r",i,count);
- for (s=0 ; s<1 ; s++)
- {
- if (p->sidenum[s] == -1)
- continue; /* no back side */
- /* add both points to sector bounding box */
- /* sd = (mapsidedef_t *)[sdefstore_i elementAt: p->sidenum[s]]; */
- sd = (mapsidedef_t *)sdefstore_i->data + p->sidenum[s];
- sec = sd->sector;
- AddToBBox (&secboxes[sec], vt[p->v1].x, vt[p->v1].y);
- AddToBBox (&secboxes[sec], vt[p->v2].x, vt[p->v2].y);
- }
- }
-
- /*
- make a list of only the solid lines
- */
- /*
- lines = [[Storage alloc]
- initCount: 0
- elementSize: sizeof(bline)
- description: NULL];
- */
- /*
- lines = SafeMalloc(sizeof(STORAGE));
- lines->data = SafeMalloc(sizeof(bline));
- lines->count = 0;
- lines->size = sizeof(bline);
- */
-
- /* wl = [linestore_i elementAt: 0]; */
- printf("\n");
- wl = linestore_i->data;
- for (i=0; i<wlcount; wl++,i++)
- {
- if (wl->flags & ML_TWOSIDED)
- continue;
- RonsLines++;
- }
-
- lines = (STORAGE *)SafeMalloc(sizeof(STORAGE));
- lines->data = (bline_t *)SafeCalloc(RonsLines,sizeof(bline));
- lines->count = 0;
- lines->size = sizeof(bline);
-
- wl = linestore_i->data;
- for ( i=0 ; i<wlcount ; wl++,i++)
- {
- printf("Line #%d of %d\r",i,wlcount);
- if (wl->flags & ML_TWOSIDED)
- continue; /* don't add two sided lines */
- bline.p1.x = wl->p1.x;
- bline.p1.y = wl->p1.y;
- bline.p2.x = wl->p2.x;
- bline.p2.y = wl->p2.y;
- /* [lines addElement: &bline]; */
- memcpy((bline_t *)lines->data + lines->count, &bline, sizeof(bline));
- lines->count += 1;
- /*
- lines->data = (bline_t *)realloc(lines->data,
- sizeof(bline_t) + (lines->count + 1));
- */
- }
-
- /*
- blines = [lines elementAt: 0];
- numblines = [lines count];
- */
-
- blines = lines->data;
- numblines = lines->count;
-
- /*
- build blocking chains
- */
- printf("\nBuildBlockingChains\n");
- BuildBlockingChains ();
-
- /*
- build connection list
- */
- printf("\nBuildConnections\n");
- BuildConnections ();
- }
-
-
- /*
- =================
- =
- = OutputConnections
- =
- =================
- */
-
- void OutputConnections (void)
- {
- int i;
- int bytes;
- char *cons;
- char *bits;
-
- cons = connections;
- bytes = (numsectors*numsectors+7)/8;
- bits = (char *)malloc(bytes);
-
- for (i=0 ; i<bytes ; i++)
- {
- bits[i] = cons[0] + (cons[1]<<1) + (cons[2]<<2) + (cons[3]<<3) + (cons[4]<<4) + (cons[5]<<5) + (cons[6]<<6) + (cons[7]<<7);
- cons +=8;
- }
-
- /* [wad_i addName: "reject" data:bits size:bytes]; */
- addName("reject", bits, bytes);
- printf ("reject: %i\n",bytes);
- }