Attribute VB_Name = "Intersection"

Option Explicit

'This module handle game specific line intersections
Public Enum IRT
    IRT_Nothing
    IRT_Ground
    IRT_Item
    IRT_Vehicle
End Enum

Public Type IntersectionResult
    Collided As Boolean
    StartEndRatio As Single
    Position As Vector3
    Normal As Vector3
    Type As IRT
    Index As Long
    X As Long
    Z As Long
End Type

'This method is a game specific version of Physics_GetClosestIntersection_World_Out2V3 to improve speed and allow selection of what to intersect with
'Letting the physics engine do the line intersection with the height field is very slow because it is not made for long intersections
Public Function LineIntersection(StartPosition As Vector3, EndPosition As Vector3, UseGround As Boolean, UseItems As Boolean, UseVehicles As Boolean, ExcludedVehicleIndex As Integer) As IntersectionResult
    Dim CurrentEndPosition As Vector3
    Dim MoveLength As Single
    Dim NumberOfIterations As Long
    Dim I As Long
    Dim W As Single
    Dim InterpolatedPosition As Vector3
    Dim Collided As Boolean
    
    LineIntersection.Collided = False
    LineIntersection.StartEndRatio = 1
    LineIntersection.Type = IRT_Nothing
    CurrentEndPosition = EndPosition
    
    'Collide with the ground
    If UseGround Then
        Collided = (frmMain.DGE.RigidBody_GetFirstIntersection_Out2V3(StartPosition.X, StartPosition.Y, StartPosition.Z, CurrentEndPosition.X, CurrentEndPosition.Y, CurrentEndPosition.Z, Terrain_HeightField_RigidBody) > 0): RE
        If Collided Then
            LineIntersection.Collided = True
            LineIntersection.Position = GetVector3FromMatrixBuffer
            LineIntersection.Normal = GetSecondVector3FromMatrixBuffer
            LineIntersection.Type = IRT_Ground
            CurrentEndPosition = LineIntersection.Position 'Update the line
        End If
        'MoveLength = AbsVector3(ToVector3(StartPosition, EndPosition))
        'NumberOfIterations = Int((MoveLength / Terrain_SmallestGridSize) * 4) + 2
        'For I = 0 To NumberOfIterations - 1
        '    W = (I + 0.5) / NumberOfIterations
        '    InterpolatedPosition = LerpVector3(StartPosition, EndPosition, W)
        '    If InterpolatedPosition.Y < Terrain_GetHeightLinear(InterpolatedPosition.X, InterpolatedPosition.Z) Then
        '        LineIntersection.Collided = True
        '        LineIntersection.Position = InterpolatedPosition
        '        LineIntersection.Normal = MakeVector3(0, 1, 0) '¤¤¤¤ Simplified because it is rarely used
        '        LineIntersection.Type = IRT_Ground
        '        CurrentEndPosition = LineIntersection.Position 'Update the line
        '        Exit For
        '    End If
        'Next I
    End If
    
    'Collide with items
    If UseItems Then
        Dim IR As IntersectionResult
        IR = Item_LineIntersection(StartPosition, CurrentEndPosition)
        If IR.Collided Then
            LineIntersection = IR
            CurrentEndPosition = LineIntersection.Position 'Update the line
        End If
    End If
    
    'Collide with vehicles
    If UseVehicles Then
        For I = 0 To NumberOfVehicles - 1
            If I <> ExcludedVehicleIndex Then
                Collided = (frmMain.DGE.RigidBody_GetFirstIntersection_Out2V3(StartPosition.X, StartPosition.Y, StartPosition.Z, CurrentEndPosition.X, CurrentEndPosition.Y, CurrentEndPosition.Z, GetVehicleRigidBody(I)) > 0): RE
                If Collided Then
                    LineIntersection.Collided = True
                    LineIntersection.Position = GetVector3FromMatrixBuffer
                    LineIntersection.Normal = GetSecondVector3FromMatrixBuffer
                    LineIntersection.Type = IRT_Vehicle
                    LineIntersection.Index = I
                    CurrentEndPosition = LineIntersection.Position 'Update the line
                End If
            End If
        Next I
    End If
    
    Dim LineOffset As Vector3
    LineOffset = ToVector3(StartPosition, EndPosition)
    If Abs(LineOffset.X) > Abs(LineOffset.Y) Then
        If Abs(LineOffset.X) > Abs(LineOffset.Z) Then
            LineIntersection.StartEndRatio = Saturate(InverseLerp(StartPosition.X, EndPosition.X, LineIntersection.Position.X))
        Else
            LineIntersection.StartEndRatio = Saturate(InverseLerp(StartPosition.Z, EndPosition.Z, LineIntersection.Position.Z))
        End If
    Else
        If Abs(LineOffset.Y) > Abs(LineOffset.Z) Then
            LineIntersection.StartEndRatio = Saturate(InverseLerp(StartPosition.Y, EndPosition.Y, LineIntersection.Position.Y))
        Else
            LineIntersection.StartEndRatio = Saturate(InverseLerp(StartPosition.Z, EndPosition.Z, LineIntersection.Position.Z))
        End If
    End If
End Function
