Vision Cone

Currently I take advantage of some functions that exist in Scripts/GetEntityNeighbors.lua. For the sake of completeness I'll post what I have in that entire file. The idea is that you find entities in a bounding box around your main entity (player if you will) and then you loop over those entities and check if they are in the vision cone area.

WorldGetEntitiesInAABBDoCallbackTable = nil
GetEntityNeighborsScriptedOnly=false

function WorldGetEntitiesInAABBDoCallback(entity,extra)
    if entity~=extra then
        if GetEntityNeighborsScriptedOnly==false or entity.script~=nil then
            table.insert(WorldGetEntitiesInAABBDoCallbackTable,entity)
        end
    end
end

------------------------------------------------------------------------------------------
--Get all neigbhoring top-level entities within the specified radius.
--The optional scriptOnly parameter will skip entities that do not have a script attached.
------------------------------------------------------------------------------------------
function GetEntityNeighbors(entity,radius,scriptOnly)
    local result
    local aabb = AABB()
    local p = entity:GetPosition(true)
    local temp = GetEntityNeighborsScriptedOnly
    GetEntityNeighborsScriptedOnly=scriptOnly
    aabb.min = p - radius
    aabb.max = p + radius
    aabb:Update()
    local table = WorldGetEntitiesInAABBDoCallbackTable 
    WorldGetEntitiesInAABBDoCallbackTable = {}
    entity.world:ForEachEntityInAABBDo(aabb,"WorldGetEntitiesInAABBDoCallback",entity)    
    result = WorldGetEntitiesInAABBDoCallbackTable
    WorldGetEntitiesInAABBDoCallbackTable = table
    GetEntityNeighborsScriptedOnly = temp
    return result
end

function GetForwardVector(entity)
    local forward_vec4 = Vec4(0,0,1,0)
    local mat = entity:GetMatrix():Transpose()

    --transform
    local ret = Vec4(0)

    for i = 0,3,1 do
        ret[i] = 0
        for j = 0,3,1 do
            ret[i] = ret[i] + mat[i][j] * forward_vec4[j]
        end
    end

        return ret
end

function GetEntityNeighborsViewCone(entity, raduis, scriptOnly, angle)
    local entities = GetEntityNeighbors(entity, raduis, scriptOnly)
    local e = {}
    local k, v
    local forward_vec4 = GetForwardVector(entity)

        -- loop over all entities there were in the bounding box to see if we are in their view cone    
    for k, v in pairs(entities) do
        local diff_vec = v:GetPosition() - entity:GetPosition()
        local forward_vec = forward_vec4:xyz()

        --calculate angle
        local dot = diff_vec:Dot(forward_vec)
        local l1 = math.sqrt(diff_vec:Dot(diff_vec))
        local l2 = math.sqrt(forward_vec:Dot(forward_vec))
        local _angle = Math:ACos(dot / (l1*l2))

        local name = v:GetKeyValue("name")
        System:Print("GetEntityNeighbors = "..name)

        if(_angle < angle) then
            -- in cone
            System:Print("Inside cone")
            table.insert(e, v)
        end
    end

    return e
end

The usage is:

local entities = GetEntityNeighborsViewCone(self.entity, 10, true, 35)
local k, entity

for k, entity in pairs(entities) do
   -- these entities are in the view cone in the bounding box
end
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License