builtin/voxelworld, games/digger: WIP
This commit is contained in:
parent
6d26d3144d
commit
6115d92f3f
@ -12,6 +12,7 @@ local camera_node = nil
|
||||
local update_counter = -1
|
||||
local camera_last_dir = magic.Vector3(0, 0, 0)
|
||||
local camera_last_p = magic.Vector3(0, 0, 0)
|
||||
local end_of_update_processing_us = 0
|
||||
|
||||
M.chunk_size_voxels = nil
|
||||
M.section_size_chunks = nil
|
||||
@ -37,10 +38,10 @@ M.section_size_voxels = 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 )
|
||||
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
|
||||
@ -49,22 +50,22 @@ do
|
||||
-- Binary Search
|
||||
while iStart <= iEnd do
|
||||
-- calculate middle
|
||||
iMid = math.floor( (iStart+iEnd)/2 )
|
||||
iMid = math.floor((iStart+iEnd)/2)
|
||||
-- get compare value
|
||||
local value2 = fcompval( t[iMid] )
|
||||
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
|
||||
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
|
||||
while value == fcompval(t[num]) do
|
||||
tfound[2],num = num,num + 1
|
||||
end
|
||||
return tfound
|
||||
-- keep searching
|
||||
elseif fcomp( value,value2 ) then
|
||||
elseif fcomp(value, value2) then
|
||||
iEnd = iMid - 1
|
||||
else
|
||||
iStart = iMid + 1
|
||||
@ -87,7 +88,7 @@ end
|
||||
]]--
|
||||
do
|
||||
-- Avoid heap allocs for performance
|
||||
local fcomp_default = function( a,b ) return a < b end
|
||||
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
|
||||
@ -96,45 +97,50 @@ do
|
||||
-- Get insert position
|
||||
while iStart <= iEnd do
|
||||
-- calculate middle
|
||||
iMid = math.floor( (iStart+iEnd)/2 )
|
||||
iMid = math.floor((iStart+iEnd)/2)
|
||||
-- compare
|
||||
if fcomp( value,t[iMid] ) then
|
||||
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 )
|
||||
table.insert(t,(iMid+iState),value)
|
||||
return (iMid+iState)
|
||||
end
|
||||
end
|
||||
|
||||
local function SpatialUpdateQueue()
|
||||
local function fcomp(a, b) return a.d > b.d end
|
||||
local self = {
|
||||
p = magic.Vector3(0, 0, 0),
|
||||
queue_oldest_p = magic.Vector3(0, 0, 0),
|
||||
p = buildat.Vector3(0, 0, 0),
|
||||
queue_oldest_p = buildat.Vector3(0, 0, 0),
|
||||
queue = {},
|
||||
old_queue = nil,
|
||||
|
||||
update = function(self)
|
||||
-- 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, 100 do
|
||||
for i = 1, max_operations do
|
||||
local item = table.remove(self.old_queue)
|
||||
if not item then
|
||||
self.old_queue = nil
|
||||
break
|
||||
end
|
||||
item.d = (item.p - self.p):Length()
|
||||
local function fcomp(a, b) return a.d > b.d end
|
||||
item.d = (item.p - self.p):length()
|
||||
table_bininsert(self.queue, item, fcomp)
|
||||
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() > 16 then
|
||||
(p - self.queue_oldest_p):length() > 20 then
|
||||
-- Move queue to old_queue and reset queue
|
||||
self.old_queue = self.queue
|
||||
self.queue = {}
|
||||
@ -142,13 +148,11 @@ local function SpatialUpdateQueue()
|
||||
end
|
||||
end,
|
||||
put = function(self, p, value)
|
||||
self:update()
|
||||
local d = (p - self.p):Length()
|
||||
local function fcomp(a, b) return a.d > b.d end
|
||||
p = buildat.Vector3(p) -- Strip out the heavy Urho3D wrapper
|
||||
local d = (p - self.p):length()
|
||||
table_bininsert(self.queue, {p=p, d=d, value=value}, fcomp)
|
||||
end,
|
||||
get = function(self, p)
|
||||
self:update()
|
||||
get = function(self)
|
||||
local item = table.remove(self.queue)
|
||||
if not item then return nil end
|
||||
return item.value
|
||||
@ -174,8 +178,8 @@ function M.init()
|
||||
}},
|
||||
})
|
||||
log:info(dump(values))
|
||||
M.chunk_size_voxels = buildat.IntVector3(values.chunk_size_voxels)
|
||||
M.section_size_chunks = buildat.IntVector3(values.section_size_chunks)
|
||||
M.chunk_size_voxels = buildat.Vector3(values.chunk_size_voxels)
|
||||
M.section_size_chunks = buildat.Vector3(values.section_size_chunks)
|
||||
M.section_size_voxels =
|
||||
M.chunk_size_voxels:mul_components(M.section_size_chunks)
|
||||
end)
|
||||
@ -197,23 +201,25 @@ function M.init()
|
||||
local node_update_queue = SpatialUpdateQueue()
|
||||
|
||||
magic.SubscribeToEvent("Update", function(event_type, event_data)
|
||||
--local t0 = buildat.get_time_us()
|
||||
--local dt = event_data:GetFloat("TimeStep")
|
||||
update_counter = update_counter + 1
|
||||
|
||||
if camera_node and M.section_size_voxels then
|
||||
-- TODO: How should position information be sent to the server?
|
||||
local p = camera_node:GetWorldPosition()
|
||||
if update_counter % 60 == 0 then
|
||||
local section_p = buildat.IntVector3(p):div_components(
|
||||
local section_p = buildat.Vector3(p):div_components(
|
||||
M.section_size_voxels):floor()
|
||||
--log:info("p: "..p.x..", "..p.y..", "..p.z.." -> section_p: "..
|
||||
-- section_p.x..", "..section_p.y..", "..section_p.z)
|
||||
--[[send_get_section(section_p + buildat.IntVector3( 0, 0, 0))
|
||||
send_get_section(section_p + buildat.IntVector3(-1, 0, 0))
|
||||
send_get_section(section_p + buildat.IntVector3( 1, 0, 0))
|
||||
send_get_section(section_p + buildat.IntVector3( 0, 1, 0))
|
||||
send_get_section(section_p + buildat.IntVector3( 0,-1, 0))
|
||||
send_get_section(section_p + buildat.IntVector3( 0, 0, 1))
|
||||
send_get_section(section_p + buildat.IntVector3( 0, 0,-1))]]
|
||||
--[[send_get_section(section_p + buildat.Vector3( 0, 0, 0))
|
||||
send_get_section(section_p + buildat.Vector3(-1, 0, 0))
|
||||
send_get_section(section_p + buildat.Vector3( 1, 0, 0))
|
||||
send_get_section(section_p + buildat.Vector3( 0, 1, 0))
|
||||
send_get_section(section_p + buildat.Vector3( 0,-1, 0))
|
||||
send_get_section(section_p + buildat.Vector3( 0, 0, 1))
|
||||
send_get_section(section_p + buildat.Vector3( 0, 0,-1))]]
|
||||
end
|
||||
end
|
||||
|
||||
@ -225,36 +231,63 @@ function M.init()
|
||||
camera_p = camera_node:GetWorldPosition()
|
||||
end
|
||||
|
||||
-- Handle one node update per frame
|
||||
-- Node updates: Handle one or a few per frame
|
||||
local current_us = buildat.get_time_us()
|
||||
-- Spend time doing this proportionate to the rest of the update cycle
|
||||
local max_handling_time_us = (current_us - end_of_update_processing_us) / 2
|
||||
local stop_at_us = current_us + max_handling_time_us
|
||||
|
||||
-- Scale queue updates to the same pace as the rest of the processing
|
||||
node_update_queue:set_p(camera_p)
|
||||
local node_update = node_update_queue:get()
|
||||
if node_update then
|
||||
if node_update.type == "geometry" then
|
||||
update_voxel_geometry(node_update.node)
|
||||
node_update_queue:update(max_handling_time_us / 200 + 1)
|
||||
|
||||
for i = 1, 10 do -- Usually there is time only for a few
|
||||
local node_update = node_update_queue:get()
|
||||
if node_update then
|
||||
--local d = (node_update.node:GetWorldPosition() - camera_p):Length()
|
||||
--if d < 50 then
|
||||
if true then
|
||||
log:verbose("Handling node update #"..
|
||||
#node_update_queue.queue)
|
||||
local node = replicate.main_scene:GetNode(node_update.node_id)
|
||||
if node_update.type == "geometry" then
|
||||
update_voxel_geometry(node)
|
||||
end
|
||||
if node_update.type == "physics" then
|
||||
update_voxel_physics(node)
|
||||
end
|
||||
else
|
||||
log:verbose("Discarding node update #"..
|
||||
#node_update_queue.queue)
|
||||
end
|
||||
end
|
||||
if node_update.type == "physics" then
|
||||
update_voxel_physics(node_update.node)
|
||||
-- Check this at the end of the loop so at least one is handled
|
||||
if buildat.get_time_us() >= stop_at_us then
|
||||
log:info("Handled "..i.." node updates")
|
||||
break
|
||||
end
|
||||
end
|
||||
end_of_update_processing_us = buildat.get_time_us()
|
||||
|
||||
if camera_node then
|
||||
camera_last_dir = camera_dir
|
||||
camera_last_p = camera_p
|
||||
end
|
||||
--log:info(buildat.get_time_us()-t0)
|
||||
end)
|
||||
|
||||
replicate.sub_sync_node_added({}, function(node)
|
||||
if not node:GetVar("buildat_voxel_data"):IsEmpty() then
|
||||
node_update_queue:put(node:GetWorldPosition(), {
|
||||
type = "geometry",
|
||||
node = node,
|
||||
node_id = node:GetID(),
|
||||
})
|
||||
node_update_queue:put(node:GetWorldPosition(), {
|
||||
type = "physics",
|
||||
node = node,
|
||||
node_id = node:GetID(),
|
||||
})
|
||||
end
|
||||
local name = node:GetName()
|
||||
--local name = node:GetName()
|
||||
end)
|
||||
end
|
||||
|
||||
|
@ -197,14 +197,14 @@ struct Module: public interface::Module, public voxelworld::Interface
|
||||
sp_<interface::BlockRegistry> m_block_reg;
|
||||
|
||||
// One node holds one chunk of voxels (eg. 24x24x24)
|
||||
pv::Vector3DInt16 m_chunk_size_voxels = pv::Vector3DInt16(24, 24, 24);
|
||||
pv::Vector3DInt16 m_chunk_size_voxels = pv::Vector3DInt16(32, 32, 32);
|
||||
//pv::Vector3DInt16 m_chunk_size_voxels = pv::Vector3DInt16(24, 24, 24);
|
||||
//pv::Vector3DInt16 m_chunk_size_voxels = pv::Vector3DInt16(16, 16, 16);
|
||||
//pv::Vector3DInt16 m_chunk_size_voxels = pv::Vector3DInt16(8, 8, 8);
|
||||
|
||||
// The world is loaded and unloaded by sections (eg. 2x2x2)
|
||||
pv::Vector3DInt16 m_section_size_chunks = pv::Vector3DInt16(2, 2, 2);
|
||||
|
||||
// These are suitable for running under valgrind
|
||||
//pv::Vector3DInt16 m_chunk_size_voxels = pv::Vector3DInt16(8, 8, 8);
|
||||
//pv::Vector3DInt16 m_section_size_chunks = pv::Vector3DInt16(2, 2, 2);
|
||||
|
||||
// Sections (this(y,z)=sector, sector(x)=section)
|
||||
sm_<pv::Vector<2, int16_t>, sm_<int16_t, Section>> m_sections;
|
||||
// Cache of last used sections (add to end, remove from beginning)
|
||||
@ -339,7 +339,8 @@ struct Module: public interface::Module, public voxelworld::Interface
|
||||
|
||||
void on_start()
|
||||
{
|
||||
pv::Region region(-2, -1, -2, 2, 1, 2);
|
||||
pv::Region region(-3, -1, -3, 3, 1, 3);
|
||||
//pv::Region region(-8, -1, -8, 8, 1, 8);
|
||||
auto lc = region.getLowerCorner();
|
||||
auto uc = region.getUpperCorner();
|
||||
for(int z = lc.getZ(); z <= uc.getZ(); z++){
|
||||
|
@ -9,6 +9,8 @@ local magic = require("buildat/extension/urho3d")
|
||||
local replicate = require("buildat/extension/replicate")
|
||||
local voxelworld = require("buildat/module/voxelworld")
|
||||
|
||||
local RENDER_DISTANCE = 160
|
||||
|
||||
local PLAYER_HEIGHT = 1.7
|
||||
local PLAYER_WIDTH = 0.9
|
||||
local MOVE_SPEED = 10
|
||||
@ -24,7 +26,7 @@ zone.boundingBox = magic.BoundingBox(-1000, 1000)
|
||||
zone.ambientColor = magic.Color(0.1, 0.1, 0.1)
|
||||
zone.fogColor = magic.Color(0.6, 0.7, 0.8)
|
||||
zone.fogStart = 10
|
||||
zone.fogEnd = 300
|
||||
zone.fogEnd = RENDER_DISTANCE
|
||||
|
||||
-- Add a node that the player can use to walk around with
|
||||
local player_node = scene:CreateChild("Player")
|
||||
@ -45,30 +47,12 @@ shape:SetCapsule(PLAYER_WIDTH, PLAYER_HEIGHT)
|
||||
|
||||
local player_touches_ground = false
|
||||
|
||||
--[[local other_node = scene:CreateChild("Other")
|
||||
other_node.position = magic.Vector3(0, 10, 0)
|
||||
local body = other_node:CreateComponent("RigidBody")
|
||||
body.mass = 0
|
||||
--body.friction = 0.7
|
||||
local shape = other_node:CreateComponent("CollisionShape")
|
||||
shape:SetBox(magic.Vector3(50, 1, 50))]]
|
||||
|
||||
--[[
|
||||
-- Add a camera so we can look at the scene
|
||||
local camera_node = scene:CreateChild("Camera")
|
||||
camera_node.position = magic.Vector3(70.0, 50.0, 70.0)
|
||||
camera_node:LookAt(magic.Vector3(0, -5, 0))
|
||||
local camera = camera_node:CreateComponent("Camera")
|
||||
camera.nearClip = 1.0
|
||||
camera.farClip = 500.0
|
||||
--]]
|
||||
|
||||
-- Add a camera so we can look at the scene
|
||||
local camera_node = player_node:CreateChild("Camera")
|
||||
camera_node.position = magic.Vector3(0, 0.411*PLAYER_HEIGHT, 0)
|
||||
local camera = camera_node:CreateComponent("Camera")
|
||||
camera.nearClip = 0.3
|
||||
camera.farClip = 500.0
|
||||
camera.farClip = RENDER_DISTANCE
|
||||
camera.fov = 75
|
||||
|
||||
-- And this thing so the camera is shown on the screen
|
||||
|
@ -152,7 +152,7 @@ struct Module: public interface::Module
|
||||
log_v(MODULE, "Testbox: (%f, %f, %f)", p.x_, p.y_, p.z_);
|
||||
});*/
|
||||
static uint a = 0;
|
||||
if(((a++) % 50) == 0){
|
||||
if(((a++) % 100) == 0){
|
||||
m_server->access_scene([&](Scene *scene){
|
||||
Node *n = scene->GetChild("Testbox");
|
||||
n->SetRotation(Quaternion(30, 60, 90));
|
||||
@ -187,7 +187,7 @@ struct Module: public interface::Module
|
||||
log_t(MODULE, "on_generation_request(): p1: (%i, %i, %i)",
|
||||
p1.getX(), p1.getY(), p1.getZ());
|
||||
|
||||
interface::NoiseParams np(0, 20, interface::v3f(40,40,40), 0, 4, 0.5);
|
||||
interface::NoiseParams np(0, 25, interface::v3f(80,80,80), 0, 5, 0.5);
|
||||
|
||||
auto lc = region.getLowerCorner();
|
||||
auto uc = region.getUpperCorner();
|
||||
|
Loading…
x
Reference in New Issue
Block a user