diff --git a/source/build/include/build.h b/source/build/include/build.h index 0d3783998..a473c0a02 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -1162,6 +1162,9 @@ void updatesectorz(int32_t x, int32_t y, int32_t z, int16_t *sectnum) ATTRIBUT int32_t inside(int32_t x, int32_t y, int16_t sectnum); void dragpoint(int16_t pointhighlight, int32_t dax, int32_t day, uint8_t flags); void setfirstwall(int16_t sectnum, int16_t newfirstwall); +int32_t try_facespr_intersect(uspritetype const * const spr, const vec3_t *refpos, + int32_t vx, int32_t vy, int32_t vz, + vec3_t *intp, int32_t strictly_smaller_than_p); extern const int16_t *chsecptr_onextwall; int32_t checksectorpointer(int16_t i, int16_t sectnum); diff --git a/source/build/src/clip.cpp b/source/build/src/clip.cpp index b4d4ca89b..4c38dcab6 100644 --- a/source/build/src/clip.cpp +++ b/source/build/src/clip.cpp @@ -6,6 +6,7 @@ // by Jonathon Fowler (jf@jonof.id.au) // by the EDuke32 team (development@voidpoint.com) +#include "a.h" #include "build.h" #include "baselayer.h" #include "engine_priv.h" @@ -56,6 +57,10 @@ static usectortype *loadsector; static uwalltype *loadwall, *loadwallinv; static uspritetype *loadsprite; +static vec2_t const hitscangoal = { (1<<29)-1, (1<<29)-1 }; +#ifdef USE_OPENGL +int32_t hitallsprites = 0; +#endif void engineInitClipMaps() { @@ -864,6 +869,35 @@ static inline void keepaway(int32_t *x, int32_t *y, int32_t w) } } +static int32_t get_floorspr_clipyou(int32_t x1, int32_t x2, int32_t x3, int32_t x4, + int32_t y1, int32_t y2, int32_t y3, int32_t y4) +{ + int32_t clipyou = 0; + + if ((y1^y2) < 0) + { + if ((x1^x2) < 0) clipyou ^= (x1*y2 < x2*y1)^(y1= 0) clipyou ^= 1; + } + if ((y2^y3) < 0) + { + if ((x2^x3) < 0) clipyou ^= (x2*y3 < x3*y2)^(y2= 0) clipyou ^= 1; + } + if ((y3^y4) < 0) + { + if ((x3^x4) < 0) clipyou ^= (x3*y4 < x4*y3)^(y3= 0) clipyou ^= 1; + } + if ((y4^y1) < 0) + { + if ((x4^x1) < 0) clipyou ^= (x4*y1 < x1*y4)^(y4= 0) clipyou ^= 1; + } + + return clipyou; +} + // // clipmove // @@ -1415,3 +1449,889 @@ int32_t pushmove(vec3_t *vect, int16_t *sectnum, return bad; } + +// +// getzrange +// +void getzrange(const vec3_t *pos, int16_t sectnum, + int32_t *ceilz, int32_t *ceilhit, int32_t *florz, int32_t *florhit, + int32_t walldist, uint32_t cliptype) +{ + if (sectnum < 0) + { + *ceilz = INT32_MIN; *ceilhit = -1; + *florz = INT32_MAX; *florhit = -1; + return; + } + + int32_t clipsectcnt = 0; + +#ifdef YAX_ENABLE + // YAX round, -1:center, 0:ceiling, 1:floor + int32_t mcf=-1; +#endif + + uspritetype *curspr=NULL; // non-NULL when handling sprite with sector-like clipping + int32_t curidx=-1, clipspritecnt = 0; + + //Extra walldist for sprites on sector lines + const int32_t extradist = walldist+MAXCLIPDIST+1; + const int32_t xmin = pos->x-extradist, ymin = pos->y-extradist; + const int32_t xmax = pos->x+extradist, ymax = pos->y+extradist; + + const int32_t dawalclipmask = (cliptype&65535); + const int32_t dasprclipmask = (cliptype>>16); + + getzsofslope(sectnum,pos->x,pos->y,ceilz,florz); + *ceilhit = sectnum+16384; *florhit = sectnum+16384; + +#ifdef YAX_ENABLE + origclipsectorlist[0] = sectnum; + origclipsectnum = 1; +#endif + clipsectorlist[0] = sectnum; + clipsectnum = 1; + clipspritenum = 0; + +#ifdef HAVE_CLIPSHAPE_FEATURE + if (0) + { +beginagain: + // replace sector and wall with clip map + engineSetClipMap(&origmapinfo, &clipmapinfo); + clipsectcnt = clipsectnum; // should be a nop, "safety"... + } +#endif + +#ifdef YAX_ENABLE +restart_grand: +#endif + do //Collect sectors inside your square first + { +#ifdef HAVE_CLIPSHAPE_FEATURE + if (clipsectcnt>=clipsectnum) + { + // one set of clip-sprite sectors completed, prepare the next + + curspr = (uspritetype *)&sprite[clipspritelist[clipspritecnt]]; + curidx = clipshape_idx_for_sprite(curspr, curidx); + + if (curidx < 0) + { + // didn't find matching clipping sectors for sprite + clipspritecnt++; + continue; + } + + clipsprite_initindex(curidx, curspr, &clipsectcnt, pos); + + for (bssize_t i=0; ix,pos->y,&daz,&daz2); + int32_t fz, cz; + getzsofslope(sectq[clipinfo[curidx].qend],pos->x,pos->y,&cz,&fz); + const int hitwhat = (curspr-(uspritetype *)sprite)+49152; + + if ((sector[k].ceilingstat&1)==0) + { + if (pos->z < cz && cz < *florz) { *florz = cz; *florhit = hitwhat; } + if (pos->z > daz && daz > *ceilz) { *ceilz = daz; *ceilhit = hitwhat; } + } + if ((sector[k].floorstat&1)==0) + { + if (pos->z < daz2 && daz2 < *florz) { *florz = daz2; *florhit = hitwhat; } + if (pos->z > fz && fz > *ceilz) { *ceilz = fz; *ceilhit = hitwhat; } + } + } + } +#endif + ////////// Walls ////////// + + const sectortype *const startsec = §or[clipsectorlist[clipsectcnt]]; + const int startwall = startsec->wallptr; + const int endwall = startwall + startsec->wallnum; + + for (bssize_t j=startwall; j= 0) + { + vec2_t const v1 = *(vec2_t *)&wall[j]; + vec2_t const v2 = *(vec2_t *)&wall[wall[j].point2]; + + if ((v1.x < xmin && (v2.x < xmin)) || (v1.x > xmax && v2.x > xmax) || + (v1.y < ymin && (v2.y < ymin)) || (v1.y > ymax && v2.y > ymax)) + continue; + + vec2_t const d = { v2.x-v1.x, v2.y-v1.y }; + if (d.x*(pos->y-v1.y) < (pos->x-v1.x)*d.y) continue; //back + + vec2_t da = { (d.x > 0) ? d.x*(ymin-v1.y) : d.x*(ymax-v1.y), + (d.y > 0) ? d.y*(xmax-v1.x) : d.y*(xmin-v1.x) }; + + if (da.x >= da.y) + continue; + + if (wall[j].cstat&dawalclipmask) continue; // XXX? + const sectortype *const sec = §or[k]; + +#ifdef HAVE_CLIPSHAPE_FEATURE + if (curspr) + { + if (k==sectq[clipinfo[curidx].qend]) + continue; + if ((sec->ceilingstat&1) && (sec->floorstat&1)) + continue; + } + else +#endif + if (editstatus == 0) + { + if (((sec->ceilingstat&1) == 0) && (pos->z <= sec->ceilingz+(3<<8))) continue; + if (((sec->floorstat&1) == 0) && (pos->z >= sec->floorz-(3<<8))) continue; + } + + int i; + for (i=clipsectnum-1; i>=0; --i) + if (clipsectorlist[i] == k) break; + + if (i < 0) clipsectorlist[clipsectnum++] = k; + + if (((v1.x < xmin + MAXCLIPDIST) && (v2.x < xmin + MAXCLIPDIST)) || + ((v1.x > xmax - MAXCLIPDIST) && (v2.x > xmax - MAXCLIPDIST)) || + ((v1.y < ymin + MAXCLIPDIST) && (v2.y < ymin + MAXCLIPDIST)) || + ((v1.y > ymax - MAXCLIPDIST) && (v2.y > ymax - MAXCLIPDIST))) + continue; + + if (d.x > 0) da.x += d.x*MAXCLIPDIST; else da.x -= d.x*MAXCLIPDIST; + if (d.y > 0) da.y -= d.y*MAXCLIPDIST; else da.y += d.y*MAXCLIPDIST; + if (da.x >= da.y) + continue; +#ifdef YAX_ENABLE + if (mcf==-1 && curspr==NULL) + origclipsectorlist[origclipsectnum++] = k; +#endif + //It actually got here, through all the continue's!!! + int32_t daz, daz2; + getzsofslope(k, pos->x,pos->y, &daz,&daz2); + +#ifdef HAVE_CLIPSHAPE_FEATURE + if (curspr) + { + int32_t fz,cz, hitwhat=(curspr-(uspritetype *)sprite)+49152; + getzsofslope(sectq[clipinfo[curidx].qend],pos->x,pos->y,&cz,&fz); + + if ((sec->ceilingstat&1)==0) + { + if (pos->z < cz && cz < *florz) { *florz = cz; *florhit = hitwhat; } + if (pos->z > daz && daz > *ceilz) { *ceilz = daz; *ceilhit = hitwhat; } + } + if ((sec->floorstat&1)==0) + { + if (pos->z < daz2 && daz2 < *florz) { *florz = daz2; *florhit = hitwhat; } + if (pos->z > fz && fz > *ceilz) { *ceilz = fz; *ceilhit = hitwhat; } + } + } + else +#endif + { +#ifdef YAX_ENABLE + int16_t cb, fb; + yax_getbunches(k, &cb, &fb); +#endif + if (daz > *ceilz) +#ifdef YAX_ENABLE + if (mcf!=YAX_FLOOR && cb < 0) +#endif + *ceilz = daz, *ceilhit = k+16384; + + if (daz2 < *florz) +#ifdef YAX_ENABLE + if (mcf!=YAX_CEILING && fb < 0) +#endif + *florz = daz2, *florhit = k+16384; + } + } + } + clipsectcnt++; + } + while (clipsectcnt < clipsectnum || clipspritecnt < clipspritenum); + +#ifdef HAVE_CLIPSHAPE_FEATURE + if (curspr) + { + engineSetClipMap(NULL, &origmapinfo); // restore original map + clipsectnum = clipspritenum = 0; // skip the next for loop and check afterwards + } +#endif + + ////////// Sprites ////////// + + for (bssize_t i=0; i=0; j=nextspritesect[j]) + { + const int32_t cstat = sprite[j].cstat; + int32_t daz, daz2; + + if (cstat&dasprclipmask) + { + int32_t clipyou = 0; + +#ifdef HAVE_CLIPSHAPE_FEATURE + if (clipsprite_try((uspritetype *)&sprite[j], xmin,ymin, xmax,ymax)) + continue; +#endif + vec2_t v1 = *(vec2_t *)&sprite[j]; + + switch (cstat & CSTAT_SPRITE_ALIGNMENT_MASK) + { + case CSTAT_SPRITE_ALIGNMENT_FACING: + { + int32_t k = walldist+(sprite[j].clipdist<<2)+1; + if ((klabs(v1.x-pos->x) <= k) && (klabs(v1.y-pos->y) <= k)) + { + daz = sprite[j].z + spriteheightofs(j, &k, 1); + daz2 = daz - k; + clipyou = 1; + } + break; + } + + case CSTAT_SPRITE_ALIGNMENT_WALL: + { + vec2_t v2; + get_wallspr_points((uspritetype *)&sprite[j], &v1.x, &v2.x, &v1.y, &v2.y); + + if (clipinsideboxline(pos->x,pos->y,v1.x,v1.y,v2.x,v2.y,walldist+1) != 0) + { + int32_t k; + daz = sprite[j].z + spriteheightofs(j, &k, 1); + daz2 = daz-k; + clipyou = 1; + } + break; + } + + case CSTAT_SPRITE_ALIGNMENT_FLOOR: + { + daz = sprite[j].z; daz2 = daz; + + if ((cstat&64) != 0 && (pos->z > daz) == ((cstat&8)==0)) + continue; + + vec2_t v2, v3, v4; + get_floorspr_points((uspritetype const *) &sprite[j], pos->x, pos->y, &v1.x, &v2.x, &v3.x, &v4.x, + &v1.y, &v2.y, &v3.y, &v4.y); + + vec2_t const da = { mulscale14(sintable[(sprite[j].ang - 256 + 512) & 2047], walldist + 4), + mulscale14(sintable[(sprite[j].ang - 256) & 2047], walldist + 4) }; + + v1.x += da.x; v2.x -= da.y; v3.x -= da.x; v4.x += da.y; + v1.y += da.y; v2.y += da.x; v3.y -= da.y; v4.y -= da.x; + + clipyou = get_floorspr_clipyou(v1.x, v2.x, v3.x, v4.x, v1.y, v2.y, v3.y, v4.y); + break; + } + } + + if (clipyou != 0) + { + if ((pos->z > daz) && (daz > *ceilz +#ifdef YAX_ENABLE + || (daz == *ceilz && yax_getbunch(clipsectorlist[i], YAX_CEILING)>=0) +#endif + )) + { + *ceilz = daz; + *ceilhit = j+49152; + } + + if ((pos->z < daz2) && (daz2 < *florz +#ifdef YAX_ENABLE + // can have a floor-sprite lying directly on the floor! + || (daz2 == *florz && yax_getbunch(clipsectorlist[i], YAX_FLOOR)>=0) +#endif + )) + { + *florz = daz2; + *florhit = j+49152; + } + } + } + } + } + +#ifdef HAVE_CLIPSHAPE_FEATURE + if (clipspritenum>0) + goto beginagain; +#endif + +#ifdef YAX_ENABLE + if (numyaxbunches > 0) + { + int const dasecclipmask = yax_waltosecmask(dawalclipmask); + int16_t cb, fb; + + yax_getbunches(sectnum, &cb, &fb); + + mcf++; + clipsectcnt = 0; clipsectnum = 0; + + int didchange = 0; + if (cb>=0 && mcf==0 && *ceilhit==sectnum+16384) + { + int i; + for (i=0; i= 0) + if (sector[j].ceilingstat&dasecclipmask) + break; + } + + if (i==origclipsectnum) + for (i=0; ix,pos->y, j)==1) + { + clipsectorlist[clipsectnum++] = j; + int const daz = getceilzofslope(j, pos->x,pos->y); + if (!didchange || daz > *ceilz) + didchange=1, *ceilhit = j+16384, *ceilz = daz; + } + } + + if (clipsectnum==0) + mcf++; + } + else if (mcf==0) + mcf++; + + didchange = 0; + if (fb>=0 && mcf==1 && *florhit==sectnum+16384) + { + int i=0; + for (; i= 0) + if (sector[j].floorstat&dasecclipmask) + break; + } + + // (almost) same as above, but with floors... + if (i==origclipsectnum) + for (i=0; ix,pos->y, j)==1) + { + clipsectorlist[clipsectnum++] = j; + int const daz = getflorzofslope(j, pos->x,pos->y); + if (!didchange || daz < *florz) + didchange=1, *florhit = j+16384, *florz = daz; + } + } + } + + if (clipsectnum > 0) + { + // sector-like sprite re-init: + curidx = -1; + curspr = NULL; + clipspritecnt = 0; clipspritenum = 0; + + goto restart_grand; + } + } +#endif +} + + +// intp: point of currently best (closest) intersection +int32_t try_facespr_intersect(uspritetype const * const spr, const vec3_t *refpos, + int32_t vx, int32_t vy, int32_t vz, + vec3_t *intp, int32_t strictly_smaller_than_p) +{ + const int32_t x1=spr->x, y1=spr->y; + const int32_t xs=refpos->x, ys=refpos->y; + + const int32_t topt = vx*(x1-xs) + vy*(y1-ys); + if (topt > 0) + { + const int32_t bot = vx*vx + vy*vy; + if (bot != 0) + { + int32_t i; + const int32_t intz = refpos->z + scale(vz,topt,bot); + const int32_t z1 = spr->z + spriteheightofsptr(spr, &i, 1); + + if (intz >= z1-i && intz <= z1) + { + const int32_t topu = vx*(y1-ys) - vy*(x1-xs); + + const int32_t offx = scale(vx,topu,bot); + const int32_t offy = scale(vy,topu,bot); + const int32_t dist = offx*offx + offy*offy; + + i = tilesiz[spr->picnum].x*spr->xrepeat; + if (dist <= mulscale7(i,i)) + { + const int32_t intx = xs + scale(vx,topt,bot); + const int32_t inty = ys + scale(vy,topt,bot); + + if (klabs(intx-xs)+klabs(inty-ys) + strictly_smaller_than_p + <= klabs(intp->x-xs)+klabs(intp->y-ys)) + { + intp->x = intx; + intp->y = inty; + intp->z = intz; + return 1; + } + } + } + } + } + + return 0; +} + +static inline void hit_set(hitdata_t *hit, int32_t sectnum, int32_t wallnum, int32_t spritenum, + int32_t x, int32_t y, int32_t z) +{ + hit->sect = sectnum; + hit->wall = wallnum; + hit->sprite = spritenum; + hit->pos.x = x; + hit->pos.y = y; + hit->pos.z = z; +} + +static int32_t hitscan_hitsectcf=-1; + +// stat, heinum, z: either ceiling- or floor- +// how: -1: behave like ceiling, 1: behave like floor +static int32_t hitscan_trysector(const vec3_t *sv, const usectortype *sec, hitdata_t *hit, + int32_t vx, int32_t vy, int32_t vz, + uint16_t stat, int16_t heinum, int32_t z, int32_t how, const intptr_t *tmp) +{ + int32_t x1 = INT32_MAX, y1, z1; + int32_t i; + + if (stat&2) + { + const uwalltype *const wal = (uwalltype *)&wall[sec->wallptr]; + const uwalltype *const wal2 = (uwalltype *)&wall[wal->point2]; + int32_t j, dax=wal2->x-wal->x, day=wal2->y-wal->y; + + i = nsqrtasm(uhypsq(dax,day)); if (i == 0) return 1; //continue; + i = divscale15(heinum,i); + dax *= i; day *= i; + + j = (vz<<8)-dmulscale15(dax,vy,-day,vx); + if (j != 0) + { + i = ((z - sv->z)<<8)+dmulscale15(dax,sv->y-wal->y,-day,sv->x-wal->x); + if (((i^j) >= 0) && ((klabs(i)>>1) < klabs(j))) + { + i = divscale30(i,j); + x1 = sv->x + mulscale30(vx,i); + y1 = sv->y + mulscale30(vy,i); + z1 = sv->z + mulscale30(vz,i); + } + } + } + else if ((how*vz > 0) && (how*sv->z <= how*z)) + { + z1 = z; i = z1-sv->z; + if ((klabs(i)>>1) < vz*how) + { + i = divscale30(i,vz); + x1 = sv->x + mulscale30(vx,i); + y1 = sv->y + mulscale30(vy,i); + } + } + + if ((x1 != INT32_MAX) && (klabs(x1-sv->x)+klabs(y1-sv->y) < klabs((hit->pos.x)-sv->x)+klabs((hit->pos.y)-sv->y))) + { + if (tmp==NULL) + { + if (inside(x1,y1,sec-(usectortype *)sector) == 1) + { + hit_set(hit, sec-(usectortype *)sector, -1, -1, x1, y1, z1); + hitscan_hitsectcf = (how+1)>>1; + } + } + else + { + const int32_t curidx=(int32_t)tmp[0]; + const uspritetype *const curspr=(uspritetype *)tmp[1]; + const int32_t thislastsec = tmp[2]; + + if (!thislastsec) + { + if (inside(x1,y1,sec-(usectortype *)sector) == 1) + hit_set(hit, curspr->sectnum, -1, curspr-(uspritetype *)sprite, x1, y1, z1); + } +#ifdef HAVE_CLIPSHAPE_FEATURE + else + { + for (i=clipinfo[curidx].qbeg; isectnum, -1, curspr-(uspritetype *)sprite, x1, y1, z1); + break; + } + } + } +#endif + } + } + + return 0; +} + +// +// hitscan +// +int32_t hitscan(const vec3_t *sv, int16_t sectnum, int32_t vx, int32_t vy, int32_t vz, + hitdata_t *hit, uint32_t cliptype) +{ + int32_t x1, y1=0, z1=0, x2, y2, intx, inty, intz; + int32_t i, k, daz; + int16_t tempshortcnt, tempshortnum; + + uspritetype *curspr = NULL; + int32_t clipspritecnt, curidx=-1; + // tmp: { (int32_t)curidx, (spritetype *)curspr, (!=0 if outer sector) } + intptr_t tmp[3], *tmpptr=NULL; +#ifdef YAX_ENABLE + vec3_t newsv; + int32_t oldhitsect = -1, oldhitsect2 = -2; +#endif + const int32_t dawalclipmask = (cliptype&65535); + const int32_t dasprclipmask = (cliptype>>16); + + hit->sect = -1; hit->wall = -1; hit->sprite = -1; + if (sectnum < 0) + return -1; + +#ifdef YAX_ENABLE +restart_grand: +#endif + *(vec2_t *)&hit->pos = hitscangoal; + + clipsectorlist[0] = sectnum; + tempshortcnt = 0; tempshortnum = 1; + clipspritecnt = clipspritenum = 0; + do + { + const usectortype *sec; + const uwalltype *wal; + int32_t dasector, z, startwall, endwall; + +#ifdef HAVE_CLIPSHAPE_FEATURE + if (tempshortcnt >= tempshortnum) + { + // one bunch of sectors completed, prepare the next + if (!curspr) + engineSetClipMap(&origmapinfo, &clipmapinfo); // replace sector and wall with clip map + + curspr = (uspritetype *)&sprite[clipspritelist[clipspritecnt]]; + curidx = clipshape_idx_for_sprite(curspr, curidx); + + if (curidx < 0) + { + clipspritecnt++; + continue; + } + + tmp[0] = (intptr_t)curidx; + tmp[1] = (intptr_t)curspr; + tmpptr = tmp; + + clipsprite_initindex(curidx, curspr, &i, sv); // &i is dummy + tempshortnum = (int16_t)clipsectnum; + tempshortcnt = 0; + } +#endif + dasector = clipsectorlist[tempshortcnt]; sec = (usectortype *)§or[dasector]; + + i = 1; +#ifdef HAVE_CLIPSHAPE_FEATURE + if (curspr) + { + if (dasector == sectq[clipinfo[curidx].qend]) + { + i = -1; + tmp[2] = 1; + } + else tmp[2] = 0; + } +#endif + if (hitscan_trysector(sv, sec, hit, vx,vy,vz, sec->ceilingstat, sec->ceilingheinum, sec->ceilingz, -i, tmpptr)) + continue; + if (hitscan_trysector(sv, sec, hit, vx,vy,vz, sec->floorstat, sec->floorheinum, sec->floorz, i, tmpptr)) + continue; + + ////////// Walls ////////// + + startwall = sec->wallptr; endwall = startwall + sec->wallnum; + for (z=startwall,wal=(uwalltype *)&wall[startwall]; znextsector; + const uwalltype *const wal2 = (uwalltype *)&wall[wal->point2]; + int32_t daz2, zz; + + if (curspr && nextsector<0) continue; + + x1 = wal->x; y1 = wal->y; x2 = wal2->x; y2 = wal2->y; + + if ((coord_t)(x1-sv->x)*(y2-sv->y) < (coord_t)(x2-sv->x)*(y1-sv->y)) continue; + if (rintersect(sv->x,sv->y,sv->z, vx,vy,vz, x1,y1, x2,y2, &intx,&inty,&intz) == -1) continue; + + if (klabs(intx-sv->x)+klabs(inty-sv->y) >= klabs((hit->pos.x)-sv->x)+klabs((hit->pos.y)-sv->y)) + continue; + + if (!curspr) + { + if ((nextsector < 0) || (wal->cstat&dawalclipmask)) + { + hit_set(hit, dasector, z, -1, intx, inty, intz); + continue; + } + + getzsofslope(nextsector,intx,inty,&daz,&daz2); + if (intz <= daz || intz >= daz2) + { + hit_set(hit, dasector, z, -1, intx, inty, intz); + continue; + } + } +#ifdef HAVE_CLIPSHAPE_FEATURE + else + { + int32_t cz,fz; + + if (wal->cstat&dawalclipmask) + { + hit_set(hit, curspr->sectnum, -1, curspr-(uspritetype *)sprite, intx, inty, intz); + continue; + } + + getzsofslope(nextsector,intx,inty,&daz,&daz2); + getzsofslope(sectq[clipinfo[curidx].qend],intx,inty,&cz,&fz); + // ceil cz daz daz2 fz floor + if ((cz <= intz && intz <= daz) || (daz2 <= intz && intz <= fz)) + { + hit_set(hit, curspr->sectnum, -1, curspr-(uspritetype *)sprite, intx, inty, intz); + continue; + } + } +#endif + for (zz=tempshortnum-1; zz>=0; zz--) + if (clipsectorlist[zz] == nextsector) break; + if (zz < 0) clipsectorlist[tempshortnum++] = nextsector; + } + + ////////// Sprites ////////// + + if (dasprclipmask==0) + continue; + +#ifdef HAVE_CLIPSHAPE_FEATURE + if (curspr) + continue; +#endif + for (z=headspritesect[dasector]; z>=0; z=nextspritesect[z]) + { + const uspritetype *const spr = (uspritetype *)&sprite[z]; + const int32_t cstat = spr->cstat; +#ifdef USE_OPENGL + if (!hitallsprites) +#endif + if ((cstat&dasprclipmask) == 0) + continue; + +#ifdef HAVE_CLIPSHAPE_FEATURE + // 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 && clipspritenumx; y1 = spr->y; z1 = spr->z; + switch (cstat&48) + { + case 0: + { + if (try_facespr_intersect(spr, sv, vx, vy, vz, &hit->pos, 0)) + { + hit->sect = dasector; + hit->wall = -1; + hit->sprite = z; + } + + break; + } + + case 16: + { + int32_t ucoefup16; + int32_t tilenum = spr->picnum; + + get_wallspr_points(spr, &x1, &x2, &y1, &y2); + + if ((cstat&64) != 0) //back side of 1-way sprite + if ((coord_t)(x1-sv->x)*(y2-sv->y) < (coord_t)(x2-sv->x)*(y1-sv->y)) continue; + + ucoefup16 = rintersect(sv->x,sv->y,sv->z,vx,vy,vz,x1,y1,x2,y2,&intx,&inty,&intz); + if (ucoefup16 == -1) continue; + + if (klabs(intx-sv->x)+klabs(inty-sv->y) > klabs((hit->pos.x)-sv->x)+klabs((hit->pos.y)-sv->y)) + continue; + + daz = spr->z + spriteheightofs(z, &k, 1); + if (intz > daz-k && intz < daz) + { + if (picanm[tilenum].sf&PICANM_TEXHITSCAN_BIT) + { + DO_TILE_ANIM(tilenum, 0); + + if (!waloff[tilenum]) + tileLoad(tilenum); + + if (waloff[tilenum]) + { + // daz-intz > 0 && daz-intz < k + int32_t xtex = mulscale16(ucoefup16, tilesiz[tilenum].x); + int32_t vcoefup16 = 65536-divscale16(daz-intz, k); + int32_t ytex = mulscale16(vcoefup16, tilesiz[tilenum].y); + + const char *texel = (char *)(waloff[tilenum] + tilesiz[tilenum].y*xtex + ytex); + if (*texel == 255) + continue; + } + } + + hit_set(hit, dasector, -1, z, intx, inty, intz); + } + break; + } + + case 32: + { + int32_t x3, y3, x4, y4, zz; + + if (vz == 0) continue; + intz = z1; + if (((intz-sv->z)^vz) < 0) continue; + if ((cstat&64) != 0) + if ((sv->z > intz) == ((cstat&8)==0)) continue; +#if 1 + // Abyss crash prevention code ((intz-sv->z)*zx overflowing a 8-bit word) + // PK: the reason for the crash is not the overflowing (even if it IS a problem; + // signed overflow is undefined behavior in C), but rather the idiv trap when + // the resulting quotient doesn't fit into a *signed* 32-bit integer. + zz = (uint32_t)(intz-sv->z) * vx; + intx = sv->x+scale(zz,1,vz); + zz = (uint32_t)(intz-sv->z) * vy; + inty = sv->y+scale(zz,1,vz); +#else + intx = sv->x+scale(intz-sv->z,vx,vz); + inty = sv->y+scale(intz-sv->z,vy,vz); +#endif + if (klabs(intx-sv->x)+klabs(inty-sv->y) > klabs((hit->pos.x)-sv->x)+klabs((hit->pos.y)-sv->y)) + continue; + + get_floorspr_points((uspritetype const *)spr, intx, inty, &x1, &x2, &x3, &x4, + &y1, &y2, &y3, &y4); + + if (get_floorspr_clipyou(x1, x2, x3, x4, y1, y2, y3, y4)) + { + hit_set(hit, dasector, -1, z, intx, inty, intz); + } + + break; + } + } + } + } + while (++tempshortcnt < tempshortnum || clipspritecnt < clipspritenum); + +#ifdef HAVE_CLIPSHAPE_FEATURE + if (curspr) + engineSetClipMap(NULL, &origmapinfo); +#endif + +#ifdef YAX_ENABLE + if (numyaxbunches == 0 || editstatus) + return 0; + + if (hit->sprite==-1 && hit->wall==-1 && hit->sect!=oldhitsect + && hit->sect != oldhitsect2) // 'ping-pong' infloop protection + { + if (hit->sect == -1 && oldhitsect >= 0) + { + // this is bad: we didn't hit anything after going through a ceiling/floor + Bmemcpy(&hit->pos, &newsv, sizeof(vec3_t)); + hit->sect = oldhitsect; + + return 0; + } + + // 1st, 2nd, ... ceil/floor hit + // hit->sect is >=0 because if oldhitsect's init and check above + if (SECTORFLD(hit->sect,stat, hitscan_hitsectcf)&yax_waltosecmask(dawalclipmask)) + return 0; + + i = yax_getneighborsect(hit->pos.x, hit->pos.y, hit->sect, hitscan_hitsectcf); + if (i >= 0) + { + Bmemcpy(&newsv, &hit->pos, sizeof(vec3_t)); + sectnum = i; + sv = &newsv; + + oldhitsect2 = oldhitsect; + oldhitsect = hit->sect; + hit->sect = -1; + + // sector-like sprite re-init: + curspr = 0; + curidx = -1; + tmpptr = NULL; + + goto restart_grand; + } + } +#endif + + return 0; +} + diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 3a6c8fe3d..f73aa1905 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -1412,11 +1412,6 @@ static int32_t *lastx; int32_t halfxdim16, midydim16; -static vec2_t const hitscangoal = { (1<<29)-1, (1<<29)-1 }; -#ifdef USE_OPENGL -int32_t hitallsprites = 0; -#endif - typedef struct { int32_t sx, sy, z; @@ -10514,102 +10509,6 @@ add_nextsector: return 0; } -static inline void hit_set(hitdata_t *hit, int32_t sectnum, int32_t wallnum, int32_t spritenum, - int32_t x, int32_t y, int32_t z) -{ - hit->sect = sectnum; - hit->wall = wallnum; - hit->sprite = spritenum; - hit->pos.x = x; - hit->pos.y = y; - hit->pos.z = z; -} - -static int32_t hitscan_hitsectcf=-1; - -// stat, heinum, z: either ceiling- or floor- -// how: -1: behave like ceiling, 1: behave like floor -static int32_t hitscan_trysector(const vec3_t *sv, const usectortype *sec, hitdata_t *hit, - int32_t vx, int32_t vy, int32_t vz, - uint16_t stat, int16_t heinum, int32_t z, int32_t how, const intptr_t *tmp) -{ - int32_t x1 = INT32_MAX, y1, z1; - int32_t i; - - if (stat&2) - { - const uwalltype *const wal = (uwalltype *)&wall[sec->wallptr]; - const uwalltype *const wal2 = (uwalltype *)&wall[wal->point2]; - int32_t j, dax=wal2->x-wal->x, day=wal2->y-wal->y; - - i = nsqrtasm(uhypsq(dax,day)); if (i == 0) return 1; //continue; - i = divscale15(heinum,i); - dax *= i; day *= i; - - j = (vz<<8)-dmulscale15(dax,vy,-day,vx); - if (j != 0) - { - i = ((z - sv->z)<<8)+dmulscale15(dax,sv->y-wal->y,-day,sv->x-wal->x); - if (((i^j) >= 0) && ((klabs(i)>>1) < klabs(j))) - { - i = divscale30(i,j); - x1 = sv->x + mulscale30(vx,i); - y1 = sv->y + mulscale30(vy,i); - z1 = sv->z + mulscale30(vz,i); - } - } - } - else if ((how*vz > 0) && (how*sv->z <= how*z)) - { - z1 = z; i = z1-sv->z; - if ((klabs(i)>>1) < vz*how) - { - i = divscale30(i,vz); - x1 = sv->x + mulscale30(vx,i); - y1 = sv->y + mulscale30(vy,i); - } - } - - if ((x1 != INT32_MAX) && (klabs(x1-sv->x)+klabs(y1-sv->y) < klabs((hit->pos.x)-sv->x)+klabs((hit->pos.y)-sv->y))) - { - if (tmp==NULL) - { - if (inside(x1,y1,sec-(usectortype *)sector) == 1) - { - hit_set(hit, sec-(usectortype *)sector, -1, -1, x1, y1, z1); - hitscan_hitsectcf = (how+1)>>1; - } - } - else - { - const int32_t curidx=(int32_t)tmp[0]; - const uspritetype *const curspr=(uspritetype *)tmp[1]; - const int32_t thislastsec = tmp[2]; - - if (!thislastsec) - { - if (inside(x1,y1,sec-(usectortype *)sector) == 1) - hit_set(hit, curspr->sectnum, -1, curspr-(uspritetype *)sprite, x1, y1, z1); - } -#ifdef HAVE_CLIPSHAPE_FEATURE - else - { - for (i=clipinfo[curidx].qbeg; isectnum, -1, curspr-(uspritetype *)sprite, x1, y1, z1); - break; - } - } - } -#endif - } - } - - return 0; -} - // x1, y1: in/out // rest x/y: out void get_wallspr_points(uspritetype const * const spr, int32_t *x1, int32_t *x2, @@ -10679,407 +10578,6 @@ void get_floorspr_points(uspritetype const * const spr, int32_t px, int32_t py, k = -mulscale16(sinang,l); *y3 = *y2+k; *y4 = *y1+k; } -static int32_t get_floorspr_clipyou(int32_t x1, int32_t x2, int32_t x3, int32_t x4, - int32_t y1, int32_t y2, int32_t y3, int32_t y4) -{ - int32_t clipyou = 0; - - if ((y1^y2) < 0) - { - if ((x1^x2) < 0) clipyou ^= (x1*y2 < x2*y1)^(y1= 0) clipyou ^= 1; - } - if ((y2^y3) < 0) - { - if ((x2^x3) < 0) clipyou ^= (x2*y3 < x3*y2)^(y2= 0) clipyou ^= 1; - } - if ((y3^y4) < 0) - { - if ((x3^x4) < 0) clipyou ^= (x3*y4 < x4*y3)^(y3= 0) clipyou ^= 1; - } - if ((y4^y1) < 0) - { - if ((x4^x1) < 0) clipyou ^= (x4*y1 < x1*y4)^(y4= 0) clipyou ^= 1; - } - - return clipyou; -} - -// intp: point of currently best (closest) intersection -static int32_t try_facespr_intersect(uspritetype const * const spr, const vec3_t *refpos, - int32_t vx, int32_t vy, int32_t vz, - vec3_t *intp, int32_t strictly_smaller_than_p) -{ - const int32_t x1=spr->x, y1=spr->y; - const int32_t xs=refpos->x, ys=refpos->y; - - const int32_t topt = vx*(x1-xs) + vy*(y1-ys); - if (topt > 0) - { - const int32_t bot = vx*vx + vy*vy; - if (bot != 0) - { - int32_t i; - const int32_t intz = refpos->z + scale(vz,topt,bot); - const int32_t z1 = spr->z + spriteheightofsptr(spr, &i, 1); - - if (intz >= z1-i && intz <= z1) - { - const int32_t topu = vx*(y1-ys) - vy*(x1-xs); - - const int32_t offx = scale(vx,topu,bot); - const int32_t offy = scale(vy,topu,bot); - const int32_t dist = offx*offx + offy*offy; - - i = tilesiz[spr->picnum].x*spr->xrepeat; - if (dist <= mulscale7(i,i)) - { - const int32_t intx = xs + scale(vx,topt,bot); - const int32_t inty = ys + scale(vy,topt,bot); - - if (klabs(intx-xs)+klabs(inty-ys) + strictly_smaller_than_p - <= klabs(intp->x-xs)+klabs(intp->y-ys)) - { - intp->x = intx; - intp->y = inty; - intp->z = intz; - return 1; - } - } - } - } - } - - return 0; -} - -// -// hitscan -// -int32_t hitscan(const vec3_t *sv, int16_t sectnum, int32_t vx, int32_t vy, int32_t vz, - hitdata_t *hit, uint32_t cliptype) -{ - int32_t x1, y1=0, z1=0, x2, y2, intx, inty, intz; - int32_t i, k, daz; - int16_t tempshortcnt, tempshortnum; - - uspritetype *curspr = NULL; - int32_t clipspritecnt, curidx=-1; - // tmp: { (int32_t)curidx, (spritetype *)curspr, (!=0 if outer sector) } - intptr_t tmp[3], *tmpptr=NULL; -#ifdef YAX_ENABLE - vec3_t newsv; - int32_t oldhitsect = -1, oldhitsect2 = -2; -#endif - const int32_t dawalclipmask = (cliptype&65535); - const int32_t dasprclipmask = (cliptype>>16); - - hit->sect = -1; hit->wall = -1; hit->sprite = -1; - if (sectnum < 0) - return -1; - -#ifdef YAX_ENABLE -restart_grand: -#endif - *(vec2_t *)&hit->pos = hitscangoal; - - clipsectorlist[0] = sectnum; - tempshortcnt = 0; tempshortnum = 1; - clipspritecnt = clipspritenum = 0; - do - { - const usectortype *sec; - const uwalltype *wal; - int32_t dasector, z, startwall, endwall; - -#ifdef HAVE_CLIPSHAPE_FEATURE - if (tempshortcnt >= tempshortnum) - { - // one bunch of sectors completed, prepare the next - if (!curspr) - engineSetClipMap(&origmapinfo, &clipmapinfo); // replace sector and wall with clip map - - curspr = (uspritetype *)&sprite[clipspritelist[clipspritecnt]]; - curidx = clipshape_idx_for_sprite(curspr, curidx); - - if (curidx < 0) - { - clipspritecnt++; - continue; - } - - tmp[0] = (intptr_t)curidx; - tmp[1] = (intptr_t)curspr; - tmpptr = tmp; - - clipsprite_initindex(curidx, curspr, &i, sv); // &i is dummy - tempshortnum = (int16_t)clipsectnum; - tempshortcnt = 0; - } -#endif - dasector = clipsectorlist[tempshortcnt]; sec = (usectortype *)§or[dasector]; - - i = 1; -#ifdef HAVE_CLIPSHAPE_FEATURE - if (curspr) - { - if (dasector == sectq[clipinfo[curidx].qend]) - { - i = -1; - tmp[2] = 1; - } - else tmp[2] = 0; - } -#endif - if (hitscan_trysector(sv, sec, hit, vx,vy,vz, sec->ceilingstat, sec->ceilingheinum, sec->ceilingz, -i, tmpptr)) - continue; - if (hitscan_trysector(sv, sec, hit, vx,vy,vz, sec->floorstat, sec->floorheinum, sec->floorz, i, tmpptr)) - continue; - - ////////// Walls ////////// - - startwall = sec->wallptr; endwall = startwall + sec->wallnum; - for (z=startwall,wal=(uwalltype *)&wall[startwall]; znextsector; - const uwalltype *const wal2 = (uwalltype *)&wall[wal->point2]; - int32_t daz2, zz; - - if (curspr && nextsector<0) continue; - - x1 = wal->x; y1 = wal->y; x2 = wal2->x; y2 = wal2->y; - - if ((coord_t)(x1-sv->x)*(y2-sv->y) < (coord_t)(x2-sv->x)*(y1-sv->y)) continue; - if (rintersect(sv->x,sv->y,sv->z, vx,vy,vz, x1,y1, x2,y2, &intx,&inty,&intz) == -1) continue; - - if (klabs(intx-sv->x)+klabs(inty-sv->y) >= klabs((hit->pos.x)-sv->x)+klabs((hit->pos.y)-sv->y)) - continue; - - if (!curspr) - { - if ((nextsector < 0) || (wal->cstat&dawalclipmask)) - { - hit_set(hit, dasector, z, -1, intx, inty, intz); - continue; - } - - getzsofslope(nextsector,intx,inty,&daz,&daz2); - if (intz <= daz || intz >= daz2) - { - hit_set(hit, dasector, z, -1, intx, inty, intz); - continue; - } - } -#ifdef HAVE_CLIPSHAPE_FEATURE - else - { - int32_t cz,fz; - - if (wal->cstat&dawalclipmask) - { - hit_set(hit, curspr->sectnum, -1, curspr-(uspritetype *)sprite, intx, inty, intz); - continue; - } - - getzsofslope(nextsector,intx,inty,&daz,&daz2); - getzsofslope(sectq[clipinfo[curidx].qend],intx,inty,&cz,&fz); - // ceil cz daz daz2 fz floor - if ((cz <= intz && intz <= daz) || (daz2 <= intz && intz <= fz)) - { - hit_set(hit, curspr->sectnum, -1, curspr-(uspritetype *)sprite, intx, inty, intz); - continue; - } - } -#endif - for (zz=tempshortnum-1; zz>=0; zz--) - if (clipsectorlist[zz] == nextsector) break; - if (zz < 0) clipsectorlist[tempshortnum++] = nextsector; - } - - ////////// Sprites ////////// - - if (dasprclipmask==0) - continue; - -#ifdef HAVE_CLIPSHAPE_FEATURE - if (curspr) - continue; -#endif - for (z=headspritesect[dasector]; z>=0; z=nextspritesect[z]) - { - const uspritetype *const spr = (uspritetype *)&sprite[z]; - const int32_t cstat = spr->cstat; -#ifdef USE_OPENGL - if (!hitallsprites) -#endif - if ((cstat&dasprclipmask) == 0) - continue; - -#ifdef HAVE_CLIPSHAPE_FEATURE - // 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 && clipspritenumx; y1 = spr->y; z1 = spr->z; - switch (cstat&48) - { - case 0: - { - if (try_facespr_intersect(spr, sv, vx, vy, vz, &hit->pos, 0)) - { - hit->sect = dasector; - hit->wall = -1; - hit->sprite = z; - } - - break; - } - - case 16: - { - int32_t ucoefup16; - int32_t tilenum = spr->picnum; - - get_wallspr_points(spr, &x1, &x2, &y1, &y2); - - if ((cstat&64) != 0) //back side of 1-way sprite - if ((coord_t)(x1-sv->x)*(y2-sv->y) < (coord_t)(x2-sv->x)*(y1-sv->y)) continue; - - ucoefup16 = rintersect(sv->x,sv->y,sv->z,vx,vy,vz,x1,y1,x2,y2,&intx,&inty,&intz); - if (ucoefup16 == -1) continue; - - if (klabs(intx-sv->x)+klabs(inty-sv->y) > klabs((hit->pos.x)-sv->x)+klabs((hit->pos.y)-sv->y)) - continue; - - daz = spr->z + spriteheightofs(z, &k, 1); - if (intz > daz-k && intz < daz) - { - if (picanm[tilenum].sf&PICANM_TEXHITSCAN_BIT) - { - DO_TILE_ANIM(tilenum, 0); - - if (!waloff[tilenum]) - tileLoad(tilenum); - - if (waloff[tilenum]) - { - // daz-intz > 0 && daz-intz < k - int32_t xtex = mulscale16(ucoefup16, tilesiz[tilenum].x); - int32_t vcoefup16 = 65536-divscale16(daz-intz, k); - int32_t ytex = mulscale16(vcoefup16, tilesiz[tilenum].y); - - const char *texel = (char *)(waloff[tilenum] + tilesiz[tilenum].y*xtex + ytex); - if (*texel == 255) - continue; - } - } - - hit_set(hit, dasector, -1, z, intx, inty, intz); - } - break; - } - - case 32: - { - int32_t x3, y3, x4, y4, zz; - - if (vz == 0) continue; - intz = z1; - if (((intz-sv->z)^vz) < 0) continue; - if ((cstat&64) != 0) - if ((sv->z > intz) == ((cstat&8)==0)) continue; -#if 1 - // Abyss crash prevention code ((intz-sv->z)*zx overflowing a 8-bit word) - // PK: the reason for the crash is not the overflowing (even if it IS a problem; - // signed overflow is undefined behavior in C), but rather the idiv trap when - // the resulting quotient doesn't fit into a *signed* 32-bit integer. - zz = (uint32_t)(intz-sv->z) * vx; - intx = sv->x+scale(zz,1,vz); - zz = (uint32_t)(intz-sv->z) * vy; - inty = sv->y+scale(zz,1,vz); -#else - intx = sv->x+scale(intz-sv->z,vx,vz); - inty = sv->y+scale(intz-sv->z,vy,vz); -#endif - if (klabs(intx-sv->x)+klabs(inty-sv->y) > klabs((hit->pos.x)-sv->x)+klabs((hit->pos.y)-sv->y)) - continue; - - get_floorspr_points((uspritetype const *)spr, intx, inty, &x1, &x2, &x3, &x4, - &y1, &y2, &y3, &y4); - - if (get_floorspr_clipyou(x1, x2, x3, x4, y1, y2, y3, y4)) - { - hit_set(hit, dasector, -1, z, intx, inty, intz); - } - - break; - } - } - } - } - while (++tempshortcnt < tempshortnum || clipspritecnt < clipspritenum); - -#ifdef HAVE_CLIPSHAPE_FEATURE - if (curspr) - engineSetClipMap(NULL, &origmapinfo); -#endif - -#ifdef YAX_ENABLE - if (numyaxbunches == 0 || editstatus) - return 0; - - if (hit->sprite==-1 && hit->wall==-1 && hit->sect!=oldhitsect - && hit->sect != oldhitsect2) // 'ping-pong' infloop protection - { - if (hit->sect == -1 && oldhitsect >= 0) - { - // this is bad: we didn't hit anything after going through a ceiling/floor - Bmemcpy(&hit->pos, &newsv, sizeof(vec3_t)); - hit->sect = oldhitsect; - - return 0; - } - - // 1st, 2nd, ... ceil/floor hit - // hit->sect is >=0 because if oldhitsect's init and check above - if (SECTORFLD(hit->sect,stat, hitscan_hitsectcf)&yax_waltosecmask(dawalclipmask)) - return 0; - - i = yax_getneighborsect(hit->pos.x, hit->pos.y, hit->sect, hitscan_hitsectcf); - if (i >= 0) - { - Bmemcpy(&newsv, &hit->pos, sizeof(vec3_t)); - sectnum = i; - sv = &newsv; - - oldhitsect2 = oldhitsect; - oldhitsect = hit->sect; - hit->sect = -1; - - // sector-like sprite re-init: - curspr = 0; - curidx = -1; - tmpptr = NULL; - - goto restart_grand; - } - } -#endif - - return 0; -} - - // // neartag // @@ -11651,423 +11149,6 @@ int32_t krand(void) } #endif -// -// getzrange -// -void getzrange(const vec3_t *pos, int16_t sectnum, - int32_t *ceilz, int32_t *ceilhit, int32_t *florz, int32_t *florhit, - int32_t walldist, uint32_t cliptype) -{ - if (sectnum < 0) - { - *ceilz = INT32_MIN; *ceilhit = -1; - *florz = INT32_MAX; *florhit = -1; - return; - } - - int32_t clipsectcnt = 0; - -#ifdef YAX_ENABLE - // YAX round, -1:center, 0:ceiling, 1:floor - int32_t mcf=-1; -#endif - - uspritetype *curspr=NULL; // non-NULL when handling sprite with sector-like clipping - int32_t curidx=-1, clipspritecnt = 0; - - //Extra walldist for sprites on sector lines - const int32_t extradist = walldist+MAXCLIPDIST+1; - const int32_t xmin = pos->x-extradist, ymin = pos->y-extradist; - const int32_t xmax = pos->x+extradist, ymax = pos->y+extradist; - - const int32_t dawalclipmask = (cliptype&65535); - const int32_t dasprclipmask = (cliptype>>16); - - getzsofslope(sectnum,pos->x,pos->y,ceilz,florz); - *ceilhit = sectnum+16384; *florhit = sectnum+16384; - -#ifdef YAX_ENABLE - origclipsectorlist[0] = sectnum; - origclipsectnum = 1; -#endif - clipsectorlist[0] = sectnum; - clipsectnum = 1; - clipspritenum = 0; - -#ifdef HAVE_CLIPSHAPE_FEATURE - if (0) - { -beginagain: - // replace sector and wall with clip map - engineSetClipMap(&origmapinfo, &clipmapinfo); - clipsectcnt = clipsectnum; // should be a nop, "safety"... - } -#endif - -#ifdef YAX_ENABLE -restart_grand: -#endif - do //Collect sectors inside your square first - { -#ifdef HAVE_CLIPSHAPE_FEATURE - if (clipsectcnt>=clipsectnum) - { - // one set of clip-sprite sectors completed, prepare the next - - curspr = (uspritetype *)&sprite[clipspritelist[clipspritecnt]]; - curidx = clipshape_idx_for_sprite(curspr, curidx); - - if (curidx < 0) - { - // didn't find matching clipping sectors for sprite - clipspritecnt++; - continue; - } - - clipsprite_initindex(curidx, curspr, &clipsectcnt, pos); - - for (bssize_t i=0; ix,pos->y,&daz,&daz2); - int32_t fz, cz; - getzsofslope(sectq[clipinfo[curidx].qend],pos->x,pos->y,&cz,&fz); - const int hitwhat = (curspr-(uspritetype *)sprite)+49152; - - if ((sector[k].ceilingstat&1)==0) - { - if (pos->z < cz && cz < *florz) { *florz = cz; *florhit = hitwhat; } - if (pos->z > daz && daz > *ceilz) { *ceilz = daz; *ceilhit = hitwhat; } - } - if ((sector[k].floorstat&1)==0) - { - if (pos->z < daz2 && daz2 < *florz) { *florz = daz2; *florhit = hitwhat; } - if (pos->z > fz && fz > *ceilz) { *ceilz = fz; *ceilhit = hitwhat; } - } - } - } -#endif - ////////// Walls ////////// - - const sectortype *const startsec = §or[clipsectorlist[clipsectcnt]]; - const int startwall = startsec->wallptr; - const int endwall = startwall + startsec->wallnum; - - for (bssize_t j=startwall; j= 0) - { - vec2_t const v1 = *(vec2_t *)&wall[j]; - vec2_t const v2 = *(vec2_t *)&wall[wall[j].point2]; - - if ((v1.x < xmin && (v2.x < xmin)) || (v1.x > xmax && v2.x > xmax) || - (v1.y < ymin && (v2.y < ymin)) || (v1.y > ymax && v2.y > ymax)) - continue; - - vec2_t const d = { v2.x-v1.x, v2.y-v1.y }; - if (d.x*(pos->y-v1.y) < (pos->x-v1.x)*d.y) continue; //back - - vec2_t da = { (d.x > 0) ? d.x*(ymin-v1.y) : d.x*(ymax-v1.y), - (d.y > 0) ? d.y*(xmax-v1.x) : d.y*(xmin-v1.x) }; - - if (da.x >= da.y) - continue; - - if (wall[j].cstat&dawalclipmask) continue; // XXX? - const sectortype *const sec = §or[k]; - -#ifdef HAVE_CLIPSHAPE_FEATURE - if (curspr) - { - if (k==sectq[clipinfo[curidx].qend]) - continue; - if ((sec->ceilingstat&1) && (sec->floorstat&1)) - continue; - } - else -#endif - if (editstatus == 0) - { - if (((sec->ceilingstat&1) == 0) && (pos->z <= sec->ceilingz+(3<<8))) continue; - if (((sec->floorstat&1) == 0) && (pos->z >= sec->floorz-(3<<8))) continue; - } - - int i; - for (i=clipsectnum-1; i>=0; --i) - if (clipsectorlist[i] == k) break; - - if (i < 0) clipsectorlist[clipsectnum++] = k; - - if (((v1.x < xmin + MAXCLIPDIST) && (v2.x < xmin + MAXCLIPDIST)) || - ((v1.x > xmax - MAXCLIPDIST) && (v2.x > xmax - MAXCLIPDIST)) || - ((v1.y < ymin + MAXCLIPDIST) && (v2.y < ymin + MAXCLIPDIST)) || - ((v1.y > ymax - MAXCLIPDIST) && (v2.y > ymax - MAXCLIPDIST))) - continue; - - if (d.x > 0) da.x += d.x*MAXCLIPDIST; else da.x -= d.x*MAXCLIPDIST; - if (d.y > 0) da.y -= d.y*MAXCLIPDIST; else da.y += d.y*MAXCLIPDIST; - if (da.x >= da.y) - continue; -#ifdef YAX_ENABLE - if (mcf==-1 && curspr==NULL) - origclipsectorlist[origclipsectnum++] = k; -#endif - //It actually got here, through all the continue's!!! - int32_t daz, daz2; - getzsofslope(k, pos->x,pos->y, &daz,&daz2); - -#ifdef HAVE_CLIPSHAPE_FEATURE - if (curspr) - { - int32_t fz,cz, hitwhat=(curspr-(uspritetype *)sprite)+49152; - getzsofslope(sectq[clipinfo[curidx].qend],pos->x,pos->y,&cz,&fz); - - if ((sec->ceilingstat&1)==0) - { - if (pos->z < cz && cz < *florz) { *florz = cz; *florhit = hitwhat; } - if (pos->z > daz && daz > *ceilz) { *ceilz = daz; *ceilhit = hitwhat; } - } - if ((sec->floorstat&1)==0) - { - if (pos->z < daz2 && daz2 < *florz) { *florz = daz2; *florhit = hitwhat; } - if (pos->z > fz && fz > *ceilz) { *ceilz = fz; *ceilhit = hitwhat; } - } - } - else -#endif - { -#ifdef YAX_ENABLE - int16_t cb, fb; - yax_getbunches(k, &cb, &fb); -#endif - if (daz > *ceilz) -#ifdef YAX_ENABLE - if (mcf!=YAX_FLOOR && cb < 0) -#endif - *ceilz = daz, *ceilhit = k+16384; - - if (daz2 < *florz) -#ifdef YAX_ENABLE - if (mcf!=YAX_CEILING && fb < 0) -#endif - *florz = daz2, *florhit = k+16384; - } - } - } - clipsectcnt++; - } - while (clipsectcnt < clipsectnum || clipspritecnt < clipspritenum); - -#ifdef HAVE_CLIPSHAPE_FEATURE - if (curspr) - { - engineSetClipMap(NULL, &origmapinfo); // restore original map - clipsectnum = clipspritenum = 0; // skip the next for loop and check afterwards - } -#endif - - ////////// Sprites ////////// - - for (bssize_t i=0; i=0; j=nextspritesect[j]) - { - const int32_t cstat = sprite[j].cstat; - int32_t daz, daz2; - - if (cstat&dasprclipmask) - { - int32_t clipyou = 0; - -#ifdef HAVE_CLIPSHAPE_FEATURE - if (clipsprite_try((uspritetype *)&sprite[j], xmin,ymin, xmax,ymax)) - continue; -#endif - vec2_t v1 = *(vec2_t *)&sprite[j]; - - switch (cstat & CSTAT_SPRITE_ALIGNMENT_MASK) - { - case CSTAT_SPRITE_ALIGNMENT_FACING: - { - int32_t k = walldist+(sprite[j].clipdist<<2)+1; - if ((klabs(v1.x-pos->x) <= k) && (klabs(v1.y-pos->y) <= k)) - { - daz = sprite[j].z + spriteheightofs(j, &k, 1); - daz2 = daz - k; - clipyou = 1; - } - break; - } - - case CSTAT_SPRITE_ALIGNMENT_WALL: - { - vec2_t v2; - get_wallspr_points((uspritetype *)&sprite[j], &v1.x, &v2.x, &v1.y, &v2.y); - - if (clipinsideboxline(pos->x,pos->y,v1.x,v1.y,v2.x,v2.y,walldist+1) != 0) - { - int32_t k; - daz = sprite[j].z + spriteheightofs(j, &k, 1); - daz2 = daz-k; - clipyou = 1; - } - break; - } - - case CSTAT_SPRITE_ALIGNMENT_FLOOR: - { - daz = sprite[j].z; daz2 = daz; - - if ((cstat&64) != 0 && (pos->z > daz) == ((cstat&8)==0)) - continue; - - vec2_t v2, v3, v4; - get_floorspr_points((uspritetype const *) &sprite[j], pos->x, pos->y, &v1.x, &v2.x, &v3.x, &v4.x, - &v1.y, &v2.y, &v3.y, &v4.y); - - vec2_t const da = { mulscale14(sintable[(sprite[j].ang - 256 + 512) & 2047], walldist + 4), - mulscale14(sintable[(sprite[j].ang - 256) & 2047], walldist + 4) }; - - v1.x += da.x; v2.x -= da.y; v3.x -= da.x; v4.x += da.y; - v1.y += da.y; v2.y += da.x; v3.y -= da.y; v4.y -= da.x; - - clipyou = get_floorspr_clipyou(v1.x, v2.x, v3.x, v4.x, v1.y, v2.y, v3.y, v4.y); - break; - } - } - - if (clipyou != 0) - { - if ((pos->z > daz) && (daz > *ceilz -#ifdef YAX_ENABLE - || (daz == *ceilz && yax_getbunch(clipsectorlist[i], YAX_CEILING)>=0) -#endif - )) - { - *ceilz = daz; - *ceilhit = j+49152; - } - - if ((pos->z < daz2) && (daz2 < *florz -#ifdef YAX_ENABLE - // can have a floor-sprite lying directly on the floor! - || (daz2 == *florz && yax_getbunch(clipsectorlist[i], YAX_FLOOR)>=0) -#endif - )) - { - *florz = daz2; - *florhit = j+49152; - } - } - } - } - } - -#ifdef HAVE_CLIPSHAPE_FEATURE - if (clipspritenum>0) - goto beginagain; -#endif - -#ifdef YAX_ENABLE - if (numyaxbunches > 0) - { - int const dasecclipmask = yax_waltosecmask(dawalclipmask); - int16_t cb, fb; - - yax_getbunches(sectnum, &cb, &fb); - - mcf++; - clipsectcnt = 0; clipsectnum = 0; - - int didchange = 0; - if (cb>=0 && mcf==0 && *ceilhit==sectnum+16384) - { - int i; - for (i=0; i= 0) - if (sector[j].ceilingstat&dasecclipmask) - break; - } - - if (i==origclipsectnum) - for (i=0; ix,pos->y, j)==1) - { - clipsectorlist[clipsectnum++] = j; - int const daz = getceilzofslope(j, pos->x,pos->y); - if (!didchange || daz > *ceilz) - didchange=1, *ceilhit = j+16384, *ceilz = daz; - } - } - - if (clipsectnum==0) - mcf++; - } - else if (mcf==0) - mcf++; - - didchange = 0; - if (fb>=0 && mcf==1 && *florhit==sectnum+16384) - { - int i=0; - for (; i= 0) - if (sector[j].floorstat&dasecclipmask) - break; - } - - // (almost) same as above, but with floors... - if (i==origclipsectnum) - for (i=0; ix,pos->y, j)==1) - { - clipsectorlist[clipsectnum++] = j; - int const daz = getflorzofslope(j, pos->x,pos->y); - if (!didchange || daz < *florz) - didchange=1, *florhit = j+16384, *florz = daz; - } - } - } - - if (clipsectnum > 0) - { - // sector-like sprite re-init: - curidx = -1; - curspr = NULL; - clipspritecnt = 0; clipspritenum = 0; - - goto restart_grand; - } - } -#endif -} - int32_t setaspect_new_use_dimen = 0; void videoSetCorrectedAspect()