mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-11-10 23:02:03 +00:00
Texel-granular hitscan() for wall-aligned sprites.
The attribute is set per tile from DEF: either texhitscanrange <begintile> <endtile> or tilefromtexture <tile> { ... texhitscan ... } (As a special case, the list may only contain "texhitscan", in which case the texture is not changed.) In passing, do some cleanup for "tilefromtexture" DEF parsing: the list tokens should now be accepted in any order, and errors don't appear in the middle of the list parsing. git-svn-id: https://svn.eduke32.com/eduke32@3078 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
ce948c6ee4
commit
d5f7e5becf
3 changed files with 91 additions and 40 deletions
|
@ -147,6 +147,8 @@ void yax_drawrooms(void (*SpriteAnimFunc)(int32_t,int32_t,int32_t,int32_t),
|
|||
# define YAX_SKIPWALL(i) (i)=(i)
|
||||
#endif
|
||||
|
||||
#define PICANM_TEXHITSCAN_BIT (1<<28)
|
||||
|
||||
#define CLIPMASK0 (((1L)<<16)+1L)
|
||||
#define CLIPMASK1 (((256L)<<16)+64L)
|
||||
|
||||
|
|
|
@ -81,10 +81,11 @@ enum scripttoken_t
|
|||
T_CACHESIZE,
|
||||
T_IMPORTTILE,
|
||||
T_MUSIC,T_ID,T_SOUND,
|
||||
T_TILEFROMTEXTURE, T_XOFFSET, T_YOFFSET,
|
||||
T_TILEFROMTEXTURE, T_XOFFSET, T_YOFFSET, T_TEXHITSCAN,
|
||||
T_INCLUDEDEFAULT,
|
||||
T_ANIMSOUNDS,
|
||||
T_NOFLOORPALRANGE,
|
||||
T_TEXHITSCANRANGE,
|
||||
T_ECHO,
|
||||
};
|
||||
|
||||
|
@ -220,6 +221,7 @@ static int32_t defsparser(scriptfile *script)
|
|||
{ "sound", T_SOUND },
|
||||
{ "animsounds", T_ANIMSOUNDS }, // dummy
|
||||
{ "nofloorpalrange", T_NOFLOORPALRANGE }, // dummy
|
||||
{ "texhitscanrange", T_TEXHITSCANRANGE },
|
||||
// other stuff
|
||||
{ "undefmodel", T_UNDEFMODEL },
|
||||
{ "undefmodelrange", T_UNDEFMODELRANGE },
|
||||
|
@ -491,9 +493,9 @@ static int32_t defsparser(scriptfile *script)
|
|||
case T_TILEFROMTEXTURE:
|
||||
{
|
||||
char *texturetokptr = script->ltextptr, *textureend, *fn = NULL;
|
||||
int32_t tile=-1, token;
|
||||
int32_t alphacut = 255;
|
||||
int32_t xoffset = 0, yoffset = 0, goodtogo=0;
|
||||
int32_t tile=-1;
|
||||
int32_t alphacut = 255, texhitscan=0;
|
||||
int32_t xoffset = 0, yoffset = 0;
|
||||
|
||||
static const tokenlist tilefromtexturetokens[] =
|
||||
{
|
||||
|
@ -504,13 +506,14 @@ static int32_t defsparser(scriptfile *script)
|
|||
{ "xoff", T_XOFFSET },
|
||||
{ "yoffset", T_YOFFSET },
|
||||
{ "yoff", T_YOFFSET },
|
||||
{ "texhitscan", T_TEXHITSCAN },
|
||||
};
|
||||
|
||||
if (scriptfile_getsymbol(script,&tile)) break;
|
||||
if (scriptfile_getbraces(script,&textureend)) break;
|
||||
while (script->textptr < textureend)
|
||||
{
|
||||
token = getatoken(script,tilefromtexturetokens,sizeof(tilefromtexturetokens)/sizeof(tokenlist));
|
||||
int32_t token = getatoken(script,tilefromtexturetokens,sizeof(tilefromtexturetokens)/sizeof(tokenlist));
|
||||
switch (token)
|
||||
{
|
||||
case T_FILE:
|
||||
|
@ -521,24 +524,12 @@ static int32_t defsparser(scriptfile *script)
|
|||
scriptfile_getsymbol(script,&xoffset); break;
|
||||
case T_YOFFSET:
|
||||
scriptfile_getsymbol(script,&yoffset); break;
|
||||
case T_TEXHITSCAN:
|
||||
texhitscan = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((unsigned)tile >= MAXTILES) break; // message is printed later
|
||||
if (!fn)
|
||||
{
|
||||
initprintf("Error: missing 'file name' for tilefromtexture definition near line %s:%d\n",
|
||||
script->filename, scriptfile_getlinum(script,texturetokptr));
|
||||
break;
|
||||
}
|
||||
|
||||
alphacut = clamp(alphacut, 0, 255);
|
||||
|
||||
if (check_file_exist(fn))
|
||||
break;
|
||||
|
||||
goodtogo = 1;
|
||||
}
|
||||
|
||||
if ((unsigned)tile >= MAXTILES)
|
||||
|
@ -548,7 +539,22 @@ static int32_t defsparser(scriptfile *script)
|
|||
break;
|
||||
}
|
||||
|
||||
if (goodtogo)
|
||||
if (!fn)
|
||||
{
|
||||
// filefromtexture <tile> { texhitscan } sets the bit but doesn't change tile data
|
||||
if (texhitscan)
|
||||
picanm[tile] |= PICANM_TEXHITSCAN_BIT;
|
||||
else
|
||||
initprintf("Error: missing 'file name' for tilefromtexture definition near line %s:%d\n",
|
||||
script->filename, scriptfile_getlinum(script,texturetokptr));
|
||||
break;
|
||||
}
|
||||
|
||||
if (check_file_exist(fn))
|
||||
break;
|
||||
|
||||
alphacut = clamp(alphacut, 0, 255);
|
||||
|
||||
{
|
||||
int32_t xsiz, ysiz, j;
|
||||
palette_t *picptr = NULL;
|
||||
|
@ -567,6 +573,8 @@ static int32_t defsparser(scriptfile *script)
|
|||
|
||||
set_picsizanm(tile, xsiz, ysiz, (picanm[tile]&0xff0000ff)+
|
||||
(xoffset<<8)+(yoffset<<16));
|
||||
if (texhitscan)
|
||||
picanm[tile] |= PICANM_TEXHITSCAN_BIT;
|
||||
|
||||
tile_from_truecolpic(tile, picptr, alphacut);
|
||||
|
||||
|
@ -1931,6 +1939,21 @@ static int32_t defsparser(scriptfile *script)
|
|||
}
|
||||
break;
|
||||
|
||||
case T_TEXHITSCANRANGE:
|
||||
{
|
||||
int32_t b,e, i;
|
||||
|
||||
if (scriptfile_getnumber(script,&b)) break;
|
||||
if (scriptfile_getnumber(script,&e)) break;
|
||||
|
||||
b = max(b, 0);
|
||||
e = min(e, MAXTILES-1);
|
||||
|
||||
for (i=b; i<=e; i++)
|
||||
picanm[i] |= PICANM_TEXHITSCAN_BIT;
|
||||
}
|
||||
break;
|
||||
|
||||
case T_SOUND:
|
||||
case T_MUSIC:
|
||||
{
|
||||
|
|
|
@ -7920,8 +7920,10 @@ int32_t changespritestat(int16_t spritenum, int16_t newstatnum)
|
|||
//
|
||||
// lintersect (internal)
|
||||
//
|
||||
static int32_t lintersect(int32_t x1, int32_t y1, int32_t z1, int32_t x2, int32_t y2, int32_t z2, int32_t x3,
|
||||
int32_t y3, int32_t x4, int32_t y4, int32_t *intx, int32_t *inty, int32_t *intz)
|
||||
static int32_t lintersect(int32_t x1, int32_t y1, int32_t z1,
|
||||
int32_t x2, int32_t y2, int32_t z2,
|
||||
int32_t x3, int32_t y3, int32_t x4, int32_t y4,
|
||||
int32_t *intx, int32_t *inty, int32_t *intz)
|
||||
{
|
||||
//p1 to p2 is a line segment
|
||||
int32_t x21, y21, x34, y34, x31, y31, bot, topt, topu, t;
|
||||
|
@ -7959,8 +7961,11 @@ int32_t lineintersect(int32_t x1, int32_t y1, int32_t z1, int32_t x2, int32_t y2
|
|||
//
|
||||
// rintersect (internal)
|
||||
//
|
||||
static int32_t rintersect(int32_t x1, int32_t y1, int32_t z1, int32_t vx_, int32_t vy_, int32_t vz, int32_t x3,
|
||||
int32_t y3, int32_t x4, int32_t y4, int32_t *intx, int32_t *inty, int32_t *intz)
|
||||
// returns: -1 if didn't intersect, coefficient (x3--x4 fraction)<<16 else
|
||||
static int32_t rintersect(int32_t x1, int32_t y1, int32_t z1,
|
||||
int32_t vx_, int32_t vy_, int32_t vz,
|
||||
int32_t x3, int32_t y3, int32_t x4, int32_t y4,
|
||||
int32_t *intx, int32_t *inty, int32_t *intz)
|
||||
{
|
||||
//p1 towards p2 is a ray
|
||||
int64_t x34, y34, x31, y31, bot, topt, topu, t;
|
||||
|
@ -7971,16 +7976,16 @@ static int32_t rintersect(int32_t x1, int32_t y1, int32_t z1, int32_t vx_, int32
|
|||
bot = vx*y34 - vy*x34;
|
||||
if (bot >= 0)
|
||||
{
|
||||
if (bot == 0) return(0);
|
||||
if (bot == 0) return -1;
|
||||
x31 = x3-x1; y31 = y3-y1;
|
||||
topt = x31*y34 - y31*x34; if (topt < 0) return(0);
|
||||
topu = vx*y31 - vy*x31; if ((topu < 0) || (topu >= bot)) return(0);
|
||||
topt = x31*y34 - y31*x34; if (topt < 0) return -1;
|
||||
topu = vx*y31 - vy*x31; if ((topu < 0) || (topu >= bot)) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
x31 = x3-x1; y31 = y3-y1;
|
||||
topt = x31*y34 - y31*x34; if (topt > 0) return(0);
|
||||
topu = vx*y31 - vy*x31; if ((topu > 0) || (topu <= bot)) return(0);
|
||||
topt = x31*y34 - y31*x34; if (topt > 0) return -1;
|
||||
topu = vx*y31 - vy*x31; if ((topu > 0) || (topu <= bot)) return -1;
|
||||
}
|
||||
|
||||
t = (topt<<16)/bot;
|
||||
|
@ -7988,13 +7993,16 @@ static int32_t rintersect(int32_t x1, int32_t y1, int32_t z1, int32_t vx_, int32
|
|||
*inty = y1 + ((vy*t)>>16);
|
||||
*intz = z1 + ((vz*t)>>16);
|
||||
|
||||
return(1);
|
||||
t = divscale16(topu, bot);
|
||||
Bassert((unsigned)t < 65536);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
int32_t rayintersect(int32_t x1, int32_t y1, int32_t z1, int32_t vx, int32_t vy, int32_t vz, int32_t x3,
|
||||
int32_t y3, int32_t x4, int32_t y4, int32_t *intx, int32_t *inty, int32_t *intz)
|
||||
{
|
||||
return rintersect(x1, y1, z1, vx, vy, vz, x3, y3, x4, y4, intx, inty, intz);
|
||||
return (rintersect(x1, y1, z1, vx, vy, vz, x3, y3, x4, y4, intx, inty, intz) != -1);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -11290,7 +11298,7 @@ restart_grand:
|
|||
x1 = wal->x; y1 = wal->y; x2 = wal2->x; y2 = wal2->y;
|
||||
|
||||
if ((int64_t)(x1-sv->x)*(y2-sv->y) < (int64_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) == 0) 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;
|
||||
|
@ -11349,7 +11357,8 @@ restart_grand:
|
|||
#ifdef USE_OPENGL
|
||||
if (!hitallsprites)
|
||||
#endif
|
||||
if ((cstat&dasprclipmask) == 0) continue;
|
||||
if ((cstat&dasprclipmask) == 0)
|
||||
continue;
|
||||
|
||||
#ifdef HAVE_CLIPSHAPE_FEATURE
|
||||
// try and see whether this sprite's picnum has sector-like clipping data
|
||||
|
@ -11393,6 +11402,9 @@ restart_grand:
|
|||
break;
|
||||
|
||||
case 16:
|
||||
{
|
||||
int32_t ucoefup16;
|
||||
|
||||
//These lines get the 2 points of the rotated sprite
|
||||
//Given: (x1, y1) starts out as the center point
|
||||
tilenum = spr->picnum;
|
||||
|
@ -11407,19 +11419,33 @@ restart_grand:
|
|||
if ((cstat&64) != 0) //back side of 1-way sprite
|
||||
if ((int64_t)(x1-sv->x)*(y2-sv->y) < (int64_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) == 0) 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;
|
||||
|
||||
k = ((tilesizy[spr->picnum]*spr->yrepeat)<<2);
|
||||
k = ((tilesizy[tilenum]*spr->yrepeat)<<2);
|
||||
if (cstat&128) daz = spr->z+(k>>1); else daz = spr->z;
|
||||
if (picanm[spr->picnum]&0x00ff0000) daz -= ((int32_t)((int8_t)((picanm[spr->picnum]>>16)&255))*spr->yrepeat<<2);
|
||||
if ((intz < daz) && (intz > daz-k))
|
||||
if (picanm[tilenum]&0x00ff0000) daz -= ((int32_t)((int8_t)((picanm[tilenum]>>16)&255))*spr->yrepeat<<2);
|
||||
if (intz > daz-k && intz < daz)
|
||||
{
|
||||
if (picanm[tilenum]&PICANM_TEXHITSCAN_BIT)
|
||||
{
|
||||
// daz-intz > 0 && daz-intz < k
|
||||
int32_t xtex = mulscale16(ucoefup16, tilesizx[tilenum]);
|
||||
int32_t vcoefup16 = 65536-divscale16(daz-intz, k);
|
||||
int32_t ytex = mulscale16(vcoefup16, tilesizy[tilenum]);
|
||||
|
||||
const char *texel = (char *)(waloff[tilenum] + tilesizy[tilenum]*xtex + ytex);
|
||||
if (*texel == 255)
|
||||
continue;
|
||||
}
|
||||
|
||||
hit->sect = dasector; hit->wall = -1; hit->sprite = z;
|
||||
hit->pos.x = intx; hit->pos.y = inty; hit->pos.z = intz;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 32:
|
||||
if (vz == 0) continue;
|
||||
|
@ -12113,7 +12139,7 @@ int32_t clipmove(vec3_t *pos, int16_t *sectnum,
|
|||
{
|
||||
int32_t basez;
|
||||
|
||||
if (rintersect(pos->x,pos->y,0, gx,gy,0, x1,y1, x2,y2, &dax,&day,&daz) == 0)
|
||||
if (rintersect(pos->x,pos->y,0, gx,gy,0, x1,y1, x2,y2, &dax,&day,&daz) == -1)
|
||||
dax = pos->x, day = pos->y;
|
||||
daz = getflorzofslope(dasect, dax,day);
|
||||
daz2 = getflorzofslope(wal->nextsector, dax,day);
|
||||
|
@ -12141,7 +12167,7 @@ int32_t clipmove(vec3_t *pos, int16_t *sectnum,
|
|||
if ((wal->nextsector < 0) || (wal->cstat&dawalclipmask)) clipyou = 1;
|
||||
else if (editstatus == 0)
|
||||
{
|
||||
if (rintersect(pos->x,pos->y,0,gx,gy,0,x1,y1,x2,y2,&dax,&day,&daz) == 0)
|
||||
if (rintersect(pos->x,pos->y,0,gx,gy,0,x1,y1,x2,y2,&dax,&day,&daz) == -1)
|
||||
dax = pos->x, day = pos->y;
|
||||
daz = getflorzofslope(dasect, dax,day);
|
||||
daz2 = getflorzofslope(wal->nextsector, dax,day);
|
||||
|
|
Loading…
Reference in a new issue