From f1caa980d05e91afb0fe8953d9e803387cdb6297 Mon Sep 17 00:00:00 2001 From: helixhorned Date: Thu, 28 Oct 2010 20:17:22 +0000 Subject: [PATCH] Sector-like sprite clipping. Check samples/spriteclip.txt. git-svn-id: https://svn.eduke32.com/eduke32@1719 1a8010ca-5511-0410-912e-c29ae57300e0 --- polymer/eduke32/build/include/build.h | 1 + polymer/eduke32/build/src/build.c | 10 +- polymer/eduke32/build/src/engine.c | 726 +++++++++++++++++++++++- polymer/eduke32/samples/_clipshape_.map | Bin 0 -> 23858 bytes polymer/eduke32/samples/spriteclip.txt | 63 ++ polymer/eduke32/source/astub.c | 12 +- polymer/eduke32/source/game.c | 19 +- 7 files changed, 806 insertions(+), 25 deletions(-) create mode 100644 polymer/eduke32/samples/_clipshape_.map create mode 100644 polymer/eduke32/samples/spriteclip.txt diff --git a/polymer/eduke32/build/include/build.h b/polymer/eduke32/build/include/build.h index 5420291d4..917f76427 100644 --- a/polymer/eduke32/build/include/build.h +++ b/polymer/eduke32/build/include/build.h @@ -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); diff --git a/polymer/eduke32/build/src/build.c b/polymer/eduke32/build/src/build.c index 7fb694168..fdb4e73bd 100644 --- a/polymer/eduke32/build/src/build.c +++ b/polymer/eduke32/build/src/build.c @@ -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; inumsectors = 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 *)§or[Sec].ceilingxpanning) // ceilingxpanning,ceilingypanning,floorpicnum +#define CM_CEILINGZ(Sec) (*(int32_t *)§or[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=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 || 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=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 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; ii0) + { + if (wall[w].lotag=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,18 +7113,21 @@ int32_t loadboard(char *filename, char fromwhere, int32_t *daposx, int32_t *dapo kclose(fil); - Bmemset(spriteext, 0, sizeof(spriteext_t) * MAXSPRITES); + if (!quickloadboard) + { + Bmemset(spriteext, 0, sizeof(spriteext_t) * MAXSPRITES); #if defined(POLYMOST) && defined(USE_OPENGL) - Bmemset(spritesmooth, 0, sizeof(spritesmooth_t) *(MAXSPRITES+MAXUNIQHUDID)); + Bmemset(spritesmooth, 0, sizeof(spritesmooth_t) *(MAXSPRITES+MAXUNIQHUDID)); // polymost_cachesync(); # ifdef POLYMER - if (rendmode == 4) - polymer_loadboard(); + if (rendmode == 4) + 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 = §or[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]; wx = 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,9 +9411,9 @@ 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 = §or[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 = §or[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; ix,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 = §or[clipsectorlist[clipsectcnt]]; startwall = sec->wallptr; endwall = startwall + sec->wallnum; for (j=startwall,wal=&wall[startwall]; jcstat&dawalclipmask) continue; sec = §or[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 (daz > *ceilz) { *ceilz = daz; *ceilhit = k+16384; } - if (daz2 < *florz) { *florz = daz2; *florhit = k+16384; } + 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; icstat; 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() diff --git a/polymer/eduke32/samples/_clipshape_.map b/polymer/eduke32/samples/_clipshape_.map new file mode 100644 index 0000000000000000000000000000000000000000..c1a3b7afb9688029c0c4fd63f3747b0a0c747691 GIT binary patch literal 23858 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 literal 0 HcmV?d00001 diff --git a/polymer/eduke32/samples/spriteclip.txt b/polymer/eduke32/samples/spriteclip.txt new file mode 100644 index 000000000..c279c2bd9 --- /dev/null +++ b/polymer/eduke32/samples/spriteclip.txt @@ -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 diff --git a/polymer/eduke32/source/astub.c b/polymer/eduke32/source/astub.c index b08ec93e2..ccca9916c 100644 --- a/polymer/eduke32/source/astub.c +++ b/polymer/eduke32/source/astub.c @@ -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) diff --git a/polymer/eduke32/source/game.c b/polymer/eduke32/source/game.c index 34cd434b6..df04f8856 100644 --- a/polymer/eduke32/source/game.c +++ b/polymer/eduke32/source/game.c @@ -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)