From 6419e78fc2c3ab9a1da28db20d460d9c132000ed Mon Sep 17 00:00:00 2001 From: Marc Gilleron Date: Sun, 20 Aug 2017 18:37:08 +0200 Subject: [PATCH] Use VisualServer directly for mesh instances --- voxel_block.cpp | 47 ++++++++++++++++++++++++++++++++++++++--------- voxel_block.h | 8 ++++++-- voxel_terrain.cpp | 39 +++++++-------------------------------- voxel_terrain.h | 4 ++-- 4 files changed, 53 insertions(+), 45 deletions(-) diff --git a/voxel_block.cpp b/voxel_block.cpp index 1b74248..7db13e8 100644 --- a/voxel_block.cpp +++ b/voxel_block.cpp @@ -1,14 +1,5 @@ #include "voxel_block.h" -MeshInstance *VoxelBlock::get_mesh_instance(const Node &root) { - if (mesh_instance_path.is_empty()) - return NULL; - Node *n = root.get_node(mesh_instance_path); - if (n == NULL) - return NULL; - return n->cast_to(); -} - // Helper VoxelBlock *VoxelBlock::create(Vector3i bpos, Ref buffer, unsigned int size) { const int bs = size; @@ -17,6 +8,7 @@ VoxelBlock *VoxelBlock::create(Vector3i bpos, Ref buffer, unsigned VoxelBlock *block = memnew(VoxelBlock); block->pos = bpos; + block->_position_in_voxels = bpos * size; block->voxels = buffer; //block->map = ↦ @@ -25,5 +17,42 @@ VoxelBlock *VoxelBlock::create(Vector3i bpos, Ref buffer, unsigned VoxelBlock::VoxelBlock() : voxels(NULL) { + + VisualServer &vs = *VisualServer::get_singleton(); + + if (_mesh_instance.is_valid()) { + vs.free(_mesh_instance); + _mesh_instance = RID(); + } } +void VoxelBlock::set_mesh(Ref mesh, Ref world) { + + VisualServer &vs = *VisualServer::get_singleton(); + + if(mesh.is_valid()) { + + if(_mesh_instance.is_valid() == false) { + // Create instance if it doesn't exist + ERR_FAIL_COND(world.is_null()); + _mesh_instance = vs.instance_create(); + vs.instance_set_scenario(_mesh_instance, world->get_scenario()); + } + + vs.instance_set_base(_mesh_instance, mesh.is_valid() ? mesh->get_rid() : RID()); + + Transform local_transform(Basis(), _position_in_voxels.to_vec3()); + vs.instance_set_transform(_mesh_instance, local_transform); + // TODO The day VoxelTerrain becomes a Spatial, this transform will need to be updatable separately + + } else { + + if(_mesh_instance.is_valid()) { + // Delete instance if it exists + vs.free(_mesh_instance); + _mesh_instance = RID(); + } + } + + _mesh = mesh; +} diff --git a/voxel_block.h b/voxel_block.h index 3bec23a..fcc9178 100644 --- a/voxel_block.h +++ b/voxel_block.h @@ -12,14 +12,18 @@ class VoxelBlock { public: Ref voxels; // SIZE*SIZE*SIZE voxels Vector3i pos; - NodePath mesh_instance_path; static VoxelBlock *create(Vector3i bpos, Ref buffer, unsigned int size); - MeshInstance *get_mesh_instance(const Node &root); + void set_mesh(Ref mesh, Ref world); private: VoxelBlock(); + + Vector3i _position_in_voxels; + + Ref _mesh; + RID _mesh_instance; }; #endif // VOXEL_BLOCK_H diff --git a/voxel_terrain.cpp b/voxel_terrain.cpp index 2fcfbeb..7989a11 100644 --- a/voxel_terrain.cpp +++ b/voxel_terrain.cpp @@ -6,7 +6,7 @@ VoxelTerrain::VoxelTerrain() - : Node(), _generate_collisions(true) { + : Spatial(), _generate_collisions(true) { _map = Ref(memnew(VoxelMap)); _mesher = Ref(memnew(VoxelMesher)); @@ -306,6 +306,8 @@ void VoxelTerrain::_notification(int p_what) { make_all_view_dirty(); break; + // TODO Listen for transform changes + default: break; } @@ -440,8 +442,6 @@ void VoxelTerrain::update_block_mesh(Vector3i block_pos) { _map->get_buffer_copy(_map->block_to_voxel(block_pos) - Vector3i(1, 1, 1), nbuffer, 0x3); VOXEL_PROFILE_END("block_extraction") - Vector3 block_node_pos = _map->block_to_voxel(block_pos).to_vec3(); - // TODO Re-use existing meshes to optimize memory cost // Build cubic parts of the mesh @@ -449,36 +449,11 @@ void VoxelTerrain::update_block_mesh(Vector3i block_pos) { // Build smooth parts of the mesh _mesher_smooth->build(nbuffer, Voxel::CHANNEL_ISOLEVEL, mesh); - MeshInstance *mesh_instance = block->get_mesh_instance(*this); + if(is_mesh_empty(mesh)) + mesh = Ref(); - if (is_mesh_empty(mesh)) { - if (mesh_instance) { - mesh_instance->set_mesh(Ref()); - } - } else { - // The mesh exist and it has vertices - - // TODO Don't use nodes! Use servers directly, it's faster - if (mesh_instance == NULL) { - // Create and spawn mesh - mesh_instance = memnew(MeshInstance); - mesh_instance->set_mesh(mesh); - mesh_instance->set_translation(block_node_pos); - add_child(mesh_instance); - block->mesh_instance_path = mesh_instance->get_path(); - } else { - // Update mesh - VOXEL_PROFILE_BEGIN("mesh_instance_set_mesh") - mesh_instance->set_mesh(mesh); - VOXEL_PROFILE_END("mesh_instance_set_mesh") - } - - if (Engine::get_singleton()->is_editor_hint() == false && _generate_collisions) { - - // TODO Generate collisions using PhysicsServer - // TODO Need to select only specific surfaces because some may not have collisions - } - } + Ref world = get_world(); + block->set_mesh(mesh, world); } //void VoxelTerrain::block_removed(VoxelBlock & block) { diff --git a/voxel_terrain.h b/voxel_terrain.h index 3bd9d69..6051aa8 100644 --- a/voxel_terrain.h +++ b/voxel_terrain.h @@ -10,8 +10,8 @@ // Infinite static terrain made of voxels. // It is loaded around VoxelTerrainStreamers. -class VoxelTerrain : public Node /*, public IVoxelMapObserver*/ { - GDCLASS(VoxelTerrain, Node) +class VoxelTerrain : public Spatial /*, public IVoxelMapObserver*/ { + GDCLASS(VoxelTerrain, Spatial) public: VoxelTerrain();