VoxelRegistry Lua interface WIP
This commit is contained in:
parent
89ed2a114c
commit
bbc300f540
@ -155,6 +155,7 @@ if(BUILD_CLIENT)
|
||||
src/lua_bindings/misc.cpp
|
||||
src/lua_bindings/cereal.cpp
|
||||
src/lua_bindings/voxel.cpp
|
||||
src/lua_bindings/mesh.cpp
|
||||
src/lua_bindings/spatial_update_queue.cpp
|
||||
src/lua_bindings/misc_urho3d.cpp
|
||||
)
|
||||
@ -167,6 +168,7 @@ if(BUILD_CLIENT)
|
||||
smallsha1
|
||||
PolyVoxCore
|
||||
zlib
|
||||
luabind
|
||||
${ABSOLUTE_PATH_LIBS}
|
||||
${LINK_LIBS_ONLY}
|
||||
${URHO3D_HOME}/Build/ThirdParty/toluapp/src/lib/libtoluapp.a
|
||||
|
@ -37,6 +37,9 @@ local camera_last_dir = camera_dir
|
||||
|
||||
local end_of_update_processing_us = 0
|
||||
|
||||
local voxel_reg = buildat.createVoxelRegistry()
|
||||
voxel_reg:deserialize("foo")
|
||||
|
||||
M.chunk_size_voxels = nil
|
||||
M.section_size_chunks = nil
|
||||
M.section_size_voxels = nil
|
||||
|
@ -12,6 +12,7 @@ buildat.safe.disconnect = __buildat_disconnect
|
||||
buildat.safe.get_time_us = __buildat_get_time_us
|
||||
buildat.safe.profiler_block_begin = __buildat_profiler_block_begin
|
||||
buildat.safe.profiler_block_end = __buildat_profiler_block_end
|
||||
buildat.safe.createVoxelRegistry = createVoxelRegistry
|
||||
|
||||
buildat.safe.SpatialUpdateQueue = function()
|
||||
local internal = __buildat_SpatialUpdateQueue()
|
||||
|
@ -176,8 +176,28 @@ struct CVoxelRegistry: public VoxelRegistry
|
||||
// Caller sets cache.textures_valid = true
|
||||
}
|
||||
|
||||
// TODO: Network serialization
|
||||
// TODO: Ability to track changes (just some kind of set_dirty()?)
|
||||
void serialize(std::ostream &os)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void deserialize(std::istream &is)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
ss_ serialize()
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
serialize(os);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void deserialize(const ss_ &s)
|
||||
{
|
||||
std::istringstream is(s, std::ios::binary);
|
||||
deserialize(is);
|
||||
}
|
||||
};
|
||||
|
||||
VoxelRegistry* createVoxelRegistry()
|
||||
|
@ -92,7 +92,11 @@ namespace interface
|
||||
virtual const CachedVoxelDefinition* get_cached(const VoxelInstance &v,
|
||||
TextureAtlasRegistry *atlas_reg = nullptr) = 0;
|
||||
|
||||
// TODO: Network serialization
|
||||
virtual void serialize(std::ostream &os) = 0;
|
||||
virtual void deserialize(std::istream &is) = 0;
|
||||
virtual ss_ serialize() = 0;
|
||||
virtual void deserialize(const ss_ &s) = 0;
|
||||
|
||||
// TODO: Ability to track changes (just some kind of set_dirty()?)
|
||||
};
|
||||
|
||||
|
@ -10,6 +10,7 @@ namespace lua_bindings {
|
||||
extern void init_misc(lua_State *L);
|
||||
extern void init_cereal(lua_State *L);
|
||||
extern void init_voxel(lua_State *L);
|
||||
extern void init_mesh(lua_State *L);
|
||||
extern void init_spatial_update_queue(lua_State *L);
|
||||
extern void init_misc_urho3d(lua_State *L);
|
||||
|
||||
@ -18,6 +19,7 @@ void init(lua_State *L)
|
||||
init_misc(L);
|
||||
init_cereal(L);
|
||||
init_voxel(L);
|
||||
init_mesh(L);
|
||||
init_spatial_update_queue(L);
|
||||
init_misc_urho3d(L);
|
||||
}
|
||||
|
488
src/lua_bindings/mesh.cpp
Normal file
488
src/lua_bindings/mesh.cpp
Normal file
@ -0,0 +1,488 @@
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// Copyright 2014 Perttu Ahola <celeron55@gmail.com>
|
||||
#include "lua_bindings/util.h"
|
||||
#include "core/log.h"
|
||||
#include "client/app.h"
|
||||
#include "interface/mesh.h"
|
||||
#include "interface/voxel_volume.h"
|
||||
#include "interface/worker_thread.h"
|
||||
#include <tolua++.h>
|
||||
#include <c55/os.h>
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#include <Scene.h>
|
||||
#include <StaticModel.h>
|
||||
#include <Model.h>
|
||||
#include <CustomGeometry.h>
|
||||
#include <CollisionShape.h>
|
||||
#include <RigidBody.h>
|
||||
#pragma GCC diagnostic pop
|
||||
#define MODULE "lua_bindings"
|
||||
|
||||
namespace magic = Urho3D;
|
||||
namespace pv = PolyVox;
|
||||
|
||||
using interface::VoxelInstance;
|
||||
|
||||
// Just do this; Urho3D's stuff doesn't really clash with anything in buildat
|
||||
using namespace Urho3D;
|
||||
|
||||
namespace lua_bindings {
|
||||
|
||||
#define GET_TOLUA_STUFF(result_name, index, type) \
|
||||
if(!tolua_isusertype(L, index, #type, 0, &tolua_err)){ \
|
||||
tolua_error(L, __PRETTY_FUNCTION__, &tolua_err); \
|
||||
return 0; \
|
||||
} \
|
||||
type *result_name = (type*)tolua_tousertype(L, index, 0);
|
||||
#define TRY_GET_TOLUA_STUFF(result_name, index, type) \
|
||||
type *result_name = nullptr; \
|
||||
if(tolua_isusertype(L, index, #type, 0, &tolua_err)){ \
|
||||
result_name = (type*)tolua_tousertype(L, index, 0); \
|
||||
}
|
||||
|
||||
// NOTE: This API is designed this way because otherwise ownership management of
|
||||
// objects sucks
|
||||
// set_simple_voxel_model(node, w, h, d, buffer: VectorBuffer)
|
||||
static int l_set_simple_voxel_model(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
GET_TOLUA_STUFF(node, 1, Node);
|
||||
int w = lua_tointeger(L, 2);
|
||||
int h = lua_tointeger(L, 3);
|
||||
int d = lua_tointeger(L, 4);
|
||||
TRY_GET_TOLUA_STUFF(buf, 5, const VectorBuffer);
|
||||
|
||||
log_d(MODULE, "set_simple_voxel_model(): node=%p", node);
|
||||
log_d(MODULE, "set_simple_voxel_model(): buf=%p", buf);
|
||||
|
||||
ss_ data;
|
||||
if(buf == nullptr)
|
||||
data = lua_tocppstring(L, 5);
|
||||
else
|
||||
data.assign((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
|
||||
|
||||
if((int)data.size() != w * h * d){
|
||||
log_e(MODULE, "set_simple_voxel_model(): Data size does not match "
|
||||
"with dimensions (%zu vs. %i)", data.size(), w*h*d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__buildat_app");
|
||||
app::App *buildat_app = (app::App*)lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
Context *context = buildat_app->get_scene()->GetContext();
|
||||
|
||||
SharedPtr<Model> fromScratchModel(
|
||||
interface::mesh::create_simple_voxel_model(context, w, h, d, data));
|
||||
|
||||
StaticModel *object = node->GetOrCreateComponent<StaticModel>();
|
||||
object->SetModel(fromScratchModel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// set_8bit_voxel_geometry(node, w, h, d, buffer: VectorBuffer)
|
||||
static int l_set_8bit_voxel_geometry(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
GET_TOLUA_STUFF(node, 1, Node);
|
||||
int w = lua_tointeger(L, 2);
|
||||
int h = lua_tointeger(L, 3);
|
||||
int d = lua_tointeger(L, 4);
|
||||
TRY_GET_TOLUA_STUFF(buf, 5, const VectorBuffer);
|
||||
|
||||
log_d(MODULE, "set_8bit_voxel_geometry(): node=%p", node);
|
||||
log_d(MODULE, "set_8bit_voxel_geometry(): buf=%p", buf);
|
||||
|
||||
ss_ data;
|
||||
if(buf == nullptr)
|
||||
data = lua_tocppstring(L, 5);
|
||||
else
|
||||
data.assign((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
|
||||
|
||||
if((int)data.size() != w * h * d){
|
||||
log_e(MODULE, "set_8bit_voxel_geometry(): Data size does not match "
|
||||
"with dimensions (%zu vs. %i)", data.size(), w*h*d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__buildat_app");
|
||||
app::App *buildat_app = (app::App*)lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
Context *context = buildat_app->get_scene()->GetContext();
|
||||
auto *voxel_reg = buildat_app->get_voxel_registry();
|
||||
auto *atlas_reg = buildat_app->get_atlas_registry();
|
||||
|
||||
CustomGeometry *cg = node->GetOrCreateComponent<CustomGeometry>();
|
||||
|
||||
interface::mesh::set_8bit_voxel_geometry(cg, context, w, h, d, data,
|
||||
voxel_reg, atlas_reg);
|
||||
|
||||
// Maybe appropriate
|
||||
cg->SetOccluder(true);
|
||||
|
||||
// TODO: Don't do this here; allow the caller to do this
|
||||
cg->SetCastShadows(true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG_TIMING
|
||||
struct ScopeTimer {
|
||||
const char *name;
|
||||
uint64_t t0;
|
||||
ScopeTimer(const char *name="unknown"): name(name){
|
||||
t0 = get_timeofday_us();
|
||||
}
|
||||
~ScopeTimer(){
|
||||
int d = get_timeofday_us() - t0;
|
||||
if(d > 3000)
|
||||
log_w(MODULE, "%ius (%s)", d, name);
|
||||
else
|
||||
log_v(MODULE, "%ius (%s)", d, name);
|
||||
}
|
||||
};
|
||||
#else
|
||||
struct ScopeTimer {
|
||||
ScopeTimer(const char *name=""){}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct SetVoxelGeometryTask: public interface::worker_thread::Task
|
||||
{
|
||||
Node *node;
|
||||
ss_ data;
|
||||
interface::VoxelRegistry *voxel_reg;
|
||||
interface::TextureAtlasRegistry *atlas_reg;
|
||||
|
||||
up_<pv::RawVolume<VoxelInstance>> volume;
|
||||
sm_<uint, interface::mesh::TemporaryGeometry> temp_geoms;
|
||||
|
||||
SetVoxelGeometryTask(Node *node, const ss_ &data,
|
||||
interface::VoxelRegistry *voxel_reg,
|
||||
interface::TextureAtlasRegistry *atlas_reg):
|
||||
node(node), data(data), voxel_reg(voxel_reg), atlas_reg(atlas_reg)
|
||||
{
|
||||
ScopeTimer timer("pre geometry");
|
||||
// NOTE: Do the pre-processing here so that the calling code can
|
||||
// meaasure how long its execution takes
|
||||
// NOTE: Could be split in two calls
|
||||
volume = interface::deserialize_volume(data);
|
||||
interface::mesh::preload_textures(*volume, voxel_reg, atlas_reg);
|
||||
}
|
||||
// Called repeatedly from main thread until returns true
|
||||
bool pre()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Called repeatedly from worker thread until returns true
|
||||
bool thread()
|
||||
{
|
||||
generate_voxel_geometry(temp_geoms, *volume, voxel_reg, atlas_reg);
|
||||
return true;
|
||||
}
|
||||
// Called repeatedly from main thread until returns true
|
||||
bool post()
|
||||
{
|
||||
ScopeTimer timer("post geometry");
|
||||
Context *context = node->GetContext();
|
||||
CustomGeometry *cg = node->GetOrCreateComponent<CustomGeometry>();
|
||||
interface::mesh::set_voxel_geometry(cg, context, temp_geoms, atlas_reg);
|
||||
cg->SetOccluder(true);
|
||||
cg->SetCastShadows(true);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// set_voxel_geometry(node, buffer: VectorBuffer)
|
||||
static int l_set_voxel_geometry(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
GET_TOLUA_STUFF(node, 1, Node);
|
||||
TRY_GET_TOLUA_STUFF(buf, 2, const VectorBuffer);
|
||||
|
||||
log_d(MODULE, "set_voxel_geometry(): node=%p", node);
|
||||
log_d(MODULE, "set_voxel_geometry(): buf=%p", buf);
|
||||
|
||||
ss_ data;
|
||||
if(buf == nullptr)
|
||||
data = lua_tocppstring(L, 2);
|
||||
else
|
||||
data.assign((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__buildat_app");
|
||||
app::App *buildat_app = (app::App*)lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
auto *voxel_reg = buildat_app->get_voxel_registry();
|
||||
auto *atlas_reg = buildat_app->get_atlas_registry();
|
||||
|
||||
up_<SetVoxelGeometryTask> task(new SetVoxelGeometryTask(
|
||||
node, data, voxel_reg, atlas_reg
|
||||
));
|
||||
|
||||
auto *thread_pool = buildat_app->get_thread_pool();
|
||||
|
||||
thread_pool->add_task(std::move(task));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct SetVoxelLodGeometryTask: public interface::worker_thread::Task
|
||||
{
|
||||
int lod;
|
||||
Node *node;
|
||||
ss_ data;
|
||||
interface::VoxelRegistry *voxel_reg;
|
||||
interface::TextureAtlasRegistry *atlas_reg;
|
||||
|
||||
up_<pv::RawVolume<VoxelInstance>> lod_volume;
|
||||
sm_<uint, interface::mesh::TemporaryGeometry> temp_geoms;
|
||||
|
||||
SetVoxelLodGeometryTask(int lod, Node *node, const ss_ &data,
|
||||
interface::VoxelRegistry *voxel_reg,
|
||||
interface::TextureAtlasRegistry *atlas_reg):
|
||||
lod(lod), node(node), data(data),
|
||||
voxel_reg(voxel_reg), atlas_reg(atlas_reg)
|
||||
{
|
||||
ScopeTimer timer("pre lod geometry");
|
||||
// NOTE: Do the pre-processing here so that the calling code can
|
||||
// meaasure how long its execution takes
|
||||
// NOTE: Could be split in three calls
|
||||
up_<pv::RawVolume<VoxelInstance>> volume_orig =
|
||||
interface::deserialize_volume(data);
|
||||
lod_volume = interface::mesh::generate_voxel_lod_volume(
|
||||
lod, *volume_orig);
|
||||
interface::mesh::preload_textures(*lod_volume, voxel_reg, atlas_reg);
|
||||
}
|
||||
// Called repeatedly from main thread until returns true
|
||||
bool pre()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Called repeatedly from worker thread until returns true
|
||||
bool thread()
|
||||
{
|
||||
generate_voxel_lod_geometry(
|
||||
lod, temp_geoms, *lod_volume, voxel_reg, atlas_reg);
|
||||
return true;
|
||||
}
|
||||
// Called repeatedly from main thread until returns true
|
||||
bool post()
|
||||
{
|
||||
ScopeTimer timer("post lod geometry");
|
||||
Context *context = node->GetContext();
|
||||
CustomGeometry *cg = node->GetOrCreateComponent<CustomGeometry>();
|
||||
interface::mesh::set_voxel_lod_geometry(
|
||||
lod, cg, context, temp_geoms, atlas_reg);
|
||||
cg->SetOccluder(true);
|
||||
if(lod <= interface::MAX_LOD_WITH_SHADOWS)
|
||||
cg->SetCastShadows(true);
|
||||
else
|
||||
cg->SetCastShadows(false);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// set_voxel_lod_geometry(lod: number, node: Node, buffer: VectorBuffer)
|
||||
static int l_set_voxel_lod_geometry(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
int lod = lua_tointeger(L, 1);
|
||||
GET_TOLUA_STUFF(node, 2, Node);
|
||||
TRY_GET_TOLUA_STUFF(buf, 3, const VectorBuffer);
|
||||
|
||||
log_d(MODULE, "set_voxel_lod_geometry(): lod=%i", lod);
|
||||
log_d(MODULE, "set_voxel_lod_geometry(): node=%p", node);
|
||||
log_d(MODULE, "set_voxel_lod_geometry(): buf=%p", buf);
|
||||
|
||||
ss_ data;
|
||||
if(buf == nullptr)
|
||||
data = lua_tocppstring(L, 2);
|
||||
else
|
||||
data.assign((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__buildat_app");
|
||||
app::App *buildat_app = (app::App*)lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
auto *voxel_reg = buildat_app->get_voxel_registry();
|
||||
auto *atlas_reg = buildat_app->get_atlas_registry();
|
||||
|
||||
up_<SetVoxelLodGeometryTask> task(new SetVoxelLodGeometryTask(
|
||||
lod, node, data, voxel_reg, atlas_reg
|
||||
));
|
||||
|
||||
auto *thread_pool = buildat_app->get_thread_pool();
|
||||
|
||||
thread_pool->add_task(std::move(task));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// clear_voxel_geometry(node: Node)
|
||||
static int l_clear_voxel_geometry(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
GET_TOLUA_STUFF(node, 1, Node);
|
||||
|
||||
log_d(MODULE, "clear_voxel_geometry(): node=%p", node);
|
||||
|
||||
CustomGeometry *cg = node->GetComponent<CustomGeometry>();
|
||||
if(cg)
|
||||
node->RemoveComponent(cg);
|
||||
//cg->Clear();
|
||||
//cg->Commit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct SetPhysicsBoxesTask: public interface::worker_thread::Task
|
||||
{
|
||||
Node *node;
|
||||
ss_ data;
|
||||
interface::VoxelRegistry *voxel_reg;
|
||||
|
||||
up_<pv::RawVolume<VoxelInstance>> volume;
|
||||
sv_<interface::mesh::TemporaryBox> result_boxes;
|
||||
|
||||
SetPhysicsBoxesTask(Node *node, const ss_ &data,
|
||||
interface::VoxelRegistry *voxel_reg):
|
||||
node(node), data(data), voxel_reg(voxel_reg)
|
||||
{
|
||||
// NOTE: Do the pre-processing here so that the calling code can
|
||||
// meaasure how long its execution takes
|
||||
// NOTE: Could be split in two calls
|
||||
volume = interface::deserialize_volume(data);
|
||||
}
|
||||
// Called repeatedly from main thread until returns true
|
||||
bool pre()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Called repeatedly from worker thread until returns true
|
||||
bool thread()
|
||||
{
|
||||
interface::mesh::generate_voxel_physics_boxes(
|
||||
result_boxes, *volume, voxel_reg);
|
||||
return true;
|
||||
}
|
||||
// Called repeatedly from main thread until returns true
|
||||
int post_step = 1;
|
||||
bool post()
|
||||
{
|
||||
ScopeTimer timer(
|
||||
post_step == 1 ? "post physics 1" :
|
||||
post_step == 2 ? "post_physics 2" :
|
||||
post_step == 3 ? "post physics 3" :
|
||||
"post physics");
|
||||
Context *context = node->GetContext();
|
||||
switch(post_step){
|
||||
case 1:
|
||||
node->GetOrCreateComponent<RigidBody>(LOCAL);
|
||||
break;
|
||||
case 2:
|
||||
#ifdef DEBUG_LOG_TIMING
|
||||
log_v(MODULE, "num boxes: %zu", result_boxes.size());
|
||||
#endif
|
||||
// Times on Dell Precision M6800:
|
||||
// 0 boxes -> 30us
|
||||
// 1 box -> 136us
|
||||
// 160 boxes -> 7625us (hilly forest)
|
||||
// 259 boxes -> 18548us (hilly forest, bad case)
|
||||
interface::mesh::set_voxel_physics_boxes(
|
||||
node, context, result_boxes, false);
|
||||
break;
|
||||
case 3: {
|
||||
// Times on Dell Precision M6800:
|
||||
// 0 boxes -> 30us
|
||||
// 1 box -> 64us
|
||||
// 160 boxes -> 8419us (hilly forest)
|
||||
// 259 boxes -> 15704us (hilly forest, bad case)
|
||||
RigidBody *body = node->GetComponent<RigidBody>();
|
||||
if(body)
|
||||
body->OnSetEnabled();
|
||||
return true; }
|
||||
}
|
||||
post_step++;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// set_voxel_physics_boxes(node, buffer: VectorBuffer)
|
||||
static int l_set_voxel_physics_boxes(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
GET_TOLUA_STUFF(node, 1, Node);
|
||||
TRY_GET_TOLUA_STUFF(buf, 2, const VectorBuffer);
|
||||
|
||||
log_d(MODULE, "set_voxel_physics_boxes(): node=%p", node);
|
||||
log_d(MODULE, "set_voxel_physics_boxes(): buf=%p", buf);
|
||||
|
||||
ss_ data;
|
||||
if(buf == nullptr)
|
||||
data = lua_tocppstring(L, 2);
|
||||
else
|
||||
data.assign((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__buildat_app");
|
||||
app::App *buildat_app = (app::App*)lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
auto *voxel_reg = buildat_app->get_voxel_registry();
|
||||
|
||||
up_<SetPhysicsBoxesTask> task(new SetPhysicsBoxesTask(
|
||||
node, data, voxel_reg
|
||||
));
|
||||
|
||||
auto *thread_pool = buildat_app->get_thread_pool();
|
||||
|
||||
thread_pool->add_task(std::move(task));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// clear_voxel_physics_boxes(node)
|
||||
static int l_clear_voxel_physics_boxes(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
GET_TOLUA_STUFF(node, 1, Node);
|
||||
|
||||
log_d(MODULE, "clear_voxel_physics_boxes(): node=%p", node);
|
||||
|
||||
RigidBody *body = node->GetComponent<RigidBody>();
|
||||
if(body)
|
||||
node->RemoveComponent(body);
|
||||
|
||||
PODVector<CollisionShape*> previous_shapes;
|
||||
node->GetComponents<CollisionShape>(previous_shapes);
|
||||
for(size_t i = 0; i < previous_shapes.Size(); i++)
|
||||
node->RemoveComponent(previous_shapes[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_mesh(lua_State *L)
|
||||
{
|
||||
#define DEF_BUILDAT_FUNC(name){ \
|
||||
lua_pushcfunction(L, l_##name); \
|
||||
lua_setglobal(L, "__buildat_" #name); \
|
||||
}
|
||||
DEF_BUILDAT_FUNC(set_simple_voxel_model);
|
||||
DEF_BUILDAT_FUNC(set_8bit_voxel_geometry);
|
||||
DEF_BUILDAT_FUNC(set_voxel_geometry);
|
||||
DEF_BUILDAT_FUNC(set_voxel_lod_geometry);
|
||||
DEF_BUILDAT_FUNC(clear_voxel_geometry);
|
||||
DEF_BUILDAT_FUNC(set_voxel_physics_boxes);
|
||||
DEF_BUILDAT_FUNC(clear_voxel_physics_boxes);
|
||||
}
|
||||
|
||||
} // namespace lua_bindingss
|
||||
|
||||
// vim: set noet ts=4 sw=4:
|
||||
|
@ -2,470 +2,106 @@
|
||||
// Copyright 2014 Perttu Ahola <celeron55@gmail.com>
|
||||
#include "lua_bindings/util.h"
|
||||
#include "core/log.h"
|
||||
#include "client/app.h"
|
||||
#include "interface/mesh.h"
|
||||
#include "interface/voxel_volume.h"
|
||||
#include "interface/worker_thread.h"
|
||||
#include <tolua++.h>
|
||||
#include <c55/os.h>
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#include <Scene.h>
|
||||
#include <StaticModel.h>
|
||||
#include <Model.h>
|
||||
#include <CustomGeometry.h>
|
||||
#include <CollisionShape.h>
|
||||
#include <RigidBody.h>
|
||||
#pragma GCC diagnostic pop
|
||||
#include "interface/voxel.h"
|
||||
#include <luabind/luabind.hpp>
|
||||
#include <luabind/adopt_policy.hpp>
|
||||
#include <luabind/pointer_traits.hpp>
|
||||
#define MODULE "lua_bindings"
|
||||
|
||||
namespace magic = Urho3D;
|
||||
namespace pv = PolyVox;
|
||||
#define DEF_METHOD(name){ \
|
||||
lua_pushcfunction(L, l_##name); \
|
||||
lua_setfield(L, -2, #name); \
|
||||
}
|
||||
|
||||
using interface::VoxelInstance;
|
||||
using interface::VoxelRegistry;
|
||||
|
||||
// Just do this; Urho3D's stuff doesn't really clash with anything in buildat
|
||||
using namespace Urho3D;
|
||||
/*namespace luabind {
|
||||
namespace detail {
|
||||
namespace has_get_pointer_ {
|
||||
template<class T>
|
||||
T * get_pointer(std::shared_ptr<T> const& p) { return p.get(); }
|
||||
} // has_get_pointer_
|
||||
} // detail
|
||||
} // luabind*/
|
||||
|
||||
namespace lua_bindings {
|
||||
|
||||
#define GET_TOLUA_STUFF(result_name, index, type) \
|
||||
if(!tolua_isusertype(L, index, #type, 0, &tolua_err)){ \
|
||||
tolua_error(L, __PRETTY_FUNCTION__, &tolua_err); \
|
||||
return 0; \
|
||||
} \
|
||||
type *result_name = (type*)tolua_tousertype(L, index, 0);
|
||||
#define TRY_GET_TOLUA_STUFF(result_name, index, type) \
|
||||
type *result_name = nullptr; \
|
||||
if(tolua_isusertype(L, index, #type, 0, &tolua_err)){ \
|
||||
result_name = (type*)tolua_tousertype(L, index, 0); \
|
||||
}
|
||||
|
||||
// NOTE: This API is designed this way because otherwise ownership management of
|
||||
// objects sucks
|
||||
// set_simple_voxel_model(node, w, h, d, buffer: VectorBuffer)
|
||||
static int l_set_simple_voxel_model(lua_State *L)
|
||||
/*struct LuaVoxelRegistry
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
static constexpr const char *class_name = "VoxelRegistry";
|
||||
sp_<VoxelRegistry> internal;
|
||||
|
||||
GET_TOLUA_STUFF(node, 1, Node);
|
||||
int w = lua_tointeger(L, 2);
|
||||
int h = lua_tointeger(L, 3);
|
||||
int d = lua_tointeger(L, 4);
|
||||
TRY_GET_TOLUA_STUFF(buf, 5, const VectorBuffer);
|
||||
|
||||
log_d(MODULE, "set_simple_voxel_model(): node=%p", node);
|
||||
log_d(MODULE, "set_simple_voxel_model(): buf=%p", buf);
|
||||
|
||||
ss_ data;
|
||||
if(buf == nullptr)
|
||||
data = lua_tocppstring(L, 5);
|
||||
else
|
||||
data.assign((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
|
||||
|
||||
if((int)data.size() != w * h * d){
|
||||
log_e(MODULE, "set_simple_voxel_model(): Data size does not match "
|
||||
"with dimensions (%zu vs. %i)", data.size(), w*h*d);
|
||||
LuaVoxelRegistry():
|
||||
internal(interface::createVoxelRegistry())
|
||||
{}
|
||||
static int gc_object(lua_State *L){
|
||||
delete *(LuaVoxelRegistry**)(lua_touserdata(L, 1));
|
||||
return 0;
|
||||
}
|
||||
static int l_serialize(lua_State *L){
|
||||
LuaVoxelRegistry *o = internal_checkobject(L, 1);
|
||||
std::ostringstream os(std::ios::binary);
|
||||
o->internal->serialize(os);
|
||||
ss_ s = os.str();
|
||||
lua_pushlstring(L, s.c_str(), s.size());
|
||||
return 1;
|
||||
}
|
||||
static int l_deserialize(lua_State *L){
|
||||
LuaVoxelRegistry *o = internal_checkobject(L, 1);
|
||||
ss_ s = lua_checkcppstring(L, 2);
|
||||
std::istringstream is(s, std::ios::binary);
|
||||
o->internal->deserialize(is);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__buildat_app");
|
||||
app::App *buildat_app = (app::App*)lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
Context *context = buildat_app->get_scene()->GetContext();
|
||||
|
||||
SharedPtr<Model> fromScratchModel(
|
||||
interface::mesh::create_simple_voxel_model(context, w, h, d, data));
|
||||
|
||||
StaticModel *object = node->GetOrCreateComponent<StaticModel>();
|
||||
object->SetModel(fromScratchModel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// set_8bit_voxel_geometry(node, w, h, d, buffer: VectorBuffer)
|
||||
static int l_set_8bit_voxel_geometry(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
GET_TOLUA_STUFF(node, 1, Node);
|
||||
int w = lua_tointeger(L, 2);
|
||||
int h = lua_tointeger(L, 3);
|
||||
int d = lua_tointeger(L, 4);
|
||||
TRY_GET_TOLUA_STUFF(buf, 5, const VectorBuffer);
|
||||
|
||||
log_d(MODULE, "set_8bit_voxel_geometry(): node=%p", node);
|
||||
log_d(MODULE, "set_8bit_voxel_geometry(): buf=%p", buf);
|
||||
|
||||
ss_ data;
|
||||
if(buf == nullptr)
|
||||
data = lua_tocppstring(L, 5);
|
||||
else
|
||||
data.assign((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
|
||||
|
||||
if((int)data.size() != w * h * d){
|
||||
log_e(MODULE, "set_8bit_voxel_geometry(): Data size does not match "
|
||||
"with dimensions (%zu vs. %i)", data.size(), w*h*d);
|
||||
return 0;
|
||||
static LuaVoxelRegistry* internal_checkobject(lua_State *L, int narg){
|
||||
luaL_checktype(L, narg, LUA_TUSERDATA);
|
||||
void *ud = luaL_checkudata(L, narg, class_name);
|
||||
if(!ud) luaL_typerror(L, narg, class_name);
|
||||
return *(LuaVoxelRegistry**)ud;
|
||||
}
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__buildat_app");
|
||||
app::App *buildat_app = (app::App*)lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
Context *context = buildat_app->get_scene()->GetContext();
|
||||
auto *voxel_reg = buildat_app->get_voxel_registry();
|
||||
auto *atlas_reg = buildat_app->get_atlas_registry();
|
||||
|
||||
CustomGeometry *cg = node->GetOrCreateComponent<CustomGeometry>();
|
||||
|
||||
interface::mesh::set_8bit_voxel_geometry(cg, context, w, h, d, data,
|
||||
voxel_reg, atlas_reg);
|
||||
|
||||
// Maybe appropriate
|
||||
cg->SetOccluder(true);
|
||||
|
||||
// TODO: Don't do this here; allow the caller to do this
|
||||
cg->SetCastShadows(true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOG_TIMING
|
||||
struct ScopeTimer {
|
||||
const char *name;
|
||||
uint64_t t0;
|
||||
ScopeTimer(const char *name="unknown"): name(name){
|
||||
t0 = get_timeofday_us();
|
||||
static int l_create(lua_State *L){
|
||||
LuaVoxelRegistry *o = new LuaVoxelRegistry();
|
||||
*(void**)(lua_newuserdata(L, sizeof(void*))) = o;
|
||||
luaL_getmetatable(L, class_name);
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
~ScopeTimer(){
|
||||
int d = get_timeofday_us() - t0;
|
||||
if(d > 3000)
|
||||
log_w(MODULE, "%ius (%s)", d, name);
|
||||
else
|
||||
log_v(MODULE, "%ius (%s)", d, name);
|
||||
}
|
||||
};
|
||||
#else
|
||||
struct ScopeTimer {
|
||||
ScopeTimer(const char *name=""){}
|
||||
};
|
||||
#endif
|
||||
static void register_metatable(lua_State *L){
|
||||
lua_newtable(L);
|
||||
int method_table_L = lua_gettop(L);
|
||||
luaL_newmetatable(L, class_name);
|
||||
int metatable_L = lua_gettop(L);
|
||||
|
||||
struct SetVoxelGeometryTask: public interface::worker_thread::Task
|
||||
{
|
||||
Node *node;
|
||||
ss_ data;
|
||||
interface::VoxelRegistry *voxel_reg;
|
||||
interface::TextureAtlasRegistry *atlas_reg;
|
||||
// hide metatable from Lua getmetatable()
|
||||
lua_pushliteral(L, "__metatable");
|
||||
lua_pushvalue(L, method_table_L);
|
||||
lua_settable(L, metatable_L);
|
||||
|
||||
up_<pv::RawVolume<VoxelInstance>> volume;
|
||||
sm_<uint, interface::mesh::TemporaryGeometry> temp_geoms;
|
||||
lua_pushliteral(L, "__index");
|
||||
lua_pushvalue(L, method_table_L);
|
||||
lua_settable(L, metatable_L);
|
||||
|
||||
SetVoxelGeometryTask(Node *node, const ss_ &data,
|
||||
interface::VoxelRegistry *voxel_reg,
|
||||
interface::TextureAtlasRegistry *atlas_reg):
|
||||
node(node), data(data), voxel_reg(voxel_reg), atlas_reg(atlas_reg)
|
||||
{
|
||||
ScopeTimer timer("pre geometry");
|
||||
// NOTE: Do the pre-processing here so that the calling code can
|
||||
// meaasure how long its execution takes
|
||||
// NOTE: Could be split in two calls
|
||||
volume = interface::deserialize_volume(data);
|
||||
interface::mesh::preload_textures(*volume, voxel_reg, atlas_reg);
|
||||
}
|
||||
// Called repeatedly from main thread until returns true
|
||||
bool pre()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Called repeatedly from worker thread until returns true
|
||||
bool thread()
|
||||
{
|
||||
generate_voxel_geometry(temp_geoms, *volume, voxel_reg, atlas_reg);
|
||||
return true;
|
||||
}
|
||||
// Called repeatedly from main thread until returns true
|
||||
bool post()
|
||||
{
|
||||
ScopeTimer timer("post geometry");
|
||||
Context *context = node->GetContext();
|
||||
CustomGeometry *cg = node->GetOrCreateComponent<CustomGeometry>();
|
||||
interface::mesh::set_voxel_geometry(cg, context, temp_geoms, atlas_reg);
|
||||
cg->SetOccluder(true);
|
||||
cg->SetCastShadows(true);
|
||||
return true;
|
||||
lua_pushliteral(L, "__gc");
|
||||
lua_pushcfunction(L, gc_object);
|
||||
lua_settable(L, metatable_L);
|
||||
|
||||
lua_pop(L, 1); // drop metatable_L
|
||||
|
||||
// fill method_table_L
|
||||
DEF_METHOD(serialize);
|
||||
DEF_METHOD(deserialize);
|
||||
|
||||
// drop method_table_L
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
};
|
||||
|
||||
// set_voxel_geometry(node, buffer: VectorBuffer)
|
||||
static int l_set_voxel_geometry(lua_State *L)
|
||||
static int l_VoxelRegistry(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
GET_TOLUA_STUFF(node, 1, Node);
|
||||
TRY_GET_TOLUA_STUFF(buf, 2, const VectorBuffer);
|
||||
|
||||
log_d(MODULE, "set_voxel_geometry(): node=%p", node);
|
||||
log_d(MODULE, "set_voxel_geometry(): buf=%p", buf);
|
||||
|
||||
ss_ data;
|
||||
if(buf == nullptr)
|
||||
data = lua_tocppstring(L, 2);
|
||||
else
|
||||
data.assign((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__buildat_app");
|
||||
app::App *buildat_app = (app::App*)lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
auto *voxel_reg = buildat_app->get_voxel_registry();
|
||||
auto *atlas_reg = buildat_app->get_atlas_registry();
|
||||
|
||||
up_<SetVoxelGeometryTask> task(new SetVoxelGeometryTask(
|
||||
node, data, voxel_reg, atlas_reg
|
||||
));
|
||||
|
||||
auto *thread_pool = buildat_app->get_thread_pool();
|
||||
|
||||
thread_pool->add_task(std::move(task));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct SetVoxelLodGeometryTask: public interface::worker_thread::Task
|
||||
{
|
||||
int lod;
|
||||
Node *node;
|
||||
ss_ data;
|
||||
interface::VoxelRegistry *voxel_reg;
|
||||
interface::TextureAtlasRegistry *atlas_reg;
|
||||
|
||||
up_<pv::RawVolume<VoxelInstance>> lod_volume;
|
||||
sm_<uint, interface::mesh::TemporaryGeometry> temp_geoms;
|
||||
|
||||
SetVoxelLodGeometryTask(int lod, Node *node, const ss_ &data,
|
||||
interface::VoxelRegistry *voxel_reg,
|
||||
interface::TextureAtlasRegistry *atlas_reg):
|
||||
lod(lod), node(node), data(data),
|
||||
voxel_reg(voxel_reg), atlas_reg(atlas_reg)
|
||||
{
|
||||
ScopeTimer timer("pre lod geometry");
|
||||
// NOTE: Do the pre-processing here so that the calling code can
|
||||
// meaasure how long its execution takes
|
||||
// NOTE: Could be split in three calls
|
||||
up_<pv::RawVolume<VoxelInstance>> volume_orig =
|
||||
interface::deserialize_volume(data);
|
||||
lod_volume = interface::mesh::generate_voxel_lod_volume(
|
||||
lod, *volume_orig);
|
||||
interface::mesh::preload_textures(*lod_volume, voxel_reg, atlas_reg);
|
||||
}
|
||||
// Called repeatedly from main thread until returns true
|
||||
bool pre()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Called repeatedly from worker thread until returns true
|
||||
bool thread()
|
||||
{
|
||||
generate_voxel_lod_geometry(
|
||||
lod, temp_geoms, *lod_volume, voxel_reg, atlas_reg);
|
||||
return true;
|
||||
}
|
||||
// Called repeatedly from main thread until returns true
|
||||
bool post()
|
||||
{
|
||||
ScopeTimer timer("post lod geometry");
|
||||
Context *context = node->GetContext();
|
||||
CustomGeometry *cg = node->GetOrCreateComponent<CustomGeometry>();
|
||||
interface::mesh::set_voxel_lod_geometry(
|
||||
lod, cg, context, temp_geoms, atlas_reg);
|
||||
cg->SetOccluder(true);
|
||||
if(lod <= interface::MAX_LOD_WITH_SHADOWS)
|
||||
cg->SetCastShadows(true);
|
||||
else
|
||||
cg->SetCastShadows(false);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// set_voxel_lod_geometry(lod: number, node: Node, buffer: VectorBuffer)
|
||||
static int l_set_voxel_lod_geometry(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
int lod = lua_tointeger(L, 1);
|
||||
GET_TOLUA_STUFF(node, 2, Node);
|
||||
TRY_GET_TOLUA_STUFF(buf, 3, const VectorBuffer);
|
||||
|
||||
log_d(MODULE, "set_voxel_lod_geometry(): lod=%i", lod);
|
||||
log_d(MODULE, "set_voxel_lod_geometry(): node=%p", node);
|
||||
log_d(MODULE, "set_voxel_lod_geometry(): buf=%p", buf);
|
||||
|
||||
ss_ data;
|
||||
if(buf == nullptr)
|
||||
data = lua_tocppstring(L, 2);
|
||||
else
|
||||
data.assign((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__buildat_app");
|
||||
app::App *buildat_app = (app::App*)lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
auto *voxel_reg = buildat_app->get_voxel_registry();
|
||||
auto *atlas_reg = buildat_app->get_atlas_registry();
|
||||
|
||||
up_<SetVoxelLodGeometryTask> task(new SetVoxelLodGeometryTask(
|
||||
lod, node, data, voxel_reg, atlas_reg
|
||||
));
|
||||
|
||||
auto *thread_pool = buildat_app->get_thread_pool();
|
||||
|
||||
thread_pool->add_task(std::move(task));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// clear_voxel_geometry(node: Node)
|
||||
static int l_clear_voxel_geometry(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
GET_TOLUA_STUFF(node, 1, Node);
|
||||
|
||||
log_d(MODULE, "clear_voxel_geometry(): node=%p", node);
|
||||
|
||||
CustomGeometry *cg = node->GetComponent<CustomGeometry>();
|
||||
if(cg)
|
||||
node->RemoveComponent(cg);
|
||||
//cg->Clear();
|
||||
//cg->Commit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct SetPhysicsBoxesTask: public interface::worker_thread::Task
|
||||
{
|
||||
Node *node;
|
||||
ss_ data;
|
||||
interface::VoxelRegistry *voxel_reg;
|
||||
|
||||
up_<pv::RawVolume<VoxelInstance>> volume;
|
||||
sv_<interface::mesh::TemporaryBox> result_boxes;
|
||||
|
||||
SetPhysicsBoxesTask(Node *node, const ss_ &data,
|
||||
interface::VoxelRegistry *voxel_reg):
|
||||
node(node), data(data), voxel_reg(voxel_reg)
|
||||
{
|
||||
// NOTE: Do the pre-processing here so that the calling code can
|
||||
// meaasure how long its execution takes
|
||||
// NOTE: Could be split in two calls
|
||||
volume = interface::deserialize_volume(data);
|
||||
}
|
||||
// Called repeatedly from main thread until returns true
|
||||
bool pre()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// Called repeatedly from worker thread until returns true
|
||||
bool thread()
|
||||
{
|
||||
interface::mesh::generate_voxel_physics_boxes(
|
||||
result_boxes, *volume, voxel_reg);
|
||||
return true;
|
||||
}
|
||||
// Called repeatedly from main thread until returns true
|
||||
int post_step = 1;
|
||||
bool post()
|
||||
{
|
||||
ScopeTimer timer(
|
||||
post_step == 1 ? "post physics 1" :
|
||||
post_step == 2 ? "post_physics 2" :
|
||||
post_step == 3 ? "post physics 3" :
|
||||
"post physics");
|
||||
Context *context = node->GetContext();
|
||||
switch(post_step){
|
||||
case 1:
|
||||
node->GetOrCreateComponent<RigidBody>(LOCAL);
|
||||
break;
|
||||
case 2:
|
||||
#ifdef DEBUG_LOG_TIMING
|
||||
log_v(MODULE, "num boxes: %zu", result_boxes.size());
|
||||
#endif
|
||||
// Times on Dell Precision M6800:
|
||||
// 0 boxes -> 30us
|
||||
// 1 box -> 136us
|
||||
// 160 boxes -> 7625us (hilly forest)
|
||||
// 259 boxes -> 18548us (hilly forest, bad case)
|
||||
interface::mesh::set_voxel_physics_boxes(
|
||||
node, context, result_boxes, false);
|
||||
break;
|
||||
case 3: {
|
||||
// Times on Dell Precision M6800:
|
||||
// 0 boxes -> 30us
|
||||
// 1 box -> 64us
|
||||
// 160 boxes -> 8419us (hilly forest)
|
||||
// 259 boxes -> 15704us (hilly forest, bad case)
|
||||
RigidBody *body = node->GetComponent<RigidBody>();
|
||||
if(body)
|
||||
body->OnSetEnabled();
|
||||
return true; }
|
||||
}
|
||||
post_step++;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// set_voxel_physics_boxes(node, buffer: VectorBuffer)
|
||||
static int l_set_voxel_physics_boxes(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
GET_TOLUA_STUFF(node, 1, Node);
|
||||
TRY_GET_TOLUA_STUFF(buf, 2, const VectorBuffer);
|
||||
|
||||
log_d(MODULE, "set_voxel_physics_boxes(): node=%p", node);
|
||||
log_d(MODULE, "set_voxel_physics_boxes(): buf=%p", buf);
|
||||
|
||||
ss_ data;
|
||||
if(buf == nullptr)
|
||||
data = lua_tocppstring(L, 2);
|
||||
else
|
||||
data.assign((const char*)&buf->GetBuffer()[0], buf->GetBuffer().Size());
|
||||
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "__buildat_app");
|
||||
app::App *buildat_app = (app::App*)lua_touserdata(L, -1);
|
||||
lua_pop(L, 1);
|
||||
auto *voxel_reg = buildat_app->get_voxel_registry();
|
||||
|
||||
up_<SetPhysicsBoxesTask> task(new SetPhysicsBoxesTask(
|
||||
node, data, voxel_reg
|
||||
));
|
||||
|
||||
auto *thread_pool = buildat_app->get_thread_pool();
|
||||
|
||||
thread_pool->add_task(std::move(task));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// clear_voxel_physics_boxes(node)
|
||||
static int l_clear_voxel_physics_boxes(lua_State *L)
|
||||
{
|
||||
tolua_Error tolua_err;
|
||||
|
||||
GET_TOLUA_STUFF(node, 1, Node);
|
||||
|
||||
log_d(MODULE, "clear_voxel_physics_boxes(): node=%p", node);
|
||||
|
||||
RigidBody *body = node->GetComponent<RigidBody>();
|
||||
if(body)
|
||||
node->RemoveComponent(body);
|
||||
|
||||
PODVector<CollisionShape*> previous_shapes;
|
||||
node->GetComponents<CollisionShape>(previous_shapes);
|
||||
for(size_t i = 0; i < previous_shapes.Size(); i++)
|
||||
node->RemoveComponent(previous_shapes[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return LuaVoxelRegistry::l_create(L);
|
||||
}*/
|
||||
|
||||
void init_voxel(lua_State *L)
|
||||
{
|
||||
@ -473,13 +109,23 @@ void init_voxel(lua_State *L)
|
||||
lua_pushcfunction(L, l_##name); \
|
||||
lua_setglobal(L, "__buildat_" #name); \
|
||||
}
|
||||
DEF_BUILDAT_FUNC(set_simple_voxel_model);
|
||||
DEF_BUILDAT_FUNC(set_8bit_voxel_geometry);
|
||||
DEF_BUILDAT_FUNC(set_voxel_geometry);
|
||||
DEF_BUILDAT_FUNC(set_voxel_lod_geometry);
|
||||
DEF_BUILDAT_FUNC(clear_voxel_geometry);
|
||||
DEF_BUILDAT_FUNC(set_voxel_physics_boxes);
|
||||
DEF_BUILDAT_FUNC(clear_voxel_physics_boxes);
|
||||
//LuaVoxelRegistry::register_metatable(L);
|
||||
//DEF_BUILDAT_FUNC(VoxelRegistry);
|
||||
|
||||
using namespace luabind;
|
||||
|
||||
luabind::open(L);
|
||||
|
||||
module(L)[
|
||||
class_<VoxelRegistry, bases<>, sp_<VoxelRegistry>>("VoxelRegistry")
|
||||
//.def("create", &interface::createVoxelRegistry, adopt_policy<0>())
|
||||
.def("serialize", (ss_(VoxelRegistry::*)())
|
||||
&VoxelRegistry::serialize)
|
||||
.def("deserialize", (void(VoxelRegistry::*)(const ss_&))
|
||||
&VoxelRegistry::deserialize),
|
||||
def("createVoxelRegistry", &interface::createVoxelRegistry,
|
||||
adopt_policy<0>())
|
||||
];
|
||||
}
|
||||
|
||||
} // namespace lua_bindingss
|
||||
|
Loading…
x
Reference in New Issue
Block a user