From 40aa4813f3faec2f5dd1c77daf66632b989f1a6b Mon Sep 17 00:00:00 2001 From: Steve <5084958+Stooberton@users.noreply.github.com> Date: Thu, 16 May 2024 17:02:39 -0500 Subject: [PATCH] Added ACF.getTraceDepth (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. --- lua/acf/core/utilities/traces_sh.lua | 81 ++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/lua/acf/core/utilities/traces_sh.lua b/lua/acf/core/utilities/traces_sh.lua index 25d70022d..ec7764f91 100644 --- a/lua/acf/core/utilities/traces_sh.lua +++ b/lua/acf/core/utilities/traces_sh.lua @@ -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 @@ -79,4 +80,84 @@ do -- ACF.trace return Output end + + local function findOtherSideOfSphere(point, dir, ent) + local radius = ent:Radius() + local center = ent:GetPos() + + local displacement = point - origin + + local ie = ray:Dot(displacement)^2 - displacement:LengthSqr() + 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