engine.c: factor out 2 pract. ident. pieces of code into try_facespr_intersect.

The two uses are from hitscan and neartag.  The functionality is reproduced
exactly (assuming I made no mistake), down to different distance checking
(<= vs. <).

git-svn-id: https://svn.eduke32.com/eduke32@3228 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2012-11-25 13:18:57 +00:00
parent dacf2695ff
commit ca4ef47f0b
2 changed files with 70 additions and 77 deletions

View file

@ -848,7 +848,11 @@ int32_t changespritestat(int16_t spritenum, int16_t newstatnum);
int32_t setsprite(int16_t spritenum, const vec3_t *) ATTRIBUTE((nonnull(2))); int32_t setsprite(int16_t spritenum, const vec3_t *) ATTRIBUTE((nonnull(2)));
int32_t setspritez(int16_t spritenum, const vec3_t *) ATTRIBUTE((nonnull(2))); int32_t setspritez(int16_t spritenum, const vec3_t *) ATTRIBUTE((nonnull(2)));
int32_t spriteheightofs(int16_t i, int32_t *height, int32_t alsotileyofs) ATTRIBUTE((nonnull(2))); int32_t spriteheightofsptr(const spritetype *spr, int32_t *height, int32_t alsotileyofs);
static inline int32_t spriteheightofs(int16_t i, int32_t *height, int32_t alsotileyofs)
{
return spriteheightofsptr(&sprite[i], height, alsotileyofs);
}
int32_t screencapture(const char *filename, char inverseit, const char *versionstr) ATTRIBUTE((nonnull(1))); int32_t screencapture(const char *filename, char inverseit, const char *versionstr) ATTRIBUTE((nonnull(1)));

View file

@ -10883,15 +10883,15 @@ int32_t krecip(int32_t num)
// Gets the BUILD unit height and z offset of a sprite. // Gets the BUILD unit height and z offset of a sprite.
// Returns the z offset, 'height' may be NULL. // Returns the z offset, 'height' may be NULL.
int32_t spriteheightofs(int16_t i, int32_t *height, int32_t alsotileyofs) int32_t spriteheightofsptr(const spritetype *spr, int32_t *height, int32_t alsotileyofs)
{ {
int32_t hei, zofs=0; int32_t hei, zofs=0;
const int32_t picnum=sprite[i].picnum, yrepeat=sprite[i].yrepeat; const int32_t picnum=spr->picnum, yrepeat=spr->yrepeat;
hei = (tilesizy[picnum]*yrepeat)<<2; hei = (tilesizy[picnum]*yrepeat)<<2;
*height = hei; *height = hei;
if (sprite[i].cstat&128) if (spr->cstat&128)
zofs = hei>>1; zofs = hei>>1;
// NOTE: a positive per-tile yoffset translates the sprite into the // NOTE: a positive per-tile yoffset translates the sprite into the
@ -11352,6 +11352,53 @@ static int32_t get_flatspr_clipyou(int32_t x1, int32_t x2, int32_t x3, int32_t x
return clipyou; return clipyou;
} }
// intp: point of currently best (closest) intersection
static int32_t try_facespr_intersect(const spritetype *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 = tilesizx[spr->picnum]*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 // hitscan
// //
@ -11533,30 +11580,13 @@ restart_grand:
{ {
case 0: case 0:
{ {
int32_t topt, topu, bot, dist, offx, offy; if (try_facespr_intersect(spr, sv, vx, vy, vz, &hit->pos, 0))
{
hit->sect = dasector;
hit->wall = -1;
hit->sprite = z;
}
topt = vx*(x1-sv->x) + vy*(y1-sv->y); if (topt <= 0) continue;
bot = vx*vx + vy*vy; if (bot == 0) continue;
intz = sv->z+scale(vz,topt,bot);
z1 += spriteheightofs(z, &i, 1);
if ((intz > z1) || (intz < z1-i)) continue;
topu = vx*(y1-sv->y) - vy*(x1-sv->x);
offx = scale(vx,topu,bot);
offy = scale(vy,topu,bot);
dist = offx*offx + offy*offy;
i = tilesizx[spr->picnum]*spr->xrepeat; i *= i;
if (dist > (i>>7)) continue;
intx = sv->x + scale(vx,topt,bot);
inty = sv->y + scale(vy,topt,bot);
if (klabs(intx-sv->x)+klabs(inty-sv->y) > klabs((hit->pos.x)-sv->x)+klabs((hit->pos.y)-sv->y))
continue;
hit->sect = dasector; hit->wall = -1; hit->sprite = z;
hit->pos.x = intx; hit->pos.y = inty; hit->pos.z = intz;
break; break;
} }
@ -11704,10 +11734,8 @@ void neartag(int32_t xs, int32_t ys, int32_t zs, int16_t sectnum, int16_t ange,
const int32_t vx = mulscale14(sintable[(ange+2560)&2047],neartagrange); const int32_t vx = mulscale14(sintable[(ange+2560)&2047],neartagrange);
const int32_t vy = mulscale14(sintable[(ange+2048)&2047],neartagrange); const int32_t vy = mulscale14(sintable[(ange+2048)&2047],neartagrange);
const int32_t vz = 0; vec3_t hitv = { xs+vx, ys+vy, 0 };
int32_t xe = xs+vx; const vec3_t sv = { xs, ys, zs };
int32_t ye = ys+vy;
int32_t ze = 0;
*neartagsector = -1; *neartagwall = -1; *neartagsprite = -1; *neartagsector = -1; *neartagwall = -1; *neartagsprite = -1;
*neartaghitdist = 0; *neartaghitdist = 0;
@ -11747,14 +11775,14 @@ void neartag(int32_t xs, int32_t ys, int32_t zs, int16_t sectnum, int16_t ange,
if ((good == 0) && (nextsector < 0)) continue; if ((good == 0) && (nextsector < 0)) continue;
if ((int64_t)(x1-xs)*(y2-ys) < (int64_t)(x2-xs)*(y1-ys)) continue; if ((int64_t)(x1-xs)*(y2-ys) < (int64_t)(x2-xs)*(y1-ys)) continue;
if (lintersect(xs,ys,zs,xe,ye,ze,x1,y1,x2,y2,&intx,&inty,&intz) == 1) if (lintersect(xs,ys,zs,hitv.x,hitv.y,hitv.z,x1,y1,x2,y2,&intx,&inty,&intz) == 1)
{ {
if (good != 0) if (good != 0)
{ {
if (good&1) *neartagsector = nextsector; if (good&1) *neartagsector = nextsector;
if (good&2) *neartagwall = z; if (good&2) *neartagwall = z;
*neartaghitdist = dmulscale14(intx-xs,sintable[(ange+2560)&2047],inty-ys,sintable[(ange+2048)&2047]); *neartaghitdist = dmulscale14(intx-xs,sintable[(ange+2560)&2047],inty-ys,sintable[(ange+2048)&2047]);
xe = intx; ye = inty; ze = intz; hitv.x = intx; hitv.y = inty; hitv.z = intz;
} }
if (nextsector >= 0) if (nextsector >= 0)
@ -11775,56 +11803,17 @@ void neartag(int32_t xs, int32_t ys, int32_t zs, int16_t sectnum, int16_t ange,
for (z=headspritesect[dasector]; z>=0; z=nextspritesect[z]) for (z=headspritesect[dasector]; z>=0; z=nextspritesect[z])
{ {
const spritetype *const spr = &sprite[z]; const spritetype *const spr = &sprite[z];
int32_t good = 0;
if (blacklist_sprite_func && blacklist_sprite_func(z)) if (blacklist_sprite_func && blacklist_sprite_func(z))
continue; continue;
if ((tagsearch&1) && spr->lotag) good |= 1; if (((tagsearch&1) && spr->lotag) || ((tagsearch&2) && spr->hitag))
if ((tagsearch&2) && spr->hitag) good |= 1;
if (good != 0)
{ {
const int32_t x1=spr->x, y1=spr->y; if (try_facespr_intersect(spr, &sv, vx, vy, 0, &hitv, 1))
int32_t z1=spr->z;
const int32_t topt = vx*(x1-xs) + vy*(y1-ys);
if (topt > 0)
{ {
const int32_t bot = vx*vx + vy*vy; *neartagsprite = z;
*neartaghitdist = dmulscale14(hitv.x-xs, sintable[(ange+2560)&2047],
if (bot != 0) hitv.y-ys, sintable[(ange+2048)&2047]);
{
int32_t i;
const int32_t intz = zs+scale(vz,topt,bot);
z1 += spriteheightofs(z, &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 = (tilesizx[spr->picnum]*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) < klabs(xe-xs)+klabs(ye-ys))
{
*neartagsprite = z;
*neartaghitdist = dmulscale14(intx-xs,sintable[(ange+2560)&2047],inty-ys,sintable[(ange+2048)&2047]);
xe = intx;
ye = inty;
ze = intz;
}
}
}
}
} }
} }
} }