- temporarily reinstated rotatesprite, for easier porting of the 2D code. This will have to be removed again afterward.

This commit is contained in:
Christoph Oelckers 2020-10-29 20:45:28 +01:00
parent 23c6f4434e
commit 33f44c5627
2 changed files with 276 additions and 0 deletions

View file

@ -92,6 +92,7 @@ enum {
RS_ALIGN_MASK = 768,
RS_STRETCH = 1024,
ROTATESPRITE_FULL16 = 2048,
RS_MODELSUBST= 4096,
// ROTATESPRITE_MAX-1 is the mask of all externally available orientation bits
ROTATESPRITE_MAX = 8192,
@ -497,9 +498,22 @@ void videoInit();
void videoClearViewableArea(int32_t dacol);
void videoClearScreen(int32_t dacol);
void renderDrawMapView(int32_t dax, int32_t day, int32_t zoome, int16_t ang);
void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FGameTexture *pic = nullptr, int basepal = 0);
class F2DDrawer;
void twod_rotatesprite(F2DDrawer* twod, int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
int32_t clipx1, int32_t clipy1, int32_t clipx2, int32_t clipy2, FGameTexture* pic = nullptr, int basepal = 0);
////////// specialized rotatesprite wrappers for (very) often used cases //////////
static FORCE_INLINE void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat,
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FGameTexture* pic = nullptr, int basepal = 0)
{
rotatesprite_(sx, sy, z, a, picnum, dashade, dapalnum, dastat, 0, 0, cx1, cy1, cx2, cy2, pic, basepal);
}
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) ATTRIBUTE((nonnull(1,3,4,5,6)));

View file

@ -1660,6 +1660,268 @@ void FillPolygon(int* rx1, int* ry1, int* xb1, int32_t npoints, int picnum, int
#include "build.h"
#include "../src/engine_priv.h"
//sx,sy center of sprite; screen coords*65536
//z zoom*65536. > is zoomed in
//a angle (0 is default)
//dastat&1 1:translucence
//dastat&2 1:auto-scale mode (use 320*200 coordinates)
//dastat&4 1:y-flip
//dastat&8 1:don't clip to startumost/startdmost
//dastat&16 1:force point passed to be top-left corner, 0:Editart center
//dastat&32 1:reverse translucence
//dastat&64 1:non-masked, 0:masked
//dastat&128 1:draw all pages (permanent - no longer used)
//cx1,... clip window (actual screen coords)
//==========================================================================
//
// INTERNAL helper function for classic/polymost dorotatesprite
// sxptr, sxptr, z: in/out
// ret_yxaspect, ret_xyaspect: out
//
//==========================================================================
static int32_t dorotspr_handle_bit2(int32_t* sxptr, int32_t* syptr, int32_t* z, int32_t dastat, int32_t cx1_plus_cx2, int32_t cy1_plus_cy2)
{
if ((dastat & RS_AUTO) == 0)
{
if (!(dastat & RS_STRETCH) && 4 * ydim <= 3 * xdim)
{
return (10 << 16) / 12;
}
else
{
return xyaspect;
}
}
else
{
// dastat&2: Auto window size scaling
const int32_t oxdim = xdim;
const int32_t oydim = ydim;
int32_t xdim = oxdim; // SHADOWS global
int32_t ydim = oydim;
int32_t zoomsc, sx = *sxptr, sy = *syptr;
int32_t ouryxaspect = yxaspect, ourxyaspect = xyaspect;
if (!(dastat & RS_STRETCH) && 4 * ydim <= 3 * xdim)
{
if ((dastat & RS_ALIGN_MASK) && (dastat & RS_ALIGN_MASK) != RS_ALIGN_MASK)
sx += (scale(120 << 16, xdim, ydim) - (160 << 16)) * ((!(dastat & RS_ALIGN_R))?-1:1);
if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK)
ydim = scale(xdim, 3, 4);
else
xdim = scale(ydim, 4, 3);
ouryxaspect = (12 << 16) / 10;
ourxyaspect = (10 << 16) / 12;
}
// screen center to s[xy], 320<<16 coords.
const int32_t normxofs = sx - (320 << 15), normyofs = sy - (200 << 15);
// nasty hacks go here
if (!(dastat & RS_NOCLIP))
{
const int32_t twice_midcx = cx1_plus_cx2 + 2;
// screen x center to sx1, scaled to viewport
const int32_t scaledxofs = scale(normxofs, scale(xdimen, xdim, oxdim), 320);
sx = ((twice_midcx) << 15) + scaledxofs;
zoomsc = xdimenscale; //= scale(xdimen,yxaspect,320);
if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK)
zoomsc = scale(zoomsc, ydim, oydim);
sy = ((cy1_plus_cy2 + 2) << 15) + mulscale16(normyofs, zoomsc);
}
else
{
//If not clipping to startmosts, & auto-scaling on, as a
//hard-coded bonus, scale to full screen instead
sx = (xdim << 15) + 32768 + scale(normxofs, xdim, 320);
zoomsc = scale(xdim, ouryxaspect, 320);
sy = (ydim << 15) + 32768 + mulscale16(normyofs, zoomsc);
if ((dastat & RS_ALIGN_MASK) == RS_ALIGN_MASK)
sy += (oydim - ydim) << 15;
else
sx += (oxdim - xdim) << 15;
if (dastat & RS_CENTERORIGIN)
sx += oxdim << 15;
}
*sxptr = sx;
*syptr = sy;
*z = mulscale16(*z, zoomsc);
return ourxyaspect;
}
}
//==========================================================================
//
//
//
//==========================================================================
void twod_rotatesprite(F2DDrawer *twod, int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
int32_t clipx1, int32_t clipy1, int32_t clipx2, int32_t clipy2, FGameTexture* pic, int basepal)
{
// todo: re-add
#if 0
if (!tex && (dastat & RS_MODELSUBST))
{
tileUpdatePicnum(&picnum, (int16_t)0xc000);
if ((tileWidth(picnum) <= 0) || (tileHeight(picnum) <= 0)) return;
if (hw_models && tile2model[picnum].hudmem[(dastat & 4) >> 2])
{
polymost_dorotatespritemodel(sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, dablend, guniqhudid);
return;
}
}
else
#endif
if (!pic) tileUpdatePicnum(&picnum, 0);
F2DDrawer::RenderCommand dg = {};
int method = 0;
dg.mType = F2DDrawer::DrawTypeTriangles;
if (clipx1 > 0 || clipy1 > 0 || clipx2 < screen->GetWidth() - 1 || clipy2 < screen->GetHeight() - 1)
{
dg.mScissor[0] = clipx1;
dg.mScissor[1] = clipy1;
dg.mScissor[2] = clipx2 + 1;
dg.mScissor[3] = clipy2 + 1;
dg.mFlags |= F2DDrawer::DTF_Scissor;
}
if (!(dastat & RS_NOMASK))
{
if (dastat & RS_TRANS1)
method |= (dastat & RS_TRANS2) ? DAMETH_TRANS2 : DAMETH_TRANS1;
else
method |= DAMETH_MASK;
dg.mRenderStyle = GetRenderStyle(dablend, (dastat & RS_TRANS2) ? 1 : 0);
}
else
{
dg.mRenderStyle = LegacyRenderStyles[STYLE_Normal];
}
dg.mTexture = pic ? pic : tileGetTexture(picnum);
if (!dg.mTexture || !dg.mTexture->isValid()) return; // empty tile.
// todo: check for hires replacements.
// The weapon drawer needs to use the global base palette.
dg.mTranslationId = TRANSLATION(Translation_Remap + basepal, dapalnum);
dg.mVertCount = 4;
dg.mVertIndex = (int)twod->mVertices.Reserve(4);
auto ptr = &twod->mVertices[dg.mVertIndex];
float drawpoly_alpha = daalpha * (1.0f / 255.0f);
float alpha = GetAlphaFromBlend(method, dablend) * (1.f - drawpoly_alpha); // Hmmm...
PalEntry p;
if (!hw_useindexedcolortextures)
{
int light = clamp(scale((numshades - dashade), 255, numshades), 0, 255);
p = PalEntry((uint8_t)(alpha * 255), light, light, light);
}
else
{
p = PalEntry((uint8_t)(alpha * 255), 255, 255, 255);
dg.mLightLevel = clamp(dashade, 0, numshades);
}
vec2_t const siz = { (int)dg.mTexture->GetDisplayWidth(), (int)dg.mTexture->GetDisplayHeight() };
vec2_16_t ofs = { 0, 0 };
if (!(dastat & RS_TOPLEFT))
{
if (!pic && !(dastat & RS_CENTER))
{
ofs = { int16_t(tileLeftOffset(picnum) + (siz.x >> 1)),
int16_t(tileTopOffset(picnum) + (siz.y >> 1)) };
}
else
{
ofs = { int16_t((siz.x >> 1)),
int16_t((siz.y >> 1)) };
}
}
if (dastat & RS_YFLIP)
ofs.y = siz.y - ofs.y;
int32_t aspectcorrect = dorotspr_handle_bit2(&sx, &sy, &z, dastat, clipx1 + clipx2, clipy1 + clipy2);
int32_t cosang = mulscale14(sintable[(a + 512) & 2047], z);
int32_t cosang2 = cosang;
int32_t sinang = mulscale14(sintable[a & 2047], z);
int32_t sinang2 = sinang;
if ((dastat & RS_AUTO) || (!(dastat & RS_NOCLIP))) // Don't aspect unscaled perms
{
cosang2 = mulscale16(cosang2, aspectcorrect);
sinang2 = mulscale16(sinang2, aspectcorrect);
}
int cx0 = sx - ofs.x * cosang2 + ofs.y * sinang2;
int cy0 = sy - ofs.x * sinang - ofs.y * cosang;
int cx1 = cx0 + siz.x * cosang2;
int cy1 = cy0 + siz.x * sinang;
int cx3 = cx0 - siz.y * sinang2;
int cy3 = cy0 + siz.y * cosang;
int cx2 = cx1 + cx3 - cx0;
int cy2 = cy1 + cy3 - cy0;
float y = (dastat & RS_YFLIP) ? 1.f : 0.f;
ptr->Set(cx0 / 65536.f, cy0 / 65536.f, 0.f, 0.f, y, p); ptr++;
ptr->Set(cx1 / 65536.f, cy1 / 65536.f, 0.f, 1.f, y, p); ptr++;
ptr->Set(cx2 / 65536.f, cy2 / 65536.f, 0.f, 1.f, 1.f - y, p); ptr++;
ptr->Set(cx3 / 65536.f, cy3 / 65536.f, 0.f, 0.f, 1.f - y, p); ptr++;
dg.mIndexIndex = twod->mIndices.Size();
dg.mIndexCount += 6;
twod->AddIndices(dg.mVertIndex, 6, 0, 1, 2, 0, 2, 3);
twod->AddCommand(&dg);
}
void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, FGameTexture* tex, int basepal)
{
if (!tex && (unsigned)picnum >= MAXTILES)
return;
if ((cx1 > cx2) || (cy1 > cy2)) return;
if (z <= 16) return;
// We must store all calls in the 2D drawer so that the backend can operate on a clean 3D view.
twod_rotatesprite(twod, sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, dablend, cx1, cy1, cx2, cy2, tex, basepal);
}
//
// fillpolygon (internal)