So... Remember that one decision I made about avoiding BlockThingsIterator as much as possible? Turns out that was a stupid idea. There ARE situations where it's better to iterate sector thinglists, yes, especially for things that are NOT part of the blockmap, but in other cases, the excess allocations of new iterators are a reasonable price to pay for the lower perf impact in extreme cases, such as maps that have a gazillion sectors with gazillions of things in them (I'm looking at you, UDMF mappers). As a compromise, at least, in situations where the thinglists are needed, I did add a sort of micro-optimization by implementing code to check if a bounding box is inside a sector (would be nice if this was part of GZDoom itself, tho).
122 lines
5.2 KiB
Text
122 lines
5.2 KiB
Text
// ported and optimized from old debug test mod
|
|
|
|
extend Class SWWMHandler
|
|
{
|
|
ui SWWMProjectionData projdata;
|
|
|
|
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???
|
|
double da, db, s;
|
|
Vector3 p;
|
|
da = a dot (0.,0.,-1.)-1.;
|
|
db = b dot (0.,0.,-1.)-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;
|
|
}
|
|
Vector2 va = SWWMUtility.NDCToViewport(projdata,a);
|
|
Vector2 vb = SWWMUtility.NDCToViewport(projdata,b);
|
|
Screen.DrawLine(int(va.x),int(va.y),int(vb.x),int(vb.y),col);
|
|
}
|
|
|
|
private ui void DrawWorldCircle( RenderEvent e, Vector3 pos, double radius, Color col )
|
|
{
|
|
let [x, y, z] = SWWMUtility.GetAxes(e.viewangle,e.viewpitch,e.viewroll);
|
|
Vector3 ndc[64];
|
|
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);
|
|
}
|
|
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???
|
|
double da, db, s;
|
|
Vector3 p;
|
|
da = a dot (0.,0.,-1.)-1.;
|
|
db = b dot (0.,0.,-1.)-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;
|
|
}
|
|
Vector2 va = SWWMUtility.NDCToViewport(projdata,a);
|
|
Vector2 vb = SWWMUtility.NDCToViewport(projdata,b);
|
|
Screen.DrawLine(int(va.x),int(va.y),int(vb.x),int(vb.y),col);
|
|
}
|
|
}
|
|
|
|
private ui void DrawActor( RenderEvent e, Actor a )
|
|
{
|
|
Vector3 pos = SWWMUtility.LerpVector3(a.prev,a.pos,e.FracTic);
|
|
if ( a is 'DynamicLight' ) DrawWorldCircle(e,pos,a.args[3]*2,Color(a.args[0],a.args[1],a.args[2]));
|
|
if ( (a.radius > 0.) && (a.height > 0.) )
|
|
{
|
|
Vector3 b1, b2;
|
|
b1 = pos-(a.radius,a.radius,0);
|
|
b2 = pos+(a.radius,a.radius,a.height);
|
|
DrawWorldLine(e,(b1.x,b1.y,b1.z),(b1.x,b2.y,b1.z),"White");
|
|
DrawWorldLine(e,(b1.x,b2.y,b1.z),(b2.x,b2.y,b1.z),"White");
|
|
DrawWorldLine(e,(b2.x,b2.y,b1.z),(b2.x,b1.y,b1.z),"White");
|
|
DrawWorldLine(e,(b2.x,b1.y,b1.z),(b1.x,b1.y,b1.z),"White");
|
|
DrawWorldLine(e,(b1.x,b1.y,b2.z),(b1.x,b2.y,b2.z),"White");
|
|
DrawWorldLine(e,(b1.x,b2.y,b2.z),(b2.x,b2.y,b2.z),"White");
|
|
DrawWorldLine(e,(b2.x,b2.y,b2.z),(b2.x,b1.y,b2.z),"White");
|
|
DrawWorldLine(e,(b2.x,b1.y,b2.z),(b1.x,b1.y,b2.z),"White");
|
|
DrawWorldLine(e,(b1.x,b1.y,b1.z),(b1.x,b1.y,b2.z),"White");
|
|
DrawWorldLine(e,(b2.x,b1.y,b1.z),(b2.x,b1.y,b2.z),"White");
|
|
DrawWorldLine(e,(b1.x,b2.y,b1.z),(b1.x,b2.y,b2.z),"White");
|
|
DrawWorldLine(e,(b2.x,b2.y,b1.z),(b2.x,b2.y,b2.z),"White");
|
|
}
|
|
let [x, y, z] = SWWMUtility.GetAxes(a.angle,a.pitch,a.roll);
|
|
DrawWorldLine(e,pos,pos+x*16,"Red");
|
|
DrawWorldLine(e,pos,pos+y*16,"Green");
|
|
DrawWorldLine(e,pos,pos+z*16,"Blue");
|
|
if ( a.vel != (0,0,0) ) DrawWorldLine(e,pos,pos+a.vel*GameTicRate,"Yellow");
|
|
if ( a.target ) DrawWorldLine(e,pos,SWWMUtility.LerpVector3(a.target.prev,a.target.pos,e.FracTic),"Gold");
|
|
if ( a.tracer ) DrawWorldLine(e,pos,SWWMUtility.LerpVector3(a.tracer.prev,a.tracer.pos,e.FracTic),"Orange");
|
|
if ( a.master ) DrawWorldLine(e,pos,SWWMUtility.LerpVector3(a.master.prev,a.master.pos,e.FracTic),"Purple");
|
|
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;
|
|
Vector2 vpos = SWWMUtility.NDCToViewport(projdata,ndc);
|
|
String tag = a.player?a.player.GetUserName():a.GetTag();
|
|
if ( tag == a.GetClassName() ) SWWMUtility.BeautifyClassName(tag);
|
|
Screen.DrawText(NewSmallFont,a.bDROPPED?Font.CR_DARKRED:Font.CR_RED,vpos.x-NewSmallFont.StringWidth(tag)/2,vpos.y-NewSmallFont.GetHeight()/2,tag);
|
|
}
|
|
|
|
private ui void DrawDebug( RenderEvent e )
|
|
{
|
|
if ( !swwm_debugview ) return;
|
|
// prepare projection data, we're going to need this
|
|
SWWMUtility.PrepareProjData(projdata,e.ViewPos,e.ViewAngle,e.ViewPitch,e.ViewRoll,players[consoleplayer].fov);
|
|
foreach ( s:level.Sectors )
|
|
{
|
|
// don't check sectors that aren't within bounds, saves some time
|
|
if ( !BoxInSectorBounds(s,players[consoleplayer].Camera.pos.xy,1000,players[consoleplayer].Camera.CurSector.PortalGroup) )
|
|
continue;
|
|
for ( Actor a=s.thinglist; a; a=a.snext )
|
|
{
|
|
if ( (a == players[consoleplayer].Camera) && !(players[consoleplayer].cheats&CF_CHASECAM) ) continue;
|
|
if ( a.bINVISIBLE && !(a is 'DynamicLight') ) continue;
|
|
if ( (a is 'Inventory') && Inventory(a).Owner ) continue;
|
|
if ( (a is 'SWWMPickupFlash') && (a.CurState == a.FindState('Pickup')) ) continue;
|
|
if ( (a is 'SWWMShadow') || (a is 'SWWMItemOverlay') || (a is 'HeadpatTracker') || (a is 'SWWMTeleportLine') || (a is 'SWWMTeleportDest') ) continue;
|
|
if ( a.Distance3DSquared(e.Camera) > 1000000 ) continue;
|
|
DrawActor(e,a);
|
|
}
|
|
}
|
|
}
|
|
}
|