client: voxelworld.get_static_voxel()

master
Perttu Ahola 2014-10-21 12:57:57 +03:00
parent 3c25b40bae
commit d2839d5cf3
9 changed files with 151 additions and 3 deletions

View File

@ -13,7 +13,8 @@ local M = {}
-- because each chunk will be rendered as a whole according to the zone its
-- center position is in
--local ideal_zone_size = 32
-- NOTE: Actually, when zone overrides are used, this can be lower
-- NOTE: Actually, when zone overrides are used, this can be lower; but it will
-- require more processing as all renderable things are in the same octree
local ideal_zone_size = 16
M.sector_size = buildat.Vector2(0, 0)

View File

@ -362,6 +362,78 @@ function M.sub_geometry_update(cb)
table.insert(geometry_update_cbs, cb)
end
-- Return value: VoxelInstance (found), VoxelInstance(0) (not found)
function M.get_static_voxel(p)
p = buildat.Vector3(p):round()
log:debug("get_static_voxel(): p="..p:dump())
-- Calculate which chunk this voxel is in
local chunk_p = p:div_components(M.chunk_size_voxels):floor()
log:debug("get_static_voxel(): chunk_p="..chunk_p:dump())
-- NOTE: Chunks are positioned by their center position, and chunks are
-- aligned to a grid offset by half their size from global origin
local chunk_center_p = chunk_p:mul_components(M.chunk_size_voxels) +
M.chunk_size_voxels / 2
log:debug("get_static_voxel(): chunk_center_p="..chunk_center_p:dump())
-- Find the static node
local scene = replicate.main_scene
local octree = scene:GetComponent("Octree")
local clearance = magic.Vector3(1,1,1)
local find_lc = chunk_center_p - clearance
local find_uc = chunk_center_p + clearance
log:debug("get_static_voxel(): find_lc="..find_lc:dump())
log:debug("get_static_voxel(): find_uc="..find_uc:dump())
local result = octree:GetDrawables(magic.BoundingBox(
magic.Vector3.from_buildat(find_lc),
magic.Vector3.from_buildat(find_uc)))
log:debug("get_static_voxel(): result="..dump(result))
-- NOTE: The result will contain all kinds of global things like zones and
-- lights
-- NOTE: Static nodes can be distinguished by the user variable
-- buildat_static=true
local node = nil
for _, v in ipairs(result) do
--log:debug("get_static_voxel(): result node:GetName()="..v.node:GetName())
local buildat_static_var = v.node:GetVar("buildat_static")
if buildat_static_var:GetBool() == true then
node = v.node
break
end
end
if node == nil then
log:debug("get_static_voxel(): static node not found")
for _, v in ipairs(result) do
log:debug("get_static_voxel(): * not "..v.node:GetName())
end
return buildat.VoxelInstance(0)
end
-- Calculate position inside the chunk
local in_chunk_p = p - M.chunk_size_voxels:mul_components(chunk_p)
log:debug("get_static_voxel(): in_chunk_p="..in_chunk_p:dump())
-- Get voxel from volume
local data = node:GetVar("buildat_voxel_data"):GetBuffer()
if data == nil then
log_w(MODULE, "Invalid static node does not contain buildat_voxel_data")
return buildat.VoxelInstance(0)
end
local volume = buildat.deserialize_volume(data)
log:debug("get_static_voxel(): volume="..dump(volume))
local v = volume:get_voxel_at(in_chunk_p.x, in_chunk_p.y, in_chunk_p.z)
log:debug("get_static_voxel(): v="..dump(v))
return v
end
-- TODO
-- NOTE: This does not synchronize the voxel to the server, because games have
-- to implement their own mechanisms for disallowing cheating
function M.set_static_voxel(x, y, z, v)
if type(x) == "table" then
z = x.z
y = x.y
x = x.x
end
end
function send_get_section(p)
local data = cereal.binary_output({
p = {

View File

@ -29,6 +29,7 @@
#include <ResourceCache.h>
#include <Light.h>
#include <Geometry.h>
#include <Zone.h>
#pragma GCC diagnostic pop
#include <deque>
#include <algorithm>
@ -533,13 +534,23 @@ struct Module: public interface::Module, public voxelworld::Interface
throw Exception("Can't handle static node id=0");
section.node_ids->setVoxelAt(chunk_p, n->GetID());
n->SetScale(Vector3(1.0f, 1.0f, 1.0f));
n->SetPosition(node_p);
// Distinguish static voxel nodes from others
n->SetVar(StringHash("buildat_static"), Variant(true));
int w = m_chunk_size_voxels.getX();
int h = m_chunk_size_voxels.getY();
int d = m_chunk_size_voxels.getZ();
// This makes sure the node will be found when searched from the octree,
// both on the server and the client
Zone *node_zone = n->CreateComponent<Zone>();
node_zone->SetPriority(-1000);
node_zone->SetBoundingBox(BoundingBox(
Vector3(-w/2, -h/2, -d/2), Vector3(w/2, h/2, d/2)));
n->SetScale(Vector3(1.0f, 1.0f, 1.0f));
n->SetPosition(node_p);
// NOTE: These volumes have one extra voxel at each edge in order to
// make proper meshes without gaps
// TODO: Is this needed anymore?

View File

@ -20,6 +20,7 @@ buildat.safe.createAtlasRegistry = __buildat_createAtlasRegistry
buildat.safe.Region = __buildat_Region
buildat.safe.VoxelInstance = __buildat_VoxelInstance
buildat.safe.Volume = __buildat_Volume
buildat.safe.deserialize_volume = __buildat_deserialize_volume
buildat.safe.deserialize_volume_int32 = __buildat_deserialize_volume_int32
buildat.safe.deserialize_volume_8bit = __buildat_deserialize_volume_8bit
@ -225,6 +226,10 @@ local Vector3_prototype = {
return buildat.safe.Vector3(
math.floor(a.x), math.floor(a.y), math.floor(a.z))
end,
round = function(a)
return buildat.safe.Vector3(
math.floor(a.x+0.5), math.floor(a.y+0.5), math.floor(a.z+0.5))
end,
add = function(a, b)
return buildat.safe.Vector3(
a.x + b.x, a.y + b.y, a.z + b.z)
@ -284,6 +289,10 @@ local Vector2_prototype = {
return buildat.safe.Vector2(
math.floor(a.x), math.floor(a.y))
end,
round = function(a)
return buildat.safe.Vector2(
math.floor(a.x+0.5), math.floor(a.y+0.5))
end,
add = function(a, b)
return buildat.safe.Vector2(
a.x + b.x, a.y + b.y)

View File

@ -61,3 +61,5 @@ Buildat TODO
without anyone noticing
- Altough, network is very rarely modified so it doesn't really matter
- Rename VoxelInstance::getId() to VoxelInstance::get_id()
- A way of figuring out which voxel is being pointed at
- Get rid of the dual module reload when saving a C++ file in Vim

View File

@ -256,6 +256,8 @@ function M.unsafe_to_safe(unsafe_thing, valid_types)
if valid_type == '__nil' and unsafe_thing == nil then
return unsafe_thing
end
-- NOTE: Do not consider tables safe until explicitly allowed, because
-- tables often are unsafe
if valid_type == '__safe' and (
unsafe_thing == nil or
(type(thing_meta) == 'table' and thing_meta.type_name) or

View File

@ -49,6 +49,8 @@ function M.define(dst, util)
"GetString", {"string"}, {"Variant"}),
GetInt = util.self_function(
"GetInt", {"number"}, {"Variant"}),
GetBool = util.self_function(
"GetBool", {"boolean"}, {"Variant"}),
GetBuffer = util.wrap_function({"Variant"},
function(self)
return util.wrap_instance("VectorBuffer", self:GetBuffer())
@ -136,6 +138,11 @@ function M.define(dst, util)
function(x, y, z)
return util.wrap_instance("Vector3", Vector3(x, y, z))
end),
class = {
from_buildat = function(v)
return util.wrap_instance("Vector3", Vector3(v.x, v.y, v.z))
end,
},
instance = {
Length = util.self_function(
"Length", {"number"}, {"Vector3"}),
@ -271,6 +278,25 @@ function M.define(dst, util)
util.wc("Octree", {
inherited_from_by_wrapper = dst.Component,
instance = {
GetDrawables = util.wrap_function({"table"}, {"Octree", "BoundingBox"},
function(self, query)
local unsafe_result = self:GetDrawables(query)
--log:info(dump(result))
-- The result is a list of OctreeQueryResults; we will
-- convert it to a list of tables that contain the fields of
-- OctreeQueryResult.
local result = {}
for _, v in ipairs(unsafe_result) do
table.insert(result, {
drawable = util.wrap_instance("Drawable", v.drawable),
node = util.wrap_instance("Node", v.node),
})
end
return result
end
),
},
})
util.wc("Drawable", {

View File

@ -177,6 +177,10 @@ magic.SubscribeToEvent("KeyDown", function(event_type, event_data)
end
end)
-- Return value: nil or buildat.Vector3
local function find_pointed_voxel()
end
magic.SubscribeToEvent("MouseButtonDown", function(event_type, event_data)
local button = event_data:GetInt("Button")
log:info("MouseButtonDown: "..button)
@ -214,6 +218,12 @@ magic.SubscribeToEvent("MouseButtonDown", function(event_type, event_data)
})
buildat.send_packet("main:dig", data)
end
if button == magic.MOUSEB_MIDDLE then
local p = player_node.position
local v = voxelworld.get_static_voxel(p)
log:info("get_static_voxel("..buildat.Vector3(p):dump()..")"..
" returned v.id="..dump(v.id))
end
end)
magic.SubscribeToEvent("Update", function(event_type, event_data)

View File

@ -56,6 +56,20 @@ void voxelinstance_set_int32(VoxelInstance &v, int32_t d){
typedef pv::RawVolume<VoxelInstance> CommonVolume;
sp_<CommonVolume> deserialize_volume(
const luabind::object &buffer_o, lua_State *L)
{
TRY_GET_SANDBOX_STUFF(buf, 1, VectorBuffer);
ss_ data;
if(buf == nullptr)
data = lua_checkcppstring(L, 1);
else
data.assign((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
return interface::deserialize_volume(data);
}
sp_<CommonVolume> deserialize_volume_int32(
const luabind::object &buffer_o, lua_State *L)
{
@ -153,6 +167,7 @@ void init_voxel_volume(lua_State *L)
&CommonVolume::setVoxelAt)
.def("get_enclosing_region", &CommonVolume::getEnclosingRegion)
,
LUABIND_FUNC(deserialize_volume),
LUABIND_FUNC(deserialize_volume_int32),
LUABIND_FUNC(deserialize_volume_8bit)
];