Revision Difference
util.IntersectRayWithTriangle#568269
<function name="IntersectRayWithTriangle" parent="util" type="libraryfunc">⤶
<description>Performs a ray-triangle intersection and returns the hit position or nil.</description>⤶
<added>2026.07.16</added>⤶
<realm>Shared</realm>⤶
<args>⤶
<arg name="rayOrigin" type="Vector">Origin/start position of the ray.</arg>⤶
<arg name="rayEnd" type="Vector">The end position of the ray.</arg>⤶
<arg name="triA" type="Vector">The first vertex of the triangle.</arg>⤶
<arg name="triB" type="Vector">The second vertex of the triangle.</arg>⤶
<arg name="triC" type="Vector">The third vertex of the triangle.</arg>⤶
<arg name="oneSided" type="boolean" default="false">Whether the triangle can be hit from only one side (`true`) or from both sides (`false`).⤶
<validate>This assumes clockwise vertex arrangement to determine the "hittable" side.</validate>⤶
</arg>⤶
</args>⤶
<rets>⤶
<ret name="" type="Vector">The position of intersection, `nil` if not hit.</ret>⤶
<ret name="" type="number">The fraction of start position to end position in range of [0,1] to the hit point, if there was a hit. i.e. 0.5 would be a hit in the exact middle of start and end positions.</ret>⤶
</rets>⤶
</function>⤶
⤶
<example>⤶
<code>⤶
-- Store entity we look at, so we have a reference to test again⤶
local ent = NULL⤶
⤶
hook.Add( "Think", "Think_IntersectRayWithTriangleExample", function()⤶
⤶
-- Store player object⤶
local ply = LocalPlayer()⤶
⤶
-- If player looked at some valid entity, swtich our entity to that⤶
local trEnt = ply:GetEyeTrace().Entity⤶
if ( IsValid( trEnt ) ) then ent = trEnt end⤶
⤶
-- No entity? do nothing⤶
if ( !IsValid( ent ) ) then return end⤶
⤶
local rayStart = ply:GetShootPos()⤶
local rayEnd = rayStart + ply:GetAimVector() * 500⤶
⤶
-- OBB corners (local space)⤶
local mins = ent:OBBMins()⤶
local maxs = ent:OBBMaxs()⤶
⤶
-- Top face corners⤶
local p1 = ent:LocalToWorld( Vector( mins.x, mins.y, maxs.z ) )⤶
local p2 = ent:LocalToWorld( Vector( maxs.x, mins.y, maxs.z ) )⤶
local p3 = ent:LocalToWorld( Vector( maxs.x, maxs.y, maxs.z ) )⤶
local p4 = ent:LocalToWorld( Vector( mins.x, maxs.y, maxs.z ) )⤶
⤶
local color1 = Color( 255, 255, 255, 128 )⤶
local color2 = Color( 255, 255, 255, 100 )⤶
⤶
-- Test first triangle⤶
local hitpos = util.IntersectRayWithTriangle( rayStart, rayEnd, p1, p2, p3 )⤶
if ( hitpos ) then color1 = Color( 0, 255, 0, 128 ) end⤶
⤶
-- If that misses, test the second half of the quad⤶
if ( !hitpos ) then⤶
hitpos = util.IntersectRayWithTriangle( rayStart, rayEnd, p1, p3, p4 )⤶
if ( hitpos ) then color2 = Color( 0, 255, 0, 100 ) end⤶
end⤶
⤶
-- Draw the hit position if we hit a triangle⤶
if ( hitpos ) then⤶
debugoverlay.Axis( hitpos, angle_zero, 10, 0.01 )⤶
end⤶
⤶
-- Draw the triangles⤶
debugoverlay.Triangle( p3, p2, p1, 0.01, color1, true )⤶
debugoverlay.Triangle( p4, p3, p1, 0.01, color2, true )⤶
⤶
-- Draw the back sides too⤶
debugoverlay.Triangle( p1, p2, p3, 0.01, color1, true )⤶
debugoverlay.Triangle( p1, p3, p4, 0.01, color2, true )⤶
⤶
end )⤶
</code>⤶
<output>⤶
<upload src="70c/8df03b876c92995.png" size="862483" name="image.png" />⤶
</output>⤶
</example>
Garry's Mod
Rust
Steamworks
Wiki Help