View morph splitscreen support!

There are some issues I ran into:

- Rotation is jittery (not introduced by this commit)
- 2P is wack, I don't care
This commit is contained in:
James R 2020-09-23 17:48:39 -07:00
parent 997d142cb5
commit 031665cdfc
3 changed files with 148 additions and 91 deletions

View file

@ -304,8 +304,13 @@ static void D_Display(void)
#endif #endif
} }
if (rendermode == render_soft && !splitscreen) if (rendermode == render_soft)
R_CheckViewMorph(); {
for (i = 0; i <= r_splitscreen; ++i)
{
R_CheckViewMorph(i);
}
}
// change the view size if needed // change the view size if needed
if (setsizeneeded || setrenderstillneeded) if (setsizeneeded || setrenderstillneeded)
@ -529,13 +534,10 @@ static void D_Display(void)
if (rendermode == render_soft) if (rendermode == render_soft)
{ {
if (! r_splitscreen)
{
R_ApplyViewMorph();
}
for (i = 0; i <= r_splitscreen; i++) for (i = 0; i <= r_splitscreen; i++)
{ {
R_ApplyViewMorph(i);
if (postimgtype[i]) if (postimgtype[i])
V_DoPostProcessor(i, postimgtype[i], postimgparam[i]); V_DoPostProcessor(i, postimgtype[i], postimgparam[i]);
} }

View file

@ -602,7 +602,7 @@ static inline void R_InitLightTables(void)
//#define WOUGHMP_WOUGHMP // I got a fish-eye lens - I'll make a rap video with a couple of friends //#define WOUGHMP_WOUGHMP // I got a fish-eye lens - I'll make a rap video with a couple of friends
// it's kinda laggy sometimes // it's kinda laggy sometimes
static struct { static struct viewmorph {
angle_t rollangle; // pre-shifted by fineshift angle_t rollangle; // pre-shifted by fineshift
#ifdef WOUGHMP_WOUGHMP #ifdef WOUGHMP_WOUGHMP
fixed_t fisheye; fixed_t fisheye;
@ -616,38 +616,39 @@ static struct {
INT16 ceilingclip[MAXVIDWIDTH], floorclip[MAXVIDWIDTH]; INT16 ceilingclip[MAXVIDWIDTH], floorclip[MAXVIDWIDTH];
boolean use; boolean use;
} viewmorph = { } viewmorph[MAXSPLITSCREENPLAYERS] = {0};
0,
#ifdef WOUGHMP_WOUGHMP
0,
#endif
FRACUNIT, void R_CheckViewMorph(int s)
NULL,
0,
0,
{}, {},
false
};
void R_CheckViewMorph(void)
{ {
struct viewmorph * v = &viewmorph[s];
float zoomfactor, rollcos, rollsin; float zoomfactor, rollcos, rollsin;
float x1, y1, x2, y2; float x1, y1, x2, y2;
fixed_t temp; fixed_t temp;
INT32 end, vx, vy, pos, usedpos; INT32 end, vx, vy, pos, usedpos;
INT32 usedx, usedy, halfwidth = vid.width/2, halfheight = vid.height/2; INT32 realend;
INT32 usedx, usedy;
INT32 width = vid.width;
INT32 height = vid.height;
INT32 halfwidth;
INT32 halfheight;
#ifdef WOUGHMP_WOUGHMP #ifdef WOUGHMP_WOUGHMP
float fisheyemap[MAXVIDWIDTH/2 + 1]; float fisheyemap[MAXVIDWIDTH/2 + 1];
#endif #endif
angle_t rollangle = players[displayplayers[0]].viewrollangle; angle_t rollangle = players[displayplayers[s]].viewrollangle;
#ifdef WOUGHMP_WOUGHMP #ifdef WOUGHMP_WOUGHMP
fixed_t fisheye = cv_cam2_turnmultiplier.value; // temporary test value fixed_t fisheye = cv_cam2_turnmultiplier.value; // temporary test value
#endif #endif
if (v->zoomneeded == 0)
{
v->zoomneeded = FRACUNIT;
}
rollangle >>= ANGLETOFINESHIFT; rollangle >>= ANGLETOFINESHIFT;
rollangle = ((rollangle+2) & ~3) & FINEMASK; // Limit the distinct number of angles to reduce recalcs from angles changing a lot. rollangle = ((rollangle+2) & ~3) & FINEMASK; // Limit the distinct number of angles to reduce recalcs from angles changing a lot.
@ -655,39 +656,52 @@ void R_CheckViewMorph(void)
fisheye &= ~0x7FF; // Same fisheye &= ~0x7FF; // Same
#endif #endif
if (rollangle == viewmorph.rollangle && if (r_splitscreen > 0)
{
height /= 2;
if (r_splitscreen > 1)
{
width /= 2;
}
}
halfwidth = width / 2;
halfheight = height / 2;
if (rollangle == v->rollangle &&
#ifdef WOUGHMP_WOUGHMP #ifdef WOUGHMP_WOUGHMP
fisheye == viewmorph.fisheye && fisheye == v->fisheye &&
#endif #endif
viewmorph.scrmapsize == vid.width*vid.height) v->scrmapsize == width * height)
return; // No change return; // No change
viewmorph.rollangle = rollangle; v->rollangle = rollangle;
#ifdef WOUGHMP_WOUGHMP #ifdef WOUGHMP_WOUGHMP
viewmorph.fisheye = fisheye; v->fisheye = fisheye;
#endif #endif
if (viewmorph.rollangle == 0 if (v->rollangle == 0
#ifdef WOUGHMP_WOUGHMP #ifdef WOUGHMP_WOUGHMP
&& viewmorph.fisheye == 0 && v->fisheye == 0
#endif #endif
) )
{ {
viewmorph.use = false; v->use = false;
viewmorph.x1 = 0; v->x1 = 0;
if (viewmorph.zoomneeded != FRACUNIT) if (v->zoomneeded != FRACUNIT)
R_SetViewSize(); R_SetViewSize();
viewmorph.zoomneeded = FRACUNIT; v->zoomneeded = FRACUNIT;
return; return;
} }
if (viewmorph.scrmapsize != vid.width*vid.height) if (v->scrmapsize != width * height)
{ {
if (viewmorph.scrmap) if (v->scrmap)
free(viewmorph.scrmap); free(v->scrmap);
viewmorph.scrmap = malloc(vid.width*vid.height * sizeof(INT32)); v->scrmap = malloc(width * height * sizeof(INT32));
viewmorph.scrmapsize = vid.width*vid.height; v->scrmapsize = width * height;
} }
temp = FINECOSINE(rollangle); temp = FINECOSINE(rollangle);
@ -696,8 +710,8 @@ void R_CheckViewMorph(void)
rollsin = FIXED_TO_FLOAT(temp); rollsin = FIXED_TO_FLOAT(temp);
// Calculate maximum zoom needed // Calculate maximum zoom needed
x1 = (vid.width*fabsf(rollcos) + vid.height*fabsf(rollsin)) / vid.width; x1 = (width * fabsf(rollcos) + height * fabsf(rollsin)) / width;
y1 = (vid.height*fabsf(rollcos) + vid.width*fabsf(rollsin)) / vid.height; y1 = (height * fabsf(rollcos) + width * fabsf(rollsin)) / height;
#ifdef WOUGHMP_WOUGHMP #ifdef WOUGHMP_WOUGHMP
if (fisheye) if (fisheye)
@ -723,15 +737,20 @@ void R_CheckViewMorph(void)
//CONS_Printf("Setting zoom to %f\n", FIXED_TO_FLOAT(temp)); //CONS_Printf("Setting zoom to %f\n", FIXED_TO_FLOAT(temp));
if (temp != viewmorph.zoomneeded) if (temp != v->zoomneeded)
{ {
viewmorph.zoomneeded = temp; v->zoomneeded = temp;
R_SetViewSize(); R_SetViewSize();
} }
zoomfactor = FIXED_TO_FLOAT(viewmorph.zoomneeded); zoomfactor = FIXED_TO_FLOAT(v->zoomneeded);
end = vid.width * vid.height - 1; realend = end = width * height - 1;
if (r_splitscreen > 1)
{
realend = ( realend << 1 ) - width;
}
pos = 0; pos = 0;
@ -744,49 +763,49 @@ void R_CheckViewMorph(void)
#ifdef WOUGHMP_WOUGHMP #ifdef WOUGHMP_WOUGHMP
if (fisheye) if (fisheye)
viewmorph.x1 = (INT32)(halfwidth - (halfwidth * fabsf(rollcos) + halfheight * fabsf(rollsin)) * fisheyemap[halfwidth]); v->x1 = (INT32)(halfwidth - (halfwidth * fabsf(rollcos) + halfheight * fabsf(rollsin)) * fisheyemap[halfwidth]);
else else
#endif #endif
viewmorph.x1 = (INT32)(halfwidth - (halfwidth * fabsf(rollcos) + halfheight * fabsf(rollsin))); v->x1 = (INT32)(halfwidth - (halfwidth * fabsf(rollcos) + halfheight * fabsf(rollsin)));
//CONS_Printf("saving %d cols\n", viewmorph.x1); //CONS_Printf("saving %d cols\n", v->x1);
// Set ceilingclip and floorclip // Set ceilingclip and floorclip
for (vx = 0; vx < vid.width; vx++) for (vx = 0; vx < width; vx++)
{ {
viewmorph.ceilingclip[vx] = vid.height; v->ceilingclip[vx] = height;
viewmorph.floorclip[vx] = -1; v->floorclip[vx] = -1;
} }
x2 = x1; x2 = x1;
y2 = y1; y2 = y1;
for (vx = 0; vx < vid.width; vx++) for (vx = 0; vx < width; vx++)
{ {
INT16 xa, ya, xb, yb; INT16 xa, ya, xb, yb;
xa = x2+halfwidth; xa = x2+halfwidth;
ya = y2+halfheight-1; ya = y2+halfheight-1;
xb = vid.width-1-xa; xb = width-1-xa;
yb = vid.height-1-ya; yb = height-1-ya;
viewmorph.ceilingclip[xa] = min(viewmorph.ceilingclip[xa], ya); v->ceilingclip[xa] = min(v->ceilingclip[xa], ya);
viewmorph.floorclip[xa] = max(viewmorph.floorclip[xa], ya); v->floorclip[xa] = max(v->floorclip[xa], ya);
viewmorph.ceilingclip[xb] = min(viewmorph.ceilingclip[xb], yb); v->ceilingclip[xb] = min(v->ceilingclip[xb], yb);
viewmorph.floorclip[xb] = max(viewmorph.floorclip[xb], yb); v->floorclip[xb] = max(v->floorclip[xb], yb);
x2 += rollcos; x2 += rollcos;
y2 += rollsin; y2 += rollsin;
} }
x2 = x1; x2 = x1;
y2 = y1; y2 = y1;
for (vy = 0; vy < vid.height; vy++) for (vy = 0; vy < height; vy++)
{ {
INT16 xa, ya, xb, yb; INT16 xa, ya, xb, yb;
xa = x2+halfwidth; xa = x2+halfwidth;
ya = y2+halfheight; ya = y2+halfheight;
xb = vid.width-1-xa; xb = width-1-xa;
yb = vid.height-1-ya; yb = height-1-ya;
viewmorph.ceilingclip[xa] = min(viewmorph.ceilingclip[xa], ya); v->ceilingclip[xa] = min(v->ceilingclip[xa], ya);
viewmorph.floorclip[xa] = max(viewmorph.floorclip[xa], ya); v->floorclip[xa] = max(v->floorclip[xa], ya);
viewmorph.ceilingclip[xb] = min(viewmorph.ceilingclip[xb], yb); v->ceilingclip[xb] = min(v->ceilingclip[xb], yb);
viewmorph.floorclip[xb] = max(viewmorph.floorclip[xb], yb); v->floorclip[xb] = max(v->floorclip[xb], yb);
x2 -= rollsin; x2 -= rollsin;
y2 += rollcos; y2 += rollcos;
} }
@ -803,15 +822,15 @@ void R_CheckViewMorph(void)
x1 -= rollsin; x1 -= rollsin;
y1 += rollcos; y1 += rollcos;
for (vx = 0; vx < vid.width; vx++) for (vx = 0; vx < width; vx++)
{ {
usedx = halfwidth + x2*fisheyemap[(int) floorf(fabsf(y2*zoomfactor))]; usedx = halfwidth + x2*fisheyemap[(int) floorf(fabsf(y2*zoomfactor))];
usedy = halfheight + y2*fisheyemap[(int) floorf(fabsf(x2*zoomfactor))]; usedy = halfheight + y2*fisheyemap[(int) floorf(fabsf(x2*zoomfactor))];
usedpos = usedx + usedy*vid.width; usedpos = usedx + usedy*width;
viewmorph.scrmap[pos] = usedpos; v->scrmap[pos] = usedpos;
viewmorph.scrmap[end-pos] = end-usedpos; v->scrmap[end-pos] = end-usedpos;
x2 += rollcos; x2 += rollcos;
y2 += rollsin; y2 += rollsin;
@ -832,15 +851,15 @@ void R_CheckViewMorph(void)
x1 -= rollsin; x1 -= rollsin;
y1 += rollcos; y1 += rollcos;
for (vx = 0; vx < vid.width; vx++) for (vx = 0; vx < width; vx++)
{ {
usedx = x2; usedx = x2;
usedy = y2; usedy = y2;
usedpos = usedx + usedy*vid.width; usedpos = usedx + usedy * vid.width;
viewmorph.scrmap[pos] = usedpos; v->scrmap[pos] = usedpos;
viewmorph.scrmap[end-pos] = end-usedpos; v->scrmap[end-pos] = realend-usedpos;
x2 += rollcos; x2 += rollcos;
y2 += rollsin; y2 += rollsin;
@ -851,18 +870,49 @@ void R_CheckViewMorph(void)
} }
#endif #endif
viewmorph.use = true; v->use = true;
} }
void R_ApplyViewMorph(void) void R_ApplyViewMorph(int s)
{ {
UINT8 *tmpscr = screens[4]; UINT8 *tmpscr = screens[4];
UINT8 *srcscr = screens[0]; UINT8 *srcscr = screens[0];
INT32 p, end = vid.width * vid.height; INT32 width = vid.width;
INT32 height = vid.height;
INT32 p;
INT32 end;
if (!viewmorph.use) if (!viewmorph[s].use)
return; return;
if (r_splitscreen == 1)
{
height /= 2;
if (s == 1)
{
srcscr += vid.width * height;
}
}
else if (r_splitscreen > 1)
{
width /= 2;
height /= 2;
if (s % 2)
{
srcscr += width;
}
if (s > 1)
{
srcscr += vid.width * height;
}
}
end = width * height;
#if 0
if (cv_debug & DBG_VIEWMORPH) if (cv_debug & DBG_VIEWMORPH)
{ {
UINT8 border = 32; UINT8 border = 32;
@ -889,11 +939,16 @@ void R_ApplyViewMorph(void)
} }
} }
else else
#endif
{
for (p = 0; p < end; p++) for (p = 0; p < end; p++)
tmpscr[p] = srcscr[viewmorph.scrmap[p]]; {
tmpscr[p] = srcscr[viewmorph[s].scrmap[p]];
}
}
VID_BlitLinearScreen(tmpscr, screens[0], VID_BlitLinearScreen(tmpscr, srcscr,
vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.width); width*vid.bpp, height, width*vid.bpp, vid.width);
} }
@ -953,7 +1008,7 @@ void R_ExecuteSetViewSize(void)
for (s = 0; s <= r_splitscreen; ++s) for (s = 0; s <= r_splitscreen; ++s)
{ {
fov = FixedAngle(cv_fov[s].value/2) + ANGLE_90; fov = FixedAngle(cv_fov[s].value/2) + ANGLE_90;
fovtan[s] = FixedMul(FINETANGENT(fov >> ANGLETOFINESHIFT), viewmorph.zoomneeded); fovtan[s] = FixedMul(FINETANGENT(fov >> ANGLETOFINESHIFT), viewmorph[s].zoomneeded);
if (r_splitscreen == 1) // Splitscreen FOV should be adjusted to maintain expected vertical view if (r_splitscreen == 1) // Splitscreen FOV should be adjusted to maintain expected vertical view
fovtan[s] = 17*fovtan[s]/10; fovtan[s] = 17*fovtan[s]/10;
@ -1484,13 +1539,13 @@ void R_RenderPlayerView(void)
// Clear buffers. // Clear buffers.
R_ClearPlanes(); R_ClearPlanes();
if (viewmorph.use) if (viewmorph[viewssnum].use)
{ {
portalclipstart = viewmorph.x1; portalclipstart = viewmorph[viewssnum].x1;
portalclipend = viewwidth-viewmorph.x1-1; portalclipend = viewwidth-viewmorph[viewssnum].x1-1;
R_PortalClearClipSegs(portalclipstart, portalclipend); R_PortalClearClipSegs(portalclipstart, portalclipend);
memcpy(ceilingclip, viewmorph.ceilingclip, sizeof(INT16)*vid.width); memcpy(ceilingclip, viewmorph[viewssnum].ceilingclip, sizeof(INT16)*vid.width);
memcpy(floorclip, viewmorph.floorclip, sizeof(INT16)*vid.width); memcpy(floorclip, viewmorph[viewssnum].floorclip, sizeof(INT16)*vid.width);
} }
else else
{ {

View file

@ -115,8 +115,8 @@ void R_InitHardwareMode(void);
#endif #endif
void R_ReloadHUDGraphics(void); void R_ReloadHUDGraphics(void);
void R_CheckViewMorph(void); void R_CheckViewMorph(int split);
void R_ApplyViewMorph(void); void R_ApplyViewMorph(int split);
// just sets setsizeneeded true // just sets setsizeneeded true
extern boolean setsizeneeded; extern boolean setsizeneeded;