Garry's Mod Wiki

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>