Sector-like sprite clipping. Check samples/spriteclip.txt.

git-svn-id: https://svn.eduke32.com/eduke32@1719 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2010-10-28 20:17:22 +00:00
parent 47be9ff8ce
commit f1caa980d0
7 changed files with 806 additions and 25 deletions

View file

@ -439,6 +439,7 @@ void uninitengine(void);
void initspritelists(void);
int32_t loadboard(char *filename, char fromwhere, int32_t *daposx, int32_t *daposy, int32_t *daposz, int16_t *daang, int16_t *dacursectnum);
int32_t loadmaphack(char *filename);
int32_t clipmapinfo_load(char *filename);
int32_t saveboard(char *filename, int32_t *daposx, int32_t *daposy, int32_t *daposz, int16_t *daang, int16_t *dacursectnum);
int32_t loadpics(char *filename, int32_t askedsize);
void loadtile(int16_t tilenume);

View file

@ -444,6 +444,12 @@ int32_t app_main(int32_t argc, const char **argv)
if (j > k) { k = j; whitecol = i; }
}
k = clipmapinfo_load("_clipshape_.map");
if (k==0)
initprintf("Loaded sprite clipping map from \"_clipshape_.map\"\n");
else if (k>0)
initprintf("There was an error loading the sprite clipping map from \"_clipshape_.map\" (status %d).\n", k);
for (i=0; i<MAXSECTORS; i++) sector[i].extra = -1;
for (i=0; i<MAXWALLS; i++) wall[i].extra = -1;
for (i=0; i<MAXSPRITES; i++) sprite[i].extra = -1;
@ -6638,8 +6644,8 @@ void test_map(int32_t mode)
if (current_cwd[0] != '\0')
{
chdir(program_origcwd);
system(fullparam);
// message("Error launching the game!");
if (system(fullparam))
message("Error launching the game!");
chdir(current_cwd);
}
else system(fullparam);

View file

@ -166,6 +166,365 @@ qlz_state_decompress *state_decompress = NULL;
int32_t whitecol;
////// sector-like clipping for sprites //////
typedef struct
{
int16_t numsectors, numwalls;
sectortype *sector;
walltype *wall;
} mapinfo_t;
static void mapinfo_set(mapinfo_t *bak, mapinfo_t *new)
{
if (bak)
{
bak->numsectors = numsectors;
bak->numwalls = numwalls;
bak->sector = sector;
bak->wall = wall;
}
if (new)
{
numsectors = new->numsectors;
numwalls = new->numwalls;
sector = new->sector;
wall = new->wall;
}
}
static mapinfo_t origmapinfo, clipmapinfo;
static int32_t quickloadboard=0;
#define CM_MAX 256 // must be a power of 2
typedef struct
{
int16_t qbeg, qend; // indices into sectq
int16_t picnum, next;
int32_t maxdist;
} clipinfo_t;
static int32_t numclipmaps;
static clipinfo_t clipinfo[CM_MAX];
static int32_t numclipsects; // number in sectq[]
static int16_t *sectoidx, *sectq; // [numsectors]
static int16_t pictoidx[MAXTILES]; // maps tile num to clipinfo[] index
static int16_t *tempictoidx;
// sectoidx bits
#define CM_NONE (CM_MAX<<1)
#define CM_SOME (CM_NONE-1)
#define CM_OUTER (CM_MAX) // sector surrounds clipping sector
// offset x and y of clipping sectors by this much
// so that we avoid problems with inside() etc. later
#define CM_OFS (1<<20)
// sprite -> sector tag mappings
#define CM_XREPEAT floorpal
#define CM_YREPEAT floorxpanning
#define CM_XOFFSET ceilingshade
#define CM_YOFFSET floorshade
#define CM_CSTAT hitag
#define CM_ANG extra
#define CM_FLOORZ(Sec) (*(int32_t *)&sector[Sec].ceilingxpanning) // ceilingxpanning,ceilingypanning,floorpicnum
#define CM_CEILINGZ(Sec) (*(int32_t *)&sector[Sec].visibility) // visibility,filler,lotag
// backup of original normalized coordinates
#define CM_WALL_X(Wal) (*(int32_t *)&wall[Wal].picnum)
#define CM_WALL_Y(Wal) (*(int32_t *)&wall[Wal].lotag)
// don't rotate when applying clipping, for models with rotational symmetry
#define CM_NOROT(Spri) (sprite[Spri].cstat&2)
#define CM_NOROTS(Sect) (sector[Sect].CM_CSTAT&2)
static void clipmapinfo_init()
{
int32_t i;
if (clipmapinfo.sector) { Bfree(clipmapinfo.sector); clipmapinfo.sector=NULL; }
if (clipmapinfo.wall) { Bfree(clipmapinfo.wall); clipmapinfo.wall=NULL; }
clipmapinfo.numsectors = clipmapinfo.numwalls = 0;
numclipmaps = 0;
numclipsects = 0;
if (sectq) { Bfree(sectq); sectq=NULL; }
if (sectoidx) { Bfree(sectoidx); sectoidx=NULL; }
if (tempictoidx) { Bfree(tempictoidx); tempictoidx=NULL; }
for (i=0; i<MAXTILES; i++)
pictoidx[i]=-1;
}
int32_t clipmapinfo_load(char *filename)
{
int32_t i,k,w, px,py,pz;
int16_t ang,cs;
clipmapinfo_init();
quickloadboard = 1;
i = loadboard(filename, 0, &px,&py,&pz, &ang,&cs);
quickloadboard = 0;
if (i<0)
return i;
sectoidx = Bmalloc(numsectors*sizeof(sectoidx[0]));
if (!sectoidx)
{
clipmapinfo_init();
return 1;
}
for (i=0; i<numsectors; i++)
sectoidx[i] = CM_NONE;
// determine outer sectors
for (i=0; i<numsectors; i++)
{
for (w=sector[i].wallptr; w<sector[i].wallptr+sector[i].wallnum; w++)
if (wall[w].nextsector<0)
{
sectoidx[i] = CM_OUTER;
break;
}
}
// break connections between outer sectors
for (i=0; i<numsectors; i++)
{
if (sectoidx[i] == CM_OUTER)
for (w=sector[i].wallptr; w<sector[i].wallptr+sector[i].wallnum; w++)
{
k = wall[w].nextwall;
if (k>=0 && sectoidx[wall[w].nextsector]==CM_OUTER)
{
wall[k].nextwall = wall[k].nextsector = -1;
wall[w].nextwall = wall[w].nextsector = -1;
}
}
}
{
int16_t ns, outersect;
int32_t pn,scnt, x,y,z, maxdist;
sectq = Bmalloc(numsectors*sizeof(sectq[0]));
tempictoidx = Bmalloc(MAXTILES*sizeof(tempictoidx[0]));
if (!sectq || !tempictoidx)
{
clipmapinfo_init();
return 1;
}
for (i=0; i<MAXTILES; i++)
tempictoidx[i]=-1;
// collect sprite picnums
for (i=0; i<MAXSPRITES && sprite[i].statnum<MAXSTATUS; i++)
{
pn = sprite[i].picnum;
k = sprite[i].sectnum;
// -v- note the <= ignore sprites in outer sectors
if (pn<=0 || pn>=MAXTILES || k<0 || k>=numsectors || (sectoidx[k]&CM_OUTER))
continue;
// chain
if (pictoidx[pn]>=0)
{
if (sectoidx[k]&CM_SOME)
{
initprintf("clip map: error: tried to chain picnum %d (sprite %d) in sector %d which"
" already belongs to picnum %d.\n", pn, i, k, clipinfo[sectoidx[k]].picnum);
clipmapinfo_init();
return 2;
}
// new one is front
clipinfo[numclipmaps].next = pictoidx[pn];
pictoidx[pn] = numclipmaps;
}
else
{
clipinfo[numclipmaps].next = -1;
pictoidx[pn] = numclipmaps;
}
if (!CM_NOROT(i))
{
if (sprite[i].ang!=1536 && sprite[i].ang!=512)
{
initprintf("clip map: warning: sprite %d pointing neither northward nor southward. %s"
" will be wrong.", i, (sprite[i].cstat&48)==32 ? "Scaling and flipping" : "X-flipping");
}
}
clipinfo[numclipmaps].picnum = pn;
// collect sectors
scnt = numclipsects;
sectq[numclipsects++] = k;
sectoidx[k] = numclipmaps;
clipinfo[numclipmaps].qbeg = scnt;
outersect = -1;
do
{
k = sectq[scnt];
for (w=sector[k].wallptr; w<sector[k].wallptr+sector[k].wallnum; w++)
{
ns = wall[w].nextsector;
if (ns>=0)
{
if (sectoidx[ns]==CM_NONE)
{
sectoidx[ns] = numclipmaps;
sectq[numclipsects++] = ns;
}
else if (sectoidx[ns]&CM_OUTER)
{
if (outersect>=0 && ns!=outersect)
{
initprintf("clip map: error: encountered more than one outer sector"
" (%d and %d) for sprite %d.\n", outersect, ns, i);
clipmapinfo_init();
return 3;
}
outersect = ns;
sectoidx[outersect] |= numclipmaps;
}
else if (sectoidx[ns]!=numclipmaps)
{
initprintf("clip map: error: encountered sector %d belonging to index %d"
" while collecting sectors for sprite %d (index %d).\n",
ns, sectoidx[ns], i, numclipmaps);
clipmapinfo_init();
return 4;
}
}
}
} while (++scnt < numclipsects);
sectq[numclipsects++] = outersect; // last is outer
clipinfo[numclipmaps].qend = numclipsects-1;
// normalize
maxdist = 0;
for (scnt=clipinfo[numclipmaps].qbeg; scnt<=clipinfo[numclipmaps].qend; scnt++)
{
k = sectq[scnt];
sector[k].floorz -= z;
sector[k].ceilingz -= z;
x = sprite[i].x;
y = sprite[i].y;
z = sprite[i].z;
if (scnt==clipinfo[numclipmaps].qbeg)
{
// backup sprite tags since we'll discard sprites later
sector[k].CM_XREPEAT = sprite[i].xrepeat;
sector[k].CM_YREPEAT = sprite[i].yrepeat;
sector[k].CM_XOFFSET = sprite[i].xoffset;
sector[k].CM_YOFFSET = sprite[i].yoffset;
sector[k].CM_CSTAT = sprite[i].cstat;
sector[k].CM_ANG = sprite[i].ang;
}
// backup floor and ceiling z
CM_FLOORZ(k) = sector[k].floorz;
CM_CEILINGZ(k) = sector[k].ceilingz;
for (w=sector[k].wallptr; w<sector[k].wallptr+sector[k].wallnum; w++)
{
wall[w].x -= x;
wall[w].y -= y;
if (scnt!=clipinfo[numclipmaps].qend)
{
if (CM_NOROT(i))
{
if (klabs(wall[w].x) > maxdist)
maxdist = klabs(wall[w].x);
if (klabs(wall[w].y) > maxdist)
maxdist = klabs(wall[w].y);
}
else
{
int32_t tmp = ksqrt(wall[w].x*wall[w].x + wall[w].y*wall[w].y);
if (tmp > maxdist)
maxdist = tmp;
}
}
// aliasing
if (wall[w].lotag>0 || wall[w].hitag>0)
{
int32_t ii;
if (wall[w].lotag>0 && wall[w].hitag>0)
{
if (wall[w].lotag > wall[w].hitag)
swapshort(&wall[w].lotag, &wall[w].hitag);
for (ii=wall[w].lotag; ii<MAXTILES; ii++)
tempictoidx[ii] = numclipmaps;
}
else if (wall[w].lotag>0)
{
if (wall[w].lotag<MAXTILES)
tempictoidx[wall[w].lotag] = numclipmaps;
}
else
{
if (wall[w].hitag<MAXTILES)
tempictoidx[wall[w].hitag] = numclipmaps;
}
}
CM_WALL_X(w) = wall[w].x;
CM_WALL_Y(w) = wall[w].y;
wall[w].x += CM_OFS;
wall[w].y += CM_OFS;
}
}
clipinfo[numclipmaps].maxdist = maxdist;
numclipmaps++;
}
}
clipmapinfo.numsectors = numsectors;
clipmapinfo.sector = Bmalloc(numsectors * sizeof(sectortype));
Bmemcpy(clipmapinfo.sector, sector, numsectors*sizeof(sectortype));
clipmapinfo.numwalls = numwalls;
clipmapinfo.wall = Bmalloc(numwalls * sizeof(walltype));
Bmemcpy(clipmapinfo.wall, wall, numwalls*sizeof(walltype));
for (i=0; i<MAXTILES; i++)
{
if (pictoidx[i]==-1 && tempictoidx[i]>=0)
pictoidx[i]=tempictoidx[i];
}
Bfree(tempictoidx);
return 0;
}
////// //////
#if defined(_MSC_VER) && !defined(NOASM)
//
@ -531,7 +890,8 @@ int32_t hitallsprites = 0;
typedef struct { int32_t x1, y1, x2, y2; } linetype;
static linetype clipit[MAXCLIPNUM];
static int16_t clipsectorlist[MAXCLIPNUM], clipsectnum;
static int16_t clipsectorlist[MAXCLIPNUM], clipsectnum, origclipsectorlist[MAXCLIPNUM], origclipsectnum;
static int16_t clipspritelist[MAXCLIPNUM], clipspritenum; // sector-like sprite clipping
static int16_t clipobjectval[MAXCLIPNUM];
typedef struct
@ -5615,6 +5975,8 @@ int32_t preinitengine(void)
initcrc32table();
clipmapinfo_init();
preinitcalled = 1;
return 0;
}
@ -6751,6 +7113,8 @@ int32_t loadboard(char *filename, char fromwhere, int32_t *daposx, int32_t *dapo
kclose(fil);
if (!quickloadboard)
{
Bmemset(spriteext, 0, sizeof(spriteext_t) * MAXSPRITES);
#if defined(POLYMOST) && defined(USE_OPENGL)
@ -6763,6 +7127,7 @@ int32_t loadboard(char *filename, char fromwhere, int32_t *daposx, int32_t *dapo
polymer_loadboard();
#endif
#endif
}
guniqhudid = 0;
startposx = *daposx;
@ -7881,6 +8246,7 @@ int32_t loadpics(char *filename, int32_t askedsize)
artfilename[7] = (k%10)+48;
artfilename[6] = ((k/10)%10)+48;
artfilename[5] = ((k/100)%10)+48;
if ((fil = kopen4load(artfilename,0)) != -1)
{
kread(fil,&artversion,4); artversion = B_LITTLE32(artversion);
@ -8914,6 +9280,129 @@ int32_t lastwall(int16_t point)
}
//////////
static int32_t clipsprite_try(spritetype *spr, int32_t xmin, int32_t ymin, int32_t xmax, int32_t ymax)
{
int32_t i,k,tempint1,tempint2;
// try and see whether this sprite's picnum has sector-like clipping data
i = pictoidx[spr->picnum];
// handle sector-like floor sprites separately
while (i>=0 && (spr->cstat&32) != (clipmapinfo.sector[sectq[clipinfo[i].qbeg]].CM_CSTAT&32))
i = clipinfo[i].next;
if (i>=0)
{
int32_t maxcorrection = clipinfo[i].maxdist;
k = sectq[clipinfo[i].qbeg];
if ((spr->cstat&48)!=32) // face/wall sprite
{
tempint1 = clipmapinfo.sector[k].CM_XREPEAT;
maxcorrection = (maxcorrection * (int32_t)spr->xrepeat)/tempint1;
}
else // floor sprite
{
tempint1 = clipmapinfo.sector[k].CM_XREPEAT;
tempint2 = clipmapinfo.sector[k].CM_YREPEAT;
maxcorrection = max((maxcorrection * (int32_t)spr->xrepeat)/tempint1,
(maxcorrection * (int32_t)spr->yrepeat)/tempint2);
}
maxcorrection -= MAXCLIPDIST;
if (spr->x < xmin - maxcorrection) return 1;
if (spr->y < ymin - maxcorrection) return 1;
if (spr->x > xmax + maxcorrection) return 1;
if (spr->y > ymax + maxcorrection) return 1;
if (clipspritenum < MAXCLIPNUM)
clipspritelist[clipspritenum++] = spr-sprite;
//initprintf("%d: clip sprite[%d]\n",clipspritenum,j);
return 1;
}
return 0;
}
// return: -1 if curspr has x-flip xor y-flip (in the horizontal map plane!), 1 else
static int32_t clipsprite_initindex(int32_t curidx, spritetype *curspr, int32_t *clipsectcnt, const vec3_t *vect)
{
int32_t j,k,w,tempint1,tempint2,daz = curspr->z;
int32_t scalex,scaley,scalez,flipx,flipy,rotang, dorot;
int32_t startwall, endwall, flipmul=1;
sectortype *sec;
walltype *wal;
j = sectq[clipinfo[curidx].qbeg];
tempint1 = sector[j].CM_XREPEAT;
tempint2 = sector[j].CM_YREPEAT;
if ((curspr->cstat&48)!=32) // face/wall sprite
{
scalex = scaley = divscale22(curspr->xrepeat, tempint1);
scalez = divscale22(curspr->yrepeat, tempint2);
flipx = 1-((curspr->cstat&4)>>1);
flipy = 1;
}
else
{
scalex = divscale22(curspr->xrepeat, tempint1);
scaley = divscale22(curspr->yrepeat, tempint2);
scalez = scalex;
flipx = 1-((curspr->cstat&4)>>1);
flipy = 1-((curspr->cstat&8)>>2);
}
rotang = (curspr->ang - sector[j].CM_ANG)&2047;
dorot = !CM_NOROTS(j);
if (dorot)
flipmul = flipx*flipy;
if ((curspr->cstat&128) != (sector[j].CM_CSTAT&128))
daz += (((curspr->cstat&128)>>6)-1)*(((int32_t)tilesizy[curspr->picnum]*(int32_t)curspr->yrepeat)<<1);
*clipsectcnt = clipsectnum = 0;
// init sectors for this index
for (k=clipinfo[curidx].qbeg; k<=clipinfo[curidx].qend; k++)
{
j = sectq[k];
sec = &sector[j];
sec->floorz = daz + mulscale22(scalez, CM_FLOORZ(j));
sec->ceilingz = daz + mulscale22(scalez, CM_CEILINGZ(j));
//initprintf("sec %d: f=%d, c=%d\n", j, sec->floorz, sec->ceilingz);
startwall=sec->wallptr; endwall=startwall+sec->wallnum;
for (w=startwall,wal=&wall[startwall]; w<endwall; w++,wal++)
{
wal->x = mulscale22(scalex, CM_WALL_X(w));
wal->y = mulscale22(scaley, CM_WALL_Y(w));
if (dorot)
{
wal->x *= flipx;
wal->y *= flipy;
rotatepoint(0,0, wal->x,wal->y, rotang, &wal->x,&wal->y);
}
wal->x += curspr->x;
wal->y += curspr->y;
if (flipmul==-1)
wal->x = vect->x - (wal->x-vect->x);
}
if (inside(vect->x, vect->y, j)==1)
clipsectorlist[clipsectnum++] = j;
}
if (clipsectnum==0)
clipsectorlist[clipsectnum++] = sectq[k-1];
return flipmul;
}
#define addclipline(dax1, day1, dax2, day2, daoval) \
{ \
@ -8922,7 +9411,7 @@ int32_t lastwall(int16_t point)
clipit[clipnum].x2 = dax2; clipit[clipnum].y2 = day2; \
clipobjectval[clipnum] = daoval; \
clipnum++; \
} \
} else if (!warned) { initprintf("!!clipnum\n"); warned=1; } \
} \
int32_t clipmoveboxtracenum = 3;
@ -8945,6 +9434,9 @@ int32_t clipmove(vec3_t *vect, int16_t *sectnum,
int32_t xrepeat, yrepeat, gx, gy, dx, dy, dasprclipmask, dawalclipmask;
int32_t hitwall, cnt, clipyou;
spritetype *curspr=NULL; // non-NULL when handling sprite with sector-like clipping
int32_t curidx=-1, warned=0, clipspritecnt, mulxdir=1;
if (((xvect|yvect) == 0) || (*sectnum < 0)) return(0);
retval = 0;
@ -8970,8 +9462,44 @@ int32_t clipmove(vec3_t *vect, int16_t *sectnum,
clipsectorlist[0] = (*sectnum);
clipsectcnt = 0; clipsectnum = 1;
clipspritecnt = 0; clipspritenum = 0;
do
{
if (clipsectcnt>=clipsectnum)
{
// one bunch of sectors completed (either the very first
// one or a sector-like sprite one), prepare the next
//initprintf("init sprite %d\n", clipspritecnt);
if (!curspr)
{
// init sector-like sprites for clipping
origclipsectnum = clipsectnum;
Bmemcpy(origclipsectorlist, clipsectorlist, clipsectnum*sizeof(clipsectorlist[0]));
// replace sector and wall with clip map
mapinfo_set(&origmapinfo, &clipmapinfo);
}
curspr = &sprite[clipspritelist[clipspritecnt]];
if (curidx < 0) // per-sprite init
curidx = pictoidx[curspr->picnum];
else
curidx = clipinfo[curidx].next;
while (curidx>=0 && (curspr->cstat&32) != (sector[sectq[clipinfo[curidx].qbeg]].CM_CSTAT&32))
curidx = clipinfo[curidx].next;
if (curidx < 0)
{
clipspritecnt++;
continue;
}
mulxdir = clipsprite_initindex(curidx, curspr, &clipsectcnt, vect);
}
dasect = clipsectorlist[clipsectcnt++];
sec = &sector[dasect];
startwall = sec->wallptr; endwall = startwall + sec->wallnum;
@ -8993,7 +9521,36 @@ int32_t clipmove(vec3_t *vect, int16_t *sectnum,
if (dax >= day) continue;
clipyou = 0;
if ((wal->nextsector < 0) || (wal->cstat&dawalclipmask)) clipyou = 1;
if (curspr)
{
if (wal->nextsector>=0)
{
int32_t basez;
if (rintersect(vect->x,vect->y,0, gx*mulxdir,gy,0, x1,y1, x2,y2, &dax,&day,&daz) == 0)
dax = vect->x, day = vect->y;
daz = getflorzofslope((int16_t)dasect,dax,day);
daz2 = getflorzofslope(wal->nextsector,dax,day);
basez = getflorzofslope(sectq[clipinfo[curidx].qend],dax,day);
sec2 = &sector[wal->nextsector];
if ((sec2->floorstat&1) == 0)
// if (dasect==sectq[clipinfo[curidx].qend] || daz2 < daz-(1<<8))
if (vect->z <= basez+(flordist-1))
if (vect->z >= daz2-(flordist-1)) clipyou = 1;
if (clipyou == 0)
{
daz = getceilzofslope((int16_t)dasect,dax,day);
daz2 = getceilzofslope(wal->nextsector,dax,day);
basez = getceilzofslope(clipsectorlist[clipsectnum-1],dax,day);
if ((sec2->ceilingstat&1) == 0)
// if (dasect==sectq[clipinfo[curidx].qend] || daz2 > daz+(1<<8))
if (vect->z >= basez-(ceildist-1))
if (vect->z <= daz2+(ceildist-1)) clipyou = 1;
}
}
}
else if ((wal->nextsector < 0) || (wal->cstat&dawalclipmask)) clipyou = 1;
else if (editstatus == 0)
{
if (rintersect(vect->x,vect->y,0,gx,gy,0,x1,y1,x2,y2,&dax,&day,&daz) == 0)
@ -9017,17 +9574,33 @@ int32_t clipmove(vec3_t *vect, int16_t *sectnum,
if (clipyou)
{
int16_t objtype;
if (!curspr)
objtype = (int16_t)j+32768;
else
{
objtype = (int16_t)(curspr-sprite)+49152;
if (mulxdir==-1)
{
x1 = vect->x - (x1-vect->x);
x2 = vect->x - (x2-vect->x);
swaplong(&x1,&x2);
swaplong(&y1,&y2);
dx *= -1;
}
}
//Add 2 boxes at endpoints
bsz = walldist; if (gx < 0) bsz = -bsz;
addclipline(x1-bsz,y1-bsz,x1-bsz,y1+bsz,(int16_t)j+32768);
addclipline(x2-bsz,y2-bsz,x2-bsz,y2+bsz,(int16_t)j+32768);
bsz = walldist; if (gx*mulxdir < 0) bsz = -bsz;
addclipline(x1-bsz,y1-bsz,x1-bsz,y1+bsz,objtype);
addclipline(x2-bsz,y2-bsz,x2-bsz,y2+bsz,objtype);
bsz = walldist; if (gy < 0) bsz = -bsz;
addclipline(x1+bsz,y1-bsz,x1-bsz,y1-bsz,(int16_t)j+32768);
addclipline(x2+bsz,y2-bsz,x2-bsz,y2-bsz,(int16_t)j+32768);
addclipline(x1+bsz,y1-bsz,x1-bsz,y1-bsz,objtype);
addclipline(x2+bsz,y2-bsz,x2-bsz,y2-bsz,objtype);
dax = walldist; if (dy > 0) dax = -dax;
day = walldist; if (dx < 0) day = -day;
addclipline(x1+dax,y1+day,x2+dax,y2+day,(int16_t)j+32768);
addclipline(x1+dax,y1+day,x2+dax,y2+day,objtype);
}
else
{
@ -9037,12 +9610,20 @@ int32_t clipmove(vec3_t *vect, int16_t *sectnum,
}
}
if (curspr)
continue; // next sector of this index
for (j=headspritesect[dasect]; j>=0; j=nextspritesect[j])
{
spr = &sprite[j];
cstat = spr->cstat;
if ((cstat&dasprclipmask) == 0) continue;
if (clipsprite_try(spr, xmin,ymin, xmax,ymax))
continue;
x1 = spr->x; y1 = spr->y;
switch (cstat&48)
{
case 0:
@ -9158,9 +9739,19 @@ int32_t clipmove(vec3_t *vect, int16_t *sectnum,
break;
}
}
//if (clipspritenum)
// initprintf("sect %d/%d sprite %d/%d\n", clipsectcnt,clipsectnum, clipspritecnt,clipspritenum);
}
while (clipsectcnt < clipsectnum);
while (clipsectcnt < clipsectnum || clipspritecnt < clipspritenum);
if (curspr)
{
// restore original map
mapinfo_set(NULL, &origmapinfo);
clipsectnum = origclipsectnum;
Bmemcpy(clipsectorlist, origclipsectorlist, clipsectnum*sizeof(clipsectorlist[0]));
}
hitwall = 0;
cnt = clipmoveboxtracenum;
@ -9586,6 +10177,9 @@ void getzrange(const vec3_t *vect, int16_t sectnum,
char clipyou;
spritetype *curspr=NULL; // non-NULL when handling sprite with sector-like clipping
int32_t curidx=-1, clipspritecnt;
if (sectnum < 0)
{
*ceilz = 0x80000000; *ceilhit = -1;
@ -9606,9 +10200,64 @@ void getzrange(const vec3_t *vect, int16_t sectnum,
clipsectorlist[0] = sectnum;
clipsectcnt = 0; clipsectnum = 1;
clipspritecnt = clipspritenum = 0;
if (0)
{
beginagain:
// replace sector and wall with clip map
mapinfo_set(&origmapinfo, &clipmapinfo);
clipsectcnt = clipsectnum; // should be a nop, "safety"...
}
do //Collect sectors inside your square first
{
if (clipsectcnt>=clipsectnum)
{
// one bunch of sectors completed, prepare the next
curspr = &sprite[clipspritelist[clipspritecnt]];
if (curidx < 0) // per-sprite init
curidx = pictoidx[curspr->picnum];
else
curidx = clipinfo[curidx].next;
while (curidx>=0 && (curspr->cstat&32) != (sector[sectq[clipinfo[curidx].qbeg]].CM_CSTAT&32))
curidx = clipinfo[curidx].next;
if (curidx < 0)
{
clipspritecnt++;
continue;
}
clipsprite_initindex(curidx, curspr, &clipsectcnt, vect);
for (i=0; i<clipsectnum; i++)
{
int32_t fz,cz;
k = clipsectorlist[i];
if (k==sectq[clipinfo[curidx].qend])
continue;
getzsofslope((int16_t)k,vect->x,vect->y,&daz,&daz2);
getzsofslope(sectq[clipinfo[curidx].qend],vect->x,vect->y,&cz,&fz);
if ((sector[k].ceilingstat&1)==0)
{
if (vect->z < cz && cz < *florz) { *florz = cz; *florhit = (curspr-sprite)+49152; }
if (vect->z > daz && daz > *ceilz) { *ceilz = daz; *ceilhit = (curspr-sprite)+49152; }
}
if ((sector[k].floorstat&1)==0)
{
if (vect->z < daz2 && daz2 < *florz) { *florz = daz2; *florhit = (curspr-sprite)+49152; }
if (vect->z > fz && fz > *ceilz) { *ceilz = fz; *ceilhit = (curspr-sprite)+49152; }
}
}
}
sec = &sector[clipsectorlist[clipsectcnt]];
startwall = sec->wallptr; endwall = startwall + sec->wallnum;
for (j=startwall,wal=&wall[startwall]; j<endwall; j++,wal++)
@ -9632,7 +10281,15 @@ void getzrange(const vec3_t *vect, int16_t sectnum,
if (wal->cstat&dawalclipmask) continue;
sec = &sector[k];
if (editstatus == 0)
if (curspr)
{
if (k==sectq[clipinfo[curidx].qend])
continue;
if ((sec->ceilingstat&1) && (sec->floorstat&1))
continue;
}
else if (editstatus == 0)
{
if (((sec->ceilingstat&1) == 0) && (vect->z <= sec->ceilingz+(3<<8))) continue;
if (((sec->floorstat&1) == 0) && (vect->z >= sec->floorz-(3<<8))) continue;
@ -9651,13 +10308,38 @@ void getzrange(const vec3_t *vect, int16_t sectnum,
//It actually got here, through all the continue's!!!
getzsofslope((int16_t)k,vect->x,vect->y,&daz,&daz2);
if (curspr)
{
int32_t fz,cz;
getzsofslope(sectq[clipinfo[curidx].qend],vect->x,vect->y,&cz,&fz);
if ((sec->ceilingstat&1)==0)
{
if (vect->z < cz && cz < *florz) { *florz = cz; *florhit = (curspr-sprite)+49152; }
if (vect->z > daz && daz > *ceilz) { *ceilz = daz; *ceilhit = (curspr-sprite)+49152; }
}
if ((sec->floorstat&1)==0)
{
if (vect->z < daz2 && daz2 < *florz) { *florz = daz2; *florhit = (curspr-sprite)+49152; }
if (vect->z > fz && fz > *ceilz) { *ceilz = fz; *ceilhit = (curspr-sprite)+49152; }
}
}
else
{
if (daz > *ceilz) { *ceilz = daz; *ceilhit = k+16384; }
if (daz2 < *florz) { *florz = daz2; *florhit = k+16384; }
}
}
}
clipsectcnt++;
}
while (clipsectcnt < clipsectnum);
while (clipsectcnt < clipsectnum || clipspritecnt < clipspritenum);
if (curspr)
{
mapinfo_set(NULL, &origmapinfo); // restore original map
return;
}
for (i=0; i<clipsectnum; i++)
{
@ -9667,6 +10349,9 @@ void getzrange(const vec3_t *vect, int16_t sectnum,
cstat = spr->cstat;
if (cstat&dasprclipmask)
{
if (clipsprite_try(spr, xmin,ymin, xmax,ymax))
continue;
x1 = spr->x; y1 = spr->y;
clipyou = 0;
@ -9765,6 +10450,9 @@ void getzrange(const vec3_t *vect, int16_t sectnum,
}
}
}
if (clipspritenum>0)
goto beginagain;
}
void setaspect_new()

Binary file not shown.

View file

@ -0,0 +1,63 @@
Sector-like clipping for sprites
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sprite picnums can be assigned to a bunch of connected sectors so that
clipping against these sprites will work as if it is carried out on the
associated sectors. For this, a file named _clipshape_.map must be present
at program start time that must be built to certain rules:
* Every sector that contains at least one white wall is considered an "outer" sector.
Conversely, sectors with only red walls are "inner" (clipping) sectors.
* Sprites in outer sectors are ignored.
* To associate a picnum with a bunch of sectors, place a sprite with that picnum in
some inner sector of the lot. At the end stage of editing, align the sprite so that
the model matches the sectors well. See samples/_clipshape_.map for examples.
* A picnum may be associated with many "layers" (called "indices" in the code) of
sectorwork. This serves two purposes: one is to enable more complex shapes than
would be possible using only one sector. The other reason is that a sprite may differ
in orientation in such a way that it is not possible to calculate one from another.
In particular, floor-aligned sprites and face/wall sprites should have their own
sector versions (of course only if they are intended to be used in a particular
orientation).
* The sprites in inner sectors should point northward and should not have any orientation-
changing bits like x-flip or y-flip set. Setting centering is permitted, though.
* A set of picnums can be aliased to a layer. This is useful if "secondary" picnums
are going to be used as decoration, for example. For this, set lotags and/or hitags
of any wall of an inner sector to the picnums to be aliased to values greater than 0.
If only one of them is set, it is taken as one picnum, otherwise as a both-sided inclusive
range, the order doesn't matter. The pigcop tank is present as an example in
samples/_clipshape_.map.
* The inner sectors of a given layer must be all interconnected (not necessarily directly)
and for a layer there must be a unique outer sector.
* Making the floor or ceiling of a sector parallaxed will disable clipping on it in certain
ways. Normally, there are four horizontal clipping planes (see the round table for an
example). Making the ceiling parallaxed disables the upper two, and analogously for the floor.
* Making a sprite transparent will disable rotation around its origin to match a given sprite's
angle. Use it on models with rotational symmetry.
Notes:
------
* Only clipmove and getzrange are changed, so that hitscan weapons will still behave the old way.
* The clipping will not change with rendering modes or options.
Known bugs:
-----------
* Flipping doesn't work correctly
* The behaviour in Mapster32 and EDuke32 differs slightly, see the
round table arrangement in the test area of _clipshape_.map
--Helixhorned

View file

@ -7341,7 +7341,11 @@ static void G_CheckCommandLine(int32_t argc, const char **argv)
while (i < argc)
{
c = (char *)argv[i];
if (((*c == '/') || (*c == '-')))
if ((*c == '-')
#ifdef _WIN32
|| (*c == '/')
#endif
)
{
if (!Bstrcasecmp(c+1,"?") || !Bstrcasecmp(c+1,"help") || !Bstrcasecmp(c+1,"-help"))
{
@ -7458,7 +7462,11 @@ static void G_CheckCommandLine(int32_t argc, const char **argv)
#endif
}
if ((*c == '/') || (*c == '-'))
if ((*c == '-')
#ifdef _WIN32
|| (*c == '/')
#endif
)
{
c++;
switch (*c)

View file

@ -175,6 +175,7 @@ int32_t kopen4loadfrommod(const char *filename, char searchfirst)
r = kopen4load(fn,searchfirst);
if (r < 0)
r = kopen4load(filename,searchfirst);
return r;
}
@ -8184,7 +8185,11 @@ static void G_CheckCommandLine(int32_t argc, const char **argv)
while (i < argc)
{
c = (char *)argv[i];
if (((*c == '/') || (*c == '-')))
if ((*c == '-')
#ifdef _WIN32
|| (*c == '/')
#endif
)
{
if (!Bstrcasecmp(c+1,"?") || !Bstrcasecmp(c+1,"help") || !Bstrcasecmp(c+1,"-help"))
{
@ -8406,7 +8411,11 @@ static void G_CheckCommandLine(int32_t argc, const char **argv)
#endif
}
if ((*c == '/') || (*c == '-'))
if ((*c == '-')
#ifdef _WIN32
|| (*c == '/')
#endif
)
{
c++;
switch (Btolower(*c))
@ -9850,6 +9859,12 @@ CLEAN_DIRECTORY:
Bfree(ptr);
}
i = clipmapinfo_load("_clipshape_.map");
if (i==0)
initprintf("Loaded sprite clipping map from \"_clipshape_.map\"\n");
else if (i>0)
initprintf("There was an error loading the sprite clipping map from \"_clipshape_.map\" (status %d).\n", i);
OSD_Exec("autoexec.cfg");
if (setgamemode(ud.config.ScreenMode,ud.config.ScreenWidth,ud.config.ScreenHeight,ud.config.ScreenBPP) < 0)