From 2395749192b406305f0340322f04c55b9d79ec65 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Sep 2020 17:35:08 +0200 Subject: [PATCH] - restored the automap texture drawer in the backend. While ultimately this needs to be tossed into the deepest bowels of hell for being one gargantuan piece of bad code, it is still needed and does not really work when placed in a separate source file, due to its endless list of global dependencies. --- source/build/src/engine.cpp | 366 +++++++++++++++++++++++++++++++++++- 1 file changed, 365 insertions(+), 1 deletion(-) diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index 8f138dbbf..417e685c9 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -30,7 +30,6 @@ #include "gamestate.h" #include "inputstate.h" #include "printf.h" -#include "gamecontrol.h" #ifdef USE_OPENGL # include "mdsprite.h" @@ -1779,6 +1778,371 @@ killsprite: } +//========================================================================== +// +// +// +//========================================================================== + +void FillPolygon(int* rx1, int* ry1, int* xb1, int32_t npoints, int picnum, int palette, int shade, int props, const FVector2& xtex, const FVector2& ytex, const FVector2& otex, + int clipx1, int clipy1, int clipx2, int clipy2) +{ + //Convert int32_t to float (in-place) + TArray points(npoints, true); + using Point = std::pair; + std::vector> polygon; + std::vector* curPoly; + + polygon.resize(1); + curPoly = &polygon.back(); + + for (bssize_t i = 0; i < npoints; ++i) + { + auto X = ((float)rx1[i]) * (1.0f / 4096.f); + auto Y = ((float)ry1[i]) * (1.0f / 4096.f); + curPoly->push_back(std::make_pair(X, Y)); + if (xb1[i] < i && i < npoints - 1) + { + polygon.resize(polygon.size() + 1); + curPoly = &polygon.back(); + } + } + // Now make sure that the outer boundary is the first polygon by picking a point that's as much to the outside as possible. + int outer = 0; + float minx = FLT_MAX; + float miny = FLT_MAX; + for (size_t a = 0; a < polygon.size(); a++) + { + for (auto& pt : polygon[a]) + { + if (pt.first < minx || (pt.first == minx && pt.second < miny)) + { + minx = pt.first; + miny = pt.second; + outer = a; + } + } + } + if (outer != 0) std::swap(polygon[0], polygon[outer]); + auto indices = mapbox::earcut(polygon); + + int p = 0; + for (size_t a = 0; a < polygon.size(); a++) + { + for (auto& pt : polygon[a]) + { + FVector4 point = { pt.first, pt.second, float(pt.first * xtex.X + pt.second * ytex.X + otex.X), float(pt.first * xtex.Y + pt.second * ytex.Y + otex.Y) }; + points[p++] = point; + } + } + + int maskprops = (props >> 7) & DAMETH_MASKPROPS; + FRenderStyle rs = LegacyRenderStyles[STYLE_Translucent]; + double alpha = 1.; + if (maskprops > DAMETH_MASK) + { + rs = GetRenderStyle(0, maskprops == DAMETH_TRANS2); + alpha = GetAlphaFromBlend(maskprops, 0); + } + int translation = TRANSLATION(Translation_Remap + curbasepal, palette); + int light = clamp(scale((numshades - shade), 255, numshades), 0, 255); + PalEntry pe = PalEntry(uint8_t(alpha*255), light, light, light); + + twod->AddPoly(tileGetTexture(picnum), points.Data(), points.Size(), indices.data(), indices.size(), translation, pe, rs, clipx1, clipy1, clipx2, clipy2); +} + +void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, PalEntry p) +{ + twod->AddLine(x1 / 4096.f, y1 / 4096.f, x2 / 4096.f, y2 / 4096.f, windowxy1.x, windowxy1.y, windowxy2.x, windowxy2.y, p); +} + +void drawlinergb(int32_t x1, int32_t y1, int32_t x2, int32_t y2, palette_t p) +{ + drawlinergb(x1, y1, x2, y2, PalEntry(p.r, p.g, p.b)); +} + +void renderDrawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t col) +{ + drawlinergb(x1, y1, x2, y2, GPalette.BaseColors[GPalette.Remap[col]]); +} + + +//========================================================================== +// +// +// +//========================================================================== + + +#include "build.h" +#include "../src/engine_priv.h" + + +// +// fillpolygon (internal) +// +static void renderFillPolygon(int32_t npoints) +{ + // fix for bad next-point (xb1) values... + for (int z = 0; z < npoints; z++) + if ((unsigned)xb1[z] >= (unsigned)npoints) + xb1[z] = 0; + + FVector2 xtex, ytex, otex; + int x1 = mulscale16(globalx1, xyaspect); + int y2 = mulscale16(globaly2, xyaspect); + xtex.X = ((float)asm1) * (1.f / 4294967296.f); + xtex.Y = ((float)asm2) * (1.f / 4294967296.f); + ytex.X = ((float)x1) * (1.f / 4294967296.f); + ytex.Y = ((float)y2) * (-1.f / 4294967296.f); + otex.X = (fxdim * xtex.X + fydim * ytex.X) * -0.5f + fglobalposx * (1.f / 4294967296.f); + otex.Y = (fxdim * xtex.Y + fydim * ytex.Y) * -0.5f - fglobalposy * (1.f / 4294967296.f); + FillPolygon(rx1, ry1, xb1, npoints, globalpicnum, globalpal, globalshade, globalorientation, xtex, ytex, otex, windowxy1.x, windowxy1.y, windowxy2.x, windowxy2.y); +} + +// +// drawmapview +// +void renderDrawMapView(int32_t dax, int32_t day, int32_t zoome, int16_t ang) +{ + int32_t i, j, k, l; + int32_t x, y; + int32_t s, ox, oy; + + int32_t const oyxaspect = yxaspect, oviewingrange = viewingrange; + + renderSetAspect(65536, divscale16((320*5)/8, 200)); + + Bmemset(gotsector, 0, sizeof(gotsector)); + + vec2_t const c1 = { (windowxy1.x<<12), (windowxy1.y<<12) }; + vec2_t const c2 = { ((windowxy2.x+1)<<12)-1, ((windowxy2.y+1)<<12)-1 }; + + zoome <<= 8; + + vec2_t const bakgvect = { divscale28(sintable[(1536 - ang) & 2047], zoome), + divscale28(sintable[(2048 - ang) & 2047], zoome) }; + vec2_t const vect = { mulscale8(sintable[(2048 - ang) & 2047], zoome), mulscale8(sintable[(1536 - ang) & 2047], zoome) }; + vec2_t const vect2 = { mulscale16(vect.x, yxaspect), mulscale16(vect.y, yxaspect) }; + + int32_t sortnum = 0; + + usectorptr_t sec; + + for (s=0,sec=(usectorptr_t)§or[s]; swallptr; + j = startwall; l = 0; + uwallptr_t wal; + int32_t w; + for (w=sec->wallnum,wal=(uwallptr_t)&wall[startwall]; w>0; w--,wal++,j++) + { + k = lastwall(j); + if ((k > j) && (npoints > 0)) { xb1[npoints-1] = l; l = npoints; } //overwrite point2 + //wall[k].x wal->x wall[wal->point2].x + //wall[k].y wal->y wall[wal->point2].y + if (!dmulscale1(wal->x-wall[k].x,wall[wal->point2].y-wal->y,-(wal->y-wall[k].y),wall[wal->point2].x-wal->x)) continue; + ox = wal->x - dax; oy = wal->y - day; + x = dmulscale16(ox,vect.x,-oy,vect.y) + (xdim<<11); + y = dmulscale16(oy,vect2.x,ox,vect2.y) + (ydim<<11); + i |= getclipmask(x-c1.x,c2.x-x,y-c1.y,c2.y-y); + rx1[npoints] = x; + ry1[npoints] = y; + xb1[npoints] = npoints+1; + npoints++; + } + if (npoints > 0) xb1[npoints-1] = l; //overwrite point2 + + vec2_t bak = { rx1[0], mulscale16(ry1[0]-(ydim<<11),xyaspect)+(ydim<<11) }; + + + //Collect floor sprites to draw + for (i=headspritesect[s]; i>=0; i=nextspritesect[i]) + { + if (sprite[i].cstat & 32768) + continue; + + if ((sprite[i].cstat & 48) == 32) + { + if ((sprite[i].cstat & (64 + 8)) == (64 + 8)) + continue; + tsprite[sortnum++].owner = i; + } + } + gotsector[s>>3] |= pow2char[s&7]; + + globalorientation = (int32_t)sec->floorstat; + if ((globalorientation&1) != 0) continue; + + globalpal = sec->floorpal; + + globalpicnum = sec->floorpicnum; + if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0; + tileUpdatePicnum(&globalpicnum, s); + setgotpic(globalpicnum); + if ((tilesiz[globalpicnum].x <= 0) || (tilesiz[globalpicnum].y <= 0)) continue; + + globalshade = max(min(sec->floorshade, numshades - 1), 0); + if ((globalorientation&64) == 0) + { + set_globalpos(dax, day, globalposz); + globalx1 = bakgvect.x; globaly1 = bakgvect.y; + globalx2 = bakgvect.x; globaly2 = bakgvect.y; + } + else + { + ox = wall[wall[startwall].point2].x - wall[startwall].x; + oy = wall[wall[startwall].point2].y - wall[startwall].y; + i = nsqrtasm(uhypsq(ox,oy)); if (i == 0) continue; + i = 1048576/i; + globalx1 = mulscale10(dmulscale10(ox,bakgvect.x,oy,bakgvect.y),i); + globaly1 = mulscale10(dmulscale10(ox,bakgvect.y,-oy,bakgvect.x),i); + ox = (bak.x>>4)-(xdim<<7); oy = (bak.y>>4)-(ydim<<7); + globalposx = dmulscale28(-oy, globalx1, -ox, globaly1); + globalposy = dmulscale28(-ox, globalx1, oy, globaly1); + globalx2 = -globalx1; + globaly2 = -globaly1; + + int32_t const daslope = sector[s].floorheinum; + i = nsqrtasm(daslope*daslope+16777216); + set_globalpos(globalposx, mulscale12(globalposy,i), globalposz); + globalx2 = mulscale12(globalx2,i); + globaly2 = mulscale12(globaly2,i); + } + + calc_globalshifts(); + + if ((globalorientation&0x4) > 0) + { + i = globalposx; globalposx = -globalposy; globalposy = -i; + i = globalx2; globalx2 = globaly1; globaly1 = i; + i = globalx1; globalx1 = -globaly2; globaly2 = -i; + } + if ((globalorientation&0x10) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalposx = -globalposx; + if ((globalorientation&0x20) > 0) globalx2 = -globalx2, globaly2 = -globaly2, globalposy = -globalposy; + asm1 = (globaly1<floorxpanning)<<24), + ((int64_t) globalposy<<(20+globalyshift))-(((uint32_t) sec->floorypanning)<<24), + globalposz); + renderFillPolygon(npoints); + } + + //Sort sprite list + int32_t gap = 1; + + while (gap < sortnum) gap = (gap << 1) + 1; + + for (gap>>=1; gap>0; gap>>=1) + for (i=0; i=0; j-=gap) + { + if (sprite[tsprite[j].owner].z <= sprite[tsprite[j+gap].owner].z) break; + swapshort(&tsprite[j].owner,&tsprite[j+gap].owner); + } + + for (s=sortnum-1; s>=0; s--) + { + auto const spr = (uspritetype * )&sprite[tsprite[s].owner]; + if ((spr->cstat&48) == 32) + { + const int32_t xspan = tilesiz[spr->picnum].x; + + int32_t npoints = 0; + vec2_t v1 = { spr->x, spr->y }, v2, v3, v4; + + get_floorspr_points(spr, 0, 0, &v1.x, &v2.x, &v3.x, &v4.x, + &v1.y, &v2.y, &v3.y, &v4.y); + + xb1[0] = 1; xb1[1] = 2; xb1[2] = 3; xb1[3] = 0; + npoints = 4; + + i = 0; + + ox = v1.x - dax; oy = v1.y - day; + x = dmulscale16(ox,vect.x,-oy,vect.y) + (xdim<<11); + y = dmulscale16(oy,vect2.x,ox,vect2.y) + (ydim<<11); + i |= getclipmask(x-c1.x,c2.x-x,y-c1.y,c2.y-y); + rx1[0] = x; ry1[0] = y; + + ox = v2.x - dax; oy = v2.y - day; + x = dmulscale16(ox,vect.x,-oy,vect.y) + (xdim<<11); + y = dmulscale16(oy,vect2.x,ox,vect2.y) + (ydim<<11); + i |= getclipmask(x-c1.x,c2.x-x,y-c1.y,c2.y-y); + rx1[1] = x; ry1[1] = y; + + ox = v3.x - dax; oy = v3.y - day; + x = dmulscale16(ox,vect.x,-oy,vect.y) + (xdim<<11); + y = dmulscale16(oy,vect2.x,ox,vect2.y) + (ydim<<11); + i |= getclipmask(x-c1.x,c2.x-x,y-c1.y,c2.y-y); + rx1[2] = x; ry1[2] = y; + + x = rx1[0]+rx1[2]-rx1[1]; + y = ry1[0]+ry1[2]-ry1[1]; + i |= getclipmask(x-c1.x,c2.x-x,y-c1.y,c2.y-y); + rx1[3] = x; ry1[3] = y; + + + vec2_t bak = { rx1[0], mulscale16(ry1[0] - (ydim << 11), xyaspect) + (ydim << 11) }; + + + globalpicnum = spr->picnum; + globalpal = spr->pal; // GL needs this, software doesn't + if ((unsigned)globalpicnum >= (unsigned)MAXTILES) globalpicnum = 0; + tileUpdatePicnum(&globalpicnum, s); + setgotpic(globalpicnum); + if ((tilesiz[globalpicnum].x <= 0) || (tilesiz[globalpicnum].y <= 0)) continue; + + if ((sector[spr->sectnum].ceilingstat&1) > 0) + globalshade = ((int32_t)sector[spr->sectnum].ceilingshade); + else + globalshade = ((int32_t)sector[spr->sectnum].floorshade); + globalshade = max(min(globalshade+spr->shade+6,numshades-1),0); + + //relative alignment stuff + ox = v2.x-v1.x; oy = v2.y-v1.y; + i = ox*ox+oy*oy; if (i == 0) continue; i = 65536*16384 / i; + globalx1 = mulscale10(dmulscale10(ox,bakgvect.x,oy,bakgvect.y),i); + globaly1 = mulscale10(dmulscale10(ox,bakgvect.y,-oy,bakgvect.x),i); + ox = v1.y-v4.y; oy = v4.x-v1.x; + i = ox*ox+oy*oy; if (i == 0) continue; i = 65536 * 16384 / i; + globalx2 = mulscale10(dmulscale10(ox,bakgvect.x,oy,bakgvect.y),i); + globaly2 = mulscale10(dmulscale10(ox,bakgvect.y,-oy,bakgvect.x),i); + + ox = widthBits(globalpicnum); + oy = heightBits(globalpicnum); + if ((1 << ox) != xspan) + { + ox++; + globalx1 = mulscale(globalx1,xspan,ox); + globaly1 = mulscale(globaly1,xspan,ox); + } + + bak.x = (bak.x>>4)-(xdim<<7); bak.y = (bak.y>>4)-(ydim<<7); + globalposx = dmulscale28(-bak.y,globalx1,-bak.x,globaly1); + globalposy = dmulscale28(bak.x,globalx2,-bak.y,globaly2); + + if ((spr->cstat&0x4) > 0) globalx1 = -globalx1, globaly1 = -globaly1, globalposx = -globalposx; + asm1 = (globaly1<<2); globalx1 <<= 2; globalposx <<= (20+2); + asm2 = (globalx2<<2); globaly2 <<= 2; globalposy <<= (20+2); + + set_globalpos(globalposx, globalposy, globalposz); + + // so polymost can get the translucency. ignored in software mode: + globalorientation = ((spr->cstat&2)<<7) | ((spr->cstat&512)>>2); + renderFillPolygon(npoints); + } + } + + + renderSetAspect(oviewingrange, oyxaspect); +} + +//////////////////// LOADING AND SAVING ROUTINES //////////////////// static FORCE_INLINE int32_t have_maptext(void) {