OGL affines
We lose hardware spritesplits in the process; I do not care
This commit is contained in:
parent
307e334e27
commit
7792079fbc
2 changed files with 394 additions and 42 deletions
|
|
@ -43,6 +43,12 @@ typedef struct
|
|||
float z;
|
||||
} polyvertex_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
} f_vector2_t;
|
||||
|
||||
// a convex 'plane' polygon, clockwise order
|
||||
typedef struct
|
||||
{
|
||||
|
|
@ -84,6 +90,28 @@ typedef struct gl_vissprite_s
|
|||
|
||||
angle_t angle; // for splats
|
||||
|
||||
// Affine nonsense
|
||||
struct {
|
||||
// Vertex points for the affine sprite to be drawn to.
|
||||
//
|
||||
// 4--3
|
||||
// | /|
|
||||
// |/ |
|
||||
// 1--2
|
||||
f_vector2_t p1, p2, p3, p4;
|
||||
|
||||
// The "root", or center, of the affine sprite
|
||||
polyvertex_t root;
|
||||
|
||||
// Bounding point (leftmost and highest point), to resolve clipping
|
||||
polyvertex_t bounding_point;
|
||||
|
||||
// Sine/cosine multiplier, used for billboarding.
|
||||
float patchsin, patchcos;
|
||||
|
||||
affine_t transform; // The actual affine transformation.
|
||||
} affine;
|
||||
|
||||
//Hurdler: 25/04/2000: now support colormap in hardware mode
|
||||
UINT8 *colormap;
|
||||
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
|
||||
|
|
|
|||
|
|
@ -3343,6 +3343,8 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
|||
// This is expecting a pointer to an array containing 4 wallVerts for a sprite
|
||||
static void HWR_RotateSpritePolyToAim(gl_vissprite_t *spr, FOutVector *wallVerts, const boolean precip)
|
||||
{
|
||||
const boolean affine = ((spr->mobj && !P_MobjWasRemoved(spr->mobj)) && ((spr->mobj->player != NULL) || R_ThingIsAffineSprite(spr->mobj)));
|
||||
|
||||
if (cv_glspritebillboarding.value
|
||||
&& spr && spr->mobj && !R_ThingIsPaperSprite(spr->mobj)
|
||||
&& wallVerts)
|
||||
|
|
@ -3370,20 +3372,42 @@ static void HWR_RotateSpritePolyToAim(gl_vissprite_t *spr, FOutVector *wallVerts
|
|||
// X, Y, AND Z need to be manipulated for the polys to rotate around the
|
||||
// origin, because of how the origin setting works I believe that should
|
||||
// be mobj->z or mobj->z + mobj->height
|
||||
wallVerts[2].y = wallVerts[3].y = (spr->gzt - basey) * gl_viewludsin + basey;
|
||||
wallVerts[0].y = wallVerts[1].y = (lowy - basey) * gl_viewludsin + basey;
|
||||
// translate back to be around 0 before translating back
|
||||
wallVerts[3].x += ((spr->gzt - basey) * gl_viewludcos) * gl_viewcos;
|
||||
wallVerts[2].x += ((spr->gzt - basey) * gl_viewludcos) * gl_viewcos;
|
||||
|
||||
wallVerts[0].x += ((lowy - basey) * gl_viewludcos) * gl_viewcos;
|
||||
wallVerts[1].x += ((lowy - basey) * gl_viewludcos) * gl_viewcos;
|
||||
if (affine)
|
||||
{
|
||||
wallVerts[0].y = (spr->affine.p1.y * gl_viewludsin) + spr->affine.root.y;
|
||||
wallVerts[0].x += (spr->affine.p1.y * gl_viewludcos) * gl_viewcos;
|
||||
wallVerts[0].z += (spr->affine.p1.y * gl_viewludcos) * gl_viewsin;
|
||||
|
||||
wallVerts[3].z += ((spr->gzt - basey) * gl_viewludcos) * gl_viewsin;
|
||||
wallVerts[2].z += ((spr->gzt - basey) * gl_viewludcos) * gl_viewsin;
|
||||
wallVerts[1].y = (spr->affine.p2.y * gl_viewludsin) + spr->affine.root.y;
|
||||
wallVerts[1].x += (spr->affine.p2.y * gl_viewludcos) * gl_viewcos;
|
||||
wallVerts[1].z += (spr->affine.p2.y * gl_viewludcos) * gl_viewsin;
|
||||
|
||||
wallVerts[0].z += ((lowy - basey) * gl_viewludcos) * gl_viewsin;
|
||||
wallVerts[1].z += ((lowy - basey) * gl_viewludcos) * gl_viewsin;
|
||||
wallVerts[2].y = (spr->affine.p3.y * gl_viewludsin) + spr->affine.root.y;
|
||||
wallVerts[2].x += (spr->affine.p3.y * gl_viewludcos) * gl_viewcos;
|
||||
wallVerts[2].z += (spr->affine.p3.y * gl_viewludcos) * gl_viewsin;
|
||||
|
||||
wallVerts[3].y = (spr->affine.p4.y * gl_viewludsin) + spr->affine.root.y;
|
||||
wallVerts[3].x += (spr->affine.p4.y * gl_viewludcos) * gl_viewcos;
|
||||
wallVerts[3].z += (spr->affine.p4.y * gl_viewludcos) * gl_viewsin;
|
||||
}
|
||||
else
|
||||
{
|
||||
wallVerts[2].y = wallVerts[3].y = (spr->gzt - basey) * gl_viewludsin + basey;
|
||||
wallVerts[0].y = wallVerts[1].y = (lowy - basey) * gl_viewludsin + basey;
|
||||
// translate back to be around 0 before translating back
|
||||
wallVerts[3].x += ((spr->gzt - basey) * gl_viewludcos) * gl_viewcos;
|
||||
wallVerts[2].x += ((spr->gzt - basey) * gl_viewludcos) * gl_viewcos;
|
||||
|
||||
wallVerts[0].x += ((lowy - basey) * gl_viewludcos) * gl_viewcos;
|
||||
wallVerts[1].x += ((lowy - basey) * gl_viewludcos) * gl_viewcos;
|
||||
|
||||
wallVerts[3].z += ((spr->gzt - basey) * gl_viewludcos) * gl_viewsin;
|
||||
wallVerts[2].z += ((spr->gzt - basey) * gl_viewludcos) * gl_viewsin;
|
||||
|
||||
wallVerts[0].z += ((lowy - basey) * gl_viewludcos) * gl_viewsin;
|
||||
wallVerts[1].z += ((lowy - basey) * gl_viewludcos) * gl_viewsin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3468,7 +3492,14 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
|
|||
HWR_RotateSpritePolyToAim(spr, baseWallVerts, false);
|
||||
|
||||
// push it toward the camera to mitigate floor-clipping sprites
|
||||
float sprdist = sqrtf((spr->x1 - gl_viewx)*(spr->x1 - gl_viewx) + (spr->z1 - gl_viewy)*(spr->z1 - gl_viewy) + (spr->gzt - gl_viewz)*(spr->gzt - gl_viewz));
|
||||
float sprdist = 0;
|
||||
|
||||
float f_xdiff = (spr->x1 - gl_viewx);
|
||||
float f_ydiff = (spr->z1 - gl_viewy);
|
||||
float f_zdiff = (spr->gzt - gl_viewz);
|
||||
|
||||
sprdist = sqrtf((f_xdiff*f_xdiff) + (f_ydiff*f_ydiff) + (f_zdiff*f_zdiff));
|
||||
|
||||
float distfact = ((2.0f*spr->dispoffset) + 20.0f) / sprdist;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
|
|
@ -3746,6 +3777,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
|
|||
patch_t *gpatch;
|
||||
GLPatch_t *hwrpatch;
|
||||
FSurfaceInfo Surf = {};
|
||||
const boolean affine = ((spr->mobj && !P_MobjWasRemoved(spr->mobj)) && ((spr->mobj->player != NULL) || R_ThingIsAffineSprite(spr->mobj)));
|
||||
const boolean splat = R_ThingIsFloorSprite(spr->mobj);
|
||||
|
||||
if (!spr->mobj || !spr->mobj->subsector)
|
||||
|
|
@ -3753,7 +3785,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
|
|||
|
||||
if (spr->mobj->subsector->sector->numlights
|
||||
&& (spr->mobj->renderflags & RF_ABSOLUTELIGHTLEVEL) == 0
|
||||
&& !splat)
|
||||
&& !splat && !affine)
|
||||
{
|
||||
HWR_SplitSprite(spr);
|
||||
return;
|
||||
|
|
@ -3886,6 +3918,29 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
|
|||
wallVerts[i].y = FIXED_TO_FLOAT(spr->gz) + zoffset;
|
||||
}
|
||||
}
|
||||
else if (affine)
|
||||
{
|
||||
// Affines are weird; we've generated the transformations for them,
|
||||
// so now we need to piece together each wall vertex.
|
||||
const float _cos = spr->affine.patchcos;
|
||||
const float _sin = spr->affine.patchsin;
|
||||
|
||||
wallVerts[0].x = spr->affine.root.x + (spr->affine.p1.x * _cos);
|
||||
wallVerts[0].z = spr->affine.root.z + (spr->affine.p1.x * _sin);
|
||||
wallVerts[0].y = spr->affine.root.y + spr->affine.p1.y;
|
||||
|
||||
wallVerts[1].x = spr->affine.root.x + (spr->affine.p2.x * _cos);
|
||||
wallVerts[1].z = spr->affine.root.z + (spr->affine.p2.x * _sin);
|
||||
wallVerts[1].y = spr->affine.root.y + spr->affine.p2.y;
|
||||
|
||||
wallVerts[2].x = spr->affine.root.x + (spr->affine.p3.x * _cos);
|
||||
wallVerts[2].z = spr->affine.root.z + (spr->affine.p3.x * _sin);
|
||||
wallVerts[2].y = spr->affine.root.y + spr->affine.p3.y;
|
||||
|
||||
wallVerts[3].x = spr->affine.root.x + (spr->affine.p4.x * _cos);
|
||||
wallVerts[3].z = spr->affine.root.z + (spr->affine.p4.x * _sin);
|
||||
wallVerts[3].y = spr->affine.root.y + spr->affine.p4.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
// these were already scaled in HWR_ProjectSprite
|
||||
|
|
@ -3939,7 +3994,27 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
|
|||
HWR_RotateSpritePolyToAim(spr, wallVerts, false);
|
||||
|
||||
// push it toward the camera to mitigate floor-clipping sprites
|
||||
sprdist = sqrtf((spr->x1 - gl_viewx)*(spr->x1 - gl_viewx) + (spr->z1 - gl_viewy)*(spr->z1 -gl_viewy)+ (spr->gzt - gl_viewz)*(spr->gzt - gl_viewz));
|
||||
polyvertex_t pushpoint = {0};
|
||||
|
||||
if (affine)
|
||||
{
|
||||
pushpoint.x = spr->affine.bounding_point.x;
|
||||
pushpoint.y = spr->affine.bounding_point.y;
|
||||
pushpoint.z = spr->affine.bounding_point.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
pushpoint.x = spr->x1;
|
||||
pushpoint.y = spr->z1;
|
||||
pushpoint.z = spr->gzt;
|
||||
}
|
||||
|
||||
float f_xdiff = (pushpoint.x - gl_viewx);
|
||||
float f_ydiff = (pushpoint.y - gl_viewy);
|
||||
float f_zdiff = (pushpoint.z - gl_viewz);
|
||||
|
||||
sprdist = sqrtf((f_xdiff*f_xdiff) + (f_ydiff*f_ydiff) + (f_zdiff*f_zdiff));
|
||||
|
||||
distfact = ((2.0f* spr->dispoffset) + 20.0f) / sprdist;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
|
|
@ -3976,9 +4051,21 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
|
|||
if (!R_ThingIsFullBright(spr->mobj) && !(spr->mobj->renderflags & RF_NOCOLORMAPS))
|
||||
colormap = sector->extra_colormap;
|
||||
|
||||
if (splat && sector->numlights)
|
||||
if ((splat||affine) && sector->numlights)
|
||||
{
|
||||
INT32 light = R_GetPlaneLight(sector, spr->mobj->z, false);
|
||||
// Affine splitting is going to require more advanced tricks
|
||||
// (GLSL fragment shader, or generating a "split" polygon on the fly).
|
||||
// I've already spent too much time on this damn thing, so I'm just doing
|
||||
// what precipitation (and, by extension, MD2) does.
|
||||
|
||||
fixed_t _zoffs = 0;
|
||||
|
||||
if (affine)
|
||||
{
|
||||
_zoffs = spr->mobj->height; // Always use the light at the top instead of whatever I was doing before
|
||||
}
|
||||
|
||||
INT32 light = R_GetPlaneLight(sector, spr->mobj->z + _zoffs, false);
|
||||
|
||||
if (!lightset)
|
||||
lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel;
|
||||
|
|
@ -4823,6 +4910,14 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
vector2_t visoffs, rotoffset;
|
||||
#endif
|
||||
|
||||
// Affines
|
||||
boolean affinesprite = ((thing->player != NULL) || R_ThingIsAffineSprite(thing));
|
||||
affine_t affine_transform = {0};
|
||||
vector2_t affine_scale = {0};
|
||||
polyvertex_t affine_rootpoint = {0};
|
||||
f_vector2_t affine_point[4] = {0};
|
||||
float leftbound = 0, backbound = 0, topbound = 0;
|
||||
|
||||
// uncapped/interpolation
|
||||
interpmobjstate_t interp = {0};
|
||||
mobj_t *interptarg;
|
||||
|
|
@ -4991,11 +5086,14 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
spr_offset = spritecachedinfo[lumpoff].offset;
|
||||
spr_topoffset = spritecachedinfo[lumpoff].topoffset;
|
||||
|
||||
float base_topoffs = FIXED_TO_FLOAT(spr_topoffset);
|
||||
|
||||
#ifdef ROTSPRITE
|
||||
spriterotangle = R_SpriteRotationAngle(thing, NULL, &interp, false);
|
||||
|
||||
if (spriterotangle != 0
|
||||
&& !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE)))
|
||||
&& !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))
|
||||
&& (!affinesprite)) // Affines are capable of rotation; this is redundant
|
||||
{
|
||||
rollangle = R_GetRollAngle(papersprite == vflip
|
||||
? spriterotangle : InvAngle(spriterotangle));
|
||||
|
|
@ -5036,6 +5134,39 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (affinesprite)
|
||||
{
|
||||
affine_scale.x = FLOAT_TO_FIXED(spritexscale * this_scale);
|
||||
affine_scale.y = FLOAT_TO_FIXED(spriteyscale * this_scale);
|
||||
|
||||
angle_t angle;
|
||||
|
||||
INT32 flipsign = ((flip && papersprite) ? -1 : 1); // Flip OGL affine papersprites for Software parity
|
||||
|
||||
angle = spriterotangle * flipsign;
|
||||
|
||||
const fixed_t rolloffs_x = FixedDiv(interptarg->rollingxoffset, highresscale) * (((thing->renderflags & RF_FLIPOFFSETS) && flip) ? -1 : 1);
|
||||
const fixed_t rolloffs_y = FixedDiv(interptarg->rollingyoffset, highresscale);
|
||||
fixed_t y_piv = spr_topoffset;
|
||||
|
||||
if (vflip)
|
||||
{
|
||||
// Flip the upper offset, and use *that* as the pivot
|
||||
y_piv = spr_height - y_piv;
|
||||
}
|
||||
|
||||
fixed_t sa = FSIN(angle), ca = FCOS(angle);
|
||||
affine_transform.a = FixedDiv(ca, affine_scale.x);
|
||||
affine_transform.b = FixedDiv(-sa, affine_scale.x);
|
||||
affine_transform.c = FixedDiv(sa, affine_scale.y);
|
||||
affine_transform.d = FixedDiv(ca, affine_scale.y);
|
||||
affine_transform.ox = spr_offset - rolloffs_x;
|
||||
affine_transform.oy = y_piv - rolloffs_y;
|
||||
|
||||
spritexscale = 1.0;
|
||||
spriteyscale = 1,0;
|
||||
}
|
||||
|
||||
if (thing->renderflags & RF_ABSOLUTEOFFSETS)
|
||||
{
|
||||
spr_offset = FixedDiv(interp.spritexoffset,highresscale);
|
||||
|
|
@ -5115,23 +5246,150 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
visoffs.x = (FixedDiv((visoffs.x * FRACUNIT), mapobjectscale));
|
||||
}
|
||||
#endif
|
||||
if (flip)
|
||||
if (affinesprite)
|
||||
{
|
||||
x1 = x2 = z1 = z2 = 0.0f;
|
||||
|
||||
float f_offs, f_width, f_height;
|
||||
|
||||
f_offs = FIXED_TO_FLOAT(spr_offset);
|
||||
f_width = FIXED_TO_FLOAT(spr_width);
|
||||
f_height = FIXED_TO_FLOAT(spr_height);
|
||||
|
||||
// From HWR_DrawAffinePatch
|
||||
|
||||
float fa = FIXED_TO_FLOAT(affine_transform.a);
|
||||
float fd = FIXED_TO_FLOAT(affine_transform.d);
|
||||
float fc = FIXED_TO_FLOAT(affine_transform.c);
|
||||
float fb = FIXED_TO_FLOAT(affine_transform.b);
|
||||
float fx = FIXED_TO_FLOAT(affine_transform.ox);
|
||||
float fy = FIXED_TO_FLOAT(affine_transform.oy);
|
||||
|
||||
// now, the matrix passed to this function maps screen coordinates to texel coordinates...
|
||||
// but to translate this from software to GL, we have to figure out where each corner
|
||||
// (or vertex) of the patch should end up on the screen.
|
||||
// which means we have to map texel coordinates to screen coordinates.
|
||||
// which means we have to invert the matrix.
|
||||
// how do you invert a matrix?
|
||||
// ...
|
||||
// i don't fucking know, i spent a day on this and got absolutely nowhere, but this guy knows:
|
||||
// https://nigeltao.github.io/blog/2021/inverting-3x2-affine-transformation-matrix.html
|
||||
float determinant = fa * fd - fb * fc;
|
||||
if (determinant > 0.0f)
|
||||
{
|
||||
float ba = fd / determinant;
|
||||
float bb = -fb / determinant;
|
||||
float bc = -fc / determinant;
|
||||
float bd = fa / determinant;
|
||||
|
||||
// set the polygon vertices to the right positions
|
||||
// 3--2
|
||||
// | /|
|
||||
// |/ |
|
||||
// 0--1
|
||||
affine_point[3].x = (ba * -fx + bb * -fy + fx);
|
||||
affine_point[3].y = (bc * -fx + bd * -fy + fy);
|
||||
|
||||
affine_point[2].x = ba * (f_width - fx) + bb * -fy + fx;
|
||||
affine_point[2].y = bc * (f_width - fx) + bd * -fy + fy;
|
||||
|
||||
affine_point[0].x = ba * -fx + bb * (f_height - fy) + fx;
|
||||
affine_point[0].y = bc * -fx + bd * (f_height - fy) + fy;
|
||||
|
||||
affine_point[1].x = ba * (f_width - fx) + bb * (f_height - fy) + fx;
|
||||
affine_point[1].y = bc * (f_width - fx) + bd * (f_height - fy) + fy;
|
||||
|
||||
// Focus each point on the center.
|
||||
affine_point[0].x = fx - affine_point[0].x;
|
||||
affine_point[1].x = fx - affine_point[1].x;
|
||||
affine_point[2].x = fx - affine_point[2].x;
|
||||
affine_point[3].x = fx - affine_point[3].x;
|
||||
|
||||
affine_point[1].y -= fy;
|
||||
affine_point[2].y -= fy;
|
||||
affine_point[0].y -= fy;
|
||||
affine_point[3].y -= fy;
|
||||
|
||||
// ...okay, now comb through all four vertices and set the output bounds based on this.
|
||||
// "Why not a loop?" According to SM64 programming wizard Kaze Emanuar,
|
||||
// loops take more processing time. If we can help it, it's better to just cut corners.
|
||||
float f_left = 0;
|
||||
float f_bottom = 0;
|
||||
#define BOUNDCHECK(i) \
|
||||
{ \
|
||||
f_left = min(affine_point[i].x, f_left); \
|
||||
f_bottom = max(affine_point[i].y, f_bottom); \
|
||||
}
|
||||
|
||||
BOUNDCHECK(0);
|
||||
BOUNDCHECK(1);
|
||||
BOUNDCHECK(2);
|
||||
BOUNDCHECK(3);
|
||||
|
||||
#undef BOUNDCHECK
|
||||
|
||||
backbound = (f_left * rightsin);
|
||||
leftbound = (f_left * rightcos);
|
||||
topbound = f_bottom * -1;
|
||||
|
||||
// Invert the Y values.
|
||||
affine_point[0].y *= -1.0f;
|
||||
affine_point[1].y *= -1.0f;
|
||||
affine_point[2].y *= -1.0f;
|
||||
affine_point[3].y *= -1.0f;
|
||||
|
||||
affine_rootpoint.x = tr_x;
|
||||
affine_rootpoint.z = tr_y;
|
||||
|
||||
#ifdef ROTSPRITE
|
||||
spr_offset -= visoffs.x;
|
||||
spr_offset -= rotoffset.x;
|
||||
const float xrescale = this_xscale / FIXED_TO_FLOAT(mapobjectscale);
|
||||
float f_visx = (FIXED_TO_FLOAT(FixedMul(visoffs.x, mapobjectscale))) * xrescale;
|
||||
if (flip)
|
||||
{
|
||||
spr_offset -= visoffs.x;
|
||||
affine_rootpoint.x -= (f_visx * rightcos);
|
||||
affine_rootpoint.z -= (f_visx * rightsin);
|
||||
}
|
||||
else
|
||||
{
|
||||
spr_offset += visoffs.x;
|
||||
affine_rootpoint.x += (f_visx * rightcos);
|
||||
affine_rootpoint.z += (f_visx * rightsin);
|
||||
}
|
||||
#endif
|
||||
x1 = (FIXED_TO_FLOAT((spr_width - spr_offset)) * this_xscale);
|
||||
x2 = (FIXED_TO_FLOAT(spr_offset) * this_xscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto nodeterminant;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
nodeterminant:
|
||||
if (flip)
|
||||
{
|
||||
#ifdef ROTSPRITE
|
||||
spr_offset += visoffs.x;
|
||||
spr_offset += rotoffset.x;
|
||||
spr_offset -= visoffs.x;
|
||||
spr_offset -= rotoffset.x;
|
||||
#endif
|
||||
x1 = (FIXED_TO_FLOAT(spr_offset) * this_xscale);
|
||||
x2 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_xscale);
|
||||
x1 = (FIXED_TO_FLOAT((spr_width - spr_offset)) * this_xscale);
|
||||
x2 = (FIXED_TO_FLOAT(spr_offset) * this_xscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef ROTSPRITE
|
||||
spr_offset += visoffs.x;
|
||||
spr_offset += rotoffset.x;
|
||||
#endif
|
||||
x1 = (FIXED_TO_FLOAT(spr_offset) * this_xscale);
|
||||
x2 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_xscale);
|
||||
}
|
||||
|
||||
z1 = tr_y + x1 * rightsin;
|
||||
z2 = tr_y - x2 * rightsin;
|
||||
x1 = tr_x + x1 * rightcos;
|
||||
x2 = tr_x - x2 * rightcos;
|
||||
}
|
||||
// test if too close
|
||||
/*
|
||||
|
|
@ -5145,23 +5403,46 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
}
|
||||
*/
|
||||
|
||||
z1 = tr_y + x1 * rightsin;
|
||||
z2 = tr_y - x2 * rightsin;
|
||||
x1 = tr_x + x1 * rightcos;
|
||||
x2 = tr_x - x2 * rightcos;
|
||||
|
||||
if (thing->terrain && thing->terrain->floorClip)
|
||||
spr_topoffset -= thing->terrain->floorClip;
|
||||
spr_topoffset -= thing->terrain->floorClip;
|
||||
|
||||
affine_rootpoint.y = 0;
|
||||
|
||||
const float f_topoffs = FIXED_TO_FLOAT(spr_topoffset);
|
||||
|
||||
if (vflip)
|
||||
{
|
||||
gz = FIXED_TO_FLOAT(interp.z + thing->height) - (FIXED_TO_FLOAT(spr_topoffset) * this_yscale);
|
||||
gzt = gz + (FIXED_TO_FLOAT(spr_height) * this_yscale);
|
||||
affine_rootpoint.y = FIXED_TO_FLOAT(interp.z + thing->height) - (f_topoffs * this_yscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
gzt = FIXED_TO_FLOAT(interp.z) + (FIXED_TO_FLOAT(spr_topoffset) * this_yscale);
|
||||
gz = gzt - (FIXED_TO_FLOAT(spr_height) * this_yscale);
|
||||
affine_rootpoint.y = FIXED_TO_FLOAT(interp.z) + (f_topoffs * this_yscale);
|
||||
}
|
||||
|
||||
if (!affinesprite)
|
||||
{
|
||||
if (vflip)
|
||||
{
|
||||
gz = affine_rootpoint.y;
|
||||
gzt = gz + (FIXED_TO_FLOAT(spr_height) * this_yscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
gzt = affine_rootpoint.y;
|
||||
gz = gzt - (FIXED_TO_FLOAT(spr_height) * this_yscale);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vflip)
|
||||
{
|
||||
affine_rootpoint.y += (base_topoffs * this_yscale);
|
||||
}
|
||||
else
|
||||
{
|
||||
affine_rootpoint.y -= (base_topoffs * this_yscale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5227,10 +5508,50 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
|
||||
// store information in a vissprite
|
||||
vis = HWR_NewVisSprite();
|
||||
vis->x1 = x1;
|
||||
vis->x2 = x2;
|
||||
vis->z1 = z1;
|
||||
vis->z2 = z2;
|
||||
|
||||
if (affinesprite)
|
||||
{
|
||||
vis->affine.p1.x = affine_point[0].x;
|
||||
vis->affine.p1.y = affine_point[0].y;
|
||||
|
||||
vis->affine.p2.x = affine_point[1].x;
|
||||
vis->affine.p2.y = affine_point[1].y;
|
||||
|
||||
vis->affine.p3.x = affine_point[2].x;
|
||||
vis->affine.p3.y = affine_point[2].y;
|
||||
|
||||
vis->affine.p4.x = affine_point[3].x;
|
||||
vis->affine.p4.y = affine_point[3].y;
|
||||
|
||||
vis->affine.root.x = affine_rootpoint.x;
|
||||
vis->affine.root.y = affine_rootpoint.y;
|
||||
vis->affine.root.z = affine_rootpoint.z;
|
||||
|
||||
vis->affine.patchcos = rightcos;
|
||||
vis->affine.patchsin = rightsin;
|
||||
|
||||
vis->affine.transform.a = affine_transform.a;
|
||||
vis->affine.transform.c = affine_transform.b;
|
||||
vis->affine.transform.b = affine_transform.c;
|
||||
vis->affine.transform.d = affine_transform.d;
|
||||
vis->affine.transform.ox = affine_transform.ox;
|
||||
vis->affine.transform.oy = affine_transform.oy;
|
||||
|
||||
vis->affine.bounding_point.x = affine_rootpoint.x + leftbound;
|
||||
vis->affine.bounding_point.y = affine_rootpoint.z + backbound;
|
||||
vis->affine.bounding_point.z = affine_rootpoint.y + topbound;
|
||||
|
||||
// We're using this info to draw the affine sprite; zero-out "standard" draw info.
|
||||
vis->x1 = vis->x2 = vis->z1 = vis->z2 = 0;
|
||||
vis->gz = vis->gzt = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
vis->x1 = x1;
|
||||
vis->x2 = x2;
|
||||
vis->z1 = z1;
|
||||
vis->z2 = z2;
|
||||
}
|
||||
|
||||
vis->tz = tz; // Keep tz for the simple sprite sorting that happens
|
||||
vis->tracertz = tracertz;
|
||||
|
|
@ -5303,9 +5624,12 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
vis->colormap += COLORMAP_REMAPOFFSET;
|
||||
}
|
||||
|
||||
// set top/bottom coords
|
||||
vis->gzt = gzt;
|
||||
vis->gz = gz;
|
||||
if (!affinesprite)
|
||||
{
|
||||
// set top/bottom coords
|
||||
vis->gzt = gzt;
|
||||
vis->gz = gz;
|
||||
}
|
||||
|
||||
//CONS_Debug(DBG_RENDER, "------------------\nH: sprite : %d\nH: frame : %x\nH: type : %d\nH: sname : %s\n\n",
|
||||
// thing->sprite, thing->frame, thing->type, sprnames[thing->sprite]);
|
||||
|
|
|
|||
Loading…
Reference in a new issue