Generalized hitnormal functions (where possible).

This commit is contained in:
Mari the Deer 2022-12-18 20:03:36 +01:00
commit b1683dae8e
24 changed files with 206 additions and 785 deletions

View file

@ -348,7 +348,7 @@ extend Class SWWMUtility
}
// the stupidest thing ever, it's called BlockingLine but it's not always blocking us
static play bool BlockingLineIsBlocking( Actor a, int blockflags = Line.ML_BLOCKEVERYTHING, Line testline = null )
static clearscope bool BlockingLineIsBlocking( Actor a, int blockflags = Line.ML_BLOCKEVERYTHING, Line testline = null )
{
Line l = testline?testline:a.BlockingLine;
// not blocked
@ -537,6 +537,136 @@ extend Class SWWMUtility
return (al+ah+bl+bh)*.25;
}
// gets the hit normal vector for projectiles and hitscan
// bNoBounce: actor didn't just bounce, meaning the fallback normal shouldn't be the inverse of velocity
static clearscope Vector3 GetActorHitNormal( Actor a, bool bNoBounce = false )
{
Vector3 HitNormal = (0,0,0);
F3DFloor ff;
if ( a.BlockingMobj )
{
let mo = a.BlockingMobj;
Vector3 diff = level.Vec3Diff(mo.pos,a.pos);
if ( diff.x >= mo.radius ) HitNormal += (1,0,0);
else if ( diff.x <= -mo.radius ) HitNormal += (-1,0,0);
if ( diff.y >= mo.radius ) HitNormal += (0,1,0);
else if ( diff.y <= -mo.radius ) HitNormal += (0,-1,0);
if ( diff.z >= mo.height ) HitNormal += (0,0,1);
else if ( diff.z <= 0. ) HitNormal += (0,0,-1);
double len = HitNormal.length();
if ( len < double.epsilon ) HitNormal = Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90));
else HitNormal /= len;
}
else if ( a.BlockingFloor )
{
// find closest 3d floor for its normal
for ( int i=0; i<a.BlockingFloor.Get3DFloorCount(); i++ )
{
if ( !(a.BlockingFloor.Get3DFloor(i).flags&F3DFloor.FF_SOLID) ) continue;
if ( !(a.BlockingFloor.Get3DFloor(i).top.ZAtPoint(a.pos.xy) ~== a.floorz) ) continue;
ff = a.BlockingFloor.Get3DFloor(i);
break;
}
if ( ff ) HitNormal = -ff.top.Normal;
else HitNormal = a.BlockingFloor.floorplane.Normal;
}
else if ( a.BlockingCeiling )
{
// find closest 3d floor for its normal
for ( int i=0; i<a.BlockingCeiling.Get3DFloorCount(); i++ )
{
if ( !(a.BlockingCeiling.Get3DFloor(i).flags&F3DFloor.FF_SOLID) ) continue;
if ( !(a.BlockingCeiling.Get3DFloor(i).bottom.ZAtPoint(a.pos.xy) ~== a.ceilingz) ) continue;
ff = a.BlockingCeiling.Get3DFloor(i);
break;
}
if ( ff ) HitNormal = -ff.bottom.Normal;
else HitNormal = a.BlockingCeiling.ceilingplane.Normal;
}
else if ( a.BlockingLine && BlockingLineIsBlocking(a,Line.ML_BLOCKEVERYTHING|Line.ML_BLOCKPROJECTILE,a.BlockingLine) )
{
HitNormal = (-a.BlockingLine.delta.y,a.BlockingLine.delta.x,0).unit();
if ( !SWWMUtility.PointOnLineSide(a.pos.xy,a.BlockingLine) )
HitNormal *= -1;
}
else
{
double len = a.vel.length();
if ( len > 0. ) HitNormal = bNoBounce?(-a.vel/len):(a.vel/len);
}
return HitNormal;
}
static clearscope Vector3 GetLineTraceHitNormal( FLineTraceData d )
{
Vector3 HitNormal = (0,0,0);
if ( d.HitType == TRACE_HitActor )
{
let mo = d.HitActor;
Vector3 diff = level.Vec3Diff(mo.pos,d.HitLocation);
if ( diff.x >= mo.radius ) HitNormal += (1,0,0);
else if ( diff.x <= -mo.radius ) HitNormal += (-1,0,0);
if ( diff.y >= mo.radius ) HitNormal += (0,1,0);
else if ( diff.y <= -mo.radius ) HitNormal += (0,-1,0);
if ( diff.z >= mo.height ) HitNormal += (0,0,1);
else if ( diff.z <= 0. ) HitNormal += (0,0,-1);
double len = HitNormal.length();
if ( len < double.epsilon ) HitNormal = Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90));
else HitNormal /= len;
}
else if ( d.HitType == TRACE_HitFloor )
{
if ( d.Hit3DFloor ) HitNormal = -d.Hit3DFloor.top.Normal;
else HitNormal = d.HitSector.floorplane.Normal;
}
else if ( d.HitType == TRACE_HitCeiling )
{
if ( d.Hit3DFloor ) HitNormal = -d.Hit3DFloor.bottom.Normal;
else HitNormal = d.HitSector.ceilingplane.Normal;
}
else if ( d.HitType == TRACE_HitWall )
{
HitNormal = (-d.HitLine.delta.y,d.HitLine.delta.x,0).unit();
if ( !d.LineSide ) HitNormal *= -1;
}
else HitNormal = -d.HitDir;
return HitNormal;
}
static clearscope Vector3 GetLineTracerHitNormal( TraceResults r )
{
Vector3 HitNormal = (0,0,0);
if ( r.HitType == TRACE_HitActor )
{
let mo = r.HitActor;
Vector3 diff = level.Vec3Diff(mo.pos,r.HitPos);
if ( diff.x >= mo.radius ) HitNormal += (1,0,0);
else if ( diff.x <= -mo.radius ) HitNormal += (-1,0,0);
if ( diff.y >= mo.radius ) HitNormal += (0,1,0);
else if ( diff.y <= -mo.radius ) HitNormal += (0,-1,0);
if ( diff.z >= mo.height ) HitNormal += (0,0,1);
else if ( diff.z <= 0. ) HitNormal += (0,0,-1);
double len = HitNormal.length();
if ( len < double.epsilon ) HitNormal = Vec3FromAngles(FRandom[ExploS](0,360),FRandom[ExploS](-90,90));
else HitNormal /= len;
}
else if ( r.HitType == TRACE_HitFloor )
{
if ( r.ffloor ) HitNormal = -r.ffloor.top.Normal;
else HitNormal = r.HitSector.floorplane.Normal;
}
else if ( r.HitType == TRACE_HitCeiling )
{
if ( r.ffloor ) HitNormal = -r.ffloor.bottom.Normal;
else HitNormal = r.HitSector.ceilingplane.Normal;
}
else if ( r.HitType == TRACE_HitWall )
{
HitNormal = (-r.HitLine.delta.y,r.HitLine.delta.x,0).unit();
if ( !r.Side ) HitNormal *= -1;
}
else HitNormal = -r.HitVector;
return HitNormal;
}
static bool, TextureID DefaceTexture( TextureID checkme )
{
String tn = TexMan.GetName(checkme);