mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 05:43:46 +03:00
Upload
This commit is contained in:
284
lua/niknaks/modules/sh_bsp_pvspas.lua
Normal file
284
lua/niknaks/modules/sh_bsp_pvspas.lua
Normal file
@@ -0,0 +1,284 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
-- Copyright © 2022-2072, Nak, https://steamcommunity.com/id/Nak2/
|
||||
-- All Rights Reserved. Not allowed to be reuploaded.
|
||||
-- License: https://github.com/Nak2/NikNaks/blob/main/LICENSE
|
||||
|
||||
local obj_tostring = "BSP %s"
|
||||
local format = string.format
|
||||
|
||||
--- @class BSPObject
|
||||
local meta = NikNaks.__metatables["BSP"]
|
||||
local meta_leaf = NikNaks.__metatables["BSP Leaf"]
|
||||
|
||||
--[[The data is stored as an array of bit-vectors; for each cluster, a list of which other clusters are visible
|
||||
from it are stored as individual bits (1 if visible, 0 if occluded) in an array, with the nth bit position
|
||||
corresponding to the nth cluster. ]]
|
||||
--- @param vis VisibilityInfo
|
||||
--- @param offset number
|
||||
local function getClusters( vis, offset, PVS )
|
||||
local c = 0
|
||||
local v = offset
|
||||
local pvs_buffer = vis._bytebuff
|
||||
local num_clusters = vis.num_clusters
|
||||
|
||||
while c <= num_clusters do
|
||||
if pvs_buffer[v] == 0 then
|
||||
v = v + 1
|
||||
c = c + 8 * pvs_buffer[v]
|
||||
else
|
||||
local b = 1
|
||||
|
||||
while b ~= 0 do
|
||||
if bit.band( pvs_buffer[v], b ) ~= 0 then
|
||||
PVS[c] = true
|
||||
end
|
||||
|
||||
b = bit.band( b * 2, 0xFF )
|
||||
c = c + 1
|
||||
end
|
||||
end
|
||||
|
||||
v = v + 1
|
||||
end
|
||||
end
|
||||
|
||||
--- PVS ( Potentially Visible Set )
|
||||
do
|
||||
--- @class PVSObject
|
||||
--- @field __map BSPObject
|
||||
local meta_pvs = {}
|
||||
meta_pvs.__index = meta_pvs
|
||||
meta_pvs.__tostring = "BSP PVS"
|
||||
meta_pvs.MetaName = "BSP PVS"
|
||||
NikNaks.__metatables["BSP PVS"] = meta_pvs
|
||||
|
||||
local DVIS_PVS = 1
|
||||
|
||||
--- Creates a new empty PVS-object.
|
||||
--- @return PVSObject
|
||||
function meta:CreatePVS()
|
||||
local t = {}
|
||||
t.__map = self
|
||||
setmetatable( t, meta_pvs )
|
||||
return t
|
||||
end
|
||||
|
||||
--- Uses the given ( or creates a new PVS-object ) and adds the position to it.
|
||||
--- @param position Vector
|
||||
--- @param PVS PVSObject?
|
||||
--- @return PVSObject
|
||||
function meta:PVSForOrigin( position, PVS )
|
||||
PVS = PVS or self:CreatePVS()
|
||||
|
||||
PVS.__map = self
|
||||
local cluster = self:ClusterFromPoint( position )
|
||||
if cluster < 0 then return PVS end -- Empty cluster position.
|
||||
|
||||
local vis = self:GetVisibility()
|
||||
local visofs = vis.VisData[cluster].PVS
|
||||
|
||||
getClusters( vis, visofs, PVS )
|
||||
|
||||
return PVS
|
||||
end
|
||||
|
||||
--- Returns true if the two positions are in same PVS.
|
||||
--- @param position Vector
|
||||
--- @param position2 Vector
|
||||
--- @return boolean
|
||||
function meta:PVSCheck( position, position2 )
|
||||
local PVS = self:PVSForOrigin( position )
|
||||
local cluster = self:ClusterFromPoint( position2 )
|
||||
return PVS[cluster] or false
|
||||
end
|
||||
|
||||
|
||||
--- Adds the position to PVS
|
||||
--- @param position Vector
|
||||
--- @return self
|
||||
function meta_pvs:AddPVS( position )
|
||||
self.__map:PVSForOrigin( position, self )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes the position from PVS
|
||||
--- @param position Vector
|
||||
--- @return self
|
||||
function meta_pvs:RemovePVS( position )
|
||||
for id in pairs( self.__map:PVSForOrigin( position ) ) do
|
||||
if id ~= "__map" then self[id] = nil end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes the leaf from PVS
|
||||
--- @param leaf LeafObject
|
||||
--- @return self PVSObject
|
||||
function meta_pvs:RemoveLeaf( leaf )
|
||||
self[leaf.cluster] = nil
|
||||
return self
|
||||
end
|
||||
|
||||
--- Returns true if the position is visible in the PVS
|
||||
--- @param position Vector
|
||||
--- @return boolean
|
||||
function meta_pvs:TestPosition( position )
|
||||
local cluster = self.__map:ClusterFromPoint( position )
|
||||
return self[cluster] or false
|
||||
end
|
||||
|
||||
--- Create PVS from Leaf
|
||||
--- @return PVSObject
|
||||
function meta_leaf:CreatePVS()
|
||||
local PVS = {}
|
||||
PVS.__map = self.__map
|
||||
setmetatable( PVS, meta_pvs )
|
||||
if self.cluster < 0 then return PVS end -- Leaf invalid. Return empty PVS.
|
||||
|
||||
local vis = self.__map:GetVisibility()
|
||||
local visofs = vis.VisData[self.cluster].PVS
|
||||
|
||||
getClusters( vis, visofs, PVS )
|
||||
|
||||
return PVS
|
||||
end
|
||||
|
||||
--- Returns a list of leafs within this PVS. Note: This is a bit slow.
|
||||
function meta_pvs:GetLeafs()
|
||||
local t = {}
|
||||
local n = 1
|
||||
local leafs = self.__map:GetLeafs()
|
||||
|
||||
for i = 1, #leafs do
|
||||
local leaf = leafs[i]
|
||||
local cluster = leaf.cluster
|
||||
|
||||
if cluster >= 0 and self[cluster] then
|
||||
t[n] = leaf
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
--- Returns true if the PVS has the given leaf
|
||||
--- @param leaf LeafObject
|
||||
--- @return boolean
|
||||
function meta_pvs:HasLeaf( leaf )
|
||||
if leaf.cluster < 0 then return false end
|
||||
return self[leaf.cluster]
|
||||
end
|
||||
end
|
||||
|
||||
-- PAS
|
||||
do
|
||||
---@class PASObject
|
||||
local meta_pas = {}
|
||||
meta_pas.__index = meta_pas
|
||||
meta_pas.__tostring = "BSP PAS"
|
||||
meta_pas.MetaName = "BSP PAS"
|
||||
NikNaks.__metatables["BSP PAS"] = meta_pas
|
||||
local DVIS_PAS = 2
|
||||
|
||||
--- Creates a new empty PAS-object.
|
||||
--- @return PASObject
|
||||
function meta:CreatePAS()
|
||||
return setmetatable( {}, meta_pas )
|
||||
end
|
||||
|
||||
--- Uses the given ( or creates a new PAS-object ) and adds the position to it.
|
||||
--- @param position Vector
|
||||
--- @param PAS PASObject?
|
||||
--- @return PASObject?
|
||||
function meta:PASForOrigin( position, PAS )
|
||||
PAS = PAS or self:CreatePAS()
|
||||
PAS.__map = self
|
||||
|
||||
local cluster = self:ClusterFromPoint( position )
|
||||
local vis = self:GetVisibility()
|
||||
if cluster < 0 then return end -- err
|
||||
|
||||
local visofs = vis.VisData[cluster].PAS
|
||||
|
||||
getClusters( vis, visofs, PAS )
|
||||
|
||||
return PAS
|
||||
end
|
||||
|
||||
--- Returns true if the two positions are in same PAS
|
||||
--- @param position Vector
|
||||
--- @param position2 Vector
|
||||
--- @return boolean
|
||||
function meta:PASCheck( position, position2 )
|
||||
local PAS = self:PASForOrigin( position )
|
||||
return PAS[self:ClusterFromPoint( position2 )] or false
|
||||
end
|
||||
|
||||
--- Adds the position to PAS
|
||||
--- @param position Vector
|
||||
--- @return PASObject self
|
||||
function meta_pas:AddPAS( position )
|
||||
self.__map:PASForOrigin( position, self )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes the position from PAS
|
||||
--- @param position Vector
|
||||
--- @return PASObject self
|
||||
function meta_pas:RemovePAS( position )
|
||||
for id in pairs( self.__map:PASForOrigin( position ) ) do
|
||||
if id ~= "__map" then self[id] = nil end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes the leaf from PVS
|
||||
--- @param leaf LeafObject
|
||||
--- @return PASObject self
|
||||
function meta_pas:RemoveLeaf( leaf )
|
||||
self[leaf.cluster] = nil
|
||||
return self
|
||||
end
|
||||
|
||||
--- Returns true if the position is visible in the PAS
|
||||
--- @param position Vector
|
||||
--- @return boolean
|
||||
function meta_pas:TestPosition( position )
|
||||
local cluster = self.__map:ClusterFromPoint( position )
|
||||
return self[cluster] or false
|
||||
end
|
||||
|
||||
--- Create PAS from Leaf
|
||||
--- @return PASObject
|
||||
function meta_leaf:CreatePAS()
|
||||
local PAS = setmetatable( {}, meta_pas )
|
||||
if self.cluster < 0 then return PAS end -- Leaf invalid. Return empty PVS.
|
||||
|
||||
local vis = self.__map:GetVisibility()
|
||||
local visofs = vis[ self.cluster ][ DVIS_PAS ]
|
||||
|
||||
getClusters( vis, visofs, PAS )
|
||||
|
||||
return PAS
|
||||
end
|
||||
|
||||
--- Returns true if the PAS has the given leaf
|
||||
--- @param leaf LeafObject
|
||||
--- @return boolean
|
||||
function meta_pas:HasLeaf( leaf )
|
||||
if leaf.cluster < 0 then return false end
|
||||
return self[leaf.cluster]
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user