Skip to content

Commit

Permalink
Added ACF.getTraceDepth
Browse files Browse the repository at this point in the history
(Untested code)
Returns the depth in mm a trace penetrates a prop before hitting something else. This is the full line of sight thickness if there are no obstacles.
  • Loading branch information
Stooberton committed May 16, 2024
1 parent 6439556 commit 40aa481
Showing 1 changed file with 81 additions and 0 deletions.
81 changes: 81 additions & 0 deletions lua/acf/core/utilities/traces_sh.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ do -- ACF.trace
-- Automatically filters out and retries when hitting a clipped portion of a prop
-- Does NOT modify the original filter
local util = util
local sqrt = math.sqrt

local function doRecursiveTrace(traceData)
local Output = traceData.output
Expand Down Expand Up @@ -79,4 +80,84 @@ do -- ACF.trace

return Output
end

local function findOtherSideOfSphere(point, dir, ent)

Check warning on line 84 in lua/acf/core/utilities/traces_sh.lua

View workflow job for this annotation

GitHub Actions / Lint / lint

"Unused variable"

Unused variable: dir
local radius = ent:Radius()

Check warning on line 85 in lua/acf/core/utilities/traces_sh.lua

View workflow job for this annotation

GitHub Actions / Lint / lint

"Unused variable"

Unused variable: radius
local center = ent:GetPos()

local displacement = point - origin

local ie = ray:Dot(displacement)^2 - displacement:LengthSqr()

Check warning on line 90 in lua/acf/core/utilities/traces_sh.lua

View workflow job for this annotation

GitHub Actions / Lint / lint

"Whitespace style"

Style: Please put some whitespace after ')'
local exit = ray:Dot(point - center) + sqrt(ie)
local length = (point - exit):Length() * 25.4

return exit, length
end

local function findOtherSideOfPoly(Ent, Origin, Dir)
local Mesh = Ent:GetPhysicsObject():GetMeshConvexes()
local Min = math.huge

for K in pairs(Mesh) do -- Loop over mesh
local Hull = Mesh[K]

for I = 1, #Hull, 3 do -- Loop over each tri (groups of 3)
-- Points on tri
local P1 = Ent:LocalToWorld(Hull[I].pos)
local P2 = Ent:LocalToWorld(Hull[I + 1].pos)
local P3 = Ent:LocalToWorld(Hull[I + 2].pos)

-- Two edges to test with
local Edge1 = P2 - P1
local Edge2 = P3 - P1

-- Plane facing the wrong way?
if Dir:Dot(Edge1:Cross(Edge2)) > 0 then continue end

-- Ray is perpendicular to plane?
local H = Dir:Cross(Edge2)
local A = Edge1:Dot(H)

if A > -0.0001 and A < 0.0001 then continue end

-- Ray passes through the triangle?
local F = 1 / A
local S = Origin - P1 -- Displacement from to origin from P1
local U = F * S:Dot(H)

if U < 0 or U > 1 then continue end

local Q = S:Cross(Edge1)
local V = F * Dir:Dot(Q)

if V < 0 or U + V > 1 then continue end

-- Ray intersects triangle
-- Length of ray to intersection
local T = F * Edge2:Dot(Q)

if T > 0.0001 and T < Min then Min = T end
end
end

return Origin + Dir * Min
end

function ACF.getTraceDepth(trace)
-- Traces from the surface of an object to the furthest tri on the opposite side
-- Stops at any other object that is intersecting inside

local ent = trace.Entity
local origin = trace.StartPos
local enter = trace.HitPos
local rayDir = (enter - trace.StartPos):GetNormalized()

local tempFilter = {}; for k, v in pairs(trace.Filter) do filter[k] = v end -- Shallow copy of the original filter (presumably a projectile trace) prevents two overlapping cubes from infinitely intersecting

local opposite = ent._IsSpherical and findOtherSideOfSphere(enter, rayDir, ent:GetPos()) or findOtherSideOfPoly(ent, origin, rayDir)
local exit = ACF.trace({start = enter, endpos = opposite, filter = tempFilter}).HitPos -- Not strictly an exit... may have run into an intersecting entity
local length = (exit - enter):Length() * 25.4 -- Inches to mm

return exit, length
end
end

0 comments on commit 40aa481

Please sign in to comment.