builtin/voxelworld: Remove slow Lua implementation of SpatialUpdateQueue and use higher max_operations
This commit is contained in:
parent
abad1e0e2f
commit
1728d15b43
@ -27,219 +27,6 @@ M.chunk_size_voxels = nil
|
||||
M.section_size_chunks = nil
|
||||
M.section_size_voxels = nil
|
||||
|
||||
--[[
|
||||
table.binsearch( table, value [, compval [, reversed] ] )
|
||||
|
||||
Searches the table through BinarySearch for the given value.
|
||||
If the value is found:
|
||||
it returns a table holding all the mathing indices (e.g. { startindice,endindice } )
|
||||
endindice may be the same as startindice if only one matching indice was found
|
||||
If compval is given:
|
||||
then it must be a function that takes one value and returns a second value2,
|
||||
to be compared with the input value, e.g.:
|
||||
compvalue = function( value ) return value[1] end
|
||||
If reversed is set to true:
|
||||
then the search assumes that the table is sorted in reverse order (largest value at position 1)
|
||||
note when reversed is given compval must be given as well, it can be nil/_ in this case
|
||||
Return value:
|
||||
on success: a table holding matching indices (e.g. { startindice,endindice } )
|
||||
on failure: nil
|
||||
]]--
|
||||
do
|
||||
-- Avoid heap allocs for performance
|
||||
local default_fcompval = function(value) return value end
|
||||
local fcompf = function(a,b) return a < b end
|
||||
local fcompr = function(a,b) return a > b end
|
||||
function table_binsearch(t,value,fcompval,reversed)
|
||||
-- Initialise functions
|
||||
local fcompval = fcompval or default_fcompval
|
||||
local fcomp = reversed and fcompr or fcompf
|
||||
-- Initialise numbers
|
||||
local iStart,iEnd,iMid = 1,#t,0
|
||||
-- Binary Search
|
||||
while iStart <= iEnd do
|
||||
-- calculate middle
|
||||
iMid = math.floor((iStart+iEnd)/2)
|
||||
-- get compare value
|
||||
local value2 = fcompval(t[iMid])
|
||||
-- get all values that match
|
||||
if value == value2 then
|
||||
local tfound,num = {iMid,iMid},iMid - 1
|
||||
while value == fcompval(t[num]) do
|
||||
tfound[1],num = num,num - 1
|
||||
end
|
||||
num = iMid + 1
|
||||
while value == fcompval(t[num]) do
|
||||
tfound[2],num = num,num + 1
|
||||
end
|
||||
return tfound
|
||||
-- keep searching
|
||||
elseif fcomp(value, value2) then
|
||||
iEnd = iMid - 1
|
||||
else
|
||||
iStart = iMid + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
table.bininsert( table, value [, comp] )
|
||||
|
||||
Inserts a given value through BinaryInsert into the table sorted by [, comp].
|
||||
|
||||
If 'comp' is given, then it must be a function that receives
|
||||
two table elements, and returns true when the first is less
|
||||
than the second, e.g. comp = function(a, b) return a > b end,
|
||||
will give a sorted table, with the biggest value on position 1.
|
||||
[, comp] behaves as in table.sort(table, value [, comp])
|
||||
returns the index where 'value' was inserted
|
||||
]]--
|
||||
do
|
||||
-- Avoid heap allocs for performance
|
||||
local fcomp_default = function(a,b) return a < b end
|
||||
function table_bininsert(t, value, fcomp)
|
||||
-- Initialise compare function
|
||||
local fcomp = fcomp or fcomp_default
|
||||
-- Initialise numbers
|
||||
local iStart,iEnd,iMid,iState = 1,#t,1,0
|
||||
-- Get insert position
|
||||
while iStart <= iEnd do
|
||||
-- calculate middle
|
||||
iMid = math.floor((iStart+iEnd)/2)
|
||||
-- compare
|
||||
if fcomp(value, t[iMid]) then
|
||||
iEnd,iState = iMid - 1,0
|
||||
else
|
||||
iStart,iState = iMid + 1,1
|
||||
end
|
||||
end
|
||||
table.insert(t,(iMid+iState),value)
|
||||
return (iMid+iState)
|
||||
end
|
||||
end
|
||||
|
||||
local function SpatialUpdateQueue()
|
||||
local function fcomp(a, b)
|
||||
-- Always maintain all f<=1.0 items at the end of the table
|
||||
if a.f > 1.0 and b.f <= 1.0 then
|
||||
return true
|
||||
end
|
||||
if a.f <= 1.0 and b.f > 1.0 then
|
||||
return false
|
||||
end
|
||||
return a.fw > b.fw
|
||||
end
|
||||
local self = {
|
||||
p = buildat.Vector3(0, 0, 0),
|
||||
queue_oldest_p = buildat.Vector3(0, 0, 0),
|
||||
queue = {},
|
||||
old_queue = nil,
|
||||
|
||||
-- This has to be called once per frame or so
|
||||
update = function(self, max_operations)
|
||||
max_operations = max_operations or 100
|
||||
if self.old_queue then
|
||||
log:debug("SpatialUpdateQueue(): Items in old queue: "..
|
||||
#self.old_queue)
|
||||
-- Move stuff from old queue to new queue
|
||||
for i = 1, max_operations do
|
||||
local item = table.remove(self.old_queue)
|
||||
if not item then
|
||||
self.old_queue = nil
|
||||
break
|
||||
end
|
||||
self:put_item(item)
|
||||
end
|
||||
end
|
||||
end,
|
||||
set_p = function(self, p)
|
||||
p = buildat.Vector3(p) -- Strip out the heavy Urho3D wrapper
|
||||
self.p = p
|
||||
if self.old_queue == nil and
|
||||
(p - self.queue_oldest_p):length() > 20 then
|
||||
-- Move queue to old_queue and reset queue
|
||||
self.old_queue = self.queue
|
||||
self.queue = {}
|
||||
self.queue_oldest_p = self.p
|
||||
end
|
||||
end,
|
||||
put_item = function(self, item)
|
||||
local d = (item.p - self.p):length()
|
||||
item.f = nil
|
||||
item.fw = nil
|
||||
if item.near_trigger_d then
|
||||
local f_near = d / item.near_trigger_d
|
||||
local fw_near = f_near / item.near_weight
|
||||
if item.fw == nil or (fw_near < item.fw and
|
||||
(item.f == nil or f_near < item.f)) then
|
||||
item.f = f_near
|
||||
item.fw = fw_near
|
||||
end
|
||||
end
|
||||
if item.far_trigger_d then
|
||||
local f_far = item.far_trigger_d / d
|
||||
local fw_far = f_far / item.far_weight
|
||||
if item.fw == nil or (fw_far < item.fw and
|
||||
(item.f == nil or f_far < item.f)) then
|
||||
item.f = f_far
|
||||
item.fw = fw_far
|
||||
end
|
||||
end
|
||||
assert(item.f)
|
||||
assert(item.fw)
|
||||
log:verbose("put_item"..
|
||||
": d="..dump(d)..
|
||||
", near_weight="..dump(item.near_weight)..
|
||||
", near_trigger_d="..dump(item.near_trigger_d)..
|
||||
", far_weight="..dump(item.far_weight)..
|
||||
", far_trigger_d="..dump(item.far_trigger_d)..
|
||||
" -> f="..item.f..", fw="..item.fw)
|
||||
table_bininsert(self.queue, item, fcomp)
|
||||
end,
|
||||
-- Put something to be prioritized bidirectionally
|
||||
put = function(self, p, near_weight, near_trigger_d,
|
||||
far_weight, far_trigger_d, value)
|
||||
if near_trigger_d and far_trigger_d then
|
||||
assert(near_trigger_d < far_trigger_d)
|
||||
assert(near_weight)
|
||||
assert(far_weight)
|
||||
else
|
||||
assert((near_trigger_d and near_weight) or
|
||||
(far_trigger_d and far_weight))
|
||||
end
|
||||
p = buildat.Vector3(p) -- Strip out the heavy Urho3D wrapper
|
||||
self:put_item({p=p, value=value,
|
||||
near_weight=near_weight, near_trigger_d=near_trigger_d,
|
||||
far_weight=far_weight, far_trigger_d=far_trigger_d})
|
||||
end,
|
||||
get = function(self)
|
||||
local item = table.remove(self.queue)
|
||||
if not item then return nil end
|
||||
return item.value
|
||||
end,
|
||||
-- item.f is the trigger_d value normalized so that f<1.0 means the item
|
||||
-- has passed its trigger_d.
|
||||
peek_next_f = function(self)
|
||||
local item = self.queue[#self.queue]
|
||||
if not item then return nil end
|
||||
return item.f
|
||||
end,
|
||||
-- item.fw is a comparison value; both near_priority and far_priority
|
||||
-- items are normalized so that values that have fw=1 have equal
|
||||
-- priority.
|
||||
peek_next_fw = function(self)
|
||||
local item = self.queue[#self.queue]
|
||||
if not item then return nil end
|
||||
return item.fw
|
||||
end,
|
||||
get_length = function(self)
|
||||
return #self.queue
|
||||
end,
|
||||
}
|
||||
return self
|
||||
end
|
||||
|
||||
function M.init()
|
||||
log:info("voxelworld.init()")
|
||||
|
||||
@ -367,7 +154,7 @@ function M.init()
|
||||
node_update_queue:set_p(camera_p)
|
||||
-- Scale queue update operations according to the handling time of the
|
||||
-- rest of the processing
|
||||
node_update_queue:update(max_handling_time_us / 200 + 1)
|
||||
node_update_queue:update(max_handling_time_us / 50 + 1)
|
||||
|
||||
for i = 1, 10 do -- Usually there is time only for a few
|
||||
local f = node_update_queue:peek_next_f()
|
||||
|
Loading…
x
Reference in New Issue
Block a user