mirror of
https://github.com/ZDoom/raze-gles.git
synced 2025-01-11 18:50:46 +00:00
Move some clipping related stuff out of engine.cpp and into clip.cpp
git-svn-id: https://svn.eduke32.com/eduke32@7417 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
95fa4e04f9
commit
7ccbd22013
3 changed files with 923 additions and 919 deletions
|
@ -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);
|
||||
|
|
|
@ -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<y2);
|
||||
else if (x1 >= 0) clipyou ^= 1;
|
||||
}
|
||||
if ((y2^y3) < 0)
|
||||
{
|
||||
if ((x2^x3) < 0) clipyou ^= (x2*y3 < x3*y2)^(y2<y3);
|
||||
else if (x2 >= 0) clipyou ^= 1;
|
||||
}
|
||||
if ((y3^y4) < 0)
|
||||
{
|
||||
if ((x3^x4) < 0) clipyou ^= (x3*y4 < x4*y3)^(y3<y4);
|
||||
else if (x3 >= 0) clipyou ^= 1;
|
||||
}
|
||||
if ((y4^y1) < 0)
|
||||
{
|
||||
if ((x4^x1) < 0) clipyou ^= (x4*y1 < x1*y4)^(y4<y1);
|
||||
else if (x4 >= 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; i<clipsectnum; i++)
|
||||
{
|
||||
int const k = clipsectorlist[i];
|
||||
|
||||
if (k==sectq[clipinfo[curidx].qend])
|
||||
continue;
|
||||
|
||||
int32_t daz, daz2;
|
||||
getzsofslope(k,pos->x,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<endwall; j++)
|
||||
{
|
||||
const int k = wall[j].nextsector;
|
||||
|
||||
if (k >= 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<clipsectnum; i++)
|
||||
{
|
||||
if (dasprclipmask==0)
|
||||
break;
|
||||
|
||||
for (bssize_t j=headspritesect[clipsectorlist[i]]; j>=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<origclipsectnum; i++)
|
||||
{
|
||||
int const j = origclipsectorlist[i];
|
||||
if (yax_getbunch(j, YAX_CEILING) >= 0)
|
||||
if (sector[j].ceilingstat&dasecclipmask)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i==origclipsectnum)
|
||||
for (i=0; i<origclipsectnum; i++)
|
||||
{
|
||||
cb = yax_getbunch(origclipsectorlist[i], YAX_CEILING);
|
||||
if (cb < 0)
|
||||
continue;
|
||||
|
||||
for (bssize_t SECTORS_OF_BUNCH(cb,YAX_FLOOR, j))
|
||||
if (inside(pos->x,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<origclipsectnum; i++)
|
||||
{
|
||||
int const j = origclipsectorlist[i];
|
||||
if (yax_getbunch(j, YAX_FLOOR) >= 0)
|
||||
if (sector[j].floorstat&dasecclipmask)
|
||||
break;
|
||||
}
|
||||
|
||||
// (almost) same as above, but with floors...
|
||||
if (i==origclipsectnum)
|
||||
for (i=0; i<origclipsectnum; i++)
|
||||
{
|
||||
fb = yax_getbunch(origclipsectorlist[i], YAX_FLOOR);
|
||||
if (fb < 0)
|
||||
continue;
|
||||
|
||||
for (bssize_t SECTORS_OF_BUNCH(fb, YAX_CEILING, j))
|
||||
if (inside(pos->x,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; i<clipinfo[curidx].qend; i++)
|
||||
{
|
||||
if (inside(x1,y1,sectq[i]) == 1)
|
||||
{
|
||||
hit_set(hit, curspr->sectnum, -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]; z<endwall; z++,wal++)
|
||||
{
|
||||
const int32_t nextsector = wal->nextsector;
|
||||
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 && clipspritenum<MAXCLIPNUM)
|
||||
{
|
||||
clipspritelist[clipspritenum++] = z;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
x1 = spr->x; 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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; i<clipinfo[curidx].qend; i++)
|
||||
{
|
||||
if (inside(x1,y1,sectq[i]) == 1)
|
||||
{
|
||||
hit_set(hit, curspr->sectnum, -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<y2);
|
||||
else if (x1 >= 0) clipyou ^= 1;
|
||||
}
|
||||
if ((y2^y3) < 0)
|
||||
{
|
||||
if ((x2^x3) < 0) clipyou ^= (x2*y3 < x3*y2)^(y2<y3);
|
||||
else if (x2 >= 0) clipyou ^= 1;
|
||||
}
|
||||
if ((y3^y4) < 0)
|
||||
{
|
||||
if ((x3^x4) < 0) clipyou ^= (x3*y4 < x4*y3)^(y3<y4);
|
||||
else if (x3 >= 0) clipyou ^= 1;
|
||||
}
|
||||
if ((y4^y1) < 0)
|
||||
{
|
||||
if ((x4^x1) < 0) clipyou ^= (x4*y1 < x1*y4)^(y4<y1);
|
||||
else if (x4 >= 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]; z<endwall; z++,wal++)
|
||||
{
|
||||
const int32_t nextsector = wal->nextsector;
|
||||
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 && clipspritenum<MAXCLIPNUM)
|
||||
{
|
||||
clipspritelist[clipspritenum++] = z;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
x1 = spr->x; 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; i<clipsectnum; i++)
|
||||
{
|
||||
int const k = clipsectorlist[i];
|
||||
|
||||
if (k==sectq[clipinfo[curidx].qend])
|
||||
continue;
|
||||
|
||||
int32_t daz, daz2;
|
||||
getzsofslope(k,pos->x,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<endwall; j++)
|
||||
{
|
||||
const int k = wall[j].nextsector;
|
||||
|
||||
if (k >= 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<clipsectnum; i++)
|
||||
{
|
||||
if (dasprclipmask==0)
|
||||
break;
|
||||
|
||||
for (bssize_t j=headspritesect[clipsectorlist[i]]; j>=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<origclipsectnum; i++)
|
||||
{
|
||||
int const j = origclipsectorlist[i];
|
||||
if (yax_getbunch(j, YAX_CEILING) >= 0)
|
||||
if (sector[j].ceilingstat&dasecclipmask)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i==origclipsectnum)
|
||||
for (i=0; i<origclipsectnum; i++)
|
||||
{
|
||||
cb = yax_getbunch(origclipsectorlist[i], YAX_CEILING);
|
||||
if (cb < 0)
|
||||
continue;
|
||||
|
||||
for (bssize_t SECTORS_OF_BUNCH(cb,YAX_FLOOR, j))
|
||||
if (inside(pos->x,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<origclipsectnum; i++)
|
||||
{
|
||||
int const j = origclipsectorlist[i];
|
||||
if (yax_getbunch(j, YAX_FLOOR) >= 0)
|
||||
if (sector[j].floorstat&dasecclipmask)
|
||||
break;
|
||||
}
|
||||
|
||||
// (almost) same as above, but with floors...
|
||||
if (i==origclipsectnum)
|
||||
for (i=0; i<origclipsectnum; i++)
|
||||
{
|
||||
fb = yax_getbunch(origclipsectorlist[i], YAX_FLOOR);
|
||||
if (fb < 0)
|
||||
continue;
|
||||
|
||||
for (bssize_t SECTORS_OF_BUNCH(fb, YAX_CEILING, j))
|
||||
if (inside(pos->x,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()
|
||||
|
|
Loading…
Reference in a new issue