From d5f7e5becf4777cf84f8e94d65ab23169e0b604f Mon Sep 17 00:00:00 2001 From: helixhorned Date: Sun, 14 Oct 2012 20:41:34 +0000 Subject: [PATCH] Texel-granular hitscan() for wall-aligned sprites. The attribute is set per tile from DEF: either texhitscanrange or tilefromtexture { ... 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 --- polymer/eduke32/build/include/build.h | 2 + polymer/eduke32/build/src/defs.c | 65 ++++++++++++++++++--------- polymer/eduke32/build/src/engine.c | 64 ++++++++++++++++++-------- 3 files changed, 91 insertions(+), 40 deletions(-) diff --git a/polymer/eduke32/build/include/build.h b/polymer/eduke32/build/include/build.h index 01fa0ca28..3ebc266fe 100644 --- a/polymer/eduke32/build/include/build.h +++ b/polymer/eduke32/build/include/build.h @@ -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) diff --git a/polymer/eduke32/build/src/defs.c b/polymer/eduke32/build/src/defs.c index 857ecfdc8..f62360292 100644 --- a/polymer/eduke32/build/src/defs.c +++ b/polymer/eduke32/build/src/defs.c @@ -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 { 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: { diff --git a/polymer/eduke32/build/src/engine.c b/polymer/eduke32/build/src/engine.c index 45c9e7c32..f1061946a 100644 --- a/polymer/eduke32/build/src/engine.c +++ b/polymer/eduke32/build/src/engine.c @@ -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);