Remove Gutamatics, use bespoke projection code from UT99 modding days.

This commit is contained in:
Mari the Deer 2025-03-16 15:50:00 +01:00
commit a5e58add12
19 changed files with 103 additions and 1216 deletions

View file

@ -27,8 +27,8 @@ extend Class SWWMHandler
transient ui int numcrosshairs; // how many crosshairs the current weapon has
transient ui Vector3 tpos[MAX_CROSSHAIRS]; // current trace positions in world space
transient ui Color tcol[MAX_CROSSHAIRS]; // current crosshair colors
transient ui SWWMProjectionData tprojdata; // cached Gutamatics projection data
transient ui Vector3 lagtndc[MAX_CROSSHAIRS]; // "lagged" NDC for crosshairs
transient ui SWWMProjectionData tprojdata; // cached Fast projection data
transient ui Vector2 lagvpos[MAX_CROSSHAIRS]; // "lagged" clip pos for crosshairs
transient ui bool tactive[MAX_CROSSHAIRS]; // denotes that the crosshair is "active" for drawing
transient ui double prevframe; // previous frame timestamp
@ -128,6 +128,8 @@ extend Class SWWMHandler
if ( int(ts.x)%2 ) oddfix.x = -floor(sz/2.)+1.;
if ( int(ts.y)%2 ) oddfix.y = -floor(sz/2.)+1.;
SWWMUtility.PrepareProjData(tprojdata,e.ViewPos,e.ViewAngle,e.ViewPitch,e.ViewRoll,players[consoleplayer].fov);
int cliptop = tprojdata.viewy, clipbottom = tprojdata.viewy+tprojdata.viewh,
clipleft = tprojdata.viewx, clipright = tprojdata.viewx+tprojdata.vieww;
Vector2 actpos[MAX_CROSSHAIRS];
for ( int i=0; i<MAX_CROSSHAIRS; i++ )
{
@ -137,30 +139,28 @@ extend Class SWWMHandler
Vector3 tdir = (e.ViewPos-cpos);
// project (but account for rare corner case where distance is zero)
Vector3 ndc = (tdir.length()<=double.epsilon)?(0,0,0):SWWMUtility.ProjectPoint(tprojdata,cpos);
if ( ndc.z >= 1. ) continue;
// invalid or behind view, skip
if ( ndc.z <= 0. ) continue;
Vector2 vpos = SWWMUtility.NDCToViewport(tprojdata,ndc);
if ( !prevframe ) lagtndc[i] = ndc;
if ( lagtndc[i].z >= 1. ) continue;
Vector2 oldvpos = SWWMUtility.NDCToViewport(tprojdata,lagtndc[i]);
lagtndc[i] = SWWMUtility.LerpVector3(lagtndc[i],ndc,theta);
if ( lagtndc[i].z >= 1. ) continue;
Vector2 lagvpos = SWWMUtility.NDCToViewport(tprojdata,lagtndc[i]);
if ( !prevframe ) lagvpos[i] = vpos;
Vector2 oldvpos = lagvpos[i];
lagvpos[i] = SWWMUtility.LerpVector2(lagvpos[i],vpos,theta);
if ( !tactive[i] ) continue;
// draw
int streak = int(max(abs(oldvpos.x-lagvpos.x),abs(oldvpos.y-lagvpos.y)));
int streak = int(max(abs(oldvpos.x-lagvpos[i].x),abs(oldvpos.y-lagvpos[i].y)));
double alph = 1.;
if ( i < numcrosshairs ) actpos[i] = lagvpos;
if ( i < numcrosshairs ) actpos[i] = lagvpos[i];
else
{
// unused crosshairs must "linger" until they merge with the ones that are drawn
int j = (i-numcrosshairs)%numcrosshairs;
double dist = (lagvpos-actpos[j]).length();
double dist = (lagvpos[i]-actpos[j]).length();
if ( (streak <= 0) && (dist < 1.) )
tactive[i] = false;
alph = clamp(dist/max(2,streak+2),0.,1.); // this should make the merge less jarring
}
for ( int i=0; i<streak; i++ ) Screen.DrawTexture(ctex,false,int(SWWMUtility.lerp(oldvpos.x,lagvpos.x,i/double(streak)))+oddfix.x,int(SWWMUtility.lerp(oldvpos.y,lagvpos.y,i/double(streak)))+oddfix.y,DTA_DestWidthF,ts.x*sz,DTA_DestHeightF,ts.y*sz,DTA_AlphaChannel,true,DTA_FillColor,ccol,DTA_Alpha,((i*.5)/streak)*alph);
Screen.DrawTexture(ctex,false,int(lagvpos.x)+oddfix.x,int(lagvpos.y)+oddfix.y,DTA_DestWidthF,ts.x*sz,DTA_DestHeightF,ts.y*sz,DTA_AlphaChannel,true,DTA_FillColor,ccol,DTA_Alpha,alph);
for ( int j=0; j<streak; j++ ) Screen.DrawTexture(ctex,false,int(SWWMUtility.lerp(oldvpos.x,lagvpos[i].x,j/double(streak)))+oddfix.x,int(SWWMUtility.lerp(oldvpos.y,lagvpos[i].y,j/double(streak)))+oddfix.y,DTA_DestWidthF,ts.x*sz,DTA_DestHeightF,ts.y*sz,DTA_AlphaChannel,true,DTA_FillColor,ccol,DTA_Alpha,((j*.5)/streak)*alph,DTA_ClipTop,cliptop,DTA_ClipBottom,clipbottom,DTA_ClipLeft,clipleft,DTA_ClipRight,clipright);
Screen.DrawTexture(ctex,false,int(lagvpos[i].x)+oddfix.x,int(lagvpos[i].y)+oddfix.y,DTA_DestWidthF,ts.x*sz,DTA_DestHeightF,ts.y*sz,DTA_AlphaChannel,true,DTA_FillColor,ccol,DTA_Alpha,alph,DTA_ClipTop,cliptop,DTA_ClipBottom,clipbottom,DTA_ClipLeft,clipleft,DTA_ClipRight,clipright);
}
prevframe = curframe;
}

View file

@ -6,20 +6,22 @@ extend Class SWWMHandler
private ui void DrawWorldLine( RenderEvent e, Vector3 apos, Vector3 bpos, Color col )
{
Vector3 a = SWWMUtility.ProjectPoint(projdata,e.viewpos+level.Vec3Diff(e.viewpos,apos)),
b = SWWMUtility.ProjectPoint(projdata,e.viewpos+level.Vec3Diff(e.viewpos,bpos));
if ( (a.z > 1.) && (b.z > 1.) ) return;
if ( (a.z == -double.infinity) || (b.z == -double.infinity) ) return; // how???
Vector3 a = SWWMUtility.ProjectPoint(projdata,e.viewpos+level.Vec3Diff(e.viewpos,apos),false),
b = SWWMUtility.ProjectPoint(projdata,e.viewpos+level.Vec3Diff(e.viewpos,bpos),false);
// both points are behind the screen
if ( (a.z <= 0.) && (b.z < 0.) ) return;
// at least one point is invalid
if ( (a.z == 0.) || (b.z == 0.) ) return;
double da, db, s;
Vector3 p;
da = a dot (0.,0.,-1.)-1.;
db = b dot (0.,0.,-1.)-1.;
da = a dot (0.,0.,1.);
db = b dot (0.,0.,1.);
if ( da-db != 0. )
{
s = da/(da-db);
p = (a.x+s*(b.x-a.x),a.y+s*(b.y-a.y),a.z+s*(b.z-a.z));
if ( a.z > 1. ) a = p;
if ( b.z > 1. ) b = p;
if ( a.z < 0. ) a = p;
if ( b.z < 0. ) b = p;
}
Vector2 va = SWWMUtility.NDCToViewport(projdata,a);
Vector2 vb = SWWMUtility.NDCToViewport(projdata,b);
@ -33,23 +35,25 @@ extend Class SWWMHandler
for ( int i=0; i<64; i++ )
{
Vector3 wpos = e.viewpos+level.Vec3Diff(e.viewpos,level.Vec3Offset(pos,SWWMUtility.CircleOffset(y,z,i*5.625,radius)));
ndc[i] = SWWMUtility.ProjectPoint(projdata,wpos);
ndc[i] = SWWMUtility.ProjectPoint(projdata,wpos,false);
}
for ( int i=0; i<64; i++ )
{
Vector3 a = ndc[i], b = ndc[(i+1)%64];
if ( (a.z > 1.) && (b.z > 1.) ) continue;
if ( (a.z == -double.infinity) || (b.z == -double.infinity) ) continue; // how???
// both points are behind the screen
if ( (a.z <= 0.) && (b.z < 0.) ) return;
// at least one point is invalid
if ( (a.z == 0.) || (b.z == 0.) ) return;
double da, db, s;
Vector3 p;
da = a dot (0.,0.,-1.)-1.;
db = b dot (0.,0.,-1.)-1.;
da = a dot (0.,0.,1.);
db = b dot (0.,0.,1.);
if ( da-db != 0. )
{
s = da/(da-db);
p = (a.x+s*(b.x-a.x),a.y+s*(b.y-a.y),a.z+s*(b.z-a.z));
if ( a.z > 1. ) a = p;
if ( b.z > 1. ) b = p;
if ( a.z < 0. ) a = p;
if ( b.z < 0. ) b = p;
}
Vector2 va = SWWMUtility.NDCToViewport(projdata,a);
Vector2 vb = SWWMUtility.NDCToViewport(projdata,b);
@ -90,7 +94,7 @@ extend Class SWWMHandler
double hdiff = a.Height/2;
if ( a.bFLOATBOB ) hdiff += a.GetBobOffset();
Vector3 ndc = SWWMUtility.ProjectPoint(projdata,e.viewpos+level.Vec3Diff(e.viewpos,pos+(0,0,hdiff)));
if ( ndc.z > 1. ) return;
if ( ndc.z <= 0. ) return;
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc);
String tag = a.player?a.player.GetUserName():a.GetTag();
if ( tag == a.GetClassName() ) SWWMUtility.BeautifyClassName(tag);